@tstdl/base 0.93.181 → 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 +8 -3
  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,108 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { importKey } from '../cryptography.js';
3
- import { encodeTotpSecret, generateTotpRecoveryCodes, generateTotpSecret, generateTotpToken, generateTotpUri, hashTotpRecoveryCode, verifyTotpRecoveryCode, verifyTotpToken } from '../totp.js';
4
- const totpOptions = {
5
- codeHashAlgorithm: 'SHA-1',
6
- recoveryCodeHashOptions: {
7
- algorithm: { name: 'PBKDF2', hash: 'SHA-256', salt: new Uint8Array(16), iterations: 10 },
8
- length: 64,
9
- },
10
- };
11
- describe('TOTP Utilities', () => {
12
- test('should generate a secret of appropriate length', () => {
13
- expect(generateTotpSecret('SHA-1').byteLength).toBe(20);
14
- expect(generateTotpSecret('SHA-256').byteLength).toBe(32);
15
- expect(generateTotpSecret('SHA-512').byteLength).toBe(64);
16
- });
17
- test('should generate a valid TOTP token', async () => {
18
- const secretData = new Uint8Array(new ArrayBuffer(20));
19
- secretData.fill(1);
20
- const secret = await importKey('raw-secret', secretData, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']);
21
- const token = await generateTotpToken(secret, { ...totpOptions, timestamp: 1000000000 });
22
- expect(token).toMatch(/^\d{6}$/);
23
- });
24
- test('should verify a valid TOTP token', async () => {
25
- const secretData = new Uint8Array(new ArrayBuffer(20));
26
- secretData.fill(1);
27
- const secret = await importKey('raw-secret', secretData, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']);
28
- const timestamp = 1000000000;
29
- const token = await generateTotpToken(secret, { ...totpOptions, timestamp });
30
- const isValid = await verifyTotpToken(secret, token, { ...totpOptions, timestamp });
31
- expect(isValid).toBe(true);
32
- });
33
- test('should fail to verify an invalid TOTP token', async () => {
34
- const secretData = new Uint8Array(new ArrayBuffer(20));
35
- secretData.fill(1);
36
- const secret = await importKey('raw-secret', secretData, { name: 'HMAC', hash: 'SHA-1' }, false, ['sign']);
37
- const isValid = await verifyTotpToken(secret, '000000', { ...totpOptions, timestamp: 1000000000 });
38
- expect(isValid).toBe(false);
39
- });
40
- test('should generate a valid otpauth URI', () => {
41
- const secret = new Uint8Array(new ArrayBuffer(20));
42
- secret.fill(1);
43
- const encodedSecret = encodeTotpSecret(secret);
44
- const uri = generateTotpUri(encodedSecret, 'user@example.com', 'MyApp', totpOptions);
45
- expect(uri).toBe('otpauth://totp/MyApp:user%40example.com?secret=AEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIB&issuer=MyApp&algorithm=SHA1&digits=6&period=30');
46
- });
47
- test('should generate a valid otpauth URI with SHA-256', () => {
48
- const secret = new Uint8Array(new ArrayBuffer(32));
49
- secret.fill(1);
50
- const encodedSecret = encodeTotpSecret(secret);
51
- const uri = generateTotpUri(encodedSecret, 'user@example.com', 'MyApp', { ...totpOptions, codeHashAlgorithm: 'SHA-256' });
52
- expect(uri).toBe('otpauth://totp/MyApp:user%40example.com?secret=AEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQCAIBAEAQ&issuer=MyApp&algorithm=SHA256&digits=6&period=30');
53
- });
54
- test('should verify a valid TOTP token with SHA-256', async () => {
55
- const secretData = new Uint8Array(new ArrayBuffer(32));
56
- secretData.fill(1);
57
- const secret = await importKey('raw-secret', secretData, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
58
- const timestamp = 1000000000;
59
- const options = { ...totpOptions, timestamp, codeHashAlgorithm: 'SHA-256' };
60
- const token = await generateTotpToken(secret, options);
61
- const isValid = await verifyTotpToken(secret, token, options);
62
- expect(isValid).toBe(true);
63
- });
64
- test('should verify a valid TOTP token with SHA-512', async () => {
65
- const secretData = new Uint8Array(new ArrayBuffer(64));
66
- secretData.fill(1);
67
- const secret = await importKey('raw-secret', secretData, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign']);
68
- const timestamp = 1000000000;
69
- const options = { ...totpOptions, timestamp, codeHashAlgorithm: 'SHA-512' };
70
- const token = await generateTotpToken(secret, options);
71
- const isValid = await verifyTotpToken(secret, token, options);
72
- expect(isValid).toBe(true);
73
- });
74
- test('should generate recovery codes', () => {
75
- const codes = generateTotpRecoveryCodes(10, 8);
76
- expect(codes.length).toBe(10);
77
- for (const code of codes) {
78
- expect(code).toMatch(/^[A-Z2-7]{8}$/);
79
- }
80
- });
81
- test('should hash and verify a recovery code', async () => {
82
- const code = 'ABCDEFGH';
83
- const salt = new Uint8Array(new ArrayBuffer(16));
84
- salt.fill(1);
85
- const options = { algorithm: { name: 'PBKDF2', hash: 'SHA-256', salt, iterations: 10 }, length: 64 };
86
- const hash = await hashTotpRecoveryCode(code, options);
87
- const isValid = await verifyTotpRecoveryCode(code, hash, options);
88
- expect(isValid).toBe(true);
89
- });
90
- test('should fail to verify an invalid recovery code', async () => {
91
- const code = 'ABCDEFGH';
92
- const salt = new Uint8Array(new ArrayBuffer(16));
93
- salt.fill(1);
94
- const options = { algorithm: { name: 'PBKDF2', hash: 'SHA-256', salt, iterations: 10 }, length: 64 };
95
- const hash = await hashTotpRecoveryCode(code, options);
96
- const isValid = await verifyTotpRecoveryCode('WRONGONE', hash, options);
97
- expect(isValid).toBe(false);
98
- });
99
- test('should hash and verify a recovery code with Argon2id', async () => {
100
- const code = 'ABCDEFGH';
101
- const salt = new Uint8Array(new ArrayBuffer(16));
102
- salt.fill(1);
103
- const options = { algorithm: { name: 'Argon2id', parallelism: 1, memory: 1024, passes: 1, nonce: salt }, length: 64 };
104
- const hash = await hashTotpRecoveryCode(code, options);
105
- const isValid = await verifyTotpRecoveryCode(code, hash, options);
106
- expect(isValid).toBe(true);
107
- });
108
- });
@@ -1,59 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest';
2
- import { injectModel } from '../../ai/genkit/index.js';
3
- import { runInInjectionContext } from '../../injector/index.js';
4
- import { setupIntegrationTest } from '../../testing/index.js';
5
- import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
6
- import { DocumentCategoryTypeService, DocumentManagementAiProviderService, DocumentManagementAncillaryService } from '../server/services/index.js';
7
- import { TestDocumentManagementAncillaryService } from './helper.js';
8
- describe('DocumentManagementAiService Hierarchy', () => {
9
- let injector;
10
- let aiService;
11
- const tenantId = crypto.randomUUID();
12
- const mockAiProvider = {
13
- getGlobalConfiguration: vi.fn(),
14
- getClassificationConfiguration: vi.fn(),
15
- getDataExtractionConfiguration: vi.fn(),
16
- getAssignmentConfiguration: vi.fn(),
17
- getValidationConfiguration: vi.fn(),
18
- getContentExtractionConfiguration: vi.fn(),
19
- };
20
- beforeAll(async () => {
21
- ({ injector } = await setupIntegrationTest({
22
- modules: { messageBus: true, signals: true, objectStorage: true, documentManagement: true },
23
- }));
24
- injector.register(DocumentManagementAiProviderService, { useValue: mockAiProvider });
25
- // Ancillary and configuration are already registered by setupIntegrationTest, but we can override if needed
26
- injector.register(DocumentManagementAncillaryService, { useToken: TestDocumentManagementAncillaryService });
27
- aiService = await injector.resolveAsync(DocumentManagementAiService);
28
- });
29
- afterAll(async () => {
30
- await injector?.dispose();
31
- });
32
- test('resolveAiConfiguration should implement Type > Category > Global Step > Global Defaults hierarchy', async () => {
33
- const categoryTypeService = await injector.resolveAsync(DocumentCategoryTypeService);
34
- const category = await categoryTypeService.createCategory({ tenantId, label: 'Finance', key: 'finance-cat', parentId: null });
35
- const type = await categoryTypeService.createType({ tenantId, categoryId: category.id, label: 'Invoice', key: 'invoice-type' });
36
- mockAiProvider.getGlobalConfiguration.mockResolvedValue({
37
- defaults: { language: 'de', classification: 'Global Default Classify' },
38
- steps: {
39
- 'data-extraction': { language: 'en', extraction: { title: 'Global Step Title' } }
40
- },
41
- categories: {
42
- 'finance-cat': { extraction: { title: 'Category Title', subtitle: 'Category Subtitle' } }
43
- },
44
- documentTypes: {
45
- 'invoice-type': { extraction: { title: 'Type Title' } }
46
- }
47
- });
48
- mockAiProvider.getDataExtractionConfiguration.mockResolvedValue({
49
- extraction: { subtitle: 'Provider Subtitle' }
50
- });
51
- await runInInjectionContext(injector, async () => {
52
- const config = await aiService.resolveAiConfiguration(tenantId, 'data-extraction', { type });
53
- expect(config.language).toBe('en'); // Step > Defaults
54
- expect(config.classification).toBe('Global Default Classify'); // Fallback to defaults
55
- expect(config.extraction.title).toBe('Type Title'); // Type > Category > Step
56
- expect(config.extraction.subtitle).toBe('Provider Subtitle'); // Provider > Category
57
- });
58
- });
59
- });
@@ -1,125 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest';
2
- const mockGenerate = vi.fn();
3
- vi.mock('genkit', async () => {
4
- const original = await vi.importActual('genkit');
5
- return {
6
- ...original,
7
- genkit: () => ({
8
- generate: mockGenerate,
9
- }),
10
- };
11
- });
12
- import { injectModel } from '../../ai/genkit/index.js';
13
- import { runInInjectionContext } from '../../injector/index.js';
14
- import { ObjectStorage } from '../../object-storage/index.js';
15
- import { setupIntegrationTest } from '../../testing/index.js';
16
- import { DocumentCategoryTypeService } from '../server/services/document-category-type.service.js';
17
- import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
18
- import { DocumentService } from '../server/services/document.service.js';
19
- import { DocumentManagementAiProviderService, DocumentManagementAncillaryService } from '../server/services/index.js';
20
- import { TestDocumentManagementAncillaryService } from './helper.js';
21
- describe('DocumentManagementAiService Integration', () => {
22
- let injector;
23
- let aiService;
24
- let flashModel;
25
- const tenantId = crypto.randomUUID();
26
- const mockAiProvider = {
27
- getGlobalConfiguration: vi.fn(),
28
- getClassificationConfiguration: vi.fn(),
29
- getDataExtractionConfiguration: vi.fn(),
30
- getAssignmentConfiguration: vi.fn(),
31
- getValidationConfiguration: vi.fn(),
32
- getContentExtractionConfiguration: vi.fn(),
33
- };
34
- beforeAll(async () => {
35
- ({ injector } = await setupIntegrationTest({
36
- modules: { messageBus: true, signals: true, objectStorage: true, documentManagement: true, taskQueue: true },
37
- }));
38
- const mockObjectStorage = {
39
- store: vi.fn().mockResolvedValue({ mimeType: 'application/pdf', hash: 'hash', size: 100 }),
40
- uploadObject: vi.fn(),
41
- getDownloadUrl: vi.fn(),
42
- getContent: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])),
43
- getContentStream: vi.fn(),
44
- getObject: vi.fn(),
45
- exists: vi.fn(),
46
- };
47
- runInInjectionContext(injector, () => {
48
- flashModel = injectModel('gemini-2.5-flash');
49
- });
50
- injector.register(DocumentManagementAiProviderService, { useValue: mockAiProvider });
51
- injector.register(DocumentManagementAncillaryService, { useToken: TestDocumentManagementAncillaryService });
52
- injector.register(ObjectStorage, { useValue: mockObjectStorage });
53
- aiService = await injector.resolveAsync(DocumentManagementAiService);
54
- });
55
- afterAll(async () => {
56
- await injector?.dispose();
57
- });
58
- test('extractData should include granular instructions in prompt', async () => {
59
- const categoryTypeService = await injector.resolveAsync(DocumentCategoryTypeService);
60
- const documentService = await injector.resolveAsync(DocumentService);
61
- const category = await categoryTypeService.createCategory({ tenantId, label: 'Finance', key: 'finance', parentId: null });
62
- const type = await categoryTypeService.createType({ tenantId, categoryId: category.id, label: 'Invoice', key: 'invoice' });
63
- const document = await documentService.create(tenantId, {
64
- typeId: type.id,
65
- originalFileName: 'test.pdf',
66
- skipWorkflow: true,
67
- assignment: { collections: [] }
68
- }, new Uint8Array([1, 2, 3]));
69
- mockAiProvider.getGlobalConfiguration.mockResolvedValue({
70
- documentTypes: {
71
- 'invoice': {
72
- extraction: {
73
- title: { format: 'INV-{{Date}}' },
74
- summary: { content: 'Focus on items.', strategy: 'append' }
75
- }
76
- }
77
- }
78
- });
79
- mockAiProvider.getDataExtractionConfiguration.mockResolvedValue(undefined);
80
- // Mock Genkit output
81
- mockGenerate.mockResolvedValue({
82
- output: {
83
- documentTitle: 'INV-2024',
84
- documentSubtitle: null,
85
- documentSummary: 'Summary',
86
- documentTags: [],
87
- documentDate: null
88
- }
89
- });
90
- await runInInjectionContext(injector, async () => {
91
- await aiService.extractData(tenantId, document.id);
92
- const lastCall = mockGenerate.mock.calls[0][0];
93
- const userPrompt = lastCall.prompt;
94
- const userPromptText = userPrompt.map((p) => p.text).join('\n');
95
- expect(userPromptText).toContain('Format the title of the document exactly as follows: INV-{{Date}}');
96
- expect(userPromptText).toContain('Focus on items.');
97
- });
98
- });
99
- test('classifyDocumentType should include granular instructions in prompt', async () => {
100
- const documentService = await injector.resolveAsync(DocumentService);
101
- const document = await documentService.create(tenantId, {
102
- originalFileName: 'test.pdf',
103
- skipWorkflow: true,
104
- assignment: { collections: [] }
105
- }, new Uint8Array([1, 2, 3]));
106
- mockAiProvider.getGlobalConfiguration.mockResolvedValue({
107
- defaults: {
108
- classification: { content: 'Prefer Finance types.', strategy: 'append' }
109
- }
110
- });
111
- mockAiProvider.getClassificationConfiguration.mockResolvedValue(undefined);
112
- mockGenerate.mockResolvedValue({
113
- output: {
114
- documentType: 'Category: Finance | Type: Invoice'
115
- }
116
- });
117
- await runInInjectionContext(injector, async () => {
118
- await aiService.classifyDocumentType(tenantId, document.id);
119
- const lastCall = mockGenerate.mock.calls[1][0];
120
- const systemPrompt = lastCall.system;
121
- const systemPromptText = systemPrompt.map((p) => p.text).join('\n');
122
- expect(systemPromptText).toContain('Prefer Finance types.');
123
- });
124
- });
125
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,46 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { mergeInstructions } from '../server/services/document-management-ai.service.js';
3
- describe('AI Instruction Merging', () => {
4
- test('should return base when no overrides are provided', () => {
5
- const base = 'Default instruction';
6
- expect(mergeInstructions(base, [])).toBe(base);
7
- });
8
- test('should replace with string override', () => {
9
- const base = 'Default instruction';
10
- const overrides = ['Custom instruction'];
11
- expect(mergeInstructions(base, overrides)).toBe('Custom instruction');
12
- });
13
- test('should append with append strategy', () => {
14
- const base = 'Default instruction';
15
- const overrides = [{ content: 'Added instruction', strategy: 'append' }];
16
- expect(mergeInstructions(base, overrides)).toBe('Default instruction\n\nAdded instruction');
17
- });
18
- test('should replace with replace strategy', () => {
19
- const base = 'Default instruction';
20
- const overrides = [{ content: 'New instruction', strategy: 'replace' }];
21
- expect(mergeInstructions(base, overrides)).toBe('New instruction');
22
- });
23
- test('should handle multiple overrides in order', () => {
24
- const base = 'Base';
25
- const overrides = [
26
- { content: 'Global', strategy: 'append' },
27
- { content: 'Category', strategy: 'append' },
28
- { content: 'Type', strategy: 'replace' }
29
- ];
30
- expect(mergeInstructions(base, overrides)).toBe('Type');
31
- });
32
- test('should handle format simple override', () => {
33
- const base = 'Create a title.';
34
- const overrides = [{ format: '[ID] - [Name]' }];
35
- const result = mergeInstructions(base, overrides);
36
- expect(result).toContain('[ID] - [Name]');
37
- });
38
- test('should handle Instructions in content', () => {
39
- const base = 'Base';
40
- const overrides = [{ content: { Detail: 'More info' }, strategy: 'append' }];
41
- const result = mergeInstructions(base, overrides);
42
- expect(result).toContain('Base');
43
- expect(result).toContain('# Detail');
44
- expect(result).toContain('More info');
45
- });
46
- });
@@ -1,63 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest';
2
- import { injectModel } from '../../ai/genkit/index.js';
3
- import { runInInjectionContext } from '../../injector/index.js';
4
- import { ObjectStorage } from '../../object-storage/index.js';
5
- import { setupIntegrationTest } from '../../testing/index.js';
6
- import { DocumentManagementConfiguration } from '../server/module.js';
7
- import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
8
- import { DocumentCategoryTypeService, DocumentManagementAiProviderService, DocumentManagementAncillaryService } from '../server/services/index.js';
9
- import { TestDocumentManagementAncillaryService } from './helper.js';
10
- describe('DocumentManagementAiService Overrides', () => {
11
- let injector;
12
- let aiService;
13
- let flashModel;
14
- let proModel;
15
- const tenantId = crypto.randomUUID();
16
- const mockAiProvider = {
17
- getGlobalConfiguration: vi.fn(),
18
- getClassificationConfiguration: vi.fn(),
19
- getDataExtractionConfiguration: vi.fn(),
20
- getAssignmentConfiguration: vi.fn(),
21
- getValidationConfiguration: vi.fn(),
22
- };
23
- beforeAll(async () => {
24
- ({ injector } = await setupIntegrationTest({
25
- modules: { messageBus: true, signals: true, objectStorage: true },
26
- }));
27
- runInInjectionContext(injector, () => {
28
- flashModel = injectModel('gemini-2.5-flash');
29
- proModel = injectModel('gemini-2.5-pro');
30
- });
31
- injector.register(DocumentManagementAiProviderService, { useValue: mockAiProvider });
32
- injector.register(DocumentManagementAncillaryService, { useToken: TestDocumentManagementAncillaryService });
33
- injector.register(DocumentManagementConfiguration, { useValue: { fileObjectStorageModule: 'docs', fileUploadObjectStorageModule: 'uploads', filePreviewObjectStorageModule: 'previews' } });
34
- aiService = await injector.resolveAsync(DocumentManagementAiService);
35
- });
36
- afterAll(async () => {
37
- await injector?.dispose();
38
- });
39
- test('resolveAiConfiguration should merge configurations correctly', async () => {
40
- const categoryTypeService = await injector.resolveAsync(DocumentCategoryTypeService);
41
- const category = await categoryTypeService.createCategory({ tenantId, label: 'Finance', key: 'finance-cat', parentId: null });
42
- const type = await categoryTypeService.createType({ tenantId, categoryId: category.id, label: 'Invoice', key: 'invoice-key' });
43
- mockAiProvider.getGlobalConfiguration.mockResolvedValue({
44
- defaults: {
45
- language: 'en',
46
- model: flashModel,
47
- prompt: { systemAddition: 'Global System' },
48
- },
49
- });
50
- mockAiProvider.getDataExtractionConfiguration.mockResolvedValue({
51
- model: proModel,
52
- prompt: { systemAddition: 'Extraction System', systemOverride: (base) => `OVERRIDDEN: ${base}` },
53
- });
54
- await runInInjectionContext(injector, async () => {
55
- // Accessing private method for testing purposes
56
- const config = await aiService.resolveAiConfiguration(tenantId, 'data-extraction', { type });
57
- expect(config.language).toBe('en');
58
- expect(config.model).toBe(proModel);
59
- expect(config.prompt.systemAddition).toEqual(['Global System', 'Extraction System']);
60
- expect(config.prompt.systemOverride('Base')).toBe('OVERRIDDEN: Base');
61
- });
62
- });
63
- });
@@ -1,157 +0,0 @@
1
- import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
2
- import { GenkitModuleOptions } from '../../ai/genkit/module.js';
3
- import { runInInjectionContext } from '../../injector/index.js';
4
- import { ObjectStorage } from '../../object-storage/index.js';
5
- import { TaskQueue } from '../../task-queue/index.js';
6
- import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
7
- import { configureDocumentManagement } from '../server/configure.js';
8
- import { DocumentCategoryTypeService } from '../server/services/document-category-type.service.js';
9
- import { DocumentCollectionService } from '../server/services/document-collection.service.js';
10
- import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
11
- import { DocumentManagementService } from '../server/services/document-management.service.js';
12
- import { DocumentPropertyService } from '../server/services/document-property.service.js';
13
- import { DocumentRequestService } from '../server/services/document-request.service.js';
14
- import { DocumentWorkflowService } from '../server/services/document-workflow.service.js';
15
- import { DocumentService } from '../server/services/document.service.js';
16
- import { TestDocumentManagementAncillaryService, TestDocumentManagementAuthorizationService } from './helper.js';
17
- describe('Document Management Core', () => {
18
- let injector;
19
- let database;
20
- let documentService;
21
- let collectionService;
22
- let requestService;
23
- let managementService;
24
- let categoryTypeService;
25
- const schema = 'document_management';
26
- const tenantId = crypto.randomUUID();
27
- beforeAll(async () => {
28
- ({ injector, database } = await setupIntegrationTest({
29
- modules: { taskQueue: false, messageBus: true, documentManagement: true }, // Disabled TaskQueue to avoid background noise
30
- orm: { schema },
31
- }));
32
- injector.register(GenkitModuleOptions, { useValue: {} });
33
- injector.register(DocumentManagementAiService, { useValue: { extractContent: vi.fn(), classifyDocumentType: vi.fn(), extractData: vi.fn(), findSuitableCollectionsForDocument: vi.fn(), findSuitableRequestForDocument: vi.fn() } });
34
- injector.register(ObjectStorage, {
35
- useValue: {
36
- uploadObject: vi.fn(),
37
- getDownloadUrl: vi.fn(),
38
- getContent: vi.fn(),
39
- getContentStream: vi.fn(),
40
- getObject: vi.fn(),
41
- exists: vi.fn(),
42
- },
43
- });
44
- // Mock TaskQueue
45
- injector.register(TaskQueue, {
46
- useValue: {
47
- enqueue: vi.fn(),
48
- enqueueMany: vi.fn(),
49
- process: vi.fn(),
50
- },
51
- });
52
- configureDocumentManagement({
53
- ancillaryService: TestDocumentManagementAncillaryService,
54
- authorizationService: TestDocumentManagementAuthorizationService,
55
- fileObjectStorageModule: 'documents',
56
- fileUploadObjectStorageModule: 'document-uploads',
57
- filePreviewObjectStorageModule: 'document-previews',
58
- injector,
59
- });
60
- documentService = await injector.resolveAsync(DocumentService);
61
- collectionService = await injector.resolveAsync(DocumentCollectionService);
62
- requestService = await injector.resolveAsync(DocumentRequestService);
63
- managementService = await injector.resolveAsync(DocumentManagementService);
64
- categoryTypeService = await injector.resolveAsync(DocumentCategoryTypeService);
65
- });
66
- afterAll(async () => {
67
- await injector?.dispose();
68
- });
69
- beforeEach(async () => {
70
- await clearTenantData(database, schema, ['request_collection_assignment', 'collection_assignment', 'workflow', 'request', 'document', 'collection', 'type', 'category'], tenantId);
71
- });
72
- // --- Collection Management ---
73
- test('Create and load collection', async () => {
74
- await runInInjectionContext(injector, async () => {
75
- const collection = await collectionService.createCollection(tenantId, null);
76
- expect(collection.id).toBeDefined();
77
- const loaded = await collectionService.repository.loadByQuery({ tenantId, id: collection.id });
78
- expect(loaded.id).toBe(collection.id);
79
- });
80
- });
81
- test('Load collection view resolves metadata', async () => {
82
- await runInInjectionContext(injector, async () => {
83
- const collection = await collectionService.createCollection(tenantId, null);
84
- const data = await managementService.loadData(tenantId, [collection.id]);
85
- const view = data.collections.find((c) => c.id === collection.id);
86
- expect(view).toBeDefined();
87
- // Metadata comes from TestDocumentManagementAncillaryService in helper.ts
88
- expect(view?.name).toBe(`Collection ${collection.id}`);
89
- expect(view?.group).toBe('Test');
90
- });
91
- });
92
- // --- Document Assignments ---
93
- test('Assign document to collection', async () => {
94
- await runInInjectionContext(injector, async () => {
95
- const collection = await collectionService.createCollection(tenantId, null);
96
- const doc = await documentService.create(tenantId, {
97
- originalFileName: 'test.pdf',
98
- assignment: { collections: [] },
99
- skipAi: true,
100
- }, new Uint8Array([]));
101
- await documentService.update(tenantId, doc.id, { collections: { assign: [collection.id] } });
102
- const assignedCollections = await managementService.getRelevantDocumentCollectionIds(tenantId, doc.id);
103
- expect(assignedCollections).toContain(collection.id);
104
- });
105
- });
106
- test('Unassign document from collection', async () => {
107
- await runInInjectionContext(injector, async () => {
108
- const collection = await collectionService.createCollection(tenantId, null);
109
- const doc = await documentService.create(tenantId, {
110
- originalFileName: 'test.pdf',
111
- assignment: { collections: [collection.id] },
112
- skipAi: true,
113
- }, new Uint8Array([]));
114
- // Archive assignment to unassign
115
- await documentService.update(tenantId, doc.id, { collections: { archive: [collection.id] } });
116
- // getRelevantDocumentCollectionIds includes all assignments (even archived ones maybe?).
117
- // Let's check the loadData response for active assignments.
118
- const data = await managementService.loadData(tenantId, [collection.id]);
119
- const docView = data.documents.find((d) => d.id === doc.id);
120
- // The assignment should be filtered out or marked archived in the view?
121
- // loadData: documentCollectionAssignments.filter((collectionDocument) => collectionDocument.documentId == document.id)
122
- // The query in loadData loads ALL assignments for the collection.
123
- // But typically "active" documents are what we care about.
124
- // If archived, it might still show up. Let's check the 'archiveTimestamp' in the assignment view.
125
- const assignment = docView?.assignment.collections.find((a) => a.collectionId === collection.id);
126
- expect(assignment?.archiveTimestamp).not.toBeNull();
127
- });
128
- });
129
- // --- Requests ---
130
- test('Create and load document request', async () => {
131
- await runInInjectionContext(injector, async () => {
132
- // Create a dummy type first
133
- const category = await categoryTypeService.createCategory({ tenantId, label: 'ReqCat', parentId: null });
134
- const type = await categoryTypeService.createType({ tenantId, label: 'ReqType', categoryId: category.id });
135
- const collection = await collectionService.createCollection(tenantId, null);
136
- const request = await requestService.createRequest(tenantId, type.id, [collection.id], 'New Request');
137
- expect(request.comment).toBe('New Request');
138
- // Verify via loadData (indirectly verifies persistence)
139
- const data = await managementService.loadData(tenantId, [collection.id]);
140
- const loaded = data.requests.find((r) => r.id === request.id);
141
- expect(loaded).toBeDefined();
142
- expect(loaded?.comment).toBe('New Request');
143
- });
144
- });
145
- test('Request with collection assignment', async () => {
146
- await runInInjectionContext(injector, async () => {
147
- const category = await categoryTypeService.createCategory({ tenantId, label: 'Cat2', parentId: null });
148
- const type = await categoryTypeService.createType({ tenantId, label: 'Type2', categoryId: category.id });
149
- const collection = await collectionService.createCollection(tenantId, null);
150
- const request = await requestService.createRequest(tenantId, type.id, [collection.id], 'Assignment Request');
151
- const data = await managementService.loadData(tenantId, [collection.id]);
152
- const reqView = data.requests.find((r) => r.id === request.id);
153
- expect(reqView).toBeDefined();
154
- expect(reqView?.collectionIds).toContain(collection.id);
155
- });
156
- });
157
- });