@fragno-dev/test 0.1.11 → 0.1.13
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 +15 -11
- package/CHANGELOG.md +35 -0
- package/dist/adapters.d.ts +3 -11
- package/dist/adapters.d.ts.map +1 -1
- package/dist/adapters.js +65 -50
- package/dist/adapters.js.map +1 -1
- package/dist/db-test.d.ts +129 -0
- package/dist/db-test.d.ts.map +1 -0
- package/dist/db-test.js +214 -0
- package/dist/db-test.js.map +1 -0
- package/dist/index.d.ts +23 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -91
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
- package/src/adapters.ts +137 -118
- package/src/db-test.test.ts +352 -0
- package/src/db-test.ts +574 -0
- package/src/index.test.ts +287 -546
- package/src/index.ts +39 -241
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @fragno-dev/test@0.1.
|
|
2
|
+
> @fragno-dev/test@0.1.13 build /home/runner/work/fragno/fragno/packages/fragno-test
|
|
3
3
|
> tsdown
|
|
4
4
|
|
|
5
5
|
[34mℹ[39m tsdown [2mv0.15.12[22m powered by rolldown [2mv1.0.0-beta.45[22m
|
|
@@ -7,13 +7,17 @@
|
|
|
7
7
|
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
8
|
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
9
9
|
[34mℹ[39m Build start
|
|
10
|
-
[34mℹ[39m [2mdist/[22m[1mindex.js[22m [2m
|
|
11
|
-
[34mℹ[39m [2mdist/[
|
|
12
|
-
[34mℹ[39m [2mdist/[
|
|
13
|
-
[34mℹ[39m [2mdist/[22madapters.js [2m
|
|
14
|
-
[34mℹ[39m [2mdist/[
|
|
15
|
-
[34mℹ[39m [2mdist/[
|
|
16
|
-
[34mℹ[39m [2mdist/[
|
|
17
|
-
[34mℹ[39m [2mdist/[
|
|
18
|
-
[34mℹ[39m
|
|
19
|
-
[32m
|
|
10
|
+
[34mℹ[39m [2mdist/[22m[1mindex.js[22m [2m 0.71 kB[22m [2m│ gzip: 0.40 kB[22m
|
|
11
|
+
[34mℹ[39m [2mdist/[22mdb-test.js.map [2m23.72 kB[22m [2m│ gzip: 5.83 kB[22m
|
|
12
|
+
[34mℹ[39m [2mdist/[22madapters.js.map [2m18.56 kB[22m [2m│ gzip: 4.04 kB[22m
|
|
13
|
+
[34mℹ[39m [2mdist/[22madapters.js [2m 7.97 kB[22m [2m│ gzip: 1.74 kB[22m
|
|
14
|
+
[34mℹ[39m [2mdist/[22mdb-test.js [2m 7.25 kB[22m [2m│ gzip: 2.14 kB[22m
|
|
15
|
+
[34mℹ[39m [2mdist/[22mdb-test.d.ts.map [2m 3.19 kB[22m [2m│ gzip: 1.47 kB[22m
|
|
16
|
+
[34mℹ[39m [2mdist/[22mindex.js.map [2m 2.44 kB[22m [2m│ gzip: 0.96 kB[22m
|
|
17
|
+
[34mℹ[39m [2mdist/[22mindex.d.ts.map [2m 0.55 kB[22m [2m│ gzip: 0.31 kB[22m
|
|
18
|
+
[34mℹ[39m [2mdist/[22madapters.d.ts.map [2m 0.42 kB[22m [2m│ gzip: 0.27 kB[22m
|
|
19
|
+
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.ts[22m[39m [2m 1.79 kB[22m [2m│ gzip: 0.68 kB[22m
|
|
20
|
+
[34mℹ[39m [2mdist/[22m[32mdb-test.d.ts[39m [2m 6.67 kB[22m [2m│ gzip: 1.80 kB[22m
|
|
21
|
+
[34mℹ[39m [2mdist/[22m[32madapters.d.ts[39m [2m 0.95 kB[22m [2m│ gzip: 0.37 kB[22m
|
|
22
|
+
[34mℹ[39m 12 files, total: 74.22 kB
|
|
23
|
+
[32m✔[39m Build complete in [32m1914ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @fragno-dev/test
|
|
2
2
|
|
|
3
|
+
## 0.1.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e848208: feat: restrict Unit of Work in service contexts
|
|
8
|
+
- 0f4c9fe: fix: move core/db dependencies to peerDependencies
|
|
9
|
+
- 7276378: feat: add providesPrivateService method to Fragment definition
|
|
10
|
+
|
|
11
|
+
This allows the Fragment author to define private services that are only accessible within the
|
|
12
|
+
Fragment's own code.
|
|
13
|
+
|
|
14
|
+
- 5ea24d2: refactor: improve Fragment builder and instatiator
|
|
15
|
+
- Updated dependencies [d6a7ff5]
|
|
16
|
+
- Updated dependencies [e848208]
|
|
17
|
+
- Updated dependencies [e9b2e7d]
|
|
18
|
+
- Updated dependencies [5e185bc]
|
|
19
|
+
- Updated dependencies [ec622bc]
|
|
20
|
+
- Updated dependencies [219ce35]
|
|
21
|
+
- Updated dependencies [b34917f]
|
|
22
|
+
- Updated dependencies [7276378]
|
|
23
|
+
- Updated dependencies [462004f]
|
|
24
|
+
- Updated dependencies [5ea24d2]
|
|
25
|
+
- Updated dependencies [f22c503]
|
|
26
|
+
- Updated dependencies [3474006]
|
|
27
|
+
- @fragno-dev/db@0.1.15
|
|
28
|
+
- @fragno-dev/core@0.1.9
|
|
29
|
+
|
|
30
|
+
## 0.1.12
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- Updated dependencies [acb0877]
|
|
35
|
+
- @fragno-dev/core@0.1.8
|
|
36
|
+
- @fragno-dev/db@0.1.14
|
|
37
|
+
|
|
3
38
|
## 0.1.11
|
|
4
39
|
|
|
5
40
|
### Patch Changes
|
package/dist/adapters.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import "./index.js";
|
|
1
2
|
import { Kysely } from "kysely";
|
|
2
3
|
import { drizzle } from "drizzle-orm/pglite";
|
|
3
4
|
import { AnySchema } from "@fragno-dev/db/schema";
|
|
4
|
-
import { DatabaseAdapter } from "@fragno-dev/db/adapters";
|
|
5
5
|
import { AbstractQuery } from "@fragno-dev/db/query";
|
|
6
6
|
|
|
7
7
|
//#region src/adapters.d.ts
|
|
@@ -17,19 +17,11 @@ interface DrizzlePgliteAdapter {
|
|
|
17
17
|
databasePath?: string;
|
|
18
18
|
}
|
|
19
19
|
type SupportedAdapter = KyselySqliteAdapter | KyselyPgliteAdapter | DrizzlePgliteAdapter;
|
|
20
|
-
type
|
|
21
|
-
readonly db: AbstractQuery<any>;
|
|
20
|
+
type AdapterContext<T extends SupportedAdapter> = T extends KyselySqliteAdapter | KyselyPgliteAdapter ? {
|
|
22
21
|
readonly kysely: Kysely<any>;
|
|
23
|
-
readonly adapter: DatabaseAdapter<any>;
|
|
24
|
-
resetDatabase: () => Promise<void>;
|
|
25
|
-
cleanup: () => Promise<void>;
|
|
26
22
|
} : T extends DrizzlePgliteAdapter ? {
|
|
27
|
-
readonly db: AbstractQuery<any>;
|
|
28
23
|
readonly drizzle: ReturnType<typeof drizzle<any>>;
|
|
29
|
-
readonly adapter: DatabaseAdapter<any>;
|
|
30
|
-
resetDatabase: () => Promise<void>;
|
|
31
|
-
cleanup: () => Promise<void>;
|
|
32
24
|
} : never;
|
|
33
25
|
//#endregion
|
|
34
|
-
export { DrizzlePgliteAdapter, KyselyPgliteAdapter, KyselySqliteAdapter, SupportedAdapter
|
|
26
|
+
export { AdapterContext, DrizzlePgliteAdapter, KyselyPgliteAdapter, KyselySqliteAdapter, SupportedAdapter };
|
|
35
27
|
//# sourceMappingURL=adapters.d.ts.map
|
package/dist/adapters.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.d.ts","names":[],"sources":["../src/adapters.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","names":[],"sources":["../src/adapters.ts"],"sourcesContent":[],"mappings":";;;;;;;UAkBiB,mBAAA;EAAA,IAAA,EAAA,eAAA;AAIjB;AAKiB,UALA,mBAAA,CAKoB;EAKzB,IAAA,EAAA,eAAgB;EAAG,YAAA,CAAA,EAAA,MAAA;;AAA4C,UAL1D,oBAAA,CAK0D;EAAoB,IAAA,EAAA,gBAAA;EAenF,YAAA,CAAA,EAAA,MAAc;;AAA+B,KAf7C,gBAAA,GAAmB,mBAe0B,GAfJ,mBAeI,GAfkB,oBAelB;KAA7C,yBAAyB,oBAAoB,UACrD,sBACA;mBAEmB;IAEnB,UAAU;oBAEY,kBAAkB"}
|
package/dist/adapters.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createCommonTestContextMethods } from "./index.js";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
3
|
import { Kysely } from "kysely";
|
|
3
4
|
import { SQLocalKysely } from "sqlocal/kysely";
|
|
@@ -13,8 +14,9 @@ import { existsSync } from "node:fs";
|
|
|
13
14
|
//#region src/adapters.ts
|
|
14
15
|
/**
|
|
15
16
|
* Create Kysely + SQLite adapter using SQLocalKysely (always in-memory)
|
|
17
|
+
* Supports multiple schemas with separate namespaces
|
|
16
18
|
*/
|
|
17
|
-
async function createKyselySqliteAdapter(_config,
|
|
19
|
+
async function createKyselySqliteAdapter(_config, schemas) {
|
|
18
20
|
const createDatabase = async () => {
|
|
19
21
|
const { dialect } = new SQLocalKysely(":memory:");
|
|
20
22
|
const kysely$1 = new Kysely({ dialect });
|
|
@@ -22,36 +24,41 @@ async function createKyselySqliteAdapter(_config, schema, namespace, migrateToVe
|
|
|
22
24
|
db: kysely$1,
|
|
23
25
|
provider: "sqlite"
|
|
24
26
|
});
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
+
const ormMap$1 = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const { schema, namespace, migrateToVersion } of schemas) {
|
|
29
|
+
const migrator = adapter$1.createMigrationEngine(schema, namespace);
|
|
30
|
+
await (migrateToVersion ? await migrator.prepareMigrationTo(migrateToVersion, { updateSettings: false }) : await migrator.prepareMigration({ updateSettings: false })).execute();
|
|
31
|
+
const orm = adapter$1.createQueryEngine(schema, namespace);
|
|
32
|
+
ormMap$1.set(namespace, orm);
|
|
33
|
+
}
|
|
27
34
|
return {
|
|
28
35
|
kysely: kysely$1,
|
|
29
36
|
adapter: adapter$1,
|
|
30
|
-
|
|
37
|
+
ormMap: ormMap$1
|
|
31
38
|
};
|
|
32
39
|
};
|
|
33
|
-
let { kysely, adapter,
|
|
40
|
+
let { kysely, adapter, ormMap } = await createDatabase();
|
|
34
41
|
const resetDatabase = async () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
for (const { schema, namespace } of schemas) {
|
|
43
|
+
const mapper = adapter.createTableNameMapper(namespace);
|
|
44
|
+
for (const tableName of Object.keys(schema.tables)) {
|
|
45
|
+
const physicalTableName = mapper.toPhysical(tableName);
|
|
46
|
+
await kysely.deleteFrom(physicalTableName).execute();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
40
49
|
};
|
|
41
50
|
const cleanup = async () => {
|
|
42
51
|
await kysely.destroy();
|
|
43
52
|
};
|
|
44
53
|
return {
|
|
45
54
|
testContext: {
|
|
46
|
-
get db() {
|
|
47
|
-
return orm;
|
|
48
|
-
},
|
|
49
55
|
get kysely() {
|
|
50
56
|
return kysely;
|
|
51
57
|
},
|
|
52
58
|
get adapter() {
|
|
53
59
|
return adapter;
|
|
54
60
|
},
|
|
61
|
+
...createCommonTestContextMethods(ormMap),
|
|
55
62
|
resetDatabase,
|
|
56
63
|
cleanup
|
|
57
64
|
},
|
|
@@ -62,8 +69,9 @@ async function createKyselySqliteAdapter(_config, schema, namespace, migrateToVe
|
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Create Kysely + PGLite adapter using kysely-pglite
|
|
72
|
+
* Supports multiple schemas with separate namespaces
|
|
65
73
|
*/
|
|
66
|
-
async function createKyselyPgliteAdapter(config,
|
|
74
|
+
async function createKyselyPgliteAdapter(config, schemas) {
|
|
67
75
|
const databasePath = config.databasePath;
|
|
68
76
|
const createDatabase = async () => {
|
|
69
77
|
const kyselyPglite$1 = await KyselyPGlite.create(databasePath);
|
|
@@ -72,26 +80,30 @@ async function createKyselyPgliteAdapter(config, schema, namespace, migrateToVer
|
|
|
72
80
|
db: kysely$1,
|
|
73
81
|
provider: "postgresql"
|
|
74
82
|
});
|
|
75
|
-
const
|
|
76
|
-
|
|
83
|
+
const ormMap$1 = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const { schema, namespace, migrateToVersion } of schemas) {
|
|
85
|
+
const migrator = adapter$1.createMigrationEngine(schema, namespace);
|
|
86
|
+
await (migrateToVersion ? await migrator.prepareMigrationTo(migrateToVersion, { updateSettings: false }) : await migrator.prepareMigration({ updateSettings: false })).execute();
|
|
87
|
+
const orm = adapter$1.createQueryEngine(schema, namespace);
|
|
88
|
+
ormMap$1.set(namespace, orm);
|
|
89
|
+
}
|
|
77
90
|
return {
|
|
78
91
|
kysely: kysely$1,
|
|
79
92
|
adapter: adapter$1,
|
|
80
93
|
kyselyPglite: kyselyPglite$1,
|
|
81
|
-
|
|
94
|
+
ormMap: ormMap$1
|
|
82
95
|
};
|
|
83
96
|
};
|
|
84
|
-
|
|
97
|
+
const { kysely, adapter, kyselyPglite, ormMap } = await createDatabase();
|
|
85
98
|
const resetDatabase = async () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
orm = newDb.orm;
|
|
99
|
+
if (databasePath && databasePath !== ":memory:") throw new Error("resetDatabase is only supported for in-memory databases");
|
|
100
|
+
for (const { schema, namespace } of schemas) {
|
|
101
|
+
const mapper = adapter.createTableNameMapper(namespace);
|
|
102
|
+
for (const tableName of Object.keys(schema.tables)) {
|
|
103
|
+
const physicalTableName = mapper.toPhysical(tableName);
|
|
104
|
+
await kysely.deleteFrom(physicalTableName).execute();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
95
107
|
};
|
|
96
108
|
const cleanup = async () => {
|
|
97
109
|
await kysely.destroy();
|
|
@@ -105,15 +117,13 @@ async function createKyselyPgliteAdapter(config, schema, namespace, migrateToVer
|
|
|
105
117
|
};
|
|
106
118
|
return {
|
|
107
119
|
testContext: {
|
|
108
|
-
get db() {
|
|
109
|
-
return orm;
|
|
110
|
-
},
|
|
111
120
|
get kysely() {
|
|
112
121
|
return kysely;
|
|
113
122
|
},
|
|
114
123
|
get adapter() {
|
|
115
124
|
return adapter;
|
|
116
125
|
},
|
|
126
|
+
...createCommonTestContextMethods(ormMap),
|
|
117
127
|
resetDatabase,
|
|
118
128
|
cleanup
|
|
119
129
|
},
|
|
@@ -124,8 +134,9 @@ async function createKyselyPgliteAdapter(config, schema, namespace, migrateToVer
|
|
|
124
134
|
}
|
|
125
135
|
/**
|
|
126
136
|
* Create Drizzle + PGLite adapter using drizzle-orm/pglite
|
|
137
|
+
* Supports multiple schemas with separate namespaces
|
|
127
138
|
*/
|
|
128
|
-
async function createDrizzlePgliteAdapter(config,
|
|
139
|
+
async function createDrizzlePgliteAdapter(config, schemas) {
|
|
129
140
|
const databasePath = config.databasePath;
|
|
130
141
|
const { generateDrizzleJson, generateMigration } = createRequire(import.meta.url)("drizzle-kit/api");
|
|
131
142
|
const { generateSchema } = await import("@fragno-dev/db/adapters/drizzle/generate");
|
|
@@ -133,10 +144,10 @@ async function createDrizzlePgliteAdapter(config, schema, namespace, _migrateToV
|
|
|
133
144
|
const testDir = join(import.meta.dirname, "_generated", "drizzle-test");
|
|
134
145
|
await mkdir(testDir, { recursive: true }).catch(() => {});
|
|
135
146
|
const schemaFilePath = join(testDir, `test-schema-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.ts`);
|
|
136
|
-
await writeFile(schemaFilePath, generateSchema(
|
|
147
|
+
await writeFile(schemaFilePath, generateSchema(schemas.map(({ schema, namespace }) => ({
|
|
137
148
|
namespace: namespace ?? "",
|
|
138
149
|
schema
|
|
139
|
-
}
|
|
150
|
+
})), "postgresql"), "utf-8");
|
|
140
151
|
const schemaModule = await import(`${schemaFilePath}?t=${Date.now()}`);
|
|
141
152
|
const cleanup$1 = async () => {
|
|
142
153
|
await rm(testDir, {
|
|
@@ -159,24 +170,29 @@ async function createDrizzlePgliteAdapter(config, schema, namespace, _migrateToV
|
|
|
159
170
|
db: () => db,
|
|
160
171
|
provider: "postgresql"
|
|
161
172
|
});
|
|
173
|
+
const ormMap$1 = /* @__PURE__ */ new Map();
|
|
174
|
+
for (const { schema, namespace } of schemas) {
|
|
175
|
+
const orm = adapter$1.createQueryEngine(schema, namespace);
|
|
176
|
+
ormMap$1.set(namespace, orm);
|
|
177
|
+
}
|
|
162
178
|
return {
|
|
163
179
|
drizzle: db,
|
|
164
180
|
adapter: adapter$1,
|
|
165
181
|
pglite: pglite$1,
|
|
166
182
|
cleanup: cleanup$1,
|
|
167
|
-
|
|
183
|
+
ormMap: ormMap$1
|
|
168
184
|
};
|
|
169
185
|
};
|
|
170
|
-
|
|
186
|
+
const { drizzle: drizzleDb, adapter, pglite, cleanup: schemaCleanup, ormMap } = await createDatabase();
|
|
171
187
|
const resetDatabase = async () => {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
188
|
+
if (databasePath && databasePath !== ":memory:") throw new Error("resetDatabase is only supported for in-memory databases");
|
|
189
|
+
for (const { schema, namespace } of schemas) {
|
|
190
|
+
const mapper = adapter.createTableNameMapper(namespace);
|
|
191
|
+
for (const tableName of Object.keys(schema.tables)) {
|
|
192
|
+
const physicalTableName = mapper.toPhysical(tableName);
|
|
193
|
+
await drizzleDb.execute(`DELETE FROM "${physicalTableName}"`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
180
196
|
};
|
|
181
197
|
const cleanup = async () => {
|
|
182
198
|
await pglite.close();
|
|
@@ -188,15 +204,13 @@ async function createDrizzlePgliteAdapter(config, schema, namespace, _migrateToV
|
|
|
188
204
|
};
|
|
189
205
|
return {
|
|
190
206
|
testContext: {
|
|
191
|
-
get db() {
|
|
192
|
-
return orm;
|
|
193
|
-
},
|
|
194
207
|
get drizzle() {
|
|
195
208
|
return drizzleDb;
|
|
196
209
|
},
|
|
197
210
|
get adapter() {
|
|
198
211
|
return adapter;
|
|
199
212
|
},
|
|
213
|
+
...createCommonTestContextMethods(ormMap),
|
|
200
214
|
resetDatabase,
|
|
201
215
|
cleanup
|
|
202
216
|
},
|
|
@@ -207,11 +221,12 @@ async function createDrizzlePgliteAdapter(config, schema, namespace, _migrateToV
|
|
|
207
221
|
}
|
|
208
222
|
/**
|
|
209
223
|
* Create adapter based on configuration
|
|
224
|
+
* Supports multiple schemas with separate namespaces
|
|
210
225
|
*/
|
|
211
|
-
async function createAdapter(adapterConfig,
|
|
212
|
-
if (adapterConfig.type === "kysely-sqlite") return createKyselySqliteAdapter(adapterConfig,
|
|
213
|
-
else if (adapterConfig.type === "kysely-pglite") return createKyselyPgliteAdapter(adapterConfig,
|
|
214
|
-
else if (adapterConfig.type === "drizzle-pglite") return createDrizzlePgliteAdapter(adapterConfig,
|
|
226
|
+
async function createAdapter(adapterConfig, schemas) {
|
|
227
|
+
if (adapterConfig.type === "kysely-sqlite") return createKyselySqliteAdapter(adapterConfig, schemas);
|
|
228
|
+
else if (adapterConfig.type === "kysely-pglite") return createKyselyPgliteAdapter(adapterConfig, schemas);
|
|
229
|
+
else if (adapterConfig.type === "drizzle-pglite") return createDrizzlePgliteAdapter(adapterConfig, schemas);
|
|
215
230
|
throw new Error(`Unsupported adapter type: ${adapterConfig.type}`);
|
|
216
231
|
}
|
|
217
232
|
|
package/dist/adapters.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.js","names":["kysely","adapter","kyselyPglite","cleanup","pglite"],"sources":["../src/adapters.ts"],"sourcesContent":["import { Kysely } from \"kysely\";\nimport { SQLocalKysely } from \"sqlocal/kysely\";\nimport { KyselyPGlite } from \"kysely-pglite\";\nimport { drizzle } from \"drizzle-orm/pglite\";\nimport { PGlite } from \"@electric-sql/pglite\";\nimport { KyselyAdapter } from \"@fragno-dev/db/adapters/kysely\";\nimport { DrizzleAdapter } from \"@fragno-dev/db/adapters/drizzle\";\nimport type { AnySchema } from \"@fragno-dev/db/schema\";\nimport type { DatabaseAdapter } from \"@fragno-dev/db/adapters\";\nimport type { AbstractQuery } from \"@fragno-dev/db/query\";\nimport { createRequire } from \"node:module\";\nimport { mkdir, writeFile, rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\n// Adapter configuration types\nexport interface KyselySqliteAdapter {\n type: \"kysely-sqlite\";\n}\n\nexport interface KyselyPgliteAdapter {\n type: \"kysely-pglite\";\n databasePath?: string;\n}\n\nexport interface DrizzlePgliteAdapter {\n type: \"drizzle-pglite\";\n databasePath?: string;\n}\n\nexport type SupportedAdapter = KyselySqliteAdapter | KyselyPgliteAdapter | DrizzlePgliteAdapter;\n\n// Conditional return types based on adapter\nexport type TestContext<T extends SupportedAdapter> = T extends\n | KyselySqliteAdapter\n | KyselyPgliteAdapter\n ? {\n readonly db: AbstractQuery<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n readonly kysely: Kysely<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n readonly adapter: DatabaseAdapter<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n resetDatabase: () => Promise<void>;\n cleanup: () => Promise<void>;\n }\n : T extends DrizzlePgliteAdapter\n ? {\n readonly db: AbstractQuery<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n readonly drizzle: ReturnType<typeof drizzle<any>>; // eslint-disable-line @typescript-eslint/no-explicit-any\n readonly adapter: DatabaseAdapter<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n resetDatabase: () => Promise<void>;\n cleanup: () => Promise<void>;\n }\n : never;\n\n// Factory function return type\ninterface AdapterFactoryResult<T extends SupportedAdapter> {\n testContext: TestContext<T>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n adapter: DatabaseAdapter<any>;\n}\n\n/**\n * Create Kysely + SQLite adapter using SQLocalKysely (always in-memory)\n */\nexport async function createKyselySqliteAdapter(\n _config: KyselySqliteAdapter,\n schema: AnySchema,\n namespace: string,\n migrateToVersion?: number,\n): Promise<AdapterFactoryResult<KyselySqliteAdapter>> {\n // Helper to create a new database instance and run migrations\n const createDatabase = async () => {\n // Create SQLocalKysely instance (always in-memory for tests)\n const { dialect } = new SQLocalKysely(\":memory:\");\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const kysely = new Kysely<any>({\n dialect,\n });\n\n // Create KyselyAdapter\n const adapter = new KyselyAdapter({\n db: kysely,\n provider: \"sqlite\",\n });\n\n // Run migrations\n const migrator = adapter.createMigrationEngine(schema, namespace);\n const preparedMigration = migrateToVersion\n ? await migrator.prepareMigrationTo(migrateToVersion, {\n updateSettings: false,\n })\n : await migrator.prepareMigration({\n updateSettings: false,\n });\n await preparedMigration.execute();\n\n // Create ORM instance\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const orm = adapter.createQueryEngine(schema, namespace) as AbstractQuery<any>;\n\n return { kysely, adapter, orm };\n };\n\n // Create initial database\n let { kysely, adapter, orm } = await createDatabase();\n\n // Reset database function - creates a fresh in-memory database and re-runs migrations\n const resetDatabase = async () => {\n // Destroy the old Kysely instance\n await kysely.destroy();\n\n // Create a new database instance\n const newDb = await createDatabase();\n kysely = newDb.kysely;\n adapter = newDb.adapter;\n orm = newDb.orm;\n };\n\n // Cleanup function - closes connections (no files to delete for in-memory)\n const cleanup = async () => {\n await kysely.destroy();\n };\n\n return {\n testContext: {\n get db() {\n return orm;\n },\n get kysely() {\n return kysely;\n },\n get adapter() {\n return adapter;\n },\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create Kysely + PGLite adapter using kysely-pglite\n */\nexport async function createKyselyPgliteAdapter(\n config: KyselyPgliteAdapter,\n schema: AnySchema,\n namespace: string,\n migrateToVersion?: number,\n): Promise<AdapterFactoryResult<KyselyPgliteAdapter>> {\n const databasePath = config.databasePath;\n\n // Helper to create a new database instance and run migrations\n const createDatabase = async () => {\n // Create KyselyPGlite instance\n const kyselyPglite = await KyselyPGlite.create(databasePath);\n\n // Create Kysely instance with PGlite dialect\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const kysely = new Kysely<any>({\n dialect: kyselyPglite.dialect,\n });\n\n // Create KyselyAdapter\n const adapter = new KyselyAdapter({\n db: kysely,\n provider: \"postgresql\",\n });\n\n // Run migrations\n const migrator = adapter.createMigrationEngine(schema, namespace);\n const preparedMigration = migrateToVersion\n ? await migrator.prepareMigrationTo(migrateToVersion, {\n updateSettings: false,\n })\n : await migrator.prepareMigration({\n updateSettings: false,\n });\n await preparedMigration.execute();\n\n // Create ORM instance\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const orm = adapter.createQueryEngine(schema, namespace) as AbstractQuery<any>;\n\n return { kysely, adapter, kyselyPglite, orm };\n };\n\n // Create initial database\n let { kysely, adapter, kyselyPglite, orm } = await createDatabase();\n\n // Reset database function - creates a fresh database and re-runs migrations\n const resetDatabase = async () => {\n // Close the old instances\n await kysely.destroy();\n\n try {\n await kyselyPglite.client.close();\n } catch {\n // Ignore if already closed\n }\n\n // Create a new database instance\n const newDb = await createDatabase();\n kysely = newDb.kysely;\n adapter = newDb.adapter;\n kyselyPglite = newDb.kyselyPglite;\n orm = newDb.orm;\n };\n\n // Cleanup function - closes connections and deletes database directory\n const cleanup = async () => {\n await kysely.destroy();\n\n try {\n await kyselyPglite.client.close();\n } catch {\n // Ignore if already closed\n }\n\n // Delete the database directory if it exists and is a file path\n if (databasePath && databasePath !== \":memory:\" && existsSync(databasePath)) {\n await rm(databasePath, { recursive: true, force: true });\n }\n };\n\n return {\n testContext: {\n get db() {\n return orm;\n },\n get kysely() {\n return kysely;\n },\n get adapter() {\n return adapter;\n },\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create Drizzle + PGLite adapter using drizzle-orm/pglite\n */\nexport async function createDrizzlePgliteAdapter(\n config: DrizzlePgliteAdapter,\n schema: AnySchema,\n namespace: string,\n _migrateToVersion?: number,\n): Promise<AdapterFactoryResult<DrizzlePgliteAdapter>> {\n const databasePath = config.databasePath;\n\n // Import drizzle-kit for migrations\n const require = createRequire(import.meta.url);\n const { generateDrizzleJson, generateMigration } =\n require(\"drizzle-kit/api\") as typeof import(\"drizzle-kit/api\");\n\n // Import generateSchema from the properly exported module\n const { generateSchema } = await import(\"@fragno-dev/db/adapters/drizzle/generate\");\n\n // Helper to write schema to file and dynamically import it\n const writeAndLoadSchema = async () => {\n const testDir = join(import.meta.dirname, \"_generated\", \"drizzle-test\");\n await mkdir(testDir, { recursive: true }).catch(() => {\n // Ignore error if directory already exists\n });\n\n const schemaFilePath = join(\n testDir,\n `test-schema-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.ts`,\n );\n\n // Generate and write the Drizzle schema to file\n const drizzleSchemaTs = generateSchema([{ namespace: namespace ?? \"\", schema }], \"postgresql\");\n await writeFile(schemaFilePath, drizzleSchemaTs, \"utf-8\");\n\n // Dynamically import the generated schema (with cache busting)\n const schemaModule = await import(`${schemaFilePath}?t=${Date.now()}`);\n\n const cleanup = async () => {\n await rm(testDir, { recursive: true, force: true });\n };\n\n return { schemaModule, cleanup };\n };\n\n // Helper to create a new database instance and run migrations\n const createDatabase = async () => {\n // Write schema to file and load it\n const { schemaModule, cleanup } = await writeAndLoadSchema();\n\n // Create PGlite instance\n const pglite = new PGlite(databasePath);\n\n // Create Drizzle instance with PGlite\n const db = drizzle(pglite, {\n schema: schemaModule,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any;\n\n // Generate and run migrations\n const migrationStatements = await generateMigration(\n generateDrizzleJson({}), // Empty schema (starting state)\n generateDrizzleJson(schemaModule), // Target schema\n );\n\n // Execute migration SQL\n for (const statement of migrationStatements) {\n await db.execute(statement);\n }\n\n // Create DrizzleAdapter\n const adapter = new DrizzleAdapter({\n db: () => db,\n provider: \"postgresql\",\n });\n\n // Create ORM instance\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const orm = adapter.createQueryEngine(schema, namespace) as AbstractQuery<any>;\n\n return { drizzle: db, adapter, pglite, cleanup, orm };\n };\n\n // Create initial database\n let { drizzle: drizzleDb, adapter, pglite, cleanup: schemaCleanup, orm } = await createDatabase();\n\n // Reset database function - creates a fresh database and re-runs migrations\n const resetDatabase = async () => {\n // Close the old instances and cleanup\n await pglite.close();\n await schemaCleanup();\n\n // Create a new database instance\n const newDb = await createDatabase();\n drizzleDb = newDb.drizzle;\n adapter = newDb.adapter;\n pglite = newDb.pglite;\n schemaCleanup = newDb.cleanup;\n orm = newDb.orm;\n };\n\n // Cleanup function - closes connections and deletes generated files and database directory\n const cleanup = async () => {\n await pglite.close();\n await schemaCleanup();\n\n // Delete the database directory if it exists and is a file path\n if (databasePath && databasePath !== \":memory:\" && existsSync(databasePath)) {\n await rm(databasePath, { recursive: true, force: true });\n }\n };\n\n return {\n testContext: {\n get db() {\n return orm;\n },\n get drizzle() {\n return drizzleDb;\n },\n get adapter() {\n return adapter;\n },\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create adapter based on configuration\n */\nexport async function createAdapter<T extends SupportedAdapter>(\n adapterConfig: T,\n schema: AnySchema,\n namespace: string,\n migrateToVersion?: number,\n): Promise<AdapterFactoryResult<T>> {\n if (adapterConfig.type === \"kysely-sqlite\") {\n return createKyselySqliteAdapter(adapterConfig, schema, namespace, migrateToVersion) as Promise<\n AdapterFactoryResult<T>\n >;\n } else if (adapterConfig.type === \"kysely-pglite\") {\n return createKyselyPgliteAdapter(adapterConfig, schema, namespace, migrateToVersion) as Promise<\n AdapterFactoryResult<T>\n >;\n } else if (adapterConfig.type === \"drizzle-pglite\") {\n return createDrizzlePgliteAdapter(\n adapterConfig,\n schema,\n namespace,\n migrateToVersion,\n ) as Promise<AdapterFactoryResult<T>>;\n }\n\n throw new Error(`Unsupported adapter type: ${(adapterConfig as SupportedAdapter).type}`);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"adapters.js","names":["kysely","adapter","ormMap","kyselyPglite","cleanup","pglite"],"sources":["../src/adapters.ts"],"sourcesContent":["import { Kysely } from \"kysely\";\nimport { SQLocalKysely } from \"sqlocal/kysely\";\nimport { KyselyPGlite } from \"kysely-pglite\";\nimport { drizzle } from \"drizzle-orm/pglite\";\nimport { PGlite } from \"@electric-sql/pglite\";\nimport { KyselyAdapter } from \"@fragno-dev/db/adapters/kysely\";\nimport { DrizzleAdapter } from \"@fragno-dev/db/adapters/drizzle\";\nimport type { AnySchema } from \"@fragno-dev/db/schema\";\nimport type { DatabaseAdapter } from \"@fragno-dev/db/adapters\";\nimport type { AbstractQuery } from \"@fragno-dev/db/query\";\nimport { createRequire } from \"node:module\";\nimport { mkdir, writeFile, rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { BaseTestContext } from \".\";\nimport { createCommonTestContextMethods } from \".\";\n\n// Adapter configuration types\nexport interface KyselySqliteAdapter {\n type: \"kysely-sqlite\";\n}\n\nexport interface KyselyPgliteAdapter {\n type: \"kysely-pglite\";\n databasePath?: string;\n}\n\nexport interface DrizzlePgliteAdapter {\n type: \"drizzle-pglite\";\n databasePath?: string;\n}\n\nexport type SupportedAdapter = KyselySqliteAdapter | KyselyPgliteAdapter | DrizzlePgliteAdapter;\n\n// Schema configuration for multi-schema adapters\nexport interface SchemaConfig {\n schema: AnySchema;\n namespace: string;\n migrateToVersion?: number;\n}\n\n// Internal test context extends BaseTestContext with getOrm (not exposed publicly)\ninterface InternalTestContext extends BaseTestContext {\n getOrm: <TSchema extends AnySchema>(namespace: string) => AbstractQuery<TSchema>;\n}\n\n// Conditional return types based on adapter (adapter-specific properties only)\nexport type AdapterContext<T extends SupportedAdapter> = T extends\n | KyselySqliteAdapter\n | KyselyPgliteAdapter\n ? {\n readonly kysely: Kysely<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n }\n : T extends DrizzlePgliteAdapter\n ? {\n readonly drizzle: ReturnType<typeof drizzle<any>>; // eslint-disable-line @typescript-eslint/no-explicit-any\n }\n : never;\n\n// Factory function return type\ninterface AdapterFactoryResult<T extends SupportedAdapter> {\n testContext: InternalTestContext & AdapterContext<T>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n adapter: DatabaseAdapter<any>;\n}\n\n/**\n * Create Kysely + SQLite adapter using SQLocalKysely (always in-memory)\n * Supports multiple schemas with separate namespaces\n */\nexport async function createKyselySqliteAdapter(\n _config: KyselySqliteAdapter,\n schemas: SchemaConfig[],\n): Promise<AdapterFactoryResult<KyselySqliteAdapter>> {\n // Helper to create a new database instance and run migrations for all schemas\n const createDatabase = async () => {\n // Create SQLocalKysely instance (always in-memory for tests)\n const { dialect } = new SQLocalKysely(\":memory:\");\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const kysely = new Kysely<any>({\n dialect,\n });\n\n // Create KyselyAdapter\n const adapter = new KyselyAdapter({\n db: kysely,\n provider: \"sqlite\",\n });\n\n // Run migrations for all schemas in order\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ormMap = new Map<string, AbstractQuery<any, any>>();\n\n for (const { schema, namespace, migrateToVersion } of schemas) {\n // Run migrations\n const migrator = adapter.createMigrationEngine(schema, namespace);\n const preparedMigration = migrateToVersion\n ? await migrator.prepareMigrationTo(migrateToVersion, {\n updateSettings: false,\n })\n : await migrator.prepareMigration({\n updateSettings: false,\n });\n await preparedMigration.execute();\n\n // Create ORM instance and store in map\n const orm = adapter.createQueryEngine(schema, namespace);\n ormMap.set(namespace, orm);\n }\n\n return { kysely, adapter, ormMap };\n };\n\n // Create initial database\n let { kysely, adapter, ormMap } = await createDatabase();\n\n // Reset database function - truncates all tables (only supported for in-memory databases)\n const resetDatabase = async () => {\n // For SQLite, truncate all tables by deleting rows\n for (const { schema, namespace } of schemas) {\n const mapper = adapter.createTableNameMapper(namespace);\n for (const tableName of Object.keys(schema.tables)) {\n const physicalTableName = mapper.toPhysical(tableName);\n await kysely.deleteFrom(physicalTableName).execute();\n }\n }\n };\n\n // Cleanup function - closes connections (no files to delete for in-memory)\n const cleanup = async () => {\n await kysely.destroy();\n };\n\n const commonMethods = createCommonTestContextMethods(ormMap);\n\n return {\n testContext: {\n get kysely() {\n return kysely;\n },\n get adapter() {\n return adapter;\n },\n ...commonMethods,\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create Kysely + PGLite adapter using kysely-pglite\n * Supports multiple schemas with separate namespaces\n */\nexport async function createKyselyPgliteAdapter(\n config: KyselyPgliteAdapter,\n schemas: SchemaConfig[],\n): Promise<AdapterFactoryResult<KyselyPgliteAdapter>> {\n const databasePath = config.databasePath;\n\n // Helper to create a new database instance and run migrations for all schemas\n const createDatabase = async () => {\n // Create KyselyPGlite instance\n const kyselyPglite = await KyselyPGlite.create(databasePath);\n\n // Create Kysely instance with PGlite dialect\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const kysely = new Kysely<any>({\n dialect: kyselyPglite.dialect,\n });\n\n // Create KyselyAdapter\n const adapter = new KyselyAdapter({\n db: kysely,\n provider: \"postgresql\",\n });\n\n // Run migrations for all schemas in order\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ormMap = new Map<string, AbstractQuery<any, any>>();\n\n for (const { schema, namespace, migrateToVersion } of schemas) {\n // Run migrations\n const migrator = adapter.createMigrationEngine(schema, namespace);\n const preparedMigration = migrateToVersion\n ? await migrator.prepareMigrationTo(migrateToVersion, {\n updateSettings: false,\n })\n : await migrator.prepareMigration({\n updateSettings: false,\n });\n await preparedMigration.execute();\n\n // Create ORM instance and store in map\n const orm = adapter.createQueryEngine(schema, namespace);\n ormMap.set(namespace, orm);\n }\n\n return { kysely, adapter, kyselyPglite, ormMap };\n };\n\n // Create initial database\n const { kysely, adapter, kyselyPglite, ormMap } = await createDatabase();\n\n // Reset database function - truncates all tables (only supported for in-memory databases)\n const resetDatabase = async () => {\n if (databasePath && databasePath !== \":memory:\") {\n throw new Error(\"resetDatabase is only supported for in-memory databases\");\n }\n\n // Truncate all tables\n for (const { schema, namespace } of schemas) {\n const mapper = adapter.createTableNameMapper(namespace);\n for (const tableName of Object.keys(schema.tables)) {\n const physicalTableName = mapper.toPhysical(tableName);\n await kysely.deleteFrom(physicalTableName).execute();\n }\n }\n };\n\n // Cleanup function - closes connections and deletes database directory\n const cleanup = async () => {\n await kysely.destroy();\n\n try {\n await kyselyPglite.client.close();\n } catch {\n // Ignore if already closed\n }\n\n // Delete the database directory if it exists and is a file path\n if (databasePath && databasePath !== \":memory:\" && existsSync(databasePath)) {\n await rm(databasePath, { recursive: true, force: true });\n }\n };\n\n const commonMethods = createCommonTestContextMethods(ormMap);\n\n return {\n testContext: {\n get kysely() {\n return kysely;\n },\n get adapter() {\n return adapter;\n },\n ...commonMethods,\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create Drizzle + PGLite adapter using drizzle-orm/pglite\n * Supports multiple schemas with separate namespaces\n */\nexport async function createDrizzlePgliteAdapter(\n config: DrizzlePgliteAdapter,\n schemas: SchemaConfig[],\n): Promise<AdapterFactoryResult<DrizzlePgliteAdapter>> {\n const databasePath = config.databasePath;\n\n // Import drizzle-kit for migrations\n const require = createRequire(import.meta.url);\n const { generateDrizzleJson, generateMigration } =\n require(\"drizzle-kit/api\") as typeof import(\"drizzle-kit/api\");\n\n // Import generateSchema from the properly exported module\n const { generateSchema } = await import(\"@fragno-dev/db/adapters/drizzle/generate\");\n\n // Helper to write schema to file and dynamically import it\n const writeAndLoadSchema = async () => {\n const testDir = join(import.meta.dirname, \"_generated\", \"drizzle-test\");\n await mkdir(testDir, { recursive: true }).catch(() => {\n // Ignore error if directory already exists\n });\n\n const schemaFilePath = join(\n testDir,\n `test-schema-${Date.now()}-${Math.random().toString(36).slice(2, 9)}.ts`,\n );\n\n // Combine all schemas into a single Drizzle schema with namespaced tables\n const schemaConfigs = schemas.map(({ schema, namespace }) => ({\n namespace: namespace ?? \"\",\n schema,\n }));\n\n const drizzleSchemaTs = generateSchema(schemaConfigs, \"postgresql\");\n await writeFile(schemaFilePath, drizzleSchemaTs, \"utf-8\");\n\n // Dynamically import the generated schema (with cache busting)\n const schemaModule = await import(`${schemaFilePath}?t=${Date.now()}`);\n\n const cleanup = async () => {\n await rm(testDir, { recursive: true, force: true });\n };\n\n return { schemaModule, cleanup };\n };\n\n // Helper to create a new database instance and run migrations for all schemas\n const createDatabase = async () => {\n // Write schema to file and load it\n const { schemaModule, cleanup } = await writeAndLoadSchema();\n\n // Create PGlite instance\n const pglite = new PGlite(databasePath);\n\n // Create Drizzle instance with PGlite\n const db = drizzle(pglite, {\n schema: schemaModule,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n }) as any;\n\n // Generate and run migrations\n const migrationStatements = await generateMigration(\n generateDrizzleJson({}), // Empty schema (starting state)\n generateDrizzleJson(schemaModule), // Target schema\n );\n\n // Execute migration SQL\n for (const statement of migrationStatements) {\n await db.execute(statement);\n }\n\n // Create DrizzleAdapter\n const adapter = new DrizzleAdapter({\n db: () => db,\n provider: \"postgresql\",\n });\n\n // Create ORM instances for each schema and store in map\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ormMap = new Map<string, AbstractQuery<any, any>>();\n\n for (const { schema, namespace } of schemas) {\n const orm = adapter.createQueryEngine(schema, namespace);\n ormMap.set(namespace, orm);\n }\n\n return { drizzle: db, adapter, pglite, cleanup, ormMap };\n };\n\n // Create initial database\n const {\n drizzle: drizzleDb,\n adapter,\n pglite,\n cleanup: schemaCleanup,\n ormMap,\n } = await createDatabase();\n\n // Reset database function - truncates all tables (only supported for in-memory databases)\n const resetDatabase = async () => {\n if (databasePath && databasePath !== \":memory:\") {\n throw new Error(\"resetDatabase is only supported for in-memory databases\");\n }\n\n // Truncate all tables by deleting rows\n for (const { schema, namespace } of schemas) {\n const mapper = adapter.createTableNameMapper(namespace);\n for (const tableName of Object.keys(schema.tables)) {\n const physicalTableName = mapper.toPhysical(tableName);\n await drizzleDb.execute(`DELETE FROM \"${physicalTableName}\"`);\n }\n }\n };\n\n // Cleanup function - closes connections and deletes generated files and database directory\n const cleanup = async () => {\n await pglite.close();\n await schemaCleanup();\n\n // Delete the database directory if it exists and is a file path\n if (databasePath && databasePath !== \":memory:\" && existsSync(databasePath)) {\n await rm(databasePath, { recursive: true, force: true });\n }\n };\n\n const commonMethods = createCommonTestContextMethods(ormMap);\n\n return {\n testContext: {\n get drizzle() {\n return drizzleDb;\n },\n get adapter() {\n return adapter;\n },\n ...commonMethods,\n resetDatabase,\n cleanup,\n },\n get adapter() {\n return adapter;\n },\n };\n}\n\n/**\n * Create adapter based on configuration\n * Supports multiple schemas with separate namespaces\n */\nexport async function createAdapter<T extends SupportedAdapter>(\n adapterConfig: T,\n schemas: SchemaConfig[],\n): Promise<AdapterFactoryResult<T>> {\n if (adapterConfig.type === \"kysely-sqlite\") {\n return createKyselySqliteAdapter(adapterConfig, schemas) as Promise<AdapterFactoryResult<T>>;\n } else if (adapterConfig.type === \"kysely-pglite\") {\n return createKyselyPgliteAdapter(adapterConfig, schemas) as Promise<AdapterFactoryResult<T>>;\n } else if (adapterConfig.type === \"drizzle-pglite\") {\n return createDrizzlePgliteAdapter(adapterConfig, schemas) as Promise<AdapterFactoryResult<T>>;\n }\n\n throw new Error(`Unsupported adapter type: ${(adapterConfig as SupportedAdapter).type}`);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AdapterContext, SupportedAdapter } from "./adapters.js";
|
|
2
|
+
import { BaseTestContext } from "./index.js";
|
|
3
|
+
import { AnySchema } from "@fragno-dev/db/schema";
|
|
4
|
+
import { AbstractQuery } from "@fragno-dev/db/query";
|
|
5
|
+
import { DatabaseAdapter } from "@fragno-dev/db";
|
|
6
|
+
import { FragmentInstantiationBuilder, FragnoInstantiatedFragment, FragnoPublicConfig, RequestThisContext } from "@fragno-dev/core";
|
|
7
|
+
import { AnyRouteOrFactory, FlattenRouteFactories } from "@fragno-dev/core/route";
|
|
8
|
+
|
|
9
|
+
//#region src/db-test.d.ts
|
|
10
|
+
type BoundServices<T> = { [K in keyof T]: T[K] extends ((this: any, ...args: infer A) => infer R) ? (...args: A) => R : T[K] extends Record<string, unknown> ? BoundServices<T[K]> : T[K] };
|
|
11
|
+
type ExtractSchemaFromDeps<TDeps> = TDeps extends {
|
|
12
|
+
schema: infer TSchema extends AnySchema;
|
|
13
|
+
} ? TSchema : AnySchema;
|
|
14
|
+
type AnyLinkedFragments = Record<string, any>;
|
|
15
|
+
interface FragmentResult<TDeps, TServices extends Record<string, unknown>, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TRoutes extends readonly any[],
|
|
16
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
17
|
+
TSchema$1 extends AnySchema, TLinkedFragments extends AnyLinkedFragments = {}> {
|
|
18
|
+
fragment: FragnoInstantiatedFragment<TRoutes, TDeps, TServices, TServiceThisContext, THandlerThisContext, TRequestStorage, FragnoPublicConfig, TLinkedFragments>;
|
|
19
|
+
services: TServices;
|
|
20
|
+
deps: TDeps;
|
|
21
|
+
callRoute: FragnoInstantiatedFragment<TRoutes, TDeps, TServices, TServiceThisContext, THandlerThisContext, TRequestStorage, FragnoPublicConfig, TLinkedFragments>["callRoute"];
|
|
22
|
+
db: AbstractQuery<TSchema$1>;
|
|
23
|
+
}
|
|
24
|
+
type AnyFragmentResult = FragmentResult<any,
|
|
25
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
26
|
+
any,
|
|
27
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
28
|
+
any,
|
|
29
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
30
|
+
any,
|
|
31
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
32
|
+
any,
|
|
33
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
34
|
+
any,
|
|
35
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
36
|
+
any,
|
|
37
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
38
|
+
any>;
|
|
39
|
+
/**
|
|
40
|
+
* Test context combining base and adapter-specific functionality
|
|
41
|
+
*/
|
|
42
|
+
type TestContext<T extends SupportedAdapter, TFirstFragmentThisContext extends RequestThisContext = RequestThisContext> = BaseTestContext & AdapterContext<T> & {
|
|
43
|
+
adapter: DatabaseAdapter<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Execute a callback within the first fragment's request context.
|
|
46
|
+
* This is useful for calling services outside of route handlers in tests.
|
|
47
|
+
*/
|
|
48
|
+
inContext<TResult>(callback: (this: TFirstFragmentThisContext) => TResult): TResult;
|
|
49
|
+
inContext<TResult>(callback: (this: TFirstFragmentThisContext) => Promise<TResult>): Promise<TResult>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Result of building the database fragments test
|
|
53
|
+
*/
|
|
54
|
+
interface DatabaseFragmentsTestResult<TFragments extends Record<string, AnyFragmentResult>, TAdapter extends SupportedAdapter, TFirstFragmentThisContext extends RequestThisContext = RequestThisContext> {
|
|
55
|
+
fragments: TFragments;
|
|
56
|
+
test: TestContext<TAdapter, TFirstFragmentThisContext>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Builder for creating multiple database fragments for testing
|
|
60
|
+
*/
|
|
61
|
+
declare class DatabaseFragmentsTestBuilder<TFragments extends Record<string, AnyFragmentResult>, TAdapter extends SupportedAdapter | undefined = undefined, TFirstFragmentThisContext extends RequestThisContext = RequestThisContext> {
|
|
62
|
+
#private;
|
|
63
|
+
/**
|
|
64
|
+
* Set the test adapter configuration
|
|
65
|
+
*/
|
|
66
|
+
withTestAdapter<TNewAdapter extends SupportedAdapter>(adapter: TNewAdapter): DatabaseFragmentsTestBuilder<TFragments, TNewAdapter, TFirstFragmentThisContext>;
|
|
67
|
+
/**
|
|
68
|
+
* Add a fragment to the test setup
|
|
69
|
+
*
|
|
70
|
+
* @param name - Unique name for the fragment
|
|
71
|
+
* @param builder - Pre-configured instantiation builder
|
|
72
|
+
* @param options - Additional options (optional)
|
|
73
|
+
*/
|
|
74
|
+
withFragment<TName extends string, TConfig, TOptions extends FragnoPublicConfig, TDeps, TBaseServices extends Record<string, unknown>, TServices extends Record<string, unknown>, TServiceDependencies, TPrivateServices extends Record<string, unknown>, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TRoutesOrFactories extends readonly AnyRouteOrFactory[], TLinkedFragments extends AnyLinkedFragments>(name: TName, builder: FragmentInstantiationBuilder<TConfig, TOptions, TDeps, TBaseServices, TServices, TServiceDependencies, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TRoutesOrFactories, TLinkedFragments>, options?: {
|
|
75
|
+
migrateToVersion?: number;
|
|
76
|
+
}): DatabaseFragmentsTestBuilder<TFragments & { [K in TName]: FragmentResult<TDeps, BoundServices<TBaseServices & TServices>, TServiceThisContext, THandlerThisContext, TRequestStorage, FlattenRouteFactories<TRoutesOrFactories>, ExtractSchemaFromDeps<TDeps>,
|
|
77
|
+
// Extract actual schema type from deps
|
|
78
|
+
TLinkedFragments> }, TAdapter, keyof TFragments extends never ? THandlerThisContext : TFirstFragmentThisContext>;
|
|
79
|
+
/**
|
|
80
|
+
* Build the test setup and return fragments and test context
|
|
81
|
+
*/
|
|
82
|
+
build(): Promise<TAdapter extends SupportedAdapter ? DatabaseFragmentsTestResult<TFragments, TAdapter, TFirstFragmentThisContext> : never>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a builder for setting up multiple database fragments for testing.
|
|
86
|
+
* This is the new builder-based API that works with the new fragment instantiation builders.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const userFragmentDef = defineFragment("user")
|
|
91
|
+
* .extend(withDatabase(userSchema))
|
|
92
|
+
* .withDependencies(...)
|
|
93
|
+
* .build();
|
|
94
|
+
*
|
|
95
|
+
* const postFragmentDef = defineFragment("post")
|
|
96
|
+
* .extend(withDatabase(postSchema))
|
|
97
|
+
* .withDependencies(...)
|
|
98
|
+
* .build();
|
|
99
|
+
*
|
|
100
|
+
* const { fragments, test } = await buildDatabaseFragmentsTest()
|
|
101
|
+
* .withTestAdapter({ type: "kysely-sqlite" })
|
|
102
|
+
* .withFragment("user",
|
|
103
|
+
* instantiate(userFragmentDef)
|
|
104
|
+
* .withConfig({ ... })
|
|
105
|
+
* .withRoutes([...])
|
|
106
|
+
* )
|
|
107
|
+
* .withFragment("post",
|
|
108
|
+
* instantiate(postFragmentDef)
|
|
109
|
+
* .withRoutes([...])
|
|
110
|
+
* )
|
|
111
|
+
* .build();
|
|
112
|
+
*
|
|
113
|
+
* // Access fragments by name
|
|
114
|
+
* await fragments.user.services.createUser(...);
|
|
115
|
+
* await fragments.post.services.createPost(...);
|
|
116
|
+
*
|
|
117
|
+
* // Access dependencies directly
|
|
118
|
+
* const userDeps = fragments.user.deps;
|
|
119
|
+
*
|
|
120
|
+
* // Shared test context
|
|
121
|
+
* await test.resetDatabase();
|
|
122
|
+
* await test.cleanup();
|
|
123
|
+
* const adapter = test.adapter; // Access the database adapter
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare function buildDatabaseFragmentsTest(): DatabaseFragmentsTestBuilder<{}, undefined, RequestThisContext>;
|
|
127
|
+
//#endregion
|
|
128
|
+
export { DatabaseFragmentsTestBuilder, buildDatabaseFragmentsTest };
|
|
129
|
+
//# sourceMappingURL=db-test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-test.d.ts","names":[],"sources":["../src/db-test.ts"],"sourcesContent":[],"mappings":"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"}
|