@tstdl/base 0.93.87 → 0.93.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/genkit/helpers.d.ts +3 -1
- package/ai/genkit/helpers.js +3 -3
- package/api/server/gateway.d.ts +3 -0
- package/api/server/gateway.js +15 -4
- package/api/server/middlewares/catch-error.middleware.js +2 -4
- package/api/server/middlewares/cors.middleware.js +2 -3
- package/api/server/middlewares/csrf.middleware.d.ts +41 -0
- package/api/server/middlewares/csrf.middleware.js +108 -0
- package/api/server/middlewares/index.d.ts +1 -0
- package/api/server/middlewares/index.js +1 -0
- package/api/server/module.d.ts +8 -2
- package/api/server/module.js +14 -8
- package/api/server/tests/csrf.middleware.test.js +91 -0
- package/audit/drizzle/{0000_bored_stick.sql → 0000_lumpy_thunderball.sql} +3 -3
- package/audit/drizzle/meta/0000_snapshot.json +4 -4
- package/audit/drizzle/meta/_journal.json +2 -9
- package/audit/module.d.ts +4 -1
- package/audit/module.js +3 -2
- package/audit/schemas.d.ts +1 -1
- package/audit/types.d.ts +1 -1
- package/audit/types.js +1 -1
- package/authentication/client/authentication.service.d.ts +14 -1
- package/authentication/client/authentication.service.js +82 -23
- package/authentication/client/http-client.middleware.d.ts +6 -0
- package/authentication/client/http-client.middleware.js +36 -0
- package/authentication/client/module.js +8 -2
- package/authentication/models/service-account.model.d.ts +2 -2
- package/authentication/models/service-account.model.js +10 -5
- package/authentication/models/subject.model.d.ts +20 -5
- package/authentication/models/subject.model.js +34 -29
- package/authentication/models/system-account.model.d.ts +3 -2
- package/authentication/models/system-account.model.js +11 -5
- package/authentication/models/user.model.d.ts +2 -11
- package/authentication/models/user.model.js +5 -16
- package/authentication/server/authentication-api-request-token.provider.d.ts +0 -2
- package/authentication/server/authentication-api-request-token.provider.js +3 -11
- package/authentication/server/authentication.api-controller.d.ts +1 -2
- package/authentication/server/authentication.api-controller.js +8 -9
- package/authentication/server/authentication.audit.d.ts +3 -2
- package/authentication/server/authentication.service.d.ts +27 -1
- package/authentication/server/authentication.service.js +67 -18
- package/authentication/server/drizzle/{0000_normal_paper_doll.sql → 0000_soft_tag.sql} +25 -32
- package/authentication/server/drizzle/meta/0000_snapshot.json +180 -205
- package/authentication/server/drizzle/meta/_journal.json +2 -2
- package/authentication/server/helper.js +9 -2
- package/authentication/server/module.d.ts +4 -1
- package/authentication/server/module.js +9 -5
- package/authentication/server/schemas.d.ts +2 -1
- package/authentication/server/schemas.js +2 -2
- package/authentication/server/subject.service.d.ts +17 -11
- package/authentication/server/subject.service.js +86 -84
- package/authentication/tests/authentication-ancillary.service.test.d.ts +1 -0
- package/authentication/tests/authentication-ancillary.service.test.js +13 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.d.ts +1 -0
- package/authentication/tests/authentication-secret-requirements.validator.test.js +29 -0
- package/authentication/tests/authentication.api-controller.test.d.ts +1 -0
- package/authentication/tests/authentication.api-controller.test.js +88 -0
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +1 -0
- package/authentication/tests/authentication.api-request-token.provider.test.js +48 -0
- package/authentication/tests/authentication.client-middleware.test.d.ts +1 -0
- package/authentication/tests/authentication.client-middleware.test.js +23 -0
- package/authentication/tests/authentication.client-service.test.d.ts +1 -0
- package/authentication/tests/authentication.client-service.test.js +70 -0
- package/authentication/tests/authentication.service.test.d.ts +1 -0
- package/authentication/tests/authentication.service.test.js +186 -0
- package/authentication/tests/authentication.test-ancillary-service.d.ts +9 -0
- package/authentication/tests/authentication.test-ancillary-service.js +27 -0
- package/authentication/tests/helper.test.d.ts +1 -0
- package/authentication/tests/helper.test.js +107 -0
- package/authentication/tests/secret-requirements.error.test.d.ts +1 -0
- package/authentication/tests/secret-requirements.error.test.js +14 -0
- package/authentication/tests/subject.service.test.d.ts +1 -0
- package/authentication/tests/subject.service.test.js +140 -0
- package/circuit-breaker/postgres/drizzle/meta/0000_snapshot.json +1 -1
- package/circuit-breaker/postgres/drizzle/meta/_journal.json +2 -2
- package/circuit-breaker/postgres/module.d.ts +7 -1
- package/circuit-breaker/postgres/module.js +8 -6
- package/circuit-breaker/tests/circuit-breaker.test.js +2 -22
- package/document-management/api/document-management.api.js +2 -6
- package/document-management/server/services/document-validation.service.js +6 -5
- package/document-management/server/services/document-workflow.service.js +5 -5
- package/document-management/service-models/document-folders.view-model.d.ts +5 -2
- package/document-management/service-models/document-folders.view-model.js +42 -9
- package/document-management/service-models/enriched/enriched-document-management-data.view.js +1 -1
- package/examples/document-management/main.js +4 -4
- package/http/client/adapters/undici.adapter.d.ts +7 -5
- package/http/client/adapters/undici.adapter.js +13 -10
- package/http/client/module.d.ts +3 -1
- package/http/client/module.js +8 -9
- package/http/server/http-server.d.ts +2 -0
- package/http/server/node/module.d.ts +6 -2
- package/http/server/node/module.js +6 -4
- package/http/server/node/node-http-server.d.ts +2 -0
- package/http/server/node/node-http-server.js +7 -0
- package/http/types.d.ts +1 -1
- package/key-value-store/postgres/module.d.ts +7 -1
- package/key-value-store/postgres/module.js +7 -3
- package/lock/postgres/lock.js +0 -1
- package/lock/postgres/module.d.ts +7 -1
- package/lock/postgres/module.js +9 -5
- package/logger/formatter.d.ts +2 -0
- package/logger/formatters/json.js +2 -2
- package/logger/formatters/pretty-print.js +8 -10
- package/logger/logger.d.ts +1 -1
- package/logger/logger.js +15 -12
- package/message-bus/local/module.d.ts +5 -2
- package/message-bus/local/module.js +5 -4
- package/module/module.d.ts +2 -1
- package/module/module.js +3 -0
- package/module/modules/web-server.module.d.ts +11 -6
- package/module/modules/web-server.module.js +15 -10
- package/orm/decorators.d.ts +24 -1
- package/orm/decorators.js +40 -4
- package/orm/query/base.d.ts +17 -17
- package/orm/query/base.js +1 -1
- package/orm/repository.types.d.ts +45 -1
- package/orm/schemas/tsvector.js +1 -1
- package/orm/server/drizzle/schema-converter.d.ts +3 -1
- package/orm/server/drizzle/schema-converter.js +120 -14
- package/orm/server/index.d.ts +1 -0
- package/orm/server/index.js +1 -0
- package/orm/server/module.d.ts +4 -2
- package/orm/server/module.js +6 -5
- package/orm/server/query-converter.d.ts +6 -3
- package/orm/server/query-converter.js +32 -20
- package/orm/server/repository-config.d.ts +8 -0
- package/orm/server/repository-config.js +8 -0
- package/orm/server/repository.d.ts +117 -43
- package/orm/server/repository.js +757 -253
- package/orm/server/transaction.d.ts +4 -2
- package/orm/server/transaction.js +14 -5
- package/orm/server/transactional.d.ts +6 -2
- package/orm/server/transactional.js +39 -9
- package/orm/server/types.d.ts +2 -0
- package/orm/sqls/case-when.d.ts +3 -3
- package/orm/sqls/case-when.js +2 -2
- package/orm/sqls/sqls.d.ts +31 -5
- package/orm/sqls/sqls.js +69 -6
- package/orm/tests/data-types.test.d.ts +1 -0
- package/orm/tests/data-types.test.js +39 -0
- package/orm/tests/decorators.test.d.ts +1 -0
- package/orm/tests/decorators.test.js +77 -0
- package/orm/tests/encryption.test.d.ts +1 -0
- package/orm/tests/encryption.test.js +34 -0
- package/orm/tests/query-complex.test.d.ts +1 -0
- package/orm/tests/query-complex.test.js +203 -0
- package/orm/tests/query-converter-complex.test.d.ts +1 -0
- package/orm/tests/query-converter-complex.test.js +126 -0
- package/orm/tests/query-converter.test.d.ts +1 -0
- package/orm/tests/query-converter.test.js +123 -0
- package/orm/tests/repository-advanced.test.d.ts +1 -0
- package/orm/tests/repository-advanced.test.js +232 -0
- package/orm/tests/repository-attributes.test.d.ts +1 -0
- package/orm/tests/repository-attributes.test.js +99 -0
- package/orm/tests/repository-comprehensive.test.d.ts +1 -0
- package/orm/tests/repository-comprehensive.test.js +187 -0
- package/orm/tests/repository-coverage.test.d.ts +1 -0
- package/orm/tests/repository-coverage.test.js +303 -0
- package/orm/tests/repository-cti-complex.test.d.ts +1 -0
- package/orm/tests/repository-cti-complex.test.js +170 -0
- package/orm/tests/repository-cti-embedded.test.d.ts +1 -0
- package/orm/tests/repository-cti-embedded.test.js +188 -0
- package/orm/tests/repository-cti-extensive.test.d.ts +1 -0
- package/orm/tests/repository-cti-extensive.test.js +308 -0
- package/orm/tests/repository-cti-mapping.test.d.ts +1 -0
- package/orm/tests/repository-cti-mapping.test.js +121 -0
- package/orm/tests/repository-cti-search.test.d.ts +1 -0
- package/orm/tests/repository-cti-search.test.js +152 -0
- package/orm/tests/repository-cti-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-cti-soft-delete.test.js +115 -0
- package/orm/tests/repository-cti-transactions.test.d.ts +1 -0
- package/orm/tests/repository-cti-transactions.test.js +126 -0
- package/orm/tests/repository-cti-upsert-many.test.d.ts +1 -0
- package/orm/tests/repository-cti-upsert-many.test.js +127 -0
- package/orm/tests/repository-cti.test.d.ts +1 -0
- package/orm/tests/repository-cti.test.js +456 -0
- package/orm/tests/repository-edge-cases.test.d.ts +1 -0
- package/orm/tests/repository-edge-cases.test.js +216 -0
- package/orm/tests/repository-expiration.test.d.ts +1 -0
- package/orm/tests/repository-expiration.test.js +153 -0
- package/orm/tests/repository-extra-coverage.test.d.ts +1 -0
- package/orm/tests/repository-extra-coverage.test.js +546 -0
- package/orm/tests/repository-mapping.test.d.ts +1 -0
- package/orm/tests/repository-mapping.test.js +71 -0
- package/orm/tests/repository-regression.test.d.ts +1 -0
- package/orm/tests/repository-regression.test.js +330 -0
- package/orm/tests/repository-search-coverage.test.d.ts +1 -0
- package/orm/tests/repository-search-coverage.test.js +129 -0
- package/orm/tests/repository-search.test.d.ts +1 -0
- package/orm/tests/repository-search.test.js +116 -0
- package/orm/tests/repository-soft-delete.test.d.ts +1 -0
- package/orm/tests/repository-soft-delete.test.js +143 -0
- package/orm/tests/repository-transactions-nested.test.d.ts +1 -0
- package/orm/tests/repository-transactions-nested.test.js +202 -0
- package/orm/tests/repository-types.test.d.ts +1 -0
- package/orm/tests/repository-types.test.js +218 -0
- package/orm/tests/schema-converter.test.d.ts +1 -0
- package/orm/tests/schema-converter.test.js +81 -0
- package/orm/tests/schema-generation.test.d.ts +1 -0
- package/orm/tests/schema-generation.test.js +127 -0
- package/orm/tests/sql-helpers.test.d.ts +1 -0
- package/orm/tests/sql-helpers.test.js +67 -0
- package/orm/tests/transaction-safety.test.d.ts +1 -0
- package/orm/tests/transaction-safety.test.js +81 -0
- package/orm/tests/transactional.test.d.ts +1 -0
- package/orm/tests/transactional.test.js +224 -0
- package/orm/tests/utils.test.d.ts +1 -0
- package/orm/tests/utils.test.js +70 -0
- package/orm/utils.d.ts +7 -0
- package/orm/utils.js +26 -6
- package/package.json +12 -7
- package/pool/pool.js +1 -1
- package/rate-limit/index.d.ts +2 -0
- package/rate-limit/index.js +2 -0
- package/rate-limit/postgres/drizzle/0000_watery_rage.sql +7 -0
- package/{queue → rate-limit}/postgres/drizzle/meta/0000_snapshot.json +14 -39
- package/rate-limit/postgres/drizzle/meta/_journal.json +13 -0
- package/{queue → rate-limit}/postgres/drizzle.config.js +1 -1
- package/rate-limit/postgres/index.d.ts +4 -0
- package/rate-limit/postgres/index.js +4 -0
- package/rate-limit/postgres/module.d.ts +12 -0
- package/rate-limit/postgres/module.js +28 -0
- package/rate-limit/postgres/postgres-rate-limiter.d.ts +9 -0
- package/rate-limit/postgres/postgres-rate-limiter.js +56 -0
- package/rate-limit/postgres/rate-limit.model.d.ts +8 -0
- package/rate-limit/postgres/rate-limit.model.js +35 -0
- package/rate-limit/postgres/rate-limiter.provider.d.ts +6 -0
- package/rate-limit/postgres/rate-limiter.provider.js +21 -0
- package/rate-limit/postgres/schemas.d.ts +3 -0
- package/rate-limit/postgres/schemas.js +4 -0
- package/rate-limit/provider.d.ts +9 -0
- package/rate-limit/provider.js +2 -0
- package/rate-limit/rate-limiter.d.ts +35 -0
- package/rate-limit/rate-limiter.js +3 -0
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +1 -0
- package/rate-limit/tests/postgres-rate-limiter.test.js +92 -0
- package/signals/implementation/configure.d.ts +3 -0
- package/signals/implementation/configure.js +3 -0
- package/sse/data-stream-source.d.ts +1 -1
- package/sse/data-stream-source.js +6 -6
- package/task-queue/enqueue-batch.d.ts +17 -0
- package/task-queue/enqueue-batch.js +24 -0
- package/{queue → task-queue}/index.d.ts +1 -1
- package/{queue → task-queue}/index.js +1 -1
- package/task-queue/postgres/drizzle/0000_thin_black_panther.sql +74 -0
- package/task-queue/postgres/drizzle/meta/0000_snapshot.json +592 -0
- package/task-queue/postgres/drizzle/meta/_journal.json +13 -0
- package/task-queue/postgres/drizzle.config.d.ts +2 -0
- package/task-queue/postgres/drizzle.config.js +11 -0
- package/task-queue/postgres/index.d.ts +4 -0
- package/task-queue/postgres/index.js +4 -0
- package/task-queue/postgres/module.d.ts +12 -0
- package/task-queue/postgres/module.js +28 -0
- package/task-queue/postgres/schemas.d.ts +16 -0
- package/task-queue/postgres/schemas.js +8 -0
- package/task-queue/postgres/task-queue.d.ts +83 -0
- package/task-queue/postgres/task-queue.js +1054 -0
- package/task-queue/postgres/task-queue.provider.d.ts +7 -0
- package/{queue/postgres/queue.provider.js → task-queue/postgres/task-queue.provider.js} +8 -8
- package/task-queue/postgres/task.model.d.ts +39 -0
- package/task-queue/postgres/task.model.js +178 -0
- package/{queue → task-queue}/provider.d.ts +3 -3
- package/task-queue/provider.js +2 -0
- package/{queue → task-queue}/task-context.d.ts +7 -7
- package/{queue → task-queue}/task-context.js +8 -8
- package/{queue/queue.d.ts → task-queue/task-queue.d.ts} +128 -59
- package/task-queue/task-queue.js +200 -0
- package/task-queue/tests/complex.test.d.ts +1 -0
- package/task-queue/tests/complex.test.js +299 -0
- package/task-queue/tests/dependencies.test.d.ts +1 -0
- package/task-queue/tests/dependencies.test.js +174 -0
- package/task-queue/tests/queue.test.d.ts +1 -0
- package/task-queue/tests/queue.test.js +334 -0
- package/task-queue/tests/worker.test.d.ts +1 -0
- package/task-queue/tests/worker.test.js +163 -0
- package/test1.js +1 -1
- package/test4.js +2 -2
- package/unit-test/index.d.ts +1 -0
- package/unit-test/index.js +1 -0
- package/unit-test/integration-setup.d.ts +55 -0
- package/unit-test/integration-setup.js +182 -0
- package/utils/patterns.d.ts +3 -0
- package/utils/patterns.js +6 -1
- package/audit/drizzle/0001_previous_network.sql +0 -2
- package/audit/drizzle/meta/0001_snapshot.json +0 -195
- package/queue/enqueue-batch.d.ts +0 -17
- package/queue/enqueue-batch.js +0 -18
- package/queue/postgres/drizzle/0000_zippy_moondragon.sql +0 -11
- package/queue/postgres/drizzle/0001_certain_wild_pack.sql +0 -2
- package/queue/postgres/drizzle/0002_dear_meggan.sql +0 -2
- package/queue/postgres/drizzle/0003_tricky_venom.sql +0 -30
- package/queue/postgres/drizzle/meta/0001_snapshot.json +0 -103
- package/queue/postgres/drizzle/meta/0002_snapshot.json +0 -90
- package/queue/postgres/drizzle/meta/0003_snapshot.json +0 -288
- package/queue/postgres/drizzle/meta/_journal.json +0 -34
- package/queue/postgres/index.d.ts +0 -4
- package/queue/postgres/index.js +0 -4
- package/queue/postgres/module.d.ts +0 -9
- package/queue/postgres/module.js +0 -29
- package/queue/postgres/queue.d.ts +0 -60
- package/queue/postgres/queue.js +0 -681
- package/queue/postgres/queue.provider.d.ts +0 -7
- package/queue/postgres/schemas.d.ts +0 -14
- package/queue/postgres/schemas.js +0 -6
- package/queue/postgres/task.model.d.ts +0 -24
- package/queue/postgres/task.model.js +0 -115
- package/queue/provider.js +0 -2
- package/queue/queue.js +0 -131
- package/queue/tests/queue.test.js +0 -623
- package/test3.d.ts +0 -1
- package/test3.js +0 -47
- /package/{queue/tests/queue.test.d.ts → api/server/tests/csrf.middleware.test.d.ts} +0 -0
- /package/circuit-breaker/postgres/drizzle/{0000_hard_shocker.sql → 0000_cooing_korath.sql} +0 -0
- /package/{queue → rate-limit}/postgres/drizzle.config.d.ts +0 -0
|
@@ -7,7 +7,9 @@ export type TransactionConfig = PgTransactionConfig;
|
|
|
7
7
|
export declare abstract class Transaction implements AsyncDisposable {
|
|
8
8
|
#private;
|
|
9
9
|
readonly afterCommit: import("../../utils/async-hook/index.js").AsyncHook<never, never, unknown>;
|
|
10
|
+
readonly parent?: Transaction;
|
|
10
11
|
manualCommit: boolean;
|
|
12
|
+
constructor(parent?: Transaction);
|
|
11
13
|
[Symbol.asyncDispose](): Promise<void>;
|
|
12
14
|
withManualCommit(): void;
|
|
13
15
|
/**
|
|
@@ -23,8 +25,8 @@ export declare abstract class Transaction implements AsyncDisposable {
|
|
|
23
25
|
export declare class DrizzleTransaction extends Transaction {
|
|
24
26
|
#private;
|
|
25
27
|
readonly pgTransaction: PgTransaction;
|
|
26
|
-
constructor(pgTransaction: PgTransaction);
|
|
27
|
-
static create(session: Database | PgTransaction, config?: TransactionConfig): Promise<DrizzleTransaction>;
|
|
28
|
+
constructor(pgTransaction: PgTransaction, parent?: Transaction);
|
|
29
|
+
static create(session: Database | PgTransaction, config?: TransactionConfig, parent?: Transaction): Promise<DrizzleTransaction>;
|
|
28
30
|
protected _commit(): Promise<void>;
|
|
29
31
|
protected _rollback(): Promise<void>;
|
|
30
32
|
private setTransactionResultPromise;
|
|
@@ -6,7 +6,11 @@ export class Transaction {
|
|
|
6
6
|
#useCounter = 0;
|
|
7
7
|
#done = false;
|
|
8
8
|
afterCommit = asyncHook();
|
|
9
|
+
parent;
|
|
9
10
|
manualCommit = false;
|
|
11
|
+
constructor(parent) {
|
|
12
|
+
this.parent = parent;
|
|
13
|
+
}
|
|
10
14
|
async [Symbol.asyncDispose]() {
|
|
11
15
|
if (!this.#done) {
|
|
12
16
|
await this.rollback();
|
|
@@ -49,7 +53,12 @@ export class Transaction {
|
|
|
49
53
|
}
|
|
50
54
|
this.#done = true;
|
|
51
55
|
await this._commit();
|
|
52
|
-
|
|
56
|
+
if (this.parent) {
|
|
57
|
+
this.parent.afterCommit.register(async () => await this.afterCommit.trigger());
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
await this.afterCommit.trigger();
|
|
61
|
+
}
|
|
53
62
|
}
|
|
54
63
|
async rollback() {
|
|
55
64
|
if (this.#done) {
|
|
@@ -63,14 +72,14 @@ export class DrizzleTransaction extends Transaction {
|
|
|
63
72
|
#deferPromise = new DeferredPromise();
|
|
64
73
|
pgTransaction;
|
|
65
74
|
#pgTransactionResultPromise;
|
|
66
|
-
constructor(pgTransaction) {
|
|
67
|
-
super();
|
|
75
|
+
constructor(pgTransaction, parent) {
|
|
76
|
+
super(parent);
|
|
68
77
|
this.pgTransaction = pgTransaction;
|
|
69
78
|
}
|
|
70
|
-
static async create(session, config) {
|
|
79
|
+
static async create(session, config, parent) {
|
|
71
80
|
const instancePromise = new DeferredPromise();
|
|
72
81
|
const pgTransactionResultPromise = session.transaction(async (tx) => {
|
|
73
|
-
const transaction = new DrizzleTransaction(tx);
|
|
82
|
+
const transaction = new DrizzleTransaction(tx, parent);
|
|
74
83
|
instancePromise.resolve(transaction);
|
|
75
84
|
await transaction.#deferPromise;
|
|
76
85
|
}, config);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type InjectionToken, type ResolveArgument } from '../../injector/index.js';
|
|
2
|
+
import type { Type } from '../../types/index.js';
|
|
2
3
|
import { Database } from './database.js';
|
|
3
4
|
import { Transaction, type PgTransaction, type TransactionConfig } from './transaction.js';
|
|
4
5
|
export type TransactionInitOptions = TransactionConfig & {
|
|
@@ -11,7 +12,7 @@ export type TransactionInitOptions = TransactionConfig & {
|
|
|
11
12
|
export type TransactionHandler<R> = (transaction: Transaction) => Promise<R>;
|
|
12
13
|
type TransactionalContext<ContextData = unknown> = {
|
|
13
14
|
session: Database | PgTransaction;
|
|
14
|
-
|
|
15
|
+
instances: WeakMap<Type, WeakMap<Database | PgTransaction, any>>;
|
|
15
16
|
data: ContextData;
|
|
16
17
|
};
|
|
17
18
|
declare const getCurrentTransactionalContext: {
|
|
@@ -22,7 +23,7 @@ declare const getCurrentTransactionalContext: {
|
|
|
22
23
|
export { getCurrentTransactionalContext, isInTransactionalContext, runInTransactionalContext };
|
|
23
24
|
export declare abstract class Transactional<ContextData = unknown> {
|
|
24
25
|
#private;
|
|
25
|
-
readonly session:
|
|
26
|
+
readonly session: Database | PgTransaction;
|
|
26
27
|
readonly isInTransaction: boolean;
|
|
27
28
|
constructor();
|
|
28
29
|
/**
|
|
@@ -64,6 +65,9 @@ export declare abstract class Transactional<ContextData = unknown> {
|
|
|
64
65
|
/**
|
|
65
66
|
* Starts a new transaction, executes the provided handler function within it,
|
|
66
67
|
* and automatically commits the transaction if the handler succeeds or rolls it back if it throws an error.
|
|
68
|
+
*
|
|
69
|
+
* If called within an existing transaction, it reuses the existing transaction unless specified otherwise in the config.
|
|
70
|
+
*
|
|
67
71
|
* @template R The return type of the handler.
|
|
68
72
|
* @param handler The function to execute within the transaction.
|
|
69
73
|
* @param config Optional transaction configuration.
|
|
@@ -30,7 +30,15 @@ export class Transactional {
|
|
|
30
30
|
#injector = inject(Injector);
|
|
31
31
|
#classConstructor;
|
|
32
32
|
#context = getCurrentTransactionalContext() ?? {};
|
|
33
|
-
#
|
|
33
|
+
#instances = this.#context.instances ?? new WeakMap();
|
|
34
|
+
get #instanceCache() {
|
|
35
|
+
let cache = this.#instances.get(this.#classConstructor);
|
|
36
|
+
if (isUndefined(cache)) {
|
|
37
|
+
cache = new WeakMap();
|
|
38
|
+
this.#instances.set(this.#classConstructor, cache);
|
|
39
|
+
}
|
|
40
|
+
return cache;
|
|
41
|
+
}
|
|
34
42
|
session = this.#context.session ?? inject(Database);
|
|
35
43
|
isInTransaction = this.session instanceof DrizzlePgTransaction;
|
|
36
44
|
constructor() {
|
|
@@ -42,13 +50,14 @@ export class Transactional {
|
|
|
42
50
|
* @returns A promise that resolves to the new Transaction instance.
|
|
43
51
|
*/
|
|
44
52
|
async startTransaction(config) {
|
|
45
|
-
if ((config?.useExisting
|
|
53
|
+
if ((config?.useExisting == true) && this.isInTransaction) {
|
|
46
54
|
const existing = transactionCache.get(this.session);
|
|
47
55
|
if (isDefined(existing)) {
|
|
48
56
|
return existing;
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
|
-
const
|
|
59
|
+
const parentTransaction = tryGetTstdlTransaction(this.session);
|
|
60
|
+
const transaction = await DrizzleTransaction.create(this.session, config, parentTransaction);
|
|
52
61
|
transactionCache.set(transaction.pgTransaction, transaction);
|
|
53
62
|
return transaction;
|
|
54
63
|
}
|
|
@@ -68,7 +77,7 @@ export class Transactional {
|
|
|
68
77
|
}
|
|
69
78
|
const context = {
|
|
70
79
|
session: session,
|
|
71
|
-
|
|
80
|
+
instances: this.#instances,
|
|
72
81
|
data: this.getTransactionalContextData(),
|
|
73
82
|
};
|
|
74
83
|
const repositoryWithSession = runInInjectionContext(this.#injector, () => runInTransactionalContext(context, () => new this.#classConstructor()));
|
|
@@ -108,11 +117,19 @@ export class Transactional {
|
|
|
108
117
|
if (isUndefined(existingTransaction)) {
|
|
109
118
|
return await this.transaction(handler);
|
|
110
119
|
}
|
|
111
|
-
|
|
120
|
+
const context = {
|
|
121
|
+
session: existingTransaction.pgTransaction,
|
|
122
|
+
instances: this.#instances,
|
|
123
|
+
data: this.getTransactionalContextData(),
|
|
124
|
+
};
|
|
125
|
+
return await existingTransaction.use(async () => await runInTransactionalContext(context, async () => await handler(existingTransaction)));
|
|
112
126
|
}
|
|
113
127
|
/**
|
|
114
128
|
* Starts a new transaction, executes the provided handler function within it,
|
|
115
129
|
* and automatically commits the transaction if the handler succeeds or rolls it back if it throws an error.
|
|
130
|
+
*
|
|
131
|
+
* If called within an existing transaction, it reuses the existing transaction unless specified otherwise in the config.
|
|
132
|
+
*
|
|
116
133
|
* @template R The return type of the handler.
|
|
117
134
|
* @param handler The function to execute within the transaction.
|
|
118
135
|
* @param config Optional transaction configuration.
|
|
@@ -120,17 +137,30 @@ export class Transactional {
|
|
|
120
137
|
*/
|
|
121
138
|
async transaction(handler, config) {
|
|
122
139
|
const transaction = await this.startTransaction(config);
|
|
123
|
-
|
|
140
|
+
const context = {
|
|
141
|
+
session: transaction.pgTransaction,
|
|
142
|
+
instances: this.#instances,
|
|
143
|
+
data: this.getTransactionalContextData(),
|
|
144
|
+
};
|
|
145
|
+
return await transaction.use(async () => await runInTransactionalContext(context, async () => await handler(transaction)));
|
|
124
146
|
}
|
|
125
147
|
getTransactionalContextData() {
|
|
126
|
-
return transactionalContextDataGuard;
|
|
148
|
+
return transactionalContextDataGuard;
|
|
127
149
|
}
|
|
128
150
|
}
|
|
129
151
|
export function tryGetTransactionalContextData(_instance) {
|
|
130
|
-
|
|
152
|
+
const data = getCurrentTransactionalContext()?.data;
|
|
153
|
+
if (data == transactionalContextDataGuard) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return data;
|
|
131
157
|
}
|
|
132
158
|
export function getTransactionalContextData(_instance) {
|
|
133
|
-
|
|
159
|
+
const data = getCurrentTransactionalContext(true, getTransactionalContextData).data;
|
|
160
|
+
if (data == transactionalContextDataGuard) {
|
|
161
|
+
throw new Error('function getTransactionalContextData must be implemented to use transactional context data.');
|
|
162
|
+
}
|
|
163
|
+
return data;
|
|
134
164
|
}
|
|
135
165
|
export function tryGetTstdlTransaction(transactionOrSession) {
|
|
136
166
|
if (isUndefined(transactionOrSession)) {
|
package/orm/server/types.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type ColumnDefinition = {
|
|
|
14
14
|
name: string;
|
|
15
15
|
objectPath: JsonPath;
|
|
16
16
|
reflectionData: OrmColumnReflectionData | undefined;
|
|
17
|
+
inherited: boolean;
|
|
18
|
+
table: PgTableFromType | ExtraConfigColumnsFromType;
|
|
17
19
|
buildType: (options: BuildTypeOptions) => PgColumnBuilder<any, any, any, any>;
|
|
18
20
|
dereferenceObjectPath: (obj: Record) => any;
|
|
19
21
|
toDatabase: (value: unknown, context: TransformContext) => any;
|
package/orm/sqls/case-when.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare class CaseBuilder<TReturn = never> {
|
|
|
4
4
|
caseExpression?: SQL | SQLWrapper;
|
|
5
5
|
constructor(expression?: SQL | SQLWrapper);
|
|
6
6
|
/** Adds a WHEN clause. */
|
|
7
|
-
when<TValue>(pattern: SQL | SQLWrapper | string | number | boolean | undefined, result: TValue |
|
|
7
|
+
when<TValue>(pattern: SQL | SQLWrapper | string | number | boolean | undefined, result: SQL<TValue> | TValue | SQLWrapper): CaseBuilder<TReturn | TValue>;
|
|
8
8
|
/**
|
|
9
9
|
* Adds an ELSE clause and finishes the statement.
|
|
10
10
|
* If no WHEN clauses were added, it returns the value directly.
|
|
@@ -21,5 +21,5 @@ export declare class CaseBuilder<TReturn = never> {
|
|
|
21
21
|
* Creates a "Searched Case" builder.
|
|
22
22
|
* Syntax: CASE WHEN condition THEN result ...
|
|
23
23
|
*/
|
|
24
|
-
export declare function caseWhen
|
|
25
|
-
export declare function caseWhen<TValue>(condition: SQL | SQLWrapper | undefined, value: TValue |
|
|
24
|
+
export declare function caseWhen(caseExpression: SQL | SQLWrapper): CaseBuilder;
|
|
25
|
+
export declare function caseWhen<TValue>(condition: SQL | SQLWrapper | string | number | boolean | undefined, value: SQL<TValue> | TValue | SQLWrapper): CaseBuilder<TValue>;
|
package/orm/sqls/case-when.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDefined
|
|
1
|
+
import { isDefined } from '../../utils/type-guards.js';
|
|
2
2
|
import { sql } from 'drizzle-orm';
|
|
3
3
|
export class CaseBuilder {
|
|
4
4
|
cases = [];
|
|
@@ -8,7 +8,7 @@ export class CaseBuilder {
|
|
|
8
8
|
}
|
|
9
9
|
/** Adds a WHEN clause. */
|
|
10
10
|
when(pattern, result) {
|
|
11
|
-
if (
|
|
11
|
+
if (isDefined(pattern)) {
|
|
12
12
|
this.cases.push(sql `WHEN ${pattern} THEN ${result}`);
|
|
13
13
|
}
|
|
14
14
|
return this;
|
package/orm/sqls/sqls.d.ts
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { Column, type AnyColumn, type SQL, type SQLChunk } from 'drizzle-orm';
|
|
8
8
|
import type { GetSelectTableSelection, SelectResultField, TableLike } from 'drizzle-orm/query-builders/select.types';
|
|
9
|
-
import type { EnumerationObject, EnumerationValue } from '../../types/types.js';
|
|
9
|
+
import type { EnumerationObject, EnumerationValue, Record } from '../../types/types.js';
|
|
10
10
|
import { type PgEnumFromEnumeration } from '../enums.js';
|
|
11
11
|
import type { TsVectorWeight } from '../query/index.js';
|
|
12
12
|
import type { Uuid } from '../types.js';
|
|
13
13
|
/** Represents valid units for PostgreSQL interval values. */
|
|
14
14
|
export type IntervalUnit = 'millennium' | 'millenniums' | 'millennia' | 'century' | 'centuries' | 'decade' | 'decades' | 'year' | 'years' | 'day' | 'days' | 'hour' | 'hours' | 'minute' | 'minutes' | 'second' | 'seconds' | 'millisecond' | 'milliseconds' | 'microsecond' | 'microseconds';
|
|
15
15
|
export type ExclusiveColumnCondition = Column | boolean | SQL;
|
|
16
|
+
export declare const simpleJsonKeyPattern: RegExp;
|
|
16
17
|
export type TsHeadlineOptions = {
|
|
17
18
|
/**
|
|
18
19
|
* The longest headline to output.
|
|
@@ -114,8 +115,7 @@ export declare function exclusiveNotNull(...columns: Column[]): SQL;
|
|
|
114
115
|
* By default, it generates an `IS NOT NULL` check.
|
|
115
116
|
*/
|
|
116
117
|
export declare function enumerationCaseWhen<T extends EnumerationObject>(enumeration: T, discriminator: Column, conditionMapping: Record<EnumerationValue<T>, Column | [Column, ...Column[]] | boolean | SQL>, defaultColumnCondition?: (column: [Column, ...Column[]]) => SQL<unknown> | undefined): SQL;
|
|
117
|
-
export declare function array<T>(values: SQL<T>[]): SQL<T[]>;
|
|
118
|
-
export declare function array<T = unknown>(values: SQLChunk[]): SQL<T[]>;
|
|
118
|
+
export declare function array<T>(values: readonly (SQL<T> | SQLChunk | T)[]): SQL<T[]>;
|
|
119
119
|
export declare function autoAlias<T>(column: AnyColumn<{
|
|
120
120
|
data: T;
|
|
121
121
|
}>): SQL.Aliased<T>;
|
|
@@ -183,7 +183,28 @@ export declare function greatest<T extends (Column | SQL | number)[]>(...values:
|
|
|
183
183
|
[P in keyof T]: T[P] extends number ? Exclude<T[P], number> | SQL<number> : T[P];
|
|
184
184
|
}[number]>>;
|
|
185
185
|
export declare function greatest<T>(...values: T[]): SQL<SelectResultField<T>>;
|
|
186
|
-
export declare function unnest<T>(array: SQL<readonly T[]>): SQL<T>;
|
|
186
|
+
export declare function unnest<T>(array: SQL<readonly T[]> | SQL.Aliased<readonly T[]> | Column): SQL<T>;
|
|
187
|
+
/**
|
|
188
|
+
* Creates a PostgreSQL array contains operator expression (@>).
|
|
189
|
+
* @param left - The array column or expression.
|
|
190
|
+
* @param right - The array value or expression to check for containment.
|
|
191
|
+
* @returns A Drizzle SQL object representing the array contains operation.
|
|
192
|
+
*/
|
|
193
|
+
export declare function arrayContains<T>(left: Column | SQL<readonly T[]>, right: readonly T[] | Column | SQL<readonly T[]>): SQL<boolean>;
|
|
194
|
+
/**
|
|
195
|
+
* Creates a PostgreSQL array is contained by operator expression (<@).
|
|
196
|
+
* @param left - The array value or expression to check.
|
|
197
|
+
* @param right - The array column or expression to check against.
|
|
198
|
+
* @returns A Drizzle SQL object representing the array is contained by operation.
|
|
199
|
+
*/
|
|
200
|
+
export declare function arrayIsContainedBy<T>(left: readonly T[] | Column | SQL<readonly T[]>, right: Column | SQL<readonly T[]>): SQL<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* Creates a PostgreSQL array overlaps operator expression (&&).
|
|
203
|
+
* @param left - The first array column or expression.
|
|
204
|
+
* @param right - The second array value or expression.
|
|
205
|
+
* @returns A Drizzle SQL object representing the array overlaps operation.
|
|
206
|
+
*/
|
|
207
|
+
export declare function arrayOverlaps<T>(left: Column | SQL<readonly T[]>, right: readonly T[] | Column | SQL<readonly T[]>): SQL<boolean>;
|
|
187
208
|
export declare function toTsVector(language: string | SQLChunk, text: string | SQLChunk): SQL<string>;
|
|
188
209
|
export declare function tsvectorToArray(tsvector: SQL): SQL<string[]>;
|
|
189
210
|
/**
|
|
@@ -283,4 +304,9 @@ export declare function isStrictWordSimilar(left: string | SQLChunk, right: stri
|
|
|
283
304
|
export declare function distance(left: string | SQLChunk, right: string | SQLChunk): SQL<number>;
|
|
284
305
|
export declare function wordDistance(left: string | SQLChunk, right: string | SQLChunk): SQL<number>;
|
|
285
306
|
export declare function strictWordDistance(left: string | SQLChunk, right: string | SQLChunk): SQL<number>;
|
|
286
|
-
export declare function jsonbBuildObject(properties: Record<string,
|
|
307
|
+
export declare function jsonbBuildObject(properties: Record<string, unknown> | readonly [string, unknown][]): SQL;
|
|
308
|
+
/**
|
|
309
|
+
* A recursive utility to build PostgreSQL JSONB from TS structures.
|
|
310
|
+
* Supports: Nested Objects, Arrays, Drizzle Columns, and Raw SQL.
|
|
311
|
+
*/
|
|
312
|
+
export declare function buildJsonb(value: any): SQL;
|
package/orm/sqls/sqls.js
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
* simplifying common SQL operations like generating UUIDs, working with intervals,
|
|
5
5
|
* and aggregating data.
|
|
6
6
|
*/
|
|
7
|
-
import { and, Column, eq, sql, isNotNull as sqlIsNotNull, isNull as sqlIsNull, Table } from 'drizzle-orm';
|
|
7
|
+
import { and, Column, eq, isSQLWrapper, sql, isNotNull as sqlIsNotNull, isNull as sqlIsNull, Table } from 'drizzle-orm';
|
|
8
8
|
import { match, P } from 'ts-pattern';
|
|
9
9
|
import { distinct, toArray } from '../../utils/array/array.js';
|
|
10
10
|
import { objectEntries, objectValues } from '../../utils/object/object.js';
|
|
11
|
-
import { assertDefined, isArray, isBoolean, isDefined, isInstanceOf, isNotNull, isNull, isNumber, isString } from '../../utils/type-guards.js';
|
|
11
|
+
import { assertDefined, isArray, isBoolean, isDefined, isInstanceOf, isNotNull, isNull, isNumber, isObject, isString } from '../../utils/type-guards.js';
|
|
12
12
|
import { getEnumName } from '../enums.js';
|
|
13
13
|
import { caseWhen } from './case-when.js';
|
|
14
|
+
export const simpleJsonKeyPattern = /^[a-zA-Z0-9_-]+$/u;
|
|
14
15
|
/** Drizzle SQL helper for getting the current transaction's timestamp. Returns a Date object. */
|
|
15
16
|
export const TRANSACTION_TIMESTAMP = sql `transaction_timestamp()`;
|
|
16
17
|
/** Drizzle SQL helper for generating a random UUID (v4). Returns a Uuid string. */
|
|
@@ -115,7 +116,8 @@ ${sql.join(whens, sql `\n`)}
|
|
|
115
116
|
END`;
|
|
116
117
|
}
|
|
117
118
|
export function array(values) {
|
|
118
|
-
const
|
|
119
|
+
const chunks = values.map((value) => isSQLWrapper(value) ? value : sql `${value}`);
|
|
120
|
+
const valueString = sql.join(chunks, sql.raw(', '));
|
|
119
121
|
return sql `ARRAY[${valueString}]`;
|
|
120
122
|
}
|
|
121
123
|
export function autoAlias(column) {
|
|
@@ -206,6 +208,36 @@ export function greatest(...values) {
|
|
|
206
208
|
export function unnest(array) {
|
|
207
209
|
return sql `unnest(${array})`;
|
|
208
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates a PostgreSQL array contains operator expression (@>).
|
|
213
|
+
* @param left - The array column or expression.
|
|
214
|
+
* @param right - The array value or expression to check for containment.
|
|
215
|
+
* @returns A Drizzle SQL object representing the array contains operation.
|
|
216
|
+
*/
|
|
217
|
+
export function arrayContains(left, right) {
|
|
218
|
+
const rightSql = isArray(right) ? array(right) : right;
|
|
219
|
+
return sql `(${left} @> ${rightSql})`;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Creates a PostgreSQL array is contained by operator expression (<@).
|
|
223
|
+
* @param left - The array value or expression to check.
|
|
224
|
+
* @param right - The array column or expression to check against.
|
|
225
|
+
* @returns A Drizzle SQL object representing the array is contained by operation.
|
|
226
|
+
*/
|
|
227
|
+
export function arrayIsContainedBy(left, right) {
|
|
228
|
+
const leftSql = isArray(left) ? array(left) : left;
|
|
229
|
+
return sql `(${leftSql} <@ ${right})`;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Creates a PostgreSQL array overlaps operator expression (&&).
|
|
233
|
+
* @param left - The first array column or expression.
|
|
234
|
+
* @param right - The second array value or expression.
|
|
235
|
+
* @returns A Drizzle SQL object representing the array overlaps operation.
|
|
236
|
+
*/
|
|
237
|
+
export function arrayOverlaps(left, right) {
|
|
238
|
+
const rightSql = isArray(right) ? array(right) : right;
|
|
239
|
+
return sql `(${left} && ${rightSql})`;
|
|
240
|
+
}
|
|
209
241
|
export function toTsVector(language, text) {
|
|
210
242
|
return sql `to_tsvector(${language}, ${text})`;
|
|
211
243
|
}
|
|
@@ -354,8 +386,39 @@ export function strictWordDistance(left, right) {
|
|
|
354
386
|
}
|
|
355
387
|
export function jsonbBuildObject(properties) {
|
|
356
388
|
const entries = isArray(properties) ? properties : objectEntries(properties);
|
|
357
|
-
const chunks =
|
|
358
|
-
|
|
359
|
-
|
|
389
|
+
const chunks = [];
|
|
390
|
+
for (const [key, value] of entries) {
|
|
391
|
+
if (isDefined(value)) {
|
|
392
|
+
const isSimpleKey = simpleJsonKeyPattern.test(key);
|
|
393
|
+
const sqlKey = isSimpleKey ? sql.raw(`'${key}'`) : sql `${key}`;
|
|
394
|
+
chunks.push(sqlKey, buildJsonb(value));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (chunks.length == 0) {
|
|
398
|
+
return sql `'{}'::jsonb`;
|
|
399
|
+
}
|
|
360
400
|
return sql `jsonb_build_object(${sql.join(chunks, sql `, `)})`;
|
|
361
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* A recursive utility to build PostgreSQL JSONB from TS structures.
|
|
404
|
+
* Supports: Nested Objects, Arrays, Drizzle Columns, and Raw SQL.
|
|
405
|
+
*/
|
|
406
|
+
export function buildJsonb(value) {
|
|
407
|
+
if (isSQLWrapper(value)) {
|
|
408
|
+
return sql `${value}`;
|
|
409
|
+
}
|
|
410
|
+
if (isNull(value)) {
|
|
411
|
+
return sql `null`;
|
|
412
|
+
}
|
|
413
|
+
if (isArray(value)) {
|
|
414
|
+
if (value.length == 0) {
|
|
415
|
+
return sql `'[]'::jsonb`;
|
|
416
|
+
}
|
|
417
|
+
const elements = value.map((inner) => buildJsonb(inner));
|
|
418
|
+
return sql `jsonb_build_array(${sql.join(elements, sql `, `)})`;
|
|
419
|
+
}
|
|
420
|
+
if (isObject(value)) {
|
|
421
|
+
return jsonbBuildObject(value);
|
|
422
|
+
}
|
|
423
|
+
return sql `${value}`;
|
|
424
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { dateToNumericDate, numericDateToDateObject } from '../../utils/date-time.js';
|
|
3
|
+
describe('ORM Data Types - numericDate Logic', () => {
|
|
4
|
+
test('dateToNumericDate should return days since epoch', () => {
|
|
5
|
+
const date = new Date(Date.UTC(2024, 0, 1));
|
|
6
|
+
expect(dateToNumericDate(date)).toBe(19723);
|
|
7
|
+
});
|
|
8
|
+
test('numericDateToDateObject should convert days since epoch to date components', () => {
|
|
9
|
+
const { year, month, day } = numericDateToDateObject(19723);
|
|
10
|
+
expect(year).toBe(2024);
|
|
11
|
+
expect(month).toBe(1);
|
|
12
|
+
expect(day).toBe(1);
|
|
13
|
+
});
|
|
14
|
+
test('leap year handling (2024-02-29)', () => {
|
|
15
|
+
const leapDate = new Date(Date.UTC(2024, 1, 29));
|
|
16
|
+
const numeric = dateToNumericDate(leapDate);
|
|
17
|
+
expect(numeric).toBe(19782);
|
|
18
|
+
const { year, month, day } = numericDateToDateObject(19782);
|
|
19
|
+
expect(year).toBe(2024);
|
|
20
|
+
expect(month).toBe(2);
|
|
21
|
+
expect(day).toBe(29);
|
|
22
|
+
});
|
|
23
|
+
test('epoch start (1970-01-01)', () => {
|
|
24
|
+
const epoch = new Date(Date.UTC(1970, 0, 1));
|
|
25
|
+
expect(dateToNumericDate(epoch)).toBe(0);
|
|
26
|
+
const { year, month, day } = numericDateToDateObject(0);
|
|
27
|
+
expect(year).toBe(1970);
|
|
28
|
+
expect(month).toBe(1);
|
|
29
|
+
expect(day).toBe(1);
|
|
30
|
+
});
|
|
31
|
+
test('before epoch (1969-12-31)', () => {
|
|
32
|
+
const beforeEpoch = new Date(Date.UTC(1969, 11, 31));
|
|
33
|
+
expect(dateToNumericDate(beforeEpoch)).toBe(-1);
|
|
34
|
+
const { year, month, day } = numericDateToDateObject(-1);
|
|
35
|
+
expect(year).toBe(1969);
|
|
36
|
+
expect(month).toBe(12);
|
|
37
|
+
expect(day).toBe(31);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
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 { describe, expect, test } from 'vitest';
|
|
11
|
+
import { reflectionRegistry } from '../../reflection/index.js';
|
|
12
|
+
import { Entity } from '../entity.js';
|
|
13
|
+
import { Inheritance, ChildEntity, Column } from '../decorators.js';
|
|
14
|
+
import { StringProperty } from '../../schema/index.js';
|
|
15
|
+
describe('ORM Inheritance Decorators', () => {
|
|
16
|
+
test('should register inheritance metadata on parent', () => {
|
|
17
|
+
let BaseUser = class BaseUser extends Entity {
|
|
18
|
+
kind;
|
|
19
|
+
};
|
|
20
|
+
__decorate([
|
|
21
|
+
StringProperty(),
|
|
22
|
+
Column({}),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], BaseUser.prototype, "kind", void 0);
|
|
25
|
+
BaseUser = __decorate([
|
|
26
|
+
Inheritance({ strategy: 'joined', discriminatorColumn: 'kind' })
|
|
27
|
+
], BaseUser);
|
|
28
|
+
const metadata = reflectionRegistry.getMetadata(BaseUser);
|
|
29
|
+
const ormData = metadata?.data.tryGet('orm');
|
|
30
|
+
expect(ormData?.inheritance).toBeDefined();
|
|
31
|
+
expect(ormData?.inheritance?.discriminatorColumn).toBe('kind');
|
|
32
|
+
expect(ormData?.inheritance?.subclasses).toBeInstanceOf(Array);
|
|
33
|
+
});
|
|
34
|
+
test('should register child entity metadata and link to parent', () => {
|
|
35
|
+
let Vehicle = class Vehicle extends Entity {
|
|
36
|
+
type;
|
|
37
|
+
};
|
|
38
|
+
__decorate([
|
|
39
|
+
StringProperty(),
|
|
40
|
+
Column({}),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], Vehicle.prototype, "type", void 0);
|
|
43
|
+
Vehicle = __decorate([
|
|
44
|
+
Inheritance({ strategy: 'joined', discriminatorColumn: 'type' })
|
|
45
|
+
], Vehicle);
|
|
46
|
+
let Car = class Car extends Vehicle {
|
|
47
|
+
};
|
|
48
|
+
Car = __decorate([
|
|
49
|
+
ChildEntity('car')
|
|
50
|
+
], Car);
|
|
51
|
+
const parentMetadata = reflectionRegistry.getMetadata(Vehicle);
|
|
52
|
+
const parentOrmData = parentMetadata?.data.tryGet('orm');
|
|
53
|
+
const childMetadata = reflectionRegistry.getMetadata(Car);
|
|
54
|
+
const childOrmData = childMetadata?.data.tryGet('orm');
|
|
55
|
+
// Check Child Metadata
|
|
56
|
+
expect(childOrmData?.childEntity).toBeDefined();
|
|
57
|
+
expect(childOrmData?.childEntity?.discriminatorValue).toBe('car');
|
|
58
|
+
// Check Parent Link
|
|
59
|
+
expect(parentOrmData?.inheritance?.subclasses).toContain(Car);
|
|
60
|
+
});
|
|
61
|
+
test('should use default discriminator column if not provided', () => {
|
|
62
|
+
let Animal = class Animal extends Entity {
|
|
63
|
+
type;
|
|
64
|
+
};
|
|
65
|
+
__decorate([
|
|
66
|
+
StringProperty(),
|
|
67
|
+
Column({}),
|
|
68
|
+
__metadata("design:type", String)
|
|
69
|
+
], Animal.prototype, "type", void 0);
|
|
70
|
+
Animal = __decorate([
|
|
71
|
+
Inheritance({ strategy: 'joined' })
|
|
72
|
+
], Animal);
|
|
73
|
+
const metadata = reflectionRegistry.getMetadata(Animal);
|
|
74
|
+
const ormData = metadata?.data.tryGet('orm');
|
|
75
|
+
expect(ormData?.inheritance?.discriminatorColumn).toBe('type');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { DetailsError } from '../../errors/index.js';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import { decryptBytes, encryptBytes } from '../server/encryption.js';
|
|
4
|
+
describe('ORM Encryption', () => {
|
|
5
|
+
async function generateKey() {
|
|
6
|
+
return await globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
|
|
7
|
+
}
|
|
8
|
+
test('should encrypt and decrypt correctly', async () => {
|
|
9
|
+
const key = await generateKey();
|
|
10
|
+
const data = new TextEncoder().encode('Hello, ORM Encryption!');
|
|
11
|
+
const encrypted = await encryptBytes(data, key);
|
|
12
|
+
const decrypted = await decryptBytes(encrypted, key);
|
|
13
|
+
expect(new TextDecoder().decode(decrypted)).toBe('Hello, ORM Encryption!');
|
|
14
|
+
});
|
|
15
|
+
test('should throw DetailsError on corrupted data', async () => {
|
|
16
|
+
const key = await generateKey();
|
|
17
|
+
const data = new TextEncoder().encode('Corrupt me');
|
|
18
|
+
const encrypted = await encryptBytes(data, key);
|
|
19
|
+
// Corrupt the ciphertext (last byte)
|
|
20
|
+
const lastIndex = encrypted.length - 1;
|
|
21
|
+
encrypted[lastIndex] = encrypted[lastIndex] ^ 1;
|
|
22
|
+
await expect(decryptBytes(encrypted, key)).rejects.toThrow(DetailsError);
|
|
23
|
+
await expect(decryptBytes(encrypted, key)).rejects.toThrow('Decrypt error');
|
|
24
|
+
});
|
|
25
|
+
test('should throw error on invalid version', async () => {
|
|
26
|
+
const key = await generateKey();
|
|
27
|
+
const data = new TextEncoder().encode('Wrong version');
|
|
28
|
+
const encrypted = await encryptBytes(data, key);
|
|
29
|
+
// Corrupt version byte (set to a very high number)
|
|
30
|
+
const view = new DataView(encrypted.buffer, encrypted.byteOffset, encrypted.length);
|
|
31
|
+
view.setUint16(0, 9999);
|
|
32
|
+
await expect(decryptBytes(encrypted, key)).rejects.toThrow('Invalid encryption version.');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|