@danceroutine/tango-orm 1.3.0 → 1.5.0
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/dist/PostgresAdapter-BFdo_nIt.js +4 -0
- package/dist/{PostgresAdapter-C9a1XJRx.js → PostgresAdapter-CMiEpHya.js} +4 -52
- package/dist/PostgresAdapter-CMiEpHya.js.map +1 -0
- package/dist/PostgresClient-BQJZfEOT.js +68 -0
- package/dist/PostgresClient-BQJZfEOT.js.map +1 -0
- package/dist/SqliteAdapter-A-P9zUhP.js +4 -0
- package/dist/SqliteAdapter-CeqhyrPC.js +44 -0
- package/dist/SqliteAdapter-CeqhyrPC.js.map +1 -0
- package/dist/{SqliteAdapter-Dp6VRXmz.js → SqliteClient-CjOK9-ki.js} +20 -41
- package/dist/SqliteClient-CjOK9-ki.js.map +1 -0
- package/dist/connection/clients/DBClient.d.ts +6 -0
- package/dist/connection/clients/dialects/PostgresClient.d.ts +21 -5
- package/dist/connection/clients/dialects/SqliteClient.d.ts +13 -1
- package/dist/connection/index.js +5 -3
- package/dist/{connection-CVvycXus.js → connection-B_K2ZAf7.js} +7 -5
- package/dist/{connection-CVvycXus.js.map → connection-B_K2ZAf7.js.map} +1 -1
- package/dist/defaultRuntime-BPK9kWEW.js +447 -0
- package/dist/defaultRuntime-BPK9kWEW.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +12 -9
- package/dist/manager/ModelManager.d.ts +13 -11
- package/dist/manager/index.js +6 -6
- package/dist/manager/internal/RuntimeBoundClient.d.ts +5 -1
- package/dist/{manager-D6tU8xTO.js → manager-C6oJ2tAF.js} +2 -2
- package/dist/{manager-D6tU8xTO.js.map → manager-C6oJ2tAF.js.map} +1 -1
- package/dist/query/QuerySet.d.ts +17 -13
- package/dist/query/compiler/QueryCompiler.d.ts +14 -21
- package/dist/query/domain/CompiledQuery.d.ts +26 -9
- package/dist/query/domain/RelationMeta.d.ts +37 -0
- package/dist/query/domain/RelationTyping.d.ts +42 -0
- package/dist/query/domain/TableMeta.d.ts +9 -0
- package/dist/query/domain/TableMetaFactory.d.ts +23 -0
- package/dist/query/domain/index.d.ts +2 -1
- package/dist/query/index.js +1 -1
- package/dist/query/planning/QueryPlanner.d.ts +16 -0
- package/dist/query/planning/domain/QueryHydrationPlan.d.ts +20 -0
- package/dist/query/planning/index.d.ts +2 -0
- package/dist/{query-6GeNOf-w.js → query-DYiJ5m_B.js} +434 -165
- package/dist/query-DYiJ5m_B.js.map +1 -0
- package/dist/{registerModelObjects-CXSI5ndy.js → registerModelObjects-B1VzZ072.js} +28 -144
- package/dist/registerModelObjects-B1VzZ072.js.map +1 -0
- package/dist/runtime/TangoRuntime.d.ts +17 -4
- package/dist/runtime/index.js +6 -6
- package/dist/runtime/internal/DBClientProvider.d.ts +12 -0
- package/dist/runtime/internal/PostgresDBClientProvider.d.ts +12 -0
- package/dist/runtime/internal/SqliteDBClientProvider.d.ts +16 -0
- package/dist/runtime/internal/createDBClientProvider.d.ts +5 -0
- package/dist/{runtime-7U5_XDad.js → runtime-ByXbpVBS.js} +3 -2
- package/dist/{runtime-7U5_XDad.js.map → runtime-ByXbpVBS.js.map} +1 -1
- package/dist/transaction/AtomicTransaction.d.ts +32 -0
- package/dist/transaction/UnitOfWork.d.ts +3 -0
- package/dist/transaction/atomic.d.ts +2 -0
- package/dist/transaction/index.d.ts +2 -0
- package/dist/transaction/index.js +5 -2
- package/dist/transaction/internal/context/AsyncLocalTransactionEngine.d.ts +21 -0
- package/dist/transaction/internal/context/CallbackRecord.d.ts +5 -0
- package/dist/transaction/internal/context/FrameBoundTransaction.d.ts +20 -0
- package/dist/transaction/internal/context/FrameTransactionHandle.d.ts +4 -0
- package/dist/transaction/internal/context/TransactionEngine.d.ts +16 -0
- package/dist/transaction/internal/context/TransactionFrame.d.ts +7 -0
- package/dist/transaction/internal/context/TransactionState.d.ts +10 -0
- package/dist/transaction/internal/context/index.d.ts +1 -0
- package/dist/{transaction-DooTMuAl.js → transaction-Cs0Z9tbW.js} +15 -3
- package/dist/transaction-Cs0Z9tbW.js.map +1 -0
- package/package.json +6 -6
- package/dist/PostgresAdapter-C9a1XJRx.js.map +0 -1
- package/dist/PostgresAdapter-CBc1u8eT.js +0 -3
- package/dist/SqliteAdapter-BJKNxCvS.js +0 -3
- package/dist/SqliteAdapter-Dp6VRXmz.js.map +0 -1
- package/dist/query-6GeNOf-w.js.map +0 -1
- package/dist/registerModelObjects-CXSI5ndy.js.map +0 -1
- package/dist/transaction-DooTMuAl.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerModelObjects-B1VzZ072.js","names":["dialect: Dialect","plan: ValidatedInsertSqlPlan","values: readonly unknown[]","plan: ValidatedUpdateSqlPlan","id: unknown","plan: ValidatedDeleteSqlPlan","valueRows: ReadonlyArray<ReadonlyArray<unknown>>","count: number","index: number","model: ModelLike<TModelRow>","runtime: TangoRuntime","value: unknown","id: TModelRow[keyof TModelRow]","input: Partial<TModelRow>","patch: Partial<TModelRow>","inputs: Partial<TModelRow>[]","batchPrepared: Partial<TModelRow>[]","data: Partial<TModelRow>","current: TModelRow","model: SchemaModel<TSchema, TKey>"],"sources":["../src/manager/internal/MutationCompiler.ts","../src/manager/ModelManager.ts","../src/manager/registerModelObjects.ts"],"sourcesContent":["import type { CompiledQuery, Dialect } from '../../query/domain/index';\nimport type {\n ValidatedDeleteSqlPlan,\n ValidatedInsertSqlPlan,\n ValidatedUpdateSqlPlan,\n} from '../../validation/SQLValidationEngine';\n\n/**\n * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.\n */\nexport class MutationCompiler {\n constructor(private readonly dialect: Dialect) {}\n\n compileInsert(plan: ValidatedInsertSqlPlan, values: readonly unknown[]): CompiledQuery {\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES (${this.buildValuePlaceholders(plan.writeKeys.length)}) RETURNING *`,\n params: values,\n };\n }\n\n compileUpdate(plan: ValidatedUpdateSqlPlan, values: readonly unknown[], id: unknown): CompiledQuery {\n const sets = plan.writeKeys.map((key, index) => `${key} = ${this.placeholder(index + 1)}`).join(', ');\n const whereParam = this.placeholder(plan.writeKeys.length + 1);\n\n return {\n sql: `UPDATE ${plan.meta.table} SET ${sets} WHERE ${plan.meta.pk} = ${whereParam} RETURNING *`,\n params: [...values, id],\n };\n }\n\n compileDelete(plan: ValidatedDeleteSqlPlan, id: unknown): CompiledQuery {\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${plan.meta.pk} = ${this.placeholder(1)}`,\n params: [id],\n };\n }\n\n compileBulkInsert(plan: ValidatedInsertSqlPlan, valueRows: ReadonlyArray<ReadonlyArray<unknown>>): CompiledQuery {\n const columnCount = plan.writeKeys.length;\n const placeholders = valueRows\n .map((_row, rowIndex) => {\n const offset = rowIndex * columnCount;\n return `(${plan.writeKeys.map((_, colIndex) => this.placeholder(offset + colIndex + 1)).join(', ')})`;\n })\n .join(', ');\n\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders} RETURNING *`,\n params: valueRows.flat(),\n };\n }\n\n private buildValuePlaceholders(count: number): string {\n return Array.from({ length: count }, (_value, index) => this.placeholder(index + 1)).join(', ');\n }\n\n private placeholder(index: number): string {\n return this.dialect === 'postgres' ? `$${index}` : '?';\n }\n}\n","import { NotFoundError } from '@danceroutine/tango-core';\nimport type { ModelWriteHooks } from '@danceroutine/tango-schema';\nimport type { Model as SchemaModel } from '@danceroutine/tango-schema/domain';\nimport type { FilterInput, TableMeta } from '../query/domain/index';\nimport { TableMetaFactory } from '../query/domain/TableMetaFactory';\nimport type { QuerySet } from '../query/index';\nimport { QuerySet as QuerySetClass } from '../query/index';\nimport type { Dialect, QueryExecutor } from '../query/index';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { OrmSqlSafetyAdapter } from '../validation';\nimport { TransactionEngine } from '../transaction/internal/context';\nimport type { ManagerLike } from './ManagerLike';\nimport { MutationCompiler } from './internal/MutationCompiler';\nimport { RuntimeBoundClient } from './internal/RuntimeBoundClient';\n\nconst sqlSafetyAdapter = new OrmSqlSafetyAdapter();\n\ntype ModelMetadataLike = Omit<SchemaModel['metadata'], 'key' | 'namespace' | 'fields'> & {\n key?: string;\n namespace?: string;\n fields: Array<{\n name: string;\n type: string;\n primaryKey?: boolean;\n }>;\n};\n\ntype ModelLike<TModelRow extends Record<string, unknown>> = {\n metadata: ModelMetadataLike;\n schema: {\n parse(input: unknown): TModelRow;\n };\n hooks?: ModelWriteHooks<TModelRow>;\n};\n\n/**\n * Model-backed data access API exposed as `Model.objects`.\n */\nexport class ModelManager<TModelRow extends Record<string, unknown>, TSourceModel = unknown>\n implements ManagerLike<TModelRow, TSourceModel>\n{\n static readonly BRAND = 'tango.orm.model_manager' as const;\n readonly __tangoBrand: typeof ModelManager.BRAND = ModelManager.BRAND;\n private readonly queryExecutor: QueryExecutor<TModelRow>;\n private readonly mutationCompiler: MutationCompiler;\n private readonly model: ModelLike<TModelRow>;\n private readonly client: RuntimeBoundClient;\n private readonly dialect: Dialect;\n private readonly runtime: TangoRuntime;\n\n constructor(model: ModelLike<TModelRow>, runtime: TangoRuntime) {\n this.model = model;\n this.runtime = runtime;\n this.client = new RuntimeBoundClient(runtime);\n this.dialect = runtime.getDialect() as Dialect;\n this.mutationCompiler = new MutationCompiler(this.dialect);\n this.queryExecutor = {\n get meta() {\n return ModelManager.createTableMeta(model);\n },\n client: this.client,\n dialect: this.dialect,\n run: async (compiled) => {\n const result = await this.client.query<TModelRow>(compiled.sql, compiled.params);\n return result.rows;\n },\n };\n }\n\n get meta(): TableMeta {\n return ModelManager.createTableMeta(this.model);\n }\n\n /**\n * Narrow an unknown value to `ModelManager`.\n */\n static isModelManager<TModelRow extends Record<string, unknown>>(value: unknown): value is ModelManager<TModelRow> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ModelManager.BRAND\n );\n }\n\n private static createTableMeta<TModelRow extends Record<string, unknown>>(model: ModelLike<TModelRow>): TableMeta {\n const rawMeta = TableMetaFactory.create(model);\n const validatedMeta = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: rawMeta,\n writeKeys: Object.keys(rawMeta.columns),\n }).meta;\n\n if (rawMeta.relations) {\n validatedMeta.relations = rawMeta.relations;\n }\n\n return validatedMeta;\n }\n\n query(): QuerySet<TModelRow, TModelRow, TSourceModel> {\n return new QuerySetClass<TModelRow, TModelRow, TSourceModel>(this.queryExecutor, {});\n }\n\n async findById(id: TModelRow[keyof TModelRow]): Promise<TModelRow | null> {\n const filter = { [this.meta.pk]: id } as unknown as FilterInput<TModelRow>;\n return this.query().filter(filter).fetchOne();\n }\n\n async getOrThrow(id: TModelRow[keyof TModelRow]): Promise<TModelRow> {\n const result = await this.findById(id);\n if (!result) {\n throw new NotFoundError(`${this.model.metadata.name} with ${this.meta.pk}=${String(id)} not found`);\n }\n return result;\n }\n\n async create(input: Partial<TModelRow>): Promise<TModelRow> {\n const prepared = await this.runBeforeCreate(input);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileInsert(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof TModelRow])\n );\n const result = await this.queryExecutor.client.query<TModelRow>(compiled.sql, compiled.params);\n const created = result.rows[0]!;\n await this.model.hooks?.afterCreate?.({\n record: created,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n });\n return created;\n }\n\n async update(id: TModelRow[keyof TModelRow], patch: Partial<TModelRow>): Promise<TModelRow> {\n const current = await this.getOrThrow(id);\n const prepared = await this.runBeforeUpdate(id, patch, current);\n const preparedKeys = Object.keys(prepared);\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot update ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'update',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const compiled = this.mutationCompiler.compileUpdate(\n validatedPlan,\n preparedKeys.map((key) => prepared[key as keyof TModelRow]),\n id\n );\n const result = await this.queryExecutor.client.query<TModelRow>(compiled.sql, compiled.params);\n const updated = result.rows[0]!;\n await this.model.hooks?.afterUpdate?.({\n id,\n patch: prepared,\n previous: current,\n record: updated,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n });\n return updated;\n }\n\n async delete(id: TModelRow[keyof TModelRow]): Promise<void> {\n const current = await this.getOrThrow(id);\n await this.model.hooks?.beforeDelete?.({\n id,\n current,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n });\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'delete',\n meta: this.meta,\n });\n const compiled = this.mutationCompiler.compileDelete(validatedPlan, id);\n await this.queryExecutor.client.query(compiled.sql, compiled.params);\n await this.model.hooks?.afterDelete?.({\n id,\n previous: current,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n });\n }\n\n async bulkCreate(inputs: Partial<TModelRow>[]): Promise<TModelRow[]> {\n if (inputs.length === 0) {\n return [];\n }\n\n const perRowPrepared = await Promise.all(inputs.map((input) => this.runBeforeCreate(input)));\n const batchPrepared: Partial<TModelRow>[] =\n (await this.model.hooks?.beforeBulkCreate?.({\n rows: perRowPrepared,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n })) ?? perRowPrepared;\n const preparedKeys = Object.keys(batchPrepared[0] ?? {});\n if (preparedKeys.length === 0) {\n throw new Error(`Cannot create ${this.model.metadata.name} without any values.`);\n }\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: 'insert',\n meta: this.meta,\n writeKeys: preparedKeys,\n });\n const valueRows = batchPrepared.map((input) => preparedKeys.map((key) => input[key as keyof TModelRow]));\n const compiled = this.mutationCompiler.compileBulkInsert(validatedPlan, valueRows);\n const result = await this.queryExecutor.client.query<TModelRow>(compiled.sql, compiled.params);\n await Promise.all(\n result.rows.map((record) =>\n this.model.hooks?.afterCreate?.({\n record,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n })\n )\n );\n await this.model.hooks?.afterBulkCreate?.({\n records: result.rows,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n });\n return result.rows;\n }\n\n private async runBeforeCreate(data: Partial<TModelRow>): Promise<Partial<TModelRow>> {\n return (\n (await this.model.hooks?.beforeCreate?.({\n data,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n })) ?? data\n );\n }\n\n private async runBeforeUpdate(\n id: TModelRow[keyof TModelRow],\n patch: Partial<TModelRow>,\n current: TModelRow\n ): Promise<Partial<TModelRow>> {\n return (\n (await this.model.hooks?.beforeUpdate?.({\n id,\n patch,\n current,\n model: this.model,\n manager: this,\n transaction: this.getHookTransaction(),\n })) ?? patch\n );\n }\n\n private getHookTransaction() {\n return TransactionEngine.forRuntime(this.runtime).getActiveTransaction();\n }\n}\n","import type { z } from 'zod';\nimport type { Model as SchemaModel, PersistedModelOutput } from '@danceroutine/tango-schema/domain';\nimport { registerModelAugmentor } from '@danceroutine/tango-schema';\nimport { ModelManager } from './ModelManager';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { getTangoRuntime } from '../runtime/defaultRuntime';\n\nconst managerCache = new WeakMap<object, { runtime: TangoRuntime; manager: ModelManager<Record<string, unknown>> }>();\nlet hasRegisteredModelObjects = false;\n\ntype AugmentableSchemaModel<TSchema extends z.ZodObject<z.ZodRawShape>> = Pick<\n SchemaModel<TSchema>,\n 'metadata' | 'hooks'\n> & {\n schema: {\n parse(input: unknown): PersistedModelOutput<TSchema>;\n };\n};\n\nfunction defineObjectsProperty<TSchema extends z.ZodObject<z.ZodRawShape>, TKey extends string>(\n model: SchemaModel<TSchema, TKey>\n): void {\n Object.defineProperty(model, 'objects', {\n configurable: true,\n enumerable: true,\n get() {\n const runtime = getTangoRuntime();\n const cached = managerCache.get(model);\n if (cached && cached.runtime === runtime) {\n return cached.manager;\n }\n\n const manager = new ModelManager<PersistedModelOutput<TSchema>, SchemaModel<TSchema, TKey>>(\n model as unknown as AugmentableSchemaModel<TSchema>,\n runtime\n );\n managerCache.set(model, {\n runtime,\n manager: manager as ModelManager<Record<string, unknown>>,\n });\n return manager;\n },\n });\n}\n\n/**\n * Install the schema model augmentor that exposes `Model.objects`.\n * This registration is idempotent so multiple Tango entrypoints can safely call it.\n */\nexport function registerModelObjects(): void {\n if (hasRegisteredModelObjects) {\n return;\n }\n\n registerModelAugmentor(defineObjectsProperty);\n hasRegisteredModelObjects = true;\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { LoadedConfig } from '@danceroutine/tango-config';
|
|
2
2
|
import type { DBClient } from '../connection/index';
|
|
3
3
|
import type { Dialect } from '../query/domain/index';
|
|
4
|
+
import type { TransactionClientLease } from './internal/DBClientProvider';
|
|
4
5
|
/**
|
|
5
6
|
* Framework-owned database runtime that resolves Tango config and lazily
|
|
6
|
-
* creates the shared
|
|
7
|
+
* creates the shared connection provider used by manager-backed models.
|
|
7
8
|
*/
|
|
8
9
|
export declare class TangoRuntime {
|
|
9
10
|
static readonly BRAND: "tango.orm.runtime";
|
|
10
11
|
readonly __tangoBrand: typeof TangoRuntime.BRAND;
|
|
11
12
|
private readonly loadedConfig;
|
|
12
|
-
private
|
|
13
|
+
private providerPromise;
|
|
14
|
+
private runtimeClientPromise;
|
|
13
15
|
constructor(loadLoadedConfig: () => LoadedConfig);
|
|
14
16
|
/**
|
|
15
17
|
* Narrow an unknown value to `TangoRuntime`.
|
|
@@ -24,11 +26,22 @@ export declare class TangoRuntime {
|
|
|
24
26
|
*/
|
|
25
27
|
getDialect(): Dialect;
|
|
26
28
|
/**
|
|
27
|
-
* Return the
|
|
29
|
+
* Return the runtime-bound DB client facade used by manager-backed code.
|
|
28
30
|
*/
|
|
29
31
|
getClient(): Promise<DBClient>;
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
33
|
+
* Execute SQL through the autocommit path owned by this runtime.
|
|
34
|
+
*/
|
|
35
|
+
query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{
|
|
36
|
+
rows: T[];
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Lease a transaction-scoped client for `transaction.atomic(...)`.
|
|
40
|
+
*/
|
|
41
|
+
leaseTransactionClient(): Promise<TransactionClientLease>;
|
|
42
|
+
/**
|
|
43
|
+
* Close and clear the cached runtime resources so tests can start fresh.
|
|
32
44
|
*/
|
|
33
45
|
reset(): Promise<void>;
|
|
46
|
+
private getProvider;
|
|
34
47
|
}
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import "../
|
|
3
|
-
import "../
|
|
4
|
-
import "../
|
|
5
|
-
import {
|
|
6
|
-
import "../runtime-
|
|
1
|
+
import "../PostgresClient-BQJZfEOT.js";
|
|
2
|
+
import "../SqliteClient-CjOK9-ki.js";
|
|
3
|
+
import "../query-DYiJ5m_B.js";
|
|
4
|
+
import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "../defaultRuntime-BPK9kWEW.js";
|
|
5
|
+
import { registerModelObjects } from "../registerModelObjects-B1VzZ072.js";
|
|
6
|
+
import "../runtime-ByXbpVBS.js";
|
|
7
7
|
|
|
8
8
|
export { TangoRuntime, getTangoRuntime, initializeTangoRuntime, registerModelObjects, resetTangoRuntime };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DBClient } from '../../connection/clients/DBClient';
|
|
2
|
+
export interface TransactionClientLease {
|
|
3
|
+
readonly client: DBClient;
|
|
4
|
+
release(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface DBClientProvider {
|
|
7
|
+
query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{
|
|
8
|
+
rows: T[];
|
|
9
|
+
}>;
|
|
10
|
+
leaseTransactionClient(): Promise<TransactionClientLease>;
|
|
11
|
+
reset(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AdapterConfig } from '../../connection/adapters/Adapter';
|
|
2
|
+
import type { DBClientProvider, TransactionClientLease } from './DBClientProvider';
|
|
3
|
+
export declare class PostgresDBClientProvider implements DBClientProvider {
|
|
4
|
+
private readonly pool;
|
|
5
|
+
private activeLeaseCount;
|
|
6
|
+
constructor(config: AdapterConfig);
|
|
7
|
+
query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{
|
|
8
|
+
rows: T[];
|
|
9
|
+
}>;
|
|
10
|
+
leaseTransactionClient(): Promise<TransactionClientLease>;
|
|
11
|
+
reset(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AdapterConfig } from '../../connection/adapters/Adapter';
|
|
2
|
+
import type { DBClientProvider, TransactionClientLease } from './DBClientProvider';
|
|
3
|
+
export declare class SqliteDBClientProvider implements DBClientProvider {
|
|
4
|
+
private readonly filename;
|
|
5
|
+
private readonly Database;
|
|
6
|
+
private readonly autocommitClient;
|
|
7
|
+
private activeLeaseCount;
|
|
8
|
+
constructor(config?: AdapterConfig);
|
|
9
|
+
query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{
|
|
10
|
+
rows: T[];
|
|
11
|
+
}>;
|
|
12
|
+
leaseTransactionClient(): Promise<TransactionClientLease>;
|
|
13
|
+
reset(): Promise<void>;
|
|
14
|
+
private openClient;
|
|
15
|
+
private getDatabaseCtor;
|
|
16
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { __export } from "./chunk-DLY2FNSh.js";
|
|
2
|
-
import { TangoRuntime, getTangoRuntime, initializeTangoRuntime,
|
|
2
|
+
import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "./defaultRuntime-BPK9kWEW.js";
|
|
3
|
+
import { registerModelObjects } from "./registerModelObjects-B1VzZ072.js";
|
|
3
4
|
|
|
4
5
|
//#region src/runtime/index.ts
|
|
5
6
|
var runtime_exports = {};
|
|
@@ -14,4 +15,4 @@ registerModelObjects();
|
|
|
14
15
|
|
|
15
16
|
//#endregion
|
|
16
17
|
export { runtime_exports };
|
|
17
|
-
//# sourceMappingURL=runtime-
|
|
18
|
+
//# sourceMappingURL=runtime-ByXbpVBS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-
|
|
1
|
+
{"version":3,"file":"runtime-ByXbpVBS.js","names":[],"sources":["../src/runtime/index.ts"],"sourcesContent":["import type { z } from 'zod';\nimport type { ModelManager } from '../manager/ModelManager';\nimport type { Model, PersistedModelOutput } from '@danceroutine/tango-schema/domain';\nimport { registerModelObjects } from '../manager/registerModelObjects';\n\n/**\n * Domain boundary barrel: centralizes Tango runtime ownership APIs.\n */\n\ndeclare global {\n interface TangoSchemaModelAugmentations<\n TSchema extends z.ZodObject<z.ZodRawShape> = z.ZodObject<z.ZodRawShape>,\n TKey extends string = string,\n > {\n readonly objects: ModelManager<PersistedModelOutput<TSchema>, Model<TSchema, TKey>>;\n }\n}\n\nregisterModelObjects();\n\nexport { registerModelObjects } from '../manager/registerModelObjects';\nexport { TangoRuntime } from './TangoRuntime';\nexport { getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from './defaultRuntime';\n"],"mappings":";;;;;;;;;;;;;AAkBA,sBAAsB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface OnCommitOptions {
|
|
2
|
+
robust?: boolean;
|
|
3
|
+
}
|
|
4
|
+
export interface SavepointOptions {
|
|
5
|
+
throwOnError?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Result returned by `tx.savepoint(...)`.
|
|
9
|
+
*/
|
|
10
|
+
export type SavepointResult<T> = {
|
|
11
|
+
ok: true;
|
|
12
|
+
value: T;
|
|
13
|
+
} | {
|
|
14
|
+
ok: false;
|
|
15
|
+
error: unknown;
|
|
16
|
+
};
|
|
17
|
+
export interface AtomicTransaction {
|
|
18
|
+
/**
|
|
19
|
+
* Register a callback that should run only after the outermost transaction commit succeeds.
|
|
20
|
+
*/
|
|
21
|
+
onCommit(callback: () => void, options?: OnCommitOptions): void;
|
|
22
|
+
/**
|
|
23
|
+
* Run work inside a nested savepoint and, by default, capture rollback as a result object instead of throwing.
|
|
24
|
+
*/
|
|
25
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<SavepointResult<T>>;
|
|
26
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: {
|
|
27
|
+
throwOnError: false;
|
|
28
|
+
}): Promise<SavepointResult<T>>;
|
|
29
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: {
|
|
30
|
+
throwOnError: true;
|
|
31
|
+
}): Promise<T>;
|
|
32
|
+
}
|
|
@@ -15,6 +15,9 @@ import type { DBClient } from '../connection/clients/DBClient';
|
|
|
15
15
|
* throw error;
|
|
16
16
|
* }
|
|
17
17
|
* ```
|
|
18
|
+
*
|
|
19
|
+
* @deprecated Use `transaction.atomic(async (tx) => { ... })` for application
|
|
20
|
+
* transaction workflows. `UnitOfWork` remains exported only for compatibility.
|
|
18
21
|
*/
|
|
19
22
|
export declare class UnitOfWork {
|
|
20
23
|
static readonly BRAND: "tango.orm.unit_of_work";
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Domain boundary barrel: centralizes this subdomain's public contract.
|
|
3
3
|
*/
|
|
4
|
+
export { atomic } from './atomic';
|
|
5
|
+
export type { AtomicTransaction, OnCommitOptions, SavepointOptions, SavepointResult } from './AtomicTransaction';
|
|
4
6
|
export { UnitOfWork } from './UnitOfWork';
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../PostgresClient-BQJZfEOT.js";
|
|
2
|
+
import "../SqliteClient-CjOK9-ki.js";
|
|
3
|
+
import "../defaultRuntime-BPK9kWEW.js";
|
|
4
|
+
import { UnitOfWork, atomic } from "../transaction-Cs0Z9tbW.js";
|
|
2
5
|
|
|
3
|
-
export { UnitOfWork };
|
|
6
|
+
export { UnitOfWork, atomic };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TangoRuntime } from '../../../runtime/TangoRuntime';
|
|
2
|
+
import type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';
|
|
3
|
+
import type { AtomicTransaction, SavepointOptions, SavepointResult } from '../../AtomicTransaction';
|
|
4
|
+
import type { TransactionState } from './TransactionState';
|
|
5
|
+
export declare class AsyncLocalTransactionEngine {
|
|
6
|
+
private readonly logger;
|
|
7
|
+
private readonly storage;
|
|
8
|
+
assertNoActiveAtomicTransaction(): void;
|
|
9
|
+
getActiveTransaction(runtime: TangoRuntime): AtomicTransaction | undefined;
|
|
10
|
+
getActiveLease(runtime: TangoRuntime): TransactionClientLease | undefined;
|
|
11
|
+
atomic<T>(runtime: TangoRuntime, work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T>;
|
|
12
|
+
runSavepoint<T>(state: TransactionState, work: (tx: AtomicTransaction) => Promise<T> | T, options: SavepointOptions): Promise<T | SavepointResult<T>>;
|
|
13
|
+
private runNested;
|
|
14
|
+
private pushFrame;
|
|
15
|
+
private popFrame;
|
|
16
|
+
private rollbackOuter;
|
|
17
|
+
private runCommittedCallbacks;
|
|
18
|
+
private deactivateAllFrames;
|
|
19
|
+
private attachCause;
|
|
20
|
+
private isErrorValue;
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AtomicTransaction, OnCommitOptions, SavepointResult } from '../../AtomicTransaction';
|
|
2
|
+
import type { AsyncLocalTransactionEngine } from './AsyncLocalTransactionEngine';
|
|
3
|
+
import type { TransactionFrame } from './TransactionFrame';
|
|
4
|
+
import type { TransactionState } from './TransactionState';
|
|
5
|
+
export declare class FrameBoundTransaction implements AtomicTransaction {
|
|
6
|
+
private readonly engine;
|
|
7
|
+
private readonly state;
|
|
8
|
+
private readonly frame;
|
|
9
|
+
private active;
|
|
10
|
+
constructor(engine: AsyncLocalTransactionEngine, state: TransactionState, frame: TransactionFrame);
|
|
11
|
+
onCommit(callback: () => void, options?: OnCommitOptions): void;
|
|
12
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<SavepointResult<T>>;
|
|
13
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: {
|
|
14
|
+
throwOnError: false;
|
|
15
|
+
}): Promise<SavepointResult<T>>;
|
|
16
|
+
savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: {
|
|
17
|
+
throwOnError: true;
|
|
18
|
+
}): Promise<T>;
|
|
19
|
+
deactivate(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TangoRuntime } from '../../../runtime/TangoRuntime';
|
|
2
|
+
import type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';
|
|
3
|
+
import type { AtomicTransaction } from '../../AtomicTransaction';
|
|
4
|
+
/**
|
|
5
|
+
* Runtime-bound transaction facade used by internal ORM/runtime components.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TransactionEngine {
|
|
8
|
+
private readonly runtime;
|
|
9
|
+
private static readonly engine;
|
|
10
|
+
private constructor();
|
|
11
|
+
static forRuntime(runtime: TangoRuntime): TransactionEngine;
|
|
12
|
+
static assertNoActiveAtomicTransaction(): void;
|
|
13
|
+
getActiveTransaction(): AtomicTransaction | undefined;
|
|
14
|
+
getActiveLease(): TransactionClientLease | undefined;
|
|
15
|
+
atomic<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TangoRuntime } from '../../../runtime/TangoRuntime';
|
|
2
|
+
import type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';
|
|
3
|
+
import type { TransactionFrame } from './TransactionFrame';
|
|
4
|
+
export type TransactionState = {
|
|
5
|
+
runtime: TangoRuntime;
|
|
6
|
+
lease: TransactionClientLease;
|
|
7
|
+
frames: TransactionFrame[];
|
|
8
|
+
nextCallbackOrder: number;
|
|
9
|
+
nextSavepointId: number;
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TransactionEngine } from './TransactionEngine';
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { __export } from "./chunk-DLY2FNSh.js";
|
|
2
|
+
import { TransactionEngine, getTangoRuntime } from "./defaultRuntime-BPK9kWEW.js";
|
|
2
3
|
|
|
4
|
+
//#region src/transaction/atomic.ts
|
|
5
|
+
async function atomic(work) {
|
|
6
|
+
return TransactionEngine.forRuntime(getTangoRuntime()).atomic(work);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
3
10
|
//#region src/transaction/UnitOfWork.ts
|
|
4
11
|
var UnitOfWork = class UnitOfWork {
|
|
5
12
|
static BRAND = "tango.orm.unit_of_work";
|
|
@@ -19,6 +26,7 @@ var UnitOfWork = class UnitOfWork {
|
|
|
19
26
|
* Convenience factory that constructs and begins a unit of work.
|
|
20
27
|
*/
|
|
21
28
|
static async start(client) {
|
|
29
|
+
TransactionEngine.assertNoActiveAtomicTransaction();
|
|
22
30
|
const uow = new UnitOfWork(client);
|
|
23
31
|
await uow.begin();
|
|
24
32
|
return uow;
|
|
@@ -27,6 +35,7 @@ var UnitOfWork = class UnitOfWork {
|
|
|
27
35
|
* Begin a transaction if one is not already active.
|
|
28
36
|
*/
|
|
29
37
|
async begin() {
|
|
38
|
+
TransactionEngine.assertNoActiveAtomicTransaction();
|
|
30
39
|
if (!this.isActive) {
|
|
31
40
|
await this.client.begin();
|
|
32
41
|
this.isActive = true;
|
|
@@ -61,8 +70,11 @@ var UnitOfWork = class UnitOfWork {
|
|
|
61
70
|
//#endregion
|
|
62
71
|
//#region src/transaction/index.ts
|
|
63
72
|
var transaction_exports = {};
|
|
64
|
-
__export(transaction_exports, {
|
|
73
|
+
__export(transaction_exports, {
|
|
74
|
+
UnitOfWork: () => UnitOfWork,
|
|
75
|
+
atomic: () => atomic
|
|
76
|
+
});
|
|
65
77
|
|
|
66
78
|
//#endregion
|
|
67
|
-
export { UnitOfWork, transaction_exports };
|
|
68
|
-
//# sourceMappingURL=transaction-
|
|
79
|
+
export { UnitOfWork, atomic, transaction_exports };
|
|
80
|
+
//# sourceMappingURL=transaction-Cs0Z9tbW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-Cs0Z9tbW.js","names":["work: (tx: AtomicTransaction) => Promise<T> | T","client: DBClient","value: unknown"],"sources":["../src/transaction/atomic.ts","../src/transaction/UnitOfWork.ts","../src/transaction/index.ts"],"sourcesContent":["import { getTangoRuntime } from '../runtime/defaultRuntime';\nimport type { AtomicTransaction } from './AtomicTransaction';\nimport { TransactionEngine } from './internal/context';\n\nexport async function atomic<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n return TransactionEngine.forRuntime(getTangoRuntime()).atomic(work);\n}\n","import type { DBClient } from '../connection/clients/DBClient';\nimport { TransactionEngine } from './internal/context';\n\n/**\n * Unit of Work pattern implementation for managing database transactions.\n * Ensures that a set of operations either all succeed or all fail together.\n *\n * @example\n * ```typescript\n * const uow = await UnitOfWork.start(dbClient);\n * try {\n * await userRepo.create({ email: 'test@example.com' });\n * await postRepo.create({ title: 'Hello' });\n * await uow.commit();\n * } catch (error) {\n * await uow.rollback();\n * throw error;\n * }\n * ```\n *\n * @deprecated Use `transaction.atomic(async (tx) => { ... })` for application\n * transaction workflows. `UnitOfWork` remains exported only for compatibility.\n */\nexport class UnitOfWork {\n static readonly BRAND = 'tango.orm.unit_of_work' as const;\n readonly __tangoBrand: typeof UnitOfWork.BRAND = UnitOfWork.BRAND;\n protected client: DBClient;\n protected isActive = false;\n\n constructor(client: DBClient) {\n this.client = client;\n }\n\n /**\n * Narrow an unknown value to `UnitOfWork`.\n */\n static isUnitOfWork(value: unknown): value is UnitOfWork {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === UnitOfWork.BRAND\n );\n }\n\n /**\n * Convenience factory that constructs and begins a unit of work.\n */\n static async start(client: DBClient): Promise<UnitOfWork> {\n TransactionEngine.assertNoActiveAtomicTransaction();\n const uow = new UnitOfWork(client);\n await uow.begin();\n return uow;\n }\n\n /**\n * Begin a transaction if one is not already active.\n */\n async begin(): Promise<void> {\n TransactionEngine.assertNoActiveAtomicTransaction();\n if (!this.isActive) {\n await this.client.begin();\n this.isActive = true;\n }\n }\n\n /**\n * Commit the active transaction.\n */\n async commit(): Promise<void> {\n if (this.isActive) {\n await this.client.commit();\n this.isActive = false;\n }\n }\n\n /**\n * Return the underlying database client.\n */\n getClient(): DBClient {\n return this.client;\n }\n\n /**\n * Roll back the active transaction.\n */\n async rollback(): Promise<void> {\n if (this.isActive) {\n await this.client.rollback();\n this.isActive = false;\n }\n }\n}\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { atomic } from './atomic';\nexport type { AtomicTransaction, OnCommitOptions, SavepointOptions, SavepointResult } from './AtomicTransaction';\nexport { UnitOfWork } from './UnitOfWork';\n"],"mappings":";;;;AAIO,eAAe,OAAUA,MAA6D;AACzF,QAAO,kBAAkB,WAAW,iBAAiB,CAAC,CAAC,OAAO,KAAK;AACtE;;;;ICiBY,aAAN,MAAM,WAAW;CACpB,OAAgB,QAAQ;CACxB,eAAiD,WAAW;CAC5D;CACA,WAAqB;CAErB,YAAYC,QAAkB;AAC1B,OAAK,SAAS;CACjB;;;;CAKD,OAAO,aAAaC,OAAqC;AACrD,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,WAAW;CAEzE;;;;CAKD,aAAa,MAAMD,QAAuC;AACtD,oBAAkB,iCAAiC;EACnD,MAAM,MAAM,IAAI,WAAW;AAC3B,QAAM,IAAI,OAAO;AACjB,SAAO;CACV;;;;CAKD,MAAM,QAAuB;AACzB,oBAAkB,iCAAiC;AACnD,OAAK,KAAK,UAAU;AAChB,SAAM,KAAK,OAAO,OAAO;AACzB,QAAK,WAAW;EACnB;CACJ;;;;CAKD,MAAM,SAAwB;AAC1B,MAAI,KAAK,UAAU;AACf,SAAM,KAAK,OAAO,QAAQ;AAC1B,QAAK,WAAW;EACnB;CACJ;;;;CAKD,YAAsB;AAClB,SAAO,KAAK;CACf;;;;CAKD,MAAM,WAA0B;AAC5B,MAAI,KAAK,UAAU;AACf,SAAM,KAAK,OAAO,UAAU;AAC5B,QAAK,WAAW;EACnB;CACJ;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danceroutine/tango-orm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Model-first querying, runtime-managed database access, and transactions for Tango",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"zod": "^4.0.0",
|
|
52
|
-
"@danceroutine/tango-config": "1.
|
|
53
|
-
"@danceroutine/tango-core": "1.
|
|
54
|
-
"@danceroutine/tango-schema": "1.
|
|
52
|
+
"@danceroutine/tango-config": "1.5.0",
|
|
53
|
+
"@danceroutine/tango-core": "1.5.0",
|
|
54
|
+
"@danceroutine/tango-schema": "1.5.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"pg": "^8.13.1",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"tsdown": "^0.4.0",
|
|
75
75
|
"typescript": "^5.6.3",
|
|
76
76
|
"vitest": "^4.0.6",
|
|
77
|
-
"@danceroutine/tango-migrations": "1.
|
|
78
|
-
"@danceroutine/tango-testing": "1.
|
|
77
|
+
"@danceroutine/tango-migrations": "1.5.0",
|
|
78
|
+
"@danceroutine/tango-testing": "1.5.0"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"build": "tsdown",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PostgresAdapter-C9a1XJRx.js","names":["pool: pg.Pool","client: pg.PoolClient","value: unknown","sql: string","params?: readonly unknown[]","value: unknown","config: AdapterConfig"],"sources":["../src/connection/clients/dialects/PostgresClient.ts","../src/connection/adapters/dialects/PostgresAdapter.ts"],"sourcesContent":["import type pg from 'pg';\nimport type { DBClient } from '../DBClient';\n\n/**\n * `DBClient` implementation backed by a PostgreSQL pool client.\n */\nexport class PostgresClient implements DBClient {\n static readonly BRAND = 'tango.orm.postgres_client' as const;\n readonly __tangoBrand: typeof PostgresClient.BRAND = PostgresClient.BRAND;\n\n constructor(\n private pool: pg.Pool,\n private client: pg.PoolClient\n ) {}\n\n /**\n * Narrow an unknown value to `PostgresClient`.\n */\n static isPostgresClient(value: unknown): value is PostgresClient {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === PostgresClient.BRAND\n );\n }\n\n /**\n * Execute a SQL statement with optional bound parameters.\n */\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const result = await this.client.query(sql, params as unknown[]);\n return { rows: result.rows as T[] };\n }\n\n /**\n * Begin a database transaction.\n */\n async begin(): Promise<void> {\n await this.client.query('BEGIN');\n }\n\n /**\n * Commit the active transaction.\n */\n async commit(): Promise<void> {\n await this.client.query('COMMIT');\n }\n\n /**\n * Roll back the active transaction.\n */\n async rollback(): Promise<void> {\n await this.client.query('ROLLBACK');\n }\n\n /**\n * Release client resources and close the associated pool.\n */\n async close(): Promise<void> {\n this.client.release();\n await this.pool.end();\n }\n}\n","import pg from 'pg';\nimport type { Adapter, AdapterConfig } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { PostgresClient } from '../../clients/dialects/PostgresClient';\n\nconst { Pool } = pg;\n\n/**\n * Postgres adapter that turns adapter config into a transactional `DBClient`.\n */\nexport class PostgresAdapter implements Adapter {\n static readonly BRAND = 'tango.orm.postgres_adapter' as const;\n readonly __tangoBrand: typeof PostgresAdapter.BRAND = PostgresAdapter.BRAND;\n readonly name = 'postgres';\n /**\n * Declares capabilities of this database adapter.\n * Used by the migration runner and query compiler to determine which\n * SQL features can be safely used:\n * - transactionalDDL: Postgres supports DDL inside transactions (safe rollback of schema changes)\n * - concurrentIndex: Supports CREATE INDEX CONCURRENTLY (non-blocking index builds)\n * - validateForeignKeys: Supports deferred FK validation via NOT VALID + VALIDATE CONSTRAINT\n */\n readonly features = {\n transactionalDDL: true,\n concurrentIndex: true,\n validateForeignKeys: true,\n };\n\n /**\n * Narrow an unknown value to `PostgresAdapter`.\n */\n static isPostgresAdapter(value: unknown): value is PostgresAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === PostgresAdapter.BRAND\n );\n }\n\n /**\n * Open a Postgres connection pool and return a client-backed DB abstraction.\n */\n async connect(config: AdapterConfig): Promise<DBClient> {\n const pool = new Pool({\n connectionString: config.url,\n host: config.host,\n port: config.port,\n database: config.database,\n user: config.user,\n password: config.password,\n max: config.maxConnections || 10,\n });\n\n const client = await pool.connect();\n return new PostgresClient(pool, client);\n }\n}\n"],"mappings":";;;IAMa,iBAAN,MAAM,eAAmC;CAC5C,OAAgB,QAAQ;CACxB,eAAqD,eAAe;CAEpE,YACYA,MACAC,QACV;AAAA,OAFU,OAAA;AAAA,OACA,SAAA;CACR;;;;CAKJ,OAAO,iBAAiBC,OAAyC;AAC7D,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,eAAe;CAE7E;;;;CAKD,MAAM,MAAmBC,KAAaC,QAAqD;EACvF,MAAM,SAAS,MAAM,KAAK,OAAO,MAAM,KAAK,OAAoB;AAChE,SAAO,EAAE,MAAM,OAAO,KAAa;CACtC;;;;CAKD,MAAM,QAAuB;AACzB,QAAM,KAAK,OAAO,MAAM,QAAQ;CACnC;;;;CAKD,MAAM,SAAwB;AAC1B,QAAM,KAAK,OAAO,MAAM,SAAS;CACpC;;;;CAKD,MAAM,WAA0B;AAC5B,QAAM,KAAK,OAAO,MAAM,WAAW;CACtC;;;;CAKD,MAAM,QAAuB;AACzB,OAAK,OAAO,SAAS;AACrB,QAAM,KAAK,KAAK,KAAK;CACxB;AACJ;;;;ACzDD,MAAM,EAAE,MAAM,GAAG;IAKJ,kBAAN,MAAM,gBAAmC;CAC5C,OAAgB,QAAQ;CACxB,eAAsD,gBAAgB;CACtE,OAAgB;;;;;;;;;CAShB,WAAoB;EAChB,kBAAkB;EAClB,iBAAiB;EACjB,qBAAqB;CACxB;;;;CAKD,OAAO,kBAAkBC,OAA0C;AAC/D,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,gBAAgB;CAE9E;;;;CAKD,MAAM,QAAQC,QAA0C;EACpD,MAAM,OAAO,IAAI,KAAK;GAClB,kBAAkB,OAAO;GACzB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,KAAK,OAAO,kBAAkB;EACjC;EAED,MAAM,SAAS,MAAM,KAAK,SAAS;AACnC,SAAO,IAAI,eAAe,MAAM;CACnC;AACJ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SqliteAdapter-Dp6VRXmz.js","names":["db: Database.Database","value: unknown","sql: string","params?: readonly unknown[]","value: unknown","config: AdapterConfig"],"sources":["../src/connection/clients/dialects/SqliteClient.ts","../src/connection/adapters/dialects/SqliteAdapter.ts"],"sourcesContent":["import type Database from 'better-sqlite3';\nimport type { DBClient } from '../DBClient';\n\n/**\n * `DBClient` implementation backed by a synchronous `better-sqlite3` handle.\n */\nexport class SqliteClient implements DBClient {\n static readonly BRAND = 'tango.orm.sqlite_client' as const;\n readonly __tangoBrand: typeof SqliteClient.BRAND = SqliteClient.BRAND;\n private inTransaction = false;\n\n constructor(private db: Database.Database) {}\n\n /**\n * Narrow an unknown value to `SqliteClient`.\n */\n static isSqliteClient(value: unknown): value is SqliteClient {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === SqliteClient.BRAND\n );\n }\n\n /**\n * Execute a SQL statement with optional parameters.\n *\n * `SELECT`/`PRAGMA` statements return row data; write statements return\n * an empty row list.\n */\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const stmt = this.db.prepare(sql);\n const isPragmaWrite = /^\\s*PRAGMA\\b/i.test(sql) && /=/.test(sql);\n\n const normalizedParams = params?.map((param) => this.normalizeParam(param));\n\n if (!isPragmaWrite && stmt.reader) {\n const rows = normalizedParams ? stmt.all(...(normalizedParams as unknown[])) : stmt.all();\n return { rows: rows as T[] };\n }\n\n if (normalizedParams) {\n stmt.run(...(normalizedParams as unknown[]));\n } else {\n stmt.run();\n }\n return { rows: [] };\n }\n\n /**\n * Begin a transaction if one is not already active.\n */\n async begin(): Promise<void> {\n if (!this.inTransaction) {\n this.db.prepare('BEGIN').run();\n this.inTransaction = true;\n }\n }\n\n /**\n * Commit the active transaction.\n */\n async commit(): Promise<void> {\n if (this.inTransaction) {\n this.db.prepare('COMMIT').run();\n this.inTransaction = false;\n }\n }\n\n /**\n * Roll back the active transaction.\n */\n async rollback(): Promise<void> {\n if (this.inTransaction) {\n this.db.prepare('ROLLBACK').run();\n this.inTransaction = false;\n }\n }\n\n /**\n * Close the underlying SQLite handle.\n */\n async close(): Promise<void> {\n this.db.close();\n }\n\n private normalizeParam(value: unknown): unknown {\n if (isDateValue(value)) {\n return value.toISOString();\n }\n if (typeof value === 'boolean') {\n return value ? 1 : 0;\n }\n return value;\n }\n}\n\nfunction isDateValue(value: unknown): value is Date {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { getTime?: unknown }).getTime === 'function' &&\n typeof (value as { toISOString?: unknown }).toISOString === 'function'\n );\n}\n","import { createRequire } from 'node:module';\nimport type { Database as BetterSqliteDatabase } from 'better-sqlite3';\nimport type { Adapter, AdapterConfig } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { SqliteClient } from '../../clients/dialects/SqliteClient';\n\ntype BetterSqliteCtor = new (filename: string, options?: unknown) => BetterSqliteDatabase;\n\n/**\n * SQLite adapter that creates a `better-sqlite3` backed `DBClient`.\n */\nexport class SqliteAdapter implements Adapter {\n static readonly BRAND = 'tango.orm.sqlite_adapter' as const;\n readonly __tangoBrand: typeof SqliteAdapter.BRAND = SqliteAdapter.BRAND;\n readonly name = 'sqlite';\n readonly features = {\n transactionalDDL: true,\n concurrentIndex: false,\n validateForeignKeys: false,\n };\n\n /**\n * Narrow an unknown value to `SqliteAdapter`.\n */\n static isSqliteAdapter(value: unknown): value is SqliteAdapter {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === SqliteAdapter.BRAND\n );\n }\n\n /**\n * Open a SQLite database and apply baseline pragmas for durability/safety.\n */\n async connect(config: AdapterConfig = {}): Promise<DBClient> {\n const Database = this.getDatabaseCtor();\n const filename =\n typeof config.filename === 'string' && config.filename.length > 0 ? config.filename : ':memory:';\n const db = new Database(filename);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n\n return new SqliteClient(db);\n }\n\n private getDatabaseCtor(): BetterSqliteCtor {\n const require = createRequire(import.meta.url);\n const moduleValue = require('better-sqlite3') as unknown;\n if (typeof moduleValue === 'function') {\n return moduleValue as BetterSqliteCtor;\n }\n\n const defaultExport = (moduleValue as { default?: unknown }).default;\n if (typeof defaultExport === 'function') {\n return defaultExport as BetterSqliteCtor;\n }\n\n throw new TypeError('Failed to load better-sqlite3 constructor.');\n }\n}\n"],"mappings":";;;IAMa,eAAN,MAAM,aAAiC;CAC1C,OAAgB,QAAQ;CACxB,eAAmD,aAAa;CAChE,gBAAwB;CAExB,YAAoBA,IAAuB;AAAA,OAAvB,KAAA;CAAyB;;;;CAK7C,OAAO,eAAeC,OAAuC;AACzD,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,aAAa;CAE3E;;;;;;;CAQD,MAAM,MAAmBC,KAAaC,QAAqD;EACvF,MAAM,OAAO,KAAK,GAAG,QAAQ,IAAI;EACjC,MAAM,gBAAgB,gBAAgB,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;EAEhE,MAAM,mBAAmB,QAAQ,IAAI,CAAC,UAAU,KAAK,eAAe,MAAM,CAAC;AAE3E,OAAK,iBAAiB,KAAK,QAAQ;GAC/B,MAAM,OAAO,mBAAmB,KAAK,IAAI,GAAI,iBAA+B,GAAG,KAAK,KAAK;AACzF,UAAO,EAAQ,KAAa;EAC/B;AAED,MAAI,iBACA,MAAK,IAAI,GAAI,iBAA+B;IAE5C,MAAK,KAAK;AAEd,SAAO,EAAE,MAAM,CAAE,EAAE;CACtB;;;;CAKD,MAAM,QAAuB;AACzB,OAAK,KAAK,eAAe;AACrB,QAAK,GAAG,QAAQ,QAAQ,CAAC,KAAK;AAC9B,QAAK,gBAAgB;EACxB;CACJ;;;;CAKD,MAAM,SAAwB;AAC1B,MAAI,KAAK,eAAe;AACpB,QAAK,GAAG,QAAQ,SAAS,CAAC,KAAK;AAC/B,QAAK,gBAAgB;EACxB;CACJ;;;;CAKD,MAAM,WAA0B;AAC5B,MAAI,KAAK,eAAe;AACpB,QAAK,GAAG,QAAQ,WAAW,CAAC,KAAK;AACjC,QAAK,gBAAgB;EACxB;CACJ;;;;CAKD,MAAM,QAAuB;AACzB,OAAK,GAAG,OAAO;CAClB;CAED,eAAuBF,OAAyB;AAC5C,MAAI,YAAY,MAAM,CAClB,QAAO,MAAM,aAAa;AAE9B,aAAW,UAAU,UACjB,QAAO,QAAQ,IAAI;AAEvB,SAAO;CACV;AACJ;AAED,SAAS,YAAYA,OAA+B;AAChD,eACW,UAAU,YACjB,UAAU,eACF,MAAgC,YAAY,qBAC5C,MAAoC,gBAAgB;AAEnE;;;;IC7FY,gBAAN,MAAM,cAAiC;CAC1C,OAAgB,QAAQ;CACxB,eAAoD,cAAc;CAClE,OAAgB;CAChB,WAAoB;EAChB,kBAAkB;EAClB,iBAAiB;EACjB,qBAAqB;CACxB;;;;CAKD,OAAO,gBAAgBG,OAAwC;AAC3D,gBACW,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,cAAc;CAE5E;;;;CAKD,MAAM,QAAQC,SAAwB,CAAE,GAAqB;EACzD,MAAM,WAAW,KAAK,iBAAiB;EACvC,MAAM,kBACK,OAAO,aAAa,YAAY,OAAO,SAAS,SAAS,IAAI,OAAO,WAAW;EAC1F,MAAM,KAAK,IAAI,SAAS;AACxB,KAAG,OAAO,qBAAqB;AAC/B,KAAG,OAAO,oBAAoB;AAE9B,SAAO,IAAI,aAAa;CAC3B;CAED,kBAA4C;EACxC,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;EAC9C,MAAM,cAAc,QAAQ,iBAAiB;AAC7C,aAAW,gBAAgB,WACvB,QAAO;EAGX,MAAM,gBAAiB,YAAsC;AAC7D,aAAW,kBAAkB,WACzB,QAAO;AAGX,QAAM,IAAI,UAAU;CACvB;AACJ"}
|