@danceroutine/tango-orm 1.11.8 → 1.11.9
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/{SqliteAdapter-6oyUmoJf.js → SqliteAdapter-CrUhpTDb.js} +33 -13
- package/dist/SqliteAdapter-CrUhpTDb.js.map +1 -0
- package/dist/connection/index.d.ts +1 -1
- package/dist/connection/index.js +2 -2
- package/dist/{connection-D-E6_Yf1.js → connection-B2cDwZ72.js} +4 -4
- package/dist/{connection-D-E6_Yf1.js.map → connection-B2cDwZ72.js.map} +1 -1
- package/dist/{defaultRuntime-CdTX8cXm.js → defaultRuntime-WIsxnh8K.js} +19 -17
- package/dist/defaultRuntime-WIsxnh8K.js.map +1 -0
- package/dist/{index-B-aibguC.d.ts → index-o2LFpJ8S.d.ts} +15 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/manager/index.js +2 -2
- package/dist/{manager-CiYqAYpn.js → manager-DRra01q8.js} +2 -2
- package/dist/{manager-CiYqAYpn.js.map → manager-DRra01q8.js.map} +1 -1
- package/dist/{registerModelObjects-DZfZ20fa.js → registerModelObjects-CGjjOzd9.js} +2 -2
- package/dist/{registerModelObjects-DZfZ20fa.js.map → registerModelObjects-CGjjOzd9.js.map} +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/transaction/index.js +1 -1
- package/dist/{transaction-2_2m7VUo.js → transaction-DpDXQq5V.js} +2 -2
- package/dist/{transaction-2_2m7VUo.js.map → transaction-DpDXQq5V.js.map} +1 -1
- package/package.json +6 -6
- package/dist/SqliteAdapter-6oyUmoJf.js.map +0 -1
- package/dist/defaultRuntime-CdTX8cXm.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-8H4AJuhK.js";
|
|
2
2
|
import { t as InternalDialect } from "./InternalDialect-U3mwJjKA.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import pg from "pg";
|
|
5
4
|
//#region src/connection/clients/dialects/PostgresClient.ts
|
|
6
5
|
/**
|
|
7
6
|
* Transaction-capable client backed by a PostgreSQL pool client.
|
|
@@ -69,9 +68,37 @@ var PostgresClient = class PostgresClient {
|
|
|
69
68
|
}
|
|
70
69
|
};
|
|
71
70
|
//#endregion
|
|
71
|
+
//#region src/connection/clients/dialects/PostgresPoolProvider.ts
|
|
72
|
+
var PostgresPoolProvider = class {
|
|
73
|
+
async createPool(config) {
|
|
74
|
+
return new (await (this.loadPostgresPoolConstructor()))({
|
|
75
|
+
connectionString: config.url,
|
|
76
|
+
host: config.host,
|
|
77
|
+
port: config.port,
|
|
78
|
+
database: config.database,
|
|
79
|
+
user: config.user,
|
|
80
|
+
password: config.password,
|
|
81
|
+
max: config.maxConnections || 10
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async loadPostgresPoolConstructor() {
|
|
85
|
+
return this.resolvePostgresPoolConstructor(await import("pg"));
|
|
86
|
+
}
|
|
87
|
+
resolvePostgresPoolConstructor(moduleValue) {
|
|
88
|
+
const defaultPool = this.readProperty(this.readProperty(moduleValue, "default"), "Pool");
|
|
89
|
+
if (typeof defaultPool === "function") return defaultPool;
|
|
90
|
+
const directPool = this.readProperty(moduleValue, "Pool");
|
|
91
|
+
if (typeof directPool === "function") return directPool;
|
|
92
|
+
throw new TypeError("Failed to load pg Pool constructor.");
|
|
93
|
+
}
|
|
94
|
+
readProperty(value, key) {
|
|
95
|
+
if (typeof value !== "object" || value === null || !(key in value)) return;
|
|
96
|
+
return value[key];
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
72
100
|
//#region src/connection/adapters/dialects/PostgresAdapter.ts
|
|
73
101
|
var PostgresAdapter_exports = /* @__PURE__ */ __exportAll({ PostgresAdapter: () => PostgresAdapter });
|
|
74
|
-
const { Pool } = pg;
|
|
75
102
|
/**
|
|
76
103
|
* Postgres adapter that turns adapter config into a transactional `DBClient`.
|
|
77
104
|
*/
|
|
@@ -106,6 +133,7 @@ var PostgresAdapter = class PostgresAdapter {
|
|
|
106
133
|
return Array.from({ length: count }, (_value, index) => `$${startOffset + index + 1}`).join(", ");
|
|
107
134
|
}
|
|
108
135
|
};
|
|
136
|
+
poolProvider = new PostgresPoolProvider();
|
|
109
137
|
/**
|
|
110
138
|
* Narrow an unknown value to `PostgresAdapter`.
|
|
111
139
|
*/
|
|
@@ -116,15 +144,7 @@ var PostgresAdapter = class PostgresAdapter {
|
|
|
116
144
|
* Open a Postgres connection pool and return a client-backed DB abstraction.
|
|
117
145
|
*/
|
|
118
146
|
async connect(config) {
|
|
119
|
-
return new PostgresClient(await
|
|
120
|
-
connectionString: config.url,
|
|
121
|
-
host: config.host,
|
|
122
|
-
port: config.port,
|
|
123
|
-
database: config.database,
|
|
124
|
-
user: config.user,
|
|
125
|
-
password: config.password,
|
|
126
|
-
max: config.maxConnections || 10
|
|
127
|
-
}).connect());
|
|
147
|
+
return new PostgresClient(await (await this.poolProvider.createPool(config)).connect());
|
|
128
148
|
}
|
|
129
149
|
};
|
|
130
150
|
//#endregion
|
|
@@ -274,6 +294,6 @@ var SqliteAdapter = class SqliteAdapter {
|
|
|
274
294
|
}
|
|
275
295
|
};
|
|
276
296
|
//#endregion
|
|
277
|
-
export { PostgresAdapter_exports as a, PostgresAdapter as i, SqliteAdapter_exports as n,
|
|
297
|
+
export { PostgresAdapter_exports as a, PostgresAdapter as i, SqliteAdapter_exports as n, PostgresPoolProvider as o, SqliteClient as r, PostgresClient as s, SqliteAdapter as t };
|
|
278
298
|
|
|
279
|
-
//# sourceMappingURL=SqliteAdapter-
|
|
299
|
+
//# sourceMappingURL=SqliteAdapter-CrUhpTDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqliteAdapter-CrUhpTDb.js","names":[],"sources":["../src/connection/clients/dialects/PostgresClient.ts","../src/connection/clients/dialects/PostgresPoolProvider.ts","../src/connection/adapters/dialects/PostgresAdapter.ts","../src/connection/clients/dialects/SqliteClient.ts","../src/connection/adapters/dialects/SqliteAdapter.ts"],"sourcesContent":["import type { DBClient } from '../DBClient';\n\nexport interface PostgresPoolClientLike {\n query(sql: string, params?: readonly unknown[]): Promise<{ rows: unknown[] }>;\n release(): void;\n}\n\n/**\n * Transaction-capable client 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(private client: PostgresPoolClientLike) {}\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 * Create a savepoint inside the active transaction.\n */\n async createSavepoint(name: string): Promise<void> {\n await this.client.query(`SAVEPOINT ${name}`);\n }\n\n /**\n * Release a previously-created savepoint.\n */\n async releaseSavepoint(name: string): Promise<void> {\n await this.client.query(`RELEASE SAVEPOINT ${name}`);\n }\n\n /**\n * Roll back the active transaction to a savepoint.\n */\n async rollbackToSavepoint(name: string): Promise<void> {\n await this.client.query(`ROLLBACK TO SAVEPOINT ${name}`);\n }\n\n /**\n * Release the leased PostgreSQL client back to its owning pool.\n */\n async close(): Promise<void> {\n this.client.release();\n }\n}\n","import type { PostgresPoolClientLike } from './PostgresClient';\n\nexport type PostgresPoolLike = {\n query(sql: string, params?: readonly unknown[]): Promise<{ rows: unknown[] }>;\n connect(): Promise<PostgresPoolClientLike>;\n end(): Promise<void>;\n};\n\ntype PostgresPoolConstructor = new (config: {\n connectionString?: string;\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n password?: string;\n max: number;\n}) => PostgresPoolLike;\n\nexport type PostgresPoolConfig = {\n url?: string;\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n password?: string;\n maxConnections?: number;\n};\n\nexport class PostgresPoolProvider {\n async createPool(config: PostgresPoolConfig): Promise<PostgresPoolLike> {\n const Pool = await this.loadPostgresPoolConstructor();\n return 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\n private async loadPostgresPoolConstructor(): Promise<PostgresPoolConstructor> {\n return this.resolvePostgresPoolConstructor(await import('pg'));\n }\n\n private resolvePostgresPoolConstructor(moduleValue: unknown): PostgresPoolConstructor {\n const defaultPool = this.readProperty(this.readProperty(moduleValue, 'default'), 'Pool');\n if (typeof defaultPool === 'function') {\n return defaultPool as PostgresPoolConstructor;\n }\n\n const directPool = this.readProperty(moduleValue, 'Pool');\n if (typeof directPool === 'function') {\n return directPool as PostgresPoolConstructor;\n }\n\n throw new TypeError('Failed to load pg Pool constructor.');\n }\n\n private readProperty(value: unknown, key: string): unknown {\n if (typeof value !== 'object' || value === null || !(key in value)) {\n return undefined;\n }\n\n return (value as Record<string, unknown>)[key];\n }\n}\n","import type { Adapter, AdapterConfig, SqlPlaceholders } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { PostgresClient } from '../../clients/dialects/PostgresClient';\nimport { PostgresPoolProvider } from '../../clients/dialects/PostgresPoolProvider';\nimport { InternalDialect } from '../../../query/domain/internal/InternalDialect';\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 readonly dialect: Adapter['dialect'] = InternalDialect.POSTGRES;\n\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 * - ignoreDuplicateInsert: Supports duplicate-safe insert semantics for manager-owned link writes\n */\n readonly features: Adapter['features'] = {\n transactionalDDL: true,\n concurrentIndex: true,\n validateForeignKeys: true,\n ignoreDuplicateInsert: true,\n };\n readonly placeholders: SqlPlaceholders = {\n at(index: number): string {\n return `$${index}`;\n },\n list(count: number): string {\n return this.listFromOffset(count, 0);\n },\n listFromOffset(count: number, startOffset: number): string {\n return Array.from({ length: count }, (_value, index) => `$${startOffset + index + 1}`).join(', ');\n },\n };\n private readonly poolProvider = new PostgresPoolProvider();\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 = await this.poolProvider.createPool(config);\n const client = await pool.connect();\n return new PostgresClient(client);\n }\n}\n","import type { DBClient } from '../DBClient';\nimport type { SqliteDatabaseLike } from './SqliteDatabaseLike';\n\n/**\n * Transaction-capable client 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: SqliteDatabaseLike) {}\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 IMMEDIATE').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 * Create a savepoint inside the active transaction.\n */\n async createSavepoint(name: string): Promise<void> {\n this.db.prepare(`SAVEPOINT ${name}`).run();\n }\n\n /**\n * Release a previously-created savepoint.\n */\n async releaseSavepoint(name: string): Promise<void> {\n this.db.prepare(`RELEASE SAVEPOINT ${name}`).run();\n }\n\n /**\n * Roll back the active transaction to a savepoint.\n */\n async rollbackToSavepoint(name: string): Promise<void> {\n this.db.prepare(`ROLLBACK TO SAVEPOINT ${name}`).run();\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 { Adapter, AdapterConfig, SqlPlaceholders } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { SqliteClient } from '../../clients/dialects/SqliteClient';\nimport type { SqliteDatabaseConstructor } from '../../clients/dialects/SqliteDatabaseLike';\nimport { InternalDialect } from '../../../query/domain/internal/InternalDialect';\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 dialect: Adapter['dialect'] = InternalDialect.SQLITE;\n readonly features: Adapter['features'] = {\n transactionalDDL: true,\n concurrentIndex: false,\n validateForeignKeys: false,\n ignoreDuplicateInsert: true,\n };\n readonly placeholders: SqlPlaceholders = {\n at(): string {\n return '?';\n },\n list(count: number): string {\n return Array.from({ length: count }, () => '?').join(', ');\n },\n listFromOffset(count: number): string {\n return this.list(count);\n },\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 db.pragma('busy_timeout = 5000');\n\n return new SqliteClient(db);\n }\n\n private getDatabaseCtor(): SqliteDatabaseConstructor {\n const require = createRequire(import.meta.url);\n const moduleValue = require('better-sqlite3') as unknown;\n if (typeof moduleValue === 'function') {\n return moduleValue as SqliteDatabaseConstructor;\n }\n\n const defaultExport = (moduleValue as { default?: unknown }).default;\n if (typeof defaultExport === 'function') {\n return defaultExport as SqliteDatabaseConstructor;\n }\n\n throw new TypeError('Failed to load better-sqlite3 constructor.');\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { t as DBClient } from "../DBClient-DuYcXolQ.js";
|
|
2
2
|
import { n as AdapterConfig, r as SqlPlaceholders, t as Adapter } from "../Adapter-DKxAaL4l.js";
|
|
3
|
-
import { a as index_d_exports, c as getDefaultAdapterRegistry, i as PostgresClient, l as SqliteAdapter, n as index_d_exports$1, o as AdapterRegistry, r as SqliteClient, s as connectDB, u as PostgresAdapter } from "../index-
|
|
3
|
+
import { a as index_d_exports, c as getDefaultAdapterRegistry, i as PostgresClient, l as SqliteAdapter, n as index_d_exports$1, o as AdapterRegistry, r as SqliteClient, s as connectDB, u as PostgresAdapter } from "../index-o2LFpJ8S.js";
|
|
4
4
|
export { type Adapter, type AdapterConfig, AdapterRegistry, type DBClient, PostgresAdapter, PostgresClient, type SqlPlaceholders, SqliteAdapter, SqliteClient, index_d_exports as adapters, index_d_exports$1 as clients, connectDB, getDefaultAdapterRegistry };
|
package/dist/connection/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as PostgresAdapter,
|
|
2
|
-
import { a as connectDB, i as AdapterRegistry, n as clients_exports, o as getDefaultAdapterRegistry, r as adapters_exports } from "../connection-
|
|
1
|
+
import { i as PostgresAdapter, r as SqliteClient, s as PostgresClient, t as SqliteAdapter } from "../SqliteAdapter-CrUhpTDb.js";
|
|
2
|
+
import { a as connectDB, i as AdapterRegistry, n as clients_exports, o as getDefaultAdapterRegistry, r as adapters_exports } from "../connection-B2cDwZ72.js";
|
|
3
3
|
export { AdapterRegistry, PostgresAdapter, PostgresClient, SqliteAdapter, SqliteClient, adapters_exports as adapters, clients_exports as clients, connectDB, getDefaultAdapterRegistry };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-8H4AJuhK.js";
|
|
2
|
-
import { i as PostgresAdapter,
|
|
2
|
+
import { i as PostgresAdapter, r as SqliteClient, s as PostgresClient, t as SqliteAdapter } from "./SqliteAdapter-CrUhpTDb.js";
|
|
3
3
|
//#region src/connection/adapters/dialects/index.ts
|
|
4
4
|
var dialects_exports$1 = /* @__PURE__ */ __exportAll({
|
|
5
5
|
PostgresAdapter: () => PostgresAdapter,
|
|
@@ -30,8 +30,8 @@ var AdapterRegistry = class AdapterRegistry {
|
|
|
30
30
|
static async getDefaultRegistry() {
|
|
31
31
|
if (AdapterRegistry.defaultRegistryInstance) return AdapterRegistry.defaultRegistryInstance;
|
|
32
32
|
AdapterRegistry.defaultRegistryInstance = new AdapterRegistry();
|
|
33
|
-
const { PostgresAdapter } = await import("./SqliteAdapter-
|
|
34
|
-
const { SqliteAdapter } = await import("./SqliteAdapter-
|
|
33
|
+
const { PostgresAdapter } = await import("./SqliteAdapter-CrUhpTDb.js").then((n) => n.a);
|
|
34
|
+
const { SqliteAdapter } = await import("./SqliteAdapter-CrUhpTDb.js").then((n) => n.n);
|
|
35
35
|
AdapterRegistry.defaultRegistryInstance.register(new PostgresAdapter());
|
|
36
36
|
AdapterRegistry.defaultRegistryInstance.register(new SqliteAdapter());
|
|
37
37
|
return AdapterRegistry.defaultRegistryInstance;
|
|
@@ -112,4 +112,4 @@ var connection_exports = /* @__PURE__ */ __exportAll({
|
|
|
112
112
|
//#endregion
|
|
113
113
|
export { connectDB as a, AdapterRegistry as i, clients_exports as n, getDefaultAdapterRegistry as o, adapters_exports as r, connection_exports as t };
|
|
114
114
|
|
|
115
|
-
//# sourceMappingURL=connection-
|
|
115
|
+
//# sourceMappingURL=connection-B2cDwZ72.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-
|
|
1
|
+
{"version":3,"file":"connection-B2cDwZ72.js","names":[],"sources":["../src/connection/adapters/dialects/index.ts","../src/connection/adapters/AdapterRegistry.ts","../src/connection/adapters/index.ts","../src/connection/clients/dialects/index.ts","../src/connection/clients/index.ts","../src/connection/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { PostgresAdapter } from './PostgresAdapter';\nexport { SqliteAdapter } from './SqliteAdapter';\n","import type { Adapter, AdapterConfig } from './Adapter';\nimport type { DBClient } from '../clients/DBClient';\n\n/**\n * Runtime registry for database adapters.\n *\n * Use a custom instance when tests or applications need explicit control\n * over supported adapters; use `getDefaultRegistry()` for the built-in set.\n */\nexport class AdapterRegistry {\n static readonly BRAND = 'tango.orm.adapter_registry' as const;\n private static defaultRegistryInstance: AdapterRegistry | undefined;\n readonly __tangoBrand: typeof AdapterRegistry.BRAND = AdapterRegistry.BRAND;\n private adapters = new Map<string, Adapter>();\n\n /**\n * Narrow an unknown value to `AdapterRegistry`.\n */\n static isAdapterRegistry(value: unknown): value is AdapterRegistry {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === AdapterRegistry.BRAND\n );\n }\n\n /**\n * Return a lazily-initialized registry preloaded with built-in adapters.\n */\n static async getDefaultRegistry(): Promise<AdapterRegistry> {\n if (AdapterRegistry.defaultRegistryInstance) {\n return AdapterRegistry.defaultRegistryInstance;\n }\n\n AdapterRegistry.defaultRegistryInstance = new AdapterRegistry();\n\n const { PostgresAdapter } = await import('./dialects/PostgresAdapter');\n const { SqliteAdapter } = await import('./dialects/SqliteAdapter');\n\n AdapterRegistry.defaultRegistryInstance.register(new PostgresAdapter());\n AdapterRegistry.defaultRegistryInstance.register(new SqliteAdapter());\n\n return AdapterRegistry.defaultRegistryInstance;\n }\n\n /**\n * Register an adapter under its declared `name`.\n */\n register(adapter: Adapter): this {\n this.adapters.set(adapter.name, adapter);\n return this;\n }\n\n /**\n * Resolve an adapter by name, or throw a descriptive error.\n */\n get(name: string): Adapter {\n const adapter = this.adapters.get(name);\n if (!adapter) {\n const available = [...this.adapters.keys()].join(', ');\n throw new Error(`Unknown adapter: ${name}. Available adapters: ${available || 'none'}`);\n }\n return adapter;\n }\n\n /**\n * Check whether an adapter has been registered.\n */\n has(name: string): boolean {\n return this.adapters.has(name);\n }\n}\n\n/**\n * Connect to a database by adapter name using the provided (or default) registry.\n */\nexport async function connectDB(\n config: AdapterConfig & { adapter: string },\n registry?: AdapterRegistry\n): Promise<DBClient> {\n const effectiveRegistry = registry ?? (await AdapterRegistry.getDefaultRegistry());\n const adapter = effectiveRegistry.get(config.adapter);\n return adapter.connect(config);\n}\n\n/**\n * Convenience helper that exposes the singleton default adapter registry.\n */\nexport async function getDefaultAdapterRegistry(): Promise<AdapterRegistry> {\n return AdapterRegistry.getDefaultRegistry();\n}\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as dialects from './dialects/index';\n\nexport { AdapterRegistry, connectDB, getDefaultAdapterRegistry } from './AdapterRegistry';\nexport type { Adapter, AdapterConfig, SqlPlaceholders } from './Adapter';\nexport { PostgresAdapter, SqliteAdapter } from './dialects/index';\n","/**\n * Domain boundary barrel: centralizes this subdomain's public contract.\n */\n\nexport { PostgresClient } from './PostgresClient';\nexport { SqliteClient } from './SqliteClient';\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as dialects from './dialects/index';\n\nexport type { DBClient } from './DBClient';\nexport { PostgresClient, SqliteClient } from './dialects/index';\n","/**\n * Domain boundary barrel: exposes namespaced exports for Django-style drill-down\n * imports and curated flat exports for TS-native ergonomics.\n */\n\nexport * as adapters from './adapters/index';\nexport * as clients from './clients/index';\n\nexport { AdapterRegistry, connectDB, getDefaultAdapterRegistry } from './adapters/index';\nexport type { Adapter, AdapterConfig, SqlPlaceholders } from './adapters/index';\nexport type { DBClient } from './clients/DBClient';\nexport { PostgresAdapter, SqliteAdapter } from './adapters/index';\nexport { PostgresClient, SqliteClient } from './clients/index';\n"],"mappings":";;;;;;;;;;;;;;;ACSA,IAAa,kBAAb,MAAa,gBAAgB;CACzB,OAAgB,QAAQ;CACxB,OAAe;CACf,eAAsD,gBAAgB;CACtE,2BAAmB,IAAI,IAAqB;;;;CAK5C,OAAO,kBAAkB,OAA0C;EAC/D,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,gBAAgB;CAE/E;;;;CAKA,aAAa,qBAA+C;EACxD,IAAI,gBAAgB,yBAChB,OAAO,gBAAgB;EAG3B,gBAAgB,0BAA0B,IAAI,gBAAgB;EAE9D,MAAM,EAAE,oBAAoB,MAAM,OAAO,+BAAA,MAAA,MAAA,EAAA,CAAA;EACzC,MAAM,EAAE,kBAAkB,MAAM,OAAO,+BAAA,MAAA,MAAA,EAAA,CAAA;EAEvC,gBAAgB,wBAAwB,SAAS,IAAI,gBAAgB,CAAC;EACtE,gBAAgB,wBAAwB,SAAS,IAAI,cAAc,CAAC;EAEpE,OAAO,gBAAgB;CAC3B;;;;CAKA,SAAS,SAAwB;EAC7B,KAAK,SAAS,IAAI,QAAQ,MAAM,OAAO;EACvC,OAAO;CACX;;;;CAKA,IAAI,MAAuB;EACvB,MAAM,UAAU,KAAK,SAAS,IAAI,IAAI;EACtC,IAAI,CAAC,SAAS;GACV,MAAM,YAAY,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC,EAAE,KAAK,IAAI;GACrD,MAAM,IAAI,MAAM,oBAAoB,KAAK,wBAAwB,aAAa,QAAQ;EAC1F;EACA,OAAO;CACX;;;;CAKA,IAAI,MAAuB;EACvB,OAAO,KAAK,SAAS,IAAI,IAAI;CACjC;AACJ;;;;AAKA,eAAsB,UAClB,QACA,UACiB;CAGjB,QAF0B,YAAa,MAAM,gBAAgB,mBAAmB,GAC9C,IAAI,OAAO,OAChC,EAAE,QAAQ,MAAM;AACjC;;;;AAKA,eAAsB,4BAAsD;CACxE,OAAO,gBAAgB,mBAAmB;AAC9C"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { i as PostgresAdapter, o as
|
|
1
|
+
import { i as PostgresAdapter, o as PostgresPoolProvider, r as SqliteClient, s as PostgresClient, t as SqliteAdapter } from "./SqliteAdapter-CrUhpTDb.js";
|
|
2
2
|
import { t as InternalDialect } from "./InternalDialect-U3mwJjKA.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import pg from "pg";
|
|
5
4
|
import { getLogger } from "@danceroutine/tango-core";
|
|
6
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
6
|
import { loadConfig, loadConfigFromProjectRoot } from "@danceroutine/tango-config";
|
|
@@ -244,26 +243,19 @@ var RuntimeBoundClient = class {
|
|
|
244
243
|
};
|
|
245
244
|
//#endregion
|
|
246
245
|
//#region src/runtime/internal/PostgresDBClientProvider.ts
|
|
247
|
-
const { Pool } = pg;
|
|
248
246
|
var PostgresDBClientProvider = class {
|
|
249
|
-
|
|
247
|
+
config;
|
|
248
|
+
poolProvider = new PostgresPoolProvider();
|
|
249
|
+
poolPromise = null;
|
|
250
250
|
activeLeaseCount = 0;
|
|
251
251
|
constructor(config) {
|
|
252
|
-
this.
|
|
253
|
-
connectionString: config.url,
|
|
254
|
-
host: config.host,
|
|
255
|
-
port: config.port,
|
|
256
|
-
database: config.database,
|
|
257
|
-
user: config.user,
|
|
258
|
-
password: config.password,
|
|
259
|
-
max: config.maxConnections || 10
|
|
260
|
-
});
|
|
252
|
+
this.config = config;
|
|
261
253
|
}
|
|
262
254
|
async query(sql, params) {
|
|
263
|
-
return { rows: (await this.
|
|
255
|
+
return { rows: (await (await this.getPool()).query(sql, params)).rows };
|
|
264
256
|
}
|
|
265
257
|
async leaseTransactionClient() {
|
|
266
|
-
const client = await this.
|
|
258
|
+
const client = await (await this.getPool()).connect();
|
|
267
259
|
this.activeLeaseCount += 1;
|
|
268
260
|
let released = false;
|
|
269
261
|
return {
|
|
@@ -278,7 +270,17 @@ var PostgresDBClientProvider = class {
|
|
|
278
270
|
}
|
|
279
271
|
async reset() {
|
|
280
272
|
if (this.activeLeaseCount > 0) throw new Error("Cannot reset Tango runtime while transaction leases are still active.");
|
|
281
|
-
|
|
273
|
+
if (!this.poolPromise) return;
|
|
274
|
+
const pool = await this.poolPromise;
|
|
275
|
+
this.poolPromise = null;
|
|
276
|
+
await pool.end();
|
|
277
|
+
}
|
|
278
|
+
async getPool() {
|
|
279
|
+
if (!this.poolPromise) this.poolPromise = this.createPool();
|
|
280
|
+
return this.poolPromise;
|
|
281
|
+
}
|
|
282
|
+
async createPool() {
|
|
283
|
+
return this.poolProvider.createPool(this.config);
|
|
282
284
|
}
|
|
283
285
|
};
|
|
284
286
|
//#endregion
|
|
@@ -497,4 +499,4 @@ async function resetTangoRuntime() {
|
|
|
497
499
|
//#endregion
|
|
498
500
|
export { RuntimeBoundClient as a, TangoRuntime as i, initializeTangoRuntime as n, TransactionEngine as o, resetTangoRuntime as r, getTangoRuntime as t };
|
|
499
501
|
|
|
500
|
-
//# sourceMappingURL=defaultRuntime-
|
|
502
|
+
//# sourceMappingURL=defaultRuntime-WIsxnh8K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultRuntime-WIsxnh8K.js","names":[],"sources":["../src/transaction/internal/context/FrameBoundTransaction.ts","../src/transaction/internal/context/AsyncLocalTransactionEngine.ts","../src/transaction/internal/context/TransactionEngine.ts","../src/manager/internal/RuntimeBoundClient.ts","../src/runtime/internal/PostgresDBClientProvider.ts","../src/runtime/internal/SqliteDBClientProvider.ts","../src/runtime/internal/createDBClientProvider.ts","../src/runtime/TangoRuntime.ts","../src/runtime/defaultRuntime.ts"],"sourcesContent":["import type { AtomicTransaction, OnCommitOptions, SavepointOptions, SavepointResult } from '../../AtomicTransaction';\nimport type { AsyncLocalTransactionEngine } from './AsyncLocalTransactionEngine';\nimport type { TransactionFrame } from './TransactionFrame';\nimport type { TransactionState } from './TransactionState';\n\nexport class FrameBoundTransaction implements AtomicTransaction {\n private active = true;\n\n constructor(\n private readonly engine: AsyncLocalTransactionEngine,\n private readonly state: TransactionState,\n private readonly frame: TransactionFrame\n ) {}\n\n onCommit(callback: () => void, options: OnCommitOptions = {}): void {\n if (!this.active) {\n throw new Error('Cannot register an on-commit callback on an inactive transaction frame.');\n }\n\n this.frame.callbacks.push({\n order: this.state.nextCallbackOrder++,\n callback,\n robust: options.robust ?? false,\n });\n }\n\n savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<SavepointResult<T>>;\n savepoint<T>(\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: { throwOnError: false }\n ): Promise<SavepointResult<T>>;\n savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: { throwOnError: true }): Promise<T>;\n async savepoint<T>(\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: SavepointOptions = {}\n ): Promise<T | SavepointResult<T>> {\n if (!this.active) {\n throw new Error('Cannot open a savepoint from an inactive transaction frame.');\n }\n\n return this.engine.runSavepoint(this.state, work, options);\n }\n\n deactivate(): void {\n this.active = false;\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { getLogger } from '@danceroutine/tango-core';\nimport type { TangoRuntime } from '../../../runtime/TangoRuntime';\nimport type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';\nimport type { AtomicTransaction, SavepointOptions, SavepointResult } from '../../AtomicTransaction';\nimport type { CallbackRecord } from './CallbackRecord';\nimport { FrameBoundTransaction } from './FrameBoundTransaction';\nimport type { TransactionFrame } from './TransactionFrame';\nimport type { TransactionState } from './TransactionState';\n\nexport class AsyncLocalTransactionEngine {\n private readonly logger = getLogger('tango.orm.transaction');\n private readonly storage = new AsyncLocalStorage<TransactionState>();\n\n assertNoActiveAtomicTransaction(): void {\n if (this.storage.getStore()) {\n throw new Error('UnitOfWork is unsupported inside transaction.atomic(...).');\n }\n }\n\n getActiveTransaction(runtime: TangoRuntime): AtomicTransaction | undefined {\n const state = this.storage.getStore();\n if (!state || state.runtime !== runtime) {\n return undefined;\n }\n\n return state.frames.at(-1)?.facade;\n }\n\n getActiveLease(runtime: TangoRuntime): TransactionClientLease | undefined {\n const state = this.storage.getStore();\n if (!state || state.runtime !== runtime) {\n return undefined;\n }\n\n return state.lease;\n }\n\n async atomic<T>(runtime: TangoRuntime, work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n const existing = this.storage.getStore();\n if (existing) {\n if (existing.runtime !== runtime) {\n throw new Error(\n 'Cannot open a transaction for one Tango runtime while another runtime transaction is active.'\n );\n }\n\n return this.runNested(existing, work);\n }\n\n const lease = await runtime.leaseTransactionClient();\n const state: TransactionState = {\n runtime,\n lease,\n frames: [],\n nextCallbackOrder: 0,\n nextSavepointId: 0,\n };\n\n try {\n return await this.storage.run(state, async () => {\n await lease.client.begin();\n const frame = this.pushFrame(state);\n\n try {\n const result = await work(frame.facade);\n await lease.client.commit();\n const root = this.popFrame(state);\n root.facade.deactivate();\n await this.runCommittedCallbacks(root.callbacks);\n return result;\n } catch (error) {\n await this.rollbackOuter(state, error);\n throw error;\n }\n });\n } finally {\n this.deactivateAllFrames(state);\n await lease.release();\n }\n }\n\n async runSavepoint<T>(\n state: TransactionState,\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: SavepointOptions\n ): Promise<T | SavepointResult<T>> {\n try {\n const value = await this.runNested(state, work);\n if (options.throwOnError) {\n return value;\n }\n\n return {\n ok: true,\n value,\n };\n } catch (error) {\n if (options.throwOnError) {\n throw error;\n }\n\n return {\n ok: false,\n error,\n };\n }\n }\n\n private async runNested<T>(state: TransactionState, work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n const savepointName = `tango_sp_${state.nextSavepointId++}`;\n await state.lease.client.createSavepoint(savepointName);\n const frame = this.pushFrame(state, savepointName);\n\n try {\n const result = await work(frame.facade);\n await state.lease.client.releaseSavepoint(savepointName);\n const completed = this.popFrame(state);\n completed.facade.deactivate();\n const parent = state.frames.at(-1);\n if (!parent) {\n throw new Error('Nested transaction frame completed without a parent frame.');\n }\n\n parent.callbacks.push(...completed.callbacks);\n parent.callbacks.sort((left, right) => left.order - right.order);\n return result;\n } catch (error) {\n try {\n await state.lease.client.rollbackToSavepoint(savepointName);\n } catch (rollbackError) {\n throw this.attachCause(rollbackError, error);\n } finally {\n const discarded = this.popFrame(state);\n discarded.facade.deactivate();\n }\n\n throw error;\n }\n }\n\n private pushFrame(state: TransactionState, savepointName?: string): TransactionFrame {\n const frame = {} as TransactionFrame;\n const facade = new FrameBoundTransaction(this, state, frame);\n frame.callbacks = [];\n frame.facade = facade;\n frame.savepointName = savepointName;\n state.frames.push(frame);\n return frame;\n }\n\n private popFrame(state: TransactionState): TransactionFrame {\n const frame = state.frames.pop();\n if (!frame) {\n throw new Error('Transaction frame stack underflow.');\n }\n\n return frame;\n }\n\n private async rollbackOuter(state: TransactionState, error: unknown): Promise<void> {\n try {\n await state.lease.client.rollback();\n } catch (rollbackError) {\n throw this.attachCause(rollbackError, error);\n } finally {\n while (state.frames.length > 0) {\n const frame = this.popFrame(state);\n frame.facade.deactivate();\n }\n }\n }\n\n private async runCommittedCallbacks(callbacks: readonly CallbackRecord[]): Promise<void> {\n for (const record of callbacks) {\n try {\n await record.callback();\n } catch (error) {\n if (!record.robust) {\n throw error;\n }\n\n try {\n this.logger.error('Post-commit callback failed.', error);\n } catch {\n // A logging backend failure cannot change the already-committed outcome.\n }\n }\n }\n }\n\n private deactivateAllFrames(state: TransactionState): void {\n state.frames.length = 0;\n }\n\n private attachCause(error: unknown, cause: unknown): unknown {\n if (!this.isErrorValue(error)) {\n return error;\n }\n\n if ('cause' in error && error.cause !== undefined) {\n return error;\n }\n\n try {\n return new Error(error.message, { cause });\n } catch {\n return error;\n }\n }\n\n private isErrorValue(value: unknown): value is Error {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { message?: unknown }).message === 'string' &&\n typeof (value as { name?: unknown }).name === 'string'\n );\n }\n}\n","import type { TangoRuntime } from '../../../runtime/TangoRuntime';\nimport type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';\nimport type { AtomicTransaction } from '../../AtomicTransaction';\nimport { AsyncLocalTransactionEngine } from './AsyncLocalTransactionEngine';\n\n/**\n * Runtime-bound transaction facade used by internal ORM/runtime components.\n */\nexport class TransactionEngine {\n private static readonly engine = new AsyncLocalTransactionEngine();\n\n private constructor(private readonly runtime: TangoRuntime) {}\n\n static forRuntime(runtime: TangoRuntime): TransactionEngine {\n return new TransactionEngine(runtime);\n }\n\n static assertNoActiveAtomicTransaction(): void {\n this.engine.assertNoActiveAtomicTransaction();\n }\n\n getActiveTransaction(): AtomicTransaction | undefined {\n return TransactionEngine.engine.getActiveTransaction(this.runtime);\n }\n\n getActiveLease(): TransactionClientLease | undefined {\n return TransactionEngine.engine.getActiveLease(this.runtime);\n }\n\n async atomic<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n return TransactionEngine.engine.atomic(this.runtime, work);\n }\n}\n","import type { DBClient } from '../../connection/index';\nimport type { TangoRuntime } from '../../runtime/index';\nimport { TransactionEngine } from '../../transaction/internal/context';\n\n/**\n * DB client proxy that resolves either the active transaction lease or the\n * runtime autocommit path lazily.\n */\nexport class RuntimeBoundClient implements DBClient {\n constructor(private readonly runtime: TangoRuntime) {}\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const lease = TransactionEngine.forRuntime(this.runtime).getActiveLease();\n if (lease) {\n return lease.client.query<T>(sql, params);\n }\n\n const runtimeWithQuery = this.runtime as TangoRuntime & {\n query?: <TResult = unknown>(sql: string, params?: readonly unknown[]) => Promise<{ rows: TResult[] }>;\n };\n if (typeof runtimeWithQuery.query === 'function') {\n return runtimeWithQuery.query<T>(sql, params);\n }\n\n const client = await this.runtime.getClient();\n return client.query<T>(sql, params);\n }\n\n async begin(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual begin(). Use transaction.atomic(...) instead.');\n }\n\n async commit(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual commit(). Use transaction.atomic(...) instead.');\n }\n\n async rollback(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual rollback(). Use transaction.atomic(...) instead.');\n }\n\n async createSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoints. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async releaseSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoint release. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async rollbackToSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoint rollback. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async close(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual close(). Use TangoRuntime.reset() instead.');\n }\n}\n","import type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport { PostgresClient } from '../../connection/clients/dialects/PostgresClient';\nimport { PostgresPoolProvider, type PostgresPoolLike } from '../../connection/clients/dialects/PostgresPoolProvider';\nimport type { DBClientProvider, TransactionClientLease } from './DBClientProvider';\n\nexport class PostgresDBClientProvider implements DBClientProvider {\n private readonly poolProvider = new PostgresPoolProvider();\n private poolPromise: Promise<PostgresPoolLike> | null = null;\n private activeLeaseCount = 0;\n\n constructor(private readonly config: AdapterConfig) {}\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const pool = await this.getPool();\n const result = await pool.query(sql, params);\n return { rows: result.rows as T[] };\n }\n\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n const pool = await this.getPool();\n const client = await pool.connect();\n this.activeLeaseCount += 1;\n let released = false;\n\n return {\n client: new PostgresClient(client),\n release: async () => {\n if (released) {\n return;\n }\n\n released = true;\n this.activeLeaseCount -= 1;\n client.release();\n },\n };\n }\n\n async reset(): Promise<void> {\n if (this.activeLeaseCount > 0) {\n throw new Error('Cannot reset Tango runtime while transaction leases are still active.');\n }\n\n if (!this.poolPromise) {\n return;\n }\n\n const pool = await this.poolPromise;\n this.poolPromise = null;\n await pool.end();\n }\n\n private async getPool(): Promise<PostgresPoolLike> {\n if (!this.poolPromise) {\n this.poolPromise = this.createPool();\n }\n\n return this.poolPromise;\n }\n\n private async createPool(): Promise<PostgresPoolLike> {\n return this.poolProvider.createPool(this.config);\n }\n}\n","import { createRequire } from 'node:module';\nimport type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport { SqliteClient } from '../../connection/clients/dialects/SqliteClient';\nimport type { SqliteDatabaseConstructor } from '../../connection/clients/dialects/SqliteDatabaseLike';\nimport type { DBClientProvider, TransactionClientLease } from './DBClientProvider';\n\nexport class SqliteDBClientProvider implements DBClientProvider {\n private readonly filename: string;\n private readonly Database: SqliteDatabaseConstructor;\n private readonly autocommitClient: SqliteClient;\n private activeLeaseCount = 0;\n private exclusiveTail: Promise<void> = Promise.resolve();\n\n constructor(config: AdapterConfig = {}) {\n this.Database = this.getDatabaseCtor();\n this.filename =\n typeof config.filename === 'string' && config.filename.length > 0 ? config.filename : ':memory:';\n this.autocommitClient = this.openClient(this.filename);\n }\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n return this.runExclusive(() => this.autocommitClient.query<T>(sql, params));\n }\n\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n if (this.filename === ':memory:') {\n throw new Error('transaction.atomic(...) requires a file-backed SQLite database. :memory: is unsupported.');\n }\n\n const releaseExclusive = await this.acquireExclusive();\n try {\n const client = this.openClient(this.filename);\n this.activeLeaseCount += 1;\n let released = false;\n\n return {\n client,\n release: async () => {\n if (released) {\n return;\n }\n\n released = true;\n this.activeLeaseCount -= 1;\n try {\n await client.close();\n } finally {\n releaseExclusive();\n }\n },\n };\n } catch (error) {\n releaseExclusive();\n throw error;\n }\n }\n\n async reset(): Promise<void> {\n if (this.activeLeaseCount > 0) {\n throw new Error('Cannot reset Tango runtime while transaction leases are still active.');\n }\n\n await this.autocommitClient.close();\n }\n\n private openClient(filename: string): SqliteClient {\n const db = new this.Database(filename);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('busy_timeout = 5000');\n return new SqliteClient(db);\n }\n\n private async runExclusive<T>(work: () => Promise<T>): Promise<T> {\n const release = await this.acquireExclusive();\n try {\n return await work();\n } finally {\n release();\n }\n }\n\n private async acquireExclusive(): Promise<() => void> {\n const previous = this.exclusiveTail;\n let release: (() => void) | null = null;\n this.exclusiveTail = new Promise<void>((resolve) => {\n release = resolve;\n });\n await previous;\n return () => {\n release?.();\n };\n }\n\n private getDatabaseCtor(): SqliteDatabaseConstructor {\n const require = createRequire(import.meta.url);\n const moduleValue = require('better-sqlite3') as unknown;\n if (typeof moduleValue === 'function') {\n return moduleValue as SqliteDatabaseConstructor;\n }\n\n const defaultExport = (moduleValue as { default?: unknown }).default;\n if (typeof defaultExport === 'function') {\n return defaultExport as SqliteDatabaseConstructor;\n }\n\n throw new TypeError('Failed to load better-sqlite3 constructor.');\n }\n}\n","import type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport type { DBClientProvider } from './DBClientProvider';\nimport { PostgresDBClientProvider } from './PostgresDBClientProvider';\nimport { SqliteDBClientProvider } from './SqliteDBClientProvider';\n\nexport function createDBClientProvider(config: AdapterConfig & { adapter: string }): DBClientProvider {\n switch (config.adapter) {\n case 'postgres':\n return new PostgresDBClientProvider(config);\n case 'sqlite':\n return new SqliteDBClientProvider(config);\n default:\n throw new Error(`Unsupported adapter for Tango runtime provider: ${config.adapter}`);\n }\n}\n","import type { LoadedConfig } from '@danceroutine/tango-config';\nimport type { DBClient } from '../connection/index';\nimport type { Adapter } from '../connection/adapters/Adapter';\nimport { PostgresAdapter } from '../connection/adapters/dialects/PostgresAdapter';\nimport { SqliteAdapter } from '../connection/adapters/dialects/SqliteAdapter';\nimport type { Dialect } from '../query/domain/index';\nimport { InternalDialect } from '../query/domain/internal/InternalDialect';\nimport { RuntimeBoundClient } from '../manager/internal/RuntimeBoundClient';\nimport type { DBClientProvider, TransactionClientLease } from './internal/DBClientProvider';\nimport { createDBClientProvider } from './internal/createDBClientProvider';\n\n/**\n * Framework-owned database runtime that resolves Tango config and lazily\n * creates the shared connection provider used by manager-backed models.\n */\nexport class TangoRuntime {\n static readonly BRAND = 'tango.orm.runtime' as const;\n readonly __tangoBrand: typeof TangoRuntime.BRAND = TangoRuntime.BRAND;\n private readonly loadedConfig: LoadedConfig;\n private providerPromise: Promise<DBClientProvider> | null = null;\n private runtimeClientPromise: Promise<DBClient> | null = null;\n private cachedAdapter: Adapter | null = null;\n\n constructor(loadLoadedConfig: () => LoadedConfig) {\n this.loadedConfig = loadLoadedConfig();\n }\n\n /**\n * Narrow an unknown value to `TangoRuntime`.\n */\n static isTangoRuntime(value: unknown): value is TangoRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === TangoRuntime.BRAND\n );\n }\n\n /**\n * Return the loaded Tango config snapshot for the active environment.\n */\n getConfig(): LoadedConfig {\n return this.loadedConfig;\n }\n\n /**\n * Return the configured SQL dialect for the current runtime.\n */\n getDialect(): Dialect {\n return this.loadedConfig.current.db.adapter;\n }\n\n /**\n * Return the adapter backing the configured dialect. Manager-side\n * compilers use this to obtain placeholder formatters and dialect\n * capabilities without branching on the raw dialect string.\n */\n getAdapter(): Adapter {\n if (!this.cachedAdapter) {\n this.cachedAdapter = this.buildAdapterForDialect(this.getDialect());\n }\n return this.cachedAdapter;\n }\n\n /**\n * Return the runtime-bound DB client facade used by manager-backed code.\n */\n async getClient(): Promise<DBClient> {\n if (!this.runtimeClientPromise) {\n this.runtimeClientPromise = Promise.resolve(new RuntimeBoundClient(this));\n }\n\n return this.runtimeClientPromise;\n }\n\n /**\n * Execute SQL through the autocommit path owned by this runtime.\n */\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const provider = await this.getProvider();\n return provider.query<T>(sql, params);\n }\n\n /**\n * Lease a transaction-scoped client for `transaction.atomic(...)`.\n */\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n const provider = await this.getProvider();\n return provider.leaseTransactionClient();\n }\n\n /**\n * Close and clear the cached runtime resources so tests can start fresh.\n */\n async reset(): Promise<void> {\n if (!this.providerPromise) {\n this.runtimeClientPromise = null;\n return;\n }\n\n const provider = await this.providerPromise;\n this.providerPromise = null;\n this.runtimeClientPromise = null;\n await provider.reset();\n }\n\n private buildAdapterForDialect(dialect: Dialect): Adapter {\n switch (dialect) {\n case InternalDialect.POSTGRES:\n return new PostgresAdapter();\n case InternalDialect.SQLITE:\n return new SqliteAdapter();\n }\n }\n\n private async getProvider(): Promise<DBClientProvider> {\n if (!this.providerPromise) {\n const db = this.loadedConfig.current.db;\n this.providerPromise = Promise.resolve(\n createDBClientProvider({\n adapter: db.adapter,\n url: db.url,\n host: db.host,\n port: db.port,\n database: db.database,\n user: db.user,\n password: db.password,\n filename: db.filename,\n maxConnections: db.maxConnections,\n })\n );\n }\n\n return this.providerPromise;\n }\n}\n","import { loadConfig, loadConfigFromProjectRoot } from '@danceroutine/tango-config';\nimport { TangoRuntime } from './TangoRuntime';\n\nlet defaultRuntime: TangoRuntime | null = null;\n\n/**\n * Initialize the process-default Tango runtime from a Tango config loader.\n */\nexport function initializeTangoRuntime(fromFile: () => unknown): TangoRuntime {\n defaultRuntime = new TangoRuntime(() => loadConfig(fromFile));\n return defaultRuntime;\n}\n\n/**\n * Return the process-default Tango runtime, lazily loading Tango config on first access.\n */\nexport function getTangoRuntime(): TangoRuntime {\n if (!defaultRuntime) {\n defaultRuntime = new TangoRuntime(() => loadConfigFromProjectRoot());\n }\n\n return defaultRuntime;\n}\n\n/**\n * Reset the process-default Tango runtime and release any cached client.\n */\nexport async function resetTangoRuntime(): Promise<void> {\n if (!defaultRuntime) {\n return;\n }\n\n const runtime = defaultRuntime;\n defaultRuntime = null;\n await runtime.reset();\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { t as DBClient } from "./DBClient-DuYcXolQ.js";
|
|
2
2
|
import { n as AdapterConfig, r as SqlPlaceholders, t as Adapter } from "./Adapter-DKxAaL4l.js";
|
|
3
|
-
import Database from "better-sqlite3";
|
|
4
3
|
|
|
5
4
|
//#region src/connection/adapters/dialects/PostgresAdapter.d.ts
|
|
6
5
|
/**
|
|
@@ -22,6 +21,7 @@ declare class PostgresAdapter implements Adapter {
|
|
|
22
21
|
*/
|
|
23
22
|
readonly features: Adapter['features'];
|
|
24
23
|
readonly placeholders: SqlPlaceholders;
|
|
24
|
+
private readonly poolProvider;
|
|
25
25
|
/**
|
|
26
26
|
* Narrow an unknown value to `PostgresAdapter`.
|
|
27
27
|
*/
|
|
@@ -159,6 +159,18 @@ declare class PostgresClient implements DBClient {
|
|
|
159
159
|
close(): Promise<void>;
|
|
160
160
|
}
|
|
161
161
|
//#endregion
|
|
162
|
+
//#region src/connection/clients/dialects/SqliteDatabaseLike.d.ts
|
|
163
|
+
type SqliteStatementLike = {
|
|
164
|
+
readonly reader: boolean;
|
|
165
|
+
all(...params: unknown[]): unknown[];
|
|
166
|
+
run(...params: unknown[]): unknown;
|
|
167
|
+
};
|
|
168
|
+
type SqliteDatabaseLike = {
|
|
169
|
+
prepare(sql: string): SqliteStatementLike;
|
|
170
|
+
pragma(sql: string): unknown;
|
|
171
|
+
close(): void;
|
|
172
|
+
};
|
|
173
|
+
//#endregion
|
|
162
174
|
//#region src/connection/clients/dialects/SqliteClient.d.ts
|
|
163
175
|
/**
|
|
164
176
|
* Transaction-capable client backed by a synchronous `better-sqlite3` handle.
|
|
@@ -168,7 +180,7 @@ declare class SqliteClient implements DBClient {
|
|
|
168
180
|
static readonly BRAND: "tango.orm.sqlite_client";
|
|
169
181
|
readonly __tangoBrand: typeof SqliteClient.BRAND;
|
|
170
182
|
private inTransaction;
|
|
171
|
-
constructor(db:
|
|
183
|
+
constructor(db: SqliteDatabaseLike);
|
|
172
184
|
/**
|
|
173
185
|
* Narrow an unknown value to `SqliteClient`.
|
|
174
186
|
*/
|
|
@@ -223,4 +235,4 @@ declare namespace index_d_exports {
|
|
|
223
235
|
}
|
|
224
236
|
//#endregion
|
|
225
237
|
export { index_d_exports$3 as a, getDefaultAdapterRegistry as c, PostgresClient as i, SqliteAdapter as l, index_d_exports$1 as n, AdapterRegistry as o, SqliteClient as r, connectDB as s, index_d_exports as t, PostgresAdapter as u };
|
|
226
|
-
//# sourceMappingURL=index-
|
|
238
|
+
//# sourceMappingURL=index-o2LFpJ8S.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as DBClient } from "./DBClient-DuYcXolQ.js";
|
|
2
2
|
import { i as Dialect, n as AdapterConfig, t as Adapter } from "./Adapter-DKxAaL4l.js";
|
|
3
|
-
import { c as getDefaultAdapterRegistry, l as SqliteAdapter, o as AdapterRegistry, s as connectDB, t as index_d_exports, u as PostgresAdapter } from "./index-
|
|
3
|
+
import { c as getDefaultAdapterRegistry, l as SqliteAdapter, o as AdapterRegistry, s as connectDB, t as index_d_exports, u as PostgresAdapter } from "./index-o2LFpJ8S.js";
|
|
4
4
|
import { A as QBuilder, E as ManyToManyRelatedManager, F as QNode, H as TableMeta, I as FilterInput, L as FilterValue, M as QueryExecutor, N as QuerySet, O as ManyToManyTargetRef, P as OrderToken, R as FilterKey, U as QueryResult, V as QueryCompiler, c as RelationMeta, i as WhereClause, j as ModelQuerySet, k as index_d_exports$2, n as OrderSpec, o as Direction, s as CompiledQuery, t as QuerySetState, z as LookupType } from "./QuerySetState-CjyvAUBs.js";
|
|
5
5
|
import { t as index_d_exports$1 } from "./index-D9B6gKez.js";
|
|
6
6
|
import { a as MaterializedModelRecord, i as ManagerLike, n as ModelManager, r as TangoRuntime } from "./registerModelObjects-C-MliIiM.js";
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { i as PostgresAdapter, t as SqliteAdapter } from "./SqliteAdapter-
|
|
2
|
-
import { a as connectDB, i as AdapterRegistry, o as getDefaultAdapterRegistry, t as connection_exports } from "./connection-
|
|
1
|
+
import { i as PostgresAdapter, t as SqliteAdapter } from "./SqliteAdapter-CrUhpTDb.js";
|
|
2
|
+
import { a as connectDB, i as AdapterRegistry, o as getDefaultAdapterRegistry, t as connection_exports } from "./connection-B2cDwZ72.js";
|
|
3
3
|
import { d as QueryCompiler, i as QBuilder, l as QueryResult, n as ModelQuerySet, r as QuerySet, t as query_exports } from "./query-CP1UMIX6.js";
|
|
4
|
-
import { n as ModelManager, r as ManyToManyRelatedManager } from "./registerModelObjects-
|
|
5
|
-
import { t as manager_exports } from "./manager-
|
|
6
|
-
import { i as TangoRuntime, n as initializeTangoRuntime, r as resetTangoRuntime, t as getTangoRuntime } from "./defaultRuntime-
|
|
4
|
+
import { n as ModelManager, r as ManyToManyRelatedManager } from "./registerModelObjects-CGjjOzd9.js";
|
|
5
|
+
import { t as manager_exports } from "./manager-DRra01q8.js";
|
|
6
|
+
import { i as TangoRuntime, n as initializeTangoRuntime, r as resetTangoRuntime, t as getTangoRuntime } from "./defaultRuntime-WIsxnh8K.js";
|
|
7
7
|
import { t as runtime_exports } from "./runtime/index.js";
|
|
8
|
-
import { n as UnitOfWork, r as atomic, t as transaction_exports } from "./transaction-
|
|
8
|
+
import { n as UnitOfWork, r as atomic, t as transaction_exports } from "./transaction-DpDXQq5V.js";
|
|
9
9
|
export { AdapterRegistry, ManyToManyRelatedManager, ModelManager, ModelQuerySet, PostgresAdapter, QBuilder as Q, QBuilder, QueryCompiler, QueryResult, QuerySet, SqliteAdapter, TangoRuntime, UnitOfWork, atomic, connectDB, connection_exports as connection, getDefaultAdapterRegistry, getTangoRuntime, initializeTangoRuntime, manager_exports as manager, query_exports as query, resetTangoRuntime, runtime_exports as runtime, transaction_exports as transaction };
|
package/dist/manager/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { i as ManyToManyRelatedQuerySet, n as ModelManager, r as ManyToManyRelatedManager, t as registerModelObjects } from "../registerModelObjects-
|
|
2
|
-
import { n as relations_exports } from "../manager-
|
|
1
|
+
import { i as ManyToManyRelatedQuerySet, n as ModelManager, r as ManyToManyRelatedManager, t as registerModelObjects } from "../registerModelObjects-CGjjOzd9.js";
|
|
2
|
+
import { n as relations_exports } from "../manager-DRra01q8.js";
|
|
3
3
|
export { ManyToManyRelatedManager, ManyToManyRelatedQuerySet, ModelManager, registerModelObjects, relations_exports as relations };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-8H4AJuhK.js";
|
|
2
|
-
import { i as ManyToManyRelatedQuerySet, n as ModelManager, r as ManyToManyRelatedManager, t as registerModelObjects } from "./registerModelObjects-
|
|
2
|
+
import { i as ManyToManyRelatedQuerySet, n as ModelManager, r as ManyToManyRelatedManager, t as registerModelObjects } from "./registerModelObjects-CGjjOzd9.js";
|
|
3
3
|
//#region src/manager/relations/index.ts
|
|
4
4
|
var relations_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
ManyToManyRelatedManager: () => ManyToManyRelatedManager,
|
|
@@ -17,4 +17,4 @@ var manager_exports = /* @__PURE__ */ __exportAll({
|
|
|
17
17
|
//#endregion
|
|
18
18
|
export { relations_exports as n, manager_exports as t };
|
|
19
19
|
|
|
20
|
-
//# sourceMappingURL=manager-
|
|
20
|
+
//# sourceMappingURL=manager-DRra01q8.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager-
|
|
1
|
+
{"version":3,"file":"manager-DRra01q8.js","names":[],"sources":["../src/manager/relations/index.ts","../src/manager/index.ts"],"sourcesContent":["/**\n * Domain boundary barrel: centralizes ORM relation managers attached to\n * materialized model records.\n */\n\nexport { ManyToManyRelatedQuerySet } from './ManyToManyRelatedQuerySet';\nexport type { ManyToManyRelatedQuerySetBridge } from './ManyToManyRelatedQuerySet';\nexport { ManyToManyRelatedManager } from './ManyToManyRelatedManager';\nexport type { ManyToManyRelatedManagerCreateInputs, ManyToManyTargetRef } from './ManyToManyRelatedManager';\nexport type { MaterializedModelRecord } from './MaterializedModelRecord';\n","/**\n * Domain boundary barrel: centralizes manager-first ORM APIs.\n */\nexport * as relations from './relations/index';\n\nexport type { ManagerLike } from './ManagerLike';\nexport { ModelManager } from './ModelManager';\nexport { registerModelObjects } from './registerModelObjects';\nexport { ManyToManyRelatedQuerySet } from './relations/ManyToManyRelatedQuerySet';\nexport type { ManyToManyRelatedQuerySetBridge } from './relations/ManyToManyRelatedQuerySet';\nexport { ManyToManyRelatedManager } from './relations/ManyToManyRelatedManager';\nexport type { ManyToManyRelatedManagerCreateInputs, ManyToManyTargetRef } from './relations/ManyToManyRelatedManager';\nexport type { MaterializedModelRecord } from './relations/MaterializedModelRecord';\n"],"mappings":""}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as isQNodeLike, c as InternalRelationKind, f as OrmSqlSafetyAdapter, i as QBuilder, l as QueryResult, m as InternalQNodeType, n as ModelQuerySet, p as InternalSqlValidationPlanKind, r as QuerySet, s as TableMetaFactory } from "./query-CP1UMIX6.js";
|
|
2
|
-
import { a as RuntimeBoundClient, o as TransactionEngine, t as getTangoRuntime } from "./defaultRuntime-
|
|
2
|
+
import { a as RuntimeBoundClient, o as TransactionEngine, t as getTangoRuntime } from "./defaultRuntime-WIsxnh8K.js";
|
|
3
3
|
import { NotFoundError } from "@danceroutine/tango-core";
|
|
4
4
|
import { ModelRegistry, registerModelAugmentor } from "@danceroutine/tango-schema";
|
|
5
5
|
//#region src/manager/relations/ManyToManyRelatedQuerySet.ts
|
|
@@ -969,4 +969,4 @@ function registerModelObjects() {
|
|
|
969
969
|
//#endregion
|
|
970
970
|
export { ManyToManyRelatedQuerySet as i, ModelManager as n, ManyToManyRelatedManager as r, registerModelObjects as t };
|
|
971
971
|
|
|
972
|
-
//# sourceMappingURL=registerModelObjects-
|
|
972
|
+
//# sourceMappingURL=registerModelObjects-CGjjOzd9.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerModelObjects-DZfZ20fa.js","names":["QueryResultClass","Q","SqlPlanKind","SqlPlanKind","atom"],"sources":["../src/manager/relations/ManyToManyRelatedQuerySet.ts","../src/manager/internal/MutationCompiler.ts","../src/manager/relations/internal/ThroughTableManager.ts","../src/manager/relations/ManyToManyRelatedManager.ts","../src/manager/ModelManager.ts","../src/manager/registerModelObjects.ts"],"sourcesContent":["/*\n * Maintainer note: This subclass exists rather than a plain `QuerySet` so\n * that the related-manager can thread a prefetch-cache short-circuit and a\n * two-phase fetch through the join table without dragging many-to-many\n * knowledge into the base `QuerySet`.\n *\n * 1. Prefetch-cache short-circuit. When `prefetchRelated(...)` loads the\n * relation ahead of time, the manager primes a cache that the first\n * `fetch()` resolves with directly. Mutations via `add`/`remove`\n * invalidate it.\n * 2. Two-phase fetch through the join table. On cache miss (or once the\n * caller adds chainable state), the queryset asks the bridge for the\n * linked target primary keys and then runs a vanilla target-table query\n * scoped by `pk__in = [...]`. This keeps the compiled SQL identical to\n * what a direct `TargetModel.objects.query()` would produce and avoids\n * joining the through table into the projection.\n * 3. Chain preservation. Fluent queryset methods reuse the same\n * subclass-preserving `spawn(...)` path as the rest of the ORM surface,\n * so chains like `post.tags.all().select(['id']).orderBy('name').fetch()`\n * keep the owner scoping and cache semantics instead of falling back to\n * the model-backed queryset family.\n */\nimport type { QueryResult } from '../../query/domain/QueryResult';\nimport type { QuerySetState } from '../../query/domain/QuerySetState';\nimport type { FilterInput } from '../../query/domain/FilterInput';\nimport type { QNode } from '../../query/domain/QNode';\nimport type { QueryExecutor } from '../../query/index';\nimport { ModelQuerySet, QueryResult as QueryResultClass } from '../../query/index';\nimport { QuerySet } from '../../query/index';\nimport { InternalQNodeType } from '../../query/domain/internal/InternalQNodeType';\nimport { QBuilder as Q } from '../../query/QBuilder';\n\n/**\n * Hooks supplied by {@link ManyToManyRelatedManager} so the queryset returned\n * from `all()` can short-circuit to the prefetch cache, scope the SQL query\n * to the owner via the join table, and filter targets by the resolved primary\n * keys.\n *\n * Application code does not construct this bridge directly; it is wired by\n * the related manager when `all()` is called.\n */\nexport interface ManyToManyRelatedQuerySetBridge<TTarget extends Record<string, unknown>> {\n getCache(): readonly TTarget[] | null;\n fetchTargetIds(): Promise<readonly (string | number)[]>;\n targetPrimaryKeyField: string;\n}\n\ntype ShapeFunction<TInput, Out> = (row: TInput) => Out;\ntype ShapeParser<TInput, Out> = { parse: (row: TInput) => Out };\ntype Shape<TInput, Out> = ShapeFunction<TInput, Out> | ShapeParser<TInput, Out>;\n\nfunction applyShape<TInput, Out>(rows: readonly TInput[], shape: Shape<TInput, Out>): Out[] {\n return typeof shape === 'function' ? rows.map(shape) : rows.map((row) => shape.parse(row));\n}\n\n/**\n * {@link QuerySet} returned by `post.tags.all()` on a many-to-many related\n * manager.\n *\n * Behaves like a normal `QuerySet` over the target model from an application\n * developer's perspective: you can chain `filter`, `exclude`, `orderBy`,\n * `limit`, `offset`, and terminate with `fetch`, `fetchOne`, or `count`.\n * Each chainable call returns another `ManyToManyRelatedQuerySet` so the\n * chain keeps the membership scoping of the owning record.\n *\n * Two behaviors differ from a plain `QuerySet` and matter to application\n * developers:\n *\n * - When the relation was loaded by `prefetchRelated(...)` and no chainable\n * state has been added (no `filter`, `orderBy`, etc.), `fetch()` and\n * `count()` resolve from the prefetch cache without issuing SQL.\n * - Mutating the membership via `post.tags.add(tag)` or\n * `post.tags.remove(tag)` invalidates that cache so follow-up reads go\n * back to the database.\n *\n * @example\n * ```ts\n * const post = await PostModel.objects.getOrThrow(postId);\n * await post.tags.add(tag);\n * const tags = await post.tags.all().filter({ color: 'red' }).orderBy('name').fetch();\n * ```\n *\n * @template TTarget - The persisted target record shape (e.g. `Tag`).\n */\nexport class ManyToManyRelatedQuerySet<TTarget extends Record<string, unknown>> extends QuerySet<TTarget> {\n constructor(\n executor: QueryExecutor<TTarget>,\n private readonly bridge: ManyToManyRelatedQuerySetBridge<TTarget>,\n state: QuerySetState<TTarget> = {}\n ) {\n super(executor, state);\n }\n\n override async fetch<Out>(\n shape?: ShapeFunction<TTarget, Out> | ShapeParser<TTarget, Out>\n ): Promise<QueryResult<TTarget | Out>> {\n if (this.isStateTrivial()) {\n const cache = this.bridge.getCache();\n if (cache !== null) {\n const results: Array<TTarget | Out> = shape ? applyShape(cache, shape) : [...cache];\n return new QueryResultClass(results);\n }\n }\n const ids = await this.bridge.fetchTargetIds();\n if (ids.length === 0) {\n return new QueryResultClass([]);\n }\n const scopedQs = new ModelQuerySet<TTarget>(this.executor, this.scopedState(ids));\n return shape ? scopedQs.fetch(shape) : scopedQs.fetch();\n }\n\n override async fetchOne<Out>(\n shape?: ShapeFunction<TTarget, Out> | ShapeParser<TTarget, Out>\n ): Promise<TTarget | Out | null> {\n const result = shape ? await this.fetch(shape) : await this.fetch();\n return (result.items[0] as TTarget | Out | undefined) ?? null;\n }\n\n override async count(): Promise<number> {\n if (this.isStateTrivial()) {\n const cache = this.bridge.getCache();\n if (cache !== null) {\n return cache.length;\n }\n }\n const ids = await this.bridge.fetchTargetIds();\n if (ids.length === 0) {\n return 0;\n }\n if (this.isStateTrivial()) {\n return ids.length;\n }\n const scopedQs = new ModelQuerySet<TTarget>(this.executor, this.scopedState(ids));\n return scopedQs.count();\n }\n\n protected override spawn<\n TNextBaseResult extends Record<string, unknown>,\n TNextHydrated extends Record<string, unknown>,\n >(state: QuerySetState<TTarget>): QuerySet<TTarget, TNextBaseResult, unknown, TNextHydrated> {\n return new ManyToManyRelatedQuerySet<TTarget>(this.executor, this.bridge, state) as QuerySet<\n TTarget,\n TNextBaseResult,\n unknown,\n TNextHydrated\n >;\n }\n\n private isStateTrivial(): boolean {\n return Object.keys(this.state).length === 0;\n }\n\n private scopedState(ids: readonly (string | number)[]): QuerySetState<TTarget> {\n const inFilter: FilterInput<TTarget> = {\n [`${this.bridge.targetPrimaryKeyField}__in`]: [...ids],\n } as FilterInput<TTarget>;\n const inAtom: QNode<TTarget> = { kind: InternalQNodeType.ATOM, where: inFilter };\n const merged = this.state.q ? Q.and(inAtom, this.state.q) : inAtom;\n return { ...this.state, q: merged };\n }\n}\n","import type { CompiledQuery } from '../../query/domain/index';\nimport type { Adapter, SqlPlaceholders } from '../../connection/adapters/Adapter';\nimport type {\n ValidatedDeleteSqlPlan,\n ValidatedInsertSqlPlan,\n ValidatedSelectSqlPlan,\n ValidatedUpdateSqlPlan,\n} from '../../validation/SQLValidationEngine';\n\nexport const InternalDuplicateInsertPolicy = {\n ERROR: 'error',\n IGNORE: 'ignore',\n} as const;\n\nexport type DuplicateInsertPolicy = (typeof InternalDuplicateInsertPolicy)[keyof typeof InternalDuplicateInsertPolicy];\n\n/**\n * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.\n */\nexport class MutationCompiler {\n private readonly adapter: Adapter;\n private readonly placeholders: SqlPlaceholders;\n\n constructor(adapter: Adapter) {\n this.adapter = adapter;\n this.placeholders = adapter.placeholders;\n }\n\n compileInsert(plan: ValidatedInsertSqlPlan, values: readonly unknown[]): CompiledQuery {\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES (${this.placeholders.list(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.placeholders.at(index + 1)}`).join(', ');\n const whereParam = this.placeholders.at(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.placeholders.at(1)}`,\n params: [id],\n };\n }\n\n compileDeleteByJoinKeys(\n plan: ValidatedSelectSqlPlan,\n leftFilterKey: string,\n rightFilterKey: string,\n leftValue: unknown,\n rightValue: unknown\n ): CompiledQuery {\n const leftDescriptor = plan.filterKeys[leftFilterKey];\n const rightDescriptor = plan.filterKeys[rightFilterKey];\n if (!leftDescriptor || !rightDescriptor) {\n throw new Error(\n `MutationCompiler.compileDeleteByJoinKeys: filter keys '${leftFilterKey}' and '${rightFilterKey}' must be present on the validated plan.`\n );\n }\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} = ${this.placeholders.at(2)}`,\n params: [leftValue, rightValue],\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) => `(${this.placeholders.listFromOffset(columnCount, rowIndex * columnCount)})`)\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 compileInsertJoinLinks(\n plan: ValidatedInsertSqlPlan,\n sourceKey: string,\n targetKey: string,\n ownerValue: unknown,\n targetValues: readonly unknown[],\n duplicatePolicy: DuplicateInsertPolicy\n ): CompiledQuery {\n const valueRows = targetValues.map((targetValue) => [ownerValue, targetValue]);\n const placeholders = valueRows\n .map((_row, rowIndex) => `(${this.placeholders.listFromOffset(2, rowIndex * 2)})`)\n .join(', ');\n const params = valueRows.flat();\n\n if (duplicatePolicy === InternalDuplicateInsertPolicy.IGNORE) {\n switch (this.adapter.dialect) {\n case 'postgres':\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders} ON CONFLICT (${sourceKey}, ${targetKey}) DO NOTHING`,\n params,\n };\n case 'sqlite':\n return {\n sql: `INSERT OR IGNORE INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders}`,\n params,\n };\n }\n }\n\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders}`,\n params,\n };\n }\n\n compileDeleteJoinLinks(\n plan: ValidatedSelectSqlPlan,\n leftFilterKey: string,\n rightFilterKey: string,\n leftValue: unknown,\n rightValues: readonly unknown[]\n ): CompiledQuery {\n const leftDescriptor = plan.filterKeys[leftFilterKey];\n const rightDescriptor = plan.filterKeys[rightFilterKey];\n if (!leftDescriptor || !rightDescriptor) {\n throw new Error(\n `MutationCompiler.compileDeleteJoinLinks: filter keys '${leftFilterKey}' and '${rightFilterKey}' must be present on the validated plan.`\n );\n }\n if (rightValues.length === 0) {\n throw new Error('MutationCompiler.compileDeleteJoinLinks requires at least one target value.');\n }\n if (rightValues.length === 1) {\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} = ${this.placeholders.at(2)}`,\n params: [leftValue, rightValues[0]],\n };\n }\n\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} IN (${this.placeholders.listFromOffset(rightValues.length, 1)})`,\n params: [leftValue, ...rightValues],\n };\n }\n}\n","import type { DBClient } from '../../../connection/clients/DBClient';\nimport type { TableMeta } from '../../../query/domain/index';\nimport type { Adapter } from '../../../connection/adapters/Adapter';\nimport { OrmSqlSafetyAdapter } from '../../../validation/OrmSqlSafetyAdapter';\nimport { InternalSqlValidationPlanKind as SqlPlanKind } from '../../../validation/internal/InternalSqlValidationPlanKind';\nimport {\n InternalDuplicateInsertPolicy,\n MutationCompiler,\n type DuplicateInsertPolicy,\n} from '../../internal/MutationCompiler';\n\n/**\n * Resolved through-table descriptor used by {@link ThroughTableManager}. The\n * descriptor is derived once from a relation edge plus its through-model\n * metadata, then reused for every link insert, delete, and read.\n */\nexport interface ThroughTableLinkDescriptor {\n /** Physical join-table name validated against SQL identifier safety rules. */\n table: string;\n /** Primary-key column name on the join table. */\n primaryKey: string;\n /** Full column map for the join table, used by the SQL safety adapter. */\n columns: Record<string, string>;\n /** Join-table column that stores the owner-side primary-key value. */\n sourceColumn: string;\n /** Join-table column that stores the target-side primary-key value. */\n targetColumn: string;\n}\n\n/**\n * Inputs accepted by {@link ThroughTableManager.fromRelation}.\n */\nexport interface ThroughTableManagerFromRelationInputs {\n relation: NonNullable<TableMeta['relations']>[string];\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>;\n client: DBClient;\n mutationCompiler: MutationCompiler;\n adapter: Adapter;\n sqlSafetyAdapter: OrmSqlSafetyAdapter;\n}\n\nexport interface InsertLinkOptions {\n onDuplicate?: DuplicateInsertPolicy;\n}\n\n/**\n * Internal helper that issues the INSERT, DELETE, and SELECT statements for\n * a single many-to-many join table. Centralizes SQL safety validation and\n * compilation so {@link ManyToManyRelatedManager} implementations only deal\n * in primary-key values.\n */\nexport class ThroughTableManager {\n constructor(\n private readonly client: DBClient,\n private readonly mutationCompiler: MutationCompiler,\n private readonly descriptor: ThroughTableLinkDescriptor,\n private readonly adapter: Adapter,\n private readonly sqlSafetyAdapter: OrmSqlSafetyAdapter = new OrmSqlSafetyAdapter()\n ) {}\n\n /**\n * Derive a {@link ThroughTableLinkDescriptor} from the through-model\n * metadata exposed by a many-to-many relation edge.\n */\n static buildLinkDescriptor(\n relation: NonNullable<TableMeta['relations']>[string],\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>\n ): ThroughTableLinkDescriptor {\n if (!relation.throughTable || !relation.throughSourceKey || !relation.throughTargetKey) {\n throw new Error(\n 'Cannot derive a through-table descriptor from a relation that is not a persisted many-to-many edge.'\n );\n }\n\n const primaryKeyField = throughModelFields.find((field) => field.primaryKey);\n if (!primaryKeyField) {\n throw new Error('Through-model metadata is missing a primary-key field.');\n }\n\n return {\n table: relation.throughTable,\n primaryKey: primaryKeyField.name,\n columns: Object.fromEntries(throughModelFields.map((field) => [field.name, field.type])),\n sourceColumn: relation.throughSourceKey,\n targetColumn: relation.throughTargetKey,\n };\n }\n\n /**\n * Convenience factory that derives the join-table descriptor from the\n * relation edge and instantiates a {@link ThroughTableManager} in one\n * step.\n */\n static fromRelation(inputs: ThroughTableManagerFromRelationInputs): ThroughTableManager {\n return new ThroughTableManager(\n inputs.client,\n inputs.mutationCompiler,\n ThroughTableManager.buildLinkDescriptor(inputs.relation, inputs.throughModelFields),\n inputs.adapter,\n inputs.sqlSafetyAdapter\n );\n }\n\n /**\n * Read every target primary-key value linked to the supplied owner via\n * the join table. Used by ManyToManyRelatedManager.all to scope\n * follow-up target queries to the current owner.\n */\n async selectTargetIdsForOwner(ownerPrimaryKey: unknown): Promise<readonly (string | number)[]> {\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const sourceColumn = validated.filterKeys[this.descriptor.sourceColumn]!.field;\n const targetColumn = validated.filterKeys[this.descriptor.targetColumn]!.field;\n const placeholder = this.adapter.placeholders.at(1);\n const sql = `SELECT ${targetColumn} AS target_id FROM ${validated.meta.table} WHERE ${sourceColumn} = ${placeholder}`;\n const result = await this.client.query<{ target_id: string | number }>(sql, [ownerPrimaryKey]);\n return result.rows\n .map((row) => row.target_id)\n .filter((value): value is string | number => typeof value === 'string' || typeof value === 'number');\n }\n\n async insertLink(\n ownerPrimaryKey: unknown,\n targetPrimaryKey: unknown,\n options: InsertLinkOptions = {}\n ): Promise<void> {\n await this.insertLinks(ownerPrimaryKey, [targetPrimaryKey], options);\n }\n\n async insertLinks(\n ownerPrimaryKey: unknown,\n targetPrimaryKeys: readonly unknown[],\n options: InsertLinkOptions = {}\n ): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n const validatedPlan = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.INSERT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n writeKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const duplicatePolicy = options.onDuplicate ?? InternalDuplicateInsertPolicy.ERROR;\n if (duplicatePolicy === InternalDuplicateInsertPolicy.IGNORE && !this.adapter.features.ignoreDuplicateInsert) {\n throw new Error(\n `Adapter '${this.adapter.name}' does not support duplicate-safe link insertion for many-to-many writes.`\n );\n }\n const compiled = this.mutationCompiler.compileInsertJoinLinks(\n validatedPlan,\n this.descriptor.sourceColumn,\n this.descriptor.targetColumn,\n ownerPrimaryKey,\n targetPrimaryKeys,\n duplicatePolicy\n );\n await this.client.query(compiled.sql, compiled.params);\n }\n\n async deleteLink(ownerPrimaryKey: unknown, targetPrimaryKey: unknown): Promise<void> {\n await this.deleteLinks(ownerPrimaryKey, [targetPrimaryKey]);\n }\n\n async deleteLinks(ownerPrimaryKey: unknown, targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const compiled = this.mutationCompiler.compileDeleteJoinLinks(\n validated,\n this.descriptor.sourceColumn,\n this.descriptor.targetColumn,\n ownerPrimaryKey,\n targetPrimaryKeys\n );\n await this.client.query(compiled.sql, compiled.params);\n }\n\n /**\n * Delete every join-table row linked to one owner record. Used by\n * `ManyToManyRelatedManager.clear()` so the related manager can clear a\n * relation without first loading the current target ids.\n */\n async deleteAllLinksForOwner(ownerPrimaryKey: unknown): Promise<void> {\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn],\n });\n const sourceColumn = validated.filterKeys[this.descriptor.sourceColumn]!.field;\n const placeholder = this.adapter.placeholders.at(1);\n const sql = `DELETE FROM ${validated.meta.table} WHERE ${sourceColumn} = ${placeholder}`;\n await this.client.query(sql, [ownerPrimaryKey]);\n }\n}\n","import type { DBClient } from '../../connection/clients/DBClient';\nimport type { TableMeta } from '../../query/domain/index';\nimport type { Adapter } from '../../connection/adapters/Adapter';\nimport type { QueryExecutor, QuerySet } from '../../query/index';\nimport type { OrmSqlSafetyAdapter } from '../../validation/OrmSqlSafetyAdapter';\nimport type { MutationCompiler } from '../internal/MutationCompiler';\nimport { InternalDuplicateInsertPolicy } from '../internal/MutationCompiler';\nimport { ManyToManyRelatedQuerySet } from './ManyToManyRelatedQuerySet';\nimport { ThroughTableManager } from './internal/ThroughTableManager';\n\n/**\n * Accepted target reference shapes for {@link ManyToManyRelatedManager.add},\n * {@link ManyToManyRelatedManager.remove}, and\n * {@link ManyToManyRelatedManager.set}.\n *\n * Application code may pass a target record, a primary-key carrier object, or\n * a bare primary-key value.\n *\n * @template TTarget - The persisted target record shape.\n */\nexport type ManyToManyTargetRef<TTarget extends Record<string, unknown>> =\n | TTarget\n | { readonly [pk: string]: unknown }\n | string\n | number;\n\n/**\n * Inputs accepted by the {@link ManyToManyRelatedManager.create} factory. The\n * factory owns the wiring between relation metadata, the SQL safety adapter,\n * and the {@link ThroughTableManager}, so callers only supply context they\n * already have on hand.\n */\nexport interface ManyToManyRelatedManagerCreateInputs<TTarget extends Record<string, unknown>> {\n /** Persisted primary-key value of the owning record. */\n ownerPrimaryKey: unknown;\n /** Relation name on the owning model (for error messages). */\n relationName: string;\n /** Display name of the owning model (for error messages). */\n ownerModelLabel: string;\n /** Resolved relation edge metadata for the many-to-many relation. */\n relation: NonNullable<TableMeta['relations']>[string];\n /** Through-model column metadata used to derive the join-table descriptor. */\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>;\n /** Runtime-bound database client shared with the owning manager. */\n client: DBClient;\n /** Shared {@link MutationCompiler} configured for the active dialect. */\n mutationCompiler: MutationCompiler;\n /** Active database adapter. Supplies placeholder formatting and dialect flags. */\n adapter: Adapter;\n /** SQL safety adapter shared with the owning manager. */\n sqlSafetyAdapter: OrmSqlSafetyAdapter;\n /** Lazy resolver returning the target model's {@link QueryExecutor}. */\n targetExecutorProvider: () => QueryExecutor<TTarget> | null;\n /** Model-manager-backed create path for new target records. */\n createTarget: (input: Partial<TTarget>) => Promise<TTarget>;\n /** Internal transaction runner used for multi-target membership writes. */\n runAtomic: <T>(work: () => Promise<T>) => Promise<T>;\n}\n\ninterface ManyToManyRelatedManagerInternalInputs<TTarget extends Record<string, unknown>> {\n ownerPrimaryKey: unknown;\n relationName: string;\n ownerModelLabel: string;\n targetPrimaryKeyField: string;\n throughTableManager: ThroughTableManager;\n targetExecutorProvider: () => QueryExecutor<TTarget> | null;\n createTarget: (input: Partial<TTarget>) => Promise<TTarget>;\n runAtomic: <T>(work: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Django-style related manager exposed on materialized model records for each\n * many-to-many relation.\n *\n * Use the manager to add or remove join-table membership and to query the\n * related target rows. The owning record's primary key and the relation name\n * are bound when the manager is attached, so application code does not need\n * to pass them on every call.\n *\n * Prefetched memberships seed an internal cache that the queryset returned\n * from `all()` short-circuits to without re-querying. Mutations through\n * `add`, `remove`, `set`, `clear`, and `create` invalidate the cache so\n * subsequent reads observe the updated membership. `set(...)` applies\n * Django-shaped replacement semantics:\n * it diffs the current relation membership against the supplied targets,\n * removes any missing links, and inserts any new links inside one atomic\n * write boundary. `clear()` removes every join row for the owner, and\n * `create(...)` persists a new target row plus its join-row link inside one\n * atomic boundary.\n *\n * @template TTarget - The persisted target record shape returned by `all()`.\n */\nexport class ManyToManyRelatedManager<TTarget extends Record<string, unknown>> {\n private static readonly BRAND = 'tango.orm.m2m_related_manager' as const;\n readonly __tangoBrand: typeof ManyToManyRelatedManager.BRAND = ManyToManyRelatedManager.BRAND;\n\n private prefetchCache: readonly TTarget[] | null = null;\n\n /**\n * Constructor is internal. Application and ORM code must build instances\n * through {@link ManyToManyRelatedManager.create}, which owns the wiring\n * between relation metadata and the backing through-table mutator. The\n * testing package exposes a fixture for unit tests that need a custom\n * mutator.\n */\n constructor(private readonly inputs: ManyToManyRelatedManagerInternalInputs<TTarget>) {}\n\n /**\n * Narrow an unknown value to {@link ManyToManyRelatedManager}.\n */\n static isManyToManyRelatedManager<TTarget extends Record<string, unknown>>(\n value: unknown\n ): value is ManyToManyRelatedManager<TTarget> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ManyToManyRelatedManager.BRAND\n );\n }\n\n /**\n * Build a {@link ManyToManyRelatedManager} bound to a single owner record.\n * The factory derives the join-table descriptor from the relation edge and\n * through-model fields, wires a {@link ThroughTableManager} against the\n * supplied runtime-bound client, and returns a manager whose `add`,\n * `remove`, `clear`, `create`, and `all` methods enroll in any active\n * `transaction.atomic(...)` boundary.\n */\n static create<TTarget extends Record<string, unknown>>(\n inputs: ManyToManyRelatedManagerCreateInputs<TTarget>\n ): ManyToManyRelatedManager<TTarget> {\n const throughTableManager = ThroughTableManager.fromRelation({\n relation: inputs.relation,\n throughModelFields: inputs.throughModelFields,\n client: inputs.client,\n mutationCompiler: inputs.mutationCompiler,\n adapter: inputs.adapter,\n sqlSafetyAdapter: inputs.sqlSafetyAdapter,\n });\n return new ManyToManyRelatedManager<TTarget>({\n ownerPrimaryKey: inputs.ownerPrimaryKey,\n relationName: inputs.relationName,\n ownerModelLabel: inputs.ownerModelLabel,\n targetPrimaryKeyField: inputs.relation.targetPrimaryKey,\n throughTableManager,\n targetExecutorProvider: inputs.targetExecutorProvider,\n createTarget: inputs.createTarget,\n runAtomic: inputs.runAtomic,\n });\n }\n\n /**\n * Insert join-table rows linking the owning record to the supplied\n * targets. Duplicate links are ignored so repeated `add(...)` calls are\n * idempotent. When multiple targets are supplied, Tango performs the\n * membership write inside one `transaction.atomic(...)` boundary.\n */\n async add(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n\n if (targetPrimaryKeys.length === 1) {\n await this.insertTargetPrimaryKeys(targetPrimaryKeys);\n } else {\n await this.inputs.runAtomic(() => this.insertTargetPrimaryKeys(targetPrimaryKeys));\n }\n this.invalidateCache();\n }\n\n /**\n * Delete join-table rows linking the owning record to the supplied\n * targets. When multiple targets are supplied, Tango performs the\n * membership write inside one `transaction.atomic(...)` boundary.\n */\n async remove(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n\n if (targetPrimaryKeys.length === 1) {\n await this.deleteTargetPrimaryKeys(targetPrimaryKeys);\n } else {\n await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimaryKeys));\n }\n this.invalidateCache();\n }\n\n /**\n * Delete every join-table row linked to the owning record and invalidate\n * any prefetched membership cache after the delete succeeds.\n */\n async clear(): Promise<void> {\n await this.inputs.throughTableManager.deleteAllLinksForOwner(this.inputs.ownerPrimaryKey);\n this.invalidateCache();\n }\n\n /**\n * Create a new target record through the related model's manager and link\n * it to the owning record inside one `transaction.atomic(...)` boundary.\n * This preserves target-manager hooks and defaults while preventing a\n * created target row from leaking if the join-row insert fails.\n */\n async create(input: Partial<TTarget>): Promise<TTarget> {\n const created = await this.inputs.runAtomic(async () => {\n const target = await this.inputs.createTarget(input);\n const targetPrimaryKey = this.resolveTargetPrimaryKey(target);\n await this.insertTargetPrimaryKeys([targetPrimaryKey]);\n return target;\n });\n this.invalidateCache();\n return created;\n }\n\n /**\n * Replace the current relation membership with exactly the supplied\n * targets. Duplicate inputs are collapsed before diffing against the\n * current through-table rows, so repeated values do not trigger extra\n * writes. Calling `set()` with no targets clears the relation.\n *\n * When replacement requires writes, Tango performs the delete/insert\n * sequence inside one `transaction.atomic(...)` boundary.\n */\n async set(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const nextTargetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n const currentTargetPrimaryKeys = await this.inputs.throughTableManager.selectTargetIdsForOwner(\n this.inputs.ownerPrimaryKey\n );\n const currentCanonical = new Set(\n currentTargetPrimaryKeys.map((primaryKey) => this.canonicalizePrimaryKey(primaryKey))\n );\n const nextCanonical = new Set(\n nextTargetPrimaryKeys.map((primaryKey) => this.canonicalizePrimaryKey(primaryKey))\n );\n const targetPrimaryKeysToRemove = currentTargetPrimaryKeys.filter(\n (primaryKey) => !nextCanonical.has(this.canonicalizePrimaryKey(primaryKey))\n );\n const targetPrimaryKeysToAdd = nextTargetPrimaryKeys.filter(\n (primaryKey) => !currentCanonical.has(this.canonicalizePrimaryKey(primaryKey))\n );\n\n if (targetPrimaryKeysToRemove.length === 0 && targetPrimaryKeysToAdd.length === 0) {\n return;\n }\n\n await this.inputs.runAtomic(async () => {\n await this.deleteTargetPrimaryKeys(targetPrimaryKeysToRemove);\n await this.insertTargetPrimaryKeys(targetPrimaryKeysToAdd);\n });\n this.invalidateCache();\n }\n\n /**\n * Return a {@link QuerySet} for the related target rows of this many-to-many\n * relation. When the relation was already loaded by `prefetchRelated(...)`,\n * the first `fetch()` resolves with the cached materialization without\n * re-querying. Mutating the membership through `add`/`remove`/`set`/\n * `clear`/`create` invalidates that cache.\n */\n all(): QuerySet<TTarget> {\n const executor = this.inputs.targetExecutorProvider();\n if (!executor) {\n throw new Error(\n `Cannot resolve a target query executor for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`\n );\n }\n return new ManyToManyRelatedQuerySet<TTarget>(executor, {\n getCache: () => this.prefetchCache,\n fetchTargetIds: () => this.inputs.throughTableManager.selectTargetIdsForOwner(this.inputs.ownerPrimaryKey),\n targetPrimaryKeyField: this.inputs.targetPrimaryKeyField,\n });\n }\n\n /**\n * Replace the prefetch cache with the supplied target rows. Called by the\n * many-to-many prefetch path so a follow-up `all()` resolves without an\n * extra database round-trip.\n */\n primePrefetchCache(targets: readonly TTarget[]): void {\n this.prefetchCache = [...targets];\n }\n\n /**\n * Drop any cached prefetch results. Mutating helpers call this so reads\n * after an `add`/`remove`/`set`/`clear`/`create` go back to the database.\n */\n invalidateCache(): void {\n this.prefetchCache = null;\n }\n\n /**\n * Snapshot of the current prefetch cache, exposed for diagnostics and\n * focused unit testing. Returns a fresh array copy so callers cannot\n * mutate the manager's internal state.\n */\n snapshotCache(): readonly TTarget[] | null {\n return this.prefetchCache ? [...this.prefetchCache] : null;\n }\n\n private async insertTargetPrimaryKeys(targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n if (targetPrimaryKeys.length === 1) {\n await this.inputs.throughTableManager.insertLink(this.inputs.ownerPrimaryKey, targetPrimaryKeys[0], {\n onDuplicate: InternalDuplicateInsertPolicy.IGNORE,\n });\n return;\n }\n await this.inputs.throughTableManager.insertLinks(this.inputs.ownerPrimaryKey, targetPrimaryKeys, {\n onDuplicate: InternalDuplicateInsertPolicy.IGNORE,\n });\n }\n\n private async deleteTargetPrimaryKeys(targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n if (targetPrimaryKeys.length === 1) {\n await this.inputs.throughTableManager.deleteLink(this.inputs.ownerPrimaryKey, targetPrimaryKeys[0]);\n return;\n }\n await this.inputs.throughTableManager.deleteLinks(this.inputs.ownerPrimaryKey, targetPrimaryKeys);\n }\n\n private resolveTargetPrimaryKeys(targets: readonly ManyToManyTargetRef<TTarget>[]): unknown[] {\n const resolved: unknown[] = [];\n const seen = new Set<string>();\n\n for (const target of targets) {\n const primaryKey = this.resolveTargetPrimaryKey(target);\n const canonical = this.canonicalizePrimaryKey(primaryKey);\n if (seen.has(canonical)) {\n continue;\n }\n seen.add(canonical);\n resolved.push(primaryKey);\n }\n\n return resolved;\n }\n\n private resolveTargetPrimaryKey(target: ManyToManyTargetRef<TTarget>): unknown {\n if (typeof target === 'string' || typeof target === 'number') {\n return target;\n }\n if (typeof target === 'object' && target !== null) {\n const targetPrimaryKey = (target as Record<string, unknown>)[this.inputs.targetPrimaryKeyField];\n if (targetPrimaryKey === undefined || targetPrimaryKey === null) {\n throw new Error(\n `Cannot resolve target primary key '${this.inputs.targetPrimaryKeyField}' for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`\n );\n }\n return targetPrimaryKey;\n }\n throw new Error(\n `Unsupported target reference for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'. Expected a record, a primary-key carrier, or a primary-key value.`\n );\n }\n\n private canonicalizePrimaryKey(primaryKey: unknown): string {\n switch (typeof primaryKey) {\n case 'string':\n return `string:${primaryKey}`;\n case 'number':\n return `number:${primaryKey}`;\n case 'bigint':\n return `bigint:${String(primaryKey)}`;\n case 'boolean':\n return `boolean:${primaryKey}`;\n default:\n return `json:${JSON.stringify(primaryKey)}`;\n }\n }\n}\n","import { NotFoundError } from '@danceroutine/tango-core';\nimport { ModelRegistry } from '@danceroutine/tango-schema';\nimport type { ModelWriteHooks } from '@danceroutine/tango-schema';\nimport type { Model as SchemaModel } from '@danceroutine/tango-schema/domain';\nimport type { QNode } from '../query/domain/QNode';\nimport type { FilterInput, TableMeta } from '../query/domain/index';\nimport { InternalRelationKind } from '../query/domain/internal/InternalRelationKind';\nimport { InternalQNodeType } from '../query/domain/internal/InternalQNodeType';\nimport { TableMetaFactory } from '../query/domain/TableMetaFactory';\nimport { ModelQuerySet } from '../query/index';\nimport type { QuerySet } from '../query/index';\nimport type { QueryExecutor } from '../query/index';\nimport type { Adapter } from '../connection/adapters/Adapter';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { OrmSqlSafetyAdapter } from '../validation';\nimport { InternalSqlValidationPlanKind as SqlPlanKind } from '../validation/internal/InternalSqlValidationPlanKind';\nimport { TransactionEngine } from '../transaction/internal/context';\nimport type { ManagerLike } from './ManagerLike';\nimport { MutationCompiler } from './internal/MutationCompiler';\nimport { RuntimeBoundClient } from './internal/RuntimeBoundClient';\nimport { ManyToManyRelatedManager } from './relations/ManyToManyRelatedManager';\nimport { isQNodeLike } from '../query/internal/isQNodeLike';\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> implements ManagerLike<\n TModelRow,\n 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 adapter: Adapter;\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.adapter = runtime.getAdapter();\n this.mutationCompiler = new MutationCompiler(this.adapter);\n this.queryExecutor = {\n get meta() {\n return ModelManager.createTableMeta(model);\n },\n client: this.client,\n adapter: this.adapter,\n run: async (compiled) => {\n const result = await this.client.query<TModelRow>(compiled.sql, compiled.params);\n return result.rows;\n },\n attachPersistedRecordAccessors: (record, modelKey) => {\n this.attachManyToManyRelatedManagers(record, modelKey ?? this.model.metadata.key);\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 as SchemaModel);\n const validatedMeta = sqlSafetyAdapter.validate({\n kind: SqlPlanKind.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 private static mergeCreatePayloadFromWhere<TModelRow extends Record<string, unknown>>(\n modelName: string,\n pkColumn: string,\n where: FilterInput<TModelRow> | QNode<TModelRow>,\n defaults?: Partial<TModelRow>\n ): Partial<TModelRow> {\n const hasDefaultsArg = defaults !== undefined;\n const providedDefaults = defaults !== undefined ? ({ ...defaults } as Partial<TModelRow>) : undefined;\n\n if (isQNodeLike(where)) {\n if (!hasDefaultsArg || !providedDefaults || Object.keys(providedDefaults).length === 0) {\n throw new Error(`Cannot create ${modelName} from Q filters without defaults.`);\n }\n const fromQ = ModelManager.collectPlainFieldsFromQNode(modelName, where);\n const merged = { ...fromQ, ...providedDefaults };\n const keys = Object.keys(merged).filter((key) => merged[key as keyof TModelRow] !== undefined);\n const nonPkKeys = keys.filter((key) => key !== pkColumn);\n if (nonPkKeys.length === 0) {\n throw new Error(`Cannot create ${modelName} without any values.`);\n }\n return merged;\n }\n\n const atom = where as FilterInput<TModelRow>;\n const entries = Object.entries(atom as Record<string, unknown>);\n const plainEntries = entries.filter(([key]) => !String(key).includes('__'));\n const lookupOnly = entries.length > 0 && plainEntries.length === 0;\n const fromAtom = plainEntries.length > 0 ? (Object.fromEntries(plainEntries) as Partial<TModelRow>) : undefined;\n const mergeBase = { ...fromAtom, ...providedDefaults };\n\n if (lookupOnly && ModelManager.countDefinedValues(mergeBase, pkColumn) === 0) {\n throw new Error(`Cannot create ${modelName} from lookup-only filters without defaults.`);\n }\n\n const cleanedAtom =\n plainEntries.length > 0\n ? (Object.fromEntries(plainEntries) as Partial<TModelRow>)\n : ({} as Partial<TModelRow>);\n const merged = { ...cleanedAtom, ...mergeBase };\n const keys = Object.keys(merged).filter((key) => merged[key as keyof TModelRow] !== undefined);\n const nonPkKeys = keys.filter((key) => key !== pkColumn);\n if (nonPkKeys.length === 0) {\n throw new Error(`Cannot create ${modelName} without any values.`);\n }\n return merged;\n }\n\n private static countDefinedValues<TModelRow extends Record<string, unknown>>(\n payload: Partial<TModelRow>,\n pkColumn: string\n ): number {\n return Object.entries(payload as Record<string, unknown>).filter(\n ([key, value]) => key !== pkColumn && value !== undefined\n ).length;\n }\n\n private static collectPlainFieldsFromQNode<TModelRow extends Record<string, unknown>>(\n modelName: string,\n node: QNode<TModelRow>\n ): Partial<TModelRow> {\n switch (node.kind) {\n case InternalQNodeType.ATOM:\n return ModelManager.omitLookupKeysFromAtom(node.where as FilterInput<TModelRow>);\n case InternalQNodeType.AND: {\n const partials = (node.nodes ?? []).map((child) =>\n ModelManager.collectPlainFieldsFromQNode(modelName, child)\n );\n return ModelManager.mergeCompatiblePartials(partials);\n }\n case InternalQNodeType.OR: {\n const partials = (node.nodes ?? []).map((child) =>\n ModelManager.collectPlainFieldsFromQNode(modelName, child)\n );\n const nonEmpty = partials.filter(\n (partial) => Object.keys(partial as Record<string, unknown>).length > 0\n );\n if (nonEmpty.length > 1) {\n throw new Error(\n `Cannot derive a create payload from ${modelName} OR filters with multiple predicates. Supply defaults that fully describe the insert.`\n );\n }\n return nonEmpty.length === 1 ? nonEmpty[0]! : {};\n }\n case InternalQNodeType.NOT:\n return {};\n }\n }\n\n private static omitLookupKeysFromAtom<TModelRow extends Record<string, unknown>>(\n atom: FilterInput<TModelRow>\n ): Partial<TModelRow> {\n const entries = Object.entries(atom as Record<string, unknown>).filter(([key]) => !String(key).includes('__'));\n return Object.fromEntries(entries) as Partial<TModelRow>;\n }\n\n private static mergeCompatiblePartials<TModelRow extends Record<string, unknown>>(\n partials: Array<Partial<TModelRow>>\n ): Partial<TModelRow> {\n const merged: Partial<TModelRow> = {};\n for (const partial of partials) {\n for (const [key, value] of Object.entries(partial as Record<string, unknown>)) {\n const existing = merged[key as keyof TModelRow];\n if (existing !== undefined && existing !== value) {\n throw new Error(`Conflicting values for '${key}' while deriving create payload from Q filters.`);\n }\n (merged as Record<string, unknown>)[key] = value;\n }\n }\n return merged;\n }\n\n query(): QuerySet<TModelRow, TModelRow, TSourceModel> {\n return new ModelQuerySet<TModelRow, TModelRow, TSourceModel>(this.queryExecutor, {});\n }\n\n all(): QuerySet<TModelRow, TModelRow, TSourceModel> {\n return this.query();\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 getOrCreate(args: {\n where: FilterInput<TModelRow> | QNode<TModelRow>;\n defaults?: Partial<TModelRow>;\n }): Promise<{ record: TModelRow; created: boolean }> {\n try {\n const record = await this.query().get(args.where);\n return { record, created: false };\n } catch (error) {\n if (!NotFoundError.isNotFoundError(error)) {\n throw error;\n }\n }\n\n const merged = ModelManager.mergeCreatePayloadFromWhere(\n this.model.metadata.name,\n this.meta.pk,\n args.where,\n args.defaults\n );\n const record = await this.create(merged);\n return { record, created: true };\n }\n\n async updateOrCreate(args: {\n where: FilterInput<TModelRow> | QNode<TModelRow>;\n defaults?: Partial<TModelRow>;\n update?: Partial<TModelRow>;\n }): Promise<{ record: TModelRow; created: boolean; updated: boolean }> {\n let existing: TModelRow | null = null;\n try {\n existing = await this.query().get(args.where);\n } catch (error) {\n if (!NotFoundError.isNotFoundError(error)) {\n throw error;\n }\n }\n\n if (!existing) {\n const merged = ModelManager.mergeCreatePayloadFromWhere(\n this.model.metadata.name,\n this.meta.pk,\n args.where,\n args.defaults\n );\n const record = await this.create(merged);\n return { record, created: true, updated: false };\n }\n\n const patch = args.update ?? args.defaults ?? {};\n if (Object.keys(patch).length === 0) {\n return { record: existing, created: false, updated: false };\n }\n\n const id = existing[this.meta.pk as keyof TModelRow] as TModelRow[keyof TModelRow];\n const record = await this.update(id, patch);\n return { record, created: false, updated: true };\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: SqlPlanKind.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 this.attachOwnRelatedManagers(created);\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: SqlPlanKind.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 this.attachOwnRelatedManagers(updated);\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 this.attachOwnRelatedManagers(current);\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: SqlPlanKind.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 /**\n * Build a {@link ManyToManyRelatedManager} bound to a single owner record\n * for the supplied many-to-many relation. The returned manager performs\n * its INSERT/DELETE writes through the shared runtime-bound client, so\n * mutations enroll in any active `transaction.atomic(...)` boundary.\n */\n createManyToManyRelatedManager<TTarget extends Record<string, unknown>>(\n relationName: string,\n ownerPrimaryKey: unknown\n ): ManyToManyRelatedManager<TTarget> {\n const relation = this.requireManyToManyEdge(relationName);\n const registry = ModelRegistry.getOwner(this.model as SchemaModel);\n const throughModel = registry.getByKey(relation.throughModelKey!)!;\n return ManyToManyRelatedManager.create<TTarget>({\n ownerPrimaryKey,\n relationName,\n ownerModelLabel: this.model.metadata.name,\n relation,\n throughModelFields: throughModel.metadata.fields,\n client: this.client,\n mutationCompiler: this.mutationCompiler,\n adapter: this.adapter,\n sqlSafetyAdapter,\n targetExecutorProvider: () => this.resolveTargetExecutor<TTarget>(relation.targetModelKey),\n createTarget: async (input) => {\n const targetManager = this.resolveTargetManager<TTarget>(relation.targetModelKey);\n if (!targetManager) {\n throw new Error(\n `Cannot resolve a target manager for relation '${relationName}' on '${this.model.metadata.name}'.`\n );\n }\n return targetManager.create(input);\n },\n runAtomic: (work) => TransactionEngine.forRuntime(this.runtime).atomic(() => work()),\n });\n }\n\n /**\n * Insert multiple rows in a single multi-row INSERT statement.\n *\n * All rows must share the same field set after hook processing. Rows with\n * extra or missing fields relative to the first row will cause an error.\n * If you need to insert rows with different field sets, use individual\n * {@link create} calls instead.\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 this.assertUniformRowShape(batchPrepared, new Set(preparedKeys));\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: SqlPlanKind.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 for (const record of result.rows) {\n this.attachOwnRelatedManagers(record);\n }\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 /**\n * Attach a {@link ManyToManyRelatedManager} as a non-enumerable property\n * for every persisted many-to-many relation declared on the supplied\n * record's model. Existing properties are left untouched so that prior\n * hydration writes (such as prefetched arrays) survive the attach pass\n * during the incremental rollout of related-manager hydration.\n */\n private attachOwnRelatedManagers(record: TModelRow): void {\n this.attachManyToManyRelatedManagers(record as unknown as Record<string, unknown>, this.model.metadata.key);\n }\n\n private attachManyToManyRelatedManagers(record: Record<string, unknown>, modelKey: string | undefined): void {\n if (!modelKey) {\n return;\n }\n const targetManager = this.resolveManagerForModelKey(modelKey);\n if (!targetManager) {\n return;\n }\n const meta = targetManager.meta;\n const relations = meta.relations;\n if (!relations) {\n return;\n }\n const ownerPrimaryKey = record[meta.pk];\n if (ownerPrimaryKey === undefined || ownerPrimaryKey === null) {\n return;\n }\n for (const [relationName, relation] of Object.entries(relations)) {\n if (relation.kind !== InternalRelationKind.MANY_TO_MANY) {\n continue;\n }\n if (Object.prototype.hasOwnProperty.call(record, relationName)) {\n continue;\n }\n const relatedManager = targetManager.createManyToManyRelatedManager(relationName, ownerPrimaryKey);\n Object.defineProperty(record, relationName, {\n value: relatedManager,\n writable: true,\n configurable: true,\n /**\n * Non-enumerable so `Object.keys(record)`, `JSON.stringify(record)`,\n * `{ ...record }`, and similar enumeration paths continue to\n * see only the persisted columns. Application code reaches the\n * manager through `record.tags`, never through enumeration.\n */\n enumerable: false,\n });\n }\n }\n\n private resolveManagerForModelKey(modelKey: string): ModelManager<Record<string, unknown>> | null {\n if (modelKey === this.model.metadata.key) {\n return this as unknown as ModelManager<Record<string, unknown>>;\n }\n const registry = ModelRegistry.getOwner(this.model as SchemaModel);\n const otherModel = registry.getByKey(modelKey);\n if (!otherModel) {\n return null;\n }\n const candidate = (otherModel as { objects?: unknown }).objects;\n return ModelManager.isModelManager(candidate) ? (candidate as ModelManager<Record<string, unknown>>) : null;\n }\n\n private resolveTargetExecutor<TTarget extends Record<string, unknown>>(\n targetModelKey: string\n ): QueryExecutor<TTarget> | null {\n const targetManager = this.resolveTargetManager<TTarget>(targetModelKey);\n if (!targetManager) {\n return null;\n }\n return (targetManager as unknown as { queryExecutor: QueryExecutor<TTarget> }).queryExecutor;\n }\n\n private resolveTargetManager<TTarget extends Record<string, unknown>>(\n targetModelKey: string\n ): ModelManager<TTarget> | null {\n const targetManager = this.resolveManagerForModelKey(targetModelKey);\n if (!targetManager) {\n return null;\n }\n return targetManager as unknown as ModelManager<TTarget>;\n }\n\n private requireManyToManyEdge(relationName: string): NonNullable<TableMeta['relations']>[string] {\n const rel = this.meta.relations?.[relationName];\n if (\n !rel ||\n rel.kind !== InternalRelationKind.MANY_TO_MANY ||\n !rel.throughTable ||\n !rel.throughSourceKey ||\n !rel.throughTargetKey ||\n !rel.throughModelKey\n ) {\n throw new Error(\n `Relation '${relationName}' on '${this.model.metadata.name}' is not a persisted many-to-many edge.`\n );\n }\n return rel;\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 private assertUniformRowShape(batch: Partial<TModelRow>[], referenceKeys: Set<string>): void {\n const divergentRows = batch\n .slice(1)\n .map((row, i) => {\n const rowKeys = new Set(Object.keys(row));\n const missing = [...referenceKeys].filter((k) => !rowKeys.has(k)).sort();\n const extra = [...rowKeys].filter((k) => !referenceKeys.has(k)).sort();\n return { index: i + 1, missing, extra };\n })\n .filter((r) => r.missing.length > 0 || r.extra.length > 0);\n\n if (divergentRows.length === 0) {\n return;\n }\n\n const sortedReferenceKeys = [...referenceKeys].sort();\n const indices = divergentRows.map((r) => r.index);\n const details = divergentRows\n .map((r) => {\n const parts: string[] = [];\n if (r.missing.length > 0) {\n parts.push(`missing [${r.missing.join(', ')}]`);\n }\n if (r.extra.length > 0) {\n parts.push(`extra [${r.extra.join(', ')}]`);\n }\n return `Row at index ${r.index}: ${parts.join(', ')}.`;\n })\n .join('\\n');\n\n throw new Error(\n `bulkCreate failed after hook processing: rows at indices [${indices.join(', ')}] have mismatched fields.\\n${details}\\nExpected fields (from row at index 0): [${sortedReferenceKeys.join(', ')}].`\n );\n }\n}\n","import type { z } from 'zod';\nimport type { Model as SchemaModel, ModelWriteHooks } from '@danceroutine/tango-schema/domain';\nimport { registerModelAugmentor } from '@danceroutine/tango-schema';\nimport { ModelManager } from './ModelManager';\nimport type { MaterializedModelRecord } from './relations/MaterializedModelRecord';\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<SchemaModel<TSchema>, 'metadata'> & {\n schema: {\n parse(input: unknown): MaterializedModelRecord<TSchema>;\n };\n hooks?: ModelWriteHooks<MaterializedModelRecord<TSchema>>;\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<MaterializedModelRecord<TSchema>, SchemaModel<TSchema, TKey>>(\n model as unknown as AugmentableSchemaModel<TSchema>,\n runtime\n );\n managerCache.set(model, {\n runtime,\n manager: manager as unknown 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
|
+
{"version":3,"file":"registerModelObjects-CGjjOzd9.js","names":["QueryResultClass","Q","SqlPlanKind","SqlPlanKind","atom"],"sources":["../src/manager/relations/ManyToManyRelatedQuerySet.ts","../src/manager/internal/MutationCompiler.ts","../src/manager/relations/internal/ThroughTableManager.ts","../src/manager/relations/ManyToManyRelatedManager.ts","../src/manager/ModelManager.ts","../src/manager/registerModelObjects.ts"],"sourcesContent":["/*\n * Maintainer note: This subclass exists rather than a plain `QuerySet` so\n * that the related-manager can thread a prefetch-cache short-circuit and a\n * two-phase fetch through the join table without dragging many-to-many\n * knowledge into the base `QuerySet`.\n *\n * 1. Prefetch-cache short-circuit. When `prefetchRelated(...)` loads the\n * relation ahead of time, the manager primes a cache that the first\n * `fetch()` resolves with directly. Mutations via `add`/`remove`\n * invalidate it.\n * 2. Two-phase fetch through the join table. On cache miss (or once the\n * caller adds chainable state), the queryset asks the bridge for the\n * linked target primary keys and then runs a vanilla target-table query\n * scoped by `pk__in = [...]`. This keeps the compiled SQL identical to\n * what a direct `TargetModel.objects.query()` would produce and avoids\n * joining the through table into the projection.\n * 3. Chain preservation. Fluent queryset methods reuse the same\n * subclass-preserving `spawn(...)` path as the rest of the ORM surface,\n * so chains like `post.tags.all().select(['id']).orderBy('name').fetch()`\n * keep the owner scoping and cache semantics instead of falling back to\n * the model-backed queryset family.\n */\nimport type { QueryResult } from '../../query/domain/QueryResult';\nimport type { QuerySetState } from '../../query/domain/QuerySetState';\nimport type { FilterInput } from '../../query/domain/FilterInput';\nimport type { QNode } from '../../query/domain/QNode';\nimport type { QueryExecutor } from '../../query/index';\nimport { ModelQuerySet, QueryResult as QueryResultClass } from '../../query/index';\nimport { QuerySet } from '../../query/index';\nimport { InternalQNodeType } from '../../query/domain/internal/InternalQNodeType';\nimport { QBuilder as Q } from '../../query/QBuilder';\n\n/**\n * Hooks supplied by {@link ManyToManyRelatedManager} so the queryset returned\n * from `all()` can short-circuit to the prefetch cache, scope the SQL query\n * to the owner via the join table, and filter targets by the resolved primary\n * keys.\n *\n * Application code does not construct this bridge directly; it is wired by\n * the related manager when `all()` is called.\n */\nexport interface ManyToManyRelatedQuerySetBridge<TTarget extends Record<string, unknown>> {\n getCache(): readonly TTarget[] | null;\n fetchTargetIds(): Promise<readonly (string | number)[]>;\n targetPrimaryKeyField: string;\n}\n\ntype ShapeFunction<TInput, Out> = (row: TInput) => Out;\ntype ShapeParser<TInput, Out> = { parse: (row: TInput) => Out };\ntype Shape<TInput, Out> = ShapeFunction<TInput, Out> | ShapeParser<TInput, Out>;\n\nfunction applyShape<TInput, Out>(rows: readonly TInput[], shape: Shape<TInput, Out>): Out[] {\n return typeof shape === 'function' ? rows.map(shape) : rows.map((row) => shape.parse(row));\n}\n\n/**\n * {@link QuerySet} returned by `post.tags.all()` on a many-to-many related\n * manager.\n *\n * Behaves like a normal `QuerySet` over the target model from an application\n * developer's perspective: you can chain `filter`, `exclude`, `orderBy`,\n * `limit`, `offset`, and terminate with `fetch`, `fetchOne`, or `count`.\n * Each chainable call returns another `ManyToManyRelatedQuerySet` so the\n * chain keeps the membership scoping of the owning record.\n *\n * Two behaviors differ from a plain `QuerySet` and matter to application\n * developers:\n *\n * - When the relation was loaded by `prefetchRelated(...)` and no chainable\n * state has been added (no `filter`, `orderBy`, etc.), `fetch()` and\n * `count()` resolve from the prefetch cache without issuing SQL.\n * - Mutating the membership via `post.tags.add(tag)` or\n * `post.tags.remove(tag)` invalidates that cache so follow-up reads go\n * back to the database.\n *\n * @example\n * ```ts\n * const post = await PostModel.objects.getOrThrow(postId);\n * await post.tags.add(tag);\n * const tags = await post.tags.all().filter({ color: 'red' }).orderBy('name').fetch();\n * ```\n *\n * @template TTarget - The persisted target record shape (e.g. `Tag`).\n */\nexport class ManyToManyRelatedQuerySet<TTarget extends Record<string, unknown>> extends QuerySet<TTarget> {\n constructor(\n executor: QueryExecutor<TTarget>,\n private readonly bridge: ManyToManyRelatedQuerySetBridge<TTarget>,\n state: QuerySetState<TTarget> = {}\n ) {\n super(executor, state);\n }\n\n override async fetch<Out>(\n shape?: ShapeFunction<TTarget, Out> | ShapeParser<TTarget, Out>\n ): Promise<QueryResult<TTarget | Out>> {\n if (this.isStateTrivial()) {\n const cache = this.bridge.getCache();\n if (cache !== null) {\n const results: Array<TTarget | Out> = shape ? applyShape(cache, shape) : [...cache];\n return new QueryResultClass(results);\n }\n }\n const ids = await this.bridge.fetchTargetIds();\n if (ids.length === 0) {\n return new QueryResultClass([]);\n }\n const scopedQs = new ModelQuerySet<TTarget>(this.executor, this.scopedState(ids));\n return shape ? scopedQs.fetch(shape) : scopedQs.fetch();\n }\n\n override async fetchOne<Out>(\n shape?: ShapeFunction<TTarget, Out> | ShapeParser<TTarget, Out>\n ): Promise<TTarget | Out | null> {\n const result = shape ? await this.fetch(shape) : await this.fetch();\n return (result.items[0] as TTarget | Out | undefined) ?? null;\n }\n\n override async count(): Promise<number> {\n if (this.isStateTrivial()) {\n const cache = this.bridge.getCache();\n if (cache !== null) {\n return cache.length;\n }\n }\n const ids = await this.bridge.fetchTargetIds();\n if (ids.length === 0) {\n return 0;\n }\n if (this.isStateTrivial()) {\n return ids.length;\n }\n const scopedQs = new ModelQuerySet<TTarget>(this.executor, this.scopedState(ids));\n return scopedQs.count();\n }\n\n protected override spawn<\n TNextBaseResult extends Record<string, unknown>,\n TNextHydrated extends Record<string, unknown>,\n >(state: QuerySetState<TTarget>): QuerySet<TTarget, TNextBaseResult, unknown, TNextHydrated> {\n return new ManyToManyRelatedQuerySet<TTarget>(this.executor, this.bridge, state) as QuerySet<\n TTarget,\n TNextBaseResult,\n unknown,\n TNextHydrated\n >;\n }\n\n private isStateTrivial(): boolean {\n return Object.keys(this.state).length === 0;\n }\n\n private scopedState(ids: readonly (string | number)[]): QuerySetState<TTarget> {\n const inFilter: FilterInput<TTarget> = {\n [`${this.bridge.targetPrimaryKeyField}__in`]: [...ids],\n } as FilterInput<TTarget>;\n const inAtom: QNode<TTarget> = { kind: InternalQNodeType.ATOM, where: inFilter };\n const merged = this.state.q ? Q.and(inAtom, this.state.q) : inAtom;\n return { ...this.state, q: merged };\n }\n}\n","import type { CompiledQuery } from '../../query/domain/index';\nimport type { Adapter, SqlPlaceholders } from '../../connection/adapters/Adapter';\nimport type {\n ValidatedDeleteSqlPlan,\n ValidatedInsertSqlPlan,\n ValidatedSelectSqlPlan,\n ValidatedUpdateSqlPlan,\n} from '../../validation/SQLValidationEngine';\n\nexport const InternalDuplicateInsertPolicy = {\n ERROR: 'error',\n IGNORE: 'ignore',\n} as const;\n\nexport type DuplicateInsertPolicy = (typeof InternalDuplicateInsertPolicy)[keyof typeof InternalDuplicateInsertPolicy];\n\n/**\n * Internal compiler for manager-owned INSERT/UPDATE/DELETE statements.\n */\nexport class MutationCompiler {\n private readonly adapter: Adapter;\n private readonly placeholders: SqlPlaceholders;\n\n constructor(adapter: Adapter) {\n this.adapter = adapter;\n this.placeholders = adapter.placeholders;\n }\n\n compileInsert(plan: ValidatedInsertSqlPlan, values: readonly unknown[]): CompiledQuery {\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES (${this.placeholders.list(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.placeholders.at(index + 1)}`).join(', ');\n const whereParam = this.placeholders.at(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.placeholders.at(1)}`,\n params: [id],\n };\n }\n\n compileDeleteByJoinKeys(\n plan: ValidatedSelectSqlPlan,\n leftFilterKey: string,\n rightFilterKey: string,\n leftValue: unknown,\n rightValue: unknown\n ): CompiledQuery {\n const leftDescriptor = plan.filterKeys[leftFilterKey];\n const rightDescriptor = plan.filterKeys[rightFilterKey];\n if (!leftDescriptor || !rightDescriptor) {\n throw new Error(\n `MutationCompiler.compileDeleteByJoinKeys: filter keys '${leftFilterKey}' and '${rightFilterKey}' must be present on the validated plan.`\n );\n }\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} = ${this.placeholders.at(2)}`,\n params: [leftValue, rightValue],\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) => `(${this.placeholders.listFromOffset(columnCount, rowIndex * columnCount)})`)\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 compileInsertJoinLinks(\n plan: ValidatedInsertSqlPlan,\n sourceKey: string,\n targetKey: string,\n ownerValue: unknown,\n targetValues: readonly unknown[],\n duplicatePolicy: DuplicateInsertPolicy\n ): CompiledQuery {\n const valueRows = targetValues.map((targetValue) => [ownerValue, targetValue]);\n const placeholders = valueRows\n .map((_row, rowIndex) => `(${this.placeholders.listFromOffset(2, rowIndex * 2)})`)\n .join(', ');\n const params = valueRows.flat();\n\n if (duplicatePolicy === InternalDuplicateInsertPolicy.IGNORE) {\n switch (this.adapter.dialect) {\n case 'postgres':\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders} ON CONFLICT (${sourceKey}, ${targetKey}) DO NOTHING`,\n params,\n };\n case 'sqlite':\n return {\n sql: `INSERT OR IGNORE INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders}`,\n params,\n };\n }\n }\n\n return {\n sql: `INSERT INTO ${plan.meta.table} (${plan.writeKeys.join(', ')}) VALUES ${placeholders}`,\n params,\n };\n }\n\n compileDeleteJoinLinks(\n plan: ValidatedSelectSqlPlan,\n leftFilterKey: string,\n rightFilterKey: string,\n leftValue: unknown,\n rightValues: readonly unknown[]\n ): CompiledQuery {\n const leftDescriptor = plan.filterKeys[leftFilterKey];\n const rightDescriptor = plan.filterKeys[rightFilterKey];\n if (!leftDescriptor || !rightDescriptor) {\n throw new Error(\n `MutationCompiler.compileDeleteJoinLinks: filter keys '${leftFilterKey}' and '${rightFilterKey}' must be present on the validated plan.`\n );\n }\n if (rightValues.length === 0) {\n throw new Error('MutationCompiler.compileDeleteJoinLinks requires at least one target value.');\n }\n if (rightValues.length === 1) {\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} = ${this.placeholders.at(2)}`,\n params: [leftValue, rightValues[0]],\n };\n }\n\n return {\n sql: `DELETE FROM ${plan.meta.table} WHERE ${leftDescriptor.field} = ${this.placeholders.at(\n 1\n )} AND ${rightDescriptor.field} IN (${this.placeholders.listFromOffset(rightValues.length, 1)})`,\n params: [leftValue, ...rightValues],\n };\n }\n}\n","import type { DBClient } from '../../../connection/clients/DBClient';\nimport type { TableMeta } from '../../../query/domain/index';\nimport type { Adapter } from '../../../connection/adapters/Adapter';\nimport { OrmSqlSafetyAdapter } from '../../../validation/OrmSqlSafetyAdapter';\nimport { InternalSqlValidationPlanKind as SqlPlanKind } from '../../../validation/internal/InternalSqlValidationPlanKind';\nimport {\n InternalDuplicateInsertPolicy,\n MutationCompiler,\n type DuplicateInsertPolicy,\n} from '../../internal/MutationCompiler';\n\n/**\n * Resolved through-table descriptor used by {@link ThroughTableManager}. The\n * descriptor is derived once from a relation edge plus its through-model\n * metadata, then reused for every link insert, delete, and read.\n */\nexport interface ThroughTableLinkDescriptor {\n /** Physical join-table name validated against SQL identifier safety rules. */\n table: string;\n /** Primary-key column name on the join table. */\n primaryKey: string;\n /** Full column map for the join table, used by the SQL safety adapter. */\n columns: Record<string, string>;\n /** Join-table column that stores the owner-side primary-key value. */\n sourceColumn: string;\n /** Join-table column that stores the target-side primary-key value. */\n targetColumn: string;\n}\n\n/**\n * Inputs accepted by {@link ThroughTableManager.fromRelation}.\n */\nexport interface ThroughTableManagerFromRelationInputs {\n relation: NonNullable<TableMeta['relations']>[string];\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>;\n client: DBClient;\n mutationCompiler: MutationCompiler;\n adapter: Adapter;\n sqlSafetyAdapter: OrmSqlSafetyAdapter;\n}\n\nexport interface InsertLinkOptions {\n onDuplicate?: DuplicateInsertPolicy;\n}\n\n/**\n * Internal helper that issues the INSERT, DELETE, and SELECT statements for\n * a single many-to-many join table. Centralizes SQL safety validation and\n * compilation so {@link ManyToManyRelatedManager} implementations only deal\n * in primary-key values.\n */\nexport class ThroughTableManager {\n constructor(\n private readonly client: DBClient,\n private readonly mutationCompiler: MutationCompiler,\n private readonly descriptor: ThroughTableLinkDescriptor,\n private readonly adapter: Adapter,\n private readonly sqlSafetyAdapter: OrmSqlSafetyAdapter = new OrmSqlSafetyAdapter()\n ) {}\n\n /**\n * Derive a {@link ThroughTableLinkDescriptor} from the through-model\n * metadata exposed by a many-to-many relation edge.\n */\n static buildLinkDescriptor(\n relation: NonNullable<TableMeta['relations']>[string],\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>\n ): ThroughTableLinkDescriptor {\n if (!relation.throughTable || !relation.throughSourceKey || !relation.throughTargetKey) {\n throw new Error(\n 'Cannot derive a through-table descriptor from a relation that is not a persisted many-to-many edge.'\n );\n }\n\n const primaryKeyField = throughModelFields.find((field) => field.primaryKey);\n if (!primaryKeyField) {\n throw new Error('Through-model metadata is missing a primary-key field.');\n }\n\n return {\n table: relation.throughTable,\n primaryKey: primaryKeyField.name,\n columns: Object.fromEntries(throughModelFields.map((field) => [field.name, field.type])),\n sourceColumn: relation.throughSourceKey,\n targetColumn: relation.throughTargetKey,\n };\n }\n\n /**\n * Convenience factory that derives the join-table descriptor from the\n * relation edge and instantiates a {@link ThroughTableManager} in one\n * step.\n */\n static fromRelation(inputs: ThroughTableManagerFromRelationInputs): ThroughTableManager {\n return new ThroughTableManager(\n inputs.client,\n inputs.mutationCompiler,\n ThroughTableManager.buildLinkDescriptor(inputs.relation, inputs.throughModelFields),\n inputs.adapter,\n inputs.sqlSafetyAdapter\n );\n }\n\n /**\n * Read every target primary-key value linked to the supplied owner via\n * the join table. Used by ManyToManyRelatedManager.all to scope\n * follow-up target queries to the current owner.\n */\n async selectTargetIdsForOwner(ownerPrimaryKey: unknown): Promise<readonly (string | number)[]> {\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const sourceColumn = validated.filterKeys[this.descriptor.sourceColumn]!.field;\n const targetColumn = validated.filterKeys[this.descriptor.targetColumn]!.field;\n const placeholder = this.adapter.placeholders.at(1);\n const sql = `SELECT ${targetColumn} AS target_id FROM ${validated.meta.table} WHERE ${sourceColumn} = ${placeholder}`;\n const result = await this.client.query<{ target_id: string | number }>(sql, [ownerPrimaryKey]);\n return result.rows\n .map((row) => row.target_id)\n .filter((value): value is string | number => typeof value === 'string' || typeof value === 'number');\n }\n\n async insertLink(\n ownerPrimaryKey: unknown,\n targetPrimaryKey: unknown,\n options: InsertLinkOptions = {}\n ): Promise<void> {\n await this.insertLinks(ownerPrimaryKey, [targetPrimaryKey], options);\n }\n\n async insertLinks(\n ownerPrimaryKey: unknown,\n targetPrimaryKeys: readonly unknown[],\n options: InsertLinkOptions = {}\n ): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n const validatedPlan = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.INSERT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n writeKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const duplicatePolicy = options.onDuplicate ?? InternalDuplicateInsertPolicy.ERROR;\n if (duplicatePolicy === InternalDuplicateInsertPolicy.IGNORE && !this.adapter.features.ignoreDuplicateInsert) {\n throw new Error(\n `Adapter '${this.adapter.name}' does not support duplicate-safe link insertion for many-to-many writes.`\n );\n }\n const compiled = this.mutationCompiler.compileInsertJoinLinks(\n validatedPlan,\n this.descriptor.sourceColumn,\n this.descriptor.targetColumn,\n ownerPrimaryKey,\n targetPrimaryKeys,\n duplicatePolicy\n );\n await this.client.query(compiled.sql, compiled.params);\n }\n\n async deleteLink(ownerPrimaryKey: unknown, targetPrimaryKey: unknown): Promise<void> {\n await this.deleteLinks(ownerPrimaryKey, [targetPrimaryKey]);\n }\n\n async deleteLinks(ownerPrimaryKey: unknown, targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn, this.descriptor.targetColumn],\n });\n const compiled = this.mutationCompiler.compileDeleteJoinLinks(\n validated,\n this.descriptor.sourceColumn,\n this.descriptor.targetColumn,\n ownerPrimaryKey,\n targetPrimaryKeys\n );\n await this.client.query(compiled.sql, compiled.params);\n }\n\n /**\n * Delete every join-table row linked to one owner record. Used by\n * `ManyToManyRelatedManager.clear()` so the related manager can clear a\n * relation without first loading the current target ids.\n */\n async deleteAllLinksForOwner(ownerPrimaryKey: unknown): Promise<void> {\n const validated = this.sqlSafetyAdapter.validate({\n kind: SqlPlanKind.SELECT,\n meta: {\n table: this.descriptor.table,\n pk: this.descriptor.primaryKey,\n columns: this.descriptor.columns,\n },\n filterKeys: [this.descriptor.sourceColumn],\n });\n const sourceColumn = validated.filterKeys[this.descriptor.sourceColumn]!.field;\n const placeholder = this.adapter.placeholders.at(1);\n const sql = `DELETE FROM ${validated.meta.table} WHERE ${sourceColumn} = ${placeholder}`;\n await this.client.query(sql, [ownerPrimaryKey]);\n }\n}\n","import type { DBClient } from '../../connection/clients/DBClient';\nimport type { TableMeta } from '../../query/domain/index';\nimport type { Adapter } from '../../connection/adapters/Adapter';\nimport type { QueryExecutor, QuerySet } from '../../query/index';\nimport type { OrmSqlSafetyAdapter } from '../../validation/OrmSqlSafetyAdapter';\nimport type { MutationCompiler } from '../internal/MutationCompiler';\nimport { InternalDuplicateInsertPolicy } from '../internal/MutationCompiler';\nimport { ManyToManyRelatedQuerySet } from './ManyToManyRelatedQuerySet';\nimport { ThroughTableManager } from './internal/ThroughTableManager';\n\n/**\n * Accepted target reference shapes for {@link ManyToManyRelatedManager.add},\n * {@link ManyToManyRelatedManager.remove}, and\n * {@link ManyToManyRelatedManager.set}.\n *\n * Application code may pass a target record, a primary-key carrier object, or\n * a bare primary-key value.\n *\n * @template TTarget - The persisted target record shape.\n */\nexport type ManyToManyTargetRef<TTarget extends Record<string, unknown>> =\n | TTarget\n | { readonly [pk: string]: unknown }\n | string\n | number;\n\n/**\n * Inputs accepted by the {@link ManyToManyRelatedManager.create} factory. The\n * factory owns the wiring between relation metadata, the SQL safety adapter,\n * and the {@link ThroughTableManager}, so callers only supply context they\n * already have on hand.\n */\nexport interface ManyToManyRelatedManagerCreateInputs<TTarget extends Record<string, unknown>> {\n /** Persisted primary-key value of the owning record. */\n ownerPrimaryKey: unknown;\n /** Relation name on the owning model (for error messages). */\n relationName: string;\n /** Display name of the owning model (for error messages). */\n ownerModelLabel: string;\n /** Resolved relation edge metadata for the many-to-many relation. */\n relation: NonNullable<TableMeta['relations']>[string];\n /** Through-model column metadata used to derive the join-table descriptor. */\n throughModelFields: ReadonlyArray<{ name: string; type: string; primaryKey?: boolean }>;\n /** Runtime-bound database client shared with the owning manager. */\n client: DBClient;\n /** Shared {@link MutationCompiler} configured for the active dialect. */\n mutationCompiler: MutationCompiler;\n /** Active database adapter. Supplies placeholder formatting and dialect flags. */\n adapter: Adapter;\n /** SQL safety adapter shared with the owning manager. */\n sqlSafetyAdapter: OrmSqlSafetyAdapter;\n /** Lazy resolver returning the target model's {@link QueryExecutor}. */\n targetExecutorProvider: () => QueryExecutor<TTarget> | null;\n /** Model-manager-backed create path for new target records. */\n createTarget: (input: Partial<TTarget>) => Promise<TTarget>;\n /** Internal transaction runner used for multi-target membership writes. */\n runAtomic: <T>(work: () => Promise<T>) => Promise<T>;\n}\n\ninterface ManyToManyRelatedManagerInternalInputs<TTarget extends Record<string, unknown>> {\n ownerPrimaryKey: unknown;\n relationName: string;\n ownerModelLabel: string;\n targetPrimaryKeyField: string;\n throughTableManager: ThroughTableManager;\n targetExecutorProvider: () => QueryExecutor<TTarget> | null;\n createTarget: (input: Partial<TTarget>) => Promise<TTarget>;\n runAtomic: <T>(work: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Django-style related manager exposed on materialized model records for each\n * many-to-many relation.\n *\n * Use the manager to add or remove join-table membership and to query the\n * related target rows. The owning record's primary key and the relation name\n * are bound when the manager is attached, so application code does not need\n * to pass them on every call.\n *\n * Prefetched memberships seed an internal cache that the queryset returned\n * from `all()` short-circuits to without re-querying. Mutations through\n * `add`, `remove`, `set`, `clear`, and `create` invalidate the cache so\n * subsequent reads observe the updated membership. `set(...)` applies\n * Django-shaped replacement semantics:\n * it diffs the current relation membership against the supplied targets,\n * removes any missing links, and inserts any new links inside one atomic\n * write boundary. `clear()` removes every join row for the owner, and\n * `create(...)` persists a new target row plus its join-row link inside one\n * atomic boundary.\n *\n * @template TTarget - The persisted target record shape returned by `all()`.\n */\nexport class ManyToManyRelatedManager<TTarget extends Record<string, unknown>> {\n private static readonly BRAND = 'tango.orm.m2m_related_manager' as const;\n readonly __tangoBrand: typeof ManyToManyRelatedManager.BRAND = ManyToManyRelatedManager.BRAND;\n\n private prefetchCache: readonly TTarget[] | null = null;\n\n /**\n * Constructor is internal. Application and ORM code must build instances\n * through {@link ManyToManyRelatedManager.create}, which owns the wiring\n * between relation metadata and the backing through-table mutator. The\n * testing package exposes a fixture for unit tests that need a custom\n * mutator.\n */\n constructor(private readonly inputs: ManyToManyRelatedManagerInternalInputs<TTarget>) {}\n\n /**\n * Narrow an unknown value to {@link ManyToManyRelatedManager}.\n */\n static isManyToManyRelatedManager<TTarget extends Record<string, unknown>>(\n value: unknown\n ): value is ManyToManyRelatedManager<TTarget> {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === ManyToManyRelatedManager.BRAND\n );\n }\n\n /**\n * Build a {@link ManyToManyRelatedManager} bound to a single owner record.\n * The factory derives the join-table descriptor from the relation edge and\n * through-model fields, wires a {@link ThroughTableManager} against the\n * supplied runtime-bound client, and returns a manager whose `add`,\n * `remove`, `clear`, `create`, and `all` methods enroll in any active\n * `transaction.atomic(...)` boundary.\n */\n static create<TTarget extends Record<string, unknown>>(\n inputs: ManyToManyRelatedManagerCreateInputs<TTarget>\n ): ManyToManyRelatedManager<TTarget> {\n const throughTableManager = ThroughTableManager.fromRelation({\n relation: inputs.relation,\n throughModelFields: inputs.throughModelFields,\n client: inputs.client,\n mutationCompiler: inputs.mutationCompiler,\n adapter: inputs.adapter,\n sqlSafetyAdapter: inputs.sqlSafetyAdapter,\n });\n return new ManyToManyRelatedManager<TTarget>({\n ownerPrimaryKey: inputs.ownerPrimaryKey,\n relationName: inputs.relationName,\n ownerModelLabel: inputs.ownerModelLabel,\n targetPrimaryKeyField: inputs.relation.targetPrimaryKey,\n throughTableManager,\n targetExecutorProvider: inputs.targetExecutorProvider,\n createTarget: inputs.createTarget,\n runAtomic: inputs.runAtomic,\n });\n }\n\n /**\n * Insert join-table rows linking the owning record to the supplied\n * targets. Duplicate links are ignored so repeated `add(...)` calls are\n * idempotent. When multiple targets are supplied, Tango performs the\n * membership write inside one `transaction.atomic(...)` boundary.\n */\n async add(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n\n if (targetPrimaryKeys.length === 1) {\n await this.insertTargetPrimaryKeys(targetPrimaryKeys);\n } else {\n await this.inputs.runAtomic(() => this.insertTargetPrimaryKeys(targetPrimaryKeys));\n }\n this.invalidateCache();\n }\n\n /**\n * Delete join-table rows linking the owning record to the supplied\n * targets. When multiple targets are supplied, Tango performs the\n * membership write inside one `transaction.atomic(...)` boundary.\n */\n async remove(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const targetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n\n if (targetPrimaryKeys.length === 1) {\n await this.deleteTargetPrimaryKeys(targetPrimaryKeys);\n } else {\n await this.inputs.runAtomic(() => this.deleteTargetPrimaryKeys(targetPrimaryKeys));\n }\n this.invalidateCache();\n }\n\n /**\n * Delete every join-table row linked to the owning record and invalidate\n * any prefetched membership cache after the delete succeeds.\n */\n async clear(): Promise<void> {\n await this.inputs.throughTableManager.deleteAllLinksForOwner(this.inputs.ownerPrimaryKey);\n this.invalidateCache();\n }\n\n /**\n * Create a new target record through the related model's manager and link\n * it to the owning record inside one `transaction.atomic(...)` boundary.\n * This preserves target-manager hooks and defaults while preventing a\n * created target row from leaking if the join-row insert fails.\n */\n async create(input: Partial<TTarget>): Promise<TTarget> {\n const created = await this.inputs.runAtomic(async () => {\n const target = await this.inputs.createTarget(input);\n const targetPrimaryKey = this.resolveTargetPrimaryKey(target);\n await this.insertTargetPrimaryKeys([targetPrimaryKey]);\n return target;\n });\n this.invalidateCache();\n return created;\n }\n\n /**\n * Replace the current relation membership with exactly the supplied\n * targets. Duplicate inputs are collapsed before diffing against the\n * current through-table rows, so repeated values do not trigger extra\n * writes. Calling `set()` with no targets clears the relation.\n *\n * When replacement requires writes, Tango performs the delete/insert\n * sequence inside one `transaction.atomic(...)` boundary.\n */\n async set(...targets: ManyToManyTargetRef<TTarget>[]): Promise<void> {\n const nextTargetPrimaryKeys = this.resolveTargetPrimaryKeys(targets);\n const currentTargetPrimaryKeys = await this.inputs.throughTableManager.selectTargetIdsForOwner(\n this.inputs.ownerPrimaryKey\n );\n const currentCanonical = new Set(\n currentTargetPrimaryKeys.map((primaryKey) => this.canonicalizePrimaryKey(primaryKey))\n );\n const nextCanonical = new Set(\n nextTargetPrimaryKeys.map((primaryKey) => this.canonicalizePrimaryKey(primaryKey))\n );\n const targetPrimaryKeysToRemove = currentTargetPrimaryKeys.filter(\n (primaryKey) => !nextCanonical.has(this.canonicalizePrimaryKey(primaryKey))\n );\n const targetPrimaryKeysToAdd = nextTargetPrimaryKeys.filter(\n (primaryKey) => !currentCanonical.has(this.canonicalizePrimaryKey(primaryKey))\n );\n\n if (targetPrimaryKeysToRemove.length === 0 && targetPrimaryKeysToAdd.length === 0) {\n return;\n }\n\n await this.inputs.runAtomic(async () => {\n await this.deleteTargetPrimaryKeys(targetPrimaryKeysToRemove);\n await this.insertTargetPrimaryKeys(targetPrimaryKeysToAdd);\n });\n this.invalidateCache();\n }\n\n /**\n * Return a {@link QuerySet} for the related target rows of this many-to-many\n * relation. When the relation was already loaded by `prefetchRelated(...)`,\n * the first `fetch()` resolves with the cached materialization without\n * re-querying. Mutating the membership through `add`/`remove`/`set`/\n * `clear`/`create` invalidates that cache.\n */\n all(): QuerySet<TTarget> {\n const executor = this.inputs.targetExecutorProvider();\n if (!executor) {\n throw new Error(\n `Cannot resolve a target query executor for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`\n );\n }\n return new ManyToManyRelatedQuerySet<TTarget>(executor, {\n getCache: () => this.prefetchCache,\n fetchTargetIds: () => this.inputs.throughTableManager.selectTargetIdsForOwner(this.inputs.ownerPrimaryKey),\n targetPrimaryKeyField: this.inputs.targetPrimaryKeyField,\n });\n }\n\n /**\n * Replace the prefetch cache with the supplied target rows. Called by the\n * many-to-many prefetch path so a follow-up `all()` resolves without an\n * extra database round-trip.\n */\n primePrefetchCache(targets: readonly TTarget[]): void {\n this.prefetchCache = [...targets];\n }\n\n /**\n * Drop any cached prefetch results. Mutating helpers call this so reads\n * after an `add`/`remove`/`set`/`clear`/`create` go back to the database.\n */\n invalidateCache(): void {\n this.prefetchCache = null;\n }\n\n /**\n * Snapshot of the current prefetch cache, exposed for diagnostics and\n * focused unit testing. Returns a fresh array copy so callers cannot\n * mutate the manager's internal state.\n */\n snapshotCache(): readonly TTarget[] | null {\n return this.prefetchCache ? [...this.prefetchCache] : null;\n }\n\n private async insertTargetPrimaryKeys(targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n if (targetPrimaryKeys.length === 1) {\n await this.inputs.throughTableManager.insertLink(this.inputs.ownerPrimaryKey, targetPrimaryKeys[0], {\n onDuplicate: InternalDuplicateInsertPolicy.IGNORE,\n });\n return;\n }\n await this.inputs.throughTableManager.insertLinks(this.inputs.ownerPrimaryKey, targetPrimaryKeys, {\n onDuplicate: InternalDuplicateInsertPolicy.IGNORE,\n });\n }\n\n private async deleteTargetPrimaryKeys(targetPrimaryKeys: readonly unknown[]): Promise<void> {\n if (targetPrimaryKeys.length === 0) {\n return;\n }\n if (targetPrimaryKeys.length === 1) {\n await this.inputs.throughTableManager.deleteLink(this.inputs.ownerPrimaryKey, targetPrimaryKeys[0]);\n return;\n }\n await this.inputs.throughTableManager.deleteLinks(this.inputs.ownerPrimaryKey, targetPrimaryKeys);\n }\n\n private resolveTargetPrimaryKeys(targets: readonly ManyToManyTargetRef<TTarget>[]): unknown[] {\n const resolved: unknown[] = [];\n const seen = new Set<string>();\n\n for (const target of targets) {\n const primaryKey = this.resolveTargetPrimaryKey(target);\n const canonical = this.canonicalizePrimaryKey(primaryKey);\n if (seen.has(canonical)) {\n continue;\n }\n seen.add(canonical);\n resolved.push(primaryKey);\n }\n\n return resolved;\n }\n\n private resolveTargetPrimaryKey(target: ManyToManyTargetRef<TTarget>): unknown {\n if (typeof target === 'string' || typeof target === 'number') {\n return target;\n }\n if (typeof target === 'object' && target !== null) {\n const targetPrimaryKey = (target as Record<string, unknown>)[this.inputs.targetPrimaryKeyField];\n if (targetPrimaryKey === undefined || targetPrimaryKey === null) {\n throw new Error(\n `Cannot resolve target primary key '${this.inputs.targetPrimaryKeyField}' for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'.`\n );\n }\n return targetPrimaryKey;\n }\n throw new Error(\n `Unsupported target reference for relation '${this.inputs.relationName}' on '${this.inputs.ownerModelLabel}'. Expected a record, a primary-key carrier, or a primary-key value.`\n );\n }\n\n private canonicalizePrimaryKey(primaryKey: unknown): string {\n switch (typeof primaryKey) {\n case 'string':\n return `string:${primaryKey}`;\n case 'number':\n return `number:${primaryKey}`;\n case 'bigint':\n return `bigint:${String(primaryKey)}`;\n case 'boolean':\n return `boolean:${primaryKey}`;\n default:\n return `json:${JSON.stringify(primaryKey)}`;\n }\n }\n}\n","import { NotFoundError } from '@danceroutine/tango-core';\nimport { ModelRegistry } from '@danceroutine/tango-schema';\nimport type { ModelWriteHooks } from '@danceroutine/tango-schema';\nimport type { Model as SchemaModel } from '@danceroutine/tango-schema/domain';\nimport type { QNode } from '../query/domain/QNode';\nimport type { FilterInput, TableMeta } from '../query/domain/index';\nimport { InternalRelationKind } from '../query/domain/internal/InternalRelationKind';\nimport { InternalQNodeType } from '../query/domain/internal/InternalQNodeType';\nimport { TableMetaFactory } from '../query/domain/TableMetaFactory';\nimport { ModelQuerySet } from '../query/index';\nimport type { QuerySet } from '../query/index';\nimport type { QueryExecutor } from '../query/index';\nimport type { Adapter } from '../connection/adapters/Adapter';\nimport type { TangoRuntime } from '../runtime/TangoRuntime';\nimport { OrmSqlSafetyAdapter } from '../validation';\nimport { InternalSqlValidationPlanKind as SqlPlanKind } from '../validation/internal/InternalSqlValidationPlanKind';\nimport { TransactionEngine } from '../transaction/internal/context';\nimport type { ManagerLike } from './ManagerLike';\nimport { MutationCompiler } from './internal/MutationCompiler';\nimport { RuntimeBoundClient } from './internal/RuntimeBoundClient';\nimport { ManyToManyRelatedManager } from './relations/ManyToManyRelatedManager';\nimport { isQNodeLike } from '../query/internal/isQNodeLike';\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> implements ManagerLike<\n TModelRow,\n 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 adapter: Adapter;\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.adapter = runtime.getAdapter();\n this.mutationCompiler = new MutationCompiler(this.adapter);\n this.queryExecutor = {\n get meta() {\n return ModelManager.createTableMeta(model);\n },\n client: this.client,\n adapter: this.adapter,\n run: async (compiled) => {\n const result = await this.client.query<TModelRow>(compiled.sql, compiled.params);\n return result.rows;\n },\n attachPersistedRecordAccessors: (record, modelKey) => {\n this.attachManyToManyRelatedManagers(record, modelKey ?? this.model.metadata.key);\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 as SchemaModel);\n const validatedMeta = sqlSafetyAdapter.validate({\n kind: SqlPlanKind.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 private static mergeCreatePayloadFromWhere<TModelRow extends Record<string, unknown>>(\n modelName: string,\n pkColumn: string,\n where: FilterInput<TModelRow> | QNode<TModelRow>,\n defaults?: Partial<TModelRow>\n ): Partial<TModelRow> {\n const hasDefaultsArg = defaults !== undefined;\n const providedDefaults = defaults !== undefined ? ({ ...defaults } as Partial<TModelRow>) : undefined;\n\n if (isQNodeLike(where)) {\n if (!hasDefaultsArg || !providedDefaults || Object.keys(providedDefaults).length === 0) {\n throw new Error(`Cannot create ${modelName} from Q filters without defaults.`);\n }\n const fromQ = ModelManager.collectPlainFieldsFromQNode(modelName, where);\n const merged = { ...fromQ, ...providedDefaults };\n const keys = Object.keys(merged).filter((key) => merged[key as keyof TModelRow] !== undefined);\n const nonPkKeys = keys.filter((key) => key !== pkColumn);\n if (nonPkKeys.length === 0) {\n throw new Error(`Cannot create ${modelName} without any values.`);\n }\n return merged;\n }\n\n const atom = where as FilterInput<TModelRow>;\n const entries = Object.entries(atom as Record<string, unknown>);\n const plainEntries = entries.filter(([key]) => !String(key).includes('__'));\n const lookupOnly = entries.length > 0 && plainEntries.length === 0;\n const fromAtom = plainEntries.length > 0 ? (Object.fromEntries(plainEntries) as Partial<TModelRow>) : undefined;\n const mergeBase = { ...fromAtom, ...providedDefaults };\n\n if (lookupOnly && ModelManager.countDefinedValues(mergeBase, pkColumn) === 0) {\n throw new Error(`Cannot create ${modelName} from lookup-only filters without defaults.`);\n }\n\n const cleanedAtom =\n plainEntries.length > 0\n ? (Object.fromEntries(plainEntries) as Partial<TModelRow>)\n : ({} as Partial<TModelRow>);\n const merged = { ...cleanedAtom, ...mergeBase };\n const keys = Object.keys(merged).filter((key) => merged[key as keyof TModelRow] !== undefined);\n const nonPkKeys = keys.filter((key) => key !== pkColumn);\n if (nonPkKeys.length === 0) {\n throw new Error(`Cannot create ${modelName} without any values.`);\n }\n return merged;\n }\n\n private static countDefinedValues<TModelRow extends Record<string, unknown>>(\n payload: Partial<TModelRow>,\n pkColumn: string\n ): number {\n return Object.entries(payload as Record<string, unknown>).filter(\n ([key, value]) => key !== pkColumn && value !== undefined\n ).length;\n }\n\n private static collectPlainFieldsFromQNode<TModelRow extends Record<string, unknown>>(\n modelName: string,\n node: QNode<TModelRow>\n ): Partial<TModelRow> {\n switch (node.kind) {\n case InternalQNodeType.ATOM:\n return ModelManager.omitLookupKeysFromAtom(node.where as FilterInput<TModelRow>);\n case InternalQNodeType.AND: {\n const partials = (node.nodes ?? []).map((child) =>\n ModelManager.collectPlainFieldsFromQNode(modelName, child)\n );\n return ModelManager.mergeCompatiblePartials(partials);\n }\n case InternalQNodeType.OR: {\n const partials = (node.nodes ?? []).map((child) =>\n ModelManager.collectPlainFieldsFromQNode(modelName, child)\n );\n const nonEmpty = partials.filter(\n (partial) => Object.keys(partial as Record<string, unknown>).length > 0\n );\n if (nonEmpty.length > 1) {\n throw new Error(\n `Cannot derive a create payload from ${modelName} OR filters with multiple predicates. Supply defaults that fully describe the insert.`\n );\n }\n return nonEmpty.length === 1 ? nonEmpty[0]! : {};\n }\n case InternalQNodeType.NOT:\n return {};\n }\n }\n\n private static omitLookupKeysFromAtom<TModelRow extends Record<string, unknown>>(\n atom: FilterInput<TModelRow>\n ): Partial<TModelRow> {\n const entries = Object.entries(atom as Record<string, unknown>).filter(([key]) => !String(key).includes('__'));\n return Object.fromEntries(entries) as Partial<TModelRow>;\n }\n\n private static mergeCompatiblePartials<TModelRow extends Record<string, unknown>>(\n partials: Array<Partial<TModelRow>>\n ): Partial<TModelRow> {\n const merged: Partial<TModelRow> = {};\n for (const partial of partials) {\n for (const [key, value] of Object.entries(partial as Record<string, unknown>)) {\n const existing = merged[key as keyof TModelRow];\n if (existing !== undefined && existing !== value) {\n throw new Error(`Conflicting values for '${key}' while deriving create payload from Q filters.`);\n }\n (merged as Record<string, unknown>)[key] = value;\n }\n }\n return merged;\n }\n\n query(): QuerySet<TModelRow, TModelRow, TSourceModel> {\n return new ModelQuerySet<TModelRow, TModelRow, TSourceModel>(this.queryExecutor, {});\n }\n\n all(): QuerySet<TModelRow, TModelRow, TSourceModel> {\n return this.query();\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 getOrCreate(args: {\n where: FilterInput<TModelRow> | QNode<TModelRow>;\n defaults?: Partial<TModelRow>;\n }): Promise<{ record: TModelRow; created: boolean }> {\n try {\n const record = await this.query().get(args.where);\n return { record, created: false };\n } catch (error) {\n if (!NotFoundError.isNotFoundError(error)) {\n throw error;\n }\n }\n\n const merged = ModelManager.mergeCreatePayloadFromWhere(\n this.model.metadata.name,\n this.meta.pk,\n args.where,\n args.defaults\n );\n const record = await this.create(merged);\n return { record, created: true };\n }\n\n async updateOrCreate(args: {\n where: FilterInput<TModelRow> | QNode<TModelRow>;\n defaults?: Partial<TModelRow>;\n update?: Partial<TModelRow>;\n }): Promise<{ record: TModelRow; created: boolean; updated: boolean }> {\n let existing: TModelRow | null = null;\n try {\n existing = await this.query().get(args.where);\n } catch (error) {\n if (!NotFoundError.isNotFoundError(error)) {\n throw error;\n }\n }\n\n if (!existing) {\n const merged = ModelManager.mergeCreatePayloadFromWhere(\n this.model.metadata.name,\n this.meta.pk,\n args.where,\n args.defaults\n );\n const record = await this.create(merged);\n return { record, created: true, updated: false };\n }\n\n const patch = args.update ?? args.defaults ?? {};\n if (Object.keys(patch).length === 0) {\n return { record: existing, created: false, updated: false };\n }\n\n const id = existing[this.meta.pk as keyof TModelRow] as TModelRow[keyof TModelRow];\n const record = await this.update(id, patch);\n return { record, created: false, updated: true };\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: SqlPlanKind.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 this.attachOwnRelatedManagers(created);\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: SqlPlanKind.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 this.attachOwnRelatedManagers(updated);\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 this.attachOwnRelatedManagers(current);\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: SqlPlanKind.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 /**\n * Build a {@link ManyToManyRelatedManager} bound to a single owner record\n * for the supplied many-to-many relation. The returned manager performs\n * its INSERT/DELETE writes through the shared runtime-bound client, so\n * mutations enroll in any active `transaction.atomic(...)` boundary.\n */\n createManyToManyRelatedManager<TTarget extends Record<string, unknown>>(\n relationName: string,\n ownerPrimaryKey: unknown\n ): ManyToManyRelatedManager<TTarget> {\n const relation = this.requireManyToManyEdge(relationName);\n const registry = ModelRegistry.getOwner(this.model as SchemaModel);\n const throughModel = registry.getByKey(relation.throughModelKey!)!;\n return ManyToManyRelatedManager.create<TTarget>({\n ownerPrimaryKey,\n relationName,\n ownerModelLabel: this.model.metadata.name,\n relation,\n throughModelFields: throughModel.metadata.fields,\n client: this.client,\n mutationCompiler: this.mutationCompiler,\n adapter: this.adapter,\n sqlSafetyAdapter,\n targetExecutorProvider: () => this.resolveTargetExecutor<TTarget>(relation.targetModelKey),\n createTarget: async (input) => {\n const targetManager = this.resolveTargetManager<TTarget>(relation.targetModelKey);\n if (!targetManager) {\n throw new Error(\n `Cannot resolve a target manager for relation '${relationName}' on '${this.model.metadata.name}'.`\n );\n }\n return targetManager.create(input);\n },\n runAtomic: (work) => TransactionEngine.forRuntime(this.runtime).atomic(() => work()),\n });\n }\n\n /**\n * Insert multiple rows in a single multi-row INSERT statement.\n *\n * All rows must share the same field set after hook processing. Rows with\n * extra or missing fields relative to the first row will cause an error.\n * If you need to insert rows with different field sets, use individual\n * {@link create} calls instead.\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 this.assertUniformRowShape(batchPrepared, new Set(preparedKeys));\n\n const validatedPlan = sqlSafetyAdapter.validate({\n kind: SqlPlanKind.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 for (const record of result.rows) {\n this.attachOwnRelatedManagers(record);\n }\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 /**\n * Attach a {@link ManyToManyRelatedManager} as a non-enumerable property\n * for every persisted many-to-many relation declared on the supplied\n * record's model. Existing properties are left untouched so that prior\n * hydration writes (such as prefetched arrays) survive the attach pass\n * during the incremental rollout of related-manager hydration.\n */\n private attachOwnRelatedManagers(record: TModelRow): void {\n this.attachManyToManyRelatedManagers(record as unknown as Record<string, unknown>, this.model.metadata.key);\n }\n\n private attachManyToManyRelatedManagers(record: Record<string, unknown>, modelKey: string | undefined): void {\n if (!modelKey) {\n return;\n }\n const targetManager = this.resolveManagerForModelKey(modelKey);\n if (!targetManager) {\n return;\n }\n const meta = targetManager.meta;\n const relations = meta.relations;\n if (!relations) {\n return;\n }\n const ownerPrimaryKey = record[meta.pk];\n if (ownerPrimaryKey === undefined || ownerPrimaryKey === null) {\n return;\n }\n for (const [relationName, relation] of Object.entries(relations)) {\n if (relation.kind !== InternalRelationKind.MANY_TO_MANY) {\n continue;\n }\n if (Object.prototype.hasOwnProperty.call(record, relationName)) {\n continue;\n }\n const relatedManager = targetManager.createManyToManyRelatedManager(relationName, ownerPrimaryKey);\n Object.defineProperty(record, relationName, {\n value: relatedManager,\n writable: true,\n configurable: true,\n /**\n * Non-enumerable so `Object.keys(record)`, `JSON.stringify(record)`,\n * `{ ...record }`, and similar enumeration paths continue to\n * see only the persisted columns. Application code reaches the\n * manager through `record.tags`, never through enumeration.\n */\n enumerable: false,\n });\n }\n }\n\n private resolveManagerForModelKey(modelKey: string): ModelManager<Record<string, unknown>> | null {\n if (modelKey === this.model.metadata.key) {\n return this as unknown as ModelManager<Record<string, unknown>>;\n }\n const registry = ModelRegistry.getOwner(this.model as SchemaModel);\n const otherModel = registry.getByKey(modelKey);\n if (!otherModel) {\n return null;\n }\n const candidate = (otherModel as { objects?: unknown }).objects;\n return ModelManager.isModelManager(candidate) ? (candidate as ModelManager<Record<string, unknown>>) : null;\n }\n\n private resolveTargetExecutor<TTarget extends Record<string, unknown>>(\n targetModelKey: string\n ): QueryExecutor<TTarget> | null {\n const targetManager = this.resolveTargetManager<TTarget>(targetModelKey);\n if (!targetManager) {\n return null;\n }\n return (targetManager as unknown as { queryExecutor: QueryExecutor<TTarget> }).queryExecutor;\n }\n\n private resolveTargetManager<TTarget extends Record<string, unknown>>(\n targetModelKey: string\n ): ModelManager<TTarget> | null {\n const targetManager = this.resolveManagerForModelKey(targetModelKey);\n if (!targetManager) {\n return null;\n }\n return targetManager as unknown as ModelManager<TTarget>;\n }\n\n private requireManyToManyEdge(relationName: string): NonNullable<TableMeta['relations']>[string] {\n const rel = this.meta.relations?.[relationName];\n if (\n !rel ||\n rel.kind !== InternalRelationKind.MANY_TO_MANY ||\n !rel.throughTable ||\n !rel.throughSourceKey ||\n !rel.throughTargetKey ||\n !rel.throughModelKey\n ) {\n throw new Error(\n `Relation '${relationName}' on '${this.model.metadata.name}' is not a persisted many-to-many edge.`\n );\n }\n return rel;\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 private assertUniformRowShape(batch: Partial<TModelRow>[], referenceKeys: Set<string>): void {\n const divergentRows = batch\n .slice(1)\n .map((row, i) => {\n const rowKeys = new Set(Object.keys(row));\n const missing = [...referenceKeys].filter((k) => !rowKeys.has(k)).sort();\n const extra = [...rowKeys].filter((k) => !referenceKeys.has(k)).sort();\n return { index: i + 1, missing, extra };\n })\n .filter((r) => r.missing.length > 0 || r.extra.length > 0);\n\n if (divergentRows.length === 0) {\n return;\n }\n\n const sortedReferenceKeys = [...referenceKeys].sort();\n const indices = divergentRows.map((r) => r.index);\n const details = divergentRows\n .map((r) => {\n const parts: string[] = [];\n if (r.missing.length > 0) {\n parts.push(`missing [${r.missing.join(', ')}]`);\n }\n if (r.extra.length > 0) {\n parts.push(`extra [${r.extra.join(', ')}]`);\n }\n return `Row at index ${r.index}: ${parts.join(', ')}.`;\n })\n .join('\\n');\n\n throw new Error(\n `bulkCreate failed after hook processing: rows at indices [${indices.join(', ')}] have mismatched fields.\\n${details}\\nExpected fields (from row at index 0): [${sortedReferenceKeys.join(', ')}].`\n );\n }\n}\n","import type { z } from 'zod';\nimport type { Model as SchemaModel, ModelWriteHooks } from '@danceroutine/tango-schema/domain';\nimport { registerModelAugmentor } from '@danceroutine/tango-schema';\nimport { ModelManager } from './ModelManager';\nimport type { MaterializedModelRecord } from './relations/MaterializedModelRecord';\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<SchemaModel<TSchema>, 'metadata'> & {\n schema: {\n parse(input: unknown): MaterializedModelRecord<TSchema>;\n };\n hooks?: ModelWriteHooks<MaterializedModelRecord<TSchema>>;\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<MaterializedModelRecord<TSchema>, SchemaModel<TSchema, TKey>>(\n model as unknown as AugmentableSchemaModel<TSchema>,\n runtime\n );\n managerCache.set(model, {\n runtime,\n manager: manager as unknown 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":";;;;;AAmDA,SAAS,WAAwB,MAAyB,OAAkC;CACxF,OAAO,OAAO,UAAU,aAAa,KAAK,IAAI,KAAK,IAAI,KAAK,KAAK,QAAQ,MAAM,MAAM,GAAG,CAAC;AAC7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,4BAAb,MAAa,kCAA2E,SAAkB;CAGjF;CAFrB,YACI,UACA,QACA,QAAgC,CAAC,GACnC;EACE,MAAM,UAAU,KAAK;EAHJ,KAAA,SAAA;CAIrB;CAEA,MAAe,MACX,OACmC;EACnC,IAAI,KAAK,eAAe,GAAG;GACvB,MAAM,QAAQ,KAAK,OAAO,SAAS;GACnC,IAAI,UAAU,MAEV,OAAO,IAAIA,YAD2B,QAAQ,WAAW,OAAO,KAAK,IAAI,CAAC,GAAG,KAAK,CAC/C;EAE3C;EACA,MAAM,MAAM,MAAM,KAAK,OAAO,eAAe;EAC7C,IAAI,IAAI,WAAW,GACf,OAAO,IAAIA,YAAiB,CAAC,CAAC;EAElC,MAAM,WAAW,IAAI,cAAuB,KAAK,UAAU,KAAK,YAAY,GAAG,CAAC;EAChF,OAAO,QAAQ,SAAS,MAAM,KAAK,IAAI,SAAS,MAAM;CAC1D;CAEA,MAAe,SACX,OAC6B;EAE7B,QADe,QAAQ,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,MAAM,GACnD,MAAM,MAAoC;CAC7D;CAEA,MAAe,QAAyB;EACpC,IAAI,KAAK,eAAe,GAAG;GACvB,MAAM,QAAQ,KAAK,OAAO,SAAS;GACnC,IAAI,UAAU,MACV,OAAO,MAAM;EAErB;EACA,MAAM,MAAM,MAAM,KAAK,OAAO,eAAe;EAC7C,IAAI,IAAI,WAAW,GACf,OAAO;EAEX,IAAI,KAAK,eAAe,GACpB,OAAO,IAAI;EAGf,OAAO,IADc,cAAuB,KAAK,UAAU,KAAK,YAAY,GAAG,CACjE,EAAE,MAAM;CAC1B;CAEA,MAGE,OAA2F;EACzF,OAAO,IAAI,0BAAmC,KAAK,UAAU,KAAK,QAAQ,KAAK;CAMnF;CAEA,iBAAkC;EAC9B,OAAO,OAAO,KAAK,KAAK,KAAK,EAAE,WAAW;CAC9C;CAEA,YAAoB,KAA2D;EAC3E,MAAM,WAAiC,GAClC,GAAG,KAAK,OAAO,sBAAsB,QAAQ,CAAC,GAAG,GAAG,EACzD;EACA,MAAM,SAAyB;GAAE,MAAM,kBAAkB;GAAM,OAAO;EAAS;EAC/E,MAAM,SAAS,KAAK,MAAM,IAAIC,SAAE,IAAI,QAAQ,KAAK,MAAM,CAAC,IAAI;EAC5D,OAAO;GAAE,GAAG,KAAK;GAAO,GAAG;EAAO;CACtC;AACJ;;;ACvJA,MAAa,gCAAgC;CACzC,OAAO;CACP,QAAQ;AACZ;;;;AAOA,IAAa,mBAAb,MAA8B;CAC1B;CACA;CAEA,YAAY,SAAkB;EAC1B,KAAK,UAAU;EACf,KAAK,eAAe,QAAQ;CAChC;CAEA,cAAc,MAA8B,QAA2C;EACnF,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,YAAY,KAAK,aAAa,KAAK,KAAK,UAAU,MAAM,EAAE;GAC5H,QAAQ;EACZ;CACJ;CAEA,cAAc,MAA8B,QAA4B,IAA4B;EAChG,MAAM,OAAO,KAAK,UAAU,KAAK,KAAK,UAAU,GAAG,IAAI,KAAK,KAAK,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,IAAI;EACxG,MAAM,aAAa,KAAK,aAAa,GAAG,KAAK,UAAU,SAAS,CAAC;EAEjE,OAAO;GACH,KAAK,UAAU,KAAK,KAAK,MAAM,OAAO,KAAK,SAAS,KAAK,KAAK,GAAG,KAAK,WAAW;GACjF,QAAQ,CAAC,GAAG,QAAQ,EAAE;EAC1B;CACJ;CAEA,cAAc,MAA8B,IAA4B;EACpE,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,SAAS,KAAK,KAAK,GAAG,KAAK,KAAK,aAAa,GAAG,CAAC;GACrF,QAAQ,CAAC,EAAE;EACf;CACJ;CAEA,wBACI,MACA,eACA,gBACA,WACA,YACa;EACb,MAAM,iBAAiB,KAAK,WAAW;EACvC,MAAM,kBAAkB,KAAK,WAAW;EACxC,IAAI,CAAC,kBAAkB,CAAC,iBACpB,MAAM,IAAI,MACN,0DAA0D,cAAc,SAAS,eAAe,yCACpG;EAEJ,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,KAAK,KAAK,aAAa,GACrF,CACJ,EAAE,OAAO,gBAAgB,MAAM,KAAK,KAAK,aAAa,GAAG,CAAC;GAC1D,QAAQ,CAAC,WAAW,UAAU;EAClC;CACJ;CAEA,kBAAkB,MAA8B,WAAiE;EAC7G,MAAM,cAAc,KAAK,UAAU;EACnC,MAAM,eAAe,UAChB,KAAK,MAAM,aAAa,IAAI,KAAK,aAAa,eAAe,aAAa,WAAW,WAAW,EAAE,EAAE,EACpG,KAAK,IAAI;EAEd,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,WAAW,aAAa;GAC1F,QAAQ,UAAU,KAAK;EAC3B;CACJ;CAEA,uBACI,MACA,WACA,WACA,YACA,cACA,iBACa;EACb,MAAM,YAAY,aAAa,KAAK,gBAAgB,CAAC,YAAY,WAAW,CAAC;EAC7E,MAAM,eAAe,UAChB,KAAK,MAAM,aAAa,IAAI,KAAK,aAAa,eAAe,GAAG,WAAW,CAAC,EAAE,EAAE,EAChF,KAAK,IAAI;EACd,MAAM,SAAS,UAAU,KAAK;EAE9B,IAAI,oBAAoB,8BAA8B,QAClD,QAAQ,KAAK,QAAQ,SAArB;GACI,KAAK,YACD,OAAO;IACH,KAAK,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,WAAW,aAAa,gBAAgB,UAAU,IAAI,UAAU;IAClI;GACJ;GACJ,KAAK,UACD,OAAO;IACH,KAAK,yBAAyB,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,WAAW;IACvF;GACJ;EACR;EAGJ,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU,KAAK,IAAI,EAAE,WAAW;GAC7E;EACJ;CACJ;CAEA,uBACI,MACA,eACA,gBACA,WACA,aACa;EACb,MAAM,iBAAiB,KAAK,WAAW;EACvC,MAAM,kBAAkB,KAAK,WAAW;EACxC,IAAI,CAAC,kBAAkB,CAAC,iBACpB,MAAM,IAAI,MACN,yDAAyD,cAAc,SAAS,eAAe,yCACnG;EAEJ,IAAI,YAAY,WAAW,GACvB,MAAM,IAAI,MAAM,6EAA6E;EAEjG,IAAI,YAAY,WAAW,GACvB,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,KAAK,KAAK,aAAa,GACrF,CACJ,EAAE,OAAO,gBAAgB,MAAM,KAAK,KAAK,aAAa,GAAG,CAAC;GAC1D,QAAQ,CAAC,WAAW,YAAY,EAAE;EACtC;EAGJ,OAAO;GACH,KAAK,eAAe,KAAK,KAAK,MAAM,SAAS,eAAe,MAAM,KAAK,KAAK,aAAa,GACrF,CACJ,EAAE,OAAO,gBAAgB,MAAM,OAAO,KAAK,aAAa,eAAe,YAAY,QAAQ,CAAC,EAAE;GAC9F,QAAQ,CAAC,WAAW,GAAG,WAAW;EACtC;CACJ;AACJ;;;;;;;;;ACvGA,IAAa,sBAAb,MAAa,oBAAoB;CAER;CACA;CACA;CACA;CACA;CALrB,YACI,QACA,kBACA,YACA,SACA,mBAAyD,IAAI,oBAAoB,GACnF;EALmB,KAAA,SAAA;EACA,KAAA,mBAAA;EACA,KAAA,aAAA;EACA,KAAA,UAAA;EACA,KAAA,mBAAA;CAClB;;;;;CAMH,OAAO,oBACH,UACA,oBAC0B;EAC1B,IAAI,CAAC,SAAS,gBAAgB,CAAC,SAAS,oBAAoB,CAAC,SAAS,kBAClE,MAAM,IAAI,MACN,qGACJ;EAGJ,MAAM,kBAAkB,mBAAmB,MAAM,UAAU,MAAM,UAAU;EAC3E,IAAI,CAAC,iBACD,MAAM,IAAI,MAAM,wDAAwD;EAG5E,OAAO;GACH,OAAO,SAAS;GAChB,YAAY,gBAAgB;GAC5B,SAAS,OAAO,YAAY,mBAAmB,KAAK,UAAU,CAAC,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC;GACvF,cAAc,SAAS;GACvB,cAAc,SAAS;EAC3B;CACJ;;;;;;CAOA,OAAO,aAAa,QAAoE;EACpF,OAAO,IAAI,oBACP,OAAO,QACP,OAAO,kBACP,oBAAoB,oBAAoB,OAAO,UAAU,OAAO,kBAAkB,GAClF,OAAO,SACP,OAAO,gBACX;CACJ;;;;;;CAOA,MAAM,wBAAwB,iBAAiE;EAC3F,MAAM,YAAY,KAAK,iBAAiB,SAAS;GAC7C,MAAMC,8BAAY;GAClB,MAAM;IACF,OAAO,KAAK,WAAW;IACvB,IAAI,KAAK,WAAW;IACpB,SAAS,KAAK,WAAW;GAC7B;GACA,YAAY,CAAC,KAAK,WAAW,cAAc,KAAK,WAAW,YAAY;EAC3E,CAAC;EACD,MAAM,eAAe,UAAU,WAAW,KAAK,WAAW,cAAe;EACzE,MAAM,eAAe,UAAU,WAAW,KAAK,WAAW,cAAe;EACzE,MAAM,cAAc,KAAK,QAAQ,aAAa,GAAG,CAAC;EAClD,MAAM,MAAM,UAAU,aAAa,qBAAqB,UAAU,KAAK,MAAM,SAAS,aAAa,KAAK;EAExG,QAAO,MADc,KAAK,OAAO,MAAsC,KAAK,CAAC,eAAe,CAAC,GAC/E,KACT,KAAK,QAAQ,IAAI,SAAS,EAC1B,QAAQ,UAAoC,OAAO,UAAU,YAAY,OAAO,UAAU,QAAQ;CAC3G;CAEA,MAAM,WACF,iBACA,kBACA,UAA6B,CAAC,GACjB;EACb,MAAM,KAAK,YAAY,iBAAiB,CAAC,gBAAgB,GAAG,OAAO;CACvE;CAEA,MAAM,YACF,iBACA,mBACA,UAA6B,CAAC,GACjB;EACb,IAAI,kBAAkB,WAAW,GAC7B;EAEJ,MAAM,gBAAgB,KAAK,iBAAiB,SAAS;GACjD,MAAMA,8BAAY;GAClB,MAAM;IACF,OAAO,KAAK,WAAW;IACvB,IAAI,KAAK,WAAW;IACpB,SAAS,KAAK,WAAW;GAC7B;GACA,WAAW,CAAC,KAAK,WAAW,cAAc,KAAK,WAAW,YAAY;EAC1E,CAAC;EACD,MAAM,kBAAkB,QAAQ,eAAe,8BAA8B;EAC7E,IAAI,oBAAoB,8BAA8B,UAAU,CAAC,KAAK,QAAQ,SAAS,uBACnF,MAAM,IAAI,MACN,YAAY,KAAK,QAAQ,KAAK,0EAClC;EAEJ,MAAM,WAAW,KAAK,iBAAiB,uBACnC,eACA,KAAK,WAAW,cAChB,KAAK,WAAW,cAChB,iBACA,mBACA,eACJ;EACA,MAAM,KAAK,OAAO,MAAM,SAAS,KAAK,SAAS,MAAM;CACzD;CAEA,MAAM,WAAW,iBAA0B,kBAA0C;EACjF,MAAM,KAAK,YAAY,iBAAiB,CAAC,gBAAgB,CAAC;CAC9D;CAEA,MAAM,YAAY,iBAA0B,mBAAsD;EAC9F,IAAI,kBAAkB,WAAW,GAC7B;EAEJ,MAAM,YAAY,KAAK,iBAAiB,SAAS;GAC7C,MAAMA,8BAAY;GAClB,MAAM;IACF,OAAO,KAAK,WAAW;IACvB,IAAI,KAAK,WAAW;IACpB,SAAS,KAAK,WAAW;GAC7B;GACA,YAAY,CAAC,KAAK,WAAW,cAAc,KAAK,WAAW,YAAY;EAC3E,CAAC;EACD,MAAM,WAAW,KAAK,iBAAiB,uBACnC,WACA,KAAK,WAAW,cAChB,KAAK,WAAW,cAChB,iBACA,iBACJ;EACA,MAAM,KAAK,OAAO,MAAM,SAAS,KAAK,SAAS,MAAM;CACzD;;;;;;CAOA,MAAM,uBAAuB,iBAAyC;EAClE,MAAM,YAAY,KAAK,iBAAiB,SAAS;GAC7C,MAAMA,8BAAY;GAClB,MAAM;IACF,OAAO,KAAK,WAAW;IACvB,IAAI,KAAK,WAAW;IACpB,SAAS,KAAK,WAAW;GAC7B;GACA,YAAY,CAAC,KAAK,WAAW,YAAY;EAC7C,CAAC;EACD,MAAM,eAAe,UAAU,WAAW,KAAK,WAAW,cAAe;EACzE,MAAM,cAAc,KAAK,QAAQ,aAAa,GAAG,CAAC;EAClD,MAAM,MAAM,eAAe,UAAU,KAAK,MAAM,SAAS,aAAa,KAAK;EAC3E,MAAM,KAAK,OAAO,MAAM,KAAK,CAAC,eAAe,CAAC;CAClD;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;AC7HA,IAAa,2BAAb,MAAa,yBAAkE;CAa9C;CAZ7B,OAAwB,QAAQ;CAChC,eAA+D,yBAAyB;CAExF,gBAAmD;;;;;;;;CASnD,YAAY,QAA0E;EAAzD,KAAA,SAAA;CAA0D;;;;CAKvF,OAAO,2BACH,OAC0C;EAC1C,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,yBAAyB;CAExF;;;;;;;;;CAUA,OAAO,OACH,QACiC;EACjC,MAAM,sBAAsB,oBAAoB,aAAa;GACzD,UAAU,OAAO;GACjB,oBAAoB,OAAO;GAC3B,QAAQ,OAAO;GACf,kBAAkB,OAAO;GACzB,SAAS,OAAO;GAChB,kBAAkB,OAAO;EAC7B,CAAC;EACD,OAAO,IAAI,yBAAkC;GACzC,iBAAiB,OAAO;GACxB,cAAc,OAAO;GACrB,iBAAiB,OAAO;GACxB,uBAAuB,OAAO,SAAS;GACvC;GACA,wBAAwB,OAAO;GAC/B,cAAc,OAAO;GACrB,WAAW,OAAO;EACtB,CAAC;CACL;;;;;;;CAQA,MAAM,IAAI,GAAG,SAAwD;EACjE,MAAM,oBAAoB,KAAK,yBAAyB,OAAO;EAC/D,IAAI,kBAAkB,WAAW,GAC7B;EAGJ,IAAI,kBAAkB,WAAW,GAC7B,MAAM,KAAK,wBAAwB,iBAAiB;OAEpD,MAAM,KAAK,OAAO,gBAAgB,KAAK,wBAAwB,iBAAiB,CAAC;EAErF,KAAK,gBAAgB;CACzB;;;;;;CAOA,MAAM,OAAO,GAAG,SAAwD;EACpE,MAAM,oBAAoB,KAAK,yBAAyB,OAAO;EAC/D,IAAI,kBAAkB,WAAW,GAC7B;EAGJ,IAAI,kBAAkB,WAAW,GAC7B,MAAM,KAAK,wBAAwB,iBAAiB;OAEpD,MAAM,KAAK,OAAO,gBAAgB,KAAK,wBAAwB,iBAAiB,CAAC;EAErF,KAAK,gBAAgB;CACzB;;;;;CAMA,MAAM,QAAuB;EACzB,MAAM,KAAK,OAAO,oBAAoB,uBAAuB,KAAK,OAAO,eAAe;EACxF,KAAK,gBAAgB;CACzB;;;;;;;CAQA,MAAM,OAAO,OAA2C;EACpD,MAAM,UAAU,MAAM,KAAK,OAAO,UAAU,YAAY;GACpD,MAAM,SAAS,MAAM,KAAK,OAAO,aAAa,KAAK;GACnD,MAAM,mBAAmB,KAAK,wBAAwB,MAAM;GAC5D,MAAM,KAAK,wBAAwB,CAAC,gBAAgB,CAAC;GACrD,OAAO;EACX,CAAC;EACD,KAAK,gBAAgB;EACrB,OAAO;CACX;;;;;;;;;;CAWA,MAAM,IAAI,GAAG,SAAwD;EACjE,MAAM,wBAAwB,KAAK,yBAAyB,OAAO;EACnE,MAAM,2BAA2B,MAAM,KAAK,OAAO,oBAAoB,wBACnE,KAAK,OAAO,eAChB;EACA,MAAM,mBAAmB,IAAI,IACzB,yBAAyB,KAAK,eAAe,KAAK,uBAAuB,UAAU,CAAC,CACxF;EACA,MAAM,gBAAgB,IAAI,IACtB,sBAAsB,KAAK,eAAe,KAAK,uBAAuB,UAAU,CAAC,CACrF;EACA,MAAM,4BAA4B,yBAAyB,QACtD,eAAe,CAAC,cAAc,IAAI,KAAK,uBAAuB,UAAU,CAAC,CAC9E;EACA,MAAM,yBAAyB,sBAAsB,QAChD,eAAe,CAAC,iBAAiB,IAAI,KAAK,uBAAuB,UAAU,CAAC,CACjF;EAEA,IAAI,0BAA0B,WAAW,KAAK,uBAAuB,WAAW,GAC5E;EAGJ,MAAM,KAAK,OAAO,UAAU,YAAY;GACpC,MAAM,KAAK,wBAAwB,yBAAyB;GAC5D,MAAM,KAAK,wBAAwB,sBAAsB;EAC7D,CAAC;EACD,KAAK,gBAAgB;CACzB;;;;;;;;CASA,MAAyB;EACrB,MAAM,WAAW,KAAK,OAAO,uBAAuB;EACpD,IAAI,CAAC,UACD,MAAM,IAAI,MACN,wDAAwD,KAAK,OAAO,aAAa,QAAQ,KAAK,OAAO,gBAAgB,GACzH;EAEJ,OAAO,IAAI,0BAAmC,UAAU;GACpD,gBAAgB,KAAK;GACrB,sBAAsB,KAAK,OAAO,oBAAoB,wBAAwB,KAAK,OAAO,eAAe;GACzG,uBAAuB,KAAK,OAAO;EACvC,CAAC;CACL;;;;;;CAOA,mBAAmB,SAAmC;EAClD,KAAK,gBAAgB,CAAC,GAAG,OAAO;CACpC;;;;;CAMA,kBAAwB;EACpB,KAAK,gBAAgB;CACzB;;;;;;CAOA,gBAA2C;EACvC,OAAO,KAAK,gBAAgB,CAAC,GAAG,KAAK,aAAa,IAAI;CAC1D;CAEA,MAAc,wBAAwB,mBAAsD;EACxF,IAAI,kBAAkB,WAAW,GAC7B;EAEJ,IAAI,kBAAkB,WAAW,GAAG;GAChC,MAAM,KAAK,OAAO,oBAAoB,WAAW,KAAK,OAAO,iBAAiB,kBAAkB,IAAI,EAChG,aAAa,8BAA8B,OAC/C,CAAC;GACD;EACJ;EACA,MAAM,KAAK,OAAO,oBAAoB,YAAY,KAAK,OAAO,iBAAiB,mBAAmB,EAC9F,aAAa,8BAA8B,OAC/C,CAAC;CACL;CAEA,MAAc,wBAAwB,mBAAsD;EACxF,IAAI,kBAAkB,WAAW,GAC7B;EAEJ,IAAI,kBAAkB,WAAW,GAAG;GAChC,MAAM,KAAK,OAAO,oBAAoB,WAAW,KAAK,OAAO,iBAAiB,kBAAkB,EAAE;GAClG;EACJ;EACA,MAAM,KAAK,OAAO,oBAAoB,YAAY,KAAK,OAAO,iBAAiB,iBAAiB;CACpG;CAEA,yBAAiC,SAA6D;EAC1F,MAAM,WAAsB,CAAC;EAC7B,MAAM,uBAAO,IAAI,IAAY;EAE7B,KAAK,MAAM,UAAU,SAAS;GAC1B,MAAM,aAAa,KAAK,wBAAwB,MAAM;GACtD,MAAM,YAAY,KAAK,uBAAuB,UAAU;GACxD,IAAI,KAAK,IAAI,SAAS,GAClB;GAEJ,KAAK,IAAI,SAAS;GAClB,SAAS,KAAK,UAAU;EAC5B;EAEA,OAAO;CACX;CAEA,wBAAgC,QAA+C;EAC3E,IAAI,OAAO,WAAW,YAAY,OAAO,WAAW,UAChD,OAAO;EAEX,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;GAC/C,MAAM,mBAAoB,OAAmC,KAAK,OAAO;GACzE,IAAI,qBAAqB,KAAA,KAAa,qBAAqB,MACvD,MAAM,IAAI,MACN,sCAAsC,KAAK,OAAO,sBAAsB,kBAAkB,KAAK,OAAO,aAAa,QAAQ,KAAK,OAAO,gBAAgB,GAC3J;GAEJ,OAAO;EACX;EACA,MAAM,IAAI,MACN,8CAA8C,KAAK,OAAO,aAAa,QAAQ,KAAK,OAAO,gBAAgB,qEAC/G;CACJ;CAEA,uBAA+B,YAA6B;EACxD,QAAQ,OAAO,YAAf;GACI,KAAK,UACD,OAAO,UAAU;GACrB,KAAK,UACD,OAAO,UAAU;GACrB,KAAK,UACD,OAAO,UAAU,OAAO,UAAU;GACtC,KAAK,WACD,OAAO,WAAW;GACtB,SACI,OAAO,QAAQ,KAAK,UAAU,UAAU;EAChD;CACJ;AACJ;;;ACjWA,MAAM,mBAAmB,IAAI,oBAAoB;;;;AAuBjD,IAAa,eAAb,MAAa,aAGX;CACE,OAAgB,QAAQ;CACxB,eAAmD,aAAa;CAChE;CACA;CACA;CACA;CACA;CACA;CAEA,YAAY,OAA6B,SAAuB;EAC5D,KAAK,QAAQ;EACb,KAAK,UAAU;EACf,KAAK,SAAS,IAAI,mBAAmB,OAAO;EAC5C,KAAK,UAAU,QAAQ,WAAW;EAClC,KAAK,mBAAmB,IAAI,iBAAiB,KAAK,OAAO;EACzD,KAAK,gBAAgB;GACjB,IAAI,OAAO;IACP,OAAO,aAAa,gBAAgB,KAAK;GAC7C;GACA,QAAQ,KAAK;GACb,SAAS,KAAK;GACd,KAAK,OAAO,aAAa;IAErB,QAAO,MADc,KAAK,OAAO,MAAiB,SAAS,KAAK,SAAS,MAAM,GACjE;GAClB;GACA,iCAAiC,QAAQ,aAAa;IAClD,KAAK,gCAAgC,QAAQ,YAAY,KAAK,MAAM,SAAS,GAAG;GACpF;EACJ;CACJ;CAEA,IAAI,OAAkB;EAClB,OAAO,aAAa,gBAAgB,KAAK,KAAK;CAClD;;;;CAKA,OAAO,eAA0D,OAAkD;EAC/G,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,aAAa;CAE5E;CAEA,OAAe,gBAA2D,OAAwC;EAC9G,MAAM,UAAU,iBAAiB,OAAO,KAAoB;EAC5D,MAAM,gBAAgB,iBAAiB,SAAS;GAC5C,MAAMC,8BAAY;GAClB,MAAM;GACN,WAAW,OAAO,KAAK,QAAQ,OAAO;EAC1C,CAAC,EAAE;EAEH,IAAI,QAAQ,WACR,cAAc,YAAY,QAAQ;EAGtC,OAAO;CACX;CAEA,OAAe,4BACX,WACA,UACA,OACA,UACkB;EAClB,MAAM,iBAAiB,aAAa,KAAA;EACpC,MAAM,mBAAmB,aAAa,KAAA,IAAa,EAAE,GAAG,SAAS,IAA2B,KAAA;EAE5F,IAAI,YAAY,KAAK,GAAG;GACpB,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,OAAO,KAAK,gBAAgB,EAAE,WAAW,GACjF,MAAM,IAAI,MAAM,iBAAiB,UAAU,kCAAkC;GAGjF,MAAM,SAAS;IAAE,GADH,aAAa,4BAA4B,WAAW,KAC1C;IAAG,GAAG;GAAiB;GAG/C,IAFa,OAAO,KAAK,MAAM,EAAE,QAAQ,QAAQ,OAAO,SAA4B,KAAA,CAC/D,EAAE,QAAQ,QAAQ,QAAQ,QACnC,EAAE,WAAW,GACrB,MAAM,IAAI,MAAM,iBAAiB,UAAU,qBAAqB;GAEpE,OAAO;EACX;EAGA,MAAM,UAAU,OAAO,QAAQC,KAA+B;EAC9D,MAAM,eAAe,QAAQ,QAAQ,CAAC,SAAS,CAAC,OAAO,GAAG,EAAE,SAAS,IAAI,CAAC;EAC1E,MAAM,aAAa,QAAQ,SAAS,KAAK,aAAa,WAAW;EAEjE,MAAM,YAAY;GAAE,GADH,aAAa,SAAS,IAAK,OAAO,YAAY,YAAY,IAA2B,KAAA;GACrE,GAAG;EAAiB;EAErD,IAAI,cAAc,aAAa,mBAAmB,WAAW,QAAQ,MAAM,GACvE,MAAM,IAAI,MAAM,iBAAiB,UAAU,4CAA4C;EAO3F,MAAM,SAAS;GAAE,GAHb,aAAa,SAAS,IACf,OAAO,YAAY,YAAY,IAC/B,CAAC;GACqB,GAAG;EAAU;EAG9C,IAFa,OAAO,KAAK,MAAM,EAAE,QAAQ,QAAQ,OAAO,SAA4B,KAAA,CAC/D,EAAE,QAAQ,QAAQ,QAAQ,QACnC,EAAE,WAAW,GACrB,MAAM,IAAI,MAAM,iBAAiB,UAAU,qBAAqB;EAEpE,OAAO;CACX;CAEA,OAAe,mBACX,SACA,UACM;EACN,OAAO,OAAO,QAAQ,OAAkC,EAAE,QACrD,CAAC,KAAK,WAAW,QAAQ,YAAY,UAAU,KAAA,CACpD,EAAE;CACN;CAEA,OAAe,4BACX,WACA,MACkB;EAClB,QAAQ,KAAK,MAAb;GACI,KAAK,kBAAkB,MACnB,OAAO,aAAa,uBAAuB,KAAK,KAA+B;GACnF,KAAK,kBAAkB,KAAK;IACxB,MAAM,YAAY,KAAK,SAAS,CAAC,GAAG,KAAK,UACrC,aAAa,4BAA4B,WAAW,KAAK,CAC7D;IACA,OAAO,aAAa,wBAAwB,QAAQ;GACxD;GACA,KAAK,kBAAkB,IAAI;IAIvB,MAAM,YAHY,KAAK,SAAS,CAAC,GAAG,KAAK,UACrC,aAAa,4BAA4B,WAAW,KAAK,CAErC,EAAE,QACrB,YAAY,OAAO,KAAK,OAAkC,EAAE,SAAS,CAC1E;IACA,IAAI,SAAS,SAAS,GAClB,MAAM,IAAI,MACN,uCAAuC,UAAU,sFACrD;IAEJ,OAAO,SAAS,WAAW,IAAI,SAAS,KAAM,CAAC;GACnD;GACA,KAAK,kBAAkB,KACnB,OAAO,CAAC;EAChB;CACJ;CAEA,OAAe,uBACX,MACkB;EAClB,MAAM,UAAU,OAAO,QAAQ,IAA+B,EAAE,QAAQ,CAAC,SAAS,CAAC,OAAO,GAAG,EAAE,SAAS,IAAI,CAAC;EAC7G,OAAO,OAAO,YAAY,OAAO;CACrC;CAEA,OAAe,wBACX,UACkB;EAClB,MAAM,SAA6B,CAAC;EACpC,KAAK,MAAM,WAAW,UAClB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAkC,GAAG;GAC3E,MAAM,WAAW,OAAO;GACxB,IAAI,aAAa,KAAA,KAAa,aAAa,OACvC,MAAM,IAAI,MAAM,2BAA2B,IAAI,gDAAgD;GAEnG,OAAoC,OAAO;EAC/C;EAEJ,OAAO;CACX;CAEA,QAAsD;EAClD,OAAO,IAAI,cAAkD,KAAK,eAAe,CAAC,CAAC;CACvF;CAEA,MAAoD;EAChD,OAAO,KAAK,MAAM;CACtB;CAEA,MAAM,SAAS,IAA2D;EACtE,MAAM,SAAS,GAAG,KAAK,KAAK,KAAK,GAAG;EACpC,OAAO,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,SAAS;CAChD;CAEA,MAAM,WAAW,IAAoD;EACjE,MAAM,SAAS,MAAM,KAAK,SAAS,EAAE;EACrC,IAAI,CAAC,QACD,MAAM,IAAI,cAAc,GAAG,KAAK,MAAM,SAAS,KAAK,QAAQ,KAAK,KAAK,GAAG,GAAG,OAAO,EAAE,EAAE,WAAW;EAEtG,OAAO;CACX;CAEA,MAAM,YAAY,MAGmC;EACjD,IAAI;GAEA,OAAO;IAAE,QAAA,MADY,KAAK,MAAM,EAAE,IAAI,KAAK,KAAK;IAC/B,SAAS;GAAM;EACpC,SAAS,OAAO;GACZ,IAAI,CAAC,cAAc,gBAAgB,KAAK,GACpC,MAAM;EAEd;EAEA,MAAM,SAAS,aAAa,4BACxB,KAAK,MAAM,SAAS,MACpB,KAAK,KAAK,IACV,KAAK,OACL,KAAK,QACT;EAEA,OAAO;GAAE,QAAA,MADY,KAAK,OAAO,MAAM;GACtB,SAAS;EAAK;CACnC;CAEA,MAAM,eAAe,MAIkD;EACnE,IAAI,WAA6B;EACjC,IAAI;GACA,WAAW,MAAM,KAAK,MAAM,EAAE,IAAI,KAAK,KAAK;EAChD,SAAS,OAAO;GACZ,IAAI,CAAC,cAAc,gBAAgB,KAAK,GACpC,MAAM;EAEd;EAEA,IAAI,CAAC,UAAU;GACX,MAAM,SAAS,aAAa,4BACxB,KAAK,MAAM,SAAS,MACpB,KAAK,KAAK,IACV,KAAK,OACL,KAAK,QACT;GAEA,OAAO;IAAE,QAAA,MADY,KAAK,OAAO,MAAM;IACtB,SAAS;IAAM,SAAS;GAAM;EACnD;EAEA,MAAM,QAAQ,KAAK,UAAU,KAAK,YAAY,CAAC;EAC/C,IAAI,OAAO,KAAK,KAAK,EAAE,WAAW,GAC9B,OAAO;GAAE,QAAQ;GAAU,SAAS;GAAO,SAAS;EAAM;EAG9D,MAAM,KAAK,SAAS,KAAK,KAAK;EAE9B,OAAO;GAAE,QAAA,MADY,KAAK,OAAO,IAAI,KAAK;GACzB,SAAS;GAAO,SAAS;EAAK;CACnD;CAEA,MAAM,OAAO,OAA+C;EACxD,MAAM,WAAW,MAAM,KAAK,gBAAgB,KAAK;EACjD,MAAM,eAAe,OAAO,KAAK,QAAQ;EACzC,IAAI,aAAa,WAAW,GACxB,MAAM,IAAI,MAAM,iBAAiB,KAAK,MAAM,SAAS,KAAK,qBAAqB;EAGnF,MAAM,gBAAgB,iBAAiB,SAAS;GAC5C,MAAMD,8BAAY;GAClB,MAAM,KAAK;GACX,WAAW;EACf,CAAC;EACD,MAAM,WAAW,KAAK,iBAAiB,cACnC,eACA,aAAa,KAAK,QAAQ,SAAS,IAAuB,CAC9D;EAEA,MAAM,WAAU,MADK,KAAK,cAAc,OAAO,MAAiB,SAAS,KAAK,SAAS,MAAM,GACtE,KAAK;EAC5B,KAAK,yBAAyB,OAAO;EACrC,MAAM,KAAK,MAAM,OAAO,cAAc;GAClC,QAAQ;GACR,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC;EACD,OAAO;CACX;CAEA,MAAM,OAAO,IAAgC,OAA+C;EACxF,MAAM,UAAU,MAAM,KAAK,WAAW,EAAE;EACxC,MAAM,WAAW,MAAM,KAAK,gBAAgB,IAAI,OAAO,OAAO;EAC9D,MAAM,eAAe,OAAO,KAAK,QAAQ;EACzC,IAAI,aAAa,WAAW,GACxB,MAAM,IAAI,MAAM,iBAAiB,KAAK,MAAM,SAAS,KAAK,qBAAqB;EAGnF,MAAM,gBAAgB,iBAAiB,SAAS;GAC5C,MAAMA,8BAAY;GAClB,MAAM,KAAK;GACX,WAAW;EACf,CAAC;EACD,MAAM,WAAW,KAAK,iBAAiB,cACnC,eACA,aAAa,KAAK,QAAQ,SAAS,IAAuB,GAC1D,EACJ;EAEA,MAAM,WAAU,MADK,KAAK,cAAc,OAAO,MAAiB,SAAS,KAAK,SAAS,MAAM,GACtE,KAAK;EAC5B,KAAK,yBAAyB,OAAO;EACrC,MAAM,KAAK,MAAM,OAAO,cAAc;GAClC;GACA,OAAO;GACP,UAAU;GACV,QAAQ;GACR,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC;EACD,OAAO;CACX;CAEA,MAAM,OAAO,IAA+C;EACxD,MAAM,UAAU,MAAM,KAAK,WAAW,EAAE;EACxC,KAAK,yBAAyB,OAAO;EACrC,MAAM,KAAK,MAAM,OAAO,eAAe;GACnC;GACA;GACA,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC;EACD,MAAM,gBAAgB,iBAAiB,SAAS;GAC5C,MAAMA,8BAAY;GAClB,MAAM,KAAK;EACf,CAAC;EACD,MAAM,WAAW,KAAK,iBAAiB,cAAc,eAAe,EAAE;EACtE,MAAM,KAAK,cAAc,OAAO,MAAM,SAAS,KAAK,SAAS,MAAM;EACnE,MAAM,KAAK,MAAM,OAAO,cAAc;GAClC;GACA,UAAU;GACV,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC;CACL;;;;;;;CAQA,+BACI,cACA,iBACiC;EACjC,MAAM,WAAW,KAAK,sBAAsB,YAAY;EAExD,MAAM,eADW,cAAc,SAAS,KAAK,KACjB,EAAE,SAAS,SAAS,eAAgB;EAChE,OAAO,yBAAyB,OAAgB;GAC5C;GACA;GACA,iBAAiB,KAAK,MAAM,SAAS;GACrC;GACA,oBAAoB,aAAa,SAAS;GAC1C,QAAQ,KAAK;GACb,kBAAkB,KAAK;GACvB,SAAS,KAAK;GACd;GACA,8BAA8B,KAAK,sBAA+B,SAAS,cAAc;GACzF,cAAc,OAAO,UAAU;IAC3B,MAAM,gBAAgB,KAAK,qBAA8B,SAAS,cAAc;IAChF,IAAI,CAAC,eACD,MAAM,IAAI,MACN,iDAAiD,aAAa,QAAQ,KAAK,MAAM,SAAS,KAAK,GACnG;IAEJ,OAAO,cAAc,OAAO,KAAK;GACrC;GACA,YAAY,SAAS,kBAAkB,WAAW,KAAK,OAAO,EAAE,aAAa,KAAK,CAAC;EACvF,CAAC;CACL;;;;;;;;;CAUA,MAAM,WAAW,QAAoD;EACjE,IAAI,OAAO,WAAW,GAClB,OAAO,CAAC;EAGZ,MAAM,iBAAiB,MAAM,QAAQ,IAAI,OAAO,KAAK,UAAU,KAAK,gBAAgB,KAAK,CAAC,CAAC;EAC3F,MAAM,gBACD,MAAM,KAAK,MAAM,OAAO,mBAAmB;GACxC,MAAM;GACN,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC,KAAM;EACX,MAAM,eAAe,OAAO,KAAK,cAAc,MAAM,CAAC,CAAC;EACvD,IAAI,aAAa,WAAW,GACxB,MAAM,IAAI,MAAM,iBAAiB,KAAK,MAAM,SAAS,KAAK,qBAAqB;EAEnF,KAAK,sBAAsB,eAAe,IAAI,IAAI,YAAY,CAAC;EAE/D,MAAM,gBAAgB,iBAAiB,SAAS;GAC5C,MAAMA,8BAAY;GAClB,MAAM,KAAK;GACX,WAAW;EACf,CAAC;EACD,MAAM,YAAY,cAAc,KAAK,UAAU,aAAa,KAAK,QAAQ,MAAM,IAAuB,CAAC;EACvG,MAAM,WAAW,KAAK,iBAAiB,kBAAkB,eAAe,SAAS;EACjF,MAAM,SAAS,MAAM,KAAK,cAAc,OAAO,MAAiB,SAAS,KAAK,SAAS,MAAM;EAC7F,KAAK,MAAM,UAAU,OAAO,MACxB,KAAK,yBAAyB,MAAM;EAExC,MAAM,QAAQ,IACV,OAAO,KAAK,KAAK,WACb,KAAK,MAAM,OAAO,cAAc;GAC5B;GACA,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC,CACL,CACJ;EACA,MAAM,KAAK,MAAM,OAAO,kBAAkB;GACtC,SAAS,OAAO;GAChB,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC;EACD,OAAO,OAAO;CAClB;;;;;;;;CASA,yBAAiC,QAAyB;EACtD,KAAK,gCAAgC,QAA8C,KAAK,MAAM,SAAS,GAAG;CAC9G;CAEA,gCAAwC,QAAiC,UAAoC;EACzG,IAAI,CAAC,UACD;EAEJ,MAAM,gBAAgB,KAAK,0BAA0B,QAAQ;EAC7D,IAAI,CAAC,eACD;EAEJ,MAAM,OAAO,cAAc;EAC3B,MAAM,YAAY,KAAK;EACvB,IAAI,CAAC,WACD;EAEJ,MAAM,kBAAkB,OAAO,KAAK;EACpC,IAAI,oBAAoB,KAAA,KAAa,oBAAoB,MACrD;EAEJ,KAAK,MAAM,CAAC,cAAc,aAAa,OAAO,QAAQ,SAAS,GAAG;GAC9D,IAAI,SAAS,SAAS,qBAAqB,cACvC;GAEJ,IAAI,OAAO,UAAU,eAAe,KAAK,QAAQ,YAAY,GACzD;GAEJ,MAAM,iBAAiB,cAAc,+BAA+B,cAAc,eAAe;GACjG,OAAO,eAAe,QAAQ,cAAc;IACxC,OAAO;IACP,UAAU;IACV,cAAc;;;;;;;IAOd,YAAY;GAChB,CAAC;EACL;CACJ;CAEA,0BAAkC,UAAgE;EAC9F,IAAI,aAAa,KAAK,MAAM,SAAS,KACjC,OAAO;EAGX,MAAM,aADW,cAAc,SAAS,KAAK,KACnB,EAAE,SAAS,QAAQ;EAC7C,IAAI,CAAC,YACD,OAAO;EAEX,MAAM,YAAa,WAAqC;EACxD,OAAO,aAAa,eAAe,SAAS,IAAK,YAAsD;CAC3G;CAEA,sBACI,gBAC6B;EAC7B,MAAM,gBAAgB,KAAK,qBAA8B,cAAc;EACvE,IAAI,CAAC,eACD,OAAO;EAEX,OAAQ,cAAuE;CACnF;CAEA,qBACI,gBAC4B;EAC5B,MAAM,gBAAgB,KAAK,0BAA0B,cAAc;EACnE,IAAI,CAAC,eACD,OAAO;EAEX,OAAO;CACX;CAEA,sBAA8B,cAAmE;EAC7F,MAAM,MAAM,KAAK,KAAK,YAAY;EAClC,IACI,CAAC,OACD,IAAI,SAAS,qBAAqB,gBAClC,CAAC,IAAI,gBACL,CAAC,IAAI,oBACL,CAAC,IAAI,oBACL,CAAC,IAAI,iBAEL,MAAM,IAAI,MACN,aAAa,aAAa,QAAQ,KAAK,MAAM,SAAS,KAAK,wCAC/D;EAEJ,OAAO;CACX;CAEA,MAAc,gBAAgB,MAAuD;EACjF,OACK,MAAM,KAAK,MAAM,OAAO,eAAe;GACpC;GACA,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC,KAAM;CAEf;CAEA,MAAc,gBACV,IACA,OACA,SAC2B;EAC3B,OACK,MAAM,KAAK,MAAM,OAAO,eAAe;GACpC;GACA;GACA;GACA,OAAO,KAAK;GACZ,SAAS;GACT,aAAa,KAAK,mBAAmB;EACzC,CAAC,KAAM;CAEf;CAEA,qBAA6B;EACzB,OAAO,kBAAkB,WAAW,KAAK,OAAO,EAAE,qBAAqB;CAC3E;CAEA,sBAA8B,OAA6B,eAAkC;EACzF,MAAM,gBAAgB,MACjB,MAAM,CAAC,EACP,KAAK,KAAK,MAAM;GACb,MAAM,UAAU,IAAI,IAAI,OAAO,KAAK,GAAG,CAAC;GACxC,MAAM,UAAU,CAAC,GAAG,aAAa,EAAE,QAAQ,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,KAAK;GACvE,MAAM,QAAQ,CAAC,GAAG,OAAO,EAAE,QAAQ,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,EAAE,KAAK;GACrE,OAAO;IAAE,OAAO,IAAI;IAAG;IAAS;GAAM;EAC1C,CAAC,EACA,QAAQ,MAAM,EAAE,QAAQ,SAAS,KAAK,EAAE,MAAM,SAAS,CAAC;EAE7D,IAAI,cAAc,WAAW,GACzB;EAGJ,MAAM,sBAAsB,CAAC,GAAG,aAAa,EAAE,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK,MAAM,EAAE,KAAK;EAChD,MAAM,UAAU,cACX,KAAK,MAAM;GACR,MAAM,QAAkB,CAAC;GACzB,IAAI,EAAE,QAAQ,SAAS,GACnB,MAAM,KAAK,YAAY,EAAE,QAAQ,KAAK,IAAI,EAAE,EAAE;GAElD,IAAI,EAAE,MAAM,SAAS,GACjB,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,IAAI,EAAE,EAAE;GAE9C,OAAO,gBAAgB,EAAE,MAAM,IAAI,MAAM,KAAK,IAAI,EAAE;EACxD,CAAC,EACA,KAAK,IAAI;EAEd,MAAM,IAAI,MACN,6DAA6D,QAAQ,KAAK,IAAI,EAAE,6BAA6B,QAAQ,4CAA4C,oBAAoB,KAAK,IAAI,EAAE,GACpM;CACJ;AACJ;;;AChoBA,MAAM,+BAAe,IAAI,QAA2F;AACpH,IAAI,4BAA4B;AAShC,SAAS,sBACL,OACI;CACJ,OAAO,eAAe,OAAO,WAAW;EACpC,cAAc;EACd,YAAY;EACZ,MAAM;GACF,MAAM,UAAU,gBAAgB;GAChC,MAAM,SAAS,aAAa,IAAI,KAAK;GACrC,IAAI,UAAU,OAAO,YAAY,SAC7B,OAAO,OAAO;GAGlB,MAAM,UAAU,IAAI,aAChB,OACA,OACJ;GACA,aAAa,IAAI,OAAO;IACpB;IACS;GACb,CAAC;GACD,OAAO;EACX;CACJ,CAAC;AACL;;;;;AAMA,SAAgB,uBAA6B;CACzC,IAAI,2BACA;CAGJ,uBAAuB,qBAAqB;CAC5C,4BAA4B;AAChC"}
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "../chunk-8H4AJuhK.js";
|
|
2
|
-
import { t as registerModelObjects } from "../registerModelObjects-
|
|
3
|
-
import { i as TangoRuntime, n as initializeTangoRuntime, r as resetTangoRuntime, t as getTangoRuntime } from "../defaultRuntime-
|
|
2
|
+
import { t as registerModelObjects } from "../registerModelObjects-CGjjOzd9.js";
|
|
3
|
+
import { i as TangoRuntime, n as initializeTangoRuntime, r as resetTangoRuntime, t as getTangoRuntime } from "../defaultRuntime-WIsxnh8K.js";
|
|
4
4
|
//#region src/runtime/index.ts
|
|
5
5
|
var runtime_exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
TangoRuntime: () => TangoRuntime,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as UnitOfWork, r as atomic } from "../transaction-
|
|
1
|
+
import { n as UnitOfWork, r as atomic } from "../transaction-DpDXQq5V.js";
|
|
2
2
|
export { UnitOfWork, atomic };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-8H4AJuhK.js";
|
|
2
|
-
import { o as TransactionEngine, t as getTangoRuntime } from "./defaultRuntime-
|
|
2
|
+
import { o as TransactionEngine, t as getTangoRuntime } from "./defaultRuntime-WIsxnh8K.js";
|
|
3
3
|
//#region src/transaction/atomic.ts
|
|
4
4
|
async function atomic(work) {
|
|
5
5
|
return TransactionEngine.forRuntime(getTangoRuntime()).atomic(work);
|
|
@@ -93,4 +93,4 @@ var transaction_exports = /* @__PURE__ */ __exportAll({
|
|
|
93
93
|
//#endregion
|
|
94
94
|
export { UnitOfWork as n, atomic as r, transaction_exports as t };
|
|
95
95
|
|
|
96
|
-
//# sourceMappingURL=transaction-
|
|
96
|
+
//# sourceMappingURL=transaction-DpDXQq5V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-
|
|
1
|
+
{"version":3,"file":"transaction-DpDXQq5V.js","names":[],"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":";;;AAIA,eAAsB,OAAU,MAA6D;CACzF,OAAO,kBAAkB,WAAW,gBAAgB,CAAC,EAAE,OAAO,IAAI;AACtE;;;;;;;;;;;;;;;;;;;;;;;ACiBA,IAAa,aAAb,MAAa,WAAW;CACpB,OAAgB,QAAQ;CACxB,eAAiD,WAAW;CAC5D;CACA,WAAqB;CAErB,YAAY,QAAkB;EAC1B,KAAK,SAAS;CAClB;;;;CAKA,OAAO,aAAa,OAAqC;EACrD,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,WAAW;CAE1E;;;;CAKA,aAAa,MAAM,QAAuC;EACtD,kBAAkB,gCAAgC;EAClD,MAAM,MAAM,IAAI,WAAW,MAAM;EACjC,MAAM,IAAI,MAAM;EAChB,OAAO;CACX;;;;CAKA,MAAM,QAAuB;EACzB,kBAAkB,gCAAgC;EAClD,IAAI,CAAC,KAAK,UAAU;GAChB,MAAM,KAAK,OAAO,MAAM;GACxB,KAAK,WAAW;EACpB;CACJ;;;;CAKA,MAAM,SAAwB;EAC1B,IAAI,KAAK,UAAU;GACf,MAAM,KAAK,OAAO,OAAO;GACzB,KAAK,WAAW;EACpB;CACJ;;;;CAKA,YAAsB;EAClB,OAAO,KAAK;CAChB;;;;CAKA,MAAM,WAA0B;EAC5B,IAAI,KAAK,UAAU;GACf,MAAM,KAAK,OAAO,SAAS;GAC3B,KAAK,WAAW;EACpB;CACJ;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danceroutine/tango-orm",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.9",
|
|
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.11.
|
|
53
|
-
"@danceroutine/tango-core": "1.11.
|
|
54
|
-
"@danceroutine/tango-schema": "1.11.
|
|
52
|
+
"@danceroutine/tango-config": "1.11.9",
|
|
53
|
+
"@danceroutine/tango-core": "1.11.9",
|
|
54
|
+
"@danceroutine/tango-schema": "1.11.9"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"pg": "^8.20.0",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"tsdown": "^0.22.1",
|
|
75
75
|
"typescript": "^6.0.3",
|
|
76
76
|
"vitest": "^4.1.7",
|
|
77
|
-
"@danceroutine/tango-migrations": "1.11.
|
|
78
|
-
"@danceroutine/tango-testing": "1.11.
|
|
77
|
+
"@danceroutine/tango-migrations": "1.11.9",
|
|
78
|
+
"@danceroutine/tango-testing": "1.11.9"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"build": "tsdown",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SqliteAdapter-6oyUmoJf.js","names":[],"sources":["../src/connection/clients/dialects/PostgresClient.ts","../src/connection/adapters/dialects/PostgresAdapter.ts","../src/connection/clients/dialects/SqliteClient.ts","../src/connection/adapters/dialects/SqliteAdapter.ts"],"sourcesContent":["import type { DBClient } from '../DBClient';\n\nexport interface PostgresPoolClientLike {\n query(sql: string, params?: readonly unknown[]): Promise<{ rows: unknown[] }>;\n release(): void;\n}\n\n/**\n * Transaction-capable client 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(private client: PostgresPoolClientLike) {}\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 * Create a savepoint inside the active transaction.\n */\n async createSavepoint(name: string): Promise<void> {\n await this.client.query(`SAVEPOINT ${name}`);\n }\n\n /**\n * Release a previously-created savepoint.\n */\n async releaseSavepoint(name: string): Promise<void> {\n await this.client.query(`RELEASE SAVEPOINT ${name}`);\n }\n\n /**\n * Roll back the active transaction to a savepoint.\n */\n async rollbackToSavepoint(name: string): Promise<void> {\n await this.client.query(`ROLLBACK TO SAVEPOINT ${name}`);\n }\n\n /**\n * Release the leased PostgreSQL client back to its owning pool.\n */\n async close(): Promise<void> {\n this.client.release();\n }\n}\n","import pg from 'pg';\nimport type { Adapter, AdapterConfig, SqlPlaceholders } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { PostgresClient } from '../../clients/dialects/PostgresClient';\nimport { InternalDialect } from '../../../query/domain/internal/InternalDialect';\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 readonly dialect: Adapter['dialect'] = InternalDialect.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 * - ignoreDuplicateInsert: Supports duplicate-safe insert semantics for manager-owned link writes\n */\n readonly features: Adapter['features'] = {\n transactionalDDL: true,\n concurrentIndex: true,\n validateForeignKeys: true,\n ignoreDuplicateInsert: true,\n };\n readonly placeholders: SqlPlaceholders = {\n at(index: number): string {\n return `$${index}`;\n },\n list(count: number): string {\n return this.listFromOffset(count, 0);\n },\n listFromOffset(count: number, startOffset: number): string {\n return Array.from({ length: count }, (_value, index) => `$${startOffset + index + 1}`).join(', ');\n },\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(client);\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { DBClient } from '../DBClient';\n\n/**\n * Transaction-capable client 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 IMMEDIATE').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 * Create a savepoint inside the active transaction.\n */\n async createSavepoint(name: string): Promise<void> {\n this.db.prepare(`SAVEPOINT ${name}`).run();\n }\n\n /**\n * Release a previously-created savepoint.\n */\n async releaseSavepoint(name: string): Promise<void> {\n this.db.prepare(`RELEASE SAVEPOINT ${name}`).run();\n }\n\n /**\n * Roll back the active transaction to a savepoint.\n */\n async rollbackToSavepoint(name: string): Promise<void> {\n this.db.prepare(`ROLLBACK TO SAVEPOINT ${name}`).run();\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, SqlPlaceholders } from '../Adapter';\nimport type { DBClient } from '../../clients/DBClient';\nimport { SqliteClient } from '../../clients/dialects/SqliteClient';\nimport { InternalDialect } from '../../../query/domain/internal/InternalDialect';\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 dialect: Adapter['dialect'] = InternalDialect.SQLITE;\n readonly features: Adapter['features'] = {\n transactionalDDL: true,\n concurrentIndex: false,\n validateForeignKeys: false,\n ignoreDuplicateInsert: true,\n };\n readonly placeholders: SqlPlaceholders = {\n at(): string {\n return '?';\n },\n list(count: number): string {\n return Array.from({ length: count }, () => '?').join(', ');\n },\n listFromOffset(count: number): string {\n return this.list(count);\n },\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 db.pragma('busy_timeout = 5000');\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":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaultRuntime-CdTX8cXm.js","names":[],"sources":["../src/transaction/internal/context/FrameBoundTransaction.ts","../src/transaction/internal/context/AsyncLocalTransactionEngine.ts","../src/transaction/internal/context/TransactionEngine.ts","../src/manager/internal/RuntimeBoundClient.ts","../src/runtime/internal/PostgresDBClientProvider.ts","../src/runtime/internal/SqliteDBClientProvider.ts","../src/runtime/internal/createDBClientProvider.ts","../src/runtime/TangoRuntime.ts","../src/runtime/defaultRuntime.ts"],"sourcesContent":["import type { AtomicTransaction, OnCommitOptions, SavepointOptions, SavepointResult } from '../../AtomicTransaction';\nimport type { AsyncLocalTransactionEngine } from './AsyncLocalTransactionEngine';\nimport type { TransactionFrame } from './TransactionFrame';\nimport type { TransactionState } from './TransactionState';\n\nexport class FrameBoundTransaction implements AtomicTransaction {\n private active = true;\n\n constructor(\n private readonly engine: AsyncLocalTransactionEngine,\n private readonly state: TransactionState,\n private readonly frame: TransactionFrame\n ) {}\n\n onCommit(callback: () => void, options: OnCommitOptions = {}): void {\n if (!this.active) {\n throw new Error('Cannot register an on-commit callback on an inactive transaction frame.');\n }\n\n this.frame.callbacks.push({\n order: this.state.nextCallbackOrder++,\n callback,\n robust: options.robust ?? false,\n });\n }\n\n savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<SavepointResult<T>>;\n savepoint<T>(\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: { throwOnError: false }\n ): Promise<SavepointResult<T>>;\n savepoint<T>(work: (tx: AtomicTransaction) => Promise<T> | T, options: { throwOnError: true }): Promise<T>;\n async savepoint<T>(\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: SavepointOptions = {}\n ): Promise<T | SavepointResult<T>> {\n if (!this.active) {\n throw new Error('Cannot open a savepoint from an inactive transaction frame.');\n }\n\n return this.engine.runSavepoint(this.state, work, options);\n }\n\n deactivate(): void {\n this.active = false;\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { getLogger } from '@danceroutine/tango-core';\nimport type { TangoRuntime } from '../../../runtime/TangoRuntime';\nimport type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';\nimport type { AtomicTransaction, SavepointOptions, SavepointResult } from '../../AtomicTransaction';\nimport type { CallbackRecord } from './CallbackRecord';\nimport { FrameBoundTransaction } from './FrameBoundTransaction';\nimport type { TransactionFrame } from './TransactionFrame';\nimport type { TransactionState } from './TransactionState';\n\nexport class AsyncLocalTransactionEngine {\n private readonly logger = getLogger('tango.orm.transaction');\n private readonly storage = new AsyncLocalStorage<TransactionState>();\n\n assertNoActiveAtomicTransaction(): void {\n if (this.storage.getStore()) {\n throw new Error('UnitOfWork is unsupported inside transaction.atomic(...).');\n }\n }\n\n getActiveTransaction(runtime: TangoRuntime): AtomicTransaction | undefined {\n const state = this.storage.getStore();\n if (!state || state.runtime !== runtime) {\n return undefined;\n }\n\n return state.frames.at(-1)?.facade;\n }\n\n getActiveLease(runtime: TangoRuntime): TransactionClientLease | undefined {\n const state = this.storage.getStore();\n if (!state || state.runtime !== runtime) {\n return undefined;\n }\n\n return state.lease;\n }\n\n async atomic<T>(runtime: TangoRuntime, work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n const existing = this.storage.getStore();\n if (existing) {\n if (existing.runtime !== runtime) {\n throw new Error(\n 'Cannot open a transaction for one Tango runtime while another runtime transaction is active.'\n );\n }\n\n return this.runNested(existing, work);\n }\n\n const lease = await runtime.leaseTransactionClient();\n const state: TransactionState = {\n runtime,\n lease,\n frames: [],\n nextCallbackOrder: 0,\n nextSavepointId: 0,\n };\n\n try {\n return await this.storage.run(state, async () => {\n await lease.client.begin();\n const frame = this.pushFrame(state);\n\n try {\n const result = await work(frame.facade);\n await lease.client.commit();\n const root = this.popFrame(state);\n root.facade.deactivate();\n await this.runCommittedCallbacks(root.callbacks);\n return result;\n } catch (error) {\n await this.rollbackOuter(state, error);\n throw error;\n }\n });\n } finally {\n this.deactivateAllFrames(state);\n await lease.release();\n }\n }\n\n async runSavepoint<T>(\n state: TransactionState,\n work: (tx: AtomicTransaction) => Promise<T> | T,\n options: SavepointOptions\n ): Promise<T | SavepointResult<T>> {\n try {\n const value = await this.runNested(state, work);\n if (options.throwOnError) {\n return value;\n }\n\n return {\n ok: true,\n value,\n };\n } catch (error) {\n if (options.throwOnError) {\n throw error;\n }\n\n return {\n ok: false,\n error,\n };\n }\n }\n\n private async runNested<T>(state: TransactionState, work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n const savepointName = `tango_sp_${state.nextSavepointId++}`;\n await state.lease.client.createSavepoint(savepointName);\n const frame = this.pushFrame(state, savepointName);\n\n try {\n const result = await work(frame.facade);\n await state.lease.client.releaseSavepoint(savepointName);\n const completed = this.popFrame(state);\n completed.facade.deactivate();\n const parent = state.frames.at(-1);\n if (!parent) {\n throw new Error('Nested transaction frame completed without a parent frame.');\n }\n\n parent.callbacks.push(...completed.callbacks);\n parent.callbacks.sort((left, right) => left.order - right.order);\n return result;\n } catch (error) {\n try {\n await state.lease.client.rollbackToSavepoint(savepointName);\n } catch (rollbackError) {\n throw this.attachCause(rollbackError, error);\n } finally {\n const discarded = this.popFrame(state);\n discarded.facade.deactivate();\n }\n\n throw error;\n }\n }\n\n private pushFrame(state: TransactionState, savepointName?: string): TransactionFrame {\n const frame = {} as TransactionFrame;\n const facade = new FrameBoundTransaction(this, state, frame);\n frame.callbacks = [];\n frame.facade = facade;\n frame.savepointName = savepointName;\n state.frames.push(frame);\n return frame;\n }\n\n private popFrame(state: TransactionState): TransactionFrame {\n const frame = state.frames.pop();\n if (!frame) {\n throw new Error('Transaction frame stack underflow.');\n }\n\n return frame;\n }\n\n private async rollbackOuter(state: TransactionState, error: unknown): Promise<void> {\n try {\n await state.lease.client.rollback();\n } catch (rollbackError) {\n throw this.attachCause(rollbackError, error);\n } finally {\n while (state.frames.length > 0) {\n const frame = this.popFrame(state);\n frame.facade.deactivate();\n }\n }\n }\n\n private async runCommittedCallbacks(callbacks: readonly CallbackRecord[]): Promise<void> {\n for (const record of callbacks) {\n try {\n await record.callback();\n } catch (error) {\n if (!record.robust) {\n throw error;\n }\n\n try {\n this.logger.error('Post-commit callback failed.', error);\n } catch {\n // A logging backend failure cannot change the already-committed outcome.\n }\n }\n }\n }\n\n private deactivateAllFrames(state: TransactionState): void {\n state.frames.length = 0;\n }\n\n private attachCause(error: unknown, cause: unknown): unknown {\n if (!this.isErrorValue(error)) {\n return error;\n }\n\n if ('cause' in error && error.cause !== undefined) {\n return error;\n }\n\n try {\n return new Error(error.message, { cause });\n } catch {\n return error;\n }\n }\n\n private isErrorValue(value: unknown): value is Error {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { message?: unknown }).message === 'string' &&\n typeof (value as { name?: unknown }).name === 'string'\n );\n }\n}\n","import type { TangoRuntime } from '../../../runtime/TangoRuntime';\nimport type { TransactionClientLease } from '../../../runtime/internal/DBClientProvider';\nimport type { AtomicTransaction } from '../../AtomicTransaction';\nimport { AsyncLocalTransactionEngine } from './AsyncLocalTransactionEngine';\n\n/**\n * Runtime-bound transaction facade used by internal ORM/runtime components.\n */\nexport class TransactionEngine {\n private static readonly engine = new AsyncLocalTransactionEngine();\n\n private constructor(private readonly runtime: TangoRuntime) {}\n\n static forRuntime(runtime: TangoRuntime): TransactionEngine {\n return new TransactionEngine(runtime);\n }\n\n static assertNoActiveAtomicTransaction(): void {\n this.engine.assertNoActiveAtomicTransaction();\n }\n\n getActiveTransaction(): AtomicTransaction | undefined {\n return TransactionEngine.engine.getActiveTransaction(this.runtime);\n }\n\n getActiveLease(): TransactionClientLease | undefined {\n return TransactionEngine.engine.getActiveLease(this.runtime);\n }\n\n async atomic<T>(work: (tx: AtomicTransaction) => Promise<T> | T): Promise<T> {\n return TransactionEngine.engine.atomic(this.runtime, work);\n }\n}\n","import type { DBClient } from '../../connection/index';\nimport type { TangoRuntime } from '../../runtime/index';\nimport { TransactionEngine } from '../../transaction/internal/context';\n\n/**\n * DB client proxy that resolves either the active transaction lease or the\n * runtime autocommit path lazily.\n */\nexport class RuntimeBoundClient implements DBClient {\n constructor(private readonly runtime: TangoRuntime) {}\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const lease = TransactionEngine.forRuntime(this.runtime).getActiveLease();\n if (lease) {\n return lease.client.query<T>(sql, params);\n }\n\n const runtimeWithQuery = this.runtime as TangoRuntime & {\n query?: <TResult = unknown>(sql: string, params?: readonly unknown[]) => Promise<{ rows: TResult[] }>;\n };\n if (typeof runtimeWithQuery.query === 'function') {\n return runtimeWithQuery.query<T>(sql, params);\n }\n\n const client = await this.runtime.getClient();\n return client.query<T>(sql, params);\n }\n\n async begin(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual begin(). Use transaction.atomic(...) instead.');\n }\n\n async commit(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual commit(). Use transaction.atomic(...) instead.');\n }\n\n async rollback(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual rollback(). Use transaction.atomic(...) instead.');\n }\n\n async createSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoints. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async releaseSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoint release. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async rollbackToSavepoint(_name: string): Promise<void> {\n throw new Error(\n 'Runtime-bound clients do not support manual savepoint rollback. Use transaction.atomic(...) or tx.savepoint(...) instead.'\n );\n }\n\n async close(): Promise<void> {\n throw new Error('Runtime-bound clients do not support manual close(). Use TangoRuntime.reset() instead.');\n }\n}\n","import pg from 'pg';\nimport type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport { PostgresClient } from '../../connection/clients/dialects/PostgresClient';\nimport type { DBClientProvider, TransactionClientLease } from './DBClientProvider';\n\nconst { Pool } = pg;\n\nexport class PostgresDBClientProvider implements DBClientProvider {\n private readonly pool: pg.Pool;\n private activeLeaseCount = 0;\n\n constructor(config: AdapterConfig) {\n this.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\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const result = await this.pool.query(sql, params as unknown[]);\n return { rows: result.rows as T[] };\n }\n\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n const client = await this.pool.connect();\n this.activeLeaseCount += 1;\n let released = false;\n\n return {\n client: new PostgresClient(client),\n release: async () => {\n if (released) {\n return;\n }\n\n released = true;\n this.activeLeaseCount -= 1;\n client.release();\n },\n };\n }\n\n async reset(): Promise<void> {\n if (this.activeLeaseCount > 0) {\n throw new Error('Cannot reset Tango runtime while transaction leases are still active.');\n }\n\n await this.pool.end();\n }\n}\n","import { createRequire } from 'node:module';\nimport type { Database as BetterSqliteDatabase } from 'better-sqlite3';\nimport type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport { SqliteClient } from '../../connection/clients/dialects/SqliteClient';\nimport type { DBClientProvider, TransactionClientLease } from './DBClientProvider';\n\ntype BetterSqliteCtor = new (filename: string, options?: unknown) => BetterSqliteDatabase;\n\nexport class SqliteDBClientProvider implements DBClientProvider {\n private readonly filename: string;\n private readonly Database: BetterSqliteCtor;\n private readonly autocommitClient: SqliteClient;\n private activeLeaseCount = 0;\n private exclusiveTail: Promise<void> = Promise.resolve();\n\n constructor(config: AdapterConfig = {}) {\n this.Database = this.getDatabaseCtor();\n this.filename =\n typeof config.filename === 'string' && config.filename.length > 0 ? config.filename : ':memory:';\n this.autocommitClient = this.openClient(this.filename);\n }\n\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n return this.runExclusive(() => this.autocommitClient.query<T>(sql, params));\n }\n\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n if (this.filename === ':memory:') {\n throw new Error('transaction.atomic(...) requires a file-backed SQLite database. :memory: is unsupported.');\n }\n\n const releaseExclusive = await this.acquireExclusive();\n try {\n const client = this.openClient(this.filename);\n this.activeLeaseCount += 1;\n let released = false;\n\n return {\n client,\n release: async () => {\n if (released) {\n return;\n }\n\n released = true;\n this.activeLeaseCount -= 1;\n try {\n await client.close();\n } finally {\n releaseExclusive();\n }\n },\n };\n } catch (error) {\n releaseExclusive();\n throw error;\n }\n }\n\n async reset(): Promise<void> {\n if (this.activeLeaseCount > 0) {\n throw new Error('Cannot reset Tango runtime while transaction leases are still active.');\n }\n\n await this.autocommitClient.close();\n }\n\n private openClient(filename: string): SqliteClient {\n const db = new this.Database(filename);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n db.pragma('busy_timeout = 5000');\n return new SqliteClient(db);\n }\n\n private async runExclusive<T>(work: () => Promise<T>): Promise<T> {\n const release = await this.acquireExclusive();\n try {\n return await work();\n } finally {\n release();\n }\n }\n\n private async acquireExclusive(): Promise<() => void> {\n const previous = this.exclusiveTail;\n let release: (() => void) | null = null;\n this.exclusiveTail = new Promise<void>((resolve) => {\n release = resolve;\n });\n await previous;\n return () => {\n release?.();\n };\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","import type { AdapterConfig } from '../../connection/adapters/Adapter';\nimport type { DBClientProvider } from './DBClientProvider';\nimport { PostgresDBClientProvider } from './PostgresDBClientProvider';\nimport { SqliteDBClientProvider } from './SqliteDBClientProvider';\n\nexport function createDBClientProvider(config: AdapterConfig & { adapter: string }): DBClientProvider {\n switch (config.adapter) {\n case 'postgres':\n return new PostgresDBClientProvider(config);\n case 'sqlite':\n return new SqliteDBClientProvider(config);\n default:\n throw new Error(`Unsupported adapter for Tango runtime provider: ${config.adapter}`);\n }\n}\n","import type { LoadedConfig } from '@danceroutine/tango-config';\nimport type { DBClient } from '../connection/index';\nimport type { Adapter } from '../connection/adapters/Adapter';\nimport { PostgresAdapter } from '../connection/adapters/dialects/PostgresAdapter';\nimport { SqliteAdapter } from '../connection/adapters/dialects/SqliteAdapter';\nimport type { Dialect } from '../query/domain/index';\nimport { InternalDialect } from '../query/domain/internal/InternalDialect';\nimport { RuntimeBoundClient } from '../manager/internal/RuntimeBoundClient';\nimport type { DBClientProvider, TransactionClientLease } from './internal/DBClientProvider';\nimport { createDBClientProvider } from './internal/createDBClientProvider';\n\n/**\n * Framework-owned database runtime that resolves Tango config and lazily\n * creates the shared connection provider used by manager-backed models.\n */\nexport class TangoRuntime {\n static readonly BRAND = 'tango.orm.runtime' as const;\n readonly __tangoBrand: typeof TangoRuntime.BRAND = TangoRuntime.BRAND;\n private readonly loadedConfig: LoadedConfig;\n private providerPromise: Promise<DBClientProvider> | null = null;\n private runtimeClientPromise: Promise<DBClient> | null = null;\n private cachedAdapter: Adapter | null = null;\n\n constructor(loadLoadedConfig: () => LoadedConfig) {\n this.loadedConfig = loadLoadedConfig();\n }\n\n /**\n * Narrow an unknown value to `TangoRuntime`.\n */\n static isTangoRuntime(value: unknown): value is TangoRuntime {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { __tangoBrand?: unknown }).__tangoBrand === TangoRuntime.BRAND\n );\n }\n\n /**\n * Return the loaded Tango config snapshot for the active environment.\n */\n getConfig(): LoadedConfig {\n return this.loadedConfig;\n }\n\n /**\n * Return the configured SQL dialect for the current runtime.\n */\n getDialect(): Dialect {\n return this.loadedConfig.current.db.adapter;\n }\n\n /**\n * Return the adapter backing the configured dialect. Manager-side\n * compilers use this to obtain placeholder formatters and dialect\n * capabilities without branching on the raw dialect string.\n */\n getAdapter(): Adapter {\n if (!this.cachedAdapter) {\n this.cachedAdapter = this.buildAdapterForDialect(this.getDialect());\n }\n return this.cachedAdapter;\n }\n\n /**\n * Return the runtime-bound DB client facade used by manager-backed code.\n */\n async getClient(): Promise<DBClient> {\n if (!this.runtimeClientPromise) {\n this.runtimeClientPromise = Promise.resolve(new RuntimeBoundClient(this));\n }\n\n return this.runtimeClientPromise;\n }\n\n /**\n * Execute SQL through the autocommit path owned by this runtime.\n */\n async query<T = unknown>(sql: string, params?: readonly unknown[]): Promise<{ rows: T[] }> {\n const provider = await this.getProvider();\n return provider.query<T>(sql, params);\n }\n\n /**\n * Lease a transaction-scoped client for `transaction.atomic(...)`.\n */\n async leaseTransactionClient(): Promise<TransactionClientLease> {\n const provider = await this.getProvider();\n return provider.leaseTransactionClient();\n }\n\n /**\n * Close and clear the cached runtime resources so tests can start fresh.\n */\n async reset(): Promise<void> {\n if (!this.providerPromise) {\n this.runtimeClientPromise = null;\n return;\n }\n\n const provider = await this.providerPromise;\n this.providerPromise = null;\n this.runtimeClientPromise = null;\n await provider.reset();\n }\n\n private buildAdapterForDialect(dialect: Dialect): Adapter {\n switch (dialect) {\n case InternalDialect.POSTGRES:\n return new PostgresAdapter();\n case InternalDialect.SQLITE:\n return new SqliteAdapter();\n }\n }\n\n private async getProvider(): Promise<DBClientProvider> {\n if (!this.providerPromise) {\n const db = this.loadedConfig.current.db;\n this.providerPromise = Promise.resolve(\n createDBClientProvider({\n adapter: db.adapter,\n url: db.url,\n host: db.host,\n port: db.port,\n database: db.database,\n user: db.user,\n password: db.password,\n filename: db.filename,\n maxConnections: db.maxConnections,\n })\n );\n }\n\n return this.providerPromise;\n }\n}\n","import { loadConfig, loadConfigFromProjectRoot } from '@danceroutine/tango-config';\nimport { TangoRuntime } from './TangoRuntime';\n\nlet defaultRuntime: TangoRuntime | null = null;\n\n/**\n * Initialize the process-default Tango runtime from a Tango config loader.\n */\nexport function initializeTangoRuntime(fromFile: () => unknown): TangoRuntime {\n defaultRuntime = new TangoRuntime(() => loadConfig(fromFile));\n return defaultRuntime;\n}\n\n/**\n * Return the process-default Tango runtime, lazily loading Tango config on first access.\n */\nexport function getTangoRuntime(): TangoRuntime {\n if (!defaultRuntime) {\n defaultRuntime = new TangoRuntime(() => loadConfigFromProjectRoot());\n }\n\n return defaultRuntime;\n}\n\n/**\n * Reset the process-default Tango runtime and release any cached client.\n */\nexport async function resetTangoRuntime(): Promise<void> {\n if (!defaultRuntime) {\n return;\n }\n\n const runtime = defaultRuntime;\n defaultRuntime = null;\n await runtime.reset();\n}\n"],"mappings":";;;;;;;;AAKA,IAAa,wBAAb,MAAgE;CAIvC;CACA;CACA;CALrB,SAAiB;CAEjB,YACI,QACA,OACA,OACF;EAHmB,KAAA,SAAA;EACA,KAAA,QAAA;EACA,KAAA,QAAA;CAClB;CAEH,SAAS,UAAsB,UAA2B,CAAC,GAAS;EAChE,IAAI,CAAC,KAAK,QACN,MAAM,IAAI,MAAM,yEAAyE;EAG7F,KAAK,MAAM,UAAU,KAAK;GACtB,OAAO,KAAK,MAAM;GAClB;GACA,QAAQ,QAAQ,UAAU;EAC9B,CAAC;CACL;CAQA,MAAM,UACF,MACA,UAA4B,CAAC,GACE;EAC/B,IAAI,CAAC,KAAK,QACN,MAAM,IAAI,MAAM,6DAA6D;EAGjF,OAAO,KAAK,OAAO,aAAa,KAAK,OAAO,MAAM,OAAO;CAC7D;CAEA,aAAmB;EACf,KAAK,SAAS;CAClB;AACJ;;;ACpCA,IAAa,8BAAb,MAAyC;CACrC,SAA0B,UAAU,uBAAuB;CAC3D,UAA2B,IAAI,kBAAoC;CAEnE,kCAAwC;EACpC,IAAI,KAAK,QAAQ,SAAS,GACtB,MAAM,IAAI,MAAM,2DAA2D;CAEnF;CAEA,qBAAqB,SAAsD;EACvE,MAAM,QAAQ,KAAK,QAAQ,SAAS;EACpC,IAAI,CAAC,SAAS,MAAM,YAAY,SAC5B;EAGJ,OAAO,MAAM,OAAO,GAAG,EAAE,GAAG;CAChC;CAEA,eAAe,SAA2D;EACtE,MAAM,QAAQ,KAAK,QAAQ,SAAS;EACpC,IAAI,CAAC,SAAS,MAAM,YAAY,SAC5B;EAGJ,OAAO,MAAM;CACjB;CAEA,MAAM,OAAU,SAAuB,MAA6D;EAChG,MAAM,WAAW,KAAK,QAAQ,SAAS;EACvC,IAAI,UAAU;GACV,IAAI,SAAS,YAAY,SACrB,MAAM,IAAI,MACN,8FACJ;GAGJ,OAAO,KAAK,UAAU,UAAU,IAAI;EACxC;EAEA,MAAM,QAAQ,MAAM,QAAQ,uBAAuB;EACnD,MAAM,QAA0B;GAC5B;GACA;GACA,QAAQ,CAAC;GACT,mBAAmB;GACnB,iBAAiB;EACrB;EAEA,IAAI;GACA,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,YAAY;IAC7C,MAAM,MAAM,OAAO,MAAM;IACzB,MAAM,QAAQ,KAAK,UAAU,KAAK;IAElC,IAAI;KACA,MAAM,SAAS,MAAM,KAAK,MAAM,MAAM;KACtC,MAAM,MAAM,OAAO,OAAO;KAC1B,MAAM,OAAO,KAAK,SAAS,KAAK;KAChC,KAAK,OAAO,WAAW;KACvB,MAAM,KAAK,sBAAsB,KAAK,SAAS;KAC/C,OAAO;IACX,SAAS,OAAO;KACZ,MAAM,KAAK,cAAc,OAAO,KAAK;KACrC,MAAM;IACV;GACJ,CAAC;EACL,UAAU;GACN,KAAK,oBAAoB,KAAK;GAC9B,MAAM,MAAM,QAAQ;EACxB;CACJ;CAEA,MAAM,aACF,OACA,MACA,SAC+B;EAC/B,IAAI;GACA,MAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,IAAI;GAC9C,IAAI,QAAQ,cACR,OAAO;GAGX,OAAO;IACH,IAAI;IACJ;GACJ;EACJ,SAAS,OAAO;GACZ,IAAI,QAAQ,cACR,MAAM;GAGV,OAAO;IACH,IAAI;IACJ;GACJ;EACJ;CACJ;CAEA,MAAc,UAAa,OAAyB,MAA6D;EAC7G,MAAM,gBAAgB,YAAY,MAAM;EACxC,MAAM,MAAM,MAAM,OAAO,gBAAgB,aAAa;EACtD,MAAM,QAAQ,KAAK,UAAU,OAAO,aAAa;EAEjD,IAAI;GACA,MAAM,SAAS,MAAM,KAAK,MAAM,MAAM;GACtC,MAAM,MAAM,MAAM,OAAO,iBAAiB,aAAa;GACvD,MAAM,YAAY,KAAK,SAAS,KAAK;GACrC,UAAU,OAAO,WAAW;GAC5B,MAAM,SAAS,MAAM,OAAO,GAAG,EAAE;GACjC,IAAI,CAAC,QACD,MAAM,IAAI,MAAM,4DAA4D;GAGhF,OAAO,UAAU,KAAK,GAAG,UAAU,SAAS;GAC5C,OAAO,UAAU,MAAM,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK;GAC/D,OAAO;EACX,SAAS,OAAO;GACZ,IAAI;IACA,MAAM,MAAM,MAAM,OAAO,oBAAoB,aAAa;GAC9D,SAAS,eAAe;IACpB,MAAM,KAAK,YAAY,eAAe,KAAK;GAC/C,UAAU;IAEN,KADuB,SAAS,KACxB,EAAE,OAAO,WAAW;GAChC;GAEA,MAAM;EACV;CACJ;CAEA,UAAkB,OAAyB,eAA0C;EACjF,MAAM,QAAQ,CAAC;EACf,MAAM,SAAS,IAAI,sBAAsB,MAAM,OAAO,KAAK;EAC3D,MAAM,YAAY,CAAC;EACnB,MAAM,SAAS;EACf,MAAM,gBAAgB;EACtB,MAAM,OAAO,KAAK,KAAK;EACvB,OAAO;CACX;CAEA,SAAiB,OAA2C;EACxD,MAAM,QAAQ,MAAM,OAAO,IAAI;EAC/B,IAAI,CAAC,OACD,MAAM,IAAI,MAAM,oCAAoC;EAGxD,OAAO;CACX;CAEA,MAAc,cAAc,OAAyB,OAA+B;EAChF,IAAI;GACA,MAAM,MAAM,MAAM,OAAO,SAAS;EACtC,SAAS,eAAe;GACpB,MAAM,KAAK,YAAY,eAAe,KAAK;EAC/C,UAAU;GACN,OAAO,MAAM,OAAO,SAAS,GAEzB,KADmB,SAAS,KACxB,EAAE,OAAO,WAAW;EAEhC;CACJ;CAEA,MAAc,sBAAsB,WAAqD;EACrF,KAAK,MAAM,UAAU,WACjB,IAAI;GACA,MAAM,OAAO,SAAS;EAC1B,SAAS,OAAO;GACZ,IAAI,CAAC,OAAO,QACR,MAAM;GAGV,IAAI;IACA,KAAK,OAAO,MAAM,gCAAgC,KAAK;GAC3D,QAAQ,CAER;EACJ;CAER;CAEA,oBAA4B,OAA+B;EACvD,MAAM,OAAO,SAAS;CAC1B;CAEA,YAAoB,OAAgB,OAAyB;EACzD,IAAI,CAAC,KAAK,aAAa,KAAK,GACxB,OAAO;EAGX,IAAI,WAAW,SAAS,MAAM,UAAU,KAAA,GACpC,OAAO;EAGX,IAAI;GACA,OAAO,IAAI,MAAM,MAAM,SAAS,EAAE,MAAM,CAAC;EAC7C,QAAQ;GACJ,OAAO;EACX;CACJ;CAEA,aAAqB,OAAgC;EACjD,OACI,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAgC,YAAY,YACpD,OAAQ,MAA6B,SAAS;CAEtD;AACJ;;;;;;ACnNA,IAAa,oBAAb,MAAa,kBAAkB;CAGU;CAFrC,OAAwB,SAAS,IAAI,4BAA4B;CAEjE,YAAoB,SAAwC;EAAvB,KAAA,UAAA;CAAwB;CAE7D,OAAO,WAAW,SAA0C;EACxD,OAAO,IAAI,kBAAkB,OAAO;CACxC;CAEA,OAAO,kCAAwC;EAC3C,KAAK,OAAO,gCAAgC;CAChD;CAEA,uBAAsD;EAClD,OAAO,kBAAkB,OAAO,qBAAqB,KAAK,OAAO;CACrE;CAEA,iBAAqD;EACjD,OAAO,kBAAkB,OAAO,eAAe,KAAK,OAAO;CAC/D;CAEA,MAAM,OAAU,MAA6D;EACzE,OAAO,kBAAkB,OAAO,OAAO,KAAK,SAAS,IAAI;CAC7D;AACJ;;;;;;;ACxBA,IAAa,qBAAb,MAAoD;CACnB;CAA7B,YAAY,SAAwC;EAAvB,KAAA,UAAA;CAAwB;CAErD,MAAM,MAAmB,KAAa,QAAqD;EACvF,MAAM,QAAQ,kBAAkB,WAAW,KAAK,OAAO,EAAE,eAAe;EACxE,IAAI,OACA,OAAO,MAAM,OAAO,MAAS,KAAK,MAAM;EAG5C,MAAM,mBAAmB,KAAK;EAG9B,IAAI,OAAO,iBAAiB,UAAU,YAClC,OAAO,iBAAiB,MAAS,KAAK,MAAM;EAIhD,QAAO,MADc,KAAK,QAAQ,UAAU,GAC9B,MAAS,KAAK,MAAM;CACtC;CAEA,MAAM,QAAuB;EACzB,MAAM,IAAI,MAAM,2FAA2F;CAC/G;CAEA,MAAM,SAAwB;EAC1B,MAAM,IAAI,MAAM,4FAA4F;CAChH;CAEA,MAAM,WAA0B;EAC5B,MAAM,IAAI,MAAM,8FAA8F;CAClH;CAEA,MAAM,gBAAgB,OAA8B;EAChD,MAAM,IAAI,MACN,mHACJ;CACJ;CAEA,MAAM,iBAAiB,OAA8B;EACjD,MAAM,IAAI,MACN,0HACJ;CACJ;CAEA,MAAM,oBAAoB,OAA8B;EACpD,MAAM,IAAI,MACN,2HACJ;CACJ;CAEA,MAAM,QAAuB;EACzB,MAAM,IAAI,MAAM,wFAAwF;CAC5G;AACJ;;;ACxDA,MAAM,EAAE,SAAS;AAEjB,IAAa,2BAAb,MAAkE;CAC9D;CACA,mBAA2B;CAE3B,YAAY,QAAuB;EAC/B,KAAK,OAAO,IAAI,KAAK;GACjB,kBAAkB,OAAO;GACzB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,KAAK,OAAO,kBAAkB;EAClC,CAAC;CACL;CAEA,MAAM,MAAmB,KAAa,QAAqD;EAEvF,OAAO,EAAE,OAAM,MADM,KAAK,KAAK,MAAM,KAAK,MAAmB,GACvC,KAAY;CACtC;CAEA,MAAM,yBAA0D;EAC5D,MAAM,SAAS,MAAM,KAAK,KAAK,QAAQ;EACvC,KAAK,oBAAoB;EACzB,IAAI,WAAW;EAEf,OAAO;GACH,QAAQ,IAAI,eAAe,MAAM;GACjC,SAAS,YAAY;IACjB,IAAI,UACA;IAGJ,WAAW;IACX,KAAK,oBAAoB;IACzB,OAAO,QAAQ;GACnB;EACJ;CACJ;CAEA,MAAM,QAAuB;EACzB,IAAI,KAAK,mBAAmB,GACxB,MAAM,IAAI,MAAM,uEAAuE;EAG3F,MAAM,KAAK,KAAK,IAAI;CACxB;AACJ;;;AC9CA,IAAa,yBAAb,MAAgE;CAC5D;CACA;CACA;CACA,mBAA2B;CAC3B,gBAAuC,QAAQ,QAAQ;CAEvD,YAAY,SAAwB,CAAC,GAAG;EACpC,KAAK,WAAW,KAAK,gBAAgB;EACrC,KAAK,WACD,OAAO,OAAO,aAAa,YAAY,OAAO,SAAS,SAAS,IAAI,OAAO,WAAW;EAC1F,KAAK,mBAAmB,KAAK,WAAW,KAAK,QAAQ;CACzD;CAEA,MAAM,MAAmB,KAAa,QAAqD;EACvF,OAAO,KAAK,mBAAmB,KAAK,iBAAiB,MAAS,KAAK,MAAM,CAAC;CAC9E;CAEA,MAAM,yBAA0D;EAC5D,IAAI,KAAK,aAAa,YAClB,MAAM,IAAI,MAAM,0FAA0F;EAG9G,MAAM,mBAAmB,MAAM,KAAK,iBAAiB;EACrD,IAAI;GACA,MAAM,SAAS,KAAK,WAAW,KAAK,QAAQ;GAC5C,KAAK,oBAAoB;GACzB,IAAI,WAAW;GAEf,OAAO;IACH;IACA,SAAS,YAAY;KACjB,IAAI,UACA;KAGJ,WAAW;KACX,KAAK,oBAAoB;KACzB,IAAI;MACA,MAAM,OAAO,MAAM;KACvB,UAAU;MACN,iBAAiB;KACrB;IACJ;GACJ;EACJ,SAAS,OAAO;GACZ,iBAAiB;GACjB,MAAM;EACV;CACJ;CAEA,MAAM,QAAuB;EACzB,IAAI,KAAK,mBAAmB,GACxB,MAAM,IAAI,MAAM,uEAAuE;EAG3F,MAAM,KAAK,iBAAiB,MAAM;CACtC;CAEA,WAAmB,UAAgC;EAC/C,MAAM,KAAK,IAAI,KAAK,SAAS,QAAQ;EACrC,GAAG,OAAO,oBAAoB;EAC9B,GAAG,OAAO,mBAAmB;EAC7B,GAAG,OAAO,qBAAqB;EAC/B,OAAO,IAAI,aAAa,EAAE;CAC9B;CAEA,MAAc,aAAgB,MAAoC;EAC9D,MAAM,UAAU,MAAM,KAAK,iBAAiB;EAC5C,IAAI;GACA,OAAO,MAAM,KAAK;EACtB,UAAU;GACN,QAAQ;EACZ;CACJ;CAEA,MAAc,mBAAwC;EAClD,MAAM,WAAW,KAAK;EACtB,IAAI,UAA+B;EACnC,KAAK,gBAAgB,IAAI,SAAe,YAAY;GAChD,UAAU;EACd,CAAC;EACD,MAAM;EACN,aAAa;GACT,UAAU;EACd;CACJ;CAEA,kBAA4C;EAExC,MAAM,cADU,cAAc,OAAO,KAAK,GAChB,EAAE,gBAAgB;EAC5C,IAAI,OAAO,gBAAgB,YACvB,OAAO;EAGX,MAAM,gBAAiB,YAAsC;EAC7D,IAAI,OAAO,kBAAkB,YACzB,OAAO;EAGX,MAAM,IAAI,UAAU,4CAA4C;CACpE;AACJ;;;ACzGA,SAAgB,uBAAuB,QAA+D;CAClG,QAAQ,OAAO,SAAf;EACI,KAAK,YACD,OAAO,IAAI,yBAAyB,MAAM;EAC9C,KAAK,UACD,OAAO,IAAI,uBAAuB,MAAM;EAC5C,SACI,MAAM,IAAI,MAAM,mDAAmD,OAAO,SAAS;CAC3F;AACJ;;;;;;;ACCA,IAAa,eAAb,MAAa,aAAa;CACtB,OAAgB,QAAQ;CACxB,eAAmD,aAAa;CAChE;CACA,kBAA4D;CAC5D,uBAAyD;CACzD,gBAAwC;CAExC,YAAY,kBAAsC;EAC9C,KAAK,eAAe,iBAAiB;CACzC;;;;CAKA,OAAO,eAAe,OAAuC;EACzD,OACI,OAAO,UAAU,YACjB,UAAU,QACT,MAAqC,iBAAiB,aAAa;CAE5E;;;;CAKA,YAA0B;EACtB,OAAO,KAAK;CAChB;;;;CAKA,aAAsB;EAClB,OAAO,KAAK,aAAa,QAAQ,GAAG;CACxC;;;;;;CAOA,aAAsB;EAClB,IAAI,CAAC,KAAK,eACN,KAAK,gBAAgB,KAAK,uBAAuB,KAAK,WAAW,CAAC;EAEtE,OAAO,KAAK;CAChB;;;;CAKA,MAAM,YAA+B;EACjC,IAAI,CAAC,KAAK,sBACN,KAAK,uBAAuB,QAAQ,QAAQ,IAAI,mBAAmB,IAAI,CAAC;EAG5E,OAAO,KAAK;CAChB;;;;CAKA,MAAM,MAAmB,KAAa,QAAqD;EAEvF,QAAO,MADgB,KAAK,YAAY,GACxB,MAAS,KAAK,MAAM;CACxC;;;;CAKA,MAAM,yBAA0D;EAE5D,QAAO,MADgB,KAAK,YAAY,GACxB,uBAAuB;CAC3C;;;;CAKA,MAAM,QAAuB;EACzB,IAAI,CAAC,KAAK,iBAAiB;GACvB,KAAK,uBAAuB;GAC5B;EACJ;EAEA,MAAM,WAAW,MAAM,KAAK;EAC5B,KAAK,kBAAkB;EACvB,KAAK,uBAAuB;EAC5B,MAAM,SAAS,MAAM;CACzB;CAEA,uBAA+B,SAA2B;EACtD,QAAQ,SAAR;GACI,KAAK,gBAAgB,UACjB,OAAO,IAAI,gBAAgB;GAC/B,KAAK,gBAAgB,QACjB,OAAO,IAAI,cAAc;EACjC;CACJ;CAEA,MAAc,cAAyC;EACnD,IAAI,CAAC,KAAK,iBAAiB;GACvB,MAAM,KAAK,KAAK,aAAa,QAAQ;GACrC,KAAK,kBAAkB,QAAQ,QAC3B,uBAAuB;IACnB,SAAS,GAAG;IACZ,KAAK,GAAG;IACR,MAAM,GAAG;IACT,MAAM,GAAG;IACT,UAAU,GAAG;IACb,MAAM,GAAG;IACT,UAAU,GAAG;IACb,UAAU,GAAG;IACb,gBAAgB,GAAG;GACvB,CAAC,CACL;EACJ;EAEA,OAAO,KAAK;CAChB;AACJ;;;ACpIA,IAAI,iBAAsC;;;;AAK1C,SAAgB,uBAAuB,UAAuC;CAC1E,iBAAiB,IAAI,mBAAmB,WAAW,QAAQ,CAAC;CAC5D,OAAO;AACX;;;;AAKA,SAAgB,kBAAgC;CAC5C,IAAI,CAAC,gBACD,iBAAiB,IAAI,mBAAmB,0BAA0B,CAAC;CAGvE,OAAO;AACX;;;;AAKA,eAAsB,oBAAmC;CACrD,IAAI,CAAC,gBACD;CAGJ,MAAM,UAAU;CAChB,iBAAiB;CACjB,MAAM,QAAQ,MAAM;AACxB"}
|