@tstdl/base 0.93.181 → 0.93.183
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/server/api-request-token.provider.js +1 -1
- package/api/server/gateway.js +8 -3
- 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,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 { sql } from 'drizzle-orm';
|
|
11
|
-
import { describe, expect } from 'vitest';
|
|
12
|
-
import { StringProperty } from '../../schema/index.js';
|
|
13
|
-
import { getIntegrationTest } from '../../testing/index.js';
|
|
14
|
-
import { Table } from '../decorators.js';
|
|
15
|
-
import { Entity } from '../entity.js';
|
|
16
|
-
import { injectRepository } from '../server/repository.js';
|
|
17
|
-
const schema = 'test_orm_tx_nested';
|
|
18
|
-
const test = getIntegrationTest({ orm: { schema } });
|
|
19
|
-
describe('ORM Repository Transactions Nested (Integration)', () => {
|
|
20
|
-
let TxEntity = class TxEntity extends Entity {
|
|
21
|
-
name;
|
|
22
|
-
};
|
|
23
|
-
__decorate([
|
|
24
|
-
StringProperty(),
|
|
25
|
-
__metadata("design:type", String)
|
|
26
|
-
], TxEntity.prototype, "name", void 0);
|
|
27
|
-
TxEntity = __decorate([
|
|
28
|
-
Table('tx_entities', { schema })
|
|
29
|
-
], TxEntity);
|
|
30
|
-
test.beforeEach(async ({ database: db }) => {
|
|
31
|
-
await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
32
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
33
|
-
await db.execute(sql `
|
|
34
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} (
|
|
35
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
36
|
-
name TEXT NOT NULL,
|
|
37
|
-
revision INTEGER NOT NULL,
|
|
38
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
39
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
40
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
41
|
-
attributes JSONB NOT NULL DEFAULT '{}'
|
|
42
|
-
)
|
|
43
|
-
`);
|
|
44
|
-
});
|
|
45
|
-
test('should commit nested transaction', async ({ database: db }) => {
|
|
46
|
-
const repo = injectRepository(TxEntity);
|
|
47
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
48
|
-
await repo.transaction(async (tx1) => {
|
|
49
|
-
const repo1 = repo.withTransaction(tx1);
|
|
50
|
-
await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
|
|
51
|
-
await repo1.transaction(async (tx2) => {
|
|
52
|
-
const repo2 = repo1.withTransaction(tx2);
|
|
53
|
-
await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
const count = await repo.count();
|
|
57
|
-
expect(count).toBe(2);
|
|
58
|
-
});
|
|
59
|
-
test('should rollback nested transaction (inner fails)', async ({ database: db }) => {
|
|
60
|
-
const repo = injectRepository(TxEntity);
|
|
61
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
62
|
-
try {
|
|
63
|
-
await repo.transaction(async (tx1) => {
|
|
64
|
-
const repo1 = repo.withTransaction(tx1);
|
|
65
|
-
await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
|
|
66
|
-
await repo1.transaction(async (tx2) => {
|
|
67
|
-
const repo2 = repo1.withTransaction(tx2);
|
|
68
|
-
await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
|
|
69
|
-
throw new Error('Fail Inner');
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
expect(e.message).toBe('Fail Inner');
|
|
75
|
-
}
|
|
76
|
-
const count = await repo.count();
|
|
77
|
-
expect(count).toBe(0); // Outer should rollback too if error propagates
|
|
78
|
-
});
|
|
79
|
-
test('should rollback nested transaction but keep outer if caught', async ({ database: db }) => {
|
|
80
|
-
const repo = injectRepository(TxEntity);
|
|
81
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
82
|
-
await repo.transaction(async (tx1) => {
|
|
83
|
-
const repo1 = repo.withTransaction(tx1);
|
|
84
|
-
await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
|
|
85
|
-
try {
|
|
86
|
-
await repo1.transaction(async (tx2) => {
|
|
87
|
-
const repo2 = repo1.withTransaction(tx2);
|
|
88
|
-
await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
|
|
89
|
-
throw new Error('Fail Inner');
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
// Swallow error to keep outer alive
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
const all = await repo.loadAll();
|
|
97
|
-
expect(all).toHaveLength(1);
|
|
98
|
-
expect(all[0].name).toBe('Outer');
|
|
99
|
-
});
|
|
100
|
-
test('should rollback outer transaction (outer fails after inner commit)', async ({ database: db }) => {
|
|
101
|
-
const repo = injectRepository(TxEntity);
|
|
102
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
103
|
-
try {
|
|
104
|
-
await repo.transaction(async (tx1) => {
|
|
105
|
-
const repo1 = repo.withTransaction(tx1);
|
|
106
|
-
await repo1.insert(Object.assign(new TxEntity(), { name: 'Outer' }));
|
|
107
|
-
await repo1.transaction(async (tx2) => {
|
|
108
|
-
const repo2 = repo1.withTransaction(tx2);
|
|
109
|
-
await repo2.insert(Object.assign(new TxEntity(), { name: 'Inner' }));
|
|
110
|
-
});
|
|
111
|
-
throw new Error('Fail Outer');
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
// Expected
|
|
116
|
-
}
|
|
117
|
-
const count = await repo.count();
|
|
118
|
-
expect(count).toBe(0);
|
|
119
|
-
});
|
|
120
|
-
test('should support multiple nested transactions sequentially', async ({ database: db }) => {
|
|
121
|
-
const repo = injectRepository(TxEntity);
|
|
122
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
123
|
-
await repo.transaction(async (tx1) => {
|
|
124
|
-
const repo1 = repo.withTransaction(tx1);
|
|
125
|
-
await repo1.transaction(async (tx2) => {
|
|
126
|
-
await repo1.withTransaction(tx2).insert(Object.assign(new TxEntity(), { name: 'Inner1' }));
|
|
127
|
-
});
|
|
128
|
-
await repo1.transaction(async (tx3) => {
|
|
129
|
-
await repo1.withTransaction(tx3).insert(Object.assign(new TxEntity(), { name: 'Inner2' }));
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
const count = await repo.count();
|
|
133
|
-
expect(count).toBe(2);
|
|
134
|
-
});
|
|
135
|
-
test('should support deep nesting (3 levels)', async ({ database: db }) => {
|
|
136
|
-
const repo = injectRepository(TxEntity);
|
|
137
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
138
|
-
await repo.transaction(async (tx1) => {
|
|
139
|
-
const r1 = repo.withTransaction(tx1);
|
|
140
|
-
await r1.insert(Object.assign(new TxEntity(), { name: 'L1' }));
|
|
141
|
-
await r1.transaction(async (tx2) => {
|
|
142
|
-
const r2 = r1.withTransaction(tx2);
|
|
143
|
-
await r2.insert(Object.assign(new TxEntity(), { name: 'L2' }));
|
|
144
|
-
await r2.transaction(async (tx3) => {
|
|
145
|
-
const r3 = r2.withTransaction(tx3);
|
|
146
|
-
await r3.insert(Object.assign(new TxEntity(), { name: 'L3' }));
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
const count = await repo.count();
|
|
151
|
-
expect(count).toBe(3);
|
|
152
|
-
});
|
|
153
|
-
test('should rollback deep nesting middle layer', async ({ database: db }) => {
|
|
154
|
-
const repo = injectRepository(TxEntity);
|
|
155
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('tx_entities')} CASCADE`);
|
|
156
|
-
await repo.transaction(async (tx1) => {
|
|
157
|
-
const r1 = repo.withTransaction(tx1);
|
|
158
|
-
await r1.insert(Object.assign(new TxEntity(), { name: 'L1' }));
|
|
159
|
-
try {
|
|
160
|
-
await r1.transaction(async (tx2) => {
|
|
161
|
-
const r2 = r1.withTransaction(tx2);
|
|
162
|
-
await r2.insert(Object.assign(new TxEntity(), { name: 'L2' }));
|
|
163
|
-
await r2.transaction(async (tx3) => {
|
|
164
|
-
const r3 = r2.withTransaction(tx3);
|
|
165
|
-
await r3.insert(Object.assign(new TxEntity(), { name: 'L3' }));
|
|
166
|
-
});
|
|
167
|
-
throw new Error('Fail L2');
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
// Catch L2 failure
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
const all = await repo.loadAll();
|
|
175
|
-
expect(all).toHaveLength(1);
|
|
176
|
-
expect(all[0].name).toBe('L1');
|
|
177
|
-
});
|
|
178
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
import { sql } from 'drizzle-orm';
|
|
11
|
-
import { beforeAll, describe, expect, test } from 'vitest';
|
|
12
|
-
import { Array, BooleanProperty, Integer, NumberProperty, string, StringProperty } from '../../schema/index.js';
|
|
13
|
-
import { setupIntegrationTest } from '../../testing/index.js';
|
|
14
|
-
import { Table } from '../decorators.js';
|
|
15
|
-
import { Entity } from '../entity.js';
|
|
16
|
-
import { JsonProperty, NumericDateProperty, TimestampProperty } from '../schemas/index.js';
|
|
17
|
-
import { getRepository } from '../server/index.js';
|
|
18
|
-
describe('ORM Repository Types (Integration)', () => {
|
|
19
|
-
let injector;
|
|
20
|
-
let db;
|
|
21
|
-
let repo;
|
|
22
|
-
const schema = 'test_orm_types';
|
|
23
|
-
let TypeEntity = class TypeEntity extends Entity {
|
|
24
|
-
text;
|
|
25
|
-
int;
|
|
26
|
-
float;
|
|
27
|
-
bool;
|
|
28
|
-
numericDate;
|
|
29
|
-
timestamp;
|
|
30
|
-
json;
|
|
31
|
-
tags;
|
|
32
|
-
};
|
|
33
|
-
__decorate([
|
|
34
|
-
StringProperty(),
|
|
35
|
-
__metadata("design:type", String)
|
|
36
|
-
], TypeEntity.prototype, "text", void 0);
|
|
37
|
-
__decorate([
|
|
38
|
-
Integer(),
|
|
39
|
-
__metadata("design:type", Number)
|
|
40
|
-
], TypeEntity.prototype, "int", void 0);
|
|
41
|
-
__decorate([
|
|
42
|
-
NumberProperty(),
|
|
43
|
-
__metadata("design:type", Number)
|
|
44
|
-
], TypeEntity.prototype, "float", void 0);
|
|
45
|
-
__decorate([
|
|
46
|
-
BooleanProperty(),
|
|
47
|
-
__metadata("design:type", Boolean)
|
|
48
|
-
], TypeEntity.prototype, "bool", void 0);
|
|
49
|
-
__decorate([
|
|
50
|
-
NumericDateProperty(),
|
|
51
|
-
__metadata("design:type", Number)
|
|
52
|
-
], TypeEntity.prototype, "numericDate", void 0);
|
|
53
|
-
__decorate([
|
|
54
|
-
TimestampProperty(),
|
|
55
|
-
__metadata("design:type", Date)
|
|
56
|
-
], TypeEntity.prototype, "timestamp", void 0);
|
|
57
|
-
__decorate([
|
|
58
|
-
JsonProperty(),
|
|
59
|
-
__metadata("design:type", Object)
|
|
60
|
-
], TypeEntity.prototype, "json", void 0);
|
|
61
|
-
__decorate([
|
|
62
|
-
Array(string()),
|
|
63
|
-
__metadata("design:type", Array)
|
|
64
|
-
], TypeEntity.prototype, "tags", void 0);
|
|
65
|
-
TypeEntity = __decorate([
|
|
66
|
-
Table('type_entities', { schema })
|
|
67
|
-
], TypeEntity);
|
|
68
|
-
beforeAll(async () => {
|
|
69
|
-
({ injector, database: db } = await setupIntegrationTest({
|
|
70
|
-
orm: { schema },
|
|
71
|
-
}));
|
|
72
|
-
repo = injector.resolve(getRepository(TypeEntity));
|
|
73
|
-
await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
74
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('type_entities')} CASCADE`);
|
|
75
|
-
await db.execute(sql `
|
|
76
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('type_entities')} (
|
|
77
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
78
|
-
text TEXT NOT NULL,
|
|
79
|
-
int INTEGER NOT NULL,
|
|
80
|
-
float DOUBLE PRECISION NOT NULL,
|
|
81
|
-
bool BOOLEAN NOT NULL,
|
|
82
|
-
numeric_date DATE NOT NULL,
|
|
83
|
-
timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
84
|
-
json JSONB NOT NULL,
|
|
85
|
-
tags TEXT[] NOT NULL,
|
|
86
|
-
revision INTEGER NOT NULL,
|
|
87
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
88
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
89
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
90
|
-
attributes JSONB NOT NULL DEFAULT '{}'
|
|
91
|
-
)
|
|
92
|
-
`);
|
|
93
|
-
});
|
|
94
|
-
test('should persist and retrieve boolean values (true)', async () => {
|
|
95
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
96
|
-
text: 't', int: 1, float: 1.1, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
97
|
-
}));
|
|
98
|
-
const loaded = await repo.load(entity.id);
|
|
99
|
-
expect(loaded.bool).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
test('should persist and retrieve boolean values (false)', async () => {
|
|
102
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
103
|
-
text: 'f', int: 1, float: 1.1, bool: false, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
104
|
-
}));
|
|
105
|
-
const loaded = await repo.load(entity.id);
|
|
106
|
-
expect(loaded.bool).toBe(false);
|
|
107
|
-
});
|
|
108
|
-
test('should persist and retrieve integer boundaries', async () => {
|
|
109
|
-
const maxInt = 2147483647;
|
|
110
|
-
const minInt = -2147483648;
|
|
111
|
-
const e1 = await repo.insert(Object.assign(new TypeEntity(), {
|
|
112
|
-
text: 'max', int: maxInt, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
113
|
-
}));
|
|
114
|
-
const l1 = await repo.load(e1.id);
|
|
115
|
-
expect(l1.int).toBe(maxInt);
|
|
116
|
-
const e2 = await repo.insert(Object.assign(new TypeEntity(), {
|
|
117
|
-
text: 'min', int: minInt, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
118
|
-
}));
|
|
119
|
-
const l2 = await repo.load(e2.id);
|
|
120
|
-
expect(l2.int).toBe(minInt);
|
|
121
|
-
});
|
|
122
|
-
test('should persist and retrieve float precision', async () => {
|
|
123
|
-
const pi = 3.1415926535;
|
|
124
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
125
|
-
text: 'pi', int: 0, float: pi, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
126
|
-
}));
|
|
127
|
-
const loaded = await repo.load(entity.id);
|
|
128
|
-
expect(loaded.float).toBeCloseTo(pi);
|
|
129
|
-
});
|
|
130
|
-
test('should persist and retrieve numeric dates', async () => {
|
|
131
|
-
const today = 19723; // 2024-01-01
|
|
132
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
133
|
-
text: 'date', int: 0, float: 0, bool: true, numericDate: today, timestamp: new Date(), json: {}, tags: [],
|
|
134
|
-
}));
|
|
135
|
-
const loaded = await repo.load(entity.id);
|
|
136
|
-
expect(loaded.numericDate).toBe(today);
|
|
137
|
-
});
|
|
138
|
-
test('should persist and retrieve timestamps', async () => {
|
|
139
|
-
const now = new Date();
|
|
140
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
141
|
-
text: 'ts', int: 0, float: 0, bool: true, numericDate: 0, timestamp: now, json: {}, tags: [],
|
|
142
|
-
}));
|
|
143
|
-
const loaded = await repo.load(entity.id);
|
|
144
|
-
// Postgres stores microsecond precision, JS Date has millisecond.
|
|
145
|
-
// Drizzle custom type returns number (milliseconds).
|
|
146
|
-
// We accept a small difference due to precision loss or round-trip.
|
|
147
|
-
expect(typeof loaded.timestamp).toBe('number');
|
|
148
|
-
expect(Math.abs(loaded.timestamp - now.getTime())).toBeLessThan(2);
|
|
149
|
-
});
|
|
150
|
-
test('should persist and retrieve complex JSON', async () => {
|
|
151
|
-
const data = {
|
|
152
|
-
foo: 'bar',
|
|
153
|
-
nested: { a: 1, b: [true, false] },
|
|
154
|
-
nullVal: null,
|
|
155
|
-
};
|
|
156
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
157
|
-
text: 'json', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: data, tags: [],
|
|
158
|
-
}));
|
|
159
|
-
const loaded = await repo.load(entity.id);
|
|
160
|
-
expect(loaded.json).toEqual(data);
|
|
161
|
-
});
|
|
162
|
-
test('should persist and retrieve arrays', async () => {
|
|
163
|
-
const tags = ['a', 'b', 'c'];
|
|
164
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
165
|
-
text: 'array', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags,
|
|
166
|
-
}));
|
|
167
|
-
const loaded = await repo.load(entity.id);
|
|
168
|
-
expect(loaded.tags).toEqual(tags);
|
|
169
|
-
});
|
|
170
|
-
test('should persist and retrieve empty arrays', async () => {
|
|
171
|
-
const entity = await repo.insert(Object.assign(new TypeEntity(), {
|
|
172
|
-
text: 'empty-array', int: 0, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
173
|
-
}));
|
|
174
|
-
const loaded = await repo.load(entity.id);
|
|
175
|
-
expect(loaded.tags).toEqual([]);
|
|
176
|
-
});
|
|
177
|
-
test('should fail on integer overflow', async () => {
|
|
178
|
-
// Max int is 2147483647
|
|
179
|
-
const overflow = 3000000000;
|
|
180
|
-
await expect(repo.insert(Object.assign(new TypeEntity(), {
|
|
181
|
-
text: 'overflow', int: overflow, float: 0, bool: true, numericDate: 0, timestamp: new Date(), json: {}, tags: [],
|
|
182
|
-
}))).rejects.toThrow(); // Postgres should reject
|
|
183
|
-
});
|
|
184
|
-
});
|
|
@@ -1,201 +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 { Entity } from '../entity.js';
|
|
17
|
-
import { getRepository } from '../server/index.js';
|
|
18
|
-
describe('ORM Repository Undelete (Integration)', () => {
|
|
19
|
-
let injector;
|
|
20
|
-
let db;
|
|
21
|
-
let repository;
|
|
22
|
-
let baseRepo;
|
|
23
|
-
let subRepo;
|
|
24
|
-
const schema = 'test_orm_undelete';
|
|
25
|
-
let UndeleteEntity = class UndeleteEntity extends Entity {
|
|
26
|
-
name;
|
|
27
|
-
};
|
|
28
|
-
__decorate([
|
|
29
|
-
StringProperty(),
|
|
30
|
-
__metadata("design:type", String)
|
|
31
|
-
], UndeleteEntity.prototype, "name", void 0);
|
|
32
|
-
UndeleteEntity = __decorate([
|
|
33
|
-
Table('undelete_entities', { schema })
|
|
34
|
-
], UndeleteEntity);
|
|
35
|
-
let Base = class Base extends Entity {
|
|
36
|
-
type;
|
|
37
|
-
baseName;
|
|
38
|
-
};
|
|
39
|
-
__decorate([
|
|
40
|
-
StringProperty(),
|
|
41
|
-
Column({ name: 'type' }),
|
|
42
|
-
__metadata("design:type", String)
|
|
43
|
-
], Base.prototype, "type", void 0);
|
|
44
|
-
__decorate([
|
|
45
|
-
StringProperty(),
|
|
46
|
-
__metadata("design:type", String)
|
|
47
|
-
], Base.prototype, "baseName", void 0);
|
|
48
|
-
Base = __decorate([
|
|
49
|
-
Table('bases', { schema }),
|
|
50
|
-
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
51
|
-
], Base);
|
|
52
|
-
let Subtype = class Subtype extends Base {
|
|
53
|
-
subData;
|
|
54
|
-
};
|
|
55
|
-
__decorate([
|
|
56
|
-
StringProperty(),
|
|
57
|
-
__metadata("design:type", String)
|
|
58
|
-
], Subtype.prototype, "subData", void 0);
|
|
59
|
-
Subtype = __decorate([
|
|
60
|
-
Table('subtypes', { schema }),
|
|
61
|
-
ChildEntity('subtype')
|
|
62
|
-
], Subtype);
|
|
63
|
-
beforeAll(async () => {
|
|
64
|
-
({ injector, database: db } = await setupIntegrationTest({ orm: { schema } }));
|
|
65
|
-
repository = injector.resolve(getRepository(UndeleteEntity));
|
|
66
|
-
baseRepo = injector.resolve(getRepository(Base));
|
|
67
|
-
subRepo = injector.resolve(getRepository(Subtype));
|
|
68
|
-
await db.execute(sql `CREATE SCHEMA IF NOT EXISTS ${sql.identifier(schema)}`);
|
|
69
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
70
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('subtypes')} CASCADE`);
|
|
71
|
-
await db.execute(sql `DROP TABLE IF EXISTS ${sql.identifier(schema)}.${sql.identifier('bases')} CASCADE`);
|
|
72
|
-
await db.execute(sql `
|
|
73
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} (
|
|
74
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
75
|
-
name TEXT NOT NULL,
|
|
76
|
-
revision INTEGER NOT NULL,
|
|
77
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
78
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
79
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
80
|
-
attributes JSONB NOT NULL DEFAULT '{}'
|
|
81
|
-
)
|
|
82
|
-
`);
|
|
83
|
-
await db.execute(sql `
|
|
84
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('bases')} (
|
|
85
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
86
|
-
type TEXT NOT NULL,
|
|
87
|
-
base_name TEXT NOT NULL,
|
|
88
|
-
revision INTEGER NOT NULL,
|
|
89
|
-
revision_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
90
|
-
create_timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
91
|
-
delete_timestamp TIMESTAMP WITH TIME ZONE,
|
|
92
|
-
attributes JSONB NOT NULL DEFAULT '{}',
|
|
93
|
-
UNIQUE (id, type)
|
|
94
|
-
)
|
|
95
|
-
`);
|
|
96
|
-
await db.execute(sql `
|
|
97
|
-
CREATE TABLE ${sql.identifier(schema)}.${sql.identifier('subtypes')} (
|
|
98
|
-
id UUID PRIMARY KEY,
|
|
99
|
-
type TEXT NOT NULL CHECK (type = 'subtype'),
|
|
100
|
-
sub_data TEXT NOT NULL,
|
|
101
|
-
FOREIGN KEY (id, type) REFERENCES ${sql.identifier(schema)}.${sql.identifier('bases')} (id, type) ON DELETE CASCADE
|
|
102
|
-
)
|
|
103
|
-
`);
|
|
104
|
-
});
|
|
105
|
-
test('should undelete an entity by ID', async () => {
|
|
106
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
107
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E1' }));
|
|
108
|
-
await repository.delete(e1.id);
|
|
109
|
-
expect(await repository.has(e1.id)).toBe(false);
|
|
110
|
-
const undeleted = await repository.undelete(e1.id);
|
|
111
|
-
expect(undeleted.id).toBe(e1.id);
|
|
112
|
-
expect(undeleted.metadata.deleteTimestamp).toBeNull();
|
|
113
|
-
expect(undeleted.metadata.revision).toBe(3); // Insert (1) -> Delete (2) -> Undelete (3)
|
|
114
|
-
expect(await repository.has(e1.id)).toBe(true);
|
|
115
|
-
const loaded = await repository.load(e1.id);
|
|
116
|
-
expect(loaded.name).toBe('E1');
|
|
117
|
-
expect(loaded.metadata.deleteTimestamp).toBeNull();
|
|
118
|
-
});
|
|
119
|
-
test('should undelete multiple entities by IDs', async () => {
|
|
120
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
121
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E1' }));
|
|
122
|
-
const e2 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E2' }));
|
|
123
|
-
await repository.deleteMany([e1.id, e2.id]);
|
|
124
|
-
const undeleted = await repository.undeleteMany([e1.id, e2.id]);
|
|
125
|
-
expect(undeleted).toHaveLength(2);
|
|
126
|
-
expect(await repository.count()).toBe(2);
|
|
127
|
-
});
|
|
128
|
-
test('should undelete entities by query', async () => {
|
|
129
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
130
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'A' }));
|
|
131
|
-
const e2 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'B' }));
|
|
132
|
-
const e3 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'A' }));
|
|
133
|
-
await repository.deleteManyByQuery({ name: 'A' });
|
|
134
|
-
expect(await repository.count()).toBe(1);
|
|
135
|
-
const undeleted = await repository.undeleteManyByQuery({ name: 'A' });
|
|
136
|
-
expect(undeleted).toHaveLength(2);
|
|
137
|
-
expect(await repository.count()).toBe(3);
|
|
138
|
-
});
|
|
139
|
-
test('should ignore already active entities when undeleting', async () => {
|
|
140
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
141
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E1' }));
|
|
142
|
-
const result = await repository.tryUndelete(e1.id);
|
|
143
|
-
expect(result).toBeUndefined();
|
|
144
|
-
expect(await repository.count()).toBe(1);
|
|
145
|
-
});
|
|
146
|
-
test('should support metadata updates during undeletion', async () => {
|
|
147
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
148
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E1' }));
|
|
149
|
-
await repository.delete(e1.id);
|
|
150
|
-
const undeleted = await repository.undelete(e1.id, {}, { attributes: { restored: true } });
|
|
151
|
-
expect(undeleted.metadata.attributes).toEqual({ restored: true });
|
|
152
|
-
const loaded = await repository.load(e1.id);
|
|
153
|
-
expect(loaded.metadata.attributes).toEqual({ restored: true });
|
|
154
|
-
});
|
|
155
|
-
test('should throw NotFoundError if entity does not exist or is not deleted', async () => {
|
|
156
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('undelete_entities')} CASCADE`);
|
|
157
|
-
await expect(repository.undelete('00000000-0000-0000-0000-000000000000')).rejects.toThrow();
|
|
158
|
-
const e1 = await repository.insert(Object.assign(new UndeleteEntity(), { name: 'E1' }));
|
|
159
|
-
await expect(repository.undelete(e1.id)).rejects.toThrow();
|
|
160
|
-
});
|
|
161
|
-
test('should undelete from subtype repository (CTI)', async () => {
|
|
162
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('bases')} CASCADE`);
|
|
163
|
-
const entity = await subRepo.insert(Object.assign(new Subtype(), { baseName: 'B1', subData: 'S1' }));
|
|
164
|
-
await subRepo.delete(entity.id);
|
|
165
|
-
expect(await subRepo.has(entity.id)).toBe(false);
|
|
166
|
-
const undeleted = await subRepo.undelete(entity.id);
|
|
167
|
-
expect(undeleted.id).toBe(entity.id);
|
|
168
|
-
expect(undeleted.metadata.deleteTimestamp).toBeNull();
|
|
169
|
-
expect(undeleted.metadata.revision).toBe(3);
|
|
170
|
-
expect(await subRepo.has(entity.id)).toBe(true);
|
|
171
|
-
const loaded = await subRepo.load(entity.id);
|
|
172
|
-
expect(loaded.baseName).toBe('B1');
|
|
173
|
-
expect(loaded.subData).toBe('S1');
|
|
174
|
-
});
|
|
175
|
-
test('should undelete polymorphically from base repository (CTI)', async () => {
|
|
176
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('bases')} CASCADE`);
|
|
177
|
-
const entity = await subRepo.insert(Object.assign(new Subtype(), { baseName: 'B1', subData: 'S1' }));
|
|
178
|
-
await subRepo.delete(entity.id);
|
|
179
|
-
expect(await baseRepo.has(entity.id)).toBe(false);
|
|
180
|
-
const undeleted = await baseRepo.undelete(entity.id);
|
|
181
|
-
expect(undeleted.id).toBe(entity.id);
|
|
182
|
-
expect(undeleted.metadata.deleteTimestamp).toBeNull();
|
|
183
|
-
expect(await baseRepo.has(entity.id)).toBe(true);
|
|
184
|
-
const loaded = await baseRepo.load(entity.id, { includeSubclasses: true });
|
|
185
|
-
expect(loaded).toBeInstanceOf(Subtype);
|
|
186
|
-
expect(loaded.subData).toBe('S1');
|
|
187
|
-
});
|
|
188
|
-
test('should undelete multiple entities polymorphically (CTI)', async () => {
|
|
189
|
-
await db.execute(sql `TRUNCATE TABLE ${sql.identifier(schema)}.${sql.identifier('bases')} CASCADE`);
|
|
190
|
-
const e1 = await subRepo.insert(Object.assign(new Subtype(), { baseName: 'B1', subData: 'S1' }));
|
|
191
|
-
const e2 = await subRepo.insert(Object.assign(new Subtype(), { baseName: 'B2', subData: 'S2' }));
|
|
192
|
-
await baseRepo.deleteMany([e1.id, e2.id]);
|
|
193
|
-
expect(await baseRepo.count()).toBe(0);
|
|
194
|
-
const undeleted = await baseRepo.undeleteMany([e1.id, e2.id]);
|
|
195
|
-
expect(undeleted).toHaveLength(2);
|
|
196
|
-
expect(await baseRepo.count()).toBe(2);
|
|
197
|
-
const loadedAll = await baseRepo.loadAll({ includeSubclasses: true });
|
|
198
|
-
expect(loadedAll).toHaveLength(2);
|
|
199
|
-
expect(loadedAll.every((e) => e instanceof Subtype)).toBe(true);
|
|
200
|
-
});
|
|
201
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,82 +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 { StringProperty } from '../../schema/index.js';
|
|
11
|
-
import { getTableConfig } from 'drizzle-orm/pg-core';
|
|
12
|
-
import { describe, expect, test } from 'vitest';
|
|
13
|
-
import { Column, Index, PrimaryKeyProperty, Table } from '../decorators.js';
|
|
14
|
-
import { Entity } from '../entity.js';
|
|
15
|
-
import { getDrizzleTableFromType } from '../server/drizzle/schema-converter.js';
|
|
16
|
-
let Parent = class Parent extends Entity {
|
|
17
|
-
code;
|
|
18
|
-
};
|
|
19
|
-
__decorate([
|
|
20
|
-
StringProperty(),
|
|
21
|
-
Column({ name: 'code' }),
|
|
22
|
-
__metadata("design:type", String)
|
|
23
|
-
], Parent.prototype, "code", void 0);
|
|
24
|
-
Parent = __decorate([
|
|
25
|
-
Table('parent_table', { schema: 'test' })
|
|
26
|
-
], Parent);
|
|
27
|
-
describe('ORM Schema Generation - Detailed Configurations', () => {
|
|
28
|
-
test('should generate partial index with where clause', () => {
|
|
29
|
-
let PartialIndexEntity = class PartialIndexEntity extends Entity {
|
|
30
|
-
status;
|
|
31
|
-
};
|
|
32
|
-
__decorate([
|
|
33
|
-
StringProperty(),
|
|
34
|
-
Index({ where: () => ({ status: 'active' }) }),
|
|
35
|
-
__metadata("design:type", String)
|
|
36
|
-
], PartialIndexEntity.prototype, "status", void 0);
|
|
37
|
-
PartialIndexEntity = __decorate([
|
|
38
|
-
Table('partial_index_test', { schema: 'test' })
|
|
39
|
-
], PartialIndexEntity);
|
|
40
|
-
const table = getDrizzleTableFromType(PartialIndexEntity);
|
|
41
|
-
const config = getTableConfig(table);
|
|
42
|
-
expect(config.indexes.length).toBeGreaterThan(0);
|
|
43
|
-
const idx = config.indexes[0];
|
|
44
|
-
expect(idx).toBeDefined();
|
|
45
|
-
expect(idx.config.name).toContain('partial_idx');
|
|
46
|
-
expect(idx.config.where).toBeDefined();
|
|
47
|
-
});
|
|
48
|
-
test('should handle index with nulls ordering', () => {
|
|
49
|
-
let NullOrderingEntity = class NullOrderingEntity extends Entity {
|
|
50
|
-
val;
|
|
51
|
-
};
|
|
52
|
-
__decorate([
|
|
53
|
-
StringProperty(),
|
|
54
|
-
Index({ nulls: 'first' }),
|
|
55
|
-
__metadata("design:type", String)
|
|
56
|
-
], NullOrderingEntity.prototype, "val", void 0);
|
|
57
|
-
NullOrderingEntity = __decorate([
|
|
58
|
-
Table('null_ordering_test', { schema: 'test' })
|
|
59
|
-
], NullOrderingEntity);
|
|
60
|
-
const table = getDrizzleTableFromType(NullOrderingEntity);
|
|
61
|
-
const config = getTableConfig(table);
|
|
62
|
-
expect(config.indexes.length).toBeGreaterThan(0);
|
|
63
|
-
});
|
|
64
|
-
test('should handle renamed id column', () => {
|
|
65
|
-
let RenamedIdEntity = class RenamedIdEntity extends Entity {
|
|
66
|
-
};
|
|
67
|
-
__decorate([
|
|
68
|
-
StringProperty(),
|
|
69
|
-
Column({ name: 'custom_id' }),
|
|
70
|
-
PrimaryKeyProperty(),
|
|
71
|
-
__metadata("design:type", String)
|
|
72
|
-
], RenamedIdEntity.prototype, "id", void 0);
|
|
73
|
-
RenamedIdEntity = __decorate([
|
|
74
|
-
Table('renamed_id_test', { schema: 'test' })
|
|
75
|
-
], RenamedIdEntity);
|
|
76
|
-
const table = getDrizzleTableFromType(RenamedIdEntity);
|
|
77
|
-
const config = getTableConfig(table);
|
|
78
|
-
const idCol = config.columns.find(c => c.name === 'custom_id');
|
|
79
|
-
expect(idCol).toBeDefined();
|
|
80
|
-
expect(idCol.primary).toBe(true);
|
|
81
|
-
});
|
|
82
|
-
});
|