@tstdl/base 0.93.182 → 0.93.183
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/server/api-request-token.provider.js +1 -1
- package/api/server/gateway.js +6 -1
- package/authentication/authentication.api.d.ts +13 -40
- package/authentication/authentication.api.js +5 -14
- package/authentication/client/authentication.service.d.ts +6 -14
- package/authentication/client/authentication.service.js +22 -4
- package/authentication/client/module.d.ts +1 -1
- package/authentication/client/module.js +4 -4
- package/authentication/models/index.d.ts +1 -0
- package/authentication/models/index.js +1 -0
- package/authentication/models/totp-results.model.d.ts +11 -0
- package/authentication/models/totp-results.model.js +37 -0
- package/authentication/server/authentication.api-controller.d.ts +3 -3
- package/authentication/server/authentication.api-controller.js +31 -4
- package/authentication/server/authentication.service.d.ts +5 -14
- package/authentication/server/authentication.service.js +6 -4
- package/core.d.ts +0 -5
- package/core.js +0 -8
- package/document-management/api/document-management.api.d.ts +2 -2
- package/document-management/service-models/document.service-model.d.ts +1 -1
- package/examples/config.d.ts +25 -0
- package/examples/config.js +26 -0
- package/notification/server/module.d.ts +1 -1
- package/notification/server/module.js +1 -1
- package/package.json +5 -5
- package/signals/api.d.ts +5 -1
- package/signals/api.js +3 -1
- package/signals/implementation/api.d.ts +13 -5
- package/signals/implementation/api.js +7 -1
- package/signals/implementation/asserts.d.ts +2 -2
- package/signals/implementation/asserts.js +3 -3
- package/signals/implementation/computed.d.ts +7 -34
- package/signals/implementation/computed.js +14 -83
- package/signals/implementation/configure.js +6 -2
- package/signals/implementation/effect.d.ts +65 -46
- package/signals/implementation/effect.js +97 -62
- package/signals/implementation/index.d.ts +2 -4
- package/signals/implementation/index.js +2 -4
- package/signals/implementation/linked_signal.d.ts +36 -0
- package/signals/implementation/linked_signal.js +34 -0
- package/signals/implementation/primitive/computed.d.ts +55 -0
- package/signals/implementation/primitive/computed.js +107 -0
- package/signals/implementation/primitive/effect.d.ts +26 -0
- package/signals/implementation/primitive/effect.js +31 -0
- package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
- package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
- package/signals/implementation/primitive/errors.d.ts +10 -0
- package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
- package/signals/implementation/primitive/formatter.d.ts +19 -0
- package/signals/implementation/primitive/formatter.js +136 -0
- package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
- package/signals/implementation/primitive/graph.js +386 -0
- package/signals/implementation/primitive/linked_signal.d.ts +46 -0
- package/signals/implementation/primitive/linked_signal.js +110 -0
- package/signals/implementation/primitive/signal.d.ts +31 -0
- package/signals/implementation/primitive/signal.js +80 -0
- package/signals/implementation/primitive/untracked.d.ts +12 -0
- package/signals/implementation/primitive/untracked.js +23 -0
- package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
- package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
- package/signals/implementation/resource/api.d.ts +275 -0
- package/signals/implementation/resource/api.js +26 -0
- package/signals/implementation/resource/debounce.d.ts +13 -0
- package/signals/implementation/resource/debounce.js +113 -0
- package/signals/implementation/resource/from_snapshots.d.ts +16 -0
- package/signals/implementation/resource/from_snapshots.js +44 -0
- package/signals/implementation/resource/index.d.ts +11 -0
- package/signals/implementation/resource/index.js +11 -0
- package/signals/implementation/resource/resource.d.ts +110 -0
- package/signals/implementation/resource/resource.js +402 -0
- package/signals/implementation/root_effect_scheduler.d.ts +50 -0
- package/signals/implementation/root_effect_scheduler.js +66 -0
- package/signals/implementation/signal.d.ts +42 -18
- package/signals/implementation/signal.js +29 -49
- package/signals/implementation/to-observable.d.ts +12 -5
- package/signals/implementation/to-observable.js +12 -2
- package/signals/implementation/to-signal.d.ts +9 -18
- package/signals/implementation/to-signal.js +46 -13
- package/signals/implementation/untracked.d.ts +1 -1
- package/signals/implementation/untracked.js +3 -11
- package/signals/operators/debounce.d.ts +8 -0
- package/signals/operators/debounce.js +19 -0
- package/signals/operators/derive-async.js +43 -15
- package/signals/operators/index.d.ts +2 -0
- package/signals/operators/index.js +2 -0
- package/signals/operators/throttle.d.ts +8 -0
- package/signals/operators/throttle.js +31 -0
- package/ai/genkit/tests/multi-region.test.d.ts +0 -2
- package/ai/genkit/tests/multi-region.test.js +0 -179
- package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
- package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
- package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
- package/ai/prompts/tests/prompt-builder.test.js +0 -22
- package/ai/tests/instructions-formatter.test.d.ts +0 -1
- package/ai/tests/instructions-formatter.test.js +0 -116
- package/ai/tests/steering.test.d.ts +0 -1
- package/ai/tests/steering.test.js +0 -37
- package/api/client/tests/api-client.test.d.ts +0 -1
- package/api/client/tests/api-client.test.js +0 -194
- package/api/server/tests/csrf.middleware.test.d.ts +0 -1
- package/api/server/tests/csrf.middleware.test.js +0 -91
- package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
- package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
- package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
- package/authentication/tests/authentication.api-controller.test.js +0 -156
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
- package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
- package/authentication/tests/authentication.client-error-handling.test.js +0 -123
- package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
- package/authentication/tests/authentication.client-middleware.test.js +0 -118
- package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-methods.test.js +0 -177
- package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
- package/authentication/tests/authentication.client-service.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service.test.js +0 -76
- package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
- package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
- package/authentication/tests/authentication.service.test.d.ts +0 -1
- package/authentication/tests/authentication.service.test.js +0 -167
- package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
- package/authentication/tests/authentication.test-ancillary-service.js +0 -27
- package/authentication/tests/brute-force-protection.test.d.ts +0 -1
- package/authentication/tests/brute-force-protection.test.js +0 -211
- package/authentication/tests/helper.test.d.ts +0 -1
- package/authentication/tests/helper.test.js +0 -122
- package/authentication/tests/password-requirements.error.test.d.ts +0 -1
- package/authentication/tests/password-requirements.error.test.js +0 -14
- package/authentication/tests/remember.api.test.d.ts +0 -1
- package/authentication/tests/remember.api.test.js +0 -117
- package/authentication/tests/remember.service.test.d.ts +0 -1
- package/authentication/tests/remember.service.test.js +0 -83
- package/authentication/tests/subject.service.test.d.ts +0 -1
- package/authentication/tests/subject.service.test.js +0 -140
- package/authentication/tests/suspended-subject.test.d.ts +0 -1
- package/authentication/tests/suspended-subject.test.js +0 -120
- package/authentication/tests/totp.enrollment.test.d.ts +0 -1
- package/authentication/tests/totp.enrollment.test.js +0 -123
- package/authentication/tests/totp.login.test.d.ts +0 -1
- package/authentication/tests/totp.login.test.js +0 -213
- package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
- package/authentication/tests/totp.recovery-codes.test.js +0 -97
- package/authentication/tests/totp.status.test.d.ts +0 -1
- package/authentication/tests/totp.status.test.js +0 -72
- package/cancellation/tests/coverage.test.d.ts +0 -1
- package/cancellation/tests/coverage.test.js +0 -49
- package/cancellation/tests/leak.test.d.ts +0 -1
- package/cancellation/tests/leak.test.js +0 -35
- package/cancellation/tests/token.test.d.ts +0 -1
- package/cancellation/tests/token.test.js +0 -136
- package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
- package/cryptography/tests/cryptography.test.d.ts +0 -1
- package/cryptography/tests/cryptography.test.js +0 -175
- package/cryptography/tests/jwt.test.d.ts +0 -1
- package/cryptography/tests/jwt.test.js +0 -54
- package/cryptography/tests/modern.test.d.ts +0 -1
- package/cryptography/tests/modern.test.js +0 -105
- package/cryptography/tests/module.test.d.ts +0 -1
- package/cryptography/tests/module.test.js +0 -100
- package/cryptography/tests/totp.test.d.ts +0 -1
- package/cryptography/tests/totp.test.js +0 -108
- package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
- package/document-management/tests/ai-config-hierarchy.test.js +0 -59
- package/document-management/tests/ai-config-integration.test.d.ts +0 -1
- package/document-management/tests/ai-config-integration.test.js +0 -125
- package/document-management/tests/ai-config-merge.test.d.ts +0 -1
- package/document-management/tests/ai-config-merge.test.js +0 -46
- package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-management-ai-overrides.test.js +0 -63
- package/document-management/tests/document-management-core.test.d.ts +0 -1
- package/document-management/tests/document-management-core.test.js +0 -157
- package/document-management/tests/document-management.api.test.d.ts +0 -1
- package/document-management/tests/document-management.api.test.js +0 -101
- package/document-management/tests/document-statistics.service.test.d.ts +0 -1
- package/document-management/tests/document-statistics.service.test.js +0 -498
- package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
- package/document-management/tests/document.service.test.d.ts +0 -1
- package/document-management/tests/document.service.test.js +0 -143
- package/document-management/tests/enum-helpers.test.d.ts +0 -1
- package/document-management/tests/enum-helpers.test.js +0 -452
- package/document-management/tests/helper.d.ts +0 -24
- package/document-management/tests/helper.js +0 -39
- package/errors/tests/format.test.d.ts +0 -1
- package/errors/tests/format.test.js +0 -84
- package/http/tests/server-timing.test.d.ts +0 -1
- package/http/tests/server-timing.test.js +0 -42
- package/injector/tests/advanced.test.d.ts +0 -1
- package/injector/tests/advanced.test.js +0 -116
- package/injector/tests/async-init.test.d.ts +0 -1
- package/injector/tests/async-init.test.js +0 -77
- package/injector/tests/basic.test.d.ts +0 -1
- package/injector/tests/basic.test.js +0 -114
- package/injector/tests/hierarchical.test.d.ts +0 -1
- package/injector/tests/hierarchical.test.js +0 -59
- package/injector/tests/leak.test.d.ts +0 -1
- package/injector/tests/leak.test.js +0 -45
- package/injector/tests/lifecycles.test.d.ts +0 -1
- package/injector/tests/lifecycles.test.js +0 -109
- package/logger/tests/pretty-print.test.d.ts +0 -1
- package/logger/tests/pretty-print.test.js +0 -60
- package/notification/tests/notification-api.test.d.ts +0 -1
- package/notification/tests/notification-api.test.js +0 -124
- package/notification/tests/notification-client.test.d.ts +0 -1
- package/notification/tests/notification-client.test.js +0 -101
- package/notification/tests/notification-flow.test.d.ts +0 -1
- package/notification/tests/notification-flow.test.js +0 -296
- package/notification/tests/notification-sse.service.test.d.ts +0 -1
- package/notification/tests/notification-sse.service.test.js +0 -43
- package/notification/tests/notification-type.service.test.d.ts +0 -1
- package/notification/tests/notification-type.service.test.js +0 -41
- package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
- package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
- package/orm/tests/build-jsonb.test.d.ts +0 -1
- package/orm/tests/build-jsonb.test.js +0 -39
- package/orm/tests/data-types.test.d.ts +0 -1
- package/orm/tests/data-types.test.js +0 -39
- package/orm/tests/database-extension.test.d.ts +0 -1
- package/orm/tests/database-extension.test.js +0 -63
- package/orm/tests/database-migration.test.d.ts +0 -1
- package/orm/tests/database-migration.test.js +0 -83
- package/orm/tests/decorators.test.d.ts +0 -1
- package/orm/tests/decorators.test.js +0 -77
- package/orm/tests/encryption.test.d.ts +0 -1
- package/orm/tests/encryption.test.js +0 -31
- package/orm/tests/query-complex.test.d.ts +0 -1
- package/orm/tests/query-complex.test.js +0 -172
- package/orm/tests/query-converter-complex.test.d.ts +0 -1
- package/orm/tests/query-converter-complex.test.js +0 -131
- package/orm/tests/query-converter.test.d.ts +0 -1
- package/orm/tests/query-converter.test.js +0 -123
- package/orm/tests/repository-advanced.test.d.ts +0 -1
- package/orm/tests/repository-advanced.test.js +0 -189
- package/orm/tests/repository-attributes.test.d.ts +0 -1
- package/orm/tests/repository-attributes.test.js +0 -83
- package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
- package/orm/tests/repository-compound-primary-key.test.js +0 -226
- package/orm/tests/repository-comprehensive.test.d.ts +0 -1
- package/orm/tests/repository-comprehensive.test.js +0 -162
- package/orm/tests/repository-coverage.test.d.ts +0 -2
- package/orm/tests/repository-coverage.test.js +0 -242
- package/orm/tests/repository-cti-complex.test.d.ts +0 -1
- package/orm/tests/repository-cti-complex.test.js +0 -151
- package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
- package/orm/tests/repository-cti-embedded.test.js +0 -178
- package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
- package/orm/tests/repository-cti-extensive.test.js +0 -279
- package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
- package/orm/tests/repository-cti-mapping.test.js +0 -108
- package/orm/tests/repository-cti-search.test.d.ts +0 -1
- package/orm/tests/repository-cti-search.test.js +0 -141
- package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
- package/orm/tests/repository-cti-soft-delete.test.js +0 -103
- package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
- package/orm/tests/repository-cti-transactions.test.js +0 -112
- package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
- package/orm/tests/repository-cti-upsert-many.test.js +0 -115
- package/orm/tests/repository-cti.test.d.ts +0 -2
- package/orm/tests/repository-cti.test.js +0 -390
- package/orm/tests/repository-edge-cases.test.d.ts +0 -1
- package/orm/tests/repository-edge-cases.test.js +0 -178
- package/orm/tests/repository-expiration.test.d.ts +0 -2
- package/orm/tests/repository-expiration.test.js +0 -140
- package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
- package/orm/tests/repository-extra-coverage.test.js +0 -402
- package/orm/tests/repository-mapping.test.d.ts +0 -2
- package/orm/tests/repository-mapping.test.js +0 -65
- package/orm/tests/repository-regression.test.d.ts +0 -1
- package/orm/tests/repository-regression.test.js +0 -288
- package/orm/tests/repository-search-coverage.test.d.ts +0 -1
- package/orm/tests/repository-search-coverage.test.js +0 -107
- package/orm/tests/repository-search.test.d.ts +0 -1
- package/orm/tests/repository-search.test.js +0 -105
- package/orm/tests/repository-soft-delete.test.d.ts +0 -1
- package/orm/tests/repository-soft-delete.test.js +0 -118
- package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
- package/orm/tests/repository-transactions-nested.test.js +0 -178
- package/orm/tests/repository-types.test.d.ts +0 -1
- package/orm/tests/repository-types.test.js +0 -184
- package/orm/tests/repository-undelete.test.d.ts +0 -2
- package/orm/tests/repository-undelete.test.js +0 -201
- package/orm/tests/schema-converter.test.d.ts +0 -1
- package/orm/tests/schema-converter.test.js +0 -82
- package/orm/tests/schema-generation.test.d.ts +0 -2
- package/orm/tests/schema-generation.test.js +0 -174
- package/orm/tests/sql-helpers.test.d.ts +0 -1
- package/orm/tests/sql-helpers.test.js +0 -67
- package/orm/tests/transaction-safety.test.d.ts +0 -1
- package/orm/tests/transaction-safety.test.js +0 -81
- package/orm/tests/transactional.test.d.ts +0 -1
- package/orm/tests/transactional.test.js +0 -215
- package/orm/tests/utils.test.d.ts +0 -1
- package/orm/tests/utils.test.js +0 -70
- package/pdf/tests/utils.test.d.ts +0 -1
- package/pdf/tests/utils.test.js +0 -187
- package/process/tests/spawn.test.d.ts +0 -1
- package/process/tests/spawn.test.js +0 -182
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
- package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
- package/renderer/tests/renderer.test.d.ts +0 -1
- package/renderer/tests/renderer.test.js +0 -88
- package/rpc/tests/rpc.integration.test.d.ts +0 -1
- package/rpc/tests/rpc.integration.test.js +0 -615
- package/signals/implementation/errors.d.ts +0 -2
- package/signals/implementation/graph.js +0 -312
- package/signals/implementation/writable-signal.d.ts +0 -48
- package/signals/implementation/writable-signal.js +0 -32
- package/task-queue/tests/coverage-branch.test.d.ts +0 -1
- package/task-queue/tests/coverage-branch.test.js +0 -395
- package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
- package/task-queue/tests/coverage-enhancement.test.js +0 -150
- package/task-queue/tests/dag.test.d.ts +0 -1
- package/task-queue/tests/dag.test.js +0 -188
- package/task-queue/tests/dependencies.test.d.ts +0 -1
- package/task-queue/tests/dependencies.test.js +0 -296
- package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
- package/task-queue/tests/enqueue-batch.test.js +0 -125
- package/task-queue/tests/enqueue-item.test.d.ts +0 -1
- package/task-queue/tests/enqueue-item.test.js +0 -12
- package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
- package/task-queue/tests/fan-out-spawning.test.js +0 -94
- package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
- package/task-queue/tests/idempotent-replacement.test.js +0 -114
- package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
- package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
- package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
- package/task-queue/tests/optimization-edge-cases.test.js +0 -124
- package/task-queue/tests/queue-generic.test.d.ts +0 -1
- package/task-queue/tests/queue-generic.test.js +0 -8
- package/task-queue/tests/queue.test.d.ts +0 -1
- package/task-queue/tests/queue.test.js +0 -756
- package/task-queue/tests/shutdown.test.d.ts +0 -1
- package/task-queue/tests/shutdown.test.js +0 -41
- package/task-queue/tests/task-context.test.d.ts +0 -1
- package/task-queue/tests/task-context.test.js +0 -7
- package/task-queue/tests/task-union.test.d.ts +0 -1
- package/task-queue/tests/task-union.test.js +0 -18
- package/task-queue/tests/transactions.test.d.ts +0 -1
- package/task-queue/tests/transactions.test.js +0 -47
- package/task-queue/tests/typing.test.d.ts +0 -1
- package/task-queue/tests/typing.test.js +0 -9
- package/task-queue/tests/worker.test.d.ts +0 -1
- package/task-queue/tests/worker.test.js +0 -258
- package/task-queue/tests/zombie-parent.test.d.ts +0 -1
- package/task-queue/tests/zombie-parent.test.js +0 -45
- package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
- package/task-queue/tests/zombie-recovery.test.js +0 -51
- package/utils/tests/backoff.test.d.ts +0 -1
- package/utils/tests/backoff.test.js +0 -41
- package/utils/tests/retry-with-backoff.test.d.ts +0 -1
- package/utils/tests/retry-with-backoff.test.js +0 -49
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
/** biome-ignore-all lint/nursery/noExcessiveClassesPerFile: <explanation> */
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
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;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
import { sql } from 'drizzle-orm';
|
|
12
|
-
import { beforeAll, describe, expect, test } from 'vitest';
|
|
13
|
-
import { StringProperty } from '../../schema/index.js';
|
|
14
|
-
import { setupIntegrationTest } from '../../testing/index.js';
|
|
15
|
-
import { ChildEntity, Column, Inheritance, Table } from '../decorators.js';
|
|
16
|
-
import { BaseEntity, Entity } from '../entity.js';
|
|
17
|
-
import { getRepository } from '../server/index.js';
|
|
18
|
-
describe('ORM Repository Coverage', () => {
|
|
19
|
-
let injector;
|
|
20
|
-
let db;
|
|
21
|
-
let premiumRepo;
|
|
22
|
-
let plainRepo;
|
|
23
|
-
let simpleRepo;
|
|
24
|
-
const schema = 'test_orm_coverage';
|
|
25
|
-
let BaseItem = class BaseItem extends Entity {
|
|
26
|
-
type;
|
|
27
|
-
name;
|
|
28
|
-
};
|
|
29
|
-
__decorate([
|
|
30
|
-
StringProperty(),
|
|
31
|
-
Column({ name: 'type' }),
|
|
32
|
-
__metadata("design:type", String)
|
|
33
|
-
], BaseItem.prototype, "type", void 0);
|
|
34
|
-
__decorate([
|
|
35
|
-
StringProperty(),
|
|
36
|
-
Column({ name: 'name' }),
|
|
37
|
-
__metadata("design:type", String)
|
|
38
|
-
], BaseItem.prototype, "name", void 0);
|
|
39
|
-
BaseItem = __decorate([
|
|
40
|
-
Table('items', { schema }),
|
|
41
|
-
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
42
|
-
], BaseItem);
|
|
43
|
-
let PremiumItem = class PremiumItem extends BaseItem {
|
|
44
|
-
code;
|
|
45
|
-
};
|
|
46
|
-
__decorate([
|
|
47
|
-
StringProperty(),
|
|
48
|
-
Column({ name: 'code' }),
|
|
49
|
-
__metadata("design:type", String)
|
|
50
|
-
], PremiumItem.prototype, "code", void 0);
|
|
51
|
-
PremiumItem = __decorate([
|
|
52
|
-
Table('premium_items', { schema }),
|
|
53
|
-
ChildEntity('premium')
|
|
54
|
-
], PremiumItem);
|
|
55
|
-
let SimpleItem = class SimpleItem extends Entity {
|
|
56
|
-
label;
|
|
57
|
-
};
|
|
58
|
-
__decorate([
|
|
59
|
-
StringProperty(),
|
|
60
|
-
Column({ name: 'label' }),
|
|
61
|
-
__metadata("design:type", String)
|
|
62
|
-
], SimpleItem.prototype, "label", void 0);
|
|
63
|
-
SimpleItem = __decorate([
|
|
64
|
-
Table('simple_items', { schema })
|
|
65
|
-
], SimpleItem);
|
|
66
|
-
let PlainItem = class PlainItem extends BaseEntity {
|
|
67
|
-
description;
|
|
68
|
-
};
|
|
69
|
-
__decorate([
|
|
70
|
-
StringProperty(),
|
|
71
|
-
Column({ name: 'description' }),
|
|
72
|
-
__metadata("design:type", String)
|
|
73
|
-
], PlainItem.prototype, "description", void 0);
|
|
74
|
-
PlainItem = __decorate([
|
|
75
|
-
Table('plain_items', { schema })
|
|
76
|
-
], PlainItem);
|
|
77
|
-
beforeAll(async () => {
|
|
78
|
-
({ injector, database: db } = await setupIntegrationTest({
|
|
79
|
-
orm: { schema },
|
|
80
|
-
}));
|
|
81
|
-
premiumRepo = injector.resolve(getRepository(PremiumItem));
|
|
82
|
-
plainRepo = injector.resolve(getRepository(PlainItem));
|
|
83
|
-
simpleRepo = injector.resolve(getRepository(SimpleItem));
|
|
84
|
-
await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
85
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('premium_items')} CASCADE`);
|
|
86
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('items')} CASCADE`);
|
|
87
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('simple_items')} CASCADE`);
|
|
88
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('plain_items')} CASCADE`);
|
|
89
|
-
await db.execute(sql `
|
|
90
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('items')} (
|
|
91
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
92
|
-
type TEXT NOT NULL,
|
|
93
|
-
name TEXT NOT NULL,
|
|
94
|
-
revision INTEGER NOT NULL,
|
|
95
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
96
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
97
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
98
|
-
attributes JSONB NOT NULL DEFAULT '{}',
|
|
99
|
-
UNIQUE (id, type)
|
|
100
|
-
)
|
|
101
|
-
`);
|
|
102
|
-
await db.execute(sql `
|
|
103
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('premium_items')} (
|
|
104
|
-
id UUID PRIMARY KEY,
|
|
105
|
-
type TEXT NOT NULL CHECK (type = 'premium'),
|
|
106
|
-
code TEXT NOT NULL,
|
|
107
|
-
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('items')} (id, type) ON DELETE CASCADE
|
|
108
|
-
)
|
|
109
|
-
`);
|
|
110
|
-
await db.execute(sql `
|
|
111
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('simple_items')} (
|
|
112
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
113
|
-
label TEXT NOT NULL,
|
|
114
|
-
revision INTEGER NOT NULL,
|
|
115
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
116
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
117
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
118
|
-
attributes JSONB NOT NULL DEFAULT '{}'
|
|
119
|
-
)
|
|
120
|
-
`);
|
|
121
|
-
await db.execute(sql `
|
|
122
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('plain_items')} (
|
|
123
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
124
|
-
description TEXT NOT NULL
|
|
125
|
-
)
|
|
126
|
-
`);
|
|
127
|
-
});
|
|
128
|
-
test('upsertMany on CTI without update object (default update)', async () => {
|
|
129
|
-
const item1 = Object.assign(new PremiumItem(), { name: 'Item 1', code: 'C1' });
|
|
130
|
-
const inserted = await premiumRepo.insert(item1);
|
|
131
|
-
// Create a conflict by using the same ID
|
|
132
|
-
const conflictItem = Object.assign(new PremiumItem(), { id: inserted.id, name: 'Item 1 Updated', code: 'C1' });
|
|
133
|
-
// This should trigger the code path where `update` is undefined in upsertManyCTI
|
|
134
|
-
const upserted = await premiumRepo.upsertMany(['id'], [conflictItem]);
|
|
135
|
-
expect(upserted).toHaveLength(1);
|
|
136
|
-
expect(upserted[0].name).toBe('Item 1 Updated');
|
|
137
|
-
expect(upserted[0].metadata.revision).toBeGreaterThan(inserted.metadata.revision);
|
|
138
|
-
});
|
|
139
|
-
test('upsertMany with empty array', async () => {
|
|
140
|
-
const result = await premiumRepo.upsertMany(['id'], []);
|
|
141
|
-
expect(result).toHaveLength(0);
|
|
142
|
-
});
|
|
143
|
-
test('updateManyByQuery on CTI with no matching rows', async () => {
|
|
144
|
-
// Query matching nothing
|
|
145
|
-
const results = await premiumRepo.updateManyByQuery({ name: 'NonExistent' }, { name: 'NewName' });
|
|
146
|
-
expect(results).toEqual([]);
|
|
147
|
-
});
|
|
148
|
-
test('tryUpdate returning undefined (non-CTI, no metadata)', async () => {
|
|
149
|
-
const result = await plainRepo.tryUpdate('00000000-0000-0000-0000-000000000000', { description: 'New Desc' });
|
|
150
|
-
expect(result).toBeUndefined();
|
|
151
|
-
});
|
|
152
|
-
test('tryUpdate returning undefined (CTI)', async () => {
|
|
153
|
-
const result = await premiumRepo.tryUpdate('00000000-0000-0000-0000-000000000000', { name: 'New Name' });
|
|
154
|
-
expect(result).toBeUndefined();
|
|
155
|
-
});
|
|
156
|
-
test('tryUpdate returning undefined (CTI) - child field only', async () => {
|
|
157
|
-
// This hits line 1163 in tryUpdateCTI (else block where mappedUpdate is empty for base table)
|
|
158
|
-
// Update ONLY 'code' (Child field).
|
|
159
|
-
// Base table update will be empty.
|
|
160
|
-
const result = await premiumRepo.tryUpdate('00000000-0000-0000-0000-000000000000', { code: 'New Code' });
|
|
161
|
-
expect(result).toBeUndefined();
|
|
162
|
-
});
|
|
163
|
-
test('tryDelete returning undefined (non-CTI, has metadata)', async () => {
|
|
164
|
-
const result = await simpleRepo.tryDelete('00000000-0000-0000-0000-000000000000');
|
|
165
|
-
expect(result).toBeUndefined();
|
|
166
|
-
});
|
|
167
|
-
test('tryDelete returning undefined (non-CTI, no metadata)', async () => {
|
|
168
|
-
// This hits tryHardDelete
|
|
169
|
-
const result = await plainRepo.tryDelete('00000000-0000-0000-0000-000000000000');
|
|
170
|
-
expect(result).toBeUndefined();
|
|
171
|
-
});
|
|
172
|
-
test('tryDeleteByQuery returning undefined (non-CTI, has metadata)', async () => {
|
|
173
|
-
const result = await simpleRepo.tryDeleteByQuery({ label: 'NonExistent' });
|
|
174
|
-
expect(result).toBeUndefined();
|
|
175
|
-
});
|
|
176
|
-
test('tryDeleteByQuery returning undefined (non-CTI, no metadata)', async () => {
|
|
177
|
-
// This hits tryHardDeleteByQuery
|
|
178
|
-
const result = await plainRepo.tryDeleteByQuery({ description: 'NonExistent' });
|
|
179
|
-
expect(result).toBeUndefined();
|
|
180
|
-
});
|
|
181
|
-
test('tryUpsertCTI returning undefined when update condition fails', async () => {
|
|
182
|
-
const item = Object.assign(new PremiumItem(), { name: 'Condition Item', code: 'COND' });
|
|
183
|
-
const inserted = await premiumRepo.insert(item);
|
|
184
|
-
const conflictItem = Object.assign(new PremiumItem(), { id: inserted.id, name: 'Should Not Update', code: 'COND' });
|
|
185
|
-
// Upsert with a condition that evaluates to false
|
|
186
|
-
const result = await premiumRepo.tryUpsert(['id'], conflictItem, undefined, { set: { name: 'Impossible Name' } } // This query condition on the existing row must fail
|
|
187
|
-
);
|
|
188
|
-
expect(result).toBeUndefined();
|
|
189
|
-
const loaded = await premiumRepo.load(inserted.id);
|
|
190
|
-
expect(loaded.name).toBe('Condition Item'); // Should not have changed
|
|
191
|
-
});
|
|
192
|
-
test('Discriminator mismatch throws error', async () => {
|
|
193
|
-
// Simulate a row returned from DB that has wrong type
|
|
194
|
-
// PremiumItem expects type='premium'
|
|
195
|
-
const corruptRow = {
|
|
196
|
-
id: 'some-id',
|
|
197
|
-
type: 'wrong_type',
|
|
198
|
-
name: 'Test',
|
|
199
|
-
code: 'C1',
|
|
200
|
-
revision: 1,
|
|
201
|
-
revision_timestamp: new Date(),
|
|
202
|
-
create_timestamp: new Date(),
|
|
203
|
-
delete_timestamp: null,
|
|
204
|
-
attributes: {},
|
|
205
|
-
};
|
|
206
|
-
await expect(premiumRepo.mapToEntity(corruptRow)).rejects.toThrow('Discriminator mismatch');
|
|
207
|
-
});
|
|
208
|
-
test('updateManyByQuery (CTI) should return empty array if no IDs found', async () => {
|
|
209
|
-
// Query that returns nothing
|
|
210
|
-
const result = await premiumRepo.updateManyByQuery({ name: 'Ghost' }, { name: 'Buster' });
|
|
211
|
-
expect(result).toHaveLength(0);
|
|
212
|
-
});
|
|
213
|
-
test('updateManyByQuery on Non-CTI', async () => {
|
|
214
|
-
await simpleRepo.insert(Object.assign(new SimpleItem(), { label: 'To Update' }));
|
|
215
|
-
const results = await simpleRepo.updateManyByQuery({ label: 'To Update' }, { label: 'Updated' });
|
|
216
|
-
expect(results).toHaveLength(1);
|
|
217
|
-
expect(results[0].label).toBe('Updated');
|
|
218
|
-
});
|
|
219
|
-
test('updateByQuery throws NotFoundError', async () => {
|
|
220
|
-
await expect(simpleRepo.updateByQuery({ label: 'Ghost' }, { label: 'Buster' })).rejects.toThrow('SimpleItem not found');
|
|
221
|
-
});
|
|
222
|
-
test('tryUpdateByQuery returns undefined (CTI)', async () => {
|
|
223
|
-
const result = await premiumRepo.tryUpdateByQuery({ name: 'Ghost' }, { name: 'Buster' });
|
|
224
|
-
expect(result).toBeUndefined();
|
|
225
|
-
});
|
|
226
|
-
test('tryUpdateByQuery updates entity (CTI)', async () => {
|
|
227
|
-
const item = await premiumRepo.insert(Object.assign(new PremiumItem(), { name: 'Target', code: 'T1' }));
|
|
228
|
-
const result = await premiumRepo.tryUpdateByQuery({ name: 'Target' }, { name: 'Updated Target' });
|
|
229
|
-
expect(result).toBeDefined();
|
|
230
|
-
expect(result.name).toBe('Updated Target');
|
|
231
|
-
});
|
|
232
|
-
test('deleteManyByQuery (Soft Delete)', async () => {
|
|
233
|
-
await simpleRepo.insert(Object.assign(new SimpleItem(), { label: 'To Delete' }));
|
|
234
|
-
const results = await simpleRepo.deleteManyByQuery({ label: 'To Delete' });
|
|
235
|
-
expect(results).toHaveLength(1);
|
|
236
|
-
expect(results[0].label).toBe('To Delete');
|
|
237
|
-
expect(results[0].metadata.deleteTimestamp).not.toBeNull();
|
|
238
|
-
});
|
|
239
|
-
test('deleteByQuery throws NotFoundError', async () => {
|
|
240
|
-
await expect(simpleRepo.deleteByQuery({ label: 'Ghost' })).rejects.toThrow('SimpleItem not found');
|
|
241
|
-
});
|
|
242
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
import { sql } from 'drizzle-orm';
|
|
11
|
-
import { describe, expect } from 'vitest';
|
|
12
|
-
import { StringProperty } from '../../schema/index.js';
|
|
13
|
-
import { getIntegrationTest } from '../../testing/index.js';
|
|
14
|
-
import { ChildEntity, Inheritance, Table } from '../decorators.js';
|
|
15
|
-
import { Entity } from '../entity.js';
|
|
16
|
-
import { injectRepository } from '../server/repository.js';
|
|
17
|
-
const schema = 'test_orm_cti_complex';
|
|
18
|
-
const test = getIntegrationTest({ orm: { schema } });
|
|
19
|
-
describe('ORM Repository CTI Complex', () => {
|
|
20
|
-
let BaseEntity = class BaseEntity extends Entity {
|
|
21
|
-
type;
|
|
22
|
-
baseName;
|
|
23
|
-
};
|
|
24
|
-
__decorate([
|
|
25
|
-
StringProperty(),
|
|
26
|
-
__metadata("design:type", String)
|
|
27
|
-
], BaseEntity.prototype, "type", void 0);
|
|
28
|
-
__decorate([
|
|
29
|
-
StringProperty(),
|
|
30
|
-
__metadata("design:type", String)
|
|
31
|
-
], BaseEntity.prototype, "baseName", void 0);
|
|
32
|
-
BaseEntity = __decorate([
|
|
33
|
-
Table('base_entities', { schema }),
|
|
34
|
-
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
35
|
-
], BaseEntity);
|
|
36
|
-
let MiddleEntity = class MiddleEntity extends BaseEntity {
|
|
37
|
-
middleName;
|
|
38
|
-
};
|
|
39
|
-
__decorate([
|
|
40
|
-
StringProperty(),
|
|
41
|
-
__metadata("design:type", String)
|
|
42
|
-
], MiddleEntity.prototype, "middleName", void 0);
|
|
43
|
-
MiddleEntity = __decorate([
|
|
44
|
-
Table('middle_entities', { schema }),
|
|
45
|
-
ChildEntity('middle')
|
|
46
|
-
], MiddleEntity);
|
|
47
|
-
let LeafEntity = class LeafEntity extends MiddleEntity {
|
|
48
|
-
leafName;
|
|
49
|
-
};
|
|
50
|
-
__decorate([
|
|
51
|
-
StringProperty(),
|
|
52
|
-
__metadata("design:type", String)
|
|
53
|
-
], LeafEntity.prototype, "leafName", void 0);
|
|
54
|
-
LeafEntity = __decorate([
|
|
55
|
-
Table('leaf_entities', { schema }),
|
|
56
|
-
ChildEntity('leaf')
|
|
57
|
-
], LeafEntity);
|
|
58
|
-
test.beforeEach(async ({ database: db }) => {
|
|
59
|
-
await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
60
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('leaf_entities')} CASCADE`);
|
|
61
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('middle_entities')} CASCADE`);
|
|
62
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('base_entities')} CASCADE`);
|
|
63
|
-
await db.execute(sql `
|
|
64
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('base_entities')} (
|
|
65
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
66
|
-
type TEXT NOT NULL,
|
|
67
|
-
base_name TEXT NOT NULL,
|
|
68
|
-
revision INTEGER NOT NULL,
|
|
69
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
70
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
71
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
72
|
-
attributes JSONB NOT NULL DEFAULT '{}',
|
|
73
|
-
UNIQUE (id, type)
|
|
74
|
-
)
|
|
75
|
-
`);
|
|
76
|
-
await db.execute(sql `
|
|
77
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('middle_entities')} (
|
|
78
|
-
id UUID PRIMARY KEY,
|
|
79
|
-
type TEXT NOT NULL CHECK (type = 'middle' OR type = 'leaf'),
|
|
80
|
-
middle_name TEXT NOT NULL,
|
|
81
|
-
UNIQUE (id, type),
|
|
82
|
-
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('base_entities')}(id, type) ON DELETE CASCADE
|
|
83
|
-
)
|
|
84
|
-
`);
|
|
85
|
-
await db.execute(sql `
|
|
86
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('leaf_entities')} (
|
|
87
|
-
id UUID PRIMARY KEY,
|
|
88
|
-
type TEXT NOT NULL CHECK (type = 'leaf'),
|
|
89
|
-
leaf_name TEXT NOT NULL,
|
|
90
|
-
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('middle_entities')}(id, type) ON DELETE CASCADE
|
|
91
|
-
)
|
|
92
|
-
`);
|
|
93
|
-
});
|
|
94
|
-
test('should support deep inheritance (3 levels)', async () => {
|
|
95
|
-
const repository = injectRepository(LeafEntity);
|
|
96
|
-
const leaf = Object.assign(new LeafEntity(), {
|
|
97
|
-
baseName: 'Base',
|
|
98
|
-
middleName: 'Middle',
|
|
99
|
-
leafName: 'Leaf',
|
|
100
|
-
});
|
|
101
|
-
const inserted = await repository.insert(leaf);
|
|
102
|
-
expect(inserted.id).toBeDefined();
|
|
103
|
-
expect(inserted.baseName).toBe('Base');
|
|
104
|
-
expect(inserted.middleName).toBe('Middle');
|
|
105
|
-
expect(inserted.leafName).toBe('Leaf');
|
|
106
|
-
const loaded = await repository.load(inserted.id);
|
|
107
|
-
expect(loaded).toBeInstanceOf(LeafEntity);
|
|
108
|
-
expect(loaded.baseName).toBe('Base');
|
|
109
|
-
expect(loaded.middleName).toBe('Middle');
|
|
110
|
-
expect(loaded.leafName).toBe('Leaf');
|
|
111
|
-
});
|
|
112
|
-
test('should throw error on discriminator mismatch', async () => {
|
|
113
|
-
const middleRepository = injectRepository(MiddleEntity);
|
|
114
|
-
const leafRepository = injectRepository(LeafEntity);
|
|
115
|
-
const middle = await middleRepository.insert(Object.assign(new MiddleEntity(), {
|
|
116
|
-
baseName: 'B',
|
|
117
|
-
middleName: 'M',
|
|
118
|
-
}));
|
|
119
|
-
// Try to load middle as leaf
|
|
120
|
-
await expect(leafRepository.load(middle.id)).rejects.toThrow();
|
|
121
|
-
});
|
|
122
|
-
test('should upsert correctly on child entities', async () => {
|
|
123
|
-
const repository = injectRepository(MiddleEntity);
|
|
124
|
-
const e1 = Object.assign(new MiddleEntity(), { baseName: 'B1', middleName: 'M1' });
|
|
125
|
-
const inserted = await repository.insert(e1);
|
|
126
|
-
const update = Object.assign(new MiddleEntity(), { id: inserted.id, baseName: 'B1_Updated', middleName: 'M1_Updated' });
|
|
127
|
-
const upserted = await repository.upsert('id', update);
|
|
128
|
-
expect(upserted.id).toBe(inserted.id);
|
|
129
|
-
expect(upserted.baseName).toBe('B1_Updated');
|
|
130
|
-
expect(upserted.middleName).toBe('M1_Updated');
|
|
131
|
-
});
|
|
132
|
-
test('should handle upsert when parent exists but child does not', async ({ database: db }) => {
|
|
133
|
-
const middleRepository = injectRepository(MiddleEntity);
|
|
134
|
-
// Manually insert into base table only
|
|
135
|
-
const id = '00000000-0000-0000-0000-000000000001';
|
|
136
|
-
await db.execute(sql `
|
|
137
|
-
INSERT INTO ${sql.identifier(schema)}.${sql.identifier('base_entities')} (id, type, base_name, revision, revision_timestamp, create_timestamp, attributes)
|
|
138
|
-
VALUES (${id}, 'middle', 'OnlyBase', 1, now(), now(), '{}')
|
|
139
|
-
`);
|
|
140
|
-
// Now upsert via middle repository
|
|
141
|
-
const update = Object.assign(new MiddleEntity(), { id, baseName: 'Updated', middleName: 'NewMiddle' });
|
|
142
|
-
// This is expected to fail or behave unexpectedly if not handled,
|
|
143
|
-
// because upsert (onConflictDoUpdate) usually targets one table.
|
|
144
|
-
// In CTI, we might need special handling.
|
|
145
|
-
const upserted = await middleRepository.upsert('id', update);
|
|
146
|
-
expect(upserted.id).toBe(id);
|
|
147
|
-
expect(upserted.middleName).toBe('NewMiddle');
|
|
148
|
-
const loaded = await middleRepository.load(id);
|
|
149
|
-
expect(loaded.middleName).toBe('NewMiddle');
|
|
150
|
-
});
|
|
151
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
import { Injector, runInInjectionContext } from '../../injector/index.js';
|
|
11
|
-
import { StringProperty } from '../../schema/index.js';
|
|
12
|
-
import { setupIntegrationTest } from '../../testing/index.js';
|
|
13
|
-
import { sql } from 'drizzle-orm';
|
|
14
|
-
import { beforeAll, describe, expect, test } from 'vitest';
|
|
15
|
-
import { ChildEntity, Column, EmbeddedProperty, Inheritance, Table } from '../decorators.js';
|
|
16
|
-
import { Entity } from '../entity.js';
|
|
17
|
-
import { Database } from '../server/index.js';
|
|
18
|
-
import { injectRepository } from '../server/repository.js';
|
|
19
|
-
describe('ORM Repository CTI Embedded (Integration)', () => {
|
|
20
|
-
let injector;
|
|
21
|
-
let database;
|
|
22
|
-
const schema = 'test_orm_cti_embedded';
|
|
23
|
-
class Address {
|
|
24
|
-
street;
|
|
25
|
-
city;
|
|
26
|
-
}
|
|
27
|
-
__decorate([
|
|
28
|
-
StringProperty(),
|
|
29
|
-
__metadata("design:type", String)
|
|
30
|
-
], Address.prototype, "street", void 0);
|
|
31
|
-
__decorate([
|
|
32
|
-
StringProperty(),
|
|
33
|
-
__metadata("design:type", String)
|
|
34
|
-
], Address.prototype, "city", void 0);
|
|
35
|
-
class Contact {
|
|
36
|
-
phone;
|
|
37
|
-
email;
|
|
38
|
-
}
|
|
39
|
-
__decorate([
|
|
40
|
-
StringProperty(),
|
|
41
|
-
__metadata("design:type", String)
|
|
42
|
-
], Contact.prototype, "phone", void 0);
|
|
43
|
-
__decorate([
|
|
44
|
-
StringProperty(),
|
|
45
|
-
__metadata("design:type", String)
|
|
46
|
-
], Contact.prototype, "email", void 0);
|
|
47
|
-
let EntityWithAddress = class EntityWithAddress extends Entity {
|
|
48
|
-
type;
|
|
49
|
-
address;
|
|
50
|
-
};
|
|
51
|
-
__decorate([
|
|
52
|
-
StringProperty(),
|
|
53
|
-
Column({ name: 'type' }),
|
|
54
|
-
__metadata("design:type", String)
|
|
55
|
-
], EntityWithAddress.prototype, "type", void 0);
|
|
56
|
-
__decorate([
|
|
57
|
-
EmbeddedProperty(Address, { prefix: 'addr_' }),
|
|
58
|
-
__metadata("design:type", Address)
|
|
59
|
-
], EntityWithAddress.prototype, "address", void 0);
|
|
60
|
-
EntityWithAddress = __decorate([
|
|
61
|
-
Table('entities_with_address', { schema }),
|
|
62
|
-
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
63
|
-
], EntityWithAddress);
|
|
64
|
-
let UserWithContact = class UserWithContact extends EntityWithAddress {
|
|
65
|
-
name;
|
|
66
|
-
contact;
|
|
67
|
-
};
|
|
68
|
-
__decorate([
|
|
69
|
-
StringProperty(),
|
|
70
|
-
__metadata("design:type", String)
|
|
71
|
-
], UserWithContact.prototype, "name", void 0);
|
|
72
|
-
__decorate([
|
|
73
|
-
EmbeddedProperty(Contact, { prefix: 'contact_' }),
|
|
74
|
-
__metadata("design:type", Contact)
|
|
75
|
-
], UserWithContact.prototype, "contact", void 0);
|
|
76
|
-
UserWithContact = __decorate([
|
|
77
|
-
Table('users_with_contact', { schema }),
|
|
78
|
-
ChildEntity('user')
|
|
79
|
-
], UserWithContact);
|
|
80
|
-
beforeAll(async () => {
|
|
81
|
-
({ injector, database } = await setupIntegrationTest({ orm: { schema } }));
|
|
82
|
-
await database.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
83
|
-
await database.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('users_with_contact')} CASCADE`);
|
|
84
|
-
await database.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('entities_with_address')} CASCADE`);
|
|
85
|
-
await database.execute(sql `
|
|
86
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('entities_with_address')} (
|
|
87
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
88
|
-
type TEXT NOT NULL,
|
|
89
|
-
addr_street TEXT NOT NULL,
|
|
90
|
-
addr_city TEXT NOT NULL,
|
|
91
|
-
revision INTEGER NOT NULL,
|
|
92
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
93
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
94
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
95
|
-
attributes JSONB NOT NULL DEFAULT '{}',
|
|
96
|
-
UNIQUE (id, type)
|
|
97
|
-
)
|
|
98
|
-
`);
|
|
99
|
-
await database.execute(sql `
|
|
100
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('users_with_contact')} (
|
|
101
|
-
id UUID PRIMARY KEY,
|
|
102
|
-
type TEXT NOT NULL CHECK (type = 'user'),
|
|
103
|
-
name TEXT NOT NULL,
|
|
104
|
-
contact_phone TEXT NOT NULL,
|
|
105
|
-
contact_email TEXT NOT NULL,
|
|
106
|
-
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('entities_with_address')} (id, type) ON DELETE CASCADE
|
|
107
|
-
)
|
|
108
|
-
`);
|
|
109
|
-
});
|
|
110
|
-
test('should insert and load entities with embedded properties in CTI', async () => {
|
|
111
|
-
await runInInjectionContext(injector, async () => {
|
|
112
|
-
const repository = injectRepository(UserWithContact);
|
|
113
|
-
const user = new UserWithContact();
|
|
114
|
-
user.address = { street: 'Main St', city: 'London' };
|
|
115
|
-
user.contact = { phone: '12345', email: 'test@example.com' };
|
|
116
|
-
user.name = 'John Doe';
|
|
117
|
-
const inserted = await repository.insert(user);
|
|
118
|
-
expect(inserted.address.street).toBe('Main St');
|
|
119
|
-
expect(inserted.contact.email).toBe('test@example.com');
|
|
120
|
-
const loaded = await repository.load(inserted.id);
|
|
121
|
-
expect(loaded.address.city).toBe('London');
|
|
122
|
-
expect(loaded.contact.phone).toBe('12345');
|
|
123
|
-
expect(loaded.name).toBe('John Doe');
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
test('should load polymorphically with embedded properties', async () => {
|
|
127
|
-
await runInInjectionContext(injector, async () => {
|
|
128
|
-
const baseRepo = injectRepository(EntityWithAddress);
|
|
129
|
-
const userRepo = injectRepository(UserWithContact);
|
|
130
|
-
await userRepo.insert(Object.assign(new UserWithContact(), {
|
|
131
|
-
name: 'Jane',
|
|
132
|
-
address: { street: 'High St', city: 'Paris' },
|
|
133
|
-
contact: { phone: '999', email: 'jane@test.com' },
|
|
134
|
-
}));
|
|
135
|
-
const all = await baseRepo.loadAll({ includeSubclasses: true });
|
|
136
|
-
const jane = all.find((u) => (u instanceof UserWithContact) && (u.name == 'Jane'));
|
|
137
|
-
expect(jane).toBeDefined();
|
|
138
|
-
expect(jane.address.city).toBe('Paris');
|
|
139
|
-
expect(jane.contact.email).toBe('jane@test.com');
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
test('should update embedded properties in both tables', async () => {
|
|
143
|
-
await runInInjectionContext(injector, async () => {
|
|
144
|
-
const repository = injectRepository(UserWithContact);
|
|
145
|
-
const user = await repository.insert(Object.assign(new UserWithContact(), {
|
|
146
|
-
name: 'UpdateMe',
|
|
147
|
-
address: { street: 'Old St', city: 'Old City' },
|
|
148
|
-
contact: { phone: '000', email: 'old@test.com' },
|
|
149
|
-
}));
|
|
150
|
-
await repository.update(user.id, {
|
|
151
|
-
address: { street: 'New St', city: 'New City' },
|
|
152
|
-
contact: { email: 'new@test.com' },
|
|
153
|
-
});
|
|
154
|
-
const updated = await repository.load(user.id);
|
|
155
|
-
expect(updated.address.street).toBe('New St');
|
|
156
|
-
expect(updated.address.city).toBe('New City');
|
|
157
|
-
expect(updated.contact.phone).toBe('000'); // Unchanged
|
|
158
|
-
expect(updated.contact.email).toBe('new@test.com');
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
test('should filter by embedded properties across tables', async () => {
|
|
162
|
-
await runInInjectionContext(injector, async () => {
|
|
163
|
-
const repository = injectRepository(UserWithContact);
|
|
164
|
-
await repository.insert(Object.assign(new UserWithContact(), {
|
|
165
|
-
name: 'Target',
|
|
166
|
-
address: { street: 'Secret St', city: 'Hidden' },
|
|
167
|
-
contact: { phone: '123', email: 'target@test.com' },
|
|
168
|
-
}));
|
|
169
|
-
// Filter by address (parent table) and contact (child table)
|
|
170
|
-
const results = await repository.loadManyByQuery({
|
|
171
|
-
address: { city: 'Hidden' },
|
|
172
|
-
contact: { email: 'target@test.com' },
|
|
173
|
-
}); // Type cast might be needed if Query doesn't perfectly map embedded deep objects yet
|
|
174
|
-
expect(results).toHaveLength(1);
|
|
175
|
-
expect(results[0].name).toBe('Target');
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
});
|