@getstrata/core 2.2.35 → 2.2.37
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/CHANGELOG.md +10 -0
- package/dist/core/database/baseRepository.d.ts +4 -0
- package/dist/core/database/index.d.ts +1 -1
- package/dist/core/database/transaction.d.ts +5 -1
- package/dist/entries/audit/exportAuditLogs.js +22 -5
- package/dist/entries/auth/basicAuthGuard.js +22 -5
- package/dist/entries/auth/membershipService.js +1 -0
- package/dist/entries/auth/scimAuthMiddleware.js +121 -8
- package/dist/entries/cache/repository.js +3 -1
- package/dist/entries/cache/simpleCache.js +2 -1
- package/dist/entries/cache/simpleCacheStore.js +2 -1
- package/dist/entries/database/baseRepository.js +1 -0
- package/dist/entries/jobs/exportAuditLogsJob.js +25 -6
- package/dist/entries/jobs/invalidateCacheTagsJob.js +3 -1
- package/dist/entries/queue/failedJobRepository.js +2 -1
- package/dist/entries/queue/failedJobService.js +2 -1
- package/dist/entries/queue/queueMetrics.js +22 -5
- package/dist/entries/tenant/databaseTenantContext.js +22 -5
- package/dist/entries/tenant/tenantDatabaseScope.js +22 -5
- package/dist/framework/public-api.d.ts +1 -1
- package/dist/index.js +122 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @getstrata/core changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.37
|
|
4
|
+
|
|
5
|
+
Fix MySQL repository entity-returning mutations with transaction-pinned readback, persisted keys/defaults, honest null and deletion outcomes, complete model event payloads and injected connection ownership. Preserve native Postgres/SQLite RETURNING and conditional affected-row metadata. Close owned generated OpenAPI and failed-job command applications on success and failure before exit; retain both command and cleanup errors. Add mandatory packaged MySQL production column-tenancy CLI and HTTP auth/SCIM acceptance with an owned DML-only account, unchanged route/spec/SDK contracts, native ORM regressions and cleanup tests. Records dogfood issues #232 and #233 without application SQL workarounds.
|
|
6
|
+
|
|
7
|
+
## 2.2.36
|
|
8
|
+
|
|
9
|
+
Add a mandatory installed-package SQLite column-tenancy CLI/OpenAPI/HTTP profile, including cookie/token/JWT/Basic and repeated SCIM isolation, while preserving existing Postgres security, route inventories, compiler combinations and Docker gates. Reconcile observability/rotation trackers against shipped capabilities and remaining operational qualification.
|
|
10
|
+
|
|
11
|
+
Fix declared default exports missing from nine published core subpaths. Preserve defaults in generated non-shared entries and alias the shared BaseRepository default to its canonical root constructor, retaining named exports and singleton/class identity. Extend declaration/runtime verification with value-default and type-only-default regressions; compile all nine imports across the existing 18 generated compiler combinations and execute them in every installed candidate app. Records the published 2.2.35 reproduction from Q01 dogfooding; no shop adapter or node_modules patch.
|
|
12
|
+
|
|
3
13
|
## 2.2.35
|
|
4
14
|
|
|
5
15
|
Retire checked-in HiroApp applications after preserving security, CLI/OpenAPI/HTTP, source, migration and Docker acceptance in generated candidate-package fixtures. Keep all 23 security cases, 40 runtime operations, 22 API/protocol operations, three-engine migration cases and 18 compiler combinations. Make the private root CLI fixture-only, isolate post-commit HTTP databases, and validate the generated production image with restricted runtime credentials, Redis recovery and graceful shutdown. Remove obsolete app regeneration/selectors and update contributor, generator and deployment documentation; retain compatible example preset IDs and explicit application-owned deployment boundaries. Regenerate the sample SDK from the API-only snapshot and verify it against the installed candidate package. Core coverage retains 136 enforced files at 100%; remove only the two deleted private-entrypoint exemptions (272 remaining).
|
|
@@ -35,6 +35,10 @@ declare class BaseRepository<TEntity extends object, PrimaryKey extends keyof TE
|
|
|
35
35
|
constructor(table: TableDefinition<TEntity, PrimaryKey>, connection?: DatabaseConnection);
|
|
36
36
|
private assertTransactionalEvent;
|
|
37
37
|
private runModelMutation;
|
|
38
|
+
private mysqlMutation;
|
|
39
|
+
private mysqlRow;
|
|
40
|
+
private mysqlAffected;
|
|
41
|
+
private mysqlWriteById;
|
|
38
42
|
count(options?: ExtendedQueryOptions<TEntity>): Promise<number>;
|
|
39
43
|
findAll(options?: ExtendedQueryOptions<TEntity>): Promise<TEntity[]>;
|
|
40
44
|
paginate(options: {
|
|
@@ -24,7 +24,7 @@ export { Blueprint, ColumnDefinition, compileBlueprint, createSchemaBuilder, For
|
|
|
24
24
|
export { createSqliteConnection } from "./sqliteConnection.ts";
|
|
25
25
|
export type { TableDefinition } from "./table.ts";
|
|
26
26
|
export { defineTable } from "./table.ts";
|
|
27
|
-
export { runInTransaction } from "./transaction.ts";
|
|
27
|
+
export { isActiveTransactionConnection, runInTransaction } from "./transaction.ts";
|
|
28
28
|
export type { DatabaseComparable, DatabaseScalar, MutationValues, QueryFilterValue, QueryJoin, QueryJoinOn, QueryOperator, QueryOptions, QueryOrder, QuerySelectItem, QueryWhere, UpdateValues, } from "./types.ts";
|
|
29
29
|
export type { WhereNode } from "./whereBuilder.ts";
|
|
30
30
|
export { WhereBuilder } from "./whereBuilder.ts";
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { type TransactionAcquisitionMetrics } from "./acquisitionMetrics.ts";
|
|
2
2
|
import type { DatabaseConnection } from "./baseRepository.ts";
|
|
3
3
|
import { hasActiveTransaction, requestTransactionRollback } from "./transactionControl.ts";
|
|
4
|
+
/** Recognizes the callback handle without admitting an unrelated pool. */
|
|
5
|
+
declare function isActiveTransactionConnection(connection: DatabaseConnection): boolean;
|
|
4
6
|
interface TransactionOptions {
|
|
7
|
+
/** Explicit root pool for injected repositories; cannot switch an active transaction's owner. */
|
|
8
|
+
connection?: DatabaseConnection;
|
|
5
9
|
/** Cancel admission/pool checkout only. Does not cancel SQL or an admitted business callback. */
|
|
6
10
|
acquisitionSignal?: AbortSignal;
|
|
7
11
|
/** Observe native checkout only; requires a reserve-capable adapter. */
|
|
@@ -11,4 +15,4 @@ declare function runInTransaction<TValue>(operation: (connection: DatabaseConnec
|
|
|
11
15
|
export type { TransactionAcquisitionMetrics, TransactionAcquisitionSnapshot, } from "./acquisitionMetrics.ts";
|
|
12
16
|
export { createTransactionAcquisitionMetrics, renderTransactionAcquisitionMetrics, } from "./acquisitionMetrics.ts";
|
|
13
17
|
export type { TransactionOptions };
|
|
14
|
-
export { hasActiveTransaction, requestTransactionRollback, runInTransaction };
|
|
18
|
+
export { hasActiveTransaction, isActiveTransactionConnection, requestTransactionRollback, runInTransaction, };
|
|
@@ -733,6 +733,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
733
733
|
|
|
734
734
|
// ../../src/core/database/transaction.ts
|
|
735
735
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
736
|
+
function scopedConnection(source) {
|
|
737
|
+
const connection = createDatabaseConnection(source);
|
|
738
|
+
transactionAliases.set(connection, source);
|
|
739
|
+
return connection;
|
|
740
|
+
}
|
|
741
|
+
function isActiveTransactionConnection(connection) {
|
|
742
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
743
|
+
return false;
|
|
744
|
+
const active = getActiveDatabaseConnection(connection);
|
|
745
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
746
|
+
}
|
|
736
747
|
async function runInSavepoint(connection, operation) {
|
|
737
748
|
const inherited = transactionFrame.getStore();
|
|
738
749
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -749,7 +760,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
749
760
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
750
761
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
751
762
|
try {
|
|
752
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
763
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
753
764
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
754
765
|
return result;
|
|
755
766
|
} catch (error) {
|
|
@@ -772,9 +783,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
772
783
|
signal?.throwIfAborted();
|
|
773
784
|
return operation(connection);
|
|
774
785
|
};
|
|
775
|
-
const pool = resolveRepositoryConnection();
|
|
786
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
776
787
|
if (hasActiveDatabaseConnection()) {
|
|
777
|
-
|
|
788
|
+
const active = getActiveDatabaseConnection(pool);
|
|
789
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
790
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
791
|
+
return await runInSavepoint(active, admittedOperation);
|
|
778
792
|
}
|
|
779
793
|
if (!supportsTransactions(pool)) {
|
|
780
794
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -793,14 +807,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
793
807
|
if (!supportsTransactions(connection))
|
|
794
808
|
throw new Error("Reserved database connection does not support transactions.");
|
|
795
809
|
return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
|
|
796
|
-
|
|
810
|
+
transactionRoots.set(transaction, pool);
|
|
811
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
797
812
|
}));
|
|
798
813
|
} finally {
|
|
799
814
|
await reserved?.release();
|
|
800
815
|
}
|
|
801
816
|
}));
|
|
802
817
|
}
|
|
803
|
-
var transactionFrame, outerFrames;
|
|
818
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
804
819
|
var init_transaction = __esm(() => {
|
|
805
820
|
init_deferredModelEvents();
|
|
806
821
|
init_asyncContextStore();
|
|
@@ -812,6 +827,8 @@ var init_transaction = __esm(() => {
|
|
|
812
827
|
init_acquisitionMetrics();
|
|
813
828
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
814
829
|
outerFrames = new WeakMap;
|
|
830
|
+
transactionRoots = new WeakMap;
|
|
831
|
+
transactionAliases = new WeakMap;
|
|
815
832
|
});
|
|
816
833
|
|
|
817
834
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
@@ -733,6 +733,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
733
733
|
|
|
734
734
|
// ../../src/core/database/transaction.ts
|
|
735
735
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
736
|
+
function scopedConnection(source) {
|
|
737
|
+
const connection = createDatabaseConnection(source);
|
|
738
|
+
transactionAliases.set(connection, source);
|
|
739
|
+
return connection;
|
|
740
|
+
}
|
|
741
|
+
function isActiveTransactionConnection(connection) {
|
|
742
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
743
|
+
return false;
|
|
744
|
+
const active = getActiveDatabaseConnection(connection);
|
|
745
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
746
|
+
}
|
|
736
747
|
async function runInSavepoint(connection, operation) {
|
|
737
748
|
const inherited = transactionFrame.getStore();
|
|
738
749
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -749,7 +760,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
749
760
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
750
761
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
751
762
|
try {
|
|
752
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
763
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
753
764
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
754
765
|
return result;
|
|
755
766
|
} catch (error) {
|
|
@@ -772,9 +783,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
772
783
|
signal?.throwIfAborted();
|
|
773
784
|
return operation(connection);
|
|
774
785
|
};
|
|
775
|
-
const pool = resolveRepositoryConnection();
|
|
786
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
776
787
|
if (hasActiveDatabaseConnection()) {
|
|
777
|
-
|
|
788
|
+
const active = getActiveDatabaseConnection(pool);
|
|
789
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
790
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
791
|
+
return await runInSavepoint(active, admittedOperation);
|
|
778
792
|
}
|
|
779
793
|
if (!supportsTransactions(pool)) {
|
|
780
794
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -793,14 +807,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
793
807
|
if (!supportsTransactions(connection))
|
|
794
808
|
throw new Error("Reserved database connection does not support transactions.");
|
|
795
809
|
return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
|
|
796
|
-
|
|
810
|
+
transactionRoots.set(transaction, pool);
|
|
811
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
797
812
|
}));
|
|
798
813
|
} finally {
|
|
799
814
|
await reserved?.release();
|
|
800
815
|
}
|
|
801
816
|
}));
|
|
802
817
|
}
|
|
803
|
-
var transactionFrame, outerFrames;
|
|
818
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
804
819
|
var init_transaction = __esm(() => {
|
|
805
820
|
init_deferredModelEvents();
|
|
806
821
|
init_asyncContextStore();
|
|
@@ -812,6 +827,8 @@ var init_transaction = __esm(() => {
|
|
|
812
827
|
init_acquisitionMetrics();
|
|
813
828
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
814
829
|
outerFrames = new WeakMap;
|
|
830
|
+
transactionRoots = new WeakMap;
|
|
831
|
+
transactionAliases = new WeakMap;
|
|
815
832
|
});
|
|
816
833
|
|
|
817
834
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
@@ -568,6 +568,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
568
568
|
|
|
569
569
|
// ../../src/core/database/transaction.ts
|
|
570
570
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
571
|
+
function scopedConnection(source) {
|
|
572
|
+
const connection = createDatabaseConnection(source);
|
|
573
|
+
transactionAliases.set(connection, source);
|
|
574
|
+
return connection;
|
|
575
|
+
}
|
|
576
|
+
function isActiveTransactionConnection(connection) {
|
|
577
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
578
|
+
return false;
|
|
579
|
+
const active = getActiveDatabaseConnection(connection);
|
|
580
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
581
|
+
}
|
|
571
582
|
async function runInSavepoint(connection, operation) {
|
|
572
583
|
const inherited = transactionFrame.getStore();
|
|
573
584
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -584,7 +595,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
584
595
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
585
596
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
586
597
|
try {
|
|
587
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
598
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
588
599
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
589
600
|
return result;
|
|
590
601
|
} catch (error) {
|
|
@@ -607,9 +618,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
607
618
|
signal?.throwIfAborted();
|
|
608
619
|
return operation(connection);
|
|
609
620
|
};
|
|
610
|
-
const pool = resolveRepositoryConnection();
|
|
621
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
611
622
|
if (hasActiveDatabaseConnection()) {
|
|
612
|
-
|
|
623
|
+
const active = getActiveDatabaseConnection(pool);
|
|
624
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
625
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
626
|
+
return await runInSavepoint(active, admittedOperation);
|
|
613
627
|
}
|
|
614
628
|
if (!supportsTransactions(pool)) {
|
|
615
629
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -628,14 +642,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
628
642
|
if (!supportsTransactions(connection))
|
|
629
643
|
throw new Error("Reserved database connection does not support transactions.");
|
|
630
644
|
return await connection.begin(AsyncLocalStorage2.bind(async (transaction) => {
|
|
631
|
-
|
|
645
|
+
transactionRoots.set(transaction, pool);
|
|
646
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
632
647
|
}));
|
|
633
648
|
} finally {
|
|
634
649
|
await reserved?.release();
|
|
635
650
|
}
|
|
636
651
|
}));
|
|
637
652
|
}
|
|
638
|
-
var transactionFrame, outerFrames;
|
|
653
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
639
654
|
var init_transaction = __esm(() => {
|
|
640
655
|
init_deferredModelEvents();
|
|
641
656
|
init_asyncContextStore();
|
|
@@ -647,6 +662,8 @@ var init_transaction = __esm(() => {
|
|
|
647
662
|
init_acquisitionMetrics();
|
|
648
663
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
649
664
|
outerFrames = new WeakMap;
|
|
665
|
+
transactionRoots = new WeakMap;
|
|
666
|
+
transactionAliases = new WeakMap;
|
|
650
667
|
});
|
|
651
668
|
|
|
652
669
|
// ../../src/core/tenant/tenancyConfig.ts
|
|
@@ -968,7 +985,6 @@ function buildPaginationMeta(input) {
|
|
|
968
985
|
}
|
|
969
986
|
|
|
970
987
|
// ../../src/core/database/baseRepository.ts
|
|
971
|
-
init_connectionContext();
|
|
972
988
|
init_dialect();
|
|
973
989
|
|
|
974
990
|
// ../../src/core/database/errors.ts
|
|
@@ -2515,7 +2531,7 @@ class BaseRepository {
|
|
|
2515
2531
|
assertTransactionalEvent(action) {
|
|
2516
2532
|
if (!eventBus.hasTransactionalListeners(modelEventName(this.table.name, action)))
|
|
2517
2533
|
return;
|
|
2518
|
-
if (!hasActiveTransaction() || this.connection !== repositoryConnection && this.connection
|
|
2534
|
+
if (!hasActiveTransaction() || this.connection !== repositoryConnection && !isActiveTransactionConnection(this.connection))
|
|
2519
2535
|
throw new Error("Transactional model listeners require runInTransaction and the framework-bound repository connection before writing.");
|
|
2520
2536
|
}
|
|
2521
2537
|
async runModelMutation(action, operation) {
|
|
@@ -2523,6 +2539,32 @@ class BaseRepository {
|
|
|
2523
2539
|
return operation();
|
|
2524
2540
|
return runInTransaction(operation);
|
|
2525
2541
|
}
|
|
2542
|
+
mysqlMutation(operation) {
|
|
2543
|
+
return runInTransaction((db) => operation(this.withConnection(db)), this.connection === repositoryConnection ? {} : { connection: this.connection });
|
|
2544
|
+
}
|
|
2545
|
+
mysqlRow(id, onlyTrashed = false) {
|
|
2546
|
+
if (id === undefined || id === null)
|
|
2547
|
+
throw new Error(`MySQL write to ${this.table.name} did not identify its persisted primary key.`);
|
|
2548
|
+
return this.firstOrNull({ [this.table.primaryKey]: id }, {
|
|
2549
|
+
withTrashed: true,
|
|
2550
|
+
...onlyTrashed ? { onlyTrashed: true } : {}
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
mysqlAffected(row) {
|
|
2554
|
+
const count = row?.affectedRows;
|
|
2555
|
+
if (count === undefined || !Number.isSafeInteger(count) || count < 0)
|
|
2556
|
+
throw new Error("MySQL mutations require affectedRows metadata from the framework adapter.");
|
|
2557
|
+
return count;
|
|
2558
|
+
}
|
|
2559
|
+
async mysqlWriteById(query, id, onlyTrashed = false, allowUnchanged = false) {
|
|
2560
|
+
const [row] = await this.connection.unsafe(query.text, query.params);
|
|
2561
|
+
if (!this.mysqlAffected(row)) {
|
|
2562
|
+
if (!allowUnchanged)
|
|
2563
|
+
return null;
|
|
2564
|
+
return this.findById(id);
|
|
2565
|
+
}
|
|
2566
|
+
return this.mysqlRow(id, onlyTrashed);
|
|
2567
|
+
}
|
|
2526
2568
|
async count(options = {}) {
|
|
2527
2569
|
if (options.lock)
|
|
2528
2570
|
throw new Error("Row locks require a row selection, not count().");
|
|
@@ -2531,7 +2573,7 @@ class BaseRepository {
|
|
|
2531
2573
|
}
|
|
2532
2574
|
async findAll(options = {}) {
|
|
2533
2575
|
return await withDatabaseErrorHandling(async () => {
|
|
2534
|
-
if (options.lock && (!hasActiveTransaction() || this.connection !== repositoryConnection && this.connection
|
|
2576
|
+
if (options.lock && (!hasActiveTransaction() || this.connection !== repositoryConnection && !isActiveTransactionConnection(this.connection))) {
|
|
2535
2577
|
throw new Error("Row locks require the framework active transaction connection.");
|
|
2536
2578
|
}
|
|
2537
2579
|
const { whereNodes, ...queryOptions } = options;
|
|
@@ -2743,6 +2785,32 @@ class BaseRepository {
|
|
|
2743
2785
|
return record ?? null;
|
|
2744
2786
|
}
|
|
2745
2787
|
async upsert(values, conflictColumns, updateColumns) {
|
|
2788
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2789
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2790
|
+
const where = {};
|
|
2791
|
+
for (const column of conflictColumns) {
|
|
2792
|
+
if (!this.table.columns.includes(column) || values[column] === undefined || values[column] === null)
|
|
2793
|
+
throw new Error("MySQL upsert requires non-null supplied conflict-column values.");
|
|
2794
|
+
where[column] = values[column];
|
|
2795
|
+
}
|
|
2796
|
+
const query = buildUpsertQuery(this.table, values, conflictColumns, updateColumns);
|
|
2797
|
+
const supplied = this.table.columns.filter((column) => values[column] !== undefined);
|
|
2798
|
+
const updates = updateColumns ?? supplied.filter((column) => !conflictColumns.includes(column));
|
|
2799
|
+
const doNothing = !updates.some((column) => supplied.includes(column));
|
|
2800
|
+
const existing = doNothing ? await repository.firstOrNull(where, {
|
|
2801
|
+
withTrashed: true,
|
|
2802
|
+
lock: { mode: "update" }
|
|
2803
|
+
}) : null;
|
|
2804
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
2805
|
+
repository.mysqlAffected(result);
|
|
2806
|
+
if (doNothing && existing)
|
|
2807
|
+
return null;
|
|
2808
|
+
const generated = result?.insertId;
|
|
2809
|
+
const row = generated !== undefined && String(generated) !== "0" ? await repository.mysqlRow(generated) : await repository.firstOrNull(where, { withTrashed: true });
|
|
2810
|
+
if (!row)
|
|
2811
|
+
throw new Error("MySQL upsert could not resolve the persisted row; transaction rolled back.");
|
|
2812
|
+
return row;
|
|
2813
|
+
}));
|
|
2746
2814
|
return await withDatabaseErrorHandling(async () => {
|
|
2747
2815
|
const { text, params } = buildUpsertQuery(this.table, values, conflictColumns, updateColumns);
|
|
2748
2816
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -2750,6 +2818,8 @@ class BaseRepository {
|
|
|
2750
2818
|
});
|
|
2751
2819
|
}
|
|
2752
2820
|
async incrementById(id, column, amount = 1, extra = {}) {
|
|
2821
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2822
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(() => repository.mysqlWriteById(buildIncrementQuery(this.table, id, column, amount, extra), id, false, true)));
|
|
2753
2823
|
return await withDatabaseErrorHandling(async () => {
|
|
2754
2824
|
const { text, params } = buildIncrementQuery(this.table, id, column, amount, extra);
|
|
2755
2825
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -2761,6 +2831,18 @@ class BaseRepository {
|
|
|
2761
2831
|
}
|
|
2762
2832
|
async create(values) {
|
|
2763
2833
|
this.assertTransactionalEvent("created");
|
|
2834
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2835
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2836
|
+
const query = buildInsertQuery(this.table, values);
|
|
2837
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
2838
|
+
repository.mysqlAffected(result);
|
|
2839
|
+
const key = String(result?.insertId ?? "0") !== "0" ? result?.insertId : values[this.table.primaryKey];
|
|
2840
|
+
const row = await repository.mysqlRow(key);
|
|
2841
|
+
if (!row)
|
|
2842
|
+
throw new Error(`Insert into ${this.table.name} did not return a record.`);
|
|
2843
|
+
await dispatchModelEvent(modelEventName(this.table.name, "created"), row);
|
|
2844
|
+
return row;
|
|
2845
|
+
}));
|
|
2764
2846
|
return await this.runModelMutation("created", () => withDatabaseErrorHandling(async () => {
|
|
2765
2847
|
const { text, params } = buildInsertQuery(this.table, values);
|
|
2766
2848
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -2796,6 +2878,13 @@ class BaseRepository {
|
|
|
2796
2878
|
}
|
|
2797
2879
|
async updateById(id, changes) {
|
|
2798
2880
|
this.assertTransactionalEvent("updated");
|
|
2881
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2882
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2883
|
+
const row = await repository.mysqlWriteById(buildUpdateQuery(this.table, id, changes), id, false, true);
|
|
2884
|
+
if (row)
|
|
2885
|
+
await dispatchModelEvent(modelEventName(this.table.name, "updated"), row);
|
|
2886
|
+
return row;
|
|
2887
|
+
}));
|
|
2799
2888
|
return await this.runModelMutation("updated", () => withDatabaseErrorHandling(async () => {
|
|
2800
2889
|
const { text, params } = buildUpdateQuery(this.table, id, changes);
|
|
2801
2890
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -2821,6 +2910,14 @@ class BaseRepository {
|
|
|
2821
2910
|
}
|
|
2822
2911
|
async softDeleteById(id) {
|
|
2823
2912
|
this.assertTransactionalEvent("deleted");
|
|
2913
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2914
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2915
|
+
const row = await repository.mysqlWriteById(buildSoftDeleteByIdQuery(this.table, id, new Date), id, true);
|
|
2916
|
+
if (!row)
|
|
2917
|
+
return false;
|
|
2918
|
+
await dispatchModelEvent(modelEventName(this.table.name, "deleted"), row);
|
|
2919
|
+
return true;
|
|
2920
|
+
}));
|
|
2824
2921
|
return await this.runModelMutation("deleted", () => withDatabaseErrorHandling(async () => {
|
|
2825
2922
|
const { text, params } = buildSoftDeleteByIdQuery(this.table, id, new Date);
|
|
2826
2923
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -2833,6 +2930,15 @@ class BaseRepository {
|
|
|
2833
2930
|
}
|
|
2834
2931
|
async forceDeleteById(id) {
|
|
2835
2932
|
this.assertTransactionalEvent("force-deleted");
|
|
2933
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2934
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2935
|
+
const query = buildDeleteByIdQuery(this.table, id);
|
|
2936
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
2937
|
+
if (!repository.mysqlAffected(result))
|
|
2938
|
+
return false;
|
|
2939
|
+
await dispatchModelEvent(modelEventName(this.table.name, "force-deleted"), { id });
|
|
2940
|
+
return true;
|
|
2941
|
+
}));
|
|
2836
2942
|
return await this.runModelMutation("force-deleted", () => withDatabaseErrorHandling(async () => {
|
|
2837
2943
|
const { text, params } = buildDeleteByIdQuery(this.table, id);
|
|
2838
2944
|
const [row] = await this.connection.unsafe(text, params);
|
|
@@ -2847,6 +2953,13 @@ class BaseRepository {
|
|
|
2847
2953
|
}
|
|
2848
2954
|
async restoreById(id) {
|
|
2849
2955
|
this.assertTransactionalEvent("restored");
|
|
2956
|
+
if (currentSqlDialect().driver === "mysql")
|
|
2957
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
2958
|
+
const row = await repository.mysqlWriteById(buildRestoreByIdQuery(this.table, id), id);
|
|
2959
|
+
if (row)
|
|
2960
|
+
await dispatchModelEvent(modelEventName(this.table.name, "restored"), row);
|
|
2961
|
+
return row;
|
|
2962
|
+
}));
|
|
2850
2963
|
return await this.runModelMutation("restored", () => withDatabaseErrorHandling(async () => {
|
|
2851
2964
|
const { text, params } = buildRestoreByIdQuery(this.table, id);
|
|
2852
2965
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -733,6 +733,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
733
733
|
|
|
734
734
|
// ../../src/core/database/transaction.ts
|
|
735
735
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
736
|
+
function scopedConnection(source) {
|
|
737
|
+
const connection = createDatabaseConnection(source);
|
|
738
|
+
transactionAliases.set(connection, source);
|
|
739
|
+
return connection;
|
|
740
|
+
}
|
|
741
|
+
function isActiveTransactionConnection(connection) {
|
|
742
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
743
|
+
return false;
|
|
744
|
+
const active = getActiveDatabaseConnection(connection);
|
|
745
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
746
|
+
}
|
|
736
747
|
async function runInSavepoint(connection, operation) {
|
|
737
748
|
const inherited = transactionFrame.getStore();
|
|
738
749
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -749,7 +760,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
749
760
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
750
761
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
751
762
|
try {
|
|
752
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
763
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
753
764
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
754
765
|
return result;
|
|
755
766
|
} catch (error) {
|
|
@@ -772,9 +783,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
772
783
|
signal?.throwIfAborted();
|
|
773
784
|
return operation(connection);
|
|
774
785
|
};
|
|
775
|
-
const pool = resolveRepositoryConnection();
|
|
786
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
776
787
|
if (hasActiveDatabaseConnection()) {
|
|
777
|
-
|
|
788
|
+
const active = getActiveDatabaseConnection(pool);
|
|
789
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
790
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
791
|
+
return await runInSavepoint(active, admittedOperation);
|
|
778
792
|
}
|
|
779
793
|
if (!supportsTransactions(pool)) {
|
|
780
794
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -793,14 +807,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
793
807
|
if (!supportsTransactions(connection))
|
|
794
808
|
throw new Error("Reserved database connection does not support transactions.");
|
|
795
809
|
return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
|
|
796
|
-
|
|
810
|
+
transactionRoots.set(transaction, pool);
|
|
811
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
797
812
|
}));
|
|
798
813
|
} finally {
|
|
799
814
|
await reserved?.release();
|
|
800
815
|
}
|
|
801
816
|
}));
|
|
802
817
|
}
|
|
803
|
-
var transactionFrame, outerFrames;
|
|
818
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
804
819
|
var init_transaction = __esm(() => {
|
|
805
820
|
init_deferredModelEvents();
|
|
806
821
|
init_asyncContextStore();
|
|
@@ -812,6 +827,8 @@ var init_transaction = __esm(() => {
|
|
|
812
827
|
init_acquisitionMetrics();
|
|
813
828
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
814
829
|
outerFrames = new WeakMap;
|
|
830
|
+
transactionRoots = new WeakMap;
|
|
831
|
+
transactionAliases = new WeakMap;
|
|
815
832
|
});
|
|
816
833
|
|
|
817
834
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
@@ -1602,6 +1619,8 @@ class ExportAuditLogsJob extends Job {
|
|
|
1602
1619
|
}
|
|
1603
1620
|
}
|
|
1604
1621
|
}
|
|
1622
|
+
var exportAuditLogsJob_default = ExportAuditLogsJob;
|
|
1605
1623
|
export {
|
|
1606
|
-
ExportAuditLogsJob
|
|
1624
|
+
ExportAuditLogsJob,
|
|
1625
|
+
exportAuditLogsJob_default as default
|
|
1607
1626
|
};
|
|
@@ -105,6 +105,8 @@ class InvalidateCacheTagsJob extends Job {
|
|
|
105
105
|
await this.cache.tags(...payload.tags).flush();
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
+
var invalidateCacheTagsJob_default = InvalidateCacheTagsJob;
|
|
108
109
|
export {
|
|
109
|
-
InvalidateCacheTagsJob
|
|
110
|
+
InvalidateCacheTagsJob,
|
|
111
|
+
invalidateCacheTagsJob_default as default
|
|
110
112
|
};
|
|
@@ -808,6 +808,17 @@ var init_connection = () => {};
|
|
|
808
808
|
|
|
809
809
|
// ../../src/core/database/transaction.ts
|
|
810
810
|
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
811
|
+
function scopedConnection(source) {
|
|
812
|
+
const connection = createDatabaseConnection(source);
|
|
813
|
+
transactionAliases.set(connection, source);
|
|
814
|
+
return connection;
|
|
815
|
+
}
|
|
816
|
+
function isActiveTransactionConnection(connection) {
|
|
817
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
818
|
+
return false;
|
|
819
|
+
const active = getActiveDatabaseConnection(connection);
|
|
820
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
821
|
+
}
|
|
811
822
|
async function runInSavepoint(connection, operation) {
|
|
812
823
|
const inherited = transactionFrame.getStore();
|
|
813
824
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -824,7 +835,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
824
835
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
825
836
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
826
837
|
try {
|
|
827
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
838
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
828
839
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
829
840
|
return result;
|
|
830
841
|
} catch (error) {
|
|
@@ -847,9 +858,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
847
858
|
signal?.throwIfAborted();
|
|
848
859
|
return operation(connection);
|
|
849
860
|
};
|
|
850
|
-
const pool = resolveRepositoryConnection();
|
|
861
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
851
862
|
if (hasActiveDatabaseConnection()) {
|
|
852
|
-
|
|
863
|
+
const active = getActiveDatabaseConnection(pool);
|
|
864
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
865
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
866
|
+
return await runInSavepoint(active, admittedOperation);
|
|
853
867
|
}
|
|
854
868
|
if (!supportsTransactions(pool)) {
|
|
855
869
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -868,14 +882,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
868
882
|
if (!supportsTransactions(connection))
|
|
869
883
|
throw new Error("Reserved database connection does not support transactions.");
|
|
870
884
|
return await connection.begin(AsyncLocalStorage4.bind(async (transaction) => {
|
|
871
|
-
|
|
885
|
+
transactionRoots.set(transaction, pool);
|
|
886
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
872
887
|
}));
|
|
873
888
|
} finally {
|
|
874
889
|
await reserved?.release();
|
|
875
890
|
}
|
|
876
891
|
}));
|
|
877
892
|
}
|
|
878
|
-
var transactionFrame, outerFrames;
|
|
893
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
879
894
|
var init_transaction = __esm(() => {
|
|
880
895
|
init_deferredModelEvents();
|
|
881
896
|
init_asyncContextStore();
|
|
@@ -887,6 +902,8 @@ var init_transaction = __esm(() => {
|
|
|
887
902
|
init_acquisitionMetrics();
|
|
888
903
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
889
904
|
outerFrames = new WeakMap;
|
|
905
|
+
transactionRoots = new WeakMap;
|
|
906
|
+
transactionAliases = new WeakMap;
|
|
890
907
|
});
|
|
891
908
|
|
|
892
909
|
// ../../src/core/queue/queueMetrics.ts
|
|
@@ -733,6 +733,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
733
733
|
|
|
734
734
|
// ../../src/core/database/transaction.ts
|
|
735
735
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
736
|
+
function scopedConnection(source) {
|
|
737
|
+
const connection = createDatabaseConnection(source);
|
|
738
|
+
transactionAliases.set(connection, source);
|
|
739
|
+
return connection;
|
|
740
|
+
}
|
|
741
|
+
function isActiveTransactionConnection(connection) {
|
|
742
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
743
|
+
return false;
|
|
744
|
+
const active = getActiveDatabaseConnection(connection);
|
|
745
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
746
|
+
}
|
|
736
747
|
async function runInSavepoint(connection, operation) {
|
|
737
748
|
const inherited = transactionFrame.getStore();
|
|
738
749
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -749,7 +760,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
749
760
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
750
761
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
751
762
|
try {
|
|
752
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
763
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
753
764
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
754
765
|
return result;
|
|
755
766
|
} catch (error) {
|
|
@@ -772,9 +783,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
772
783
|
signal?.throwIfAborted();
|
|
773
784
|
return operation(connection);
|
|
774
785
|
};
|
|
775
|
-
const pool = resolveRepositoryConnection();
|
|
786
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
776
787
|
if (hasActiveDatabaseConnection()) {
|
|
777
|
-
|
|
788
|
+
const active = getActiveDatabaseConnection(pool);
|
|
789
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
790
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
791
|
+
return await runInSavepoint(active, admittedOperation);
|
|
778
792
|
}
|
|
779
793
|
if (!supportsTransactions(pool)) {
|
|
780
794
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -793,14 +807,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
793
807
|
if (!supportsTransactions(connection))
|
|
794
808
|
throw new Error("Reserved database connection does not support transactions.");
|
|
795
809
|
return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
|
|
796
|
-
|
|
810
|
+
transactionRoots.set(transaction, pool);
|
|
811
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
797
812
|
}));
|
|
798
813
|
} finally {
|
|
799
814
|
await reserved?.release();
|
|
800
815
|
}
|
|
801
816
|
}));
|
|
802
817
|
}
|
|
803
|
-
var transactionFrame, outerFrames;
|
|
818
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
804
819
|
var init_transaction = __esm(() => {
|
|
805
820
|
init_deferredModelEvents();
|
|
806
821
|
init_asyncContextStore();
|
|
@@ -812,6 +827,8 @@ var init_transaction = __esm(() => {
|
|
|
812
827
|
init_acquisitionMetrics();
|
|
813
828
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
814
829
|
outerFrames = new WeakMap;
|
|
830
|
+
transactionRoots = new WeakMap;
|
|
831
|
+
transactionAliases = new WeakMap;
|
|
815
832
|
});
|
|
816
833
|
|
|
817
834
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
@@ -666,6 +666,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
666
666
|
|
|
667
667
|
// ../../src/core/database/transaction.ts
|
|
668
668
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
669
|
+
function scopedConnection(source) {
|
|
670
|
+
const connection = createDatabaseConnection(source);
|
|
671
|
+
transactionAliases.set(connection, source);
|
|
672
|
+
return connection;
|
|
673
|
+
}
|
|
674
|
+
function isActiveTransactionConnection(connection) {
|
|
675
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
676
|
+
return false;
|
|
677
|
+
const active = getActiveDatabaseConnection(connection);
|
|
678
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
679
|
+
}
|
|
669
680
|
async function runInSavepoint(connection, operation) {
|
|
670
681
|
const inherited = transactionFrame.getStore();
|
|
671
682
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -682,7 +693,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
682
693
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
683
694
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
684
695
|
try {
|
|
685
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
696
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
686
697
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
687
698
|
return result;
|
|
688
699
|
} catch (error) {
|
|
@@ -705,9 +716,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
705
716
|
signal?.throwIfAborted();
|
|
706
717
|
return operation(connection);
|
|
707
718
|
};
|
|
708
|
-
const pool = resolveRepositoryConnection();
|
|
719
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
709
720
|
if (hasActiveDatabaseConnection()) {
|
|
710
|
-
|
|
721
|
+
const active = getActiveDatabaseConnection(pool);
|
|
722
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
723
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
724
|
+
return await runInSavepoint(active, admittedOperation);
|
|
711
725
|
}
|
|
712
726
|
if (!supportsTransactions(pool)) {
|
|
713
727
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -726,14 +740,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
726
740
|
if (!supportsTransactions(connection))
|
|
727
741
|
throw new Error("Reserved database connection does not support transactions.");
|
|
728
742
|
return await connection.begin(AsyncLocalStorage2.bind(async (transaction) => {
|
|
729
|
-
|
|
743
|
+
transactionRoots.set(transaction, pool);
|
|
744
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
730
745
|
}));
|
|
731
746
|
} finally {
|
|
732
747
|
await reserved?.release();
|
|
733
748
|
}
|
|
734
749
|
}));
|
|
735
750
|
}
|
|
736
|
-
var transactionFrame, outerFrames;
|
|
751
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
737
752
|
var init_transaction = __esm(() => {
|
|
738
753
|
init_deferredModelEvents();
|
|
739
754
|
init_asyncContextStore();
|
|
@@ -745,6 +760,8 @@ var init_transaction = __esm(() => {
|
|
|
745
760
|
init_acquisitionMetrics();
|
|
746
761
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
747
762
|
outerFrames = new WeakMap;
|
|
763
|
+
transactionRoots = new WeakMap;
|
|
764
|
+
transactionAliases = new WeakMap;
|
|
748
765
|
});
|
|
749
766
|
|
|
750
767
|
// ../../src/core/tenant/tenancyConfig.ts
|
|
@@ -69,7 +69,7 @@ export type { Seeder, SeederDatabase } from "../core/database/seeders/types.ts";
|
|
|
69
69
|
export { createSqliteConnection } from "../core/database/sqliteConnection.ts";
|
|
70
70
|
export { defineTable } from "../core/database/table.ts";
|
|
71
71
|
export type { TransactionOptions } from "../core/database/transaction.ts";
|
|
72
|
-
export { hasActiveTransaction, requestTransactionRollback, runInTransaction, } from "../core/database/transaction.ts";
|
|
72
|
+
export { hasActiveTransaction, isActiveTransactionConnection, requestTransactionRollback, runInTransaction, } from "../core/database/transaction.ts";
|
|
73
73
|
export type { ModelWhere, ModelWriteValues, QueryJoin, QueryJoinOn, QueryOptions, QueryOrder, QuerySelectItem, QueryWhere, } from "../core/database/types.ts";
|
|
74
74
|
export type { WhereNode } from "../core/database/whereBuilder.ts";
|
|
75
75
|
export { WhereBuilder } from "../core/database/whereBuilder.ts";
|
package/dist/index.js
CHANGED
|
@@ -853,6 +853,17 @@ var init_repositoryConnection = __esm(() => {
|
|
|
853
853
|
|
|
854
854
|
// ../../src/core/database/transaction.ts
|
|
855
855
|
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
856
|
+
function scopedConnection(source) {
|
|
857
|
+
const connection = createDatabaseConnection(source);
|
|
858
|
+
transactionAliases.set(connection, source);
|
|
859
|
+
return connection;
|
|
860
|
+
}
|
|
861
|
+
function isActiveTransactionConnection(connection) {
|
|
862
|
+
if (!hasActiveTransaction() || !hasActiveDatabaseConnection())
|
|
863
|
+
return false;
|
|
864
|
+
const active = getActiveDatabaseConnection(connection);
|
|
865
|
+
return connection === active || transactionAliases.get(connection) === active;
|
|
866
|
+
}
|
|
856
867
|
async function runInSavepoint(connection, operation) {
|
|
857
868
|
const inherited = transactionFrame.getStore();
|
|
858
869
|
let parent = inherited?.connection === connection ? inherited : outerFrames.get(connection);
|
|
@@ -869,7 +880,7 @@ async function runInSavepoint(connection, operation) {
|
|
|
869
880
|
return await settleTransaction(() => runWithDeferredModelEvents(async () => {
|
|
870
881
|
await connection.unsafe(`SAVEPOINT ${name}`);
|
|
871
882
|
try {
|
|
872
|
-
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(
|
|
883
|
+
const result = await transactionFrame.run({ connection, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await operation(scopedConnection(connection)))));
|
|
873
884
|
await connection.unsafe(`RELEASE SAVEPOINT ${name}`);
|
|
874
885
|
return result;
|
|
875
886
|
} catch (error) {
|
|
@@ -892,9 +903,12 @@ async function runInTransaction(operation, options = {}) {
|
|
|
892
903
|
signal?.throwIfAborted();
|
|
893
904
|
return operation(connection);
|
|
894
905
|
};
|
|
895
|
-
const pool = resolveRepositoryConnection();
|
|
906
|
+
const pool = options.connection ?? resolveRepositoryConnection();
|
|
896
907
|
if (hasActiveDatabaseConnection()) {
|
|
897
|
-
|
|
908
|
+
const active = getActiveDatabaseConnection(pool);
|
|
909
|
+
if (options.connection && options.connection !== active && options.connection !== transactionRoots.get(active) && transactionAliases.get(options.connection) !== active)
|
|
910
|
+
throw new Error("Cannot switch database connections within an active transaction.");
|
|
911
|
+
return await runInSavepoint(active, admittedOperation);
|
|
898
912
|
}
|
|
899
913
|
if (!supportsTransactions(pool)) {
|
|
900
914
|
throw new Error("Active database connection does not support transactions. Bind a client with begin() via bindDatabaseConnection.");
|
|
@@ -913,14 +927,15 @@ async function runInTransaction(operation, options = {}) {
|
|
|
913
927
|
if (!supportsTransactions(connection))
|
|
914
928
|
throw new Error("Reserved database connection does not support transactions.");
|
|
915
929
|
return await connection.begin(AsyncLocalStorage3.bind(async (transaction) => {
|
|
916
|
-
|
|
930
|
+
transactionRoots.set(transaction, pool);
|
|
931
|
+
return await runWithDatabaseConnection(transaction, () => transactionFrame.run({ connection: transaction, childActive: false }, () => runWithTransactionScope(async () => commitOrRollbackScope(await admittedOperation(scopedConnection(transaction))))));
|
|
917
932
|
}));
|
|
918
933
|
} finally {
|
|
919
934
|
await reserved?.release();
|
|
920
935
|
}
|
|
921
936
|
}));
|
|
922
937
|
}
|
|
923
|
-
var transactionFrame, outerFrames;
|
|
938
|
+
var transactionFrame, outerFrames, transactionRoots, transactionAliases;
|
|
924
939
|
var init_transaction = __esm(() => {
|
|
925
940
|
init_deferredModelEvents();
|
|
926
941
|
init_asyncContextStore();
|
|
@@ -932,6 +947,8 @@ var init_transaction = __esm(() => {
|
|
|
932
947
|
init_acquisitionMetrics();
|
|
933
948
|
transactionFrame = createAsyncContextStore("@getstrata/transactionFrame");
|
|
934
949
|
outerFrames = new WeakMap;
|
|
950
|
+
transactionRoots = new WeakMap;
|
|
951
|
+
transactionAliases = new WeakMap;
|
|
935
952
|
});
|
|
936
953
|
|
|
937
954
|
// ../../src/core/tenant/databaseTenantContext.ts
|
|
@@ -3743,7 +3760,6 @@ function buildPaginationMeta(input) {
|
|
|
3743
3760
|
}
|
|
3744
3761
|
|
|
3745
3762
|
// ../../src/core/database/baseRepository.ts
|
|
3746
|
-
init_connectionContext();
|
|
3747
3763
|
init_dialect();
|
|
3748
3764
|
|
|
3749
3765
|
// ../../src/core/database/keyset.ts
|
|
@@ -5171,7 +5187,7 @@ class BaseRepository {
|
|
|
5171
5187
|
assertTransactionalEvent(action) {
|
|
5172
5188
|
if (!eventBus.hasTransactionalListeners(modelEventName(this.table.name, action)))
|
|
5173
5189
|
return;
|
|
5174
|
-
if (!hasActiveTransaction() || this.connection !== repositoryConnection && this.connection
|
|
5190
|
+
if (!hasActiveTransaction() || this.connection !== repositoryConnection && !isActiveTransactionConnection(this.connection))
|
|
5175
5191
|
throw new Error("Transactional model listeners require runInTransaction and the framework-bound repository connection before writing.");
|
|
5176
5192
|
}
|
|
5177
5193
|
async runModelMutation(action, operation) {
|
|
@@ -5179,6 +5195,32 @@ class BaseRepository {
|
|
|
5179
5195
|
return operation();
|
|
5180
5196
|
return runInTransaction(operation);
|
|
5181
5197
|
}
|
|
5198
|
+
mysqlMutation(operation) {
|
|
5199
|
+
return runInTransaction((db) => operation(this.withConnection(db)), this.connection === repositoryConnection ? {} : { connection: this.connection });
|
|
5200
|
+
}
|
|
5201
|
+
mysqlRow(id, onlyTrashed = false) {
|
|
5202
|
+
if (id === undefined || id === null)
|
|
5203
|
+
throw new Error(`MySQL write to ${this.table.name} did not identify its persisted primary key.`);
|
|
5204
|
+
return this.firstOrNull({ [this.table.primaryKey]: id }, {
|
|
5205
|
+
withTrashed: true,
|
|
5206
|
+
...onlyTrashed ? { onlyTrashed: true } : {}
|
|
5207
|
+
});
|
|
5208
|
+
}
|
|
5209
|
+
mysqlAffected(row) {
|
|
5210
|
+
const count = row?.affectedRows;
|
|
5211
|
+
if (count === undefined || !Number.isSafeInteger(count) || count < 0)
|
|
5212
|
+
throw new Error("MySQL mutations require affectedRows metadata from the framework adapter.");
|
|
5213
|
+
return count;
|
|
5214
|
+
}
|
|
5215
|
+
async mysqlWriteById(query, id, onlyTrashed = false, allowUnchanged = false) {
|
|
5216
|
+
const [row] = await this.connection.unsafe(query.text, query.params);
|
|
5217
|
+
if (!this.mysqlAffected(row)) {
|
|
5218
|
+
if (!allowUnchanged)
|
|
5219
|
+
return null;
|
|
5220
|
+
return this.findById(id);
|
|
5221
|
+
}
|
|
5222
|
+
return this.mysqlRow(id, onlyTrashed);
|
|
5223
|
+
}
|
|
5182
5224
|
async count(options = {}) {
|
|
5183
5225
|
if (options.lock)
|
|
5184
5226
|
throw new Error("Row locks require a row selection, not count().");
|
|
@@ -5187,7 +5229,7 @@ class BaseRepository {
|
|
|
5187
5229
|
}
|
|
5188
5230
|
async findAll(options = {}) {
|
|
5189
5231
|
return await withDatabaseErrorHandling(async () => {
|
|
5190
|
-
if (options.lock && (!hasActiveTransaction() || this.connection !== repositoryConnection && this.connection
|
|
5232
|
+
if (options.lock && (!hasActiveTransaction() || this.connection !== repositoryConnection && !isActiveTransactionConnection(this.connection))) {
|
|
5191
5233
|
throw new Error("Row locks require the framework active transaction connection.");
|
|
5192
5234
|
}
|
|
5193
5235
|
const { whereNodes, ...queryOptions } = options;
|
|
@@ -5399,6 +5441,32 @@ class BaseRepository {
|
|
|
5399
5441
|
return record ?? null;
|
|
5400
5442
|
}
|
|
5401
5443
|
async upsert(values, conflictColumns, updateColumns) {
|
|
5444
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5445
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5446
|
+
const where = {};
|
|
5447
|
+
for (const column of conflictColumns) {
|
|
5448
|
+
if (!this.table.columns.includes(column) || values[column] === undefined || values[column] === null)
|
|
5449
|
+
throw new Error("MySQL upsert requires non-null supplied conflict-column values.");
|
|
5450
|
+
where[column] = values[column];
|
|
5451
|
+
}
|
|
5452
|
+
const query = buildUpsertQuery(this.table, values, conflictColumns, updateColumns);
|
|
5453
|
+
const supplied = this.table.columns.filter((column) => values[column] !== undefined);
|
|
5454
|
+
const updates = updateColumns ?? supplied.filter((column) => !conflictColumns.includes(column));
|
|
5455
|
+
const doNothing = !updates.some((column) => supplied.includes(column));
|
|
5456
|
+
const existing = doNothing ? await repository.firstOrNull(where, {
|
|
5457
|
+
withTrashed: true,
|
|
5458
|
+
lock: { mode: "update" }
|
|
5459
|
+
}) : null;
|
|
5460
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
5461
|
+
repository.mysqlAffected(result);
|
|
5462
|
+
if (doNothing && existing)
|
|
5463
|
+
return null;
|
|
5464
|
+
const generated = result?.insertId;
|
|
5465
|
+
const row = generated !== undefined && String(generated) !== "0" ? await repository.mysqlRow(generated) : await repository.firstOrNull(where, { withTrashed: true });
|
|
5466
|
+
if (!row)
|
|
5467
|
+
throw new Error("MySQL upsert could not resolve the persisted row; transaction rolled back.");
|
|
5468
|
+
return row;
|
|
5469
|
+
}));
|
|
5402
5470
|
return await withDatabaseErrorHandling(async () => {
|
|
5403
5471
|
const { text, params } = buildUpsertQuery(this.table, values, conflictColumns, updateColumns);
|
|
5404
5472
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -5406,6 +5474,8 @@ class BaseRepository {
|
|
|
5406
5474
|
});
|
|
5407
5475
|
}
|
|
5408
5476
|
async incrementById(id, column, amount = 1, extra = {}) {
|
|
5477
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5478
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(() => repository.mysqlWriteById(buildIncrementQuery(this.table, id, column, amount, extra), id, false, true)));
|
|
5409
5479
|
return await withDatabaseErrorHandling(async () => {
|
|
5410
5480
|
const { text, params } = buildIncrementQuery(this.table, id, column, amount, extra);
|
|
5411
5481
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -5417,6 +5487,18 @@ class BaseRepository {
|
|
|
5417
5487
|
}
|
|
5418
5488
|
async create(values) {
|
|
5419
5489
|
this.assertTransactionalEvent("created");
|
|
5490
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5491
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5492
|
+
const query = buildInsertQuery(this.table, values);
|
|
5493
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
5494
|
+
repository.mysqlAffected(result);
|
|
5495
|
+
const key = String(result?.insertId ?? "0") !== "0" ? result?.insertId : values[this.table.primaryKey];
|
|
5496
|
+
const row = await repository.mysqlRow(key);
|
|
5497
|
+
if (!row)
|
|
5498
|
+
throw new Error(`Insert into ${this.table.name} did not return a record.`);
|
|
5499
|
+
await dispatchModelEvent(modelEventName(this.table.name, "created"), row);
|
|
5500
|
+
return row;
|
|
5501
|
+
}));
|
|
5420
5502
|
return await this.runModelMutation("created", () => withDatabaseErrorHandling(async () => {
|
|
5421
5503
|
const { text, params } = buildInsertQuery(this.table, values);
|
|
5422
5504
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -5452,6 +5534,13 @@ class BaseRepository {
|
|
|
5452
5534
|
}
|
|
5453
5535
|
async updateById(id, changes) {
|
|
5454
5536
|
this.assertTransactionalEvent("updated");
|
|
5537
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5538
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5539
|
+
const row = await repository.mysqlWriteById(buildUpdateQuery(this.table, id, changes), id, false, true);
|
|
5540
|
+
if (row)
|
|
5541
|
+
await dispatchModelEvent(modelEventName(this.table.name, "updated"), row);
|
|
5542
|
+
return row;
|
|
5543
|
+
}));
|
|
5455
5544
|
return await this.runModelMutation("updated", () => withDatabaseErrorHandling(async () => {
|
|
5456
5545
|
const { text, params } = buildUpdateQuery(this.table, id, changes);
|
|
5457
5546
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -5477,6 +5566,14 @@ class BaseRepository {
|
|
|
5477
5566
|
}
|
|
5478
5567
|
async softDeleteById(id) {
|
|
5479
5568
|
this.assertTransactionalEvent("deleted");
|
|
5569
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5570
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5571
|
+
const row = await repository.mysqlWriteById(buildSoftDeleteByIdQuery(this.table, id, new Date), id, true);
|
|
5572
|
+
if (!row)
|
|
5573
|
+
return false;
|
|
5574
|
+
await dispatchModelEvent(modelEventName(this.table.name, "deleted"), row);
|
|
5575
|
+
return true;
|
|
5576
|
+
}));
|
|
5480
5577
|
return await this.runModelMutation("deleted", () => withDatabaseErrorHandling(async () => {
|
|
5481
5578
|
const { text, params } = buildSoftDeleteByIdQuery(this.table, id, new Date);
|
|
5482
5579
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -5489,6 +5586,15 @@ class BaseRepository {
|
|
|
5489
5586
|
}
|
|
5490
5587
|
async forceDeleteById(id) {
|
|
5491
5588
|
this.assertTransactionalEvent("force-deleted");
|
|
5589
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5590
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5591
|
+
const query = buildDeleteByIdQuery(this.table, id);
|
|
5592
|
+
const [result] = await repository.connection.unsafe(query.text, query.params);
|
|
5593
|
+
if (!repository.mysqlAffected(result))
|
|
5594
|
+
return false;
|
|
5595
|
+
await dispatchModelEvent(modelEventName(this.table.name, "force-deleted"), { id });
|
|
5596
|
+
return true;
|
|
5597
|
+
}));
|
|
5492
5598
|
return await this.runModelMutation("force-deleted", () => withDatabaseErrorHandling(async () => {
|
|
5493
5599
|
const { text, params } = buildDeleteByIdQuery(this.table, id);
|
|
5494
5600
|
const [row] = await this.connection.unsafe(text, params);
|
|
@@ -5503,6 +5609,13 @@ class BaseRepository {
|
|
|
5503
5609
|
}
|
|
5504
5610
|
async restoreById(id) {
|
|
5505
5611
|
this.assertTransactionalEvent("restored");
|
|
5612
|
+
if (currentSqlDialect().driver === "mysql")
|
|
5613
|
+
return this.mysqlMutation((repository) => withDatabaseErrorHandling(async () => {
|
|
5614
|
+
const row = await repository.mysqlWriteById(buildRestoreByIdQuery(this.table, id), id);
|
|
5615
|
+
if (row)
|
|
5616
|
+
await dispatchModelEvent(modelEventName(this.table.name, "restored"), row);
|
|
5617
|
+
return row;
|
|
5618
|
+
}));
|
|
5506
5619
|
return await this.runModelMutation("restored", () => withDatabaseErrorHandling(async () => {
|
|
5507
5620
|
const { text, params } = buildRestoreByIdQuery(this.table, id);
|
|
5508
5621
|
const [record] = await this.connection.unsafe(text, params);
|
|
@@ -17204,6 +17317,7 @@ export {
|
|
|
17204
17317
|
indexMorphToRelation,
|
|
17205
17318
|
inferReferencedTable,
|
|
17206
17319
|
installGracefulShutdownSignals,
|
|
17320
|
+
isActiveTransactionConnection,
|
|
17207
17321
|
isBlockedHostname,
|
|
17208
17322
|
isBlockedIpAddress,
|
|
17209
17323
|
isDefaultDatabaseConnection,
|