@fragno-dev/db 0.1.0 → 0.1.2
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 +63 -55
- package/CHANGELOG.md +18 -0
- package/dist/adapters/adapters.d.ts +11 -1
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +9 -2
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +21 -39
- package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-query.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-query.js +3 -2
- package/dist/adapters/drizzle/drizzle-query.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-compiler.js +7 -5
- package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-uow-executor.js.map +1 -1
- package/dist/adapters/drizzle/generate.js +107 -34
- package/dist/adapters/drizzle/generate.js.map +1 -1
- package/dist/adapters/drizzle/shared.js +14 -1
- package/dist/adapters/drizzle/shared.js.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts +2 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.js +25 -30
- package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
- package/dist/adapters/kysely/kysely-query-builder.js +48 -44
- package/dist/adapters/kysely/kysely-query-builder.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 +3 -2
- package/dist/adapters/kysely/kysely-query.js.map +1 -1
- package/dist/adapters/kysely/kysely-shared.js +18 -0
- package/dist/adapters/kysely/kysely-shared.js.map +1 -0
- package/dist/adapters/kysely/kysely-uow-compiler.js +4 -3
- package/dist/adapters/kysely/kysely-uow-compiler.js.map +1 -1
- package/dist/adapters/kysely/migration/execute.js +15 -12
- package/dist/adapters/kysely/migration/execute.js.map +1 -1
- package/dist/migration-engine/auto-from-schema.js +2 -8
- package/dist/migration-engine/auto-from-schema.js.map +1 -1
- package/dist/migration-engine/create.d.ts +1 -5
- package/dist/migration-engine/create.js +1 -1
- package/dist/migration-engine/create.js.map +1 -1
- package/dist/migration-engine/generation-engine.d.ts +51 -0
- package/dist/migration-engine/generation-engine.d.ts.map +1 -0
- package/dist/migration-engine/generation-engine.js +165 -0
- package/dist/migration-engine/generation-engine.js.map +1 -0
- package/dist/migration-engine/shared.d.ts +5 -2
- package/dist/migration-engine/shared.d.ts.map +1 -1
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/mod.d.ts +0 -8
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +0 -32
- package/dist/mod.js.map +1 -1
- package/dist/query/condition-builder.js.map +1 -1
- package/dist/query/query.d.ts +2 -2
- package/dist/query/query.d.ts.map +1 -1
- package/dist/query/result-transform.js +2 -1
- package/dist/query/result-transform.js.map +1 -1
- package/dist/schema/create.d.ts +74 -16
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +76 -11
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/serialize.js.map +1 -1
- package/dist/shared/settings-schema.js +36 -0
- package/dist/shared/settings-schema.js.map +1 -0
- package/dist/util/import-generator.js.map +1 -1
- package/dist/util/parse.js.map +1 -1
- package/package.json +10 -6
- package/src/adapters/adapters.ts +10 -3
- package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +11 -7
- package/src/adapters/drizzle/drizzle-adapter.test.ts +77 -29
- package/src/adapters/drizzle/drizzle-adapter.ts +31 -78
- package/src/adapters/drizzle/drizzle-query.ts +4 -7
- package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +10 -4
- package/src/adapters/drizzle/drizzle-uow-compiler.ts +12 -6
- package/src/adapters/drizzle/drizzle-uow-decoder.ts +1 -1
- package/src/adapters/drizzle/drizzle-uow-executor.ts +1 -1
- package/src/adapters/drizzle/generate.test.ts +573 -150
- package/src/adapters/drizzle/generate.ts +187 -36
- package/src/adapters/drizzle/migrate-drizzle.test.ts +30 -6
- package/src/adapters/drizzle/shared.ts +31 -1
- package/src/adapters/drizzle/test-utils.ts +3 -1
- package/src/adapters/kysely/kysely-adapter-pglite.test.ts +25 -27
- package/src/adapters/kysely/kysely-adapter.ts +35 -58
- package/src/adapters/kysely/kysely-query-builder.ts +75 -44
- package/src/adapters/kysely/kysely-query-compiler.ts +3 -1
- package/src/adapters/kysely/kysely-query.ts +9 -3
- package/src/adapters/kysely/kysely-shared.ts +23 -0
- package/src/adapters/kysely/kysely-uow-compiler.ts +5 -2
- package/src/adapters/kysely/migration/execute-mysql.test.ts +2 -2
- package/src/adapters/kysely/migration/execute-postgres.test.ts +19 -19
- package/src/adapters/kysely/migration/execute.ts +48 -17
- package/src/adapters/kysely/migration/kysely-migrator.test.ts +19 -37
- package/src/fragment.test.ts +48 -1
- package/src/migration-engine/auto-from-schema.ts +14 -18
- package/src/migration-engine/create.ts +1 -6
- package/src/migration-engine/generation-engine.test.ts +597 -0
- package/src/migration-engine/generation-engine.ts +356 -0
- package/src/migration-engine/shared.ts +1 -4
- package/src/mod.ts +0 -66
- package/src/query/condition-builder.ts +24 -8
- package/src/query/query.ts +4 -2
- package/src/query/result-transform.ts +7 -1
- package/src/schema/create.test.ts +4 -1
- package/src/schema/create.ts +132 -24
- package/src/schema/serialize.ts +21 -7
- package/src/shared/settings-schema.ts +61 -0
- package/src/util/deep-equal.ts +21 -7
- package/src/util/import-generator.ts +3 -1
- package/src/util/parse.ts +3 -1
- package/tsdown.config.ts +1 -0
- package/.turbo/turbo-test.log +0 -36
- package/.turbo/turbo-types$colon$check.log +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { column, idColumn, schema } from "../schema/create.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/settings-schema.ts
|
|
4
|
+
const SETTINGS_TABLE_NAME = "fragno_db_settings";
|
|
5
|
+
const SETTINGS_NAMESPACE = "fragno-db-settings";
|
|
6
|
+
const settingsSchema = schema((s) => {
|
|
7
|
+
return s.addTable(SETTINGS_TABLE_NAME, (t) => {
|
|
8
|
+
return t.addColumn("id", idColumn()).addColumn("key", column("string")).addColumn("value", column("string")).createIndex("unique_key", ["key"], { unique: true });
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
function createSettingsManager(queryEngine, namespace) {
|
|
12
|
+
return {
|
|
13
|
+
async get(key) {
|
|
14
|
+
const [[result]] = await queryEngine.createUnitOfWork().find(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", `${namespace}.${key}`))).executeRetrieve();
|
|
15
|
+
return result;
|
|
16
|
+
},
|
|
17
|
+
async set(key, value) {
|
|
18
|
+
const uow = queryEngine.createUnitOfWork("createSettingsManager#set").find(SETTINGS_TABLE_NAME, (b) => b.whereIndex("unique_key", (eb) => eb("key", "=", `${namespace}.${key}`)));
|
|
19
|
+
const [[existing]] = await uow.executeRetrieve();
|
|
20
|
+
if (existing) uow.update(SETTINGS_TABLE_NAME, existing.id, (b) => b.set({ value }).check());
|
|
21
|
+
else uow.create(SETTINGS_TABLE_NAME, {
|
|
22
|
+
key: `${namespace}.${key}`,
|
|
23
|
+
value
|
|
24
|
+
});
|
|
25
|
+
const { success } = await uow.executeMutations();
|
|
26
|
+
if (!success) throw new Error("Failed to set schema version");
|
|
27
|
+
},
|
|
28
|
+
async delete(id) {
|
|
29
|
+
await queryEngine.delete(SETTINGS_TABLE_NAME, id);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { SETTINGS_NAMESPACE, SETTINGS_TABLE_NAME, createSettingsManager, settingsSchema };
|
|
36
|
+
//# sourceMappingURL=settings-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-schema.js","names":[],"sources":["../../src/shared/settings-schema.ts"],"sourcesContent":["import type { AbstractQuery } from \"../query/query\";\nimport { schema, idColumn, column, type FragnoId } from \"../schema/create\";\n\nexport const SETTINGS_TABLE_NAME = \"fragno_db_settings\" as const;\nexport const SETTINGS_NAMESPACE = \"fragno-db-settings\" as const;\n\nexport const settingsSchema = schema((s) => {\n return s.addTable(SETTINGS_TABLE_NAME, (t) => {\n return t\n .addColumn(\"id\", idColumn())\n .addColumn(\"key\", column(\"string\"))\n .addColumn(\"value\", column(\"string\"))\n .createIndex(\"unique_key\", [\"key\"], { unique: true });\n });\n});\n\nexport function createSettingsManager(\n // oxlint-disable-next-line no-explicit-any\n queryEngine: AbstractQuery<typeof settingsSchema, any>,\n namespace: string,\n) {\n return {\n async get(key: string): Promise<{ id: FragnoId; key: string; value: string } | undefined> {\n const uow = queryEngine\n .createUnitOfWork()\n .find(SETTINGS_TABLE_NAME, (b) =>\n b.whereIndex(\"unique_key\", (eb) => eb(\"key\", \"=\", `${namespace}.${key}`)),\n );\n const [[result]] = await uow.executeRetrieve();\n return result; // Safe: result can be undefined if key doesn't exist\n },\n\n async set(key: string, value: string) {\n const uow = queryEngine\n .createUnitOfWork(\"createSettingsManager#set\")\n .find(SETTINGS_TABLE_NAME, (b) =>\n b.whereIndex(\"unique_key\", (eb) => eb(\"key\", \"=\", `${namespace}.${key}`)),\n );\n const [[existing]] = await uow.executeRetrieve();\n\n if (existing) {\n uow.update(SETTINGS_TABLE_NAME, existing.id, (b) => b.set({ value }).check());\n } else {\n uow.create(SETTINGS_TABLE_NAME, {\n key: `${namespace}.${key}`,\n value,\n });\n }\n\n const { success } = await uow.executeMutations();\n\n if (!success) {\n throw new Error(\"Failed to set schema version\");\n }\n },\n\n async delete(id: FragnoId) {\n await queryEngine.delete(SETTINGS_TABLE_NAME, id);\n },\n };\n}\n"],"mappings":";;;AAGA,MAAa,sBAAsB;AACnC,MAAa,qBAAqB;AAElC,MAAa,iBAAiB,QAAQ,MAAM;AAC1C,QAAO,EAAE,SAAS,sBAAsB,MAAM;AAC5C,SAAO,EACJ,UAAU,MAAM,UAAU,CAAC,CAC3B,UAAU,OAAO,OAAO,SAAS,CAAC,CAClC,UAAU,SAAS,OAAO,SAAS,CAAC,CACpC,YAAY,cAAc,CAAC,MAAM,EAAE,EAAE,QAAQ,MAAM,CAAC;GACvD;EACF;AAEF,SAAgB,sBAEd,aACA,WACA;AACA,QAAO;EACL,MAAM,IAAI,KAAgF;GAMxF,MAAM,CAAC,CAAC,WAAW,MALP,YACT,kBAAkB,CAClB,KAAK,sBAAsB,MAC1B,EAAE,WAAW,eAAe,OAAO,GAAG,OAAO,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC,CAC1E,CAC0B,iBAAiB;AAC9C,UAAO;;EAGT,MAAM,IAAI,KAAa,OAAe;GACpC,MAAM,MAAM,YACT,iBAAiB,4BAA4B,CAC7C,KAAK,sBAAsB,MAC1B,EAAE,WAAW,eAAe,OAAO,GAAG,OAAO,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC,CAC1E;GACH,MAAM,CAAC,CAAC,aAAa,MAAM,IAAI,iBAAiB;AAEhD,OAAI,SACF,KAAI,OAAO,qBAAqB,SAAS,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC;OAE7E,KAAI,OAAO,qBAAqB;IAC9B,KAAK,GAAG,UAAU,GAAG;IACrB;IACD,CAAC;GAGJ,MAAM,EAAE,YAAY,MAAM,IAAI,kBAAkB;AAEhD,OAAI,CAAC,QACH,OAAM,IAAI,MAAM,+BAA+B;;EAInD,MAAM,OAAO,IAAc;AACzB,SAAM,YAAY,OAAO,qBAAqB,GAAG;;EAEpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-generator.js","names":["v: string[]","names"],"sources":["../../src/util/import-generator.ts"],"sourcesContent":["export function importGenerator() {\n const names = new Set<string>();\n // specifier -> import name\n const map = new Map<string, string[]>();\n\n return {\n addImport(name: string, specifier: string) {\n if (names.has(name)) {\n return;\n }\n\n names.add(name);\n const list = map.get(specifier) ?? [];\n list.push(name);\n map.set(specifier, list);\n },\n format(): string {\n const v: string[] = [];\n for (const [specifier, names] of map) {\n if (names.length === 0) continue;\n\n v.push(`import { ${names.join(\", \")} } from \"${specifier}\"`);\n }\n\n return v.join(\"\\n\");\n },\n };\n}\n"],"mappings":";AAAA,SAAgB,kBAAkB;CAChC,MAAM,wBAAQ,IAAI,KAAa;CAE/B,MAAM,sBAAM,IAAI,KAAuB;AAEvC,QAAO;EACL,UAAU,MAAc,WAAmB;AACzC,OAAI,MAAM,IAAI,KAAK,CACjB;AAGF,SAAM,IAAI,KAAK;GACf,MAAM,OAAO,IAAI,IAAI,UAAU,IAAI,EAAE;AACrC,QAAK,KAAK,KAAK;AACf,OAAI,IAAI,WAAW,KAAK;;EAE1B,SAAiB;GACf,MAAMA,IAAc,EAAE;AACtB,QAAK,MAAM,CAAC,WAAWC,YAAU,KAAK;AACpC,QAAIA,QAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"import-generator.js","names":["v: string[]","names"],"sources":["../../src/util/import-generator.ts"],"sourcesContent":["export function importGenerator() {\n const names = new Set<string>();\n // specifier -> import name\n const map = new Map<string, string[]>();\n\n return {\n addImport(name: string, specifier: string) {\n if (names.has(name)) {\n return;\n }\n\n names.add(name);\n const list = map.get(specifier) ?? [];\n list.push(name);\n map.set(specifier, list);\n },\n format(): string {\n const v: string[] = [];\n for (const [specifier, names] of map) {\n if (names.length === 0) {\n continue;\n }\n\n v.push(`import { ${names.join(\", \")} } from \"${specifier}\"`);\n }\n\n return v.join(\"\\n\");\n },\n };\n}\n"],"mappings":";AAAA,SAAgB,kBAAkB;CAChC,MAAM,wBAAQ,IAAI,KAAa;CAE/B,MAAM,sBAAM,IAAI,KAAuB;AAEvC,QAAO;EACL,UAAU,MAAc,WAAmB;AACzC,OAAI,MAAM,IAAI,KAAK,CACjB;AAGF,SAAM,IAAI,KAAK;GACf,MAAM,OAAO,IAAI,IAAI,UAAU,IAAI,EAAE;AACrC,QAAK,KAAK,KAAK;AACf,OAAI,IAAI,WAAW,KAAK;;EAE1B,SAAiB;GACf,MAAMA,IAAc,EAAE;AACtB,QAAK,MAAM,CAAC,WAAWC,YAAU,KAAK;AACpC,QAAIA,QAAM,WAAW,EACnB;AAGF,MAAE,KAAK,YAAYA,QAAM,KAAK,KAAK,CAAC,WAAW,UAAU,GAAG;;AAG9D,UAAO,EAAE,KAAK,KAAK;;EAEtB"}
|
package/dist/util/parse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","names":[],"sources":["../../src/util/parse.ts"],"sourcesContent":["const RegexVarchar = /^varchar\\((\\d+)\\)$/;\n\nexport function parseVarchar(template: string): number {\n const match = RegexVarchar.exec(template);\n if (!match) throw new Error(\"Failed to match varchar(n)\");\n return Number(match[1]);\n}\n\nexport function ident(s: string, identation = 2): string {\n const tab = \" \".repeat(identation);\n\n return s\n .split(\"\\n\")\n .map((v) => tab + v)\n .join(\"\\n\");\n}\n"],"mappings":";AAAA,MAAM,eAAe;AAErB,SAAgB,aAAa,UAA0B;CACrD,MAAM,QAAQ,aAAa,KAAK,SAAS;AACzC,KAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"parse.js","names":[],"sources":["../../src/util/parse.ts"],"sourcesContent":["const RegexVarchar = /^varchar\\((\\d+)\\)$/;\n\nexport function parseVarchar(template: string): number {\n const match = RegexVarchar.exec(template);\n if (!match) {\n throw new Error(\"Failed to match varchar(n)\");\n }\n return Number(match[1]);\n}\n\nexport function ident(s: string, identation = 2): string {\n const tab = \" \".repeat(identation);\n\n return s\n .split(\"\\n\")\n .map((v) => tab + v)\n .join(\"\\n\");\n}\n"],"mappings":";AAAA,MAAM,eAAe;AAErB,SAAgB,aAAa,UAA0B;CACrD,MAAM,QAAQ,aAAa,KAAK,SAAS;AACzC,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,6BAA6B;AAE/C,QAAO,OAAO,MAAM,GAAG;;AAGzB,SAAgB,MAAM,GAAW,aAAa,GAAW;CACvD,MAAM,MAAM,IAAI,OAAO,WAAW;AAElC,QAAO,EACJ,MAAM,KAAK,CACX,KAAK,MAAM,MAAM,EAAE,CACnB,KAAK,KAAK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fragno-dev/db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -56,6 +56,12 @@
|
|
|
56
56
|
"development": "./src/fragment.ts",
|
|
57
57
|
"types": "./dist/fragment.d.ts",
|
|
58
58
|
"default": "./dist/fragment.js"
|
|
59
|
+
},
|
|
60
|
+
"./generation-engine": {
|
|
61
|
+
"bun": "./src/migration-engine/generation-engine.ts",
|
|
62
|
+
"development": "./src/migration-engine/generation-engine.ts",
|
|
63
|
+
"types": "./dist/migration-engine/generation-engine.d.ts",
|
|
64
|
+
"default": "./dist/migration-engine/generation-engine.js"
|
|
59
65
|
}
|
|
60
66
|
},
|
|
61
67
|
"scripts": {
|
|
@@ -67,19 +73,17 @@
|
|
|
67
73
|
},
|
|
68
74
|
"devDependencies": {
|
|
69
75
|
"@electric-sql/pglite": "^0.3.10",
|
|
76
|
+
"@fragno-dev/core": "0.1.2",
|
|
70
77
|
"@fragno-private/typescript-config": "0.0.1",
|
|
71
78
|
"@fragno-private/vitest-config": "0.0.0",
|
|
72
|
-
"@fragno-dev/core": "0.0.7",
|
|
73
79
|
"@types/bun": "^1.2.23",
|
|
74
80
|
"@types/node": "^22",
|
|
75
81
|
"@vitest/coverage-istanbul": "^3.2.4",
|
|
76
82
|
"drizzle-kit": "^0.31.5",
|
|
77
83
|
"drizzle-orm": "^0.44.6",
|
|
78
84
|
"kysely-pglite": "^0.6.1",
|
|
79
|
-
"vitest": "^3.2.4"
|
|
80
|
-
|
|
81
|
-
"peerDependencies": {
|
|
82
|
-
"@fragno-dev/core": "0.0.7"
|
|
85
|
+
"vitest": "^3.2.4",
|
|
86
|
+
"zod": "^4.1.12"
|
|
83
87
|
},
|
|
84
88
|
"repository": {
|
|
85
89
|
"type": "git",
|
package/src/adapters/adapters.ts
CHANGED
|
@@ -15,8 +15,15 @@ export interface DatabaseAdapter<TUOWConfig = void> {
|
|
|
15
15
|
) => AbstractQuery<T, TUOWConfig>;
|
|
16
16
|
|
|
17
17
|
createMigrationEngine?: <const T extends AnySchema>(schema: T, namespace: string) => Migrator;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate a combined schema file from one or more fragments.
|
|
21
|
+
* If not implemented, schema generation is not supported for this adapter.
|
|
22
|
+
*/
|
|
23
|
+
createSchemaGenerator?: (
|
|
24
|
+
fragments: { schema: AnySchema; namespace: string }[],
|
|
25
|
+
options?: { path?: string },
|
|
21
26
|
) => SchemaGenerator;
|
|
27
|
+
|
|
28
|
+
isConnectionHealthy: () => Promise<boolean>;
|
|
22
29
|
}
|
|
@@ -80,6 +80,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
80
80
|
"drizzle-adapter-pglite",
|
|
81
81
|
testSchema,
|
|
82
82
|
"postgresql",
|
|
83
|
+
"namespace",
|
|
83
84
|
);
|
|
84
85
|
|
|
85
86
|
// Create Drizzle instance with PGLite (in-memory Postgres)
|
|
@@ -103,13 +104,16 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
103
104
|
provider: "postgresql",
|
|
104
105
|
});
|
|
105
106
|
|
|
107
|
+
expect(await adapter.isConnectionHealthy()).toBe(true);
|
|
108
|
+
|
|
106
109
|
return async () => {
|
|
107
110
|
await cleanup();
|
|
108
111
|
};
|
|
109
112
|
}, 12000);
|
|
110
113
|
|
|
111
114
|
it("should execute Unit of Work with version checking", async () => {
|
|
112
|
-
|
|
115
|
+
// Pass namespace to ensure mapper translates logical table names to physical (prefixed) names
|
|
116
|
+
const queryEngine = adapter.createQueryEngine(testSchema, "namespace");
|
|
113
117
|
|
|
114
118
|
// Create initial user using UOW
|
|
115
119
|
const createUow = queryEngine.createUnitOfWork("create-user").create("users", {
|
|
@@ -194,7 +198,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
194
198
|
});
|
|
195
199
|
|
|
196
200
|
it("should support count operations", async () => {
|
|
197
|
-
const queryEngine = adapter.createQueryEngine(testSchema, "
|
|
201
|
+
const queryEngine = adapter.createQueryEngine(testSchema, "namespace");
|
|
198
202
|
|
|
199
203
|
// Create some users
|
|
200
204
|
await queryEngine
|
|
@@ -215,7 +219,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
215
219
|
});
|
|
216
220
|
|
|
217
221
|
it("should support cursor-based pagination", async () => {
|
|
218
|
-
const queryEngine = adapter.createQueryEngine(testSchema, "
|
|
222
|
+
const queryEngine = adapter.createQueryEngine(testSchema, "namespace");
|
|
219
223
|
|
|
220
224
|
const createUow = queryEngine
|
|
221
225
|
.createUnitOfWork("create-users")
|
|
@@ -262,7 +266,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
262
266
|
});
|
|
263
267
|
|
|
264
268
|
it("should support joins", async () => {
|
|
265
|
-
const queryEngine = adapter.createQueryEngine(testSchema, "
|
|
269
|
+
const queryEngine = adapter.createQueryEngine(testSchema, "namespace");
|
|
266
270
|
const queries: DrizzleCompiledQuery[] = [];
|
|
267
271
|
|
|
268
272
|
const createUow = queryEngine
|
|
@@ -298,7 +302,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
298
302
|
|
|
299
303
|
const [query] = queries;
|
|
300
304
|
expect(query.sql).toMatchInlineSnapshot(
|
|
301
|
-
`"select "
|
|
305
|
+
`"select "emails_namespace"."id", "emails_namespace"."user_id", "emails_namespace"."email", "emails_namespace"."is_primary", "emails_namespace"."_internalId", "emails_namespace"."_version", "emails_namespace_user"."data" as "user" from "emails_namespace" "emails_namespace" left join lateral (select json_build_array("emails_namespace_user"."name", "emails_namespace_user"."id", "emails_namespace_user"."age", "emails_namespace_user"."_internalId", "emails_namespace_user"."_version") as "data" from (select * from "users_namespace" "emails_namespace_user" where "emails_namespace_user"."_internalId" = "emails_namespace"."user_id" limit $1) "emails_namespace_user") "emails_namespace_user" on true"`,
|
|
302
306
|
);
|
|
303
307
|
|
|
304
308
|
expect(email).toMatchObject({
|
|
@@ -323,7 +327,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
323
327
|
});
|
|
324
328
|
|
|
325
329
|
it("should support complex nested joins (comments -> post -> author)", async () => {
|
|
326
|
-
const queryEngine = adapter.createQueryEngine(testSchema, "
|
|
330
|
+
const queryEngine = adapter.createQueryEngine(testSchema, "namespace");
|
|
327
331
|
const queries: DrizzleCompiledQuery[] = [];
|
|
328
332
|
|
|
329
333
|
// Create a user (author)
|
|
@@ -427,7 +431,7 @@ describe("DrizzleAdapter PGLite", () => {
|
|
|
427
431
|
|
|
428
432
|
const [query] = queries;
|
|
429
433
|
expect(query.sql).toMatchInlineSnapshot(
|
|
430
|
-
`"select "
|
|
434
|
+
`"select "comments_namespace"."id", "comments_namespace"."post_id", "comments_namespace"."user_id", "comments_namespace"."text", "comments_namespace"."_internalId", "comments_namespace"."_version", "comments_namespace_post"."data" as "post", "comments_namespace_commenter"."data" as "commenter" from "comments_namespace" "comments_namespace" left join lateral (select json_build_array("comments_namespace_post"."id", "comments_namespace_post"."title", "comments_namespace_post"."content", "comments_namespace_post"."_internalId", "comments_namespace_post"."_version", "comments_namespace_post_author"."data") as "data" from (select * from "posts_namespace" "comments_namespace_post" where "comments_namespace_post"."_internalId" = "comments_namespace"."post_id" order by "comments_namespace_post"."id" desc limit $1) "comments_namespace_post" left join lateral (select json_build_array("comments_namespace_post_author"."id", "comments_namespace_post_author"."name", "comments_namespace_post_author"."age", "comments_namespace_post_author"."_internalId", "comments_namespace_post_author"."_version") as "data" from (select * from "users_namespace" "comments_namespace_post_author" where "comments_namespace_post_author"."_internalId" = "comments_namespace_post"."user_id" order by "comments_namespace_post_author"."name" asc limit $2) "comments_namespace_post_author") "comments_namespace_post_author" on true) "comments_namespace_post" on true left join lateral (select json_build_array("comments_namespace_commenter"."id", "comments_namespace_commenter"."name", "comments_namespace_commenter"."_internalId", "comments_namespace_commenter"."_version") as "data" from (select * from "users_namespace" "comments_namespace_commenter" where "comments_namespace_commenter"."_internalId" = "comments_namespace"."user_id" limit $3) "comments_namespace_commenter") "comments_namespace_commenter" on true"`,
|
|
431
435
|
);
|
|
432
436
|
});
|
|
433
437
|
});
|
|
@@ -15,7 +15,7 @@ describe("DrizzleAdapter", () => {
|
|
|
15
15
|
provider: "postgresql",
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
const generator = adapter.createSchemaGenerator(testSchema, "test");
|
|
18
|
+
const generator = adapter.createSchemaGenerator([{ schema: testSchema, namespace: "test" }]);
|
|
19
19
|
const result = generator.generateSchema({ path: "schema.ts" });
|
|
20
20
|
|
|
21
21
|
expect(result.path).toBe("schema.ts");
|
|
@@ -23,22 +23,38 @@ describe("DrizzleAdapter", () => {
|
|
|
23
23
|
"import { pgTable, varchar, text, bigserial, integer, uniqueIndex } from "drizzle-orm/pg-core"
|
|
24
24
|
import { createId } from "@fragno-dev/db/id"
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
30
|
-
_version: integer("_version").notNull().default(0)
|
|
31
|
-
})
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Settings Table (shared across all fragments)
|
|
28
|
+
// ============================================================================
|
|
32
29
|
|
|
33
30
|
export const fragno_db_settings = pgTable("fragno_db_settings", {
|
|
34
31
|
id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
|
|
35
32
|
key: text("key").notNull(),
|
|
36
|
-
value: text("value").notNull()
|
|
33
|
+
value: text("value").notNull(),
|
|
37
34
|
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
38
35
|
_version: integer("_version").notNull().default(0)
|
|
39
36
|
}, (table) => [
|
|
40
37
|
uniqueIndex("unique_key").on(table.key)
|
|
41
|
-
])
|
|
38
|
+
])
|
|
39
|
+
|
|
40
|
+
export const fragnoDbSettingSchemaVersion = 1;
|
|
41
|
+
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Fragment: test
|
|
44
|
+
// ============================================================================
|
|
45
|
+
|
|
46
|
+
export const users_test = pgTable("users_test", {
|
|
47
|
+
id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
|
|
48
|
+
name: text("name").notNull(),
|
|
49
|
+
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
50
|
+
_version: integer("_version").notNull().default(0)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
export const test_schema = {
|
|
54
|
+
"users_test": users_test,
|
|
55
|
+
users: users_test,
|
|
56
|
+
schemaVersion: 1
|
|
57
|
+
}"
|
|
42
58
|
`);
|
|
43
59
|
});
|
|
44
60
|
|
|
@@ -48,7 +64,7 @@ describe("DrizzleAdapter", () => {
|
|
|
48
64
|
provider: "sqlite",
|
|
49
65
|
});
|
|
50
66
|
|
|
51
|
-
const generator = adapter.createSchemaGenerator(testSchema, "test");
|
|
67
|
+
const generator = adapter.createSchemaGenerator([{ schema: testSchema, namespace: "test" }]);
|
|
52
68
|
const result = generator.generateSchema({ path: "schema.ts" });
|
|
53
69
|
|
|
54
70
|
expect(result.path).toBe("schema.ts");
|
|
@@ -56,22 +72,38 @@ describe("DrizzleAdapter", () => {
|
|
|
56
72
|
"import { sqliteTable, text, integer, uniqueIndex } from "drizzle-orm/sqlite-core"
|
|
57
73
|
import { createId } from "@fragno-dev/db/id"
|
|
58
74
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
_internalId: integer("_internalId").primaryKey().autoincrement().notNull(),
|
|
63
|
-
_version: integer("_version").notNull().default(0)
|
|
64
|
-
})
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Settings Table (shared across all fragments)
|
|
77
|
+
// ============================================================================
|
|
65
78
|
|
|
66
79
|
export const fragno_db_settings = sqliteTable("fragno_db_settings", {
|
|
67
80
|
id: text("id").notNull().$defaultFn(() => createId()),
|
|
68
81
|
key: text("key").notNull(),
|
|
69
|
-
value: text("value").notNull()
|
|
82
|
+
value: text("value").notNull(),
|
|
70
83
|
_internalId: integer("_internalId").primaryKey().autoincrement().notNull(),
|
|
71
84
|
_version: integer("_version").notNull().default(0)
|
|
72
85
|
}, (table) => [
|
|
73
86
|
uniqueIndex("unique_key").on(table.key)
|
|
74
|
-
])
|
|
87
|
+
])
|
|
88
|
+
|
|
89
|
+
export const fragnoDbSettingSchemaVersion = 1;
|
|
90
|
+
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Fragment: test
|
|
93
|
+
// ============================================================================
|
|
94
|
+
|
|
95
|
+
export const users_test = sqliteTable("users_test", {
|
|
96
|
+
id: text("id").notNull().$defaultFn(() => createId()),
|
|
97
|
+
name: text("name").notNull(),
|
|
98
|
+
_internalId: integer("_internalId").primaryKey().autoincrement().notNull(),
|
|
99
|
+
_version: integer("_version").notNull().default(0)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
export const test_schema = {
|
|
103
|
+
"users_test": users_test,
|
|
104
|
+
users: users_test,
|
|
105
|
+
schemaVersion: 1
|
|
106
|
+
}"
|
|
75
107
|
`);
|
|
76
108
|
});
|
|
77
109
|
|
|
@@ -81,10 +113,10 @@ describe("DrizzleAdapter", () => {
|
|
|
81
113
|
provider: "postgresql",
|
|
82
114
|
});
|
|
83
115
|
|
|
84
|
-
const generator = adapter.createSchemaGenerator(testSchema, "myapp");
|
|
116
|
+
const generator = adapter.createSchemaGenerator([{ schema: testSchema, namespace: "myapp" }]);
|
|
85
117
|
const result = generator.generateSchema();
|
|
86
118
|
|
|
87
|
-
expect(result.path).toBe("
|
|
119
|
+
expect(result.path).toBe("fragno-schema.ts");
|
|
88
120
|
});
|
|
89
121
|
|
|
90
122
|
it("should preserve original schema tables", () => {
|
|
@@ -93,7 +125,7 @@ describe("DrizzleAdapter", () => {
|
|
|
93
125
|
provider: "postgresql",
|
|
94
126
|
});
|
|
95
127
|
|
|
96
|
-
const generator = adapter.createSchemaGenerator(testSchema, "test");
|
|
128
|
+
const generator = adapter.createSchemaGenerator([{ schema: testSchema, namespace: "test" }]);
|
|
97
129
|
const result = generator.generateSchema();
|
|
98
130
|
|
|
99
131
|
// Original table should still be there
|
|
@@ -101,22 +133,38 @@ describe("DrizzleAdapter", () => {
|
|
|
101
133
|
"import { pgTable, varchar, text, bigserial, integer, uniqueIndex } from "drizzle-orm/pg-core"
|
|
102
134
|
import { createId } from "@fragno-dev/db/id"
|
|
103
135
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
108
|
-
_version: integer("_version").notNull().default(0)
|
|
109
|
-
})
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Settings Table (shared across all fragments)
|
|
138
|
+
// ============================================================================
|
|
110
139
|
|
|
111
140
|
export const fragno_db_settings = pgTable("fragno_db_settings", {
|
|
112
141
|
id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
|
|
113
142
|
key: text("key").notNull(),
|
|
114
|
-
value: text("value").notNull()
|
|
143
|
+
value: text("value").notNull(),
|
|
115
144
|
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
116
145
|
_version: integer("_version").notNull().default(0)
|
|
117
146
|
}, (table) => [
|
|
118
147
|
uniqueIndex("unique_key").on(table.key)
|
|
119
|
-
])
|
|
148
|
+
])
|
|
149
|
+
|
|
150
|
+
export const fragnoDbSettingSchemaVersion = 1;
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Fragment: test
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
export const users_test = pgTable("users_test", {
|
|
157
|
+
id: varchar("id", { length: 30 }).notNull().$defaultFn(() => createId()),
|
|
158
|
+
name: text("name").notNull(),
|
|
159
|
+
_internalId: bigserial("_internalId", { mode: "number" }).primaryKey().notNull(),
|
|
160
|
+
_version: integer("_version").notNull().default(0)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
export const test_schema = {
|
|
164
|
+
"users_test": users_test,
|
|
165
|
+
users: users_test,
|
|
166
|
+
schemaVersion: 1
|
|
167
|
+
}"
|
|
120
168
|
`);
|
|
121
169
|
});
|
|
122
170
|
});
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import type { DatabaseAdapter } from "../adapters";
|
|
2
|
-
import {
|
|
3
|
-
column,
|
|
4
|
-
idColumn,
|
|
5
|
-
schema,
|
|
6
|
-
SchemaBuilder,
|
|
7
|
-
type AnySchema,
|
|
8
|
-
type FragnoId,
|
|
9
|
-
} from "../../schema/create";
|
|
2
|
+
import { type AnySchema } from "../../schema/create";
|
|
10
3
|
import type { AbstractQuery } from "../../query/query";
|
|
11
4
|
import type { SchemaGenerator } from "../../schema-generator/schema-generator";
|
|
12
5
|
import { generateSchema } from "./generate";
|
|
13
6
|
import { fromDrizzle, type DrizzleUOWConfig } from "./drizzle-query";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
import { createTableNameMapper, type DBType, type DrizzleResult } from "./shared";
|
|
8
|
+
import { createSettingsManager, settingsSchema } from "../../shared/settings-schema";
|
|
9
|
+
import { sql } from "drizzle-orm";
|
|
17
10
|
|
|
18
11
|
export interface DrizzleConfig {
|
|
19
12
|
db: unknown;
|
|
@@ -27,92 +20,52 @@ export class DrizzleAdapter implements DatabaseAdapter<DrizzleUOWConfig> {
|
|
|
27
20
|
this.#drizzleConfig = config;
|
|
28
21
|
}
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
return
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
get provider(): "sqlite" | "mysql" | "postgresql" {
|
|
24
|
+
return this.#drizzleConfig.provider;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async isConnectionHealthy(): Promise<boolean> {
|
|
28
|
+
try {
|
|
29
|
+
const result = (await (this.#drizzleConfig.db as DBType).execute(
|
|
30
|
+
sql`SELECT 1 as healthy`,
|
|
31
|
+
)) as DrizzleResult;
|
|
32
|
+
return result.rows[0]["healthy"] === 1;
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
async getSchemaVersion(namespace: string): Promise<string | undefined> {
|
|
38
|
-
const queryEngine = this.createQueryEngine(
|
|
39
|
+
const queryEngine = this.createQueryEngine(settingsSchema, namespace);
|
|
39
40
|
const manager = createSettingsManager(queryEngine, namespace);
|
|
40
|
-
const randomId = createId();
|
|
41
|
-
|
|
42
|
-
const result = await manager.createKeyWithDefault(randomId);
|
|
43
|
-
if (result) {
|
|
44
|
-
await manager.delete(result.id);
|
|
45
|
-
}
|
|
46
41
|
|
|
42
|
+
// Try to read the version key directly
|
|
43
|
+
const result = await manager.get("version");
|
|
47
44
|
return result?.value;
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
createQueryEngine<TSchema extends AnySchema>(
|
|
51
48
|
schema: TSchema,
|
|
52
|
-
|
|
49
|
+
namespace: string,
|
|
53
50
|
): AbstractQuery<TSchema, DrizzleUOWConfig> {
|
|
54
|
-
|
|
51
|
+
// Only create mapper if namespace is non-empty
|
|
52
|
+
const mapper = namespace ? createTableNameMapper(namespace) : undefined;
|
|
53
|
+
return fromDrizzle(schema, this.#drizzleConfig, mapper);
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
createSchemaGenerator(
|
|
56
|
+
createSchemaGenerator(
|
|
57
|
+
fragments: { schema: AnySchema; namespace: string }[],
|
|
58
|
+
options?: { path?: string },
|
|
59
|
+
): SchemaGenerator {
|
|
58
60
|
return {
|
|
59
|
-
generateSchema: (
|
|
60
|
-
const path = options?.path ??
|
|
61
|
-
|
|
62
|
-
const schemaWithSettingsTable = this.#createFullSchema(schema);
|
|
61
|
+
generateSchema: (genOptions) => {
|
|
62
|
+
const path = genOptions?.path ?? options?.path ?? "fragno-schema.ts";
|
|
63
63
|
|
|
64
64
|
return {
|
|
65
|
-
schema: generateSchema(
|
|
65
|
+
schema: generateSchema(fragments, this.#drizzleConfig.provider),
|
|
66
66
|
path,
|
|
67
67
|
};
|
|
68
68
|
},
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
function createSettingsSchema(version: number) {
|
|
74
|
-
return schema((s) => {
|
|
75
|
-
return s.addTable(SETTINGS_TABLE_NAME, (t) => {
|
|
76
|
-
return t
|
|
77
|
-
.addColumn("id", idColumn())
|
|
78
|
-
.addColumn("key", column("string"))
|
|
79
|
-
.addColumn("value", column("string").defaultTo(String(version)))
|
|
80
|
-
.createIndex("unique_key", ["key"], { unique: true });
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function createSettingsManager(
|
|
86
|
-
queryEngine: AbstractQuery<ReturnType<typeof createSettingsSchema>, DrizzleUOWConfig>,
|
|
87
|
-
namespace: string,
|
|
88
|
-
) {
|
|
89
|
-
return {
|
|
90
|
-
async createKeyWithDefault(key: string) {
|
|
91
|
-
const writeUow = queryEngine
|
|
92
|
-
.createUnitOfWork("createKeyWithDefault")
|
|
93
|
-
.create(SETTINGS_TABLE_NAME, {
|
|
94
|
-
key: `${namespace}.${key}`,
|
|
95
|
-
});
|
|
96
|
-
const { success } = await writeUow.executeMutations();
|
|
97
|
-
if (!success) {
|
|
98
|
-
throw new Error("Failed to create key with default");
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return this.get(key);
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
async get(key: string): Promise<{ id: FragnoId; key: string; value: string } | undefined> {
|
|
105
|
-
const uow = queryEngine
|
|
106
|
-
.createUnitOfWork()
|
|
107
|
-
.find(SETTINGS_TABLE_NAME, (b) =>
|
|
108
|
-
b.whereIndex("unique_key", (eb) => eb("key", "=", `${namespace}.${key}`)),
|
|
109
|
-
);
|
|
110
|
-
const [[result]] = await uow.executeRetrieve();
|
|
111
|
-
return result; // FIXME: result should be maybe undefined
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
async delete(id: FragnoId) {
|
|
115
|
-
await queryEngine.delete(SETTINGS_TABLE_NAME, id);
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
}
|
|
@@ -5,14 +5,9 @@ import type { CompiledMutation, UOWExecutor } from "../../query/unit-of-work";
|
|
|
5
5
|
import { createDrizzleUOWCompiler, type DrizzleCompiledQuery } from "./drizzle-uow-compiler";
|
|
6
6
|
import { executeDrizzleRetrievalPhase, executeDrizzleMutationPhase } from "./drizzle-uow-executor";
|
|
7
7
|
import { UnitOfWork } from "../../query/unit-of-work";
|
|
8
|
-
import { parseDrizzle } from "./shared";
|
|
8
|
+
import { parseDrizzle, type DrizzleResult, type TableNameMapper } from "./shared";
|
|
9
9
|
import { createDrizzleUOWDecoder } from "./drizzle-uow-decoder";
|
|
10
10
|
|
|
11
|
-
export interface DrizzleResult {
|
|
12
|
-
rows: Record<string, unknown>[];
|
|
13
|
-
affectedRows: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
11
|
/**
|
|
17
12
|
* Configuration options for creating a Drizzle Unit of Work
|
|
18
13
|
*/
|
|
@@ -33,6 +28,7 @@ export interface DrizzleUOWConfig {
|
|
|
33
28
|
*
|
|
34
29
|
* @param schema - The database schema definition
|
|
35
30
|
* @param config - Drizzle configuration containing the database instance and provider
|
|
31
|
+
* @param mapper - Optional table name mapper for namespace prefixing
|
|
36
32
|
* @returns An AbstractQuery instance for performing database operations
|
|
37
33
|
*
|
|
38
34
|
* @example
|
|
@@ -48,12 +44,13 @@ export interface DrizzleUOWConfig {
|
|
|
48
44
|
export function fromDrizzle<T extends AnySchema>(
|
|
49
45
|
schema: T,
|
|
50
46
|
config: DrizzleConfig,
|
|
47
|
+
mapper?: TableNameMapper,
|
|
51
48
|
): AbstractQuery<T, DrizzleUOWConfig> {
|
|
52
49
|
const [db] = parseDrizzle(config.db);
|
|
53
50
|
const { provider } = config;
|
|
54
51
|
|
|
55
52
|
function createUOW(name?: string, uowConfig?: DrizzleUOWConfig) {
|
|
56
|
-
const uowCompiler = createDrizzleUOWCompiler(schema, config, uowConfig?.onQuery);
|
|
53
|
+
const uowCompiler = createDrizzleUOWCompiler(schema, config, mapper, uowConfig?.onQuery);
|
|
57
54
|
|
|
58
55
|
const executor: UOWExecutor<DrizzleCompiledQuery, DrizzleResult> = {
|
|
59
56
|
executeRetrievalPhase: (retrievalBatch: DrizzleCompiledQuery[]) =>
|
|
@@ -755,9 +755,15 @@ describe("drizzle-uow-compiler", () => {
|
|
|
755
755
|
return t
|
|
756
756
|
.addColumn("id", idColumn())
|
|
757
757
|
.addColumn("message", column("string"))
|
|
758
|
-
.addColumn(
|
|
759
|
-
|
|
760
|
-
|
|
758
|
+
.addColumn(
|
|
759
|
+
"sessionId",
|
|
760
|
+
column("string").defaultTo$((b) => b.cuid()),
|
|
761
|
+
) // runtime cuid
|
|
762
|
+
.addColumn(
|
|
763
|
+
"timestamp",
|
|
764
|
+
column("timestamp").defaultTo$((b) => b.now()),
|
|
765
|
+
) // runtime now
|
|
766
|
+
.addColumn("counter", column("integer").defaultTo$(42)) // runtime function
|
|
761
767
|
.addColumn("status", column("string").defaultTo("pending")) // static default
|
|
762
768
|
.createIndex("idx_session", ["sessionId"]);
|
|
763
769
|
});
|
|
@@ -787,7 +793,7 @@ describe("drizzle-uow-compiler", () => {
|
|
|
787
793
|
return async () => {
|
|
788
794
|
await cleanup();
|
|
789
795
|
};
|
|
790
|
-
});
|
|
796
|
+
}, 12000);
|
|
791
797
|
|
|
792
798
|
it("should generate runtime defaults for missing columns", () => {
|
|
793
799
|
const uow = createTestUOWWithSchema(defaultsSchema);
|