@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,94 +0,0 @@
1
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
- import { Database } from '../../orm/server/index.js';
3
- import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
4
- import { task as taskTable } from '../../task-queue/postgres/schemas.js';
5
- import { setupIntegrationTest } from '../../testing/index.js';
6
- import { currentTimestamp } from '../../utils/date-time.js';
7
- import { eq } from 'drizzle-orm';
8
- describe('Fan-Out Spawning', () => {
9
- let injector;
10
- let queue;
11
- let database;
12
- beforeAll(async () => {
13
- ({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
14
- database = injector.resolve(Database);
15
- });
16
- beforeEach(() => {
17
- const queueProvider = injector.resolve(TaskQueueProvider);
18
- const queueName = `fan-out-queue-${crypto.randomUUID()}`;
19
- queue = queueProvider.get(queueName, {
20
- visibilityTimeout: 1000,
21
- });
22
- });
23
- afterEach(async () => {
24
- await queue.clear();
25
- });
26
- afterAll(async () => {
27
- await injector?.dispose();
28
- });
29
- it('should transition parent to Waiting when spawning children during execution', async () => {
30
- const parent = await queue.enqueue('parent', {});
31
- const dParent = await queue.dequeue();
32
- expect(dParent?.id).toBe(parent.id);
33
- // Parent spawns a child
34
- const [child] = await queue.enqueueMany([{ type: 'child', data: {}, parentId: parent.id }], { returnTasks: true });
35
- // Complete parent
36
- await queue.complete(dParent);
37
- // Parent should be Waiting for child
38
- const uParent = await queue.getTask(parent.id);
39
- expect(uParent?.status).toBe(TaskStatus.WaitingChildren);
40
- expect(uParent?.unresolvedCompleteDependencies).toBe(1);
41
- // Complete child
42
- const dChild = await queue.dequeue();
43
- await queue.complete(dChild);
44
- // Parent should now be Completed
45
- const fParent = await queue.getTask(parent.id);
46
- expect(fParent?.status).toBe(TaskStatus.Completed);
47
- });
48
- it('should NOT transition parent to Waiting if parentRequires is false', async () => {
49
- const parent = await queue.enqueue('parent', {});
50
- const dParent = await queue.dequeue();
51
- // Spawn child with parentRequires: false
52
- await queue.enqueueMany([{ type: 'child', data: {}, parentId: parent.id, parentRequires: false }], { returnTasks: true });
53
- await queue.complete(dParent);
54
- const uParent = await queue.getTask(parent.id);
55
- expect(uParent?.status).toBe(TaskStatus.Completed); // Finished immediately
56
- expect(uParent?.unresolvedCompleteDependencies).toBe(0);
57
- });
58
- it('should transition parent from WaitingChildren to Completed exactly when the last child finishes', async () => {
59
- const parent = await queue.enqueue('parent', {});
60
- const c1 = await queue.enqueue('child', { val: 1 }, { parentId: parent.id });
61
- const c2 = await queue.enqueue('child', { val: 2 }, { parentId: parent.id });
62
- const dp = await queue.dequeue();
63
- await queue.complete(dp);
64
- const up1 = await queue.getTask(parent.id);
65
- expect(up1?.status).toBe(TaskStatus.WaitingChildren);
66
- const dc1 = await queue.dequeue();
67
- await queue.complete(dc1);
68
- const up2 = await queue.getTask(parent.id);
69
- expect(up2?.status).toBe(TaskStatus.WaitingChildren);
70
- const dc2 = await queue.dequeue();
71
- await queue.complete(dc2);
72
- const up3 = await queue.getTask(parent.id);
73
- expect(up3?.status).toBe(TaskStatus.Completed);
74
- });
75
- it('should protect parent tasks from archival if orphaned child tasks still exist', async () => {
76
- const queueProvider = injector.resolve(TaskQueueProvider);
77
- const ephemeralQueue = queueProvider.get(`ephemeral-${crypto.randomUUID()}`, { retention: 0 });
78
- const parent = await ephemeralQueue.enqueue('parent', {});
79
- await ephemeralQueue.enqueue('child', {}, { parentId: parent.id });
80
- // Manually complete parent while child is still pending
81
- await database
82
- .update(taskTable)
83
- .set({
84
- status: TaskStatus.Completed,
85
- completeTimestamp: currentTimestamp() - 1000,
86
- })
87
- .where(eq(taskTable.id, parent.id));
88
- await ephemeralQueue.maintenance();
89
- const updatedParent = await ephemeralQueue.getTask(parent.id);
90
- expect(updatedParent).toBeDefined(); // Should still be in main table
91
- expect(updatedParent?.status).toBe(TaskStatus.Completed);
92
- await ephemeralQueue.clear();
93
- });
94
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,114 +0,0 @@
1
- import { eq } from 'drizzle-orm';
2
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
3
- import { Database } from '../../orm/server/index.js';
4
- import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
5
- import { taskDependency as taskDependencyTable } from '../../task-queue/postgres/schemas.js';
6
- import { setupIntegrationTest } from '../../testing/index.js';
7
- import { timeout } from '../../utils/timing.js';
8
- describe('Idempotent Replacement', () => {
9
- let injector;
10
- let queue;
11
- let database;
12
- beforeAll(async () => {
13
- ({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
14
- database = injector.resolve(Database);
15
- });
16
- beforeEach(() => {
17
- const queueProvider = injector.resolve(TaskQueueProvider);
18
- const queueName = `idempotent-queue-${crypto.randomUUID()}`;
19
- queue = queueProvider.get(queueName, {
20
- visibilityTimeout: 1000,
21
- });
22
- });
23
- afterEach(async () => {
24
- await queue.clear();
25
- });
26
- afterAll(async () => {
27
- await injector?.dispose();
28
- });
29
- it('should NOT be affected by "ghost" dependencies after replacement', async () => {
30
- const depA = await queue.enqueue('depA', {});
31
- const depB = await queue.enqueue('depB', {});
32
- const depC = await queue.enqueue('depC', {});
33
- const idempotencyKey = 'my-idempotent-task';
34
- // 1. Initial enqueue with A and B
35
- const taskV1 = await queue.enqueue('main', { version: 1 }, {
36
- idempotencyKey,
37
- scheduleAfter: [depA.id, depB.id],
38
- });
39
- expect(taskV1.status).toBe(TaskStatus.Waiting);
40
- expect(taskV1.unresolvedScheduleDependencies).toBe(2);
41
- // 2. Replacement enqueue with only C
42
- const taskV2 = await queue.enqueue('main', { version: 2 }, {
43
- idempotencyKey,
44
- scheduleAfter: [depC.id],
45
- replace: true,
46
- });
47
- expect(taskV2.id).toBe(taskV1.id);
48
- expect(taskV2.unresolvedScheduleDependencies).toBe(1);
49
- expect(taskV2.data).toEqual({ version: 2 });
50
- // 3. Complete an OLD dependency (depA)
51
- const dDepA = await queue.dequeue({ types: ['depA'] });
52
- await queue.complete(dDepA);
53
- // Give it a moment to process background dependency resolution if any
54
- await timeout(100);
55
- // 4. Verify main task is STILL waiting for depC
56
- const uTask = await queue.getTask(taskV1.id);
57
- expect(uTask?.status).toBe(TaskStatus.Waiting);
58
- expect(uTask?.unresolvedScheduleDependencies).toBe(1);
59
- // 5. Complete NEW dependency (depC)
60
- const dDepC = await queue.dequeue({ types: ['depC'] });
61
- await queue.complete(dDepC);
62
- // 6. Verify main task is now Pending
63
- const fTask = await queue.getTask(taskV1.id);
64
- expect(fTask?.status).toBe(TaskStatus.Pending);
65
- });
66
- it('should update parentId on replacement', async () => {
67
- const parent1 = await queue.enqueue('parent', { id: 1 });
68
- const parent2 = await queue.enqueue('parent', { id: 2 });
69
- const idempotencyKey = 'task-1';
70
- const taskV1 = await queue.enqueue('child', {}, { idempotencyKey, parentId: parent1.id });
71
- expect(taskV1.parentId).toBe(parent1.id);
72
- // Replace with new parent
73
- const taskV2 = await queue.enqueue('child', {}, { idempotencyKey, parentId: parent2.id, replace: true });
74
- expect(taskV2.id).toBe(taskV1.id);
75
- expect(taskV2.parentId).toBe(parent2.id);
76
- });
77
- it('should NOT corrupt state on idempotent enqueues (replace: false)', async () => {
78
- const dep = await queue.enqueue('dep', {});
79
- const idempotencyKey = 'task-2';
80
- // Initial enqueue without dependency
81
- const taskV1 = await queue.enqueue('main', {}, { idempotencyKey });
82
- expect(taskV1.status).toBe(TaskStatus.Pending);
83
- // Deduplicated enqueue with dependency
84
- const taskV2 = await queue.enqueue('main', {}, { idempotencyKey, scheduleAfter: [dep.id], replace: false });
85
- expect(taskV2.id).toBe(taskV1.id);
86
- const task = await queue.getTask(taskV2.id);
87
- expect(task?.status).toBe(TaskStatus.Pending);
88
- expect(task?.unresolvedScheduleDependencies).toBe(0);
89
- });
90
- it('should NOT orphan children on task replacement', async () => {
91
- const idempotencyKey = 'parent-task';
92
- const parent = await queue.enqueue('parent', {}, { idempotencyKey });
93
- // Enqueue child
94
- await queue.enqueue('child', {}, { parentId: parent.id });
95
- const parentAfterChild = await queue.getTask(parent.id);
96
- expect(parentAfterChild?.unresolvedCompleteDependencies).toBe(1);
97
- // Replace parent
98
- const replacedParent = await queue.enqueue('parent', { replaced: true }, { idempotencyKey, replace: true });
99
- expect(replacedParent.unresolvedCompleteDependencies).toBe(1);
100
- });
101
- it('should clear and recreate dependencies when enqueuing existing tasks with replace: true', async () => {
102
- const dep1 = await queue.enqueue('test', { value: 'dep1' });
103
- const dep2 = await queue.enqueue('test', { value: 'dep2' });
104
- const task = await queue.enqueue('test', { value: 'main' }, { idempotencyKey: 'main-key', scheduleAfter: [dep1.id] });
105
- // Re-enqueue with replace: true and different dependency
106
- await queue.enqueue('test', { value: 'main-replaced' }, { idempotencyKey: 'main-key', replace: true, scheduleAfter: [dep2.id] });
107
- const deps = await database
108
- .select()
109
- .from(taskDependencyTable)
110
- .where(eq(taskDependencyTable.taskId, task.id));
111
- expect(deps).toHaveLength(1);
112
- expect(deps[0].dependencyTaskId).toBe(dep2.id);
113
- });
114
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,39 +0,0 @@
1
- import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
2
- import { TaskQueueProvider, TaskStatus } from '../../task-queue/index.js';
3
- import { setupIntegrationTest } from '../../testing/index.js';
4
- describe('Missing Idempotent Tasks Bug', () => {
5
- let injector;
6
- let queue;
7
- beforeAll(async () => {
8
- ({ injector } = await setupIntegrationTest({ modules: { taskQueue: true } }));
9
- });
10
- beforeEach(() => {
11
- const queueProvider = injector.resolve(TaskQueueProvider);
12
- const queueName = `missing-idem-queue-${crypto.randomUUID()}`;
13
- queue = queueProvider.get(queueName, {
14
- visibilityTimeout: 1000,
15
- });
16
- });
17
- afterEach(async () => {
18
- await queue.clear();
19
- });
20
- afterAll(async () => {
21
- await injector?.dispose();
22
- });
23
- it('should NOT crash when enqueuing duplicate idempotent tasks with dependencies and returnTasks: false', async () => {
24
- const key = 'idem-key';
25
- const dep = await queue.enqueue('dep', {});
26
- // 1. Initial enqueue
27
- const task1 = await queue.enqueue('main', {}, { idempotencyKey: key });
28
- // 2. Second enqueue with same key and a dependency, returnTasks: false
29
- // This should NOT crash.
30
- // replace=false means we should ignore the new data AND the new dependency for the existing task.
31
- await expect(queue.enqueueMany([
32
- { type: 'main', data: { new: 'data' }, idempotencyKey: key, scheduleAfter: [dep.id] }
33
- ], { replace: false, returnTasks: false })).resolves.toBeUndefined();
34
- const updatedTask = await queue.getTask(task1.id);
35
- expect(updatedTask?.data).toEqual({}); // Data should not have changed
36
- expect(updatedTask?.unresolvedScheduleDependencies).toBe(0); // Dependency should not have been added
37
- expect(updatedTask?.status).toBe(TaskStatus.Pending); // Should still be Pending, not Waiting
38
- });
39
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,124 +0,0 @@
1
- import { and, eq, sql } from 'drizzle-orm';
2
- import { describe, expect, vi } from 'vitest';
3
- import { inject } from '../../injector/index.js';
4
- import { TRANSACTION_TIMESTAMP } from '../../orm/index.js';
5
- import { injectRepository } from '../../orm/server/index.js';
6
- import { getIntegrationTest } from '../../testing/index.js';
7
- import { timeout } from '../../utils/timing.js';
8
- import { taskArchive as taskArchiveTable, taskDependency as taskDependencyTable, task as taskTable } from '../postgres/schemas.js';
9
- import { PostgresTaskQueue } from '../postgres/task-queue.js';
10
- import { PostgresTask, PostgresTaskArchive } from '../postgres/task.model.js';
11
- import { TaskDependencyType, TaskStatus } from '../task-queue.js';
12
- const test = getIntegrationTest({ modules: { taskQueue: true } });
13
- describe('Task Queue Optimization Edge Cases', () => {
14
- test('should notify unique namespaces exactly once in incrementCounters', async () => {
15
- const q1 = inject(PostgresTaskQueue, 'ns-1');
16
- const q2 = inject(PostgresTaskQueue, 'ns-2');
17
- const notifySpy = vi.spyOn(PostgresTaskQueue.prototype, 'notify');
18
- const [t1] = await q1.enqueueMany([{ type: 't1', data: {} }], { returnTasks: true });
19
- const [t2] = await q2.enqueueMany([{ type: 't2', data: {} }], { returnTasks: true });
20
- notifySpy.mockClear();
21
- await q1.incrementCounters([
22
- { taskId: t1.id, dependencyTaskId: 'some-dep', type: TaskDependencyType.Schedule },
23
- { taskId: t2.id, dependencyTaskId: 'some-dep', type: TaskDependencyType.Schedule },
24
- { taskId: t1.id, dependencyTaskId: 'other-dep', type: TaskDependencyType.Schedule },
25
- ]);
26
- const notifiedNamespaces = notifySpy.mock.calls.map(call => call[0]);
27
- expect(notifiedNamespaces).toContain('ns-1');
28
- expect(notifiedNamespaces).toContain('ns-2');
29
- expect(notifiedNamespaces.filter(n => n == 'ns-1').length).toBe(1);
30
- expect(notifiedNamespaces.filter(n => n == 'ns-2').length).toBe(1);
31
- });
32
- test('should resolve edge and abort on unmatched terminal status in resolveDependenciesMany', async () => {
33
- const queue = inject(PostgresTaskQueue, 'test-namespace');
34
- const repository = injectRepository(PostgresTask);
35
- const [parent] = await queue.enqueueMany([{ type: 'parent', data: {}, abortOnDependencyFailure: true }], { returnTasks: true });
36
- const [child] = await queue.enqueueMany([{ type: 'child', data: {} }], { returnTasks: true });
37
- await repository.session.insert(taskDependencyTable).values({
38
- taskId: parent.id,
39
- dependencyTaskId: child.id,
40
- type: TaskDependencyType.Schedule,
41
- requiredStatuses: [TaskStatus.Completed],
42
- });
43
- await repository.session.update(taskTable).set({ unresolvedScheduleDependencies: 1, status: TaskStatus.Waiting }).where(eq(taskTable.id, parent.id));
44
- await queue.resolveDependenciesMany([{ id: child.id, status: TaskStatus.Dead, namespace: 'test-namespace' }]);
45
- const updatedParent = await queue.getTask(parent.id);
46
- expect(updatedParent.status).toBe(TaskStatus.Skipped);
47
- });
48
- test('should handle hard timeout during touch', async () => {
49
- // Configure with small maxExecutionTime
50
- const queue = inject(PostgresTaskQueue, { namespace: 'timeout-test', maxExecutionTime: 10 });
51
- const [task] = await queue.enqueueMany([{ type: 'test', data: {} }], { returnTasks: true });
52
- const [runningTask] = await queue.dequeueMany(1);
53
- await timeout(50);
54
- const result = await queue.touch(runningTask);
55
- expect(result).toBeUndefined();
56
- const updated = await queue.getTask(runningTask.id);
57
- expect(updated.status).toBe(TaskStatus.TimedOut);
58
- });
59
- test('should handle non-existent tasks in complete and fail', async () => {
60
- const queue = inject(PostgresTaskQueue, 'missing-test');
61
- const fakeTask = { id: crypto.randomUUID(), token: crypto.randomUUID(), tries: 0 };
62
- await expect(queue.complete(fakeTask)).resolves.toBeUndefined();
63
- await expect(queue.fail(fakeTask, new Error('fail'))).resolves.toBeUndefined();
64
- });
65
- test('should handle terminal tasks with no dependents in resolveDependenciesMany', async () => {
66
- const queue = inject(PostgresTaskQueue, 'no-deps-test');
67
- const [task] = await queue.enqueueMany([{ type: 'test', data: {} }], { returnTasks: true });
68
- await queue.resolveDependenciesMany([{ id: task.id, status: TaskStatus.Completed }]);
69
- });
70
- test('should handle archival and purge in maintenance', async () => {
71
- const namespace = `archival-test-${crypto.randomUUID()}`;
72
- // Configure with small retention
73
- const queue = inject(PostgresTaskQueue, { namespace, retention: 1000, archiveRetention: 1000 });
74
- const repository = injectRepository(PostgresTask);
75
- const archiveRepository = injectRepository(PostgresTaskArchive);
76
- const [task] = await queue.enqueueMany([{ type: 'test', data: {} }], { returnTasks: true });
77
- await repository.session.update(taskTable)
78
- .set({
79
- status: TaskStatus.Completed,
80
- completeTimestamp: sql `${TRANSACTION_TIMESTAMP} - interval '2 seconds'`,
81
- })
82
- .where(and(eq(taskTable.id, task.id), eq(taskTable.namespace, namespace)));
83
- await queue.performArchival();
84
- const archived = await archiveRepository.load(task.id);
85
- expect(archived).toBeDefined();
86
- await repository.session.update(taskArchiveTable)
87
- .set({ completeTimestamp: sql `${TRANSACTION_TIMESTAMP} - interval '2 seconds'` })
88
- .where(and(eq(taskArchiveTable.id, task.id), eq(taskArchiveTable.namespace, namespace)));
89
- await queue.performArchivePurge();
90
- const purged = await archiveRepository.load(task.id).catch(() => undefined);
91
- expect(purged).toBeUndefined();
92
- });
93
- test('should notify on restart', async () => {
94
- const namespace = `restart-test-${crypto.randomUUID()}`;
95
- const queue = inject(PostgresTaskQueue, namespace);
96
- const notifySpy = vi.spyOn(PostgresTaskQueue.prototype, 'notify');
97
- const [task] = await queue.enqueueMany([{ type: 'test', data: {} }], { returnTasks: true });
98
- await queue.cancelMany([task.id]);
99
- notifySpy.mockClear();
100
- await queue.restart(task.id);
101
- expect(notifySpy).toHaveBeenCalledWith(namespace);
102
- });
103
- test('should use exponential backoff for zombies', async () => {
104
- const namespace = `zombie-backoff-${crypto.randomUUID()}`;
105
- // Configure with standard growth
106
- const queue = inject(PostgresTaskQueue, { namespace, retryDelayMinimum: 1000, retryDelayGrowth: 2 });
107
- const repository = injectRepository(PostgresTask);
108
- const [task] = await queue.enqueueMany([{ type: 'test', data: {} }], { returnTasks: true });
109
- await queue.dequeueMany(1);
110
- await repository.session.update(taskTable)
111
- .set({
112
- status: TaskStatus.Running,
113
- visibilityDeadline: sql `${TRANSACTION_TIMESTAMP} - interval '1 minute'`,
114
- tries: 2,
115
- })
116
- .where(and(eq(taskTable.id, task.id), eq(taskTable.namespace, namespace)));
117
- await queue.recoverStaleTasks();
118
- const updated = await queue.getTask(task.id);
119
- expect(updated.status).toBe(TaskStatus.Retrying);
120
- const delay = updated.scheduleTimestamp - Date.now();
121
- expect(delay).toBeGreaterThan(1000);
122
- expect(delay).toBeLessThan(3000);
123
- });
124
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,8 +0,0 @@
1
- import { describe, test, expectTypeOf } from 'vitest';
2
- describe('TaskQueue Class Generic', () => {
3
- test('TaskQueue should accept TaskDefinitionMap', () => {
4
- // If it compiles, it's good. But we can inspect the generic constraints.
5
- // For now, simple existence check.
6
- expectTypeOf().toBeObject();
7
- });
8
- });
@@ -1 +0,0 @@
1
- export {};