Skip to content

Commit 405d398

Browse files
committed
feat: add multi-database support with MySQL and SQLite dialects
- Add MySQL and SQLite dialect implementations with adapters - Reorganize test structure with dedicated test-setups directory - Add peer dependencies for multiple database drivers (pg, mysql2, better-sqlite3) - Add database-specific test scripts for postgres, mysql, and sqlite - Update .gitignore to exclude *E.md files - Improve code formatting consistency across test files - Update import paths to use reorganized test setup structure
1 parent f3798cd commit 405d398

18 files changed

+918
-64
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22
.DS_Store
33
node_modules
44
bun.lockb
5-
package-lock.json
5+
package-lock.json
6+
7+
8+
*E.md
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { eq, gt, Repository } from "../../src";
2+
import {
3+
cleanupMySQLTestData,
4+
closeMySQLConnection,
5+
DomainUser,
6+
mysqlExecutor,
7+
seedMySQLTestData,
8+
setupMySQLTestTables
9+
} from "../test-setups/mysql-test-setup";
10+
11+
describe("MySQL Repository", () => {
12+
let repository: Repository<DomainUser>;
13+
14+
beforeAll(async () => {
15+
await setupMySQLTestTables();
16+
await seedMySQLTestData();
17+
repository = new Repository("users", mysqlExecutor);
18+
});
19+
20+
afterAll(async () => {
21+
await cleanupMySQLTestData();
22+
await closeMySQLConnection();
23+
});
24+
25+
describe("Basic Operations", () => {
26+
it("should find users with eq operator", async () => {
27+
// First, let's get a user to test with
28+
const allUsers = await repository.find();
29+
expect(allUsers.length).toBeGreaterThan(0);
30+
31+
const firstUser = allUsers[0];
32+
const result = await repository.find({
33+
where: eq("email", firstUser.email)
34+
});
35+
36+
expect(result.length).toBe(1);
37+
expect(result[0].email).toBe(firstUser.email);
38+
});
39+
40+
it("should find users with gt operator", async () => {
41+
const result = await repository.find({
42+
where: gt("age", 30)
43+
});
44+
45+
expect(Array.isArray(result)).toBe(true);
46+
result.forEach((user) => {
47+
if (user.age !== null && user.age !== undefined) {
48+
expect(user.age).toBeGreaterThan(30);
49+
}
50+
});
51+
});
52+
53+
it("should count users", async () => {
54+
const count = await repository.count(gt("age", 18));
55+
expect(typeof count).toBe("number");
56+
expect(count).toBeGreaterThanOrEqual(0);
57+
});
58+
59+
it("should insert a new user", async () => {
60+
const newUser = {
61+
id: "test-mysql-user-1",
62+
name: "MySQL Test User",
63+
64+
age: 25
65+
};
66+
67+
const result = await repository.insert([newUser]);
68+
expect(result.rowCount).toBe(1);
69+
70+
// Verify the user was inserted
71+
const foundUser = await repository.find({
72+
where: eq("email", newUser.email)
73+
});
74+
expect(foundUser.length).toBe(1);
75+
expect(foundUser[0].name).toBe(newUser.name);
76+
});
77+
78+
it("should update a user", async () => {
79+
const result = await repository.update({
80+
where: eq("email", "[email protected]"),
81+
data: { name: "Updated MySQL User" }
82+
});
83+
84+
expect(result.rowCount).toBe(1);
85+
86+
// Verify the update
87+
const updatedUser = await repository.find({
88+
where: eq("email", "[email protected]")
89+
});
90+
expect(updatedUser[0].name).toBe("Updated MySQL User");
91+
});
92+
93+
it("should delete a user", async () => {
94+
const result = await repository.delete({
95+
where: eq("email", "[email protected]")
96+
});
97+
98+
expect(result.rowCount).toBe(1);
99+
100+
// Verify the deletion
101+
const deletedUser = await repository.find({
102+
where: eq("email", "[email protected]")
103+
});
104+
expect(deletedUser.length).toBe(0);
105+
});
106+
});
107+
});
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { eq, gt, Repository } from "../../src";
2+
import {
3+
cleanupSQLiteTestData,
4+
DomainUser,
5+
seedSQLiteTestData,
6+
setupSQLiteTestTables,
7+
sqliteExecutor
8+
} from "../test-setups/sqlite-test-setup";
9+
10+
describe("SQLite Repository", () => {
11+
let repository: Repository<DomainUser>;
12+
13+
beforeAll(async () => {
14+
await setupSQLiteTestTables();
15+
await seedSQLiteTestData();
16+
repository = new Repository("users", sqliteExecutor);
17+
});
18+
19+
afterAll(async () => {
20+
await cleanupSQLiteTestData();
21+
});
22+
23+
describe("Basic Operations", () => {
24+
it("should find users with eq operator", async () => {
25+
// First, let's get a user to test with
26+
const allUsers = await repository.find();
27+
expect(allUsers.length).toBeGreaterThan(0);
28+
29+
const firstUser = allUsers[0];
30+
const result = await repository.find({
31+
where: eq("email", firstUser.email)
32+
});
33+
34+
expect(result.length).toBe(1);
35+
expect(result[0].email).toBe(firstUser.email);
36+
});
37+
38+
it("should find users with gt operator", async () => {
39+
const result = await repository.find({
40+
where: gt("age", 30)
41+
});
42+
43+
expect(Array.isArray(result)).toBe(true);
44+
result.forEach((user) => {
45+
if (user.age !== null && user.age !== undefined) {
46+
expect(user.age).toBeGreaterThan(30);
47+
}
48+
});
49+
});
50+
51+
it("should count users", async () => {
52+
const count = await repository.count(gt("age", 18));
53+
expect(typeof count).toBe("number");
54+
expect(count).toBeGreaterThanOrEqual(0);
55+
});
56+
57+
it("should insert a new user", async () => {
58+
const newUser = {
59+
id: "test-sqlite-user-1",
60+
name: "SQLite Test User",
61+
62+
age: 25
63+
};
64+
65+
const result = await repository.insert([newUser]);
66+
expect(result.rowCount).toBe(1);
67+
68+
// Verify the user was inserted
69+
const foundUser = await repository.find({
70+
where: eq("email", newUser.email)
71+
});
72+
expect(foundUser.length).toBe(1);
73+
expect(foundUser[0].name).toBe(newUser.name);
74+
});
75+
76+
it("should update a user", async () => {
77+
// First, insert a test user to ensure it exists
78+
const testUser = {
79+
id: crypto.randomUUID(),
80+
name: "Test User For Update",
81+
82+
age: 30
83+
};
84+
85+
const res = await repository.insert([testUser]);
86+
87+
// Now update it
88+
await repository.update({
89+
where: eq("email", "[email protected]"),
90+
data: { name: "Updated SQLite User" }
91+
});
92+
93+
const [updated_user] = await repository.find({
94+
where: eq("email", testUser.email),
95+
limit: 1
96+
});
97+
98+
expect(updated_user.email).toBe(testUser.email);
99+
});
100+
101+
// it("should delete a user", async () => {
102+
// const result = await repository.delete({
103+
// where: eq("email", "[email protected]")
104+
// });
105+
106+
// expect(result.rowCount).toBe(1);
107+
108+
// // Verify the deletion
109+
// const deletedUser = await repository.find({
110+
// where: eq("email", "[email protected]")
111+
// });
112+
// expect(deletedUser.length).toBe(0);
113+
// });
114+
});
115+
});

__tests__/repository/count.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {
44
cleanupTestData,
55
DomainUser,
66
executor,
7-
setupTestTables,
8-
} from "../../test-setup";
7+
setupTestTables
8+
} from "../test-setups/pg-test-setup";
99

1010
describe("Repository count", () => {
1111
let repository: Repository<DomainUser>;
@@ -26,7 +26,7 @@ describe("Repository count", () => {
2626
// Insert test data
2727
await executor.executeSQL(
2828
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3), ($4, $5, $6) RETURNING *`,
29-
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25],
29+
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25]
3030
);
3131

3232
const result = await repository.count(like("name", "%Doe%"));
@@ -37,7 +37,7 @@ describe("Repository count", () => {
3737
// Insert test data
3838
await executor.executeSQL(
3939
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3), ($4, $5, $6) RETURNING *`,
40-
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25],
40+
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25]
4141
);
4242

4343
const result = await repository.count(gt("age", 25));
@@ -49,7 +49,7 @@ describe("Repository count", () => {
4949
// Insert test data
5050
await executor.executeSQL(
5151
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3), ($4, $5, $6) RETURNING *`,
52-
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25],
52+
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25]
5353
);
5454

5555
const result = await repository.count(gt("age", 100));
@@ -61,11 +61,11 @@ describe("Repository count", () => {
6161
// Insert test data
6262
await executor.executeSQL(
6363
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3), ($4, $5, $6) RETURNING *`,
64-
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25],
64+
["John Doe", "[email protected]", 30, "Jane Doe", "[email protected]", 25]
6565
);
6666

6767
const result = await repository.count(
68-
and(gt("age", 25), like("name", "%Doe%")),
68+
and(gt("age", 25), like("name", "%Doe%"))
6969
);
7070

7171
expect(result).toBe(1);
@@ -74,7 +74,7 @@ describe("Repository count", () => {
7474
it("should handle errors during execution", async () => {
7575
// Try to count with an invalid column name
7676
await expect(
77-
repository.count(eq("invalid_column" as any, 1)),
77+
repository.count(eq("invalid_column" as any, 1))
7878
).rejects.toThrow();
7979
});
8080
});

__tests__/repository/delete.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import {
22
setupTestTables,
33
cleanupTestData,
44
executor,
5-
DomainUser,
6-
} from "../../test-setup";
5+
DomainUser
6+
} from "../test-setups/pg-test-setup";
77
import { Repository, SimpleWhere, CompositeWhere, eq } from "../../src";
88

99
describe("Repository - Delete", () => {
@@ -26,15 +26,15 @@ describe("Repository - Delete", () => {
2626
it("should delete all records when no where condition is provided", async () => {
2727
await executor.executeSQL(
2828
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3)`,
29-
["John Doe", "[email protected]", 30],
29+
["John Doe", "[email protected]", 30]
3030
);
3131

3232
await executor.executeSQL(
3333
`INSERT INTO users (name, email, age) VALUES ($1, $2, $3)`,
34-
["Jane Smith", "[email protected]", 25],
34+
["Jane Smith", "[email protected]", 25]
3535
);
3636

37-
expect(1).toBe(1)
37+
expect(1).toBe(1);
3838

3939
// const result = await repository.delete({ where: {} });
4040

__tests__/repository/find.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
DomainUser,
2121
executor,
2222
setupTestTables
23-
} from "../../test-setup";
23+
} from "../test-setups/pg-test-setup";
2424

2525
describe("Repository findRows", () => {
2626
let repository: Repository<DomainUser>;

__tests__/repository/insert.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
cleanupTestData,
44
executor,
55
DomainUser
6-
} from "../../test-setup";
6+
} from "../test-setups/pg-test-setup";
77
import { Repository } from "../../src";
88

99
describe("Repository - insert", () => {

0 commit comments

Comments
 (0)