@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.
- package/ai/genkit/helpers.d.ts +3 -1
- package/ai/genkit/helpers.js +3 -3
- package/api/server/gateway.d.ts +3 -0
- package/api/server/gateway.js +15 -4
- package/api/server/middlewares/catch-error.middleware.js +2 -4
- package/api/server/middlewares/cors.middleware.js +2 -3
- package/api/server/middlewares/csrf.middleware.d.ts +41 -0
- package/api/server/middlewares/csrf.middleware.js +108 -0
- package/api/server/middlewares/index.d.ts +1 -0
- package/api/server/middlewares/index.js +1 -0
- package/api/server/module.d.ts +8 -2
- package/api/server/module.js +14 -8
- package/api/server/tests/csrf.middleware.test.js +91 -0
- package/audit/drizzle/{0000_bored_stick.sql → 0000_lumpy_thunderball.sql} +3 -3
- package/audit/drizzle/meta/0000_snapshot.json +4 -4
- package/audit/drizzle/meta/_journal.json +2 -9
- package/audit/module.d.ts +4 -1
- package/audit/module.js +3 -2
- package/audit/schemas.d.ts +1 -1
- package/audit/types.d.ts +1 -1
- package/audit/types.js +1 -1
- package/authentication/client/authentication.service.d.ts +14 -1
- package/authentication/client/authentication.service.js +82 -23
- package/authentication/client/http-client.middleware.d.ts +6 -0
- package/authentication/client/http-client.middleware.js +36 -0
- package/authentication/client/module.js +8 -2
- package/authentication/models/service-account.model.d.ts +2 -2
- package/authentication/models/service-account.model.js +10 -5
- package/authentication/models/subject.model.d.ts +20 -5
- package/authentication/models/subject.model.js +34 -29
- package/authentication/models/system-account.model.d.ts +3 -2
- package/authentication/models/system-account.model.js +11 -5
- package/authentication/models/user.model.d.ts +2 -11
- package/authentication/models/user.model.js +5 -16
- package/authentication/server/authentication-api-request-token.provider.d.ts +0 -2
- package/authentication/server/authentication-api-request-token.provider.js +3 -11
- package/authentication/server/authentication.api-controller.d.ts +1 -2
- package/authentication/server/authentication.api-controller.js +8 -9
- package/authentication/server/authentication.audit.d.ts +3 -2
- package/authentication/server/authentication.service.d.ts +27 -1
- package/authentication/server/authentication.service.js +67 -18
- package/authentication/server/drizzle/{0000_normal_paper_doll.sql → 0000_soft_tag.sql} +25 -32
- package/authentication/server/drizzle/meta/0000_snapshot.json +180 -205
- package/authentication/server/drizzle/meta/_journal.json +2 -2
- package/authentication/server/helper.js +9 -2
- package/authentication/server/module.d.ts +4 -1
- package/authentication/server/module.js +9 -5
- package/authentication/server/schemas.d.ts +2 -1
- package/authentication/server/schemas.js +2 -2
- package/authentication/server/subject.service.d.ts +17 -11
- package/authentication/server/subject.service.js +86 -84
- package/authentication/tests/authentication-ancillary.service.test.d.ts +1 -0
- package/authentication/tests/authentication-ancillary.service.test.js +13 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.d.ts +1 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.js +29 -0
- package/authentication/tests/authentication.api-controller.test.d.ts +1 -0
- package/authentication/tests/authentication.api-controller.test.js +88 -0
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +1 -0
- package/authentication/tests/authentication.api-request-token.provider.test.js +48 -0
- package/authentication/tests/authentication.client-middleware.test.d.ts +1 -0
- package/authentication/tests/authentication.client-middleware.test.js +23 -0
- package/authentication/tests/authentication.client-service.test.d.ts +1 -0
- package/authentication/tests/authentication.client-service.test.js +70 -0
- package/authentication/tests/authentication.service.test.d.ts +1 -0
- package/authentication/tests/authentication.service.test.js +186 -0
- package/authentication/tests/authentication.test-ancillary-service.d.ts +9 -0
- package/authentication/tests/authentication.test-ancillary-service.js +27 -0
- package/authentication/tests/helper.test.d.ts +1 -0
- package/authentication/tests/helper.test.js +107 -0
- package/authentication/tests/secret-requirements.error.test.d.ts +1 -0
- package/authentication/tests/secret-requirements.error.test.js +14 -0
- package/authentication/tests/subject.service.test.d.ts +1 -0
- package/authentication/tests/subject.service.test.js +140 -0
- package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +1 -1
- package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
- package/circuit-breaker/postgres/module.d.ts +7 -1
- package/circuit-breaker/postgres/module.js +8 -6
- package/circuit-breaker/tests/circuit-breaker.test.js +2 -22
- package/document-management/api/document-management.api.js +2 -6
- package/document-management/server/services/document-validation.service.js +6 -5
- package/document-management/server/services/document-workflow.service.js +5 -5
- package/document-management/service-models/document-folders.view-model.d.ts +5 -2
- package/document-management/service-models/document-folders.view-model.js +42 -9
- package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
- package/examples/document-management/main.js +4 -4
- package/http/client/adapters/undici.adapter.d.ts +7 -5
- package/http/client/adapters/undici.adapter.js +13 -10
- package/http/client/module.d.ts +3 -1
- package/http/client/module.js +8 -9
- package/http/server/http-server.d.ts +2 -0
- package/http/server/node/module.d.ts +6 -2
- package/http/server/node/module.js +6 -4
- package/http/server/node/node-http-server.d.ts +2 -0
- package/http/server/node/node-http-server.js +7 -0
- package/http/types.d.ts +1 -1
- package/key-value-store/postgres/module.d.ts +7 -1
- package/key-value-store/postgres/module.js +7 -3
- package/lock/postgres/lock.js +0 -1
- package/lock/postgres/module.d.ts +7 -1
- package/lock/postgres/module.js +9 -5
- package/logger/formatter.d.ts +2 -0
- package/logger/formatters/json.js +2 -2
- package/logger/formatters/pretty-print.js +8 -10
- package/logger/logger.d.ts +1 -1
- package/logger/logger.js +15 -12
- package/message-bus/local/module.d.ts +5 -2
- package/message-bus/local/module.js +5 -4
- package/module/module.d.ts +2 -1
- package/module/module.js +3 -0
- package/module/modules/web-server.module.d.ts +11 -6
- package/module/modules/web-server.module.js +15 -10
- package/orm/decorators.d.ts +24 -1
- package/orm/decorators.js +40 -4
- package/orm/query/base.d.ts +17 -17
- package/orm/query/base.js +1 -1
- package/orm/repository.types.d.ts +45 -1
- package/orm/schemas/tsvector.js +1 -1
- package/orm/server/drizzle/schema-converter.d.ts +3 -1
- package/orm/server/drizzle/schema-converter.js +120 -14
- package/orm/server/index.d.ts +1 -0
- package/orm/server/index.js +1 -0
- package/orm/server/module.d.ts +4 -2
- package/orm/server/module.js +6 -5
- package/orm/server/query-converter.d.ts +6 -3
- package/orm/server/query-converter.js +32 -20
- package/orm/server/repository-config.d.ts +8 -0
- package/orm/server/repository-config.js +8 -0
- package/orm/server/repository.d.ts +117 -43
- package/orm/server/repository.js +757 -253
- package/orm/server/transaction.d.ts +4 -2
- package/orm/server/transaction.js +14 -5
- package/orm/server/transactional.d.ts +6 -2
- package/orm/server/transactional.js +39 -9
- package/orm/server/types.d.ts +2 -0
- package/orm/sqls/case-when.d.ts +3 -3
- package/orm/sqls/case-when.js +2 -2
- package/orm/sqls/sqls.d.ts +31 -5
- package/orm/sqls/sqls.js +69 -6
- package/orm/tests/data-types.test.d.ts +1 -0
- package/orm/tests/data-types.test.js +39 -0
- package/orm/tests/decorators.test.d.ts +1 -0
- package/orm/tests/decorators.test.js +77 -0
- package/orm/tests/encryption.test.d.ts +1 -0
- package/orm/tests/encryption.test.js +34 -0
- package/orm/tests/query-complex.test.d.ts +1 -0
- package/orm/tests/query-complex.test.js +203 -0
- package/orm/tests/query-converter-complex.test.d.ts +1 -0
- package/orm/tests/query-converter-complex.test.js +126 -0
- package/orm/tests/query-converter.test.d.ts +1 -0
- package/orm/tests/query-converter.test.js +123 -0
- package/orm/tests/repository-advanced.test.d.ts +1 -0
- package/orm/tests/repository-advanced.test.js +232 -0
- package/orm/tests/repository-attributes.test.d.ts +1 -0
- package/orm/tests/repository-attributes.test.js +99 -0
- package/orm/tests/repository-comprehensive.test.d.ts +1 -0
- package/orm/tests/repository-comprehensive.test.js +187 -0
- package/orm/tests/repository-coverage.test.d.ts +1 -0
- package/orm/tests/repository-coverage.test.js +303 -0
- package/orm/tests/repository-cti-complex.test.d.ts +1 -0
- package/orm/tests/repository-cti-complex.test.js +170 -0
- package/orm/tests/repository-cti-embedded.test.d.ts +1 -0
- package/orm/tests/repository-cti-embedded.test.js +188 -0
- package/orm/tests/repository-cti-extensive.test.d.ts +1 -0
- package/orm/tests/repository-cti-extensive.test.js +308 -0
- package/orm/tests/repository-cti-mapping.test.d.ts +1 -0
- package/orm/tests/repository-cti-mapping.test.js +121 -0
- package/orm/tests/repository-cti-search.test.d.ts +1 -0
- package/orm/tests/repository-cti-search.test.js +152 -0
- package/orm/tests/repository-cti-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-cti-soft-delete.test.js +115 -0
- package/orm/tests/repository-cti-transactions.test.d.ts +1 -0
- package/orm/tests/repository-cti-transactions.test.js +126 -0
- package/orm/tests/repository-cti-upsert-many.test.d.ts +1 -0
- package/orm/tests/repository-cti-upsert-many.test.js +127 -0
- package/orm/tests/repository-cti.test.d.ts +1 -0
- package/orm/tests/repository-cti.test.js +456 -0
- package/orm/tests/repository-edge-cases.test.d.ts +1 -0
- package/orm/tests/repository-edge-cases.test.js +216 -0
- package/orm/tests/repository-expiration.test.d.ts +1 -0
- package/orm/tests/repository-expiration.test.js +153 -0
- package/orm/tests/repository-extra-coverage.test.d.ts +1 -0
- package/orm/tests/repository-extra-coverage.test.js +546 -0
- package/orm/tests/repository-mapping.test.d.ts +1 -0
- package/orm/tests/repository-mapping.test.js +71 -0
- package/orm/tests/repository-regression.test.d.ts +1 -0
- package/orm/tests/repository-regression.test.js +330 -0
- package/orm/tests/repository-search-coverage.test.d.ts +1 -0
- package/orm/tests/repository-search-coverage.test.js +129 -0
- package/orm/tests/repository-search.test.d.ts +1 -0
- package/orm/tests/repository-search.test.js +116 -0
- package/orm/tests/repository-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-soft-delete.test.js +143 -0
- package/orm/tests/repository-transactions-nested.test.d.ts +1 -0
- package/orm/tests/repository-transactions-nested.test.js +202 -0
- package/orm/tests/repository-types.test.d.ts +1 -0
- package/orm/tests/repository-types.test.js +218 -0
- package/orm/tests/schema-converter.test.d.ts +1 -0
- package/orm/tests/schema-converter.test.js +81 -0
- package/orm/tests/schema-generation.test.d.ts +1 -0
- package/orm/tests/schema-generation.test.js +127 -0
- package/orm/tests/sql-helpers.test.d.ts +1 -0
- package/orm/tests/sql-helpers.test.js +67 -0
- package/orm/tests/transaction-safety.test.d.ts +1 -0
- package/orm/tests/transaction-safety.test.js +81 -0
- package/orm/tests/transactional.test.d.ts +1 -0
- package/orm/tests/transactional.test.js +224 -0
- package/orm/tests/utils.test.d.ts +1 -0
- package/orm/tests/utils.test.js +70 -0
- package/orm/utils.d.ts +7 -0
- package/orm/utils.js +26 -6
- package/package.json +12 -7
- package/pool/pool.js +1 -1
- package/rate-limit/index.d.ts +2 -0
- package/rate-limit/index.js +2 -0
- package/rate-limit/postgres/drizzle/0000_watery_rage.sql +7 -0
- package/{queue → rate-limit}/postgres/drizzle/meta/0000_snapshot.json +14 -39
- package/rate-limit/postgres/drizzle/meta/_journal.json +13 -0
- package/{queue → rate-limit}/postgres/drizzle.config.js +1 -1
- package/rate-limit/postgres/index.d.ts +4 -0
- package/rate-limit/postgres/index.js +4 -0
- package/rate-limit/postgres/module.d.ts +12 -0
- package/rate-limit/postgres/module.js +28 -0
- package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -0
- package/rate-limit/postgres/postgres-rate-limiter.js +56 -0
- package/rate-limit/postgres/rate-limit.model.d.ts +8 -0
- package/rate-limit/postgres/rate-limit.model.js +35 -0
- package/rate-limit/postgres/rate-limiter.provider.d.ts +6 -0
- package/rate-limit/postgres/rate-limiter.provider.js +21 -0
- package/rate-limit/postgres/schemas.d.ts +3 -0
- package/rate-limit/postgres/schemas.js +4 -0
- package/rate-limit/provider.d.ts +9 -0
- package/rate-limit/provider.js +2 -0
- package/rate-limit/rate-limiter.d.ts +35 -0
- package/rate-limit/rate-limiter.js +3 -0
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +1 -0
- package/rate-limit/tests/postgres-rate-limiter.test.js +92 -0
- package/signals/implementation/configure.d.ts +3 -0
- package/signals/implementation/configure.js +3 -0
- package/sse/data-stream-source.d.ts +1 -1
- package/sse/data-stream-source.js +6 -6
- package/task-queue/enqueue-batch.d.ts +17 -0
- package/task-queue/enqueue-batch.js +24 -0
- package/{queue → task-queue}/index.d.ts +1 -1
- package/{queue → task-queue}/index.js +1 -1
- package/task-queue/postgres/drizzle/0000_thin_black_panther.sql +74 -0
- package/task-queue/postgres/drizzle/meta/0000_snapshot.json +592 -0
- package/task-queue/postgres/drizzle/meta/_journal.json +13 -0
- package/task-queue/postgres/drizzle.config.d.ts +2 -0
- package/task-queue/postgres/drizzle.config.js +11 -0
- package/task-queue/postgres/index.d.ts +4 -0
- package/task-queue/postgres/index.js +4 -0
- package/task-queue/postgres/module.d.ts +12 -0
- package/task-queue/postgres/module.js +28 -0
- package/task-queue/postgres/schemas.d.ts +16 -0
- package/task-queue/postgres/schemas.js +8 -0
- package/task-queue/postgres/task-queue.d.ts +83 -0
- package/task-queue/postgres/task-queue.js +1054 -0
- package/task-queue/postgres/task-queue.provider.d.ts +7 -0
- package/{queue/postgres/queue.provider.js → task-queue/postgres/task-queue.provider.js} +8 -8
- package/task-queue/postgres/task.model.d.ts +39 -0
- package/task-queue/postgres/task.model.js +178 -0
- package/{queue → task-queue}/provider.d.ts +3 -3
- package/task-queue/provider.js +2 -0
- package/{queue → task-queue}/task-context.d.ts +7 -7
- package/{queue → task-queue}/task-context.js +8 -8
- package/{queue/queue.d.ts → task-queue/task-queue.d.ts} +128 -59
- package/task-queue/task-queue.js +200 -0
- package/task-queue/tests/complex.test.d.ts +1 -0
- package/task-queue/tests/complex.test.js +299 -0
- package/task-queue/tests/dependencies.test.d.ts +1 -0
- package/task-queue/tests/dependencies.test.js +174 -0
- package/task-queue/tests/queue.test.d.ts +1 -0
- package/task-queue/tests/queue.test.js +334 -0
- package/task-queue/tests/worker.test.d.ts +1 -0
- package/task-queue/tests/worker.test.js +163 -0
- package/test1.js +1 -1
- package/test4.js +2 -2
- package/unit-test/index.d.ts +1 -0
- package/unit-test/index.js +1 -0
- package/unit-test/integration-setup.d.ts +55 -0
- package/unit-test/integration-setup.js +182 -0
- package/utils/patterns.d.ts +3 -0
- package/utils/patterns.js +6 -1
- package/audit/drizzle/0001_previous_network.sql +0 -2
- package/audit/drizzle/meta/0001_snapshot.json +0 -195
- package/queue/enqueue-batch.d.ts +0 -17
- package/queue/enqueue-batch.js +0 -18
- package/queue/postgres/drizzle/0000_zippy_moondragon.sql +0 -11
- package/queue/postgres/drizzle/0001_certain_wild_pack.sql +0 -2
- package/queue/postgres/drizzle/0002_dear_meggan.sql +0 -2
- package/queue/postgres/drizzle/0003_tricky_venom.sql +0 -30
- package/queue/postgres/drizzle/meta/0001_snapshot.json +0 -103
- package/queue/postgres/drizzle/meta/0002_snapshot.json +0 -90
- package/queue/postgres/drizzle/meta/0003_snapshot.json +0 -288
- package/queue/postgres/drizzle/meta/_journal.json +0 -34
- package/queue/postgres/index.d.ts +0 -4
- package/queue/postgres/index.js +0 -4
- package/queue/postgres/module.d.ts +0 -9
- package/queue/postgres/module.js +0 -29
- package/queue/postgres/queue.d.ts +0 -60
- package/queue/postgres/queue.js +0 -681
- package/queue/postgres/queue.provider.d.ts +0 -7
- package/queue/postgres/schemas.d.ts +0 -14
- package/queue/postgres/schemas.js +0 -6
- package/queue/postgres/task.model.d.ts +0 -24
- package/queue/postgres/task.model.js +0 -115
- package/queue/provider.js +0 -2
- package/queue/queue.js +0 -131
- package/queue/tests/queue.test.js +0 -623
- package/test3.d.ts +0 -1
- package/test3.js +0 -47
- /package/{queue/tests/queue.test.d.ts → api/server/tests/csrf.middleware.test.d.ts} +0 -0
- /package/circuit-breaker/postgres/drizzle/{0000_hard_shocker.sql → 0000_cooing_korath.sql} +0 -0
- /package/{queue → rate-limit}/postgres/drizzle.config.d.ts +0 -0
|
@@ -0,0 +1,456 @@
|
|
|
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 { dropTables, setupIntegrationTest, truncateTables } from '../../unit-test/index.js';
|
|
13
|
+
import { sql } from 'drizzle-orm';
|
|
14
|
+
import { beforeAll, describe, expect, test } from 'vitest';
|
|
15
|
+
import { ChildEntity, Column, Inheritance, Table } from '../decorators.js';
|
|
16
|
+
import { Entity } from '../entity.js';
|
|
17
|
+
import { Database, injectRepository } from '../server/index.js';
|
|
18
|
+
describe('ORM Repository CTI (Integration)', () => {
|
|
19
|
+
let injector;
|
|
20
|
+
let database;
|
|
21
|
+
const schema = 'test_orm_cti';
|
|
22
|
+
let BaseUser = class BaseUser extends Entity {
|
|
23
|
+
type;
|
|
24
|
+
name;
|
|
25
|
+
};
|
|
26
|
+
__decorate([
|
|
27
|
+
StringProperty(),
|
|
28
|
+
Column({ name: 'type' }),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], BaseUser.prototype, "type", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
StringProperty(),
|
|
33
|
+
Column({ name: 'name' }),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], BaseUser.prototype, "name", void 0);
|
|
36
|
+
BaseUser = __decorate([
|
|
37
|
+
Table('users', { schema }),
|
|
38
|
+
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
39
|
+
], BaseUser);
|
|
40
|
+
let Admin = class Admin extends BaseUser {
|
|
41
|
+
role;
|
|
42
|
+
};
|
|
43
|
+
__decorate([
|
|
44
|
+
StringProperty(),
|
|
45
|
+
Column({ name: 'role' }),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], Admin.prototype, "role", void 0);
|
|
48
|
+
Admin = __decorate([
|
|
49
|
+
Table('admins', { schema }),
|
|
50
|
+
ChildEntity('admin')
|
|
51
|
+
], Admin);
|
|
52
|
+
let Guest = class Guest extends BaseUser {
|
|
53
|
+
permissions;
|
|
54
|
+
};
|
|
55
|
+
__decorate([
|
|
56
|
+
StringProperty(),
|
|
57
|
+
Column({ name: 'permissions' }),
|
|
58
|
+
__metadata("design:type", String)
|
|
59
|
+
], Guest.prototype, "permissions", void 0);
|
|
60
|
+
Guest = __decorate([
|
|
61
|
+
Table('guests', { schema }),
|
|
62
|
+
ChildEntity('guest')
|
|
63
|
+
], Guest);
|
|
64
|
+
let Staff = class Staff extends BaseUser {
|
|
65
|
+
employeeId;
|
|
66
|
+
};
|
|
67
|
+
__decorate([
|
|
68
|
+
StringProperty(),
|
|
69
|
+
Column({ name: 'employee_id' }),
|
|
70
|
+
__metadata("design:type", String)
|
|
71
|
+
], Staff.prototype, "employeeId", void 0);
|
|
72
|
+
Staff = __decorate([
|
|
73
|
+
Table('staff', { schema }),
|
|
74
|
+
Inheritance({ strategy: 'joined' }),
|
|
75
|
+
ChildEntity('staff')
|
|
76
|
+
], Staff);
|
|
77
|
+
let Manager = class Manager extends Staff {
|
|
78
|
+
department;
|
|
79
|
+
};
|
|
80
|
+
__decorate([
|
|
81
|
+
StringProperty(),
|
|
82
|
+
Column({ name: 'department' }),
|
|
83
|
+
__metadata("design:type", String)
|
|
84
|
+
], Manager.prototype, "department", void 0);
|
|
85
|
+
Manager = __decorate([
|
|
86
|
+
Table('managers', { schema }),
|
|
87
|
+
ChildEntity('manager')
|
|
88
|
+
], Manager);
|
|
89
|
+
beforeAll(async () => {
|
|
90
|
+
({ injector, database } = await setupIntegrationTest({ orm: { schema } }));
|
|
91
|
+
await database.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
92
|
+
await dropTables(database, schema, ['managers', 'staff', 'guests', 'admins', 'users']);
|
|
93
|
+
await database.execute(sql `
|
|
94
|
+
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('users')} (
|
|
95
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
96
|
+
type TEXT NOT NULL,
|
|
97
|
+
name TEXT NOT NULL,
|
|
98
|
+
revision INTEGER NOT NULL,
|
|
99
|
+
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
100
|
+
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
101
|
+
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
102
|
+
attributes JSONB NOT NULL DEFAULT '{}',
|
|
103
|
+
UNIQUE (id, type)
|
|
104
|
+
)
|
|
105
|
+
`);
|
|
106
|
+
await database.execute(sql `
|
|
107
|
+
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('admins')} (
|
|
108
|
+
id UUID PRIMARY KEY,
|
|
109
|
+
type TEXT NOT NULL CHECK (type = 'admin'),
|
|
110
|
+
role TEXT NOT NULL,
|
|
111
|
+
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('users')} (id, type) ON DELETE CASCADE
|
|
112
|
+
)
|
|
113
|
+
`);
|
|
114
|
+
await database.execute(sql `
|
|
115
|
+
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('guests')} (
|
|
116
|
+
id UUID PRIMARY KEY,
|
|
117
|
+
type TEXT NOT NULL CHECK (type = 'guest'),
|
|
118
|
+
permissions TEXT NOT NULL,
|
|
119
|
+
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('users')} (id, type) ON DELETE CASCADE
|
|
120
|
+
)
|
|
121
|
+
`);
|
|
122
|
+
await database.execute(sql `
|
|
123
|
+
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('staff')} (
|
|
124
|
+
id UUID PRIMARY KEY,
|
|
125
|
+
type TEXT NOT NULL,
|
|
126
|
+
employee_id TEXT NOT NULL,
|
|
127
|
+
UNIQUE (id, type),
|
|
128
|
+
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('users')} (id, type) ON DELETE CASCADE
|
|
129
|
+
)
|
|
130
|
+
`);
|
|
131
|
+
await database.execute(sql `
|
|
132
|
+
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('managers')} (
|
|
133
|
+
id UUID PRIMARY KEY,
|
|
134
|
+
type TEXT NOT NULL CHECK (type = 'manager'),
|
|
135
|
+
department TEXT NOT NULL,
|
|
136
|
+
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('staff')} (id, type) ON DELETE CASCADE
|
|
137
|
+
)
|
|
138
|
+
`);
|
|
139
|
+
});
|
|
140
|
+
test('should insert into both parent and child tables', async () => {
|
|
141
|
+
await truncateTables(database, schema, ['users']);
|
|
142
|
+
await runInInjectionContext(injector, async () => {
|
|
143
|
+
const repository = injectRepository(Admin);
|
|
144
|
+
const newAdmin = new Admin();
|
|
145
|
+
newAdmin.name = 'Alice';
|
|
146
|
+
newAdmin.role = 'SuperAdmin';
|
|
147
|
+
const inserted = await repository.insert(newAdmin);
|
|
148
|
+
expect(inserted).toBeInstanceOf(Admin);
|
|
149
|
+
expect(inserted.id).toBeDefined();
|
|
150
|
+
expect(inserted.name).toBe('Alice');
|
|
151
|
+
expect(inserted.role).toBe('SuperAdmin');
|
|
152
|
+
expect(inserted.type).toBe('admin');
|
|
153
|
+
expect(inserted.metadata.revision).toBe(1);
|
|
154
|
+
// Verify DB state
|
|
155
|
+
const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
156
|
+
expect(userRow).toBeDefined();
|
|
157
|
+
expect(userRow.type).toBe('admin');
|
|
158
|
+
expect(userRow.name).toBe('Alice');
|
|
159
|
+
expect(userRow.revision).toBe(1);
|
|
160
|
+
const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
|
|
161
|
+
expect(adminRow).toBeDefined();
|
|
162
|
+
expect(adminRow.type).toBe('admin');
|
|
163
|
+
expect(adminRow.role).toBe('SuperAdmin');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
test('should insert many into both parent and child tables', async () => {
|
|
167
|
+
await truncateTables(database, schema, ['users']);
|
|
168
|
+
await runInInjectionContext(injector, async () => {
|
|
169
|
+
const repository = injectRepository(Admin);
|
|
170
|
+
const admins = [
|
|
171
|
+
Object.assign(new Admin(), { name: 'Bob', role: 'Admin' }),
|
|
172
|
+
Object.assign(new Admin(), { name: 'Charlie', role: 'Moderator' }),
|
|
173
|
+
];
|
|
174
|
+
const insertedAdmins = await repository.insertMany(admins);
|
|
175
|
+
expect(insertedAdmins).toHaveLength(2);
|
|
176
|
+
expect(insertedAdmins[0].name).toBe('Bob');
|
|
177
|
+
expect(insertedAdmins[1].name).toBe('Charlie');
|
|
178
|
+
expect(insertedAdmins[0].type).toBe('admin');
|
|
179
|
+
expect(insertedAdmins[1].type).toBe('admin');
|
|
180
|
+
for (const inserted of insertedAdmins) {
|
|
181
|
+
const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
182
|
+
expect(userRow.name).toBe(inserted.name);
|
|
183
|
+
const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
|
|
184
|
+
expect(adminRow.role).toBe(inserted.role);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
test('should update both parent and child tables', async () => {
|
|
189
|
+
await truncateTables(database, schema, ['users']);
|
|
190
|
+
await runInInjectionContext(injector, async () => {
|
|
191
|
+
const repository = injectRepository(Admin);
|
|
192
|
+
const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
|
|
193
|
+
const inserted = await repository.insert(newAdmin);
|
|
194
|
+
const update = { name: 'Alice Updated', role: 'MegaAdmin' };
|
|
195
|
+
const updated = await repository.update(inserted.id, update);
|
|
196
|
+
expect(updated.name).toBe('Alice Updated');
|
|
197
|
+
expect(updated.role).toBe('MegaAdmin');
|
|
198
|
+
expect(updated.metadata.revision).toBe(2);
|
|
199
|
+
// Verify DB state
|
|
200
|
+
const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
201
|
+
expect(userRow.name).toBe('Alice Updated');
|
|
202
|
+
expect(userRow.revision).toBe(2);
|
|
203
|
+
const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
|
|
204
|
+
expect(adminRow.role).toBe('MegaAdmin');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
test('should soft delete from parent table', async () => {
|
|
208
|
+
await truncateTables(database, schema, ['users']);
|
|
209
|
+
await runInInjectionContext(injector, async () => {
|
|
210
|
+
const repository = injectRepository(Admin);
|
|
211
|
+
const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
|
|
212
|
+
const inserted = await repository.insert(newAdmin);
|
|
213
|
+
await repository.delete(inserted.id);
|
|
214
|
+
// Verify DB state
|
|
215
|
+
const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
216
|
+
expect(userRow.delete_timestamp).not.toBeNull();
|
|
217
|
+
// Child table should still have the row (soft delete only affects parent)
|
|
218
|
+
const { rows: [adminRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
|
|
219
|
+
expect(adminRow).toBeDefined();
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
test('should hard delete from both tables via cascade', async () => {
|
|
223
|
+
await truncateTables(database, schema, ['users']);
|
|
224
|
+
await runInInjectionContext(injector, async () => {
|
|
225
|
+
const repository = injectRepository(Admin);
|
|
226
|
+
const newAdmin = Object.assign(new Admin(), { name: 'Alice', role: 'SuperAdmin' });
|
|
227
|
+
const inserted = await repository.insert(newAdmin);
|
|
228
|
+
await repository.hardDelete(inserted.id);
|
|
229
|
+
// Verify DB state
|
|
230
|
+
const { rows: userRows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
231
|
+
expect(userRows).toHaveLength(0);
|
|
232
|
+
const { rows: adminRows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('admins')} WHERE id = ${inserted.id}`);
|
|
233
|
+
expect(adminRows).toHaveLength(0);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
test('should load entities polymorphically from parent repository', async () => {
|
|
237
|
+
await truncateTables(database, schema, ['users']);
|
|
238
|
+
await runInInjectionContext(injector, async () => {
|
|
239
|
+
const adminRepository = injectRepository(Admin);
|
|
240
|
+
const guestRepository = injectRepository(Guest);
|
|
241
|
+
const userRepository = injectRepository(BaseUser);
|
|
242
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'Admin1', role: 'Super' }));
|
|
243
|
+
await guestRepository.insert(Object.assign(new Guest(), { name: 'Guest1', permissions: 'Read' }));
|
|
244
|
+
// Load without subclasses (default)
|
|
245
|
+
const users = await userRepository.loadAll();
|
|
246
|
+
expect(users).toHaveLength(2);
|
|
247
|
+
expect(users[0]).toBeInstanceOf(BaseUser);
|
|
248
|
+
expect(users[1]).toBeInstanceOf(BaseUser);
|
|
249
|
+
expect(users[0].role).toBeUndefined();
|
|
250
|
+
// Load with subclasses
|
|
251
|
+
const polymorphicUsers = await userRepository.loadAll({ includeSubclasses: true });
|
|
252
|
+
expect(polymorphicUsers).toHaveLength(2);
|
|
253
|
+
const admin = polymorphicUsers.find((u) => u instanceof Admin);
|
|
254
|
+
const guest = polymorphicUsers.find((u) => u instanceof Guest);
|
|
255
|
+
expect(admin).toBeDefined();
|
|
256
|
+
expect(admin).toBeInstanceOf(Admin);
|
|
257
|
+
expect(admin.name).toBe('Admin1');
|
|
258
|
+
expect(admin.role).toBe('Super');
|
|
259
|
+
expect(guest).toBeDefined();
|
|
260
|
+
expect(guest).toBeInstanceOf(Guest);
|
|
261
|
+
expect(guest.name).toBe('Guest1');
|
|
262
|
+
expect(guest).toBeInstanceOf(Guest);
|
|
263
|
+
expect(guest.name).toBe('Guest1');
|
|
264
|
+
expect(guest.permissions).toBe('Read');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
test('should load polymorphic subset from parent repository', async () => {
|
|
268
|
+
await truncateTables(database, schema, ['users']);
|
|
269
|
+
await runInInjectionContext(injector, async () => {
|
|
270
|
+
const adminRepository = injectRepository(Admin);
|
|
271
|
+
const guestRepository = injectRepository(Guest);
|
|
272
|
+
const userRepository = injectRepository(BaseUser);
|
|
273
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'Admin1', role: 'Super' }));
|
|
274
|
+
await guestRepository.insert(Object.assign(new Guest(), { name: 'Guest1', permissions: 'Read' }));
|
|
275
|
+
// Load ONLY Admins polymorphically
|
|
276
|
+
const onlyAdmins = await userRepository.loadManyByQuery({}, { includeSubclasses: [Admin] });
|
|
277
|
+
expect(onlyAdmins).toHaveLength(2); // Still returns all users from base table
|
|
278
|
+
const admin = onlyAdmins.find((u) => u instanceof Admin);
|
|
279
|
+
const guestAsBase = onlyAdmins.find((u) => u.name === 'Guest1');
|
|
280
|
+
expect(admin).toBeInstanceOf(Admin);
|
|
281
|
+
expect(admin.role).toBe('Super');
|
|
282
|
+
expect(guestAsBase).not.toBeInstanceOf(Guest);
|
|
283
|
+
expect(guestAsBase).toBeInstanceOf(BaseUser);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
test('should count and check existence for child entities', async () => {
|
|
287
|
+
await truncateTables(database, schema, ['users']);
|
|
288
|
+
await runInInjectionContext(injector, async () => {
|
|
289
|
+
const adminRepository = injectRepository(Admin);
|
|
290
|
+
const guestRepository = injectRepository(Guest);
|
|
291
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'Admin1', role: 'Super' }));
|
|
292
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'Admin2', role: 'Normal' }));
|
|
293
|
+
await guestRepository.insert(Object.assign(new Guest(), { name: 'Guest1', permissions: 'Read' }));
|
|
294
|
+
expect(await adminRepository.count()).toBe(2);
|
|
295
|
+
expect(await guestRepository.count()).toBe(1);
|
|
296
|
+
const admins = await adminRepository.loadAll();
|
|
297
|
+
expect(await adminRepository.has(admins[0].id)).toBe(true);
|
|
298
|
+
expect(await adminRepository.hasByQuery({ name: 'Admin2' })).toBe(true);
|
|
299
|
+
expect(await adminRepository.hasByQuery({ name: 'Guest1' })).toBe(false); // Different table
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
test('should query child entities by parent fields', async () => {
|
|
303
|
+
await truncateTables(database, schema, ['users']);
|
|
304
|
+
await runInInjectionContext(injector, async () => {
|
|
305
|
+
const adminRepository = injectRepository(Admin);
|
|
306
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'TargetAdmin', role: 'Super' }));
|
|
307
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'OtherAdmin', role: 'Normal' }));
|
|
308
|
+
const results = await adminRepository.loadManyByQuery({ name: 'TargetAdmin' });
|
|
309
|
+
expect(results).toHaveLength(1);
|
|
310
|
+
expect(results[0].name).toBe('TargetAdmin');
|
|
311
|
+
expect(results[0].role).toBe('Super');
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
test('should perform partial updates on parent or child fields', async () => {
|
|
315
|
+
await truncateTables(database, schema, ['users']);
|
|
316
|
+
await runInInjectionContext(injector, async () => {
|
|
317
|
+
const adminRepository = injectRepository(Admin);
|
|
318
|
+
const inserted = await adminRepository.insert(Object.assign(new Admin(), { name: 'Alice', role: 'Super' }));
|
|
319
|
+
// Update only parent field
|
|
320
|
+
await adminRepository.update(inserted.id, { name: 'Alice Renamed' });
|
|
321
|
+
let updated = await adminRepository.load(inserted.id);
|
|
322
|
+
expect(updated.name).toBe('Alice Renamed');
|
|
323
|
+
expect(updated.role).toBe('Super');
|
|
324
|
+
// Update only child field
|
|
325
|
+
await adminRepository.update(inserted.id, { role: 'Demoted' });
|
|
326
|
+
updated = await adminRepository.load(inserted.id);
|
|
327
|
+
expect(updated.name).toBe('Alice Renamed');
|
|
328
|
+
expect(updated.role).toBe('Demoted');
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
test('should fail when violating discriminator check constraint', async () => {
|
|
332
|
+
// Attempt manual insert with mismatched type
|
|
333
|
+
const query = database.execute(sql `
|
|
334
|
+
INSERT INTO ${sql.identifier(schema)}.${sql.identifier('admins')} (id, type, role)
|
|
335
|
+
VALUES (gen_random_uuid(), 'guest', 'Invalid')
|
|
336
|
+
`);
|
|
337
|
+
await expect(query).rejects.toThrow();
|
|
338
|
+
});
|
|
339
|
+
test('should fail when violating composite foreign key', async () => {
|
|
340
|
+
// Insert user with type 'guest'
|
|
341
|
+
const userId = '00000000-0000-0000-0000-000000000001';
|
|
342
|
+
await database.execute(sql `
|
|
343
|
+
INSERT INTO ${sql.identifier(schema)}.${sql.identifier('users')} (id, type, name, revision, revision_timestamp, create_timestamp)
|
|
344
|
+
VALUES (${userId}, 'guest', 'Guest User', 1, now(), now())
|
|
345
|
+
`);
|
|
346
|
+
// Attempt to insert admin pointing to that user (mismatched type 'admin' vs 'guest')
|
|
347
|
+
const query = database.execute(sql `
|
|
348
|
+
INSERT INTO ${sql.identifier(schema)}.${sql.identifier('admins')} (id, type, role)
|
|
349
|
+
VALUES (${userId}, 'admin', 'Admin Role')
|
|
350
|
+
`);
|
|
351
|
+
await expect(query).rejects.toThrow();
|
|
352
|
+
});
|
|
353
|
+
test('should support nested inheritance', async () => {
|
|
354
|
+
await truncateTables(database, schema, ['users']);
|
|
355
|
+
await runInInjectionContext(injector, async () => {
|
|
356
|
+
const managerRepository = injectRepository(Manager);
|
|
357
|
+
const manager = new Manager();
|
|
358
|
+
manager.name = 'Big Boss';
|
|
359
|
+
manager.employeeId = 'EMP001';
|
|
360
|
+
manager.department = 'Executive';
|
|
361
|
+
const inserted = await managerRepository.insert(manager);
|
|
362
|
+
expect(inserted.name).toBe('Big Boss');
|
|
363
|
+
expect(inserted.employeeId).toBe('EMP001');
|
|
364
|
+
expect(inserted.department).toBe('Executive');
|
|
365
|
+
expect(inserted.type).toBe('manager');
|
|
366
|
+
// Verify DB state - all 3 tables should have rows
|
|
367
|
+
const { rows: [userRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
368
|
+
expect(userRow.name).toBe('Big Boss');
|
|
369
|
+
const { rows: [staffRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('staff')} WHERE id = ${inserted.id}`);
|
|
370
|
+
expect(staffRow.employee_id).toBe('EMP001');
|
|
371
|
+
const { rows: [managerRow] } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('managers')} WHERE id = ${inserted.id}`);
|
|
372
|
+
expect(managerRow.department).toBe('Executive');
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
test('should rollback parent insert if child insert fails', async () => {
|
|
376
|
+
await truncateTables(database, schema, ['users']);
|
|
377
|
+
await runInInjectionContext(injector, async () => {
|
|
378
|
+
const adminRepository = injectRepository(Admin);
|
|
379
|
+
// Attempt to insert an admin with a missing role (should fail because of NOT NULL)
|
|
380
|
+
const invalidAdmin = new Admin();
|
|
381
|
+
invalidAdmin.name = 'Broken Admin';
|
|
382
|
+
// role is missing
|
|
383
|
+
await expect(adminRepository.insert(invalidAdmin)).rejects.toThrow();
|
|
384
|
+
// Verify that NO row was created in the users table
|
|
385
|
+
const { rows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')}`);
|
|
386
|
+
expect(rows).toHaveLength(0);
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
test('should count and check existence polymorphically', async () => {
|
|
390
|
+
await truncateTables(database, schema, ['users']);
|
|
391
|
+
await runInInjectionContext(injector, async () => {
|
|
392
|
+
const adminRepository = injectRepository(Admin);
|
|
393
|
+
const guestRepository = injectRepository(Guest);
|
|
394
|
+
const userRepository = injectRepository(BaseUser);
|
|
395
|
+
await adminRepository.insert(Object.assign(new Admin(), { name: 'A1', role: 'R1' }));
|
|
396
|
+
await guestRepository.insert(Object.assign(new Guest(), { name: 'G1', permissions: 'P1' }));
|
|
397
|
+
expect(await userRepository.count()).toBe(2);
|
|
398
|
+
expect(await userRepository.hasByQuery({ name: 'A1' })).toBe(true);
|
|
399
|
+
expect(await userRepository.hasByQuery({ name: 'G1' })).toBe(true);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
test('should load many by IDs polymorphically', async () => {
|
|
403
|
+
await truncateTables(database, schema, ['users']);
|
|
404
|
+
await runInInjectionContext(injector, async () => {
|
|
405
|
+
const adminRepository = injectRepository(Admin);
|
|
406
|
+
const guestRepository = injectRepository(Guest);
|
|
407
|
+
const userRepository = injectRepository(BaseUser);
|
|
408
|
+
const a1 = await adminRepository.insert(Object.assign(new Admin(), { name: 'A1', role: 'R1' }));
|
|
409
|
+
const g1 = await guestRepository.insert(Object.assign(new Guest(), { name: 'G1', permissions: 'P1' }));
|
|
410
|
+
const results = await userRepository.loadMany([a1.id, g1.id], { includeSubclasses: true });
|
|
411
|
+
expect(results).toHaveLength(2);
|
|
412
|
+
expect(results.find((u) => u.id === a1.id)).toBeInstanceOf(Admin);
|
|
413
|
+
expect(results.find((u) => u.id === g1.id)).toBeInstanceOf(Guest);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
test('should update many child entities', async () => {
|
|
417
|
+
await truncateTables(database, schema, ['users']);
|
|
418
|
+
await runInInjectionContext(injector, async () => {
|
|
419
|
+
const adminRepository = injectRepository(Admin);
|
|
420
|
+
const a1 = await adminRepository.insert(Object.assign(new Admin(), { name: 'A1', role: 'Old' }));
|
|
421
|
+
const a2 = await adminRepository.insert(Object.assign(new Admin(), { name: 'A2', role: 'Old' }));
|
|
422
|
+
await adminRepository.updateMany([a1.id, a2.id], { role: 'New' });
|
|
423
|
+
const results = await adminRepository.loadMany([a1.id, a2.id]);
|
|
424
|
+
expect(results[0].role).toBe('New');
|
|
425
|
+
expect(results[1].role).toBe('New');
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
test('should update nested inheritance fields', async () => {
|
|
429
|
+
await truncateTables(database, schema, ['users']);
|
|
430
|
+
await runInInjectionContext(injector, async () => {
|
|
431
|
+
const managerRepository = injectRepository(Manager);
|
|
432
|
+
const manager = Object.assign(new Manager(), { name: 'Boss', employeeId: 'E1', department: 'D1' });
|
|
433
|
+
const inserted = await managerRepository.insert(manager);
|
|
434
|
+
await managerRepository.update(inserted.id, { name: 'New Boss', employeeId: 'E2', department: 'D2' });
|
|
435
|
+
const updated = await managerRepository.load(inserted.id);
|
|
436
|
+
expect(updated.name).toBe('New Boss');
|
|
437
|
+
expect(updated.employeeId).toBe('E2');
|
|
438
|
+
expect(updated.department).toBe('D2');
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
test('should delete from nested inheritance tables', async () => {
|
|
442
|
+
await truncateTables(database, schema, ['users']);
|
|
443
|
+
await runInInjectionContext(injector, async () => {
|
|
444
|
+
const managerRepository = injectRepository(Manager);
|
|
445
|
+
const manager = Object.assign(new Manager(), { name: 'Boss', employeeId: 'E1', department: 'D1' });
|
|
446
|
+
const inserted = await managerRepository.insert(manager);
|
|
447
|
+
await managerRepository.hardDelete(inserted.id);
|
|
448
|
+
const { rows: userRows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('users')} WHERE id = ${inserted.id}`);
|
|
449
|
+
const { rows: staffRows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('staff')} WHERE id = ${inserted.id}`);
|
|
450
|
+
const { rows: managerRows } = await database.execute(sql `SELECT * FROM ${sql.identifier(schema)}.${sql.identifier('managers')} WHERE id = ${inserted.id}`);
|
|
451
|
+
expect(userRows).toHaveLength(0);
|
|
452
|
+
expect(staffRows).toHaveLength(0);
|
|
453
|
+
expect(managerRows).toHaveLength(0);
|
|
454
|
+
});
|
|
455
|
+
});
|
|
456
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|