@fragno-dev/db 0.1.3 → 0.1.6
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/.turbo/turbo-build.log +43 -30
- package/CHANGELOG.md +19 -0
- package/dist/adapters/adapters.js +1 -0
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +9 -2
- package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
- package/dist/adapters/drizzle/generate.js +1 -1
- package/dist/adapters/drizzle/generate.js.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts +1 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.js +47 -27
- package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
- package/dist/adapters/kysely/kysely-query-compiler.js +2 -2
- package/dist/adapters/kysely/kysely-query-compiler.js.map +1 -1
- package/dist/adapters/kysely/kysely-query.js +2 -1
- package/dist/adapters/kysely/kysely-query.js.map +1 -1
- package/dist/adapters/kysely/kysely-uow-compiler.js +2 -2
- package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -1
- package/dist/adapters/kysely/migration/execute-base.js +128 -0
- package/dist/adapters/kysely/migration/execute-base.js.map +1 -0
- package/dist/adapters/kysely/migration/execute-factory.js +28 -0
- package/dist/adapters/kysely/migration/execute-factory.js.map +1 -0
- package/dist/adapters/kysely/migration/execute-mssql.js +112 -0
- package/dist/adapters/kysely/migration/execute-mssql.js.map +1 -0
- package/dist/adapters/kysely/migration/execute-mysql.js +93 -0
- package/dist/adapters/kysely/migration/execute-mysql.js.map +1 -0
- package/dist/adapters/kysely/migration/execute-postgres.js +104 -0
- package/dist/adapters/kysely/migration/execute-postgres.js.map +1 -0
- package/dist/adapters/kysely/migration/execute-sqlite.js +123 -0
- package/dist/adapters/kysely/migration/execute-sqlite.js.map +1 -0
- package/dist/adapters/kysely/migration/execute.js +23 -168
- package/dist/adapters/kysely/migration/execute.js.map +1 -1
- package/dist/migration-engine/shared.d.ts +24 -5
- package/dist/migration-engine/shared.d.ts.map +1 -1
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/query/query.d.ts +4 -4
- package/dist/query/query.d.ts.map +1 -1
- package/dist/query/unit-of-work.d.ts +22 -22
- package/dist/query/unit-of-work.d.ts.map +1 -1
- package/dist/schema/create.d.ts +41 -41
- package/dist/schema/create.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +1 -1
- package/src/adapters/drizzle/drizzle-adapter.ts +13 -3
- package/src/adapters/drizzle/generate.test.ts +97 -0
- package/src/adapters/drizzle/generate.ts +3 -2
- package/src/adapters/kysely/kysely-adapter.ts +64 -35
- package/src/adapters/kysely/kysely-query-compiler.ts +3 -1
- package/src/adapters/kysely/kysely-query.ts +3 -1
- package/src/adapters/kysely/kysely-uow-compiler.ts +4 -2
- package/src/adapters/kysely/migration/execute-base.ts +256 -0
- package/src/adapters/kysely/migration/execute-factory.ts +32 -0
- package/src/adapters/kysely/migration/execute-mssql.ts +250 -0
- package/src/adapters/kysely/migration/execute-mysql.ts +211 -0
- package/src/adapters/kysely/migration/execute-postgres.ts +234 -0
- package/src/adapters/kysely/migration/execute-sqlite.test.ts +1363 -0
- package/src/adapters/kysely/migration/execute-sqlite.ts +247 -0
- package/src/adapters/kysely/migration/execute.ts +33 -396
- package/src/adapters/kysely/migration/kysely-migrator.test.ts +84 -2
- package/src/migration-engine/shared.ts +29 -11
- package/tsdown.config.ts +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SETTINGS_TABLE_NAME } from "../../shared/settings-schema.js";
|
|
2
2
|
import { createMigrator } from "../../migration-engine/create.js";
|
|
3
|
-
import { execute } from "./migration/execute.js";
|
|
3
|
+
import { execute, preprocessOperations } from "./migration/execute.js";
|
|
4
4
|
import { fromKysely } from "./kysely-query.js";
|
|
5
5
|
import { createTableNameMapper } from "./kysely-shared.js";
|
|
6
6
|
import { sql } from "kysely";
|
|
@@ -12,52 +12,68 @@ var KyselyAdapter = class {
|
|
|
12
12
|
constructor(config) {
|
|
13
13
|
this.#kyselyConfig = config;
|
|
14
14
|
}
|
|
15
|
+
#getDb() {
|
|
16
|
+
const db = this.#kyselyConfig.db;
|
|
17
|
+
return typeof db === "function" ? db() : db;
|
|
18
|
+
}
|
|
15
19
|
createQueryEngine(schema, namespace) {
|
|
16
20
|
const mapper = namespace ? createTableNameMapper(namespace) : void 0;
|
|
17
|
-
return fromKysely(schema,
|
|
21
|
+
return fromKysely(schema, {
|
|
22
|
+
db: this.#getDb(),
|
|
23
|
+
provider: this.#kyselyConfig.provider
|
|
24
|
+
}, mapper);
|
|
18
25
|
}
|
|
19
26
|
async isConnectionHealthy() {
|
|
20
27
|
try {
|
|
21
|
-
|
|
28
|
+
const db = this.#getDb();
|
|
29
|
+
return (await db.executeQuery(sql`SELECT 1 as healthy`.compile(db))).rows[0]["healthy"] === 1;
|
|
22
30
|
} catch {
|
|
23
31
|
return false;
|
|
24
32
|
}
|
|
25
33
|
}
|
|
26
34
|
createMigrationEngine(schema, namespace) {
|
|
27
|
-
const manager = createSettingsManager(this.#
|
|
35
|
+
const manager = createSettingsManager(this.#getDb(), namespace);
|
|
28
36
|
const mapper = namespace ? createTableNameMapper(namespace) : void 0;
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
compile() {
|
|
33
|
-
return statement.compile(db);
|
|
34
|
-
},
|
|
35
|
-
execute() {
|
|
36
|
-
return statement.execute(db);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
const preprocess = (operations, db) => {
|
|
37
|
+
const preprocessMigrationOperations = (operations) => {
|
|
38
|
+
let preprocessed = preprocessOperations(operations, this.#kyselyConfig);
|
|
41
39
|
if (this.#kyselyConfig.provider === "mysql") {
|
|
42
|
-
|
|
40
|
+
preprocessed.unshift({
|
|
43
41
|
type: "custom",
|
|
44
42
|
sql: "SET FOREIGN_KEY_CHECKS = 0"
|
|
45
43
|
});
|
|
46
|
-
|
|
44
|
+
preprocessed.push({
|
|
47
45
|
type: "custom",
|
|
48
46
|
sql: "SET FOREIGN_KEY_CHECKS = 1"
|
|
49
47
|
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
}
|
|
49
|
+
return preprocessed;
|
|
50
|
+
};
|
|
51
|
+
const toExecutableNodes = (operations, db) => {
|
|
52
|
+
const onCustomNode = (node, db$1) => {
|
|
53
|
+
const statement = sql.raw(node["sql"]);
|
|
54
|
+
return {
|
|
55
|
+
compile() {
|
|
56
|
+
return statement.compile(db$1);
|
|
57
|
+
},
|
|
58
|
+
execute() {
|
|
59
|
+
return statement.execute(db$1);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
const dbConfig = {
|
|
64
|
+
db,
|
|
65
|
+
provider: this.#kyselyConfig.provider
|
|
66
|
+
};
|
|
67
|
+
return operations.flatMap((op) => execute(op, dbConfig, (node) => onCustomNode(node, db), mapper));
|
|
55
68
|
};
|
|
56
69
|
return createMigrator({
|
|
57
70
|
schema,
|
|
58
71
|
executor: async (operations) => {
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
const db = this.#getDb();
|
|
73
|
+
if (this.#kyselyConfig.provider === "sqlite") await sql.raw("PRAGMA defer_foreign_keys = ON").execute(db);
|
|
74
|
+
await db.transaction().execute(async (tx) => {
|
|
75
|
+
const nodes = toExecutableNodes(preprocessMigrationOperations(operations), tx);
|
|
76
|
+
for (const node of nodes) try {
|
|
61
77
|
await node.execute();
|
|
62
78
|
} catch (e) {
|
|
63
79
|
console.error("failed at", node.compile(), e);
|
|
@@ -66,7 +82,11 @@ var KyselyAdapter = class {
|
|
|
66
82
|
});
|
|
67
83
|
},
|
|
68
84
|
sql: { toSql: (operations) => {
|
|
69
|
-
|
|
85
|
+
const parts = [];
|
|
86
|
+
if (this.#kyselyConfig.provider === "sqlite") parts.push("PRAGMA defer_foreign_keys = ON;");
|
|
87
|
+
const compiled = toExecutableNodes(preprocessMigrationOperations(operations), this.#getDb()).map((node) => `${node.compile().sql};`);
|
|
88
|
+
parts.push(...compiled);
|
|
89
|
+
return parts.join("\n\n");
|
|
70
90
|
} },
|
|
71
91
|
settings: {
|
|
72
92
|
getVersion: async () => {
|
|
@@ -83,7 +103,7 @@ var KyselyAdapter = class {
|
|
|
83
103
|
});
|
|
84
104
|
}
|
|
85
105
|
getSchemaVersion(namespace) {
|
|
86
|
-
return createSettingsManager(this.#
|
|
106
|
+
return createSettingsManager(this.#getDb(), namespace).get(`schema_version`);
|
|
87
107
|
}
|
|
88
108
|
};
|
|
89
109
|
function createSettingsManager(db, namespace) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-adapter.js","names":["#kyselyConfig"],"sources":["../../../src/adapters/kysely/kysely-adapter.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport type { SQLProvider } from \"../../shared/providers\";\nimport type { DatabaseAdapter } from \"../adapters\";\nimport { createMigrator, type Migrator } from \"../../migration-engine/create\";\nimport type { AnySchema } from \"../../schema/create\";\nimport type { CustomOperation, MigrationOperation } from \"../../migration-engine/shared\";\nimport { execute } from \"./migration/execute\";\nimport type { AbstractQuery } from \"../../query/query\";\nimport { fromKysely } from \"./kysely-query\";\nimport { createTableNameMapper } from \"./kysely-shared\";\nimport { createHash } from \"node:crypto\";\nimport { SETTINGS_TABLE_NAME } from \"../../shared/settings-schema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KyselyAny = Kysely<any>;\n\nexport interface KyselyConfig {\n db: KyselyAny;\n provider: SQLProvider;\n}\n\nexport class KyselyAdapter implements DatabaseAdapter {\n #kyselyConfig: KyselyConfig;\n\n constructor(config: KyselyConfig) {\n this.#kyselyConfig = config;\n }\n\n createQueryEngine<T extends AnySchema>(schema: T, namespace: string): AbstractQuery<T> {\n // Only create mapper if namespace is non-empty\n const mapper = namespace ? createTableNameMapper(namespace) : undefined;\n return fromKysely(schema,
|
|
1
|
+
{"version":3,"file":"kysely-adapter.js","names":["#kyselyConfig","#getDb","db","dbConfig: KyselyConfig","parts: string[]"],"sources":["../../../src/adapters/kysely/kysely-adapter.ts"],"sourcesContent":["import { sql, type Kysely } from \"kysely\";\nimport type { SQLProvider } from \"../../shared/providers\";\nimport type { DatabaseAdapter } from \"../adapters\";\nimport { createMigrator, type Migrator } from \"../../migration-engine/create\";\nimport type { AnySchema } from \"../../schema/create\";\nimport type { CustomOperation, MigrationOperation } from \"../../migration-engine/shared\";\nimport { execute, preprocessOperations } from \"./migration/execute\";\nimport type { AbstractQuery } from \"../../query/query\";\nimport { fromKysely } from \"./kysely-query\";\nimport { createTableNameMapper } from \"./kysely-shared\";\nimport { createHash } from \"node:crypto\";\nimport { SETTINGS_TABLE_NAME } from \"../../shared/settings-schema\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KyselyAny = Kysely<any>;\n\nexport interface KyselyConfig {\n db: KyselyAny | (() => KyselyAny);\n provider: SQLProvider;\n}\n\nexport class KyselyAdapter implements DatabaseAdapter {\n #kyselyConfig: KyselyConfig;\n\n constructor(config: KyselyConfig) {\n this.#kyselyConfig = config;\n }\n\n #getDb(): KyselyAny {\n const db = this.#kyselyConfig.db;\n return typeof db === \"function\" ? db() : db;\n }\n\n createQueryEngine<T extends AnySchema>(schema: T, namespace: string): AbstractQuery<T> {\n // Only create mapper if namespace is non-empty\n const mapper = namespace ? createTableNameMapper(namespace) : undefined;\n // Resolve the db instance if it's a function\n const resolvedConfig: KyselyConfig = {\n db: this.#getDb(),\n provider: this.#kyselyConfig.provider,\n };\n return fromKysely(schema, resolvedConfig, mapper);\n }\n\n async isConnectionHealthy(): Promise<boolean> {\n try {\n const db = this.#getDb();\n const result = await db.executeQuery(sql`SELECT 1 as healthy`.compile(db));\n return (result.rows[0] as Record<string, unknown>)[\"healthy\"] === 1;\n } catch {\n return false;\n }\n }\n\n createMigrationEngine(schema: AnySchema, namespace: string): Migrator {\n const manager = createSettingsManager(this.#getDb(), namespace);\n const mapper = namespace ? createTableNameMapper(namespace) : undefined;\n\n const preprocessMigrationOperations = (operations: MigrationOperation[]) => {\n let preprocessed = preprocessOperations(operations, this.#kyselyConfig);\n\n if (this.#kyselyConfig.provider === \"mysql\") {\n preprocessed.unshift({ type: \"custom\", sql: \"SET FOREIGN_KEY_CHECKS = 0\" });\n preprocessed.push({ type: \"custom\", sql: \"SET FOREIGN_KEY_CHECKS = 1\" });\n }\n\n return preprocessed;\n };\n\n // Convert operations to executable nodes bound to specific db instance\n const toExecutableNodes = (operations: MigrationOperation[], db: KyselyAny) => {\n const onCustomNode = (node: CustomOperation, db: KyselyAny) => {\n const statement = sql.raw(node[\"sql\"] as string);\n\n return {\n compile() {\n return statement.compile(db);\n },\n execute() {\n return statement.execute(db);\n },\n };\n };\n\n const dbConfig: KyselyConfig = { db, provider: this.#kyselyConfig.provider };\n return operations.flatMap((op) =>\n execute(op, dbConfig, (node) => onCustomNode(node, db), mapper),\n );\n };\n\n const migrator = createMigrator({\n schema,\n executor: async (operations) => {\n const db = this.#getDb();\n // For SQLite, execute PRAGMA defer_foreign_keys BEFORE transaction\n if (this.#kyselyConfig.provider === \"sqlite\") {\n await sql.raw(\"PRAGMA defer_foreign_keys = ON\").execute(db);\n }\n\n await db.transaction().execute(async (tx) => {\n const preprocessed = preprocessMigrationOperations(operations);\n const nodes = toExecutableNodes(preprocessed, tx);\n for (const node of nodes) {\n try {\n await node.execute();\n } catch (e) {\n console.error(\"failed at\", node.compile(), e);\n throw e;\n }\n }\n });\n },\n sql: {\n toSql: (operations) => {\n const parts: string[] = [];\n\n // Add SQLite PRAGMA at the beginning\n if (this.#kyselyConfig.provider === \"sqlite\") {\n parts.push(\"PRAGMA defer_foreign_keys = ON;\");\n }\n\n const preprocessed = preprocessMigrationOperations(operations);\n const nodes = toExecutableNodes(preprocessed, this.#getDb());\n const compiled = nodes.map((node) => `${node.compile().sql};`);\n\n parts.push(...compiled);\n\n return parts.join(\"\\n\\n\");\n },\n },\n\n settings: {\n getVersion: async () => {\n const v = await manager.get(`schema_version`);\n return v ? parseInt(v) : 0;\n },\n updateSettingsInMigration: async (fromVersion, toVersion) => {\n return [\n {\n type: \"custom\",\n sql:\n fromVersion === 0\n ? manager.insert(`schema_version`, toVersion.toString())\n : manager.update(`schema_version`, toVersion.toString()),\n },\n ];\n },\n },\n });\n\n return migrator;\n }\n\n getSchemaVersion(namespace: string) {\n const manager = createSettingsManager(this.#getDb(), namespace);\n\n return manager.get(`schema_version`);\n }\n}\n\nfunction createSettingsManager(db: KyselyAny, namespace: string) {\n // Settings table is never namespaced, but keys include namespace prefix\n const tableName = SETTINGS_TABLE_NAME;\n\n return {\n async get(key: string): Promise<string | undefined> {\n try {\n const result = await db\n .selectFrom(tableName)\n .where(\"key\", \"=\", sql.lit(`${namespace}.${key}`))\n .select([\"value\"])\n .executeTakeFirstOrThrow();\n return result.value as string;\n } catch {\n return;\n }\n },\n\n insert(key: string, value: string) {\n return db\n .insertInto(tableName)\n .values({\n id: sql.lit(\n createHash(\"md5\").update(`${namespace}.${key}`).digest(\"base64url\").replace(/=/g, \"\"),\n ),\n key: sql.lit(`${namespace}.${key}`),\n value: sql.lit(value),\n })\n .compile().sql;\n },\n\n update(key: string, value: string) {\n return db\n .updateTable(tableName)\n .set({\n value: sql.lit(value),\n })\n .where(\"key\", \"=\", sql.lit(`${namespace}.${key}`))\n .compile().sql;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -4,8 +4,8 @@ import { createKyselyQueryBuilder } from "./kysely-query-builder.js";
|
|
|
4
4
|
|
|
5
5
|
//#region src/adapters/kysely/kysely-query-compiler.ts
|
|
6
6
|
function createKyselyQueryCompiler(schema, config, mapper) {
|
|
7
|
-
const { db
|
|
8
|
-
const queryBuilder = createKyselyQueryBuilder(
|
|
7
|
+
const { db, provider } = config;
|
|
8
|
+
const queryBuilder = createKyselyQueryBuilder(typeof db === "function" ? db() : db, provider, mapper);
|
|
9
9
|
function toTable(name) {
|
|
10
10
|
const table = schema.tables[name];
|
|
11
11
|
if (!table) throw new Error(`Invalid table name ${name}.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-query-compiler.js","names":[],"sources":["../../../src/adapters/kysely/kysely-query-compiler.ts"],"sourcesContent":["import type { CompiledQuery } from \"kysely\";\nimport type { AnySchema, AnyTable } from \"../../schema/create\";\nimport { buildCondition } from \"../../query/condition-builder\";\nimport { buildFindOptions } from \"../../query/orm/orm\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport { createKyselyQueryBuilder } from \"./kysely-query-builder\";\nimport type { ConditionBuilder, Condition } from \"../../query/condition-builder\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Internal query compiler interface for Kysely\n * Used by the UOW compiler to generate compiled queries\n */\nexport interface KyselyQueryCompiler {\n count: (\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: { where?: (eb: ConditionBuilder<any>) => any },\n ) => CompiledQuery | null;\n findFirst: (name: string, options: any) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n findMany: (name: string, options?: any) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n create: (name: string, values: any) => CompiledQuery; // eslint-disable-line @typescript-eslint/no-explicit-any\n createMany: (name: string, values: any[]) => CompiledQuery; // eslint-disable-line @typescript-eslint/no-explicit-any\n updateMany: (name: string, options: { set: any; where?: any }) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n deleteMany: (name: string, options: { where?: any }) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport function createKyselyQueryCompiler<T extends AnySchema>(\n schema: T,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): KyselyQueryCompiler {\n const { db
|
|
1
|
+
{"version":3,"file":"kysely-query-compiler.js","names":[],"sources":["../../../src/adapters/kysely/kysely-query-compiler.ts"],"sourcesContent":["import type { CompiledQuery } from \"kysely\";\nimport type { AnySchema, AnyTable } from \"../../schema/create\";\nimport { buildCondition } from \"../../query/condition-builder\";\nimport { buildFindOptions } from \"../../query/orm/orm\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport { createKyselyQueryBuilder } from \"./kysely-query-builder\";\nimport type { ConditionBuilder, Condition } from \"../../query/condition-builder\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Internal query compiler interface for Kysely\n * Used by the UOW compiler to generate compiled queries\n */\nexport interface KyselyQueryCompiler {\n count: (\n name: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n options?: { where?: (eb: ConditionBuilder<any>) => any },\n ) => CompiledQuery | null;\n findFirst: (name: string, options: any) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n findMany: (name: string, options?: any) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n create: (name: string, values: any) => CompiledQuery; // eslint-disable-line @typescript-eslint/no-explicit-any\n createMany: (name: string, values: any[]) => CompiledQuery; // eslint-disable-line @typescript-eslint/no-explicit-any\n updateMany: (name: string, options: { set: any; where?: any }) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n deleteMany: (name: string, options: { where?: any }) => CompiledQuery | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport function createKyselyQueryCompiler<T extends AnySchema>(\n schema: T,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): KyselyQueryCompiler {\n const { db, provider } = config;\n // Resolve the db instance if it's a function\n const kysely = typeof db === \"function\" ? db() : db;\n const queryBuilder = createKyselyQueryBuilder(kysely, provider, mapper);\n\n function toTable(name: unknown): AnyTable {\n const table = schema.tables[name as string];\n if (!table) {\n throw new Error(`Invalid table name ${name}.`);\n }\n return table;\n }\n\n return {\n count(name, { where } = {}) {\n const table = toTable(name);\n let conditions = where ? buildCondition(table.columns, where) : undefined;\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n return queryBuilder.count(table, { where: conditions });\n },\n\n findFirst(name, options) {\n const table = toTable(name);\n // Safe cast: FindFirstOptions is structurally compatible with FindManyOptions\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const compiledOptions = buildFindOptions(table, options as any);\n if (compiledOptions === false) {\n return null;\n }\n\n return queryBuilder.findMany(table, {\n ...compiledOptions,\n limit: 1,\n });\n },\n\n findMany(name, options = {}) {\n const table = toTable(name);\n // Safe cast: FindManyOptions from compiler matches FindManyOptions from buildFindOptions\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const compiledOptions = buildFindOptions(table, options as any);\n if (compiledOptions === false) {\n return null;\n }\n\n return queryBuilder.findMany(table, compiledOptions);\n },\n\n create(name, values) {\n const table = toTable(name);\n return queryBuilder.create(table, values);\n },\n\n createMany(name, values) {\n const table = toTable(name);\n return queryBuilder.createMany(table, values);\n },\n\n updateMany(name, { set, where }) {\n const table = toTable(name);\n let conditions = where ? buildCondition(table.columns, where) : undefined;\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n // Safe: conditions is Condition | undefined after filtering out true/false\n return queryBuilder.updateMany(table, {\n set,\n where: conditions as Condition | undefined,\n });\n },\n\n deleteMany(name, { where }) {\n const table = toTable(name);\n let conditions = where ? buildCondition(table.columns, where) : undefined;\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n // Safe: conditions is Condition | undefined after filtering out true/false\n return queryBuilder.deleteMany(table, { where: conditions as Condition | undefined });\n },\n };\n}\n"],"mappings":";;;;;AA2BA,SAAgB,0BACd,QACA,QACA,QACqB;CACrB,MAAM,EAAE,IAAI,aAAa;CAGzB,MAAM,eAAe,yBADN,OAAO,OAAO,aAAa,IAAI,GAAG,IACK,UAAU,OAAO;CAEvE,SAAS,QAAQ,MAAyB;EACxC,MAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,sBAAsB,KAAK,GAAG;AAEhD,SAAO;;AAGT,QAAO;EACL,MAAM,MAAM,EAAE,UAAU,EAAE,EAAE;GAC1B,MAAM,QAAQ,QAAQ,KAAK;GAC3B,IAAI,aAAa,QAAQ,eAAe,MAAM,SAAS,MAAM,GAAG;AAChE,OAAI,eAAe,KACjB,cAAa;AAEf,OAAI,eAAe,MACjB,QAAO;AAGT,UAAO,aAAa,MAAM,OAAO,EAAE,OAAO,YAAY,CAAC;;EAGzD,UAAU,MAAM,SAAS;GACvB,MAAM,QAAQ,QAAQ,KAAK;GAG3B,MAAM,kBAAkB,iBAAiB,OAAO,QAAe;AAC/D,OAAI,oBAAoB,MACtB,QAAO;AAGT,UAAO,aAAa,SAAS,OAAO;IAClC,GAAG;IACH,OAAO;IACR,CAAC;;EAGJ,SAAS,MAAM,UAAU,EAAE,EAAE;GAC3B,MAAM,QAAQ,QAAQ,KAAK;GAG3B,MAAM,kBAAkB,iBAAiB,OAAO,QAAe;AAC/D,OAAI,oBAAoB,MACtB,QAAO;AAGT,UAAO,aAAa,SAAS,OAAO,gBAAgB;;EAGtD,OAAO,MAAM,QAAQ;GACnB,MAAM,QAAQ,QAAQ,KAAK;AAC3B,UAAO,aAAa,OAAO,OAAO,OAAO;;EAG3C,WAAW,MAAM,QAAQ;GACvB,MAAM,QAAQ,QAAQ,KAAK;AAC3B,UAAO,aAAa,WAAW,OAAO,OAAO;;EAG/C,WAAW,MAAM,EAAE,KAAK,SAAS;GAC/B,MAAM,QAAQ,QAAQ,KAAK;GAC3B,IAAI,aAAa,QAAQ,eAAe,MAAM,SAAS,MAAM,GAAG;AAChE,OAAI,eAAe,KACjB,cAAa;AAEf,OAAI,eAAe,MACjB,QAAO;AAIT,UAAO,aAAa,WAAW,OAAO;IACpC;IACA,OAAO;IACR,CAAC;;EAGJ,WAAW,MAAM,EAAE,SAAS;GAC1B,MAAM,QAAQ,QAAQ,KAAK;GAC3B,IAAI,aAAa,QAAQ,eAAe,MAAM,SAAS,MAAM,GAAG;AAChE,OAAI,eAAe,KACjB,cAAa;AAEf,OAAI,eAAe,MACjB,QAAO;AAIT,UAAO,aAAa,WAAW,OAAO,EAAE,OAAO,YAAqC,CAAC;;EAExF"}
|
|
@@ -30,7 +30,8 @@ import { executeKyselyMutationPhase, executeKyselyRetrievalPhase } from "./kysel
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
function fromKysely(schema, config, mapper) {
|
|
33
|
-
const { db
|
|
33
|
+
const { db, provider } = config;
|
|
34
|
+
const kysely = typeof db === "function" ? db() : db;
|
|
34
35
|
const uowCompiler = createKyselyUOWCompiler(schema, config, mapper);
|
|
35
36
|
function createUOW(name) {
|
|
36
37
|
const executor = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-query.js","names":["executor: UOWExecutor<CompiledQuery, unknown>","decoder: UOWDecoder<T>","whereConfig: { indexName?: string; condition?: unknown }","setValues: unknown"],"sources":["../../../src/adapters/kysely/kysely-query.ts"],"sourcesContent":["import type { AbstractQuery } from \"../../query/query\";\nimport type { AnySchema } from \"../../schema/create\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport type { CompiledMutation, UOWDecoder, UOWExecutor } from \"../../query/unit-of-work\";\nimport { decodeResult } from \"../../query/result-transform\";\nimport { createKyselyUOWCompiler } from \"./kysely-uow-compiler\";\nimport { executeKyselyRetrievalPhase, executeKyselyMutationPhase } from \"./kysely-uow-executor\";\nimport { UnitOfWork } from \"../../query/unit-of-work\";\nimport type { CompiledQuery } from \"kysely\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Creates a Kysely-based query engine for the given schema.\n *\n * This is the main entry point for creating a database query interface using Kysely.\n * It uses a compiler-based architecture where queries are compiled to SQL and then executed,\n * enabling features like SQL snapshot testing.\n *\n * @param schema - The database schema definition\n * @param config - Kysely configuration containing the database instance and provider\n * @param mapper - Optional table name mapper for namespace prefixing\n * @returns An AbstractQuery instance for performing database operations\n *\n * @example\n * ```ts\n * const queryEngine = fromKysely(mySchema, {\n * db: kysely,\n * provider: 'postgresql'\n * });\n *\n * const users = await queryEngine.findMany('users', {\n * where: (b) => b('age', '>', 18),\n * orderBy: [['name', 'asc']]\n * });\n * ```\n */\nexport function fromKysely<T extends AnySchema>(\n schema: T,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): AbstractQuery<T> {\n const { db: kysely, provider } = config;\n const uowCompiler = createKyselyUOWCompiler(schema, config, mapper);\n\n function createUOW(name?: string): UnitOfWork<T, []> {\n const executor: UOWExecutor<CompiledQuery, unknown> = {\n executeRetrievalPhase: (retrievalBatch: CompiledQuery[]) =>\n executeKyselyRetrievalPhase(kysely, retrievalBatch),\n executeMutationPhase: (mutationBatch: CompiledMutation<CompiledQuery>[]) =>\n executeKyselyMutationPhase(kysely, mutationBatch),\n };\n\n // Create a decoder function to transform raw results into application format\n const decoder: UOWDecoder<T> = (rawResults, ops) => {\n if (rawResults.length !== ops.length) {\n throw new Error(\"rawResults and ops must have the same length\");\n }\n\n return rawResults.map((rows, index) => {\n const op = ops[index];\n if (!op) {\n throw new Error(\"op must be defined\");\n }\n\n // Handle count operations differently - return the count number directly\n if (op.type === \"count\") {\n const rowArray = rows as Record<string, unknown>[];\n const firstRow = rowArray[0];\n if (!firstRow) {\n return 0;\n }\n const count = Number(firstRow[\"count\"]);\n if (Number.isNaN(count)) {\n throw new Error(`Unexpected result for count, received: ${count}`);\n }\n return count;\n }\n\n // Each result is an array of rows - decode each row\n const rowArray = rows as Record<string, unknown>[];\n return rowArray.map((row) => decodeResult(row, op.table, provider));\n });\n };\n\n return new UnitOfWork(schema, uowCompiler, executor, decoder, name);\n }\n\n return {\n async find(tableName, builderFn) {\n const uow = createUOW();\n uow.find(tableName, builderFn);\n // executeRetrieve returns an array of results (one per find operation)\n // Since we only have one find, unwrap the first result\n const [result]: unknown[][] = await uow.executeRetrieve();\n return result ?? [];\n },\n\n async findFirst(tableName, builderFn) {\n const uow = createUOW();\n if (builderFn) {\n uow.find(tableName, (b) => builderFn(b as never).pageSize(1));\n } else {\n uow.find(tableName, (b) => b.whereIndex(\"primary\").pageSize(1));\n }\n // executeRetrieve runs an array of `find` operation results, which each return an array of rows\n const [result]: unknown[][] = await uow.executeRetrieve();\n return result?.[0] ?? null;\n },\n\n async create(tableName, values) {\n const uow = createUOW();\n uow.create(tableName, values);\n const { success } = await uow.executeMutations();\n if (!success) {\n // This should not happen because we don't `.check()` this call.\n // TODO: Verify what happens when there are unique constraints\n throw new Error(\"Failed to create record\");\n }\n\n const [createdId] = uow.getCreatedIds();\n if (!createdId) {\n throw new Error(\"Failed to get created ID\");\n }\n return createdId;\n },\n\n async createMany(tableName, valuesArray) {\n const uow = createUOW();\n for (const values of valuesArray) {\n uow.create(tableName, values);\n }\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to create records\");\n }\n\n return uow.getCreatedIds();\n },\n\n async update(tableName, id, builderFn) {\n const uow = createUOW();\n uow.update(tableName, id, builderFn as never);\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to update record (version conflict or record not found)\");\n }\n },\n\n async updateMany(tableName, builderFn) {\n // Create a special builder that captures both where and set operations\n let whereConfig: { indexName?: string; condition?: unknown } = {};\n let setValues: unknown;\n\n const specialBuilder = {\n whereIndex(indexName: string, condition?: unknown) {\n whereConfig = { indexName, condition };\n return this;\n },\n set(values: unknown) {\n setValues = values;\n return this;\n },\n };\n\n builderFn(specialBuilder);\n\n if (!whereConfig.indexName) {\n throw new Error(\"whereIndex() must be called in updateMany\");\n }\n if (!setValues) {\n throw new Error(\"set() must be called in updateMany\");\n }\n\n // First, find all matching records\n const findUow = createUOW();\n findUow.find(tableName, (b) => {\n if (whereConfig.condition) {\n return b.whereIndex(whereConfig.indexName as never, whereConfig.condition as never);\n }\n return b.whereIndex(whereConfig.indexName as never);\n });\n const findResults: unknown[][] = await findUow.executeRetrieve();\n const records = findResults[0];\n\n if (!records || records.length === 0) {\n return;\n }\n\n // Now update all found records\n const updateUow = createUOW();\n for (const record of records as never as Array<{ id: unknown }>) {\n updateUow.update(tableName as string, record.id as string, (b) =>\n b.set(setValues as never),\n );\n }\n const { success } = await updateUow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to update records (version conflict)\");\n }\n },\n\n async delete(tableName, id, builderFn) {\n const uow = createUOW();\n uow.delete(tableName, id, builderFn as never);\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to delete record (version conflict or record not found)\");\n }\n },\n\n async deleteMany(tableName, builderFn) {\n // Create a special builder that captures where configuration\n let whereConfig: { indexName?: string; condition?: unknown } = {};\n\n const specialBuilder = {\n whereIndex(indexName: string, condition?: unknown) {\n whereConfig = { indexName, condition };\n return this;\n },\n };\n\n // Safe: Call builderFn to capture the configuration\n builderFn(specialBuilder as never);\n\n if (!whereConfig.indexName) {\n throw new Error(\"whereIndex() must be called in deleteMany\");\n }\n\n // First, find all matching records\n const findUow = createUOW();\n findUow.find(tableName as string, (b) => {\n if (whereConfig.condition) {\n return b.whereIndex(whereConfig.indexName as never, whereConfig.condition as never);\n }\n return b.whereIndex(whereConfig.indexName as never);\n });\n const findResults2 = await findUow.executeRetrieve();\n const records = (findResults2 as unknown as [unknown])[0];\n\n // @ts-expect-error - Type narrowing doesn't work through unknown cast\n if (!records || records.length === 0) {\n return;\n }\n\n // Now delete all found records\n const deleteUow = createUOW();\n for (const record of records as never as Array<{ id: unknown }>) {\n deleteUow.delete(tableName as string, record.id as string);\n }\n const { success } = await deleteUow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to delete records (version conflict)\");\n }\n },\n\n createUnitOfWork(name) {\n return createUOW(name);\n },\n } as AbstractQuery<T>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kysely-query.js","names":["executor: UOWExecutor<CompiledQuery, unknown>","decoder: UOWDecoder<T>","whereConfig: { indexName?: string; condition?: unknown }","setValues: unknown"],"sources":["../../../src/adapters/kysely/kysely-query.ts"],"sourcesContent":["import type { AbstractQuery } from \"../../query/query\";\nimport type { AnySchema } from \"../../schema/create\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport type { CompiledMutation, UOWDecoder, UOWExecutor } from \"../../query/unit-of-work\";\nimport { decodeResult } from \"../../query/result-transform\";\nimport { createKyselyUOWCompiler } from \"./kysely-uow-compiler\";\nimport { executeKyselyRetrievalPhase, executeKyselyMutationPhase } from \"./kysely-uow-executor\";\nimport { UnitOfWork } from \"../../query/unit-of-work\";\nimport type { CompiledQuery } from \"kysely\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Creates a Kysely-based query engine for the given schema.\n *\n * This is the main entry point for creating a database query interface using Kysely.\n * It uses a compiler-based architecture where queries are compiled to SQL and then executed,\n * enabling features like SQL snapshot testing.\n *\n * @param schema - The database schema definition\n * @param config - Kysely configuration containing the database instance and provider\n * @param mapper - Optional table name mapper for namespace prefixing\n * @returns An AbstractQuery instance for performing database operations\n *\n * @example\n * ```ts\n * const queryEngine = fromKysely(mySchema, {\n * db: kysely,\n * provider: 'postgresql'\n * });\n *\n * const users = await queryEngine.findMany('users', {\n * where: (b) => b('age', '>', 18),\n * orderBy: [['name', 'asc']]\n * });\n * ```\n */\nexport function fromKysely<T extends AnySchema>(\n schema: T,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): AbstractQuery<T> {\n const { db, provider } = config;\n // Resolve the db instance if it's a function\n const kysely = typeof db === \"function\" ? db() : db;\n const uowCompiler = createKyselyUOWCompiler(schema, config, mapper);\n\n function createUOW(name?: string): UnitOfWork<T, []> {\n const executor: UOWExecutor<CompiledQuery, unknown> = {\n executeRetrievalPhase: (retrievalBatch: CompiledQuery[]) =>\n executeKyselyRetrievalPhase(kysely, retrievalBatch),\n executeMutationPhase: (mutationBatch: CompiledMutation<CompiledQuery>[]) =>\n executeKyselyMutationPhase(kysely, mutationBatch),\n };\n\n // Create a decoder function to transform raw results into application format\n const decoder: UOWDecoder<T> = (rawResults, ops) => {\n if (rawResults.length !== ops.length) {\n throw new Error(\"rawResults and ops must have the same length\");\n }\n\n return rawResults.map((rows, index) => {\n const op = ops[index];\n if (!op) {\n throw new Error(\"op must be defined\");\n }\n\n // Handle count operations differently - return the count number directly\n if (op.type === \"count\") {\n const rowArray = rows as Record<string, unknown>[];\n const firstRow = rowArray[0];\n if (!firstRow) {\n return 0;\n }\n const count = Number(firstRow[\"count\"]);\n if (Number.isNaN(count)) {\n throw new Error(`Unexpected result for count, received: ${count}`);\n }\n return count;\n }\n\n // Each result is an array of rows - decode each row\n const rowArray = rows as Record<string, unknown>[];\n return rowArray.map((row) => decodeResult(row, op.table, provider));\n });\n };\n\n return new UnitOfWork(schema, uowCompiler, executor, decoder, name);\n }\n\n return {\n async find(tableName, builderFn) {\n const uow = createUOW();\n uow.find(tableName, builderFn);\n // executeRetrieve returns an array of results (one per find operation)\n // Since we only have one find, unwrap the first result\n const [result]: unknown[][] = await uow.executeRetrieve();\n return result ?? [];\n },\n\n async findFirst(tableName, builderFn) {\n const uow = createUOW();\n if (builderFn) {\n uow.find(tableName, (b) => builderFn(b as never).pageSize(1));\n } else {\n uow.find(tableName, (b) => b.whereIndex(\"primary\").pageSize(1));\n }\n // executeRetrieve runs an array of `find` operation results, which each return an array of rows\n const [result]: unknown[][] = await uow.executeRetrieve();\n return result?.[0] ?? null;\n },\n\n async create(tableName, values) {\n const uow = createUOW();\n uow.create(tableName, values);\n const { success } = await uow.executeMutations();\n if (!success) {\n // This should not happen because we don't `.check()` this call.\n // TODO: Verify what happens when there are unique constraints\n throw new Error(\"Failed to create record\");\n }\n\n const [createdId] = uow.getCreatedIds();\n if (!createdId) {\n throw new Error(\"Failed to get created ID\");\n }\n return createdId;\n },\n\n async createMany(tableName, valuesArray) {\n const uow = createUOW();\n for (const values of valuesArray) {\n uow.create(tableName, values);\n }\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to create records\");\n }\n\n return uow.getCreatedIds();\n },\n\n async update(tableName, id, builderFn) {\n const uow = createUOW();\n uow.update(tableName, id, builderFn as never);\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to update record (version conflict or record not found)\");\n }\n },\n\n async updateMany(tableName, builderFn) {\n // Create a special builder that captures both where and set operations\n let whereConfig: { indexName?: string; condition?: unknown } = {};\n let setValues: unknown;\n\n const specialBuilder = {\n whereIndex(indexName: string, condition?: unknown) {\n whereConfig = { indexName, condition };\n return this;\n },\n set(values: unknown) {\n setValues = values;\n return this;\n },\n };\n\n builderFn(specialBuilder);\n\n if (!whereConfig.indexName) {\n throw new Error(\"whereIndex() must be called in updateMany\");\n }\n if (!setValues) {\n throw new Error(\"set() must be called in updateMany\");\n }\n\n // First, find all matching records\n const findUow = createUOW();\n findUow.find(tableName, (b) => {\n if (whereConfig.condition) {\n return b.whereIndex(whereConfig.indexName as never, whereConfig.condition as never);\n }\n return b.whereIndex(whereConfig.indexName as never);\n });\n const findResults: unknown[][] = await findUow.executeRetrieve();\n const records = findResults[0];\n\n if (!records || records.length === 0) {\n return;\n }\n\n // Now update all found records\n const updateUow = createUOW();\n for (const record of records as never as Array<{ id: unknown }>) {\n updateUow.update(tableName as string, record.id as string, (b) =>\n b.set(setValues as never),\n );\n }\n const { success } = await updateUow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to update records (version conflict)\");\n }\n },\n\n async delete(tableName, id, builderFn) {\n const uow = createUOW();\n uow.delete(tableName, id, builderFn as never);\n const { success } = await uow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to delete record (version conflict or record not found)\");\n }\n },\n\n async deleteMany(tableName, builderFn) {\n // Create a special builder that captures where configuration\n let whereConfig: { indexName?: string; condition?: unknown } = {};\n\n const specialBuilder = {\n whereIndex(indexName: string, condition?: unknown) {\n whereConfig = { indexName, condition };\n return this;\n },\n };\n\n // Safe: Call builderFn to capture the configuration\n builderFn(specialBuilder as never);\n\n if (!whereConfig.indexName) {\n throw new Error(\"whereIndex() must be called in deleteMany\");\n }\n\n // First, find all matching records\n const findUow = createUOW();\n findUow.find(tableName as string, (b) => {\n if (whereConfig.condition) {\n return b.whereIndex(whereConfig.indexName as never, whereConfig.condition as never);\n }\n return b.whereIndex(whereConfig.indexName as never);\n });\n const findResults2 = await findUow.executeRetrieve();\n const records = (findResults2 as unknown as [unknown])[0];\n\n // @ts-expect-error - Type narrowing doesn't work through unknown cast\n if (!records || records.length === 0) {\n return;\n }\n\n // Now delete all found records\n const deleteUow = createUOW();\n for (const record of records as never as Array<{ id: unknown }>) {\n deleteUow.delete(tableName as string, record.id as string);\n }\n const { success } = await deleteUow.executeMutations();\n if (!success) {\n throw new Error(\"Failed to delete records (version conflict)\");\n }\n },\n\n createUnitOfWork(name) {\n return createUOW(name);\n },\n } as AbstractQuery<T>;\n}\n"],"mappings":"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"}
|
|
@@ -17,8 +17,8 @@ import { createKyselyQueryCompiler } from "./kysely-query-compiler.js";
|
|
|
17
17
|
*/
|
|
18
18
|
function createKyselyUOWCompiler(schema, config, mapper) {
|
|
19
19
|
const queryCompiler = createKyselyQueryCompiler(schema, config, mapper);
|
|
20
|
-
const
|
|
21
|
-
const
|
|
20
|
+
const { db, provider } = config;
|
|
21
|
+
const queryBuilder = createKyselyQueryBuilder(typeof db === "function" ? db() : db, provider, mapper);
|
|
22
22
|
function toTable(name) {
|
|
23
23
|
const table = schema.tables[name];
|
|
24
24
|
if (!table) throw new Error(`Invalid table name ${name}.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kysely-uow-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","cursorCondition: Condition | undefined","combinedWhere: Condition | undefined"],"sources":["../../../src/adapters/kysely/kysely-uow-compiler.ts"],"sourcesContent":["import type { CompiledQuery } from \"kysely\";\nimport type { AnyColumn, AnySchema, FragnoId } from \"../../schema/create\";\nimport type {\n CompiledMutation,\n MutationOperation,\n RetrievalOperation,\n UOWCompiler,\n} from \"../../query/unit-of-work\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport { createKyselyQueryCompiler } from \"./kysely-query-compiler\";\nimport { createKyselyQueryBuilder } from \"./kysely-query-builder\";\nimport { buildCondition, type Condition } from \"../../query/condition-builder\";\nimport { decodeCursor, serializeCursorValues } from \"../../query/cursor\";\nimport type { AnySelectClause } from \"../../query/query\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Create a Kysely-specific Unit of Work compiler\n *\n * This compiler translates UOW operations into Kysely CompiledQuery objects\n * that can be executed as a batch/transaction.\n *\n * @param schema - The database schema\n * @param config - Kysely configuration\n * @param mapper - Optional table name mapper for namespace prefixing\n * @returns A UOWCompiler instance for Kysely\n */\nexport function createKyselyUOWCompiler<TSchema extends AnySchema>(\n schema: TSchema,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): UOWCompiler<TSchema, CompiledQuery> {\n const queryCompiler = createKyselyQueryCompiler(schema, config, mapper);\n const queryBuilder = createKyselyQueryBuilder(config.db, config.provider, mapper);\n const { provider } = config;\n\n function toTable(name: unknown) {\n const table = schema.tables[name as string];\n if (!table) {\n throw new Error(`Invalid table name ${name}.`);\n }\n return table;\n }\n\n return {\n compileRetrievalOperation(op: RetrievalOperation<TSchema>): CompiledQuery | null {\n switch (op.type) {\n case \"count\": {\n return queryCompiler.count(op.table.name, {\n where: op.options.where,\n });\n }\n\n case \"find\": {\n // Map UOW FindOptions to query compiler's FindManyOptions\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n // (which is the actual primary key and maintains insertion order)\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition\n let cursorCondition: Condition | undefined;\n\n if ((after || before) && indexColumns.length > 0) {\n const cursor = after || before;\n const cursorData = decodeCursor(cursor!);\n const serializedValues = serializeCursorValues(cursorData, indexColumns, provider);\n\n // Build tuple comparison for cursor pagination\n // For \"after\" with \"asc\": (col1, col2, ...) > (val1, val2, ...)\n // For \"before\" with \"desc\": reverse the comparison\n const isAfter = !!after;\n const useGreaterThan =\n (isAfter && orderDirection === \"asc\") || (!isAfter && orderDirection === \"desc\");\n\n if (indexColumns.length === 1) {\n // Simple single-column case\n const col = indexColumns[0]!;\n const val = serializedValues[col.ormName];\n const operator = useGreaterThan ? \">\" : \"<\";\n cursorCondition = {\n type: \"compare\",\n a: col,\n operator,\n b: val,\n };\n } else {\n // Multi-column tuple comparison - not yet supported for Kysely\n throw new Error(\n \"Multi-column cursor pagination is not yet supported in Kysely Unit of Work implementation\",\n );\n }\n }\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // When we have joins or need to bypass buildFindOptions, use queryBuilder directly\n if (join && join.length > 0) {\n return queryBuilder.findMany(op.table, {\n // Safe cast: select from UOW matches SimplifyFindOptions requirement\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: pageSize,\n join,\n });\n }\n\n return queryCompiler.findMany(op.table.name, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.ormName, dir]),\n limit: pageSize,\n });\n }\n }\n },\n\n compileMutationOperation(\n op: MutationOperation<TSchema>,\n ): CompiledMutation<CompiledQuery> | null {\n switch (op.type) {\n case \"create\":\n // queryCompiler.create() calls encodeValues() which handles runtime defaults\n return {\n query: queryCompiler.create(op.table, op.values),\n expectedAffectedRows: null, // creates don't need affected row checks\n };\n\n case \"update\": {\n const table = toTable(op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = typeof op.id === \"string\" ? op.id : op.id.externalId;\n const versionToCheck = getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const whereClause =\n versionToCheck !== undefined\n ? () =>\n buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : () => buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n const query = queryCompiler.updateMany(op.table, {\n where: whereClause,\n set: op.set,\n });\n\n return query\n ? {\n query,\n expectedAffectedRows: op.checkVersion ? 1 : null,\n }\n : null;\n }\n\n case \"delete\": {\n const table = toTable(op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n // Extract external ID based on whether op.id is FragnoId or string\n const externalId = typeof op.id === \"string\" ? op.id : op.id.externalId;\n const versionToCheck = getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const whereClause =\n versionToCheck !== undefined\n ? () =>\n buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : () => buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n const query = queryCompiler.deleteMany(op.table, {\n where: whereClause,\n });\n\n return query\n ? {\n query,\n expectedAffectedRows: op.checkVersion ? 1 : null,\n }\n : null;\n }\n }\n },\n };\n}\n\n/**\n * Get the version to check for a given ID and checkVersion flag.\n * @returns The version to check or undefined if no check is required.\n * @throws Error if the ID is a string and checkVersion is true.\n */\nfunction getVersionToCheck(id: FragnoId | string, checkVersion: boolean): number | undefined {\n if (!checkVersion) {\n return undefined;\n }\n\n if (typeof id === \"string\") {\n throw new Error(\n `Cannot use checkVersion with a string ID. Version checking requires a FragnoId with version information.`,\n );\n }\n\n return id.version;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,SAAgB,wBACd,QACA,QACA,QACqC;CACrC,MAAM,gBAAgB,0BAA0B,QAAQ,QAAQ,OAAO;CACvE,MAAM,eAAe,yBAAyB,OAAO,IAAI,OAAO,UAAU,OAAO;CACjF,MAAM,EAAE,aAAa;CAErB,SAAS,QAAQ,MAAe;EAC9B,MAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,sBAAsB,KAAK,GAAG;AAEhD,SAAO;;AAGT,QAAO;EACL,0BAA0B,IAAuD;AAC/E,WAAQ,GAAG,MAAX;IACE,KAAK,QACH,QAAO,cAAc,MAAM,GAAG,MAAM,MAAM,EACxC,OAAO,GAAG,QAAQ,OACnB,CAAC;IAGJ,KAAK,QAAQ;KAEX,MAAM,EACJ,UAAU,WACV,cACA,OAAO,MACP,OACA,QACA,SACA,GAAG,oBACD,GAAG;KAGP,IAAIA,eAA4B,EAAE;KAClC,IAAIC,iBAAiC;AAErC,SAAI,cAAc;MAChB,MAAM,QAAQ,GAAG,MAAM,QAAQ,aAAa;AAC5C,uBAAiB,aAAa;AAE9B,UAAI,CAAC,MAGH,KAAI,aAAa,cAAc,WAC7B,gBAAe,CAAC,GAAG,MAAM,aAAa,CAAC;UAEvC,OAAM,IAAI,MACR,UAAU,aAAa,UAAU,wBAAwB,GAAG,MAAM,KAAK,GACxE;UAIH,gBAAe,MAAM;;KAKzB,IAAIC;AACJ,SAAI,aAAa,SAAS,EACxB,WAAU,aAAa,KAAK,QAAQ,CAAC,KAAK,eAAe,CAAC;KAI5D,IAAIC;AAEJ,UAAK,SAAS,WAAW,aAAa,SAAS,GAAG;MAGhD,MAAM,mBAAmB,sBADN,aADJ,SAAS,OACgB,EACmB,cAAc,SAAS;MAKlF,MAAM,UAAU,CAAC,CAAC;MAClB,MAAM,iBACH,WAAW,mBAAmB,SAAW,CAAC,WAAW,mBAAmB;AAE3E,UAAI,aAAa,WAAW,GAAG;OAE7B,MAAM,MAAM,aAAa;OACzB,MAAM,MAAM,iBAAiB,IAAI;AAEjC,yBAAkB;QAChB,MAAM;QACN,GAAG;QACH,UAJe,iBAAiB,MAAM;QAKtC,GAAG;QACJ;YAGD,OAAM,IAAI,MACR,4FACD;;KAKL,IAAIC;AACJ,SAAI,gBAAgB,OAAO;MACzB,MAAM,cAAc,eAAe,GAAG,MAAM,SAAS,gBAAgB,MAAM;AAC3E,UAAI,gBAAgB,KAClB,iBAAgB;eACP,gBAAgB,MACzB,QAAO;UAEP,iBAAgB;;AAIpB,SAAI,gBACF,KAAI,cACF,iBAAgB;MACd,MAAM;MACN,OAAO,CAAC,eAAe,gBAAgB;MACxC;SAED,iBAAgB;AAKpB,SAAI,QAAQ,KAAK,SAAS,EACxB,QAAO,aAAa,SAAS,GAAG,OAAO;MAErC,QAAS,gBAAgB,UAAU;MACnC,OAAO;MACP;MACA,OAAO;MACP;MACD,CAAC;AAGJ,YAAO,cAAc,SAAS,GAAG,MAAM,MAAM;MAC3C,GAAG;MACH,OAAO,sBAAsB,gBAAiB;MAC9C,SAAS,SAAS,KAAK,CAAC,KAAK,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;MACzD,OAAO;MACR,CAAC;;;;EAKR,yBACE,IACwC;AACxC,WAAQ,GAAG,MAAX;IACE,KAAK,SAEH,QAAO;KACL,OAAO,cAAc,OAAO,GAAG,OAAO,GAAG,OAAO;KAChD,sBAAsB;KACvB;IAEH,KAAK,UAAU;KACb,MAAM,QAAQ,QAAQ,GAAG,MAAM;KAC/B,MAAM,WAAW,MAAM,aAAa;KACpC,MAAM,gBAAgB,MAAM,kBAAkB;KAE9C,MAAM,aAAa,OAAO,GAAG,OAAO,WAAW,GAAG,KAAK,GAAG,GAAG;KAC7D,MAAM,iBAAiB,kBAAkB,GAAG,IAAI,GAAG,aAAa;KAGhE,MAAM,cACJ,mBAAmB,eAEb,eAAe,MAAM,UAAU,OAC7B,GAAG,IACD,GAAG,SAAS,SAAS,KAAK,WAAW,EACrC,GAAG,cAAc,SAAS,KAAK,eAAe,CAC/C,CACF,SACG,eAAe,MAAM,UAAU,OAAO,GAAG,SAAS,SAAS,KAAK,WAAW,CAAC;KAExF,MAAM,QAAQ,cAAc,WAAW,GAAG,OAAO;MAC/C,OAAO;MACP,KAAK,GAAG;MACT,CAAC;AAEF,YAAO,QACH;MACE;MACA,sBAAsB,GAAG,eAAe,IAAI;MAC7C,GACD;;IAGN,KAAK,UAAU;KACb,MAAM,QAAQ,QAAQ,GAAG,MAAM;KAC/B,MAAM,WAAW,MAAM,aAAa;KACpC,MAAM,gBAAgB,MAAM,kBAAkB;KAG9C,MAAM,aAAa,OAAO,GAAG,OAAO,WAAW,GAAG,KAAK,GAAG,GAAG;KAC7D,MAAM,iBAAiB,kBAAkB,GAAG,IAAI,GAAG,aAAa;KAGhE,MAAM,cACJ,mBAAmB,eAEb,eAAe,MAAM,UAAU,OAC7B,GAAG,IACD,GAAG,SAAS,SAAS,KAAK,WAAW,EACrC,GAAG,cAAc,SAAS,KAAK,eAAe,CAC/C,CACF,SACG,eAAe,MAAM,UAAU,OAAO,GAAG,SAAS,SAAS,KAAK,WAAW,CAAC;KAExF,MAAM,QAAQ,cAAc,WAAW,GAAG,OAAO,EAC/C,OAAO,aACR,CAAC;AAEF,YAAO,QACH;MACE;MACA,sBAAsB,GAAG,eAAe,IAAI;MAC7C,GACD;;;;EAIX;;;;;;;AAQH,SAAS,kBAAkB,IAAuB,cAA2C;AAC3F,KAAI,CAAC,aACH;AAGF,KAAI,OAAO,OAAO,SAChB,OAAM,IAAI,MACR,2GACD;AAGH,QAAO,GAAG"}
|
|
1
|
+
{"version":3,"file":"kysely-uow-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","cursorCondition: Condition | undefined","combinedWhere: Condition | undefined"],"sources":["../../../src/adapters/kysely/kysely-uow-compiler.ts"],"sourcesContent":["import type { CompiledQuery } from \"kysely\";\nimport type { AnyColumn, AnySchema, FragnoId } from \"../../schema/create\";\nimport type {\n CompiledMutation,\n MutationOperation,\n RetrievalOperation,\n UOWCompiler,\n} from \"../../query/unit-of-work\";\nimport type { KyselyConfig } from \"./kysely-adapter\";\nimport { createKyselyQueryCompiler } from \"./kysely-query-compiler\";\nimport { createKyselyQueryBuilder } from \"./kysely-query-builder\";\nimport { buildCondition, type Condition } from \"../../query/condition-builder\";\nimport { decodeCursor, serializeCursorValues } from \"../../query/cursor\";\nimport type { AnySelectClause } from \"../../query/query\";\nimport type { TableNameMapper } from \"./kysely-shared\";\n\n/**\n * Create a Kysely-specific Unit of Work compiler\n *\n * This compiler translates UOW operations into Kysely CompiledQuery objects\n * that can be executed as a batch/transaction.\n *\n * @param schema - The database schema\n * @param config - Kysely configuration\n * @param mapper - Optional table name mapper for namespace prefixing\n * @returns A UOWCompiler instance for Kysely\n */\nexport function createKyselyUOWCompiler<TSchema extends AnySchema>(\n schema: TSchema,\n config: KyselyConfig,\n mapper?: TableNameMapper,\n): UOWCompiler<TSchema, CompiledQuery> {\n const queryCompiler = createKyselyQueryCompiler(schema, config, mapper);\n const { db, provider } = config;\n // Resolve the db instance if it's a function\n const kysely = typeof db === \"function\" ? db() : db;\n const queryBuilder = createKyselyQueryBuilder(kysely, provider, mapper);\n\n function toTable(name: unknown) {\n const table = schema.tables[name as string];\n if (!table) {\n throw new Error(`Invalid table name ${name}.`);\n }\n return table;\n }\n\n return {\n compileRetrievalOperation(op: RetrievalOperation<TSchema>): CompiledQuery | null {\n switch (op.type) {\n case \"count\": {\n return queryCompiler.count(op.table.name, {\n where: op.options.where,\n });\n }\n\n case \"find\": {\n // Map UOW FindOptions to query compiler's FindManyOptions\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n // (which is the actual primary key and maintains insertion order)\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition\n let cursorCondition: Condition | undefined;\n\n if ((after || before) && indexColumns.length > 0) {\n const cursor = after || before;\n const cursorData = decodeCursor(cursor!);\n const serializedValues = serializeCursorValues(cursorData, indexColumns, provider);\n\n // Build tuple comparison for cursor pagination\n // For \"after\" with \"asc\": (col1, col2, ...) > (val1, val2, ...)\n // For \"before\" with \"desc\": reverse the comparison\n const isAfter = !!after;\n const useGreaterThan =\n (isAfter && orderDirection === \"asc\") || (!isAfter && orderDirection === \"desc\");\n\n if (indexColumns.length === 1) {\n // Simple single-column case\n const col = indexColumns[0]!;\n const val = serializedValues[col.ormName];\n const operator = useGreaterThan ? \">\" : \"<\";\n cursorCondition = {\n type: \"compare\",\n a: col,\n operator,\n b: val,\n };\n } else {\n // Multi-column tuple comparison - not yet supported for Kysely\n throw new Error(\n \"Multi-column cursor pagination is not yet supported in Kysely Unit of Work implementation\",\n );\n }\n }\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // When we have joins or need to bypass buildFindOptions, use queryBuilder directly\n if (join && join.length > 0) {\n return queryBuilder.findMany(op.table, {\n // Safe cast: select from UOW matches SimplifyFindOptions requirement\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: pageSize,\n join,\n });\n }\n\n return queryCompiler.findMany(op.table.name, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.ormName, dir]),\n limit: pageSize,\n });\n }\n }\n },\n\n compileMutationOperation(\n op: MutationOperation<TSchema>,\n ): CompiledMutation<CompiledQuery> | null {\n switch (op.type) {\n case \"create\":\n // queryCompiler.create() calls encodeValues() which handles runtime defaults\n return {\n query: queryCompiler.create(op.table, op.values),\n expectedAffectedRows: null, // creates don't need affected row checks\n };\n\n case \"update\": {\n const table = toTable(op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = typeof op.id === \"string\" ? op.id : op.id.externalId;\n const versionToCheck = getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const whereClause =\n versionToCheck !== undefined\n ? () =>\n buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : () => buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n const query = queryCompiler.updateMany(op.table, {\n where: whereClause,\n set: op.set,\n });\n\n return query\n ? {\n query,\n expectedAffectedRows: op.checkVersion ? 1 : null,\n }\n : null;\n }\n\n case \"delete\": {\n const table = toTable(op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n // Extract external ID based on whether op.id is FragnoId or string\n const externalId = typeof op.id === \"string\" ? op.id : op.id.externalId;\n const versionToCheck = getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const whereClause =\n versionToCheck !== undefined\n ? () =>\n buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : () => buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n const query = queryCompiler.deleteMany(op.table, {\n where: whereClause,\n });\n\n return query\n ? {\n query,\n expectedAffectedRows: op.checkVersion ? 1 : null,\n }\n : null;\n }\n }\n },\n };\n}\n\n/**\n * Get the version to check for a given ID and checkVersion flag.\n * @returns The version to check or undefined if no check is required.\n * @throws Error if the ID is a string and checkVersion is true.\n */\nfunction getVersionToCheck(id: FragnoId | string, checkVersion: boolean): number | undefined {\n if (!checkVersion) {\n return undefined;\n }\n\n if (typeof id === \"string\") {\n throw new Error(\n `Cannot use checkVersion with a string ID. Version checking requires a FragnoId with version information.`,\n );\n }\n\n return id.version;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,SAAgB,wBACd,QACA,QACA,QACqC;CACrC,MAAM,gBAAgB,0BAA0B,QAAQ,QAAQ,OAAO;CACvE,MAAM,EAAE,IAAI,aAAa;CAGzB,MAAM,eAAe,yBADN,OAAO,OAAO,aAAa,IAAI,GAAG,IACK,UAAU,OAAO;CAEvE,SAAS,QAAQ,MAAe;EAC9B,MAAM,QAAQ,OAAO,OAAO;AAC5B,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,sBAAsB,KAAK,GAAG;AAEhD,SAAO;;AAGT,QAAO;EACL,0BAA0B,IAAuD;AAC/E,WAAQ,GAAG,MAAX;IACE,KAAK,QACH,QAAO,cAAc,MAAM,GAAG,MAAM,MAAM,EACxC,OAAO,GAAG,QAAQ,OACnB,CAAC;IAGJ,KAAK,QAAQ;KAEX,MAAM,EACJ,UAAU,WACV,cACA,OAAO,MACP,OACA,QACA,SACA,GAAG,oBACD,GAAG;KAGP,IAAIA,eAA4B,EAAE;KAClC,IAAIC,iBAAiC;AAErC,SAAI,cAAc;MAChB,MAAM,QAAQ,GAAG,MAAM,QAAQ,aAAa;AAC5C,uBAAiB,aAAa;AAE9B,UAAI,CAAC,MAGH,KAAI,aAAa,cAAc,WAC7B,gBAAe,CAAC,GAAG,MAAM,aAAa,CAAC;UAEvC,OAAM,IAAI,MACR,UAAU,aAAa,UAAU,wBAAwB,GAAG,MAAM,KAAK,GACxE;UAIH,gBAAe,MAAM;;KAKzB,IAAIC;AACJ,SAAI,aAAa,SAAS,EACxB,WAAU,aAAa,KAAK,QAAQ,CAAC,KAAK,eAAe,CAAC;KAI5D,IAAIC;AAEJ,UAAK,SAAS,WAAW,aAAa,SAAS,GAAG;MAGhD,MAAM,mBAAmB,sBADN,aADJ,SAAS,OACgB,EACmB,cAAc,SAAS;MAKlF,MAAM,UAAU,CAAC,CAAC;MAClB,MAAM,iBACH,WAAW,mBAAmB,SAAW,CAAC,WAAW,mBAAmB;AAE3E,UAAI,aAAa,WAAW,GAAG;OAE7B,MAAM,MAAM,aAAa;OACzB,MAAM,MAAM,iBAAiB,IAAI;AAEjC,yBAAkB;QAChB,MAAM;QACN,GAAG;QACH,UAJe,iBAAiB,MAAM;QAKtC,GAAG;QACJ;YAGD,OAAM,IAAI,MACR,4FACD;;KAKL,IAAIC;AACJ,SAAI,gBAAgB,OAAO;MACzB,MAAM,cAAc,eAAe,GAAG,MAAM,SAAS,gBAAgB,MAAM;AAC3E,UAAI,gBAAgB,KAClB,iBAAgB;eACP,gBAAgB,MACzB,QAAO;UAEP,iBAAgB;;AAIpB,SAAI,gBACF,KAAI,cACF,iBAAgB;MACd,MAAM;MACN,OAAO,CAAC,eAAe,gBAAgB;MACxC;SAED,iBAAgB;AAKpB,SAAI,QAAQ,KAAK,SAAS,EACxB,QAAO,aAAa,SAAS,GAAG,OAAO;MAErC,QAAS,gBAAgB,UAAU;MACnC,OAAO;MACP;MACA,OAAO;MACP;MACD,CAAC;AAGJ,YAAO,cAAc,SAAS,GAAG,MAAM,MAAM;MAC3C,GAAG;MACH,OAAO,sBAAsB,gBAAiB;MAC9C,SAAS,SAAS,KAAK,CAAC,KAAK,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;MACzD,OAAO;MACR,CAAC;;;;EAKR,yBACE,IACwC;AACxC,WAAQ,GAAG,MAAX;IACE,KAAK,SAEH,QAAO;KACL,OAAO,cAAc,OAAO,GAAG,OAAO,GAAG,OAAO;KAChD,sBAAsB;KACvB;IAEH,KAAK,UAAU;KACb,MAAM,QAAQ,QAAQ,GAAG,MAAM;KAC/B,MAAM,WAAW,MAAM,aAAa;KACpC,MAAM,gBAAgB,MAAM,kBAAkB;KAE9C,MAAM,aAAa,OAAO,GAAG,OAAO,WAAW,GAAG,KAAK,GAAG,GAAG;KAC7D,MAAM,iBAAiB,kBAAkB,GAAG,IAAI,GAAG,aAAa;KAGhE,MAAM,cACJ,mBAAmB,eAEb,eAAe,MAAM,UAAU,OAC7B,GAAG,IACD,GAAG,SAAS,SAAS,KAAK,WAAW,EACrC,GAAG,cAAc,SAAS,KAAK,eAAe,CAC/C,CACF,SACG,eAAe,MAAM,UAAU,OAAO,GAAG,SAAS,SAAS,KAAK,WAAW,CAAC;KAExF,MAAM,QAAQ,cAAc,WAAW,GAAG,OAAO;MAC/C,OAAO;MACP,KAAK,GAAG;MACT,CAAC;AAEF,YAAO,QACH;MACE;MACA,sBAAsB,GAAG,eAAe,IAAI;MAC7C,GACD;;IAGN,KAAK,UAAU;KACb,MAAM,QAAQ,QAAQ,GAAG,MAAM;KAC/B,MAAM,WAAW,MAAM,aAAa;KACpC,MAAM,gBAAgB,MAAM,kBAAkB;KAG9C,MAAM,aAAa,OAAO,GAAG,OAAO,WAAW,GAAG,KAAK,GAAG,GAAG;KAC7D,MAAM,iBAAiB,kBAAkB,GAAG,IAAI,GAAG,aAAa;KAGhE,MAAM,cACJ,mBAAmB,eAEb,eAAe,MAAM,UAAU,OAC7B,GAAG,IACD,GAAG,SAAS,SAAS,KAAK,WAAW,EACrC,GAAG,cAAc,SAAS,KAAK,eAAe,CAC/C,CACF,SACG,eAAe,MAAM,UAAU,OAAO,GAAG,SAAS,SAAS,KAAK,WAAW,CAAC;KAExF,MAAM,QAAQ,cAAc,WAAW,GAAG,OAAO,EAC/C,OAAO,aACR,CAAC;AAEF,YAAO,QACH;MACE;MACA,sBAAsB,GAAG,eAAe,IAAI;MAC7C,GACD;;;;EAIX;;;;;;;AAQH,SAAS,kBAAkB,IAAuB,cAA2C;AAC3F,KAAI,CAAC,aACH;AAGF,KAAI,OAAO,OAAO,SAChB,OAAM,IAAI,MACR,2GACD;AAGH,QAAO,GAAG"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { SETTINGS_TABLE_NAME } from "../../../shared/settings-schema.js";
|
|
2
|
+
import { schemaToDBType } from "../../../schema/serialize.js";
|
|
3
|
+
import { sql } from "kysely";
|
|
4
|
+
|
|
5
|
+
//#region src/adapters/kysely/migration/execute-base.ts
|
|
6
|
+
/**
|
|
7
|
+
* Base migration executor with common functionality.
|
|
8
|
+
* Provider-specific executors should extend this class.
|
|
9
|
+
*/
|
|
10
|
+
var BaseMigrationExecutor = class {
|
|
11
|
+
constructor(db, provider) {
|
|
12
|
+
this.db = db;
|
|
13
|
+
this.provider = provider;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Default implementation: no preprocessing, no metadata.
|
|
17
|
+
* Providers can override to transform operations.
|
|
18
|
+
*/
|
|
19
|
+
preprocessOperations(operations) {
|
|
20
|
+
return operations;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get table name, applying namespace mapping if provided.
|
|
24
|
+
* Settings table is never namespaced.
|
|
25
|
+
*/
|
|
26
|
+
getTableName(tableName, mapper) {
|
|
27
|
+
return tableName === SETTINGS_TABLE_NAME ? tableName : mapper ? mapper.toPhysical(tableName) : tableName;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get column builder callback for creating/altering columns.
|
|
31
|
+
*/
|
|
32
|
+
getColumnBuilderCallback(col) {
|
|
33
|
+
return (build) => {
|
|
34
|
+
if (!col.isNullable) build = build.notNull();
|
|
35
|
+
if (col.role === "internal-id") {
|
|
36
|
+
build = build.primaryKey();
|
|
37
|
+
if (this.provider === "postgresql" || this.provider === "cockroachdb") {} else if (this.provider === "mysql") build = build.autoIncrement();
|
|
38
|
+
else if (this.provider === "sqlite") build = build.autoIncrement();
|
|
39
|
+
else if (this.provider === "mssql") build = build.identity();
|
|
40
|
+
}
|
|
41
|
+
if (col.role === "external-id") build = build.unique();
|
|
42
|
+
const defaultValue = this.defaultValueToDB(col);
|
|
43
|
+
if (defaultValue) build = build.defaultTo(defaultValue);
|
|
44
|
+
return build;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Convert column default value to database representation.
|
|
49
|
+
*/
|
|
50
|
+
defaultValueToDB(column) {
|
|
51
|
+
const value = column.default;
|
|
52
|
+
if (!value) return;
|
|
53
|
+
if (this.provider === "mysql" && column.type === "string") return;
|
|
54
|
+
if ("value" in value && value.value !== void 0) return sql.lit(value.value);
|
|
55
|
+
if ("dbSpecial" in value && value.dbSpecial === "now") return sql`CURRENT_TIMESTAMP`;
|
|
56
|
+
if ("runtime" in value) return;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Wrap a raw SQL builder in an ExecuteNode.
|
|
60
|
+
*/
|
|
61
|
+
rawToNode(raw) {
|
|
62
|
+
return {
|
|
63
|
+
compile: () => raw.compile(this.db),
|
|
64
|
+
execute: () => raw.execute(this.db)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the database type string for a column.
|
|
69
|
+
*/
|
|
70
|
+
getDBType(col) {
|
|
71
|
+
return schemaToDBType(col, this.provider);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Returns the appropriate foreign key action based on the provider.
|
|
76
|
+
* MSSQL doesn't support RESTRICT, so we use NO ACTION (functionally equivalent).
|
|
77
|
+
*/
|
|
78
|
+
function getForeignKeyAction(provider) {
|
|
79
|
+
return provider === "mssql" ? "no action" : "restrict";
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Generates MSSQL default constraint name following the DF_tableName_columnName pattern.
|
|
83
|
+
*/
|
|
84
|
+
function getMssqlDefaultConstraintName(tableName, columnName) {
|
|
85
|
+
return `DF_${tableName}_${columnName}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Generate SQL to drop MSSQL default constraint.
|
|
89
|
+
*/
|
|
90
|
+
function mssqlDropDefaultConstraint(tableName, columnName) {
|
|
91
|
+
return sql`
|
|
92
|
+
DECLARE @ConstraintName NVARCHAR(200);
|
|
93
|
+
|
|
94
|
+
SELECT @ConstraintName = dc.name
|
|
95
|
+
FROM sys.default_constraints dc
|
|
96
|
+
JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
|
|
97
|
+
JOIN sys.tables t ON t.object_id = c.object_id
|
|
98
|
+
JOIN sys.schemas s ON t.schema_id = s.schema_id
|
|
99
|
+
WHERE s.name = 'dbo' AND t.name = ${sql.lit(tableName)} AND c.name = ${sql.lit(columnName)};
|
|
100
|
+
|
|
101
|
+
IF @ConstraintName IS NOT NULL
|
|
102
|
+
BEGIN
|
|
103
|
+
EXEC('ALTER TABLE [dbo].[' + ${sql.lit(tableName)} + '] DROP CONSTRAINT [' + @ConstraintName + ']');
|
|
104
|
+
END`;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create a unique index with provider-specific handling.
|
|
108
|
+
*/
|
|
109
|
+
function createUniqueIndex(db, name, tableName, cols, provider) {
|
|
110
|
+
const query = db.schema.createIndex(name).on(tableName).columns(cols).unique();
|
|
111
|
+
if (provider === "mssql") return query.where((b) => {
|
|
112
|
+
return b.and(cols.map((col) => b(col, "is not", null)));
|
|
113
|
+
});
|
|
114
|
+
return query;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Drop a unique index with provider-specific handling.
|
|
118
|
+
*/
|
|
119
|
+
function dropUniqueIndex(db, name, tableName, provider) {
|
|
120
|
+
let query = db.schema.dropIndex(name).ifExists();
|
|
121
|
+
if (provider === "cockroachdb") query = query.cascade();
|
|
122
|
+
if (provider === "mssql") query = query.on(tableName);
|
|
123
|
+
return query;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
export { BaseMigrationExecutor, createUniqueIndex, dropUniqueIndex, getForeignKeyAction, getMssqlDefaultConstraintName, mssqlDropDefaultConstraint };
|
|
128
|
+
//# sourceMappingURL=execute-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-base.js","names":["db: KyselyAny","provider: SQLProvider"],"sources":["../../../../src/adapters/kysely/migration/execute-base.ts"],"sourcesContent":["import { type ColumnBuilderCallback, type Kysely, type RawBuilder, sql } from \"kysely\";\nimport type {\n ColumnInfo,\n MigrationOperation,\n MigrationOperationMetadata,\n} from \"../../../migration-engine/shared\";\nimport type { SQLProvider } from \"../../../shared/providers\";\nimport { schemaToDBType } from \"../../../schema/serialize\";\nimport type { TableNameMapper } from \"../kysely-shared\";\nimport { SETTINGS_TABLE_NAME } from \"../../../shared/settings-schema\";\n\nexport type ExecuteNode = {\n compile(): { sql: string; parameters: readonly unknown[] };\n execute(): Promise<unknown>;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KyselyAny = Kysely<any>;\n\n/**\n * Migration executor interface.\n * Each provider implements this to handle database-specific migration execution.\n */\nexport interface MigrationExecutor<\n TMeta extends MigrationOperationMetadata = MigrationOperationMetadata,\n> {\n /**\n * Preprocess operations before execution.\n * Allows executors to combine, split, or transform operations based on provider capabilities.\n *\n * For example, SQLite can merge add-foreign-key operations into create-table operations.\n */\n preprocessOperations(operations: MigrationOperation[]): MigrationOperation<TMeta>[];\n\n /**\n * Execute a single migration operation.\n */\n executeOperation(\n operation: MigrationOperation<TMeta>,\n mapper?: TableNameMapper,\n ): ExecuteNode | ExecuteNode[];\n}\n\n/**\n * Base migration executor with common functionality.\n * Provider-specific executors should extend this class.\n */\nexport abstract class BaseMigrationExecutor<\n TMeta extends MigrationOperationMetadata = MigrationOperationMetadata,\n> implements MigrationExecutor<TMeta>\n{\n constructor(\n protected readonly db: KyselyAny,\n protected readonly provider: SQLProvider,\n ) {}\n\n /**\n * Default implementation: no preprocessing, no metadata.\n * Providers can override to transform operations.\n */\n preprocessOperations(operations: MigrationOperation[]): MigrationOperation<TMeta>[] {\n return operations as MigrationOperation<TMeta>[];\n }\n\n /**\n * Execute a single migration operation.\n * Must be implemented by provider-specific executors.\n */\n abstract executeOperation(\n operation: MigrationOperation<TMeta>,\n mapper?: TableNameMapper,\n ): ExecuteNode | ExecuteNode[];\n\n /**\n * Get table name, applying namespace mapping if provided.\n * Settings table is never namespaced.\n */\n protected getTableName(tableName: string, mapper?: TableNameMapper): string {\n return tableName === SETTINGS_TABLE_NAME\n ? tableName\n : mapper\n ? mapper.toPhysical(tableName)\n : tableName;\n }\n\n /**\n * Get column builder callback for creating/altering columns.\n */\n protected getColumnBuilderCallback(col: ColumnInfo): ColumnBuilderCallback {\n return (build) => {\n if (!col.isNullable) {\n build = build.notNull();\n }\n\n // Internal ID is the primary key with auto-increment\n if (col.role === \"internal-id\") {\n build = build.primaryKey();\n // Auto-increment for internal ID\n if (this.provider === \"postgresql\" || this.provider === \"cockroachdb\") {\n // SERIAL/BIGSERIAL handles auto-increment\n // Already handled in schemaToDBType\n } else if (this.provider === \"mysql\") {\n build = build.autoIncrement();\n } else if (this.provider === \"sqlite\") {\n build = build.autoIncrement();\n } else if (this.provider === \"mssql\") {\n build = build.identity();\n }\n }\n\n // External ID must be unique\n if (col.role === \"external-id\") {\n build = build.unique();\n }\n\n const defaultValue = this.defaultValueToDB(col);\n if (defaultValue) {\n build = build.defaultTo(defaultValue);\n }\n return build;\n };\n }\n\n /**\n * Convert column default value to database representation.\n */\n protected defaultValueToDB(column: ColumnInfo): RawBuilder<unknown> | undefined {\n const value = column.default;\n if (!value) {\n return undefined;\n }\n\n // MySQL doesn't support default values for TEXT columns\n if (this.provider === \"mysql\" && column.type === \"string\") {\n return undefined;\n }\n\n // Static default values: defaultTo(value)\n if (\"value\" in value && value.value !== undefined) {\n return sql.lit(value.value);\n }\n\n // Database-level special functions: defaultTo(b => b.now())\n if (\"dbSpecial\" in value && value.dbSpecial === \"now\") {\n return sql`CURRENT_TIMESTAMP`;\n }\n\n // Runtime defaults (defaultTo$) are NOT generated in SQL - they're handled in application code\n if (\"runtime\" in value) {\n return undefined;\n }\n\n return undefined;\n }\n\n /**\n * Wrap a raw SQL builder in an ExecuteNode.\n */\n protected rawToNode(raw: RawBuilder<unknown>): ExecuteNode {\n return {\n compile: () => raw.compile(this.db),\n execute: () => raw.execute(this.db),\n };\n }\n\n /**\n * Get the database type string for a column.\n */\n protected getDBType(col: ColumnInfo): string {\n return schemaToDBType(col, this.provider);\n }\n}\n\n// ============================================================================\n// Provider-Specific Helper Functions\n// ============================================================================\n\n/**\n * Returns the appropriate foreign key action based on the provider.\n * MSSQL doesn't support RESTRICT, so we use NO ACTION (functionally equivalent).\n */\nexport function getForeignKeyAction(provider: SQLProvider): \"restrict\" | \"no action\" {\n return provider === \"mssql\" ? \"no action\" : \"restrict\";\n}\n\n/**\n * Generates MSSQL default constraint name following the DF_tableName_columnName pattern.\n */\nexport function getMssqlDefaultConstraintName(tableName: string, columnName: string): string {\n const MSSQL_DEFAULT_CONSTRAINT_PREFIX = \"DF\" as const;\n return `${MSSQL_DEFAULT_CONSTRAINT_PREFIX}_${tableName}_${columnName}`;\n}\n\n/**\n * Generate SQL to drop MSSQL default constraint.\n */\nexport function mssqlDropDefaultConstraint(tableName: string, columnName: string) {\n return sql`\nDECLARE @ConstraintName NVARCHAR(200);\n\nSELECT @ConstraintName = dc.name\nFROM sys.default_constraints dc\nJOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id\nJOIN sys.tables t ON t.object_id = c.object_id\nJOIN sys.schemas s ON t.schema_id = s.schema_id\nWHERE s.name = 'dbo' AND t.name = ${sql.lit(tableName)} AND c.name = ${sql.lit(columnName)};\n\nIF @ConstraintName IS NOT NULL\nBEGIN\n EXEC('ALTER TABLE [dbo].[' + ${sql.lit(tableName)} + '] DROP CONSTRAINT [' + @ConstraintName + ']');\nEND`;\n}\n\n/**\n * Create a unique index with provider-specific handling.\n */\nexport function createUniqueIndex(\n db: KyselyAny,\n name: string,\n tableName: string,\n cols: string[],\n provider: SQLProvider,\n) {\n const query = db.schema.createIndex(name).on(tableName).columns(cols).unique();\n\n if (provider === \"mssql\") {\n // MSSQL: ignore null values in unique indexes by default\n return query.where((b) => {\n return b.and(cols.map((col) => b(col, \"is not\", null)));\n });\n }\n\n return query;\n}\n\n/**\n * Drop a unique index with provider-specific handling.\n */\nexport function dropUniqueIndex(\n db: KyselyAny,\n name: string,\n tableName: string,\n provider: SQLProvider,\n) {\n let query = db.schema.dropIndex(name).ifExists();\n\n if (provider === \"cockroachdb\") {\n query = query.cascade();\n }\n\n if (provider === \"mssql\") {\n query = query.on(tableName);\n }\n\n return query;\n}\n"],"mappings":";;;;;;;;;AA+CA,IAAsB,wBAAtB,MAGA;CACE,YACE,AAAmBA,IACnB,AAAmBC,UACnB;EAFmB;EACA;;;;;;CAOrB,qBAAqB,YAA+D;AAClF,SAAO;;;;;;CAgBT,AAAU,aAAa,WAAmB,QAAkC;AAC1E,SAAO,cAAc,sBACjB,YACA,SACE,OAAO,WAAW,UAAU,GAC5B;;;;;CAMR,AAAU,yBAAyB,KAAwC;AACzE,UAAQ,UAAU;AAChB,OAAI,CAAC,IAAI,WACP,SAAQ,MAAM,SAAS;AAIzB,OAAI,IAAI,SAAS,eAAe;AAC9B,YAAQ,MAAM,YAAY;AAE1B,QAAI,KAAK,aAAa,gBAAgB,KAAK,aAAa,eAAe,YAG5D,KAAK,aAAa,QAC3B,SAAQ,MAAM,eAAe;aACpB,KAAK,aAAa,SAC3B,SAAQ,MAAM,eAAe;aACpB,KAAK,aAAa,QAC3B,SAAQ,MAAM,UAAU;;AAK5B,OAAI,IAAI,SAAS,cACf,SAAQ,MAAM,QAAQ;GAGxB,MAAM,eAAe,KAAK,iBAAiB,IAAI;AAC/C,OAAI,aACF,SAAQ,MAAM,UAAU,aAAa;AAEvC,UAAO;;;;;;CAOX,AAAU,iBAAiB,QAAqD;EAC9E,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MACH;AAIF,MAAI,KAAK,aAAa,WAAW,OAAO,SAAS,SAC/C;AAIF,MAAI,WAAW,SAAS,MAAM,UAAU,OACtC,QAAO,IAAI,IAAI,MAAM,MAAM;AAI7B,MAAI,eAAe,SAAS,MAAM,cAAc,MAC9C,QAAO,GAAG;AAIZ,MAAI,aAAa,MACf;;;;;CASJ,AAAU,UAAU,KAAuC;AACzD,SAAO;GACL,eAAe,IAAI,QAAQ,KAAK,GAAG;GACnC,eAAe,IAAI,QAAQ,KAAK,GAAG;GACpC;;;;;CAMH,AAAU,UAAU,KAAyB;AAC3C,SAAO,eAAe,KAAK,KAAK,SAAS;;;;;;;AAY7C,SAAgB,oBAAoB,UAAiD;AACnF,QAAO,aAAa,UAAU,cAAc;;;;;AAM9C,SAAgB,8BAA8B,WAAmB,YAA4B;AAE3F,QAAO,MAAsC,UAAU,GAAG;;;;;AAM5D,SAAgB,2BAA2B,WAAmB,YAAoB;AAChF,QAAO,GAAG;;;;;;;;oCAQwB,IAAI,IAAI,UAAU,CAAC,gBAAgB,IAAI,IAAI,WAAW,CAAC;;;;mCAIxD,IAAI,IAAI,UAAU,CAAC;;;;;;AAOtD,SAAgB,kBACd,IACA,MACA,WACA,MACA,UACA;CACA,MAAM,QAAQ,GAAG,OAAO,YAAY,KAAK,CAAC,GAAG,UAAU,CAAC,QAAQ,KAAK,CAAC,QAAQ;AAE9E,KAAI,aAAa,QAEf,QAAO,MAAM,OAAO,MAAM;AACxB,SAAO,EAAE,IAAI,KAAK,KAAK,QAAQ,EAAE,KAAK,UAAU,KAAK,CAAC,CAAC;GACvD;AAGJ,QAAO;;;;;AAMT,SAAgB,gBACd,IACA,MACA,WACA,UACA;CACA,IAAI,QAAQ,GAAG,OAAO,UAAU,KAAK,CAAC,UAAU;AAEhD,KAAI,aAAa,cACf,SAAQ,MAAM,SAAS;AAGzB,KAAI,aAAa,QACf,SAAQ,MAAM,GAAG,UAAU;AAG7B,QAAO"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SqliteMigrationExecutor } from "./execute-sqlite.js";
|
|
2
|
+
import { PostgresMigrationExecutor } from "./execute-postgres.js";
|
|
3
|
+
import { MysqlMigrationExecutor } from "./execute-mysql.js";
|
|
4
|
+
import { MssqlMigrationExecutor } from "./execute-mssql.js";
|
|
5
|
+
|
|
6
|
+
//#region src/adapters/kysely/migration/execute-factory.ts
|
|
7
|
+
/**
|
|
8
|
+
* Create a provider-specific migration executor.
|
|
9
|
+
*/
|
|
10
|
+
function createMigrationExecutor(config) {
|
|
11
|
+
const { db, provider } = config;
|
|
12
|
+
const kysely = typeof db === "function" ? db() : db;
|
|
13
|
+
switch (provider) {
|
|
14
|
+
case "sqlite": return new SqliteMigrationExecutor(kysely, provider);
|
|
15
|
+
case "postgresql":
|
|
16
|
+
case "cockroachdb": return new PostgresMigrationExecutor(kysely, provider);
|
|
17
|
+
case "mysql": return new MysqlMigrationExecutor(kysely, provider);
|
|
18
|
+
case "mssql": return new MssqlMigrationExecutor(kysely, provider);
|
|
19
|
+
default: {
|
|
20
|
+
const _exhaustive = provider;
|
|
21
|
+
throw new Error(`Unsupported provider: ${_exhaustive}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { createMigrationExecutor };
|
|
28
|
+
//# sourceMappingURL=execute-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-factory.js","names":["_exhaustive: never"],"sources":["../../../../src/adapters/kysely/migration/execute-factory.ts"],"sourcesContent":["import type { KyselyConfig } from \"../kysely-adapter\";\nimport type { MigrationExecutor } from \"./execute-base\";\nimport { SqliteMigrationExecutor } from \"./execute-sqlite\";\nimport { PostgresMigrationExecutor } from \"./execute-postgres\";\nimport { MysqlMigrationExecutor } from \"./execute-mysql\";\nimport { MssqlMigrationExecutor } from \"./execute-mssql\";\n\n/**\n * Create a provider-specific migration executor.\n */\nexport function createMigrationExecutor(config: KyselyConfig): MigrationExecutor {\n const { db, provider } = config;\n // Resolve the db instance if it's a function\n const kysely = typeof db === \"function\" ? db() : db;\n\n switch (provider) {\n case \"sqlite\":\n return new SqliteMigrationExecutor(kysely, provider);\n case \"postgresql\":\n case \"cockroachdb\":\n return new PostgresMigrationExecutor(kysely, provider);\n case \"mysql\":\n return new MysqlMigrationExecutor(kysely, provider);\n case \"mssql\":\n return new MssqlMigrationExecutor(kysely, provider);\n default: {\n // Ensure exhaustive switch\n const _exhaustive: never = provider;\n throw new Error(`Unsupported provider: ${_exhaustive}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;AAUA,SAAgB,wBAAwB,QAAyC;CAC/E,MAAM,EAAE,IAAI,aAAa;CAEzB,MAAM,SAAS,OAAO,OAAO,aAAa,IAAI,GAAG;AAEjD,SAAQ,UAAR;EACE,KAAK,SACH,QAAO,IAAI,wBAAwB,QAAQ,SAAS;EACtD,KAAK;EACL,KAAK,cACH,QAAO,IAAI,0BAA0B,QAAQ,SAAS;EACxD,KAAK,QACH,QAAO,IAAI,uBAAuB,QAAQ,SAAS;EACrD,KAAK,QACH,QAAO,IAAI,uBAAuB,QAAQ,SAAS;EACrD,SAAS;GAEP,MAAMA,cAAqB;AAC3B,SAAM,IAAI,MAAM,yBAAyB,cAAc"}
|