@tstdl/base 0.93.87 → 0.93.90

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 (314) hide show
  1. package/ai/genkit/helpers.d.ts +3 -1
  2. package/ai/genkit/helpers.js +3 -3
  3. package/api/server/gateway.d.ts +3 -0
  4. package/api/server/gateway.js +15 -4
  5. package/api/server/middlewares/catch-error.middleware.js +2 -4
  6. package/api/server/middlewares/cors.middleware.js +2 -3
  7. package/api/server/middlewares/csrf.middleware.d.ts +41 -0
  8. package/api/server/middlewares/csrf.middleware.js +108 -0
  9. package/api/server/middlewares/index.d.ts +1 -0
  10. package/api/server/middlewares/index.js +1 -0
  11. package/api/server/module.d.ts +8 -2
  12. package/api/server/module.js +14 -8
  13. package/api/server/tests/csrf.middleware.test.js +91 -0
  14. package/audit/drizzle/{0000_bored_stick.sql → 0000_lumpy_thunderball.sql} +3 -3
  15. package/audit/drizzle/meta/0000_snapshot.json +4 -4
  16. package/audit/drizzle/meta/_journal.json +2 -9
  17. package/audit/module.d.ts +4 -1
  18. package/audit/module.js +3 -2
  19. package/audit/schemas.d.ts +1 -1
  20. package/audit/types.d.ts +1 -1
  21. package/audit/types.js +1 -1
  22. package/authentication/client/authentication.service.d.ts +14 -1
  23. package/authentication/client/authentication.service.js +82 -23
  24. package/authentication/client/http-client.middleware.d.ts +6 -0
  25. package/authentication/client/http-client.middleware.js +36 -0
  26. package/authentication/client/module.js +8 -2
  27. package/authentication/models/service-account.model.d.ts +2 -2
  28. package/authentication/models/service-account.model.js +10 -5
  29. package/authentication/models/subject.model.d.ts +20 -5
  30. package/authentication/models/subject.model.js +34 -29
  31. package/authentication/models/system-account.model.d.ts +3 -2
  32. package/authentication/models/system-account.model.js +11 -5
  33. package/authentication/models/user.model.d.ts +2 -11
  34. package/authentication/models/user.model.js +5 -16
  35. package/authentication/server/authentication-api-request-token.provider.d.ts +0 -2
  36. package/authentication/server/authentication-api-request-token.provider.js +3 -11
  37. package/authentication/server/authentication.api-controller.d.ts +1 -2
  38. package/authentication/server/authentication.api-controller.js +8 -9
  39. package/authentication/server/authentication.audit.d.ts +3 -2
  40. package/authentication/server/authentication.service.d.ts +27 -1
  41. package/authentication/server/authentication.service.js +67 -18
  42. package/authentication/server/drizzle/{0000_normal_paper_doll.sql → 0000_soft_tag.sql} +25 -32
  43. package/authentication/server/drizzle/meta/0000_snapshot.json +180 -205
  44. package/authentication/server/drizzle/meta/_journal.json +2 -2
  45. package/authentication/server/helper.js +9 -2
  46. package/authentication/server/module.d.ts +4 -1
  47. package/authentication/server/module.js +9 -5
  48. package/authentication/server/schemas.d.ts +2 -1
  49. package/authentication/server/schemas.js +2 -2
  50. package/authentication/server/subject.service.d.ts +17 -11
  51. package/authentication/server/subject.service.js +86 -84
  52. package/authentication/tests/authentication-ancillary.service.test.d.ts +1 -0
  53. package/authentication/tests/authentication-ancillary.service.test.js +13 -0
  54. package/authentication/tests/authentication-secret-requirements.validator.test.d.ts +1 -0
  55. package/authentication/tests/authentication-secret-requirements.validator.test.js +29 -0
  56. package/authentication/tests/authentication.api-controller.test.d.ts +1 -0
  57. package/authentication/tests/authentication.api-controller.test.js +88 -0
  58. package/authentication/tests/authentication.api-request-token.provider.test.d.ts +1 -0
  59. package/authentication/tests/authentication.api-request-token.provider.test.js +48 -0
  60. package/authentication/tests/authentication.client-middleware.test.d.ts +1 -0
  61. package/authentication/tests/authentication.client-middleware.test.js +23 -0
  62. package/authentication/tests/authentication.client-service.test.d.ts +1 -0
  63. package/authentication/tests/authentication.client-service.test.js +70 -0
  64. package/authentication/tests/authentication.service.test.d.ts +1 -0
  65. package/authentication/tests/authentication.service.test.js +186 -0
  66. package/authentication/tests/authentication.test-ancillary-service.d.ts +9 -0
  67. package/authentication/tests/authentication.test-ancillary-service.js +27 -0
  68. package/authentication/tests/helper.test.d.ts +1 -0
  69. package/authentication/tests/helper.test.js +107 -0
  70. package/authentication/tests/secret-requirements.error.test.d.ts +1 -0
  71. package/authentication/tests/secret-requirements.error.test.js +14 -0
  72. package/authentication/tests/subject.service.test.d.ts +1 -0
  73. package/authentication/tests/subject.service.test.js +140 -0
  74. package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +1 -1
  75. package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
  76. package/circuit-breaker/postgres/module.d.ts +7 -1
  77. package/circuit-breaker/postgres/module.js +8 -6
  78. package/circuit-breaker/tests/circuit-breaker.test.js +2 -22
  79. package/document-management/api/document-management.api.js +2 -6
  80. package/document-management/server/services/document-validation.service.js +6 -5
  81. package/document-management/server/services/document-workflow.service.js +5 -5
  82. package/document-management/service-models/document-folders.view-model.d.ts +5 -2
  83. package/document-management/service-models/document-folders.view-model.js +42 -9
  84. package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
  85. package/examples/document-management/main.js +4 -4
  86. package/http/client/adapters/undici.adapter.d.ts +7 -5
  87. package/http/client/adapters/undici.adapter.js +13 -10
  88. package/http/client/module.d.ts +3 -1
  89. package/http/client/module.js +8 -9
  90. package/http/server/http-server.d.ts +2 -0
  91. package/http/server/node/module.d.ts +6 -2
  92. package/http/server/node/module.js +6 -4
  93. package/http/server/node/node-http-server.d.ts +2 -0
  94. package/http/server/node/node-http-server.js +7 -0
  95. package/http/types.d.ts +1 -1
  96. package/key-value-store/postgres/module.d.ts +7 -1
  97. package/key-value-store/postgres/module.js +7 -3
  98. package/lock/postgres/lock.js +0 -1
  99. package/lock/postgres/module.d.ts +7 -1
  100. package/lock/postgres/module.js +9 -5
  101. package/logger/formatter.d.ts +2 -0
  102. package/logger/formatters/json.js +2 -2
  103. package/logger/formatters/pretty-print.js +8 -10
  104. package/logger/logger.d.ts +1 -1
  105. package/logger/logger.js +15 -12
  106. package/message-bus/local/module.d.ts +5 -2
  107. package/message-bus/local/module.js +5 -4
  108. package/module/module.d.ts +2 -1
  109. package/module/module.js +3 -0
  110. package/module/modules/web-server.module.d.ts +11 -6
  111. package/module/modules/web-server.module.js +15 -10
  112. package/orm/decorators.d.ts +24 -1
  113. package/orm/decorators.js +40 -4
  114. package/orm/query/base.d.ts +17 -17
  115. package/orm/query/base.js +1 -1
  116. package/orm/repository.types.d.ts +45 -1
  117. package/orm/schemas/tsvector.js +1 -1
  118. package/orm/server/drizzle/schema-converter.d.ts +3 -1
  119. package/orm/server/drizzle/schema-converter.js +120 -14
  120. package/orm/server/index.d.ts +1 -0
  121. package/orm/server/index.js +1 -0
  122. package/orm/server/module.d.ts +4 -2
  123. package/orm/server/module.js +6 -5
  124. package/orm/server/query-converter.d.ts +6 -3
  125. package/orm/server/query-converter.js +32 -20
  126. package/orm/server/repository-config.d.ts +8 -0
  127. package/orm/server/repository-config.js +8 -0
  128. package/orm/server/repository.d.ts +117 -43
  129. package/orm/server/repository.js +757 -253
  130. package/orm/server/transaction.d.ts +4 -2
  131. package/orm/server/transaction.js +14 -5
  132. package/orm/server/transactional.d.ts +6 -2
  133. package/orm/server/transactional.js +39 -9
  134. package/orm/server/types.d.ts +2 -0
  135. package/orm/sqls/case-when.d.ts +3 -3
  136. package/orm/sqls/case-when.js +2 -2
  137. package/orm/sqls/sqls.d.ts +31 -5
  138. package/orm/sqls/sqls.js +69 -6
  139. package/orm/tests/data-types.test.d.ts +1 -0
  140. package/orm/tests/data-types.test.js +39 -0
  141. package/orm/tests/decorators.test.d.ts +1 -0
  142. package/orm/tests/decorators.test.js +77 -0
  143. package/orm/tests/encryption.test.d.ts +1 -0
  144. package/orm/tests/encryption.test.js +34 -0
  145. package/orm/tests/query-complex.test.d.ts +1 -0
  146. package/orm/tests/query-complex.test.js +203 -0
  147. package/orm/tests/query-converter-complex.test.d.ts +1 -0
  148. package/orm/tests/query-converter-complex.test.js +126 -0
  149. package/orm/tests/query-converter.test.d.ts +1 -0
  150. package/orm/tests/query-converter.test.js +123 -0
  151. package/orm/tests/repository-advanced.test.d.ts +1 -0
  152. package/orm/tests/repository-advanced.test.js +232 -0
  153. package/orm/tests/repository-attributes.test.d.ts +1 -0
  154. package/orm/tests/repository-attributes.test.js +99 -0
  155. package/orm/tests/repository-comprehensive.test.d.ts +1 -0
  156. package/orm/tests/repository-comprehensive.test.js +187 -0
  157. package/orm/tests/repository-coverage.test.d.ts +1 -0
  158. package/orm/tests/repository-coverage.test.js +303 -0
  159. package/orm/tests/repository-cti-complex.test.d.ts +1 -0
  160. package/orm/tests/repository-cti-complex.test.js +170 -0
  161. package/orm/tests/repository-cti-embedded.test.d.ts +1 -0
  162. package/orm/tests/repository-cti-embedded.test.js +188 -0
  163. package/orm/tests/repository-cti-extensive.test.d.ts +1 -0
  164. package/orm/tests/repository-cti-extensive.test.js +308 -0
  165. package/orm/tests/repository-cti-mapping.test.d.ts +1 -0
  166. package/orm/tests/repository-cti-mapping.test.js +121 -0
  167. package/orm/tests/repository-cti-search.test.d.ts +1 -0
  168. package/orm/tests/repository-cti-search.test.js +152 -0
  169. package/orm/tests/repository-cti-soft-delete.test.d.ts +1 -0
  170. package/orm/tests/repository-cti-soft-delete.test.js +115 -0
  171. package/orm/tests/repository-cti-transactions.test.d.ts +1 -0
  172. package/orm/tests/repository-cti-transactions.test.js +126 -0
  173. package/orm/tests/repository-cti-upsert-many.test.d.ts +1 -0
  174. package/orm/tests/repository-cti-upsert-many.test.js +127 -0
  175. package/orm/tests/repository-cti.test.d.ts +1 -0
  176. package/orm/tests/repository-cti.test.js +456 -0
  177. package/orm/tests/repository-edge-cases.test.d.ts +1 -0
  178. package/orm/tests/repository-edge-cases.test.js +216 -0
  179. package/orm/tests/repository-expiration.test.d.ts +1 -0
  180. package/orm/tests/repository-expiration.test.js +153 -0
  181. package/orm/tests/repository-extra-coverage.test.d.ts +1 -0
  182. package/orm/tests/repository-extra-coverage.test.js +546 -0
  183. package/orm/tests/repository-mapping.test.d.ts +1 -0
  184. package/orm/tests/repository-mapping.test.js +71 -0
  185. package/orm/tests/repository-regression.test.d.ts +1 -0
  186. package/orm/tests/repository-regression.test.js +330 -0
  187. package/orm/tests/repository-search-coverage.test.d.ts +1 -0
  188. package/orm/tests/repository-search-coverage.test.js +129 -0
  189. package/orm/tests/repository-search.test.d.ts +1 -0
  190. package/orm/tests/repository-search.test.js +116 -0
  191. package/orm/tests/repository-soft-delete.test.d.ts +1 -0
  192. package/orm/tests/repository-soft-delete.test.js +143 -0
  193. package/orm/tests/repository-transactions-nested.test.d.ts +1 -0
  194. package/orm/tests/repository-transactions-nested.test.js +202 -0
  195. package/orm/tests/repository-types.test.d.ts +1 -0
  196. package/orm/tests/repository-types.test.js +218 -0
  197. package/orm/tests/schema-converter.test.d.ts +1 -0
  198. package/orm/tests/schema-converter.test.js +81 -0
  199. package/orm/tests/schema-generation.test.d.ts +1 -0
  200. package/orm/tests/schema-generation.test.js +127 -0
  201. package/orm/tests/sql-helpers.test.d.ts +1 -0
  202. package/orm/tests/sql-helpers.test.js +67 -0
  203. package/orm/tests/transaction-safety.test.d.ts +1 -0
  204. package/orm/tests/transaction-safety.test.js +81 -0
  205. package/orm/tests/transactional.test.d.ts +1 -0
  206. package/orm/tests/transactional.test.js +224 -0
  207. package/orm/tests/utils.test.d.ts +1 -0
  208. package/orm/tests/utils.test.js +70 -0
  209. package/orm/utils.d.ts +7 -0
  210. package/orm/utils.js +26 -6
  211. package/package.json +12 -7
  212. package/pool/pool.js +1 -1
  213. package/rate-limit/index.d.ts +2 -0
  214. package/rate-limit/index.js +2 -0
  215. package/rate-limit/postgres/drizzle/0000_watery_rage.sql +7 -0
  216. package/{queue → rate-limit}/postgres/drizzle/meta/0000_snapshot.json +14 -39
  217. package/rate-limit/postgres/drizzle/meta/_journal.json +13 -0
  218. package/{queue → rate-limit}/postgres/drizzle.config.js +1 -1
  219. package/rate-limit/postgres/index.d.ts +4 -0
  220. package/rate-limit/postgres/index.js +4 -0
  221. package/rate-limit/postgres/module.d.ts +12 -0
  222. package/rate-limit/postgres/module.js +28 -0
  223. package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -0
  224. package/rate-limit/postgres/postgres-rate-limiter.js +56 -0
  225. package/rate-limit/postgres/rate-limit.model.d.ts +8 -0
  226. package/rate-limit/postgres/rate-limit.model.js +35 -0
  227. package/rate-limit/postgres/rate-limiter.provider.d.ts +6 -0
  228. package/rate-limit/postgres/rate-limiter.provider.js +21 -0
  229. package/rate-limit/postgres/schemas.d.ts +3 -0
  230. package/rate-limit/postgres/schemas.js +4 -0
  231. package/rate-limit/provider.d.ts +9 -0
  232. package/rate-limit/provider.js +2 -0
  233. package/rate-limit/rate-limiter.d.ts +35 -0
  234. package/rate-limit/rate-limiter.js +3 -0
  235. package/rate-limit/tests/postgres-rate-limiter.test.d.ts +1 -0
  236. package/rate-limit/tests/postgres-rate-limiter.test.js +92 -0
  237. package/signals/implementation/configure.d.ts +3 -0
  238. package/signals/implementation/configure.js +3 -0
  239. package/sse/data-stream-source.d.ts +1 -1
  240. package/sse/data-stream-source.js +6 -6
  241. package/task-queue/enqueue-batch.d.ts +17 -0
  242. package/task-queue/enqueue-batch.js +24 -0
  243. package/{queue → task-queue}/index.d.ts +1 -1
  244. package/{queue → task-queue}/index.js +1 -1
  245. package/task-queue/postgres/drizzle/0000_thin_black_panther.sql +74 -0
  246. package/task-queue/postgres/drizzle/meta/0000_snapshot.json +592 -0
  247. package/task-queue/postgres/drizzle/meta/_journal.json +13 -0
  248. package/task-queue/postgres/drizzle.config.d.ts +2 -0
  249. package/task-queue/postgres/drizzle.config.js +11 -0
  250. package/task-queue/postgres/index.d.ts +4 -0
  251. package/task-queue/postgres/index.js +4 -0
  252. package/task-queue/postgres/module.d.ts +12 -0
  253. package/task-queue/postgres/module.js +28 -0
  254. package/task-queue/postgres/schemas.d.ts +16 -0
  255. package/task-queue/postgres/schemas.js +8 -0
  256. package/task-queue/postgres/task-queue.d.ts +83 -0
  257. package/task-queue/postgres/task-queue.js +1054 -0
  258. package/task-queue/postgres/task-queue.provider.d.ts +7 -0
  259. package/{queue/postgres/queue.provider.js → task-queue/postgres/task-queue.provider.js} +8 -8
  260. package/task-queue/postgres/task.model.d.ts +39 -0
  261. package/task-queue/postgres/task.model.js +178 -0
  262. package/{queue → task-queue}/provider.d.ts +3 -3
  263. package/task-queue/provider.js +2 -0
  264. package/{queue → task-queue}/task-context.d.ts +7 -7
  265. package/{queue → task-queue}/task-context.js +8 -8
  266. package/{queue/queue.d.ts → task-queue/task-queue.d.ts} +128 -59
  267. package/task-queue/task-queue.js +200 -0
  268. package/task-queue/tests/complex.test.d.ts +1 -0
  269. package/task-queue/tests/complex.test.js +299 -0
  270. package/task-queue/tests/dependencies.test.d.ts +1 -0
  271. package/task-queue/tests/dependencies.test.js +174 -0
  272. package/task-queue/tests/queue.test.d.ts +1 -0
  273. package/task-queue/tests/queue.test.js +334 -0
  274. package/task-queue/tests/worker.test.d.ts +1 -0
  275. package/task-queue/tests/worker.test.js +163 -0
  276. package/test1.js +1 -1
  277. package/test4.js +2 -2
  278. package/unit-test/index.d.ts +1 -0
  279. package/unit-test/index.js +1 -0
  280. package/unit-test/integration-setup.d.ts +55 -0
  281. package/unit-test/integration-setup.js +182 -0
  282. package/utils/patterns.d.ts +3 -0
  283. package/utils/patterns.js +6 -1
  284. package/audit/drizzle/0001_previous_network.sql +0 -2
  285. package/audit/drizzle/meta/0001_snapshot.json +0 -195
  286. package/queue/enqueue-batch.d.ts +0 -17
  287. package/queue/enqueue-batch.js +0 -18
  288. package/queue/postgres/drizzle/0000_zippy_moondragon.sql +0 -11
  289. package/queue/postgres/drizzle/0001_certain_wild_pack.sql +0 -2
  290. package/queue/postgres/drizzle/0002_dear_meggan.sql +0 -2
  291. package/queue/postgres/drizzle/0003_tricky_venom.sql +0 -30
  292. package/queue/postgres/drizzle/meta/0001_snapshot.json +0 -103
  293. package/queue/postgres/drizzle/meta/0002_snapshot.json +0 -90
  294. package/queue/postgres/drizzle/meta/0003_snapshot.json +0 -288
  295. package/queue/postgres/drizzle/meta/_journal.json +0 -34
  296. package/queue/postgres/index.d.ts +0 -4
  297. package/queue/postgres/index.js +0 -4
  298. package/queue/postgres/module.d.ts +0 -9
  299. package/queue/postgres/module.js +0 -29
  300. package/queue/postgres/queue.d.ts +0 -60
  301. package/queue/postgres/queue.js +0 -681
  302. package/queue/postgres/queue.provider.d.ts +0 -7
  303. package/queue/postgres/schemas.d.ts +0 -14
  304. package/queue/postgres/schemas.js +0 -6
  305. package/queue/postgres/task.model.d.ts +0 -24
  306. package/queue/postgres/task.model.js +0 -115
  307. package/queue/provider.js +0 -2
  308. package/queue/queue.js +0 -131
  309. package/queue/tests/queue.test.js +0 -623
  310. package/test3.d.ts +0 -1
  311. package/test3.js +0 -47
  312. /package/{queue/tests/queue.test.d.ts → api/server/tests/csrf.middleware.test.d.ts} +0 -0
  313. /package/circuit-breaker/postgres/drizzle/{0000_hard_shocker.sql → 0000_cooing_korath.sql} +0 -0
  314. /package/{queue → rate-limit}/postgres/drizzle.config.d.ts +0 -0
@@ -0,0 +1,143 @@
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 { Injector, runInInjectionContext } from '../../injector/index.js';
11
+ import { StringProperty } from '../../schema/index.js';
12
+ import { sql } from 'drizzle-orm';
13
+ import { beforeAll, describe, expect, test } from 'vitest';
14
+ import { Table } from '../decorators.js';
15
+ import { Entity } from '../entity.js';
16
+ import { configureOrm, Database } from '../server/index.js';
17
+ import { injectRepository } from '../server/repository.js';
18
+ describe('ORM Repository Soft Delete (Integration)', () => {
19
+ let injector;
20
+ let db;
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 = new Injector('Test');
34
+ configureOrm({
35
+ repositoryConfig: { schema },
36
+ connection: {
37
+ host: '127.0.0.1', port: 5432, user: 'tstdl', password: 'wf7rq6glrk5jykne', database: 'tstdl',
38
+ }
39
+ });
40
+ db = injector.resolve(Database);
41
+ await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
42
+ await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
43
+ await db.execute(sql `
44
+ CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} (
45
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
46
+ name 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
+ test('should soft delete an entity by ID', async () => {
56
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
57
+ await runInInjectionContext(injector, async () => {
58
+ const repository = injectRepository(SoftDeleteEntity);
59
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
60
+ const deleted = await repository.delete(e1.id);
61
+ expect(deleted.id).toBe(e1.id);
62
+ expect(deleted.metadata.deleteTimestamp).toBeDefined();
63
+ expect(await repository.has(e1.id)).toBe(false);
64
+ expect(await repository.tryLoad(e1.id)).toBeUndefined();
65
+ expect(await repository.count()).toBe(0);
66
+ const allWithDeleted = await repository.loadAll({ withDeleted: true });
67
+ expect(allWithDeleted).toHaveLength(1);
68
+ expect(allWithDeleted[0].id).toBe(e1.id);
69
+ });
70
+ });
71
+ test('should soft delete multiple entities by IDs', async () => {
72
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
73
+ await runInInjectionContext(injector, async () => {
74
+ const repository = injectRepository(SoftDeleteEntity);
75
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
76
+ const e2 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E2' }));
77
+ const deleted = await repository.deleteMany([e1.id, e2.id]);
78
+ expect(deleted).toHaveLength(2);
79
+ expect(await repository.count()).toBe(0);
80
+ expect(await repository.countByQuery({}, { withDeleted: true })).toBe(2);
81
+ });
82
+ });
83
+ test('should soft delete entities by query', async () => {
84
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
85
+ await runInInjectionContext(injector, async () => {
86
+ const repository = injectRepository(SoftDeleteEntity);
87
+ await repository.insertMany([
88
+ Object.assign(new SoftDeleteEntity(), { name: 'A' }),
89
+ Object.assign(new SoftDeleteEntity(), { name: 'B' }),
90
+ Object.assign(new SoftDeleteEntity(), { name: 'A' }),
91
+ ]);
92
+ const deleted = await repository.deleteManyByQuery({ name: 'A' });
93
+ expect(deleted).toHaveLength(2);
94
+ expect(await repository.count()).toBe(1);
95
+ expect(await repository.countByQuery({}, { withDeleted: true })).toBe(3);
96
+ });
97
+ });
98
+ test('should not update soft-deleted entities by default', async () => {
99
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
100
+ await runInInjectionContext(injector, async () => {
101
+ const repository = injectRepository(SoftDeleteEntity);
102
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
103
+ await repository.delete(e1.id);
104
+ const updated = await repository.tryUpdate(e1.id, { name: 'Updated' });
105
+ expect(updated).toBeUndefined();
106
+ const loaded = await repository.tryLoad(e1.id, { withDeleted: true });
107
+ expect(loaded.name).toBe('E1');
108
+ });
109
+ });
110
+ test('should support hard delete on soft-deleted entities', async () => {
111
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
112
+ await runInInjectionContext(injector, async () => {
113
+ const repository = injectRepository(SoftDeleteEntity);
114
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
115
+ await repository.delete(e1.id);
116
+ const hardDeleted = await repository.hardDelete(e1.id);
117
+ expect(hardDeleted.id).toBe(e1.id);
118
+ expect(await repository.countByQuery({}, { withDeleted: true })).toBe(0);
119
+ });
120
+ });
121
+ test('should ignore already soft-deleted entities when deleting again', async () => {
122
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
123
+ await runInInjectionContext(injector, async () => {
124
+ const repository = injectRepository(SoftDeleteEntity);
125
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
126
+ await repository.delete(e1.id);
127
+ const secondDelete = await repository.tryDelete(e1.id);
128
+ expect(secondDelete).toBeUndefined();
129
+ });
130
+ });
131
+ test('should hard delete multiple entities by query (including soft-deleted)', async () => {
132
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('soft_delete_entities')} CASCADE`);
133
+ await runInInjectionContext(injector, async () => {
134
+ const repository = injectRepository(SoftDeleteEntity);
135
+ const e1 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E1' }));
136
+ const e2 = await repository.insert(Object.assign(new SoftDeleteEntity(), { name: 'E2' }));
137
+ await repository.delete(e1.id); // Soft delete E1
138
+ const hardDeleted = await repository.hardDeleteManyByQuery({});
139
+ expect(hardDeleted).toHaveLength(2); // Should hard delete both
140
+ expect(await repository.countByQuery({}, { withDeleted: true })).toBe(0);
141
+ });
142
+ });
143
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,202 @@
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 { Injector, runInInjectionContext } from '../../injector/index.js';
13
+ import { StringProperty } from '../../schema/index.js';
14
+ import { Table } from '../decorators.js';
15
+ import { Entity } from '../entity.js';
16
+ import { configureOrm, Database } from '../server/index.js';
17
+ import { injectRepository } from '../server/repository.js';
18
+ describe('ORM Repository Transactions Nested (Integration)', () => {
19
+ let injector;
20
+ let db;
21
+ const schema = 'test_orm_tx_nested';
22
+ let TxEntity = class TxEntity extends Entity {
23
+ name;
24
+ };
25
+ __decorate([
26
+ StringProperty(),
27
+ __metadata("design:type", String)
28
+ ], TxEntity.prototype, "name", void 0);
29
+ TxEntity = __decorate([
30
+ Table('tx_entities', { schema })
31
+ ], TxEntity);
32
+ beforeAll(async () => {
33
+ injector = new Injector('Test');
34
+ configureOrm({
35
+ repositoryConfig: { schema },
36
+ connection: {
37
+ host: '127.0.0.1', port: 5432, user: 'tstdl', password: 'wf7rq6glrk5jykne', database: 'tstdl',
38
+ },
39
+ });
40
+ db = injector.resolve(Database);
41
+ await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
42
+ await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
43
+ await db.execute(sql `
44
+ CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} (
45
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
46
+ name 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
+ test('should commit nested transaction', async () => {
56
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
57
+ await runInInjectionContext(injector, async () => {
58
+ const repo = injectRepository(TxEntity);
59
+ await repo.transaction(async (tx1) => {
60
+ const repo1 = repo.withTransaction(tx1);
61
+ await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
62
+ await repo1.transaction(async (tx2) => {
63
+ const repo2 = repo1.withTransaction(tx2);
64
+ await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
65
+ });
66
+ });
67
+ const count = await repo.count();
68
+ expect(count).toBe(2);
69
+ });
70
+ });
71
+ test('should rollback nested transaction (inner fails)', async () => {
72
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
73
+ await runInInjectionContext(injector, async () => {
74
+ const repo = injectRepository(TxEntity);
75
+ try {
76
+ await repo.transaction(async (tx1) => {
77
+ const repo1 = repo.withTransaction(tx1);
78
+ await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
79
+ await repo1.transaction(async (tx2) => {
80
+ const repo2 = repo1.withTransaction(tx2);
81
+ await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
82
+ throw new Error('Fail Inner');
83
+ });
84
+ });
85
+ }
86
+ catch (e) {
87
+ expect(e.message).toBe('Fail Inner');
88
+ }
89
+ const count = await repo.count();
90
+ expect(count).toBe(0); // Outer should rollback too if error propagates
91
+ });
92
+ });
93
+ test('should rollback nested transaction but keep outer if caught', async () => {
94
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
95
+ await runInInjectionContext(injector, async () => {
96
+ const repo = injectRepository(TxEntity);
97
+ await repo.transaction(async (tx1) => {
98
+ const repo1 = repo.withTransaction(tx1);
99
+ await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
100
+ try {
101
+ await repo1.transaction(async (tx2) => {
102
+ const repo2 = repo1.withTransaction(tx2);
103
+ await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
104
+ throw new Error('Fail Inner');
105
+ });
106
+ }
107
+ catch {
108
+ // Swallow error to keep outer alive
109
+ }
110
+ });
111
+ const all = await repo.loadAll();
112
+ expect(all).toHaveLength(1);
113
+ expect(all[0].name).toBe('Outer');
114
+ });
115
+ });
116
+ test('should rollback outer transaction (outer fails after inner commit)', async () => {
117
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
118
+ await runInInjectionContext(injector, async () => {
119
+ const repo = injectRepository(TxEntity);
120
+ try {
121
+ await repo.transaction(async (tx1) => {
122
+ const repo1 = repo.withTransaction(tx1);
123
+ await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
124
+ await repo1.transaction(async (tx2) => {
125
+ const repo2 = repo1.withTransaction(tx2);
126
+ await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
127
+ });
128
+ throw new Error('Fail Outer');
129
+ });
130
+ }
131
+ catch {
132
+ // Expected
133
+ }
134
+ const count = await repo.count();
135
+ expect(count).toBe(0);
136
+ });
137
+ });
138
+ test('should support multiple nested transactions sequentially', async () => {
139
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
140
+ await runInInjectionContext(injector, async () => {
141
+ const repo = injectRepository(TxEntity);
142
+ await repo.transaction(async (tx1) => {
143
+ const repo1 = repo.withTransaction(tx1);
144
+ await repo1.transaction(async (tx2) => {
145
+ await repo1.withTransaction(tx2).insert(Object.assign(new TxEntity(), { name: 'Inner1' }));
146
+ });
147
+ await repo1.transaction(async (tx3) => {
148
+ await repo1.withTransaction(tx3).insert(Object.assign(new TxEntity(), { name: 'Inner2' }));
149
+ });
150
+ });
151
+ const count = await repo.count();
152
+ expect(count).toBe(2);
153
+ });
154
+ });
155
+ test('should support deep nesting (3 levels)', async () => {
156
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
157
+ await runInInjectionContext(injector, async () => {
158
+ const repo = injectRepository(TxEntity);
159
+ await repo.transaction(async (tx1) => {
160
+ const r1 = repo.withTransaction(tx1);
161
+ await r1.insert(Object.assign(new TxEntity(), { name: 'L1' }));
162
+ await r1.transaction(async (tx2) => {
163
+ const r2 = r1.withTransaction(tx2);
164
+ await r2.insert(Object.assign(new TxEntity(), { name: 'L2' }));
165
+ await r2.transaction(async (tx3) => {
166
+ const r3 = r2.withTransaction(tx3);
167
+ await r3.insert(Object.assign(new TxEntity(), { name: 'L3' }));
168
+ });
169
+ });
170
+ });
171
+ const count = await repo.count();
172
+ expect(count).toBe(3);
173
+ });
174
+ });
175
+ test('should rollback deep nesting middle layer', async () => {
176
+ await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
177
+ await runInInjectionContext(injector, async () => {
178
+ const repo = injectRepository(TxEntity);
179
+ await repo.transaction(async (tx1) => {
180
+ const r1 = repo.withTransaction(tx1);
181
+ await r1.insert(Object.assign(new TxEntity(), { name: 'L1' }));
182
+ try {
183
+ await r1.transaction(async (tx2) => {
184
+ const r2 = r1.withTransaction(tx2);
185
+ await r2.insert(Object.assign(new TxEntity(), { name: 'L2' }));
186
+ await r2.transaction(async (tx3) => {
187
+ const r3 = r2.withTransaction(tx3);
188
+ await r3.insert(Object.assign(new TxEntity(), { name: 'L3' }));
189
+ });
190
+ throw new Error('Fail L2');
191
+ });
192
+ }
193
+ catch {
194
+ // Catch L2 failure
195
+ }
196
+ });
197
+ const all = await repo.loadAll();
198
+ expect(all).toHaveLength(1);
199
+ expect(all[0].name).toBe('L1');
200
+ });
201
+ });
202
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,218 @@
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 { Injector, runInInjectionContext } from '../../injector/index.js';
13
+ import { Array, BooleanProperty, Integer, NumberProperty, string, StringProperty } from '../../schema/index.js';
14
+ import { Table } from '../decorators.js';
15
+ import { Entity } from '../entity.js';
16
+ import { JsonProperty, NumericDateProperty, TimestampProperty } from '../schemas/index.js';
17
+ import { configureOrm, Database } from '../server/index.js';
18
+ import { injectRepository } from '../server/repository.js';
19
+ describe('ORM Repository Types (Integration)', () => {
20
+ let injector;
21
+ let db;
22
+ const schema = 'test_orm_types';
23
+ let TypeEntity = class TypeEntity extends Entity {
24
+ text;
25
+ int;
26
+ float;
27
+ bool;
28
+ numericDate;
29
+ timestamp;
30
+ json;
31
+ tags;
32
+ };
33
+ __decorate([
34
+ StringProperty(),
35
+ __metadata("design:type", String)
36
+ ], TypeEntity.prototype, "text", void 0);
37
+ __decorate([
38
+ Integer(),
39
+ __metadata("design:type", Number)
40
+ ], TypeEntity.prototype, "int", void 0);
41
+ __decorate([
42
+ NumberProperty(),
43
+ __metadata("design:type", Number)
44
+ ], TypeEntity.prototype, "float", void 0);
45
+ __decorate([
46
+ BooleanProperty(),
47
+ __metadata("design:type", Boolean)
48
+ ], TypeEntity.prototype, "bool", void 0);
49
+ __decorate([
50
+ NumericDateProperty(),
51
+ __metadata("design:type", Number)
52
+ ], TypeEntity.prototype, "numericDate", void 0);
53
+ __decorate([
54
+ TimestampProperty(),
55
+ __metadata("design:type", Date)
56
+ ], TypeEntity.prototype, "timestamp", void 0);
57
+ __decorate([
58
+ JsonProperty(),
59
+ __metadata("design:type", Object)
60
+ ], TypeEntity.prototype, "json", void 0);
61
+ __decorate([
62
+ Array(string()),
63
+ __metadata("design:type", Array)
64
+ ], TypeEntity.prototype, "tags", void 0);
65
+ TypeEntity = __decorate([
66
+ Table('type_entities', { schema })
67
+ ], TypeEntity);
68
+ beforeAll(async () => {
69
+ injector = new Injector('Test');
70
+ configureOrm({
71
+ repositoryConfig: { schema },
72
+ connection: {
73
+ host: '127.0.0.1', port: 5432, user: 'tstdl', password: 'wf7rq6glrk5jykne', database: 'tstdl',
74
+ },
75
+ });
76
+ db = injector.resolve(Database);
77
+ await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
78
+ await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('type_entities')} CASCADE`);
79
+ await db.execute(sql `
80
+ CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('type_entities')} (
81
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
82
+ text TEXT NOT NULL,
83
+ int INTEGER NOT NULL,
84
+ float DOUBLE PRECISION NOT NULL,
85
+ bool BOOLEAN NOT NULL,
86
+ numeric_date DATE NOT NULL,
87
+ timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
88
+ json JSONB NOT NULL,
89
+ tags TEXT[] NOT NULL,
90
+ revision INTEGER NOT NULL,
91
+ revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
92
+ create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
93
+ delete_timestamp TIMESTAMP WITH TIME ZONE,
94
+ attributes JSONB NOT NULL DEFAULT '{}'
95
+ )
96
+ `);
97
+ });
98
+ test('should persist and retrieve boolean values (true)', async () => {
99
+ await runInInjectionContext(injector, async () => {
100
+ const repo = injectRepository(TypeEntity);
101
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
102
+ text: 't', int: 1, float: 1.1, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
103
+ }));
104
+ const loaded = await repo.load(entity.id);
105
+ expect(loaded.bool).toBe(true);
106
+ });
107
+ });
108
+ test('should persist and retrieve boolean values (false)', async () => {
109
+ await runInInjectionContext(injector, async () => {
110
+ const repo = injectRepository(TypeEntity);
111
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
112
+ text: 'f', int: 1, float: 1.1, bool: false, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
113
+ }));
114
+ const loaded = await repo.load(entity.id);
115
+ expect(loaded.bool).toBe(false);
116
+ });
117
+ });
118
+ test('should persist and retrieve integer boundaries', async () => {
119
+ await runInInjectionContext(injector, async () => {
120
+ const repo = injectRepository(TypeEntity);
121
+ const maxInt = 2147483647;
122
+ const minInt = -2147483648;
123
+ const e1 = await repo.insert(Object.assign(new TypeEntity(), {
124
+ text: 'max', int: maxInt, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
125
+ }));
126
+ const l1 = await repo.load(e1.id);
127
+ expect(l1.int).toBe(maxInt);
128
+ const e2 = await repo.insert(Object.assign(new TypeEntity(), {
129
+ text: 'min', int: minInt, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
130
+ }));
131
+ const l2 = await repo.load(e2.id);
132
+ expect(l2.int).toBe(minInt);
133
+ });
134
+ });
135
+ test('should persist and retrieve float precision', async () => {
136
+ await runInInjectionContext(injector, async () => {
137
+ const repo = injectRepository(TypeEntity);
138
+ const pi = 3.1415926535;
139
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
140
+ text: 'pi', int: 0, float: pi, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
141
+ }));
142
+ const loaded = await repo.load(entity.id);
143
+ expect(loaded.float).toBeCloseTo(pi);
144
+ });
145
+ });
146
+ test('should persist and retrieve numeric dates', async () => {
147
+ await runInInjectionContext(injector, async () => {
148
+ const repo = injectRepository(TypeEntity);
149
+ const today = 19723; // 2024-01-01
150
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
151
+ text: 'date', int: 0, float: 0, bool: true, numericDate: today, timestamp: new Date(), json: {}, tags: [],
152
+ }));
153
+ const loaded = await repo.load(entity.id);
154
+ expect(loaded.numericDate).toBe(today);
155
+ });
156
+ });
157
+ test('should persist and retrieve timestamps', async () => {
158
+ await runInInjectionContext(injector, async () => {
159
+ const repo = injectRepository(TypeEntity);
160
+ const now = new Date();
161
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
162
+ text: 'ts', int: 0, float: 0, bool: true, numericDate: 0, timestamp: now, json: {}, tags: [],
163
+ }));
164
+ const loaded = await repo.load(entity.id);
165
+ // Postgres stores microsecond precision, JS Date has millisecond.
166
+ // Drizzle custom type returns number (milliseconds).
167
+ // We accept a small difference due to precision loss or round-trip.
168
+ expect(typeof loaded.timestamp).toBe('number');
169
+ expect(Math.abs(loaded.timestamp - now.getTime())).toBeLessThan(2);
170
+ });
171
+ });
172
+ test('should persist and retrieve complex JSON', async () => {
173
+ await runInInjectionContext(injector, async () => {
174
+ const repo = injectRepository(TypeEntity);
175
+ const data = {
176
+ foo: 'bar',
177
+ nested: { a: 1, b: [true, false] },
178
+ nullVal: null,
179
+ };
180
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
181
+ text: 'json', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: data, tags: [],
182
+ }));
183
+ const loaded = await repo.load(entity.id);
184
+ expect(loaded.json).toEqual(data);
185
+ });
186
+ });
187
+ test('should persist and retrieve arrays', async () => {
188
+ await runInInjectionContext(injector, async () => {
189
+ const repo = injectRepository(TypeEntity);
190
+ const tags = ['a', 'b', 'c'];
191
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
192
+ text: 'array', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags,
193
+ }));
194
+ const loaded = await repo.load(entity.id);
195
+ expect(loaded.tags).toEqual(tags);
196
+ });
197
+ });
198
+ test('should persist and retrieve empty arrays', async () => {
199
+ await runInInjectionContext(injector, async () => {
200
+ const repo = injectRepository(TypeEntity);
201
+ const entity = await repo.insert(Object.assign(new TypeEntity(), {
202
+ text: 'empty-array', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
203
+ }));
204
+ const loaded = await repo.load(entity.id);
205
+ expect(loaded.tags).toEqual([]);
206
+ });
207
+ });
208
+ test('should fail on integer overflow', async () => {
209
+ await runInInjectionContext(injector, async () => {
210
+ const repo = injectRepository(TypeEntity);
211
+ // Max int is 2147483647
212
+ const overflow = 3000000000;
213
+ await expect(repo.insert(Object.assign(new TypeEntity(), {
214
+ text: 'overflow', int: overflow, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
215
+ }))).rejects.toThrow(); // Postgres should reject
216
+ });
217
+ });
218
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,81 @@
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 { StringProperty } from '../../schema/index.js';
11
+ import { getTableConfig } from 'drizzle-orm/pg-core';
12
+ import { describe, expect, test } from 'vitest';
13
+ import { Column, Index, PrimaryKeyProperty, Table } from '../decorators.js';
14
+ import { Entity } from '../entity.js';
15
+ import { getDrizzleTableFromType } from '../server/drizzle/schema-converter.js';
16
+ let Parent = class Parent extends Entity {
17
+ code;
18
+ };
19
+ __decorate([
20
+ StringProperty(),
21
+ Column({ name: 'code' }),
22
+ __metadata("design:type", String)
23
+ ], Parent.prototype, "code", void 0);
24
+ Parent = __decorate([
25
+ Table('parent_table', { schema: 'test' })
26
+ ], Parent);
27
+ describe('ORM Schema Generation - Detailed Configurations', () => {
28
+ test('should generate partial index with where clause', () => {
29
+ let PartialIndexEntity = class PartialIndexEntity extends Entity {
30
+ status;
31
+ };
32
+ __decorate([
33
+ StringProperty(),
34
+ Index({ where: () => ({ status: 'active' }) }),
35
+ __metadata("design:type", String)
36
+ ], PartialIndexEntity.prototype, "status", void 0);
37
+ PartialIndexEntity = __decorate([
38
+ Table('partial_index_test', { schema: 'test' })
39
+ ], PartialIndexEntity);
40
+ const table = getDrizzleTableFromType(PartialIndexEntity);
41
+ const config = getTableConfig(table);
42
+ expect(config.indexes.length).toBeGreaterThan(0);
43
+ const idx = config.indexes[0];
44
+ expect(idx).toBeDefined();
45
+ expect(idx.config.where).toBeDefined();
46
+ });
47
+ test('should handle index with nulls ordering', () => {
48
+ let NullOrderingEntity = class NullOrderingEntity extends Entity {
49
+ val;
50
+ };
51
+ __decorate([
52
+ StringProperty(),
53
+ Index({ nulls: 'first' }),
54
+ __metadata("design:type", String)
55
+ ], NullOrderingEntity.prototype, "val", void 0);
56
+ NullOrderingEntity = __decorate([
57
+ Table('null_ordering_test', { schema: 'test' })
58
+ ], NullOrderingEntity);
59
+ const table = getDrizzleTableFromType(NullOrderingEntity);
60
+ const config = getTableConfig(table);
61
+ expect(config.indexes.length).toBeGreaterThan(0);
62
+ });
63
+ test('should handle renamed id column', () => {
64
+ let RenamedIdEntity = class RenamedIdEntity extends Entity {
65
+ };
66
+ __decorate([
67
+ StringProperty(),
68
+ Column({ name: 'custom_id' }),
69
+ PrimaryKeyProperty(),
70
+ __metadata("design:type", String)
71
+ ], RenamedIdEntity.prototype, "id", void 0);
72
+ RenamedIdEntity = __decorate([
73
+ Table('renamed_id_test', { schema: 'test' })
74
+ ], RenamedIdEntity);
75
+ const table = getDrizzleTableFromType(RenamedIdEntity);
76
+ const config = getTableConfig(table);
77
+ const idCol = config.columns.find(c => c.name === 'custom_id');
78
+ expect(idCol).toBeDefined();
79
+ expect(idCol.primary).toBe(true);
80
+ });
81
+ });
@@ -0,0 +1 @@
1
+ export {};