@tstdl/base 0.93.182 → 0.93.183

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/api/server/api-request-token.provider.js +1 -1
  2. package/api/server/gateway.js +6 -1
  3. package/authentication/authentication.api.d.ts +13 -40
  4. package/authentication/authentication.api.js +5 -14
  5. package/authentication/client/authentication.service.d.ts +6 -14
  6. package/authentication/client/authentication.service.js +22 -4
  7. package/authentication/client/module.d.ts +1 -1
  8. package/authentication/client/module.js +4 -4
  9. package/authentication/models/index.d.ts +1 -0
  10. package/authentication/models/index.js +1 -0
  11. package/authentication/models/totp-results.model.d.ts +11 -0
  12. package/authentication/models/totp-results.model.js +37 -0
  13. package/authentication/server/authentication.api-controller.d.ts +3 -3
  14. package/authentication/server/authentication.api-controller.js +31 -4
  15. package/authentication/server/authentication.service.d.ts +5 -14
  16. package/authentication/server/authentication.service.js +6 -4
  17. package/core.d.ts +0 -5
  18. package/core.js +0 -8
  19. package/document-management/api/document-management.api.d.ts +2 -2
  20. package/document-management/service-models/document.service-model.d.ts +1 -1
  21. package/examples/config.d.ts +25 -0
  22. package/examples/config.js +26 -0
  23. package/notification/server/module.d.ts +1 -1
  24. package/notification/server/module.js +1 -1
  25. package/package.json +5 -5
  26. package/signals/api.d.ts +5 -1
  27. package/signals/api.js +3 -1
  28. package/signals/implementation/api.d.ts +13 -5
  29. package/signals/implementation/api.js +7 -1
  30. package/signals/implementation/asserts.d.ts +2 -2
  31. package/signals/implementation/asserts.js +3 -3
  32. package/signals/implementation/computed.d.ts +7 -34
  33. package/signals/implementation/computed.js +14 -83
  34. package/signals/implementation/configure.js +6 -2
  35. package/signals/implementation/effect.d.ts +65 -46
  36. package/signals/implementation/effect.js +97 -62
  37. package/signals/implementation/index.d.ts +2 -4
  38. package/signals/implementation/index.js +2 -4
  39. package/signals/implementation/linked_signal.d.ts +36 -0
  40. package/signals/implementation/linked_signal.js +34 -0
  41. package/signals/implementation/primitive/computed.d.ts +55 -0
  42. package/signals/implementation/primitive/computed.js +107 -0
  43. package/signals/implementation/primitive/effect.d.ts +26 -0
  44. package/signals/implementation/primitive/effect.js +31 -0
  45. package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
  46. package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
  47. package/signals/implementation/primitive/errors.d.ts +10 -0
  48. package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
  49. package/signals/implementation/primitive/formatter.d.ts +19 -0
  50. package/signals/implementation/primitive/formatter.js +136 -0
  51. package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
  52. package/signals/implementation/primitive/graph.js +386 -0
  53. package/signals/implementation/primitive/linked_signal.d.ts +46 -0
  54. package/signals/implementation/primitive/linked_signal.js +110 -0
  55. package/signals/implementation/primitive/signal.d.ts +31 -0
  56. package/signals/implementation/primitive/signal.js +80 -0
  57. package/signals/implementation/primitive/untracked.d.ts +12 -0
  58. package/signals/implementation/primitive/untracked.js +23 -0
  59. package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
  60. package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
  61. package/signals/implementation/resource/api.d.ts +275 -0
  62. package/signals/implementation/resource/api.js +26 -0
  63. package/signals/implementation/resource/debounce.d.ts +13 -0
  64. package/signals/implementation/resource/debounce.js +113 -0
  65. package/signals/implementation/resource/from_snapshots.d.ts +16 -0
  66. package/signals/implementation/resource/from_snapshots.js +44 -0
  67. package/signals/implementation/resource/index.d.ts +11 -0
  68. package/signals/implementation/resource/index.js +11 -0
  69. package/signals/implementation/resource/resource.d.ts +110 -0
  70. package/signals/implementation/resource/resource.js +402 -0
  71. package/signals/implementation/root_effect_scheduler.d.ts +50 -0
  72. package/signals/implementation/root_effect_scheduler.js +66 -0
  73. package/signals/implementation/signal.d.ts +42 -18
  74. package/signals/implementation/signal.js +29 -49
  75. package/signals/implementation/to-observable.d.ts +12 -5
  76. package/signals/implementation/to-observable.js +12 -2
  77. package/signals/implementation/to-signal.d.ts +9 -18
  78. package/signals/implementation/to-signal.js +46 -13
  79. package/signals/implementation/untracked.d.ts +1 -1
  80. package/signals/implementation/untracked.js +3 -11
  81. package/signals/operators/debounce.d.ts +8 -0
  82. package/signals/operators/debounce.js +19 -0
  83. package/signals/operators/derive-async.js +43 -15
  84. package/signals/operators/index.d.ts +2 -0
  85. package/signals/operators/index.js +2 -0
  86. package/signals/operators/throttle.d.ts +8 -0
  87. package/signals/operators/throttle.js +31 -0
  88. package/ai/genkit/tests/multi-region.test.d.ts +0 -2
  89. package/ai/genkit/tests/multi-region.test.js +0 -179
  90. package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
  91. package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
  92. package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
  93. package/ai/prompts/tests/prompt-builder.test.js +0 -22
  94. package/ai/tests/instructions-formatter.test.d.ts +0 -1
  95. package/ai/tests/instructions-formatter.test.js +0 -116
  96. package/ai/tests/steering.test.d.ts +0 -1
  97. package/ai/tests/steering.test.js +0 -37
  98. package/api/client/tests/api-client.test.d.ts +0 -1
  99. package/api/client/tests/api-client.test.js +0 -194
  100. package/api/server/tests/csrf.middleware.test.d.ts +0 -1
  101. package/api/server/tests/csrf.middleware.test.js +0 -91
  102. package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
  103. package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
  104. package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
  105. package/authentication/tests/authentication.api-controller.test.js +0 -156
  106. package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
  107. package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
  108. package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
  109. package/authentication/tests/authentication.client-error-handling.test.js +0 -123
  110. package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
  111. package/authentication/tests/authentication.client-middleware.test.js +0 -118
  112. package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
  113. package/authentication/tests/authentication.client-service-methods.test.js +0 -177
  114. package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
  115. package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
  116. package/authentication/tests/authentication.client-service.test.d.ts +0 -1
  117. package/authentication/tests/authentication.client-service.test.js +0 -76
  118. package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
  119. package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
  120. package/authentication/tests/authentication.service.test.d.ts +0 -1
  121. package/authentication/tests/authentication.service.test.js +0 -167
  122. package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
  123. package/authentication/tests/authentication.test-ancillary-service.js +0 -27
  124. package/authentication/tests/brute-force-protection.test.d.ts +0 -1
  125. package/authentication/tests/brute-force-protection.test.js +0 -211
  126. package/authentication/tests/helper.test.d.ts +0 -1
  127. package/authentication/tests/helper.test.js +0 -122
  128. package/authentication/tests/password-requirements.error.test.d.ts +0 -1
  129. package/authentication/tests/password-requirements.error.test.js +0 -14
  130. package/authentication/tests/remember.api.test.d.ts +0 -1
  131. package/authentication/tests/remember.api.test.js +0 -117
  132. package/authentication/tests/remember.service.test.d.ts +0 -1
  133. package/authentication/tests/remember.service.test.js +0 -83
  134. package/authentication/tests/subject.service.test.d.ts +0 -1
  135. package/authentication/tests/subject.service.test.js +0 -140
  136. package/authentication/tests/suspended-subject.test.d.ts +0 -1
  137. package/authentication/tests/suspended-subject.test.js +0 -120
  138. package/authentication/tests/totp.enrollment.test.d.ts +0 -1
  139. package/authentication/tests/totp.enrollment.test.js +0 -123
  140. package/authentication/tests/totp.login.test.d.ts +0 -1
  141. package/authentication/tests/totp.login.test.js +0 -213
  142. package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
  143. package/authentication/tests/totp.recovery-codes.test.js +0 -97
  144. package/authentication/tests/totp.status.test.d.ts +0 -1
  145. package/authentication/tests/totp.status.test.js +0 -72
  146. package/cancellation/tests/coverage.test.d.ts +0 -1
  147. package/cancellation/tests/coverage.test.js +0 -49
  148. package/cancellation/tests/leak.test.d.ts +0 -1
  149. package/cancellation/tests/leak.test.js +0 -35
  150. package/cancellation/tests/token.test.d.ts +0 -1
  151. package/cancellation/tests/token.test.js +0 -136
  152. package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
  153. package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
  154. package/cryptography/tests/cryptography.test.d.ts +0 -1
  155. package/cryptography/tests/cryptography.test.js +0 -175
  156. package/cryptography/tests/jwt.test.d.ts +0 -1
  157. package/cryptography/tests/jwt.test.js +0 -54
  158. package/cryptography/tests/modern.test.d.ts +0 -1
  159. package/cryptography/tests/modern.test.js +0 -105
  160. package/cryptography/tests/module.test.d.ts +0 -1
  161. package/cryptography/tests/module.test.js +0 -100
  162. package/cryptography/tests/totp.test.d.ts +0 -1
  163. package/cryptography/tests/totp.test.js +0 -108
  164. package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
  165. package/document-management/tests/ai-config-hierarchy.test.js +0 -59
  166. package/document-management/tests/ai-config-integration.test.d.ts +0 -1
  167. package/document-management/tests/ai-config-integration.test.js +0 -125
  168. package/document-management/tests/ai-config-merge.test.d.ts +0 -1
  169. package/document-management/tests/ai-config-merge.test.js +0 -46
  170. package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
  171. package/document-management/tests/document-management-ai-overrides.test.js +0 -63
  172. package/document-management/tests/document-management-core.test.d.ts +0 -1
  173. package/document-management/tests/document-management-core.test.js +0 -157
  174. package/document-management/tests/document-management.api.test.d.ts +0 -1
  175. package/document-management/tests/document-management.api.test.js +0 -101
  176. package/document-management/tests/document-statistics.service.test.d.ts +0 -1
  177. package/document-management/tests/document-statistics.service.test.js +0 -498
  178. package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
  179. package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
  180. package/document-management/tests/document.service.test.d.ts +0 -1
  181. package/document-management/tests/document.service.test.js +0 -143
  182. package/document-management/tests/enum-helpers.test.d.ts +0 -1
  183. package/document-management/tests/enum-helpers.test.js +0 -452
  184. package/document-management/tests/helper.d.ts +0 -24
  185. package/document-management/tests/helper.js +0 -39
  186. package/errors/tests/format.test.d.ts +0 -1
  187. package/errors/tests/format.test.js +0 -84
  188. package/http/tests/server-timing.test.d.ts +0 -1
  189. package/http/tests/server-timing.test.js +0 -42
  190. package/injector/tests/advanced.test.d.ts +0 -1
  191. package/injector/tests/advanced.test.js +0 -116
  192. package/injector/tests/async-init.test.d.ts +0 -1
  193. package/injector/tests/async-init.test.js +0 -77
  194. package/injector/tests/basic.test.d.ts +0 -1
  195. package/injector/tests/basic.test.js +0 -114
  196. package/injector/tests/hierarchical.test.d.ts +0 -1
  197. package/injector/tests/hierarchical.test.js +0 -59
  198. package/injector/tests/leak.test.d.ts +0 -1
  199. package/injector/tests/leak.test.js +0 -45
  200. package/injector/tests/lifecycles.test.d.ts +0 -1
  201. package/injector/tests/lifecycles.test.js +0 -109
  202. package/logger/tests/pretty-print.test.d.ts +0 -1
  203. package/logger/tests/pretty-print.test.js +0 -60
  204. package/notification/tests/notification-api.test.d.ts +0 -1
  205. package/notification/tests/notification-api.test.js +0 -124
  206. package/notification/tests/notification-client.test.d.ts +0 -1
  207. package/notification/tests/notification-client.test.js +0 -101
  208. package/notification/tests/notification-flow.test.d.ts +0 -1
  209. package/notification/tests/notification-flow.test.js +0 -296
  210. package/notification/tests/notification-sse.service.test.d.ts +0 -1
  211. package/notification/tests/notification-sse.service.test.js +0 -43
  212. package/notification/tests/notification-type.service.test.d.ts +0 -1
  213. package/notification/tests/notification-type.service.test.js +0 -41
  214. package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
  215. package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
  216. package/orm/tests/build-jsonb.test.d.ts +0 -1
  217. package/orm/tests/build-jsonb.test.js +0 -39
  218. package/orm/tests/data-types.test.d.ts +0 -1
  219. package/orm/tests/data-types.test.js +0 -39
  220. package/orm/tests/database-extension.test.d.ts +0 -1
  221. package/orm/tests/database-extension.test.js +0 -63
  222. package/orm/tests/database-migration.test.d.ts +0 -1
  223. package/orm/tests/database-migration.test.js +0 -83
  224. package/orm/tests/decorators.test.d.ts +0 -1
  225. package/orm/tests/decorators.test.js +0 -77
  226. package/orm/tests/encryption.test.d.ts +0 -1
  227. package/orm/tests/encryption.test.js +0 -31
  228. package/orm/tests/query-complex.test.d.ts +0 -1
  229. package/orm/tests/query-complex.test.js +0 -172
  230. package/orm/tests/query-converter-complex.test.d.ts +0 -1
  231. package/orm/tests/query-converter-complex.test.js +0 -131
  232. package/orm/tests/query-converter.test.d.ts +0 -1
  233. package/orm/tests/query-converter.test.js +0 -123
  234. package/orm/tests/repository-advanced.test.d.ts +0 -1
  235. package/orm/tests/repository-advanced.test.js +0 -189
  236. package/orm/tests/repository-attributes.test.d.ts +0 -1
  237. package/orm/tests/repository-attributes.test.js +0 -83
  238. package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
  239. package/orm/tests/repository-compound-primary-key.test.js +0 -226
  240. package/orm/tests/repository-comprehensive.test.d.ts +0 -1
  241. package/orm/tests/repository-comprehensive.test.js +0 -162
  242. package/orm/tests/repository-coverage.test.d.ts +0 -2
  243. package/orm/tests/repository-coverage.test.js +0 -242
  244. package/orm/tests/repository-cti-complex.test.d.ts +0 -1
  245. package/orm/tests/repository-cti-complex.test.js +0 -151
  246. package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
  247. package/orm/tests/repository-cti-embedded.test.js +0 -178
  248. package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
  249. package/orm/tests/repository-cti-extensive.test.js +0 -279
  250. package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
  251. package/orm/tests/repository-cti-mapping.test.js +0 -108
  252. package/orm/tests/repository-cti-search.test.d.ts +0 -1
  253. package/orm/tests/repository-cti-search.test.js +0 -141
  254. package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
  255. package/orm/tests/repository-cti-soft-delete.test.js +0 -103
  256. package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
  257. package/orm/tests/repository-cti-transactions.test.js +0 -112
  258. package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
  259. package/orm/tests/repository-cti-upsert-many.test.js +0 -115
  260. package/orm/tests/repository-cti.test.d.ts +0 -2
  261. package/orm/tests/repository-cti.test.js +0 -390
  262. package/orm/tests/repository-edge-cases.test.d.ts +0 -1
  263. package/orm/tests/repository-edge-cases.test.js +0 -178
  264. package/orm/tests/repository-expiration.test.d.ts +0 -2
  265. package/orm/tests/repository-expiration.test.js +0 -140
  266. package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
  267. package/orm/tests/repository-extra-coverage.test.js +0 -402
  268. package/orm/tests/repository-mapping.test.d.ts +0 -2
  269. package/orm/tests/repository-mapping.test.js +0 -65
  270. package/orm/tests/repository-regression.test.d.ts +0 -1
  271. package/orm/tests/repository-regression.test.js +0 -288
  272. package/orm/tests/repository-search-coverage.test.d.ts +0 -1
  273. package/orm/tests/repository-search-coverage.test.js +0 -107
  274. package/orm/tests/repository-search.test.d.ts +0 -1
  275. package/orm/tests/repository-search.test.js +0 -105
  276. package/orm/tests/repository-soft-delete.test.d.ts +0 -1
  277. package/orm/tests/repository-soft-delete.test.js +0 -118
  278. package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
  279. package/orm/tests/repository-transactions-nested.test.js +0 -178
  280. package/orm/tests/repository-types.test.d.ts +0 -1
  281. package/orm/tests/repository-types.test.js +0 -184
  282. package/orm/tests/repository-undelete.test.d.ts +0 -2
  283. package/orm/tests/repository-undelete.test.js +0 -201
  284. package/orm/tests/schema-converter.test.d.ts +0 -1
  285. package/orm/tests/schema-converter.test.js +0 -82
  286. package/orm/tests/schema-generation.test.d.ts +0 -2
  287. package/orm/tests/schema-generation.test.js +0 -174
  288. package/orm/tests/sql-helpers.test.d.ts +0 -1
  289. package/orm/tests/sql-helpers.test.js +0 -67
  290. package/orm/tests/transaction-safety.test.d.ts +0 -1
  291. package/orm/tests/transaction-safety.test.js +0 -81
  292. package/orm/tests/transactional.test.d.ts +0 -1
  293. package/orm/tests/transactional.test.js +0 -215
  294. package/orm/tests/utils.test.d.ts +0 -1
  295. package/orm/tests/utils.test.js +0 -70
  296. package/pdf/tests/utils.test.d.ts +0 -1
  297. package/pdf/tests/utils.test.js +0 -187
  298. package/process/tests/spawn.test.d.ts +0 -1
  299. package/process/tests/spawn.test.js +0 -182
  300. package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
  301. package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
  302. package/renderer/tests/renderer.test.d.ts +0 -1
  303. package/renderer/tests/renderer.test.js +0 -88
  304. package/rpc/tests/rpc.integration.test.d.ts +0 -1
  305. package/rpc/tests/rpc.integration.test.js +0 -615
  306. package/signals/implementation/errors.d.ts +0 -2
  307. package/signals/implementation/graph.js +0 -312
  308. package/signals/implementation/writable-signal.d.ts +0 -48
  309. package/signals/implementation/writable-signal.js +0 -32
  310. package/task-queue/tests/coverage-branch.test.d.ts +0 -1
  311. package/task-queue/tests/coverage-branch.test.js +0 -395
  312. package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
  313. package/task-queue/tests/coverage-enhancement.test.js +0 -150
  314. package/task-queue/tests/dag.test.d.ts +0 -1
  315. package/task-queue/tests/dag.test.js +0 -188
  316. package/task-queue/tests/dependencies.test.d.ts +0 -1
  317. package/task-queue/tests/dependencies.test.js +0 -296
  318. package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
  319. package/task-queue/tests/enqueue-batch.test.js +0 -125
  320. package/task-queue/tests/enqueue-item.test.d.ts +0 -1
  321. package/task-queue/tests/enqueue-item.test.js +0 -12
  322. package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
  323. package/task-queue/tests/fan-out-spawning.test.js +0 -94
  324. package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
  325. package/task-queue/tests/idempotent-replacement.test.js +0 -114
  326. package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
  327. package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
  328. package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
  329. package/task-queue/tests/optimization-edge-cases.test.js +0 -124
  330. package/task-queue/tests/queue-generic.test.d.ts +0 -1
  331. package/task-queue/tests/queue-generic.test.js +0 -8
  332. package/task-queue/tests/queue.test.d.ts +0 -1
  333. package/task-queue/tests/queue.test.js +0 -756
  334. package/task-queue/tests/shutdown.test.d.ts +0 -1
  335. package/task-queue/tests/shutdown.test.js +0 -41
  336. package/task-queue/tests/task-context.test.d.ts +0 -1
  337. package/task-queue/tests/task-context.test.js +0 -7
  338. package/task-queue/tests/task-union.test.d.ts +0 -1
  339. package/task-queue/tests/task-union.test.js +0 -18
  340. package/task-queue/tests/transactions.test.d.ts +0 -1
  341. package/task-queue/tests/transactions.test.js +0 -47
  342. package/task-queue/tests/typing.test.d.ts +0 -1
  343. package/task-queue/tests/typing.test.js +0 -9
  344. package/task-queue/tests/worker.test.d.ts +0 -1
  345. package/task-queue/tests/worker.test.js +0 -258
  346. package/task-queue/tests/zombie-parent.test.d.ts +0 -1
  347. package/task-queue/tests/zombie-parent.test.js +0 -45
  348. package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
  349. package/task-queue/tests/zombie-recovery.test.js +0 -51
  350. package/utils/tests/backoff.test.d.ts +0 -1
  351. package/utils/tests/backoff.test.js +0 -41
  352. package/utils/tests/retry-with-backoff.test.d.ts +0 -1
  353. package/utils/tests/retry-with-backoff.test.js +0 -49
@@ -1,288 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { sql } from 'drizzle-orm';
11
- import { beforeAll, describe, expect, test } from 'vitest';
12
- import { defineEnum } from '../../enumeration/index.js';
13
- import { NotFoundError } from '../../errors/not-found.error.js';
14
- import { Array, Enumeration, Integer, string, StringProperty } from '../../schema/index.js';
15
- import { setupIntegrationTest } from '../../testing/index.js';
16
- import { Column, EmbeddedProperty, EncryptedProperty, Reference, Table } from '../decorators.js';
17
- import { Entity } from '../entity.js';
18
- import { JsonProperty, NumericDateProperty } from '../schemas/index.js';
19
- import { getRepository } from '../server/index.js';
20
- describe('ORM Repository Regression (Integration)', () => {
21
- let injector;
22
- let db;
23
- let standardRepository;
24
- let postRepository;
25
- const schema = 'test_orm_regression';
26
- const UserRole = defineEnum('UserRole', {
27
- Admin: 'admin',
28
- User: 'user',
29
- });
30
- class Address {
31
- street;
32
- number;
33
- }
34
- __decorate([
35
- StringProperty(),
36
- __metadata("design:type", String)
37
- ], Address.prototype, "street", void 0);
38
- __decorate([
39
- Integer(),
40
- __metadata("design:type", Number)
41
- ], Address.prototype, "number", void 0);
42
- let StandardEntity = class StandardEntity extends Entity {
43
- name;
44
- address;
45
- secret;
46
- role;
47
- data;
48
- tags;
49
- birthday;
50
- };
51
- __decorate([
52
- StringProperty(),
53
- Column({ name: 'display_name' }),
54
- __metadata("design:type", String)
55
- ], StandardEntity.prototype, "name", void 0);
56
- __decorate([
57
- EmbeddedProperty(Address),
58
- __metadata("design:type", Address)
59
- ], StandardEntity.prototype, "address", void 0);
60
- __decorate([
61
- StringProperty(),
62
- EncryptedProperty(),
63
- __metadata("design:type", String)
64
- ], StandardEntity.prototype, "secret", void 0);
65
- __decorate([
66
- Enumeration(UserRole),
67
- __metadata("design:type", String)
68
- ], StandardEntity.prototype, "role", void 0);
69
- __decorate([
70
- JsonProperty(),
71
- __metadata("design:type", Object)
72
- ], StandardEntity.prototype, "data", void 0);
73
- __decorate([
74
- Array(string()),
75
- __metadata("design:type", Array)
76
- ], StandardEntity.prototype, "tags", void 0);
77
- __decorate([
78
- NumericDateProperty(),
79
- Column({ name: 'dob' }),
80
- __metadata("design:type", Number)
81
- ], StandardEntity.prototype, "birthday", void 0);
82
- StandardEntity = __decorate([
83
- Table('standard_entities', { schema })
84
- ], StandardEntity);
85
- let Post = class Post extends Entity {
86
- title;
87
- authorId;
88
- };
89
- __decorate([
90
- StringProperty(),
91
- __metadata("design:type", String)
92
- ], Post.prototype, "title", void 0);
93
- __decorate([
94
- StringProperty(),
95
- Column({ name: 'author_id' }),
96
- Reference(() => StandardEntity),
97
- __metadata("design:type", String)
98
- ], Post.prototype, "authorId", void 0);
99
- Post = __decorate([
100
- Table('posts', { schema })
101
- ], Post);
102
- beforeAll(async () => {
103
- ({ injector, database: db } = await setupIntegrationTest({
104
- orm: { schema },
105
- }));
106
- standardRepository = injector.resolve(getRepository(StandardEntity));
107
- postRepository = injector.resolve(getRepository(Post));
108
- await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
109
- await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('posts')} CASCADE`);
110
- await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
111
- await db.execute(sql `DROP TYPE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('user_role')} CASCADE`);
112
- await db.execute(sql `CREATE TYPE ${sql.identifier(schema)}.${sql.identifier('user_role')} AS ENUM ('admin', 'user')`);
113
- await db.execute(sql `
114
- CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} (
115
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
116
- display_name TEXT NOT NULL,
117
- address_street TEXT NOT NULL,
118
- address_number INTEGER NOT NULL,
119
- secret BYTEA NOT NULL,
120
- role ${sql.identifier(schema)}.${sql.identifier('user_role')} NOT NULL,
121
- data JSONB NOT NULL,
122
- tags TEXT[] NOT NULL,
123
- dob DATE NOT NULL,
124
- revision INTEGER NOT NULL,
125
- revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
126
- create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
127
- delete_timestamp TIMESTAMP WITH TIME ZONE,
128
- attributes JSONB NOT NULL DEFAULT '{}'
129
- )
130
- `);
131
- await db.execute(sql `
132
- CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('posts')} (
133
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
134
- title TEXT NOT NULL,
135
- author_id UUID NOT NULL REFERENCES ${sql.identifier(schema)}.${sql.identifier('standard_entities')} (id),
136
- revision INTEGER NOT NULL,
137
- revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
138
- create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
139
- delete_timestamp TIMESTAMP WITH TIME ZONE,
140
- attributes JSONB NOT NULL DEFAULT '{}'
141
- )
142
- `);
143
- });
144
- test('should perform basic CRUD on standard entity', async () => {
145
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
146
- const entity = new StandardEntity();
147
- entity.name = 'Test';
148
- entity.address = { street: 'Main St', number: 123 };
149
- entity.secret = 'my-secret-password';
150
- entity.role = UserRole.User;
151
- entity.data = { foo: 'bar' };
152
- entity.tags = ['a', 'b'];
153
- entity.birthday = 19716; // 2023-12-25
154
- const inserted = await standardRepository.insert(entity);
155
- expect(inserted.id).toBeDefined();
156
- expect(inserted.name).toBe('Test');
157
- expect(inserted.address.street).toBe('Main St');
158
- expect(inserted.secret).toBe('my-secret-password');
159
- expect(inserted.role).toBe(UserRole.User);
160
- expect(inserted.data).toEqual({ foo: 'bar' });
161
- expect(inserted.tags).toEqual(['a', 'b']);
162
- expect(inserted.birthday).toBe(19716);
163
- // Verify DB encrypted state
164
- const { rows: [row] } = await db.execute(sql `SELECT secret, dob FROM ${sql.identifier(schema)}.${sql.identifier('standard_entities')} WHERE id = ${inserted.id}`);
165
- expect(row['secret']).toBeInstanceOf(Uint8Array);
166
- expect(row['secret']).not.toEqual(new TextEncoder().encode('my-secret-password'));
167
- expect(row['dob']).toBe('2023-12-25');
168
- // Update
169
- await standardRepository.update(inserted.id, { name: 'Updated' });
170
- const updated = await standardRepository.load(inserted.id);
171
- expect(updated.name).toBe('Updated');
172
- expect(updated.secret).toBe('my-secret-password'); // Still readable
173
- // Soft Delete
174
- await standardRepository.delete(inserted.id);
175
- const deleted = await standardRepository.tryLoad(inserted.id);
176
- expect(deleted).toBeUndefined();
177
- const { rows: [deletedRow] } = await db.execute(sql `SELECT delete_timestamp FROM ${sql.identifier(schema)}.${sql.identifier('standard_entities')} WHERE id = ${inserted.id}`);
178
- expect(deletedRow['delete_timestamp']).not.toBeNull();
179
- });
180
- test('should support Reference decorator', async () => {
181
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
182
- const author = Object.assign(new StandardEntity(), { name: 'Author', address: { street: 'A', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 });
183
- const insertedAuthor = await standardRepository.insert(author);
184
- const post = Object.assign(new Post(), { title: 'Hello World', authorId: insertedAuthor.id });
185
- const insertedPost = await postRepository.insert(post);
186
- expect(insertedPost.authorId).toBe(insertedAuthor.id);
187
- const loadedPost = await postRepository.load(insertedPost.id);
188
- expect(loadedPost.authorId).toBe(insertedAuthor.id);
189
- });
190
- test('should perform insertMany and loadMany', async () => {
191
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
192
- const entities = [
193
- Object.assign(new StandardEntity(), { name: 'E1', address: { street: 'S1', number: 1 }, secret: 's1', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
194
- Object.assign(new StandardEntity(), { name: 'E2', address: { street: 'S2', number: 2 }, secret: 's2', role: UserRole.Admin, data: {}, tags: [], birthday: 0 }),
195
- ];
196
- const inserted = await standardRepository.insertMany(entities);
197
- expect(inserted).toHaveLength(2);
198
- const loaded = await standardRepository.loadMany(inserted.map((e) => e.id));
199
- expect(loaded).toHaveLength(2);
200
- expect(loaded.map((e) => e.name).sort()).toEqual(['E1', 'E2']);
201
- });
202
- test('should support upsert', async () => {
203
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
204
- const entity = Object.assign(new StandardEntity(), { name: 'Original', address: { street: 'S', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 });
205
- const inserted = await standardRepository.insert(entity);
206
- // Upsert: update existing
207
- const updateEntity = Object.assign(new StandardEntity(), { id: inserted.id, name: 'Upserted', address: { street: 'S', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 });
208
- const upserted = await standardRepository.upsert('id', updateEntity);
209
- expect(upserted.id).toBe(inserted.id);
210
- expect(upserted.name).toBe('Upserted');
211
- // Verify DB
212
- const loaded = await standardRepository.load(inserted.id);
213
- expect(loaded.name).toBe('Upserted');
214
- });
215
- test('should support complex queries with $or and $and', async () => {
216
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
217
- await standardRepository.insertMany([
218
- Object.assign(new StandardEntity(), { name: 'A', address: { street: 'S1', number: 10 }, secret: 's', role: UserRole.Admin, data: {}, tags: [], birthday: 0 }),
219
- Object.assign(new StandardEntity(), { name: 'B', address: { street: 'S2', number: 20 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
220
- Object.assign(new StandardEntity(), { name: 'C', address: { street: 'S3', number: 30 }, secret: 's', role: UserRole.Admin, data: {}, tags: [], birthday: 0 }),
221
- ]);
222
- const results = await standardRepository.loadManyByQuery({
223
- $or: [
224
- { name: 'B' },
225
- { $and: [{ role: UserRole.Admin }, { 'address.number': { $gt: 25 } }] }
226
- ]
227
- });
228
- expect(results).toHaveLength(2);
229
- expect(results.map((r) => r.name).sort()).toEqual(['B', 'C']);
230
- });
231
- test('should support hasAll', async () => {
232
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
233
- const inserted = await standardRepository.insertMany([
234
- Object.assign(new StandardEntity(), { name: 'E1', address: { street: 'S1', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
235
- Object.assign(new StandardEntity(), { name: 'E2', address: { street: 'S2', number: 2 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
236
- ]);
237
- expect(await standardRepository.hasAll(inserted.map((e) => e.id))).toBe(true);
238
- expect(await standardRepository.hasAll([...inserted.map((e) => e.id), '00000000-0000-0000-0000-000000000000'])).toBe(false);
239
- });
240
- test('should throw NotFoundError on missing load', async () => {
241
- await expect(standardRepository.load('00000000-0000-0000-0000-000000000000')).rejects.toThrow(NotFoundError);
242
- });
243
- test('should support upsertMany', async () => {
244
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
245
- const e1 = await standardRepository.insert(Object.assign(new StandardEntity(), { name: 'E1', address: { street: 'S1', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }));
246
- const upsertData = [
247
- Object.assign(new StandardEntity(), { id: e1.id, name: 'E1-Updated', address: { street: 'S1', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
248
- Object.assign(new StandardEntity(), { name: 'E2', address: { street: 'S2', number: 2 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
249
- ];
250
- await standardRepository.upsertMany('id', upsertData);
251
- const all = await standardRepository.loadAll();
252
- expect(all).toHaveLength(2);
253
- expect(all.find((e) => e.id === e1.id).name).toBe('E1-Updated');
254
- expect(all.find((e) => e.name === 'E2')).toBeDefined();
255
- });
256
- test('should support deleteManyByQuery', async () => {
257
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
258
- await standardRepository.insertMany([
259
- Object.assign(new StandardEntity(), { name: 'A', address: { street: 'S', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
260
- Object.assign(new StandardEntity(), { name: 'A', address: { street: 'S', number: 2 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
261
- Object.assign(new StandardEntity(), { name: 'B', address: { street: 'S', number: 3 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
262
- ]);
263
- await standardRepository.deleteManyByQuery({ name: 'A' });
264
- const remaining = await standardRepository.loadAll();
265
- expect(remaining).toHaveLength(1);
266
- expect(remaining[0].name).toBe('B');
267
- });
268
- test('should support tryInsert', async () => {
269
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
270
- const entity = Object.assign(new StandardEntity(), { name: 'E1', address: { street: 'S', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 });
271
- const inserted = await standardRepository.tryInsert(entity);
272
- expect(inserted).toBeDefined();
273
- // Conflict
274
- const conflict = await standardRepository.tryInsert(Object.assign(new StandardEntity(), { id: inserted.id, name: 'Conflict', address: { street: 'S', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }));
275
- expect(conflict).toBeUndefined();
276
- });
277
- test('should support insertManyIfNotExists', async () => {
278
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('standard_entities')} CASCADE`);
279
- const e1 = await standardRepository.insert(Object.assign(new StandardEntity(), { name: 'E1', address: { street: 'S1', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }));
280
- const data = [
281
- Object.assign(new StandardEntity(), { id: e1.id, name: 'E1-Conflict', address: { street: 'S1', number: 1 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
282
- Object.assign(new StandardEntity(), { name: 'E2', address: { street: 'S2', number: 2 }, secret: 's', role: UserRole.User, data: {}, tags: [], birthday: 0 }),
283
- ];
284
- const results = await standardRepository.insertManyIfNotExists('id', data);
285
- expect(results).toHaveLength(1);
286
- expect(results[0].name).toBe('E2');
287
- });
288
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,107 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { sql } from 'drizzle-orm';
11
- import { describe, expect } from 'vitest';
12
- import { StringProperty } from '../../schema/index.js';
13
- import { getIntegrationTest } from '../../testing/index.js';
14
- import { Table } from '../decorators.js';
15
- import { Entity } from '../entity.js';
16
- import { injectRepository } from '../server/repository.js';
17
- const schema = 'test_orm_search_coverage';
18
- const test = getIntegrationTest({ orm: { schema } });
19
- describe('ORM Repository Search Coverage', () => {
20
- let Document = class Document extends Entity {
21
- content;
22
- };
23
- __decorate([
24
- StringProperty(),
25
- __metadata("design:type", String)
26
- ], Document.prototype, "content", void 0);
27
- Document = __decorate([
28
- Table('docs', { schema })
29
- ], Document);
30
- test.beforeEach(async ({ database: db }) => {
31
- await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
32
- await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('docs')} CASCADE`);
33
- await db.execute(sql `CREATE EXTENSION IF NOT EXISTS pg_trgm`); // Enable trigram
34
- await db.execute(sql `
35
- CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('docs')} (
36
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
37
- content TEXT NOT NULL,
38
- revision INTEGER NOT NULL,
39
- revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
40
- create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
41
- delete_timestamp TIMESTAMP WITH TIME ZONE,
42
- attributes JSONB NOT NULL DEFAULT '{}'
43
- )
44
- `);
45
- });
46
- test('tsvector search with order function accessing score', async () => {
47
- const repository = injectRepository(Document);
48
- await repository.insert(Object.assign(new Document(), { content: 'Apple Banana' }));
49
- const results = await repository.search({
50
- query: { $tsvector: { fields: ['content'], query: 'Apple' } },
51
- order: (cols) => [[cols.score, 'desc']],
52
- });
53
- expect(results).toHaveLength(1);
54
- });
55
- test('trigram search basic', async () => {
56
- const repository = injectRepository(Document);
57
- await repository.insert(Object.assign(new Document(), { content: 'Trigram Test' }));
58
- const results = await repository.search({
59
- query: { $trigram: { fields: ['content'], query: 'Trigram' } },
60
- });
61
- expect(results).toHaveLength(1);
62
- });
63
- test('trigram search with threshold (phrase)', async ({ database: db }) => {
64
- const repository = injectRepository(Document);
65
- await repository.insert(Object.assign(new Document(), { content: 'Phrase Match' }));
66
- // Set threshold to a value that allows matching (default is 0.3)
67
- await db.execute(sql `SET pg_trgm.similarity_threshold = 0.1`);
68
- const results = await repository.search({
69
- query: { $trigram: { fields: ['content'], query: 'Phrase', type: 'phrase', threshold: 0.1 } },
70
- });
71
- expect(results).toHaveLength(1);
72
- });
73
- test('trigram search with threshold (word)', async ({ database: db }) => {
74
- const repository = injectRepository(Document);
75
- await repository.insert(Object.assign(new Document(), { content: 'Word Match' }));
76
- await db.execute(sql `SET pg_trgm.word_similarity_threshold = 0.1`);
77
- const results = await repository.search({
78
- query: { $trigram: { fields: ['content'], query: 'Word', type: 'word', threshold: 0.1 } },
79
- });
80
- expect(results).toHaveLength(1);
81
- });
82
- test('trigram search with threshold (strict-word)', async ({ database: db }) => {
83
- const repository = injectRepository(Document);
84
- await repository.insert(Object.assign(new Document(), { content: 'Strict Match' }));
85
- await db.execute(sql `SET pg_trgm.strict_word_similarity_threshold = 0.1`);
86
- const results = await repository.search({
87
- query: { $trigram: { fields: ['content'], query: 'Strict', type: 'strict-word', threshold: 0.1 } },
88
- });
89
- expect(results).toHaveLength(1);
90
- });
91
- test('trigram search with order function', async () => {
92
- const repository = injectRepository(Document);
93
- const results = await repository.search({
94
- query: { $trigram: { fields: ['content'], query: 'Order' } },
95
- order: ({ score }) => [[score, 'desc']],
96
- });
97
- // Even if no results, code path is exercised?
98
- // No, order function is called only if query is executed.
99
- // Insert something first
100
- await repository.insert(Object.assign(new Document(), { content: 'Order Test' }));
101
- const results2 = await repository.search({
102
- query: { $trigram: { fields: ['content'], query: 'Order' } },
103
- order: ({ score }) => [[score, 'desc']],
104
- });
105
- expect(results2).toHaveLength(1);
106
- });
107
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,105 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { sql } from 'drizzle-orm';
11
- import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
12
- import { StringProperty } from '../../schema/index.js';
13
- import { dropTables, setupIntegrationTest, truncateTables } from '../../testing/index.js';
14
- import { isArray } from '../../utils/type-guards.js';
15
- import { Table } from '../decorators.js';
16
- import { Entity } from '../entity.js';
17
- import { getRepository } from '../server/index.js';
18
- describe('ORM Repository Search', () => {
19
- let injector;
20
- let database;
21
- let repository;
22
- const schema = 'test_orm_search';
23
- let SearchEntity = class SearchEntity extends Entity {
24
- title;
25
- content;
26
- };
27
- __decorate([
28
- StringProperty(),
29
- __metadata("design:type", String)
30
- ], SearchEntity.prototype, "title", void 0);
31
- __decorate([
32
- StringProperty(),
33
- __metadata("design:type", String)
34
- ], SearchEntity.prototype, "content", void 0);
35
- SearchEntity = __decorate([
36
- Table('search_entities', { schema })
37
- ], SearchEntity);
38
- beforeAll(async () => {
39
- ({ injector, database } = await setupIntegrationTest({ orm: { schema } }));
40
- repository = injector.resolve(getRepository(SearchEntity));
41
- await dropTables(database, schema, ['search_entities']);
42
- await database.execute(sql `
43
- CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('search_entities')} (
44
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
45
- title TEXT NOT NULL,
46
- content TEXT NOT NULL,
47
- revision INTEGER NOT NULL,
48
- revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
49
- create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
50
- delete_timestamp TIMESTAMP WITH TIME ZONE,
51
- attributes JSONB NOT NULL DEFAULT '{}'
52
- )
53
- `);
54
- });
55
- beforeEach(async () => {
56
- await truncateTables(database, schema, ['search_entities']);
57
- });
58
- test('should support search with score transformer', async () => {
59
- await repository.insert(Object.assign(new SearchEntity(), { title: 'Hello World', content: 'Some content here' }));
60
- const results = await repository.search({
61
- query: { $tsvector: { fields: ['title'], query: 'hello' } },
62
- score: (score) => sql `(${score}) * 100`,
63
- });
64
- expect(results).toHaveLength(1);
65
- expect(results[0].score).toBeGreaterThan(1); // normalized score is small, * 100 should be > 1
66
- });
67
- test('should support search with highlight (column names)', async () => {
68
- await repository.insert(Object.assign(new SearchEntity(), { title: 'Highlander', content: 'There can be only one' }));
69
- const results = await repository.search({
70
- query: { $tsvector: { fields: ['title', 'content'], query: 'Highlander' } },
71
- highlight: { source: 'title' },
72
- });
73
- expect(results).toHaveLength(1);
74
- expect(results[0].highlight).toContain('<b>Highlander</b>');
75
- });
76
- test('should support search with highlight (raw SQL)', async () => {
77
- await repository.insert(Object.assign(new SearchEntity(), { title: 'SQL Master', content: 'Database wizard' }));
78
- const results = await repository.search({
79
- query: { $tsvector: { fields: ['title', 'content'], query: 'Master' } },
80
- highlight: { source: sql `title || ' ' || content` },
81
- });
82
- expect(results).toHaveLength(1);
83
- expect(results[0].highlight).toContain('<b>Master</b>');
84
- });
85
- test('should support ParadeDB search with highlightPositions', async () => {
86
- // This test requires pg_search extension to be installed.
87
- try {
88
- await database.execute(sql `CREATE EXTENSION IF NOT EXISTS pg_search`);
89
- await database.execute(sql `CREATE INDEX idx_search_parade ON ${sql.identifier(schema)}.${sql.identifier('search_entities')} USING bm25 (id, title, content) WITH (key_field='id')`);
90
- }
91
- catch (e) {
92
- console.warn('ParadeDB (pg_search) not available or index creation failed, skipping ParadeDB test.', e);
93
- return;
94
- }
95
- await repository.insert(Object.assign(new SearchEntity(), { title: 'Parade', content: 'ParadeDB is fast' }));
96
- const results = await repository.search({
97
- query: { $parade: { fields: ['title'], query: 'Parade' } },
98
- highlight: { source: 'title', includePositions: true },
99
- });
100
- expect(results).toHaveLength(1);
101
- expect(results[0].highlight).toBeDefined();
102
- expect(results[0].highlightPositions).toBeDefined();
103
- expect(isArray(results[0].highlightPositions)).toBe(true);
104
- });
105
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,118 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- import { sql } from 'drizzle-orm';
11
- import { beforeAll, describe, expect, test } from 'vitest';
12
- import { StringProperty } from '../../schema/index.js';
13
- import { setupIntegrationTest } from '../../testing/index.js';
14
- import { Table } from '../decorators.js';
15
- import { Entity } from '../entity.js';
16
- import { getRepository } from '../server/index.js';
17
- describe('ORM Repository Soft Delete (Integration)', () => {
18
- let injector;
19
- let db;
20
- let repository;
21
- const schema = 'test_orm_soft_delete';
22
- let SoftDeleteEntity = class SoftDeleteEntity extends Entity {
23
- name;
24
- };
25
- __decorate([
26
- StringProperty(),
27
- __metadata("design:type", String)
28
- ], SoftDeleteEntity.prototype, "name", void 0);
29
- SoftDeleteEntity = __decorate([
30
- Table('soft_delete_entities', { schema })
31
- ], SoftDeleteEntity);
32
- beforeAll(async () => {
33
- ({ injector, database: db } = await setupIntegrationTest({
34
- orm: { schema },
35
- }));
36
- repository = injector.resolve(getRepository(SoftDeleteEntity));
37
- await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
38
- await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
39
- await db.execute(sql `
40
- CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} (
41
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
42
- name TEXT NOT NULL,
43
- revision INTEGER NOT NULL,
44
- revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
45
- create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
46
- delete_timestamp TIMESTAMP WITH TIME ZONE,
47
- attributes JSONB NOT NULL DEFAULT '{}'
48
- )
49
- `);
50
- });
51
- test('should soft delete an entity by ID', async () => {
52
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
53
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
54
- const deleted = await repository.delete(e1.id);
55
- expect(deleted.id).toBe(e1.id);
56
- expect(deleted.metadata.deleteTimestamp).toBeDefined();
57
- expect(await repository.has(e1.id)).toBe(false);
58
- expect(await repository.tryLoad(e1.id)).toBeUndefined();
59
- expect(await repository.count()).toBe(0);
60
- const allWithDeleted = await repository.loadAll({ withDeleted: true });
61
- expect(allWithDeleted).toHaveLength(1);
62
- expect(allWithDeleted[0].id).toBe(e1.id);
63
- });
64
- test('should soft delete multiple entities by IDs', async () => {
65
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
66
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
67
- const e2 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E2' }));
68
- const deleted = await repository.deleteMany([e1.id, e2.id]);
69
- expect(deleted).toHaveLength(2);
70
- expect(await repository.count()).toBe(0);
71
- expect(await repository.countByQuery({}, { withDeleted: true })).toBe(2);
72
- });
73
- test('should soft delete entities by query', async () => {
74
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
75
- await repository.insertMany([
76
- Object.assign(new SoftDeleteEntity(), { name: 'A' }),
77
- Object.assign(new SoftDeleteEntity(), { name: 'B' }),
78
- Object.assign(new SoftDeleteEntity(), { name: 'A' }),
79
- ]);
80
- const deleted = await repository.deleteManyByQuery({ name: 'A' });
81
- expect(deleted).toHaveLength(2);
82
- expect(await repository.count()).toBe(1);
83
- expect(await repository.countByQuery({}, { withDeleted: true })).toBe(3);
84
- });
85
- test('should not update soft-deleted entities by default', async () => {
86
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
87
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
88
- await repository.delete(e1.id);
89
- const updated = await repository.tryUpdate(e1.id, { name: 'Updated' });
90
- expect(updated).toBeUndefined();
91
- const loaded = await repository.tryLoad(e1.id, { withDeleted: true });
92
- expect(loaded.name).toBe('E1');
93
- });
94
- test('should support hard delete on soft-deleted entities', async () => {
95
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
96
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
97
- await repository.delete(e1.id);
98
- const hardDeleted = await repository.hardDelete(e1.id);
99
- expect(hardDeleted.id).toBe(e1.id);
100
- expect(await repository.countByQuery({}, { withDeleted: true })).toBe(0);
101
- });
102
- test('should ignore already soft-deleted entities when deleting again', async () => {
103
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
104
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
105
- await repository.delete(e1.id);
106
- const secondDelete = await repository.tryDelete(e1.id);
107
- expect(secondDelete).toBeUndefined();
108
- });
109
- test('should hard delete multiple entities by query (including soft-deleted)', async () => {
110
- await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
111
- const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
112
- const e2 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E2' }));
113
- await repository.delete(e1.id); // Soft delete E1
114
- const hardDeleted = await repository.hardDeleteManyByQuery({});
115
- expect(hardDeleted).toHaveLength(2); // Should hard delete both
116
- expect(await repository.countByQuery({}, { withDeleted: true })).toBe(0);
117
- });
118
- });
@@ -1 +0,0 @@
1
- export {};