@casekit/orm2 0.0.0-20250331181319 → 0.0.0
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/build/builders/buildCount.d.ts +2 -1
- package/build/builders/buildCount.js +5 -8
- package/build/builders/buildCount.test.js +5 -5
- package/build/builders/buildCreate.d.ts +2 -1
- package/build/builders/buildCreate.js +6 -3
- package/build/builders/buildCreate.test.js +4 -4
- package/build/builders/buildDelete.d.ts +2 -1
- package/build/builders/buildDelete.js +2 -2
- package/build/builders/buildDelete.test.js +8 -8
- package/build/builders/buildFind.d.ts +2 -1
- package/build/builders/buildFind.js +5 -8
- package/build/builders/buildFind.test.js +4 -4
- package/build/builders/buildUpdate.d.ts +2 -1
- package/build/builders/buildUpdate.js +6 -3
- package/build/builders/buildUpdate.test.js +8 -8
- package/build/builders/buildWhere.d.ts +2 -1
- package/build/builders/buildWhere.js +30 -8
- package/build/builders/buildWhere.test.js +39 -24
- package/build/connection.d.ts +2 -2
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/orm.count.d.ts +2 -10
- package/build/orm.count.js +2 -11
- package/build/orm.createMany.d.ts +2 -1
- package/build/orm.createMany.js +2 -2
- package/build/orm.createOne.d.ts +2 -1
- package/build/orm.createOne.js +2 -2
- package/build/orm.d.ts +2 -2
- package/build/orm.deleteMany.d.ts +2 -1
- package/build/orm.deleteMany.js +2 -2
- package/build/orm.deleteOne.d.ts +2 -1
- package/build/orm.deleteOne.js +2 -2
- package/build/orm.findMany.d.ts +2 -1
- package/build/orm.findMany.js +3 -3
- package/build/orm.findOne.d.ts +2 -1
- package/build/orm.findOne.js +11 -19
- package/build/orm.js +13 -13
- package/build/orm.restrict.d.ts +2 -1
- package/build/orm.restrict.js +2 -2
- package/build/orm.updateMany.d.ts +2 -1
- package/build/orm.updateMany.js +3 -3
- package/build/orm.updateOne.d.ts +2 -1
- package/build/orm.updateOne.js +2 -2
- package/build/tests/orm.findMany.includeManyToOne.test.js +21 -5
- package/build/tests/orm.findOne.includeManyToMany.test.js +270 -0
- package/build/tests/orm.findOne.includeManyToOne.test.js +280 -0
- package/build/tests/orm.findOne.includeOneToMany.test.js +454 -0
- package/build/tests/orm.findOne.select.test.js +205 -0
- package/build/tests/orm.findOne.where.test.js +471 -0
- package/build/tests/orm.middleware.findOne.test.d.ts +1 -0
- package/build/tests/orm.middleware.set.test.d.ts +1 -0
- package/build/tests/orm.middleware.set.test.js +100 -0
- package/build/tests/orm.middleware.updateMany.test.d.ts +1 -0
- package/build/tests/orm.middleware.updateOne.test.d.ts +1 -0
- package/build/tests/orm.middleware.values.test.d.ts +1 -0
- package/build/tests/orm.middleware.values.test.js +126 -0
- package/build/tests/orm.middleware.where.test.d.ts +1 -0
- package/build/tests/orm.middleware.where.test.js +1054 -0
- package/build/tests/util/db.d.ts +52 -70
- package/build/types/CreateOneResult.d.ts +6 -2
- package/build/types/CreateOneResult.test-d.js +3 -0
- package/build/types/Middleware.d.ts +14 -0
- package/build/types/Middleware.js +37 -1
- package/build/types/WhereClause.d.ts +8 -8
- package/build/util/applySetMiddleware.d.ts +5 -0
- package/build/util/applySetMiddleware.js +7 -0
- package/build/util/applyValuesMiddleware.d.ts +5 -0
- package/build/util/applyValuesMiddleware.js +7 -0
- package/build/util/applyWhereMiddleware.d.ts +5 -0
- package/build/util/applyWhereMiddleware.js +7 -0
- package/build/util/applyWhereMiddleware.test.d.ts +1 -0
- package/build/util/applyWhereMiddleware.test.js +88 -0
- package/build/util/resultSchema.d.ts +6 -6
- package/package.json +23 -24
- /package/build/tests/{orm.count.middleware.test.d.ts → orm.findOne.includeManyToMany.test.d.ts} +0 -0
- /package/build/tests/{orm.createMany.middleware.test.d.ts → orm.findOne.includeManyToOne.test.d.ts} +0 -0
- /package/build/tests/{orm.createOne.middleware.test.d.ts → orm.findOne.includeOneToMany.test.d.ts} +0 -0
- /package/build/tests/{orm.deleteMany.middleware.test.d.ts → orm.findOne.select.test.d.ts} +0 -0
- /package/build/tests/{orm.deleteOne.middleware.test.d.ts → orm.findOne.where.test.d.ts} +0 -0
- /package/build/tests/{orm.findMany.middleware.test.d.ts → orm.middleware.count.test.d.ts} +0 -0
- /package/build/tests/{orm.count.middleware.test.js → orm.middleware.count.test.js} +0 -0
- /package/build/tests/{orm.findOne.middleware.test.d.ts → orm.middleware.createMany.test.d.ts} +0 -0
- /package/build/tests/{orm.createMany.middleware.test.js → orm.middleware.createMany.test.js} +0 -0
- /package/build/tests/{orm.updateMany.middleware.test.d.ts → orm.middleware.createOne.test.d.ts} +0 -0
- /package/build/tests/{orm.createOne.middleware.test.js → orm.middleware.createOne.test.js} +0 -0
- /package/build/tests/{orm.updateOne.middleware.test.d.ts → orm.middleware.deleteMany.test.d.ts} +0 -0
- /package/build/tests/{orm.deleteMany.middleware.test.js → orm.middleware.deleteMany.test.js} +0 -0
- /package/build/{types/BaseFindParams.d.ts → tests/orm.middleware.deleteOne.test.d.ts} +0 -0
- /package/build/tests/{orm.deleteOne.middleware.test.js → orm.middleware.deleteOne.test.js} +0 -0
- /package/build/{types/BaseFindParams.js → tests/orm.middleware.findMany.test.d.ts} +0 -0
- /package/build/tests/{orm.findMany.middleware.test.js → orm.middleware.findMany.test.js} +0 -0
- /package/build/tests/{orm.findOne.middleware.test.js → orm.middleware.findOne.test.js} +0 -0
- /package/build/tests/{orm.updateMany.middleware.test.js → orm.middleware.updateMany.test.js} +0 -0
- /package/build/tests/{orm.updateOne.middleware.test.js → orm.middleware.updateOne.test.js} +0 -0
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
|
|
2
|
+
import { $and, $eq, $gt, $gte, $ilike, $in, $is, $like, $lt, $lte, $ne, $not, $or, } from "../operators.js";
|
|
3
|
+
import { createTestDB } from "./util/db.js";
|
|
4
|
+
describe("findOne: where", () => {
|
|
5
|
+
const { db, logger, factory } = createTestDB();
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
logger.clear();
|
|
8
|
+
});
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
await db.connect();
|
|
11
|
+
});
|
|
12
|
+
afterAll(async () => {
|
|
13
|
+
await db.close();
|
|
14
|
+
});
|
|
15
|
+
describe("basic operators", () => {
|
|
16
|
+
test("a value with no operator performs an equality check", async () => {
|
|
17
|
+
await db.transact(async (db) => {
|
|
18
|
+
await db.createMany("user", {
|
|
19
|
+
values: [
|
|
20
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
21
|
+
factory.user({ id: 2, name: "Bob" }),
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
const user = await db.findOne("user", {
|
|
25
|
+
select: ["id", "name"],
|
|
26
|
+
where: { name: "Alice" },
|
|
27
|
+
});
|
|
28
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
29
|
+
}, { rollback: true });
|
|
30
|
+
});
|
|
31
|
+
test("$eq operator matches exact values", async () => {
|
|
32
|
+
await db.transact(async (db) => {
|
|
33
|
+
await db.createMany("user", {
|
|
34
|
+
values: [
|
|
35
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
36
|
+
factory.user({ id: 2, name: "Bob" }),
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
const user = await db.findOne("user", {
|
|
40
|
+
select: ["id", "name"],
|
|
41
|
+
where: { name: { [$eq]: "Alice" } },
|
|
42
|
+
});
|
|
43
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
44
|
+
}, { rollback: true });
|
|
45
|
+
});
|
|
46
|
+
test("$ne operator excludes matching values", async () => {
|
|
47
|
+
await db.transact(async (db) => {
|
|
48
|
+
await db.createMany("user", {
|
|
49
|
+
values: [
|
|
50
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
51
|
+
factory.user({ id: 2, name: "Bob" }),
|
|
52
|
+
factory.user({ id: 3, name: "Charlie" }),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
const user = await db.findOne("user", {
|
|
56
|
+
select: ["id", "name"],
|
|
57
|
+
where: {
|
|
58
|
+
[$and]: [
|
|
59
|
+
{ name: { [$ne]: "Alice" } },
|
|
60
|
+
{ name: { [$ne]: "Charlie" } },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
expect(user).toEqual({ id: 2, name: "Bob" });
|
|
65
|
+
}, { rollback: true });
|
|
66
|
+
});
|
|
67
|
+
test("$gt operator compares values correctly", async () => {
|
|
68
|
+
await db.transact(async (db) => {
|
|
69
|
+
await db.createMany("user", {
|
|
70
|
+
values: [
|
|
71
|
+
factory.user({ id: 1 }),
|
|
72
|
+
factory.user({ id: 2 }),
|
|
73
|
+
factory.user({ id: 3 }),
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
const user = await db.findOne("user", {
|
|
77
|
+
select: ["id"],
|
|
78
|
+
where: {
|
|
79
|
+
id: { [$gt]: 1, [$lt]: 3 },
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
expect(user).toEqual({ id: 2 });
|
|
83
|
+
}, { rollback: true });
|
|
84
|
+
});
|
|
85
|
+
test("$gte operator compares values correctly", async () => {
|
|
86
|
+
await db.transact(async (db) => {
|
|
87
|
+
await db.createMany("user", {
|
|
88
|
+
values: [
|
|
89
|
+
factory.user({ id: 1 }),
|
|
90
|
+
factory.user({ id: 2 }),
|
|
91
|
+
factory.user({ id: 3 }),
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
const user = await db.findOne("user", {
|
|
95
|
+
select: ["id"],
|
|
96
|
+
where: {
|
|
97
|
+
id: { [$gte]: 2, [$lt]: 3 },
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
expect(user).toEqual({ id: 2 });
|
|
101
|
+
}, { rollback: true });
|
|
102
|
+
});
|
|
103
|
+
test("$lt operator compares values correctly", async () => {
|
|
104
|
+
await db.transact(async (db) => {
|
|
105
|
+
await db.createMany("user", {
|
|
106
|
+
values: [
|
|
107
|
+
factory.user({ id: 1 }),
|
|
108
|
+
factory.user({ id: 2 }),
|
|
109
|
+
factory.user({ id: 3 }),
|
|
110
|
+
],
|
|
111
|
+
});
|
|
112
|
+
const user = await db.findOne("user", {
|
|
113
|
+
select: ["id"],
|
|
114
|
+
where: {
|
|
115
|
+
id: { [$lt]: 2 },
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
expect(user).toEqual({ id: 1 });
|
|
119
|
+
}, { rollback: true });
|
|
120
|
+
});
|
|
121
|
+
test("$lte operator compares values correctly", async () => {
|
|
122
|
+
await db.transact(async (db) => {
|
|
123
|
+
await db.createMany("user", {
|
|
124
|
+
values: [
|
|
125
|
+
factory.user({ id: 1, role: "user" }),
|
|
126
|
+
factory.user({ id: 2, role: "admin" }),
|
|
127
|
+
factory.user({ id: 3 }),
|
|
128
|
+
],
|
|
129
|
+
});
|
|
130
|
+
const user = await db.findOne("user", {
|
|
131
|
+
select: ["id"],
|
|
132
|
+
where: {
|
|
133
|
+
id: { [$lte]: 2 },
|
|
134
|
+
role: "admin",
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
expect(user).toEqual({ id: 2 });
|
|
138
|
+
}, { rollback: true });
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe("array operators", () => {
|
|
142
|
+
test("$in operator matches array of values", async () => {
|
|
143
|
+
await db.transact(async (db) => {
|
|
144
|
+
await db.createMany("user", {
|
|
145
|
+
values: [
|
|
146
|
+
factory.user({
|
|
147
|
+
id: 1,
|
|
148
|
+
name: "Alice",
|
|
149
|
+
role: "admin",
|
|
150
|
+
}),
|
|
151
|
+
factory.user({ id: 2, name: "Bob", role: "user" }),
|
|
152
|
+
factory.user({
|
|
153
|
+
id: 3,
|
|
154
|
+
name: "Charlie",
|
|
155
|
+
role: "admin",
|
|
156
|
+
}),
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
// Only Alice is in the name array and has the admin role
|
|
160
|
+
const user = await db.findOne("user", {
|
|
161
|
+
select: ["id", "name"],
|
|
162
|
+
where: {
|
|
163
|
+
name: { [$in]: ["Alice", "David"] },
|
|
164
|
+
role: "admin",
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
168
|
+
}, { rollback: true });
|
|
169
|
+
});
|
|
170
|
+
test("$in operator with matching single value returns a result", async () => {
|
|
171
|
+
await db.transact(async (db) => {
|
|
172
|
+
await db.createMany("user", {
|
|
173
|
+
values: [
|
|
174
|
+
factory.user({ id: 1 }),
|
|
175
|
+
factory.user({ id: 2 }),
|
|
176
|
+
],
|
|
177
|
+
});
|
|
178
|
+
const user = await db.findOne("user", {
|
|
179
|
+
select: ["id"],
|
|
180
|
+
where: { id: { [$in]: [1] } },
|
|
181
|
+
});
|
|
182
|
+
expect(user).toEqual({ id: 1 });
|
|
183
|
+
}, { rollback: true });
|
|
184
|
+
});
|
|
185
|
+
test("$in operator with empty array throws 'expected one row but found none'", async () => {
|
|
186
|
+
await db.transact(async (db) => {
|
|
187
|
+
await db.createMany("user", {
|
|
188
|
+
values: [
|
|
189
|
+
factory.user({ id: 1 }),
|
|
190
|
+
factory.user({ id: 2 }),
|
|
191
|
+
],
|
|
192
|
+
});
|
|
193
|
+
await expect(db.findOne("user", {
|
|
194
|
+
select: ["id"],
|
|
195
|
+
where: { id: { [$in]: [] } },
|
|
196
|
+
})).rejects.toThrow("Expected one row, but found none");
|
|
197
|
+
}, { rollback: true });
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe("string matching operators", () => {
|
|
201
|
+
test("$like operator matches pattern", async () => {
|
|
202
|
+
await db.transact(async (db) => {
|
|
203
|
+
await db.createMany("user", {
|
|
204
|
+
values: [
|
|
205
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
206
|
+
factory.user({ id: 2, name: "alex" }),
|
|
207
|
+
factory.user({ id: 3, name: "Bob" }),
|
|
208
|
+
],
|
|
209
|
+
});
|
|
210
|
+
const user = await db.findOne("user", {
|
|
211
|
+
select: ["id", "name"],
|
|
212
|
+
where: { name: { [$like]: "A%" } },
|
|
213
|
+
});
|
|
214
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
215
|
+
}, { rollback: true });
|
|
216
|
+
});
|
|
217
|
+
test("$ilike operator with specific pattern ensures single result", async () => {
|
|
218
|
+
await db.transact(async (db) => {
|
|
219
|
+
await db.createMany("user", {
|
|
220
|
+
values: [
|
|
221
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
222
|
+
factory.user({ id: 2, name: "alex" }),
|
|
223
|
+
factory.user({ id: 3, name: "Bob" }),
|
|
224
|
+
],
|
|
225
|
+
});
|
|
226
|
+
const user = await db.findOne("user", {
|
|
227
|
+
select: ["id", "name"],
|
|
228
|
+
where: { name: { [$ilike]: "al_ce" } },
|
|
229
|
+
});
|
|
230
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
231
|
+
}, { rollback: true });
|
|
232
|
+
});
|
|
233
|
+
test("$ilike operator with ambiguous pattern throws 'expected one row but found more'", async () => {
|
|
234
|
+
await db.transact(async (db) => {
|
|
235
|
+
await db.createMany("user", {
|
|
236
|
+
values: [
|
|
237
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
238
|
+
factory.user({ id: 2, name: "alex" }),
|
|
239
|
+
factory.user({ id: 3, name: "Bob" }),
|
|
240
|
+
],
|
|
241
|
+
});
|
|
242
|
+
await expect(db.findOne("user", {
|
|
243
|
+
select: ["id", "name"],
|
|
244
|
+
where: { name: { [$ilike]: "a%" } },
|
|
245
|
+
})).rejects.toThrow("Expected one row, but found more");
|
|
246
|
+
}, { rollback: true });
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
describe("null handling operators", () => {
|
|
250
|
+
test("null as a value performs an IS NULL check", async () => {
|
|
251
|
+
await db.transact(async (db) => {
|
|
252
|
+
await db.createMany("user", {
|
|
253
|
+
values: [
|
|
254
|
+
factory.user({ id: 1, deletedAt: new Date() }),
|
|
255
|
+
factory.user({ id: 2, deletedAt: null }),
|
|
256
|
+
],
|
|
257
|
+
});
|
|
258
|
+
const user = await db.findOne("user", {
|
|
259
|
+
select: ["id"],
|
|
260
|
+
where: { deletedAt: null },
|
|
261
|
+
});
|
|
262
|
+
expect(user).toEqual({ id: 2 });
|
|
263
|
+
}, { rollback: true });
|
|
264
|
+
});
|
|
265
|
+
test("$is operator handles null values", async () => {
|
|
266
|
+
await db.transact(async (db) => {
|
|
267
|
+
await db.createMany("user", {
|
|
268
|
+
values: [
|
|
269
|
+
factory.user({ id: 1, deletedAt: new Date() }),
|
|
270
|
+
factory.user({ id: 2, deletedAt: null }),
|
|
271
|
+
],
|
|
272
|
+
});
|
|
273
|
+
const user = await db.findOne("user", {
|
|
274
|
+
select: ["id"],
|
|
275
|
+
where: { deletedAt: { [$is]: null } },
|
|
276
|
+
});
|
|
277
|
+
expect(user).toEqual({ id: 2 });
|
|
278
|
+
}, { rollback: true });
|
|
279
|
+
});
|
|
280
|
+
test("$not operator with null finds non-null value", async () => {
|
|
281
|
+
await db.transact(async (db) => {
|
|
282
|
+
await db.createMany("user", {
|
|
283
|
+
values: [
|
|
284
|
+
factory.user({ id: 1, deletedAt: new Date() }),
|
|
285
|
+
factory.user({ id: 2, deletedAt: null }),
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
const user = await db.findOne("user", {
|
|
289
|
+
select: ["id"],
|
|
290
|
+
where: { deletedAt: { [$not]: null } },
|
|
291
|
+
});
|
|
292
|
+
expect(user).toEqual({ id: 1 });
|
|
293
|
+
}, { rollback: true });
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
describe("logical operators", () => {
|
|
297
|
+
test("$and operator combines conditions", async () => {
|
|
298
|
+
await db.transact(async (db) => {
|
|
299
|
+
await db.createMany("user", {
|
|
300
|
+
values: [
|
|
301
|
+
factory.user({
|
|
302
|
+
id: 1,
|
|
303
|
+
name: "Alice",
|
|
304
|
+
role: "admin",
|
|
305
|
+
}),
|
|
306
|
+
factory.user({ id: 2, name: "Bob", role: "user" }),
|
|
307
|
+
factory.user({
|
|
308
|
+
id: 3,
|
|
309
|
+
name: "Charlie",
|
|
310
|
+
role: "admin",
|
|
311
|
+
}),
|
|
312
|
+
],
|
|
313
|
+
});
|
|
314
|
+
const user = await db.findOne("user", {
|
|
315
|
+
select: ["id", "name"],
|
|
316
|
+
where: {
|
|
317
|
+
[$and]: [
|
|
318
|
+
{ role: "admin" },
|
|
319
|
+
{ name: { [$like]: "A%" } },
|
|
320
|
+
],
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
324
|
+
}, { rollback: true });
|
|
325
|
+
});
|
|
326
|
+
test("$or operator with specific condition ensures single result", async () => {
|
|
327
|
+
await db.transact(async (db) => {
|
|
328
|
+
await db.createMany("user", {
|
|
329
|
+
values: [
|
|
330
|
+
factory.user({
|
|
331
|
+
id: 1,
|
|
332
|
+
name: "Alice",
|
|
333
|
+
email: "alice@example.com",
|
|
334
|
+
role: "admin",
|
|
335
|
+
}),
|
|
336
|
+
factory.user({
|
|
337
|
+
id: 2,
|
|
338
|
+
name: "Bob",
|
|
339
|
+
email: "bob@example.com",
|
|
340
|
+
role: "user",
|
|
341
|
+
}),
|
|
342
|
+
factory.user({
|
|
343
|
+
id: 3,
|
|
344
|
+
name: "Charlie",
|
|
345
|
+
email: "charlie@example.com",
|
|
346
|
+
role: "user",
|
|
347
|
+
}),
|
|
348
|
+
],
|
|
349
|
+
});
|
|
350
|
+
// Only Alice matches this unique combination of criteria
|
|
351
|
+
const user = await db.findOne("user", {
|
|
352
|
+
select: ["id", "name"],
|
|
353
|
+
where: {
|
|
354
|
+
[$or]: [
|
|
355
|
+
// This combination only matches Alice
|
|
356
|
+
{ name: "Alice", role: "admin" },
|
|
357
|
+
// This combination doesn't match any user
|
|
358
|
+
{
|
|
359
|
+
name: "David",
|
|
360
|
+
email: "nonexistent@example.com",
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
366
|
+
}, { rollback: true });
|
|
367
|
+
});
|
|
368
|
+
test("can combine $and and $or operators to find unique record", async () => {
|
|
369
|
+
await db.transact(async (db) => {
|
|
370
|
+
await db.createMany("user", {
|
|
371
|
+
values: [
|
|
372
|
+
factory.user({
|
|
373
|
+
id: 1,
|
|
374
|
+
name: "Alice",
|
|
375
|
+
role: "admin",
|
|
376
|
+
email: "alice@example.com",
|
|
377
|
+
}),
|
|
378
|
+
factory.user({
|
|
379
|
+
id: 2,
|
|
380
|
+
name: "Bob",
|
|
381
|
+
role: "user",
|
|
382
|
+
email: "bob@example.com",
|
|
383
|
+
}),
|
|
384
|
+
factory.user({
|
|
385
|
+
id: 3,
|
|
386
|
+
name: "Charlie",
|
|
387
|
+
role: "admin",
|
|
388
|
+
email: "charlie@example.com",
|
|
389
|
+
}),
|
|
390
|
+
factory.user({
|
|
391
|
+
id: 4,
|
|
392
|
+
name: "Charlie",
|
|
393
|
+
role: "user",
|
|
394
|
+
email: "charlie2@example.com",
|
|
395
|
+
}),
|
|
396
|
+
factory.user({
|
|
397
|
+
id: 5,
|
|
398
|
+
name: "David",
|
|
399
|
+
role: "admin",
|
|
400
|
+
email: "david@example.com",
|
|
401
|
+
}),
|
|
402
|
+
],
|
|
403
|
+
});
|
|
404
|
+
// This combination of conditions should only match Alice
|
|
405
|
+
const user = await db.findOne("user", {
|
|
406
|
+
select: ["id", "name"],
|
|
407
|
+
where: {
|
|
408
|
+
[$and]: [
|
|
409
|
+
{ role: "admin" },
|
|
410
|
+
{
|
|
411
|
+
[$or]: [
|
|
412
|
+
{ name: "Alice" },
|
|
413
|
+
{
|
|
414
|
+
name: "David",
|
|
415
|
+
email: "not-david@example.com",
|
|
416
|
+
}, // Won't match
|
|
417
|
+
],
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
expect(user).toEqual({ id: 1, name: "Alice" });
|
|
423
|
+
}, { rollback: true });
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
describe("error cases", () => {
|
|
427
|
+
test("$in operator throws error with non-array value", async () => {
|
|
428
|
+
await db.transact(async (db) => {
|
|
429
|
+
await expect(db.findOne("user", {
|
|
430
|
+
select: ["id"],
|
|
431
|
+
// @ts-expect-error testing invalid value
|
|
432
|
+
where: { id: { [$in]: "not-an-array" } },
|
|
433
|
+
})).rejects.toThrow("Non-array passed to IN clause");
|
|
434
|
+
}, { rollback: true });
|
|
435
|
+
});
|
|
436
|
+
test("$not operator throws error with invalid value", async () => {
|
|
437
|
+
await db.transact(async (db) => {
|
|
438
|
+
await expect(db.findOne("user", {
|
|
439
|
+
select: ["id"],
|
|
440
|
+
// @ts-expect-error testing invalid value
|
|
441
|
+
where: { id: { [$not]: "invalid" } },
|
|
442
|
+
})).rejects.toThrow("Invalid value passed to $not operator");
|
|
443
|
+
}, { rollback: true });
|
|
444
|
+
});
|
|
445
|
+
test("throws error when no records match criteria", async () => {
|
|
446
|
+
await db.transact(async (db) => {
|
|
447
|
+
await db.createMany("user", {
|
|
448
|
+
values: [factory.user({ id: 1, name: "Alice" })],
|
|
449
|
+
});
|
|
450
|
+
await expect(db.findOne("user", {
|
|
451
|
+
select: ["id"],
|
|
452
|
+
where: { id: 999 },
|
|
453
|
+
})).rejects.toThrow("Expected one row, but found none");
|
|
454
|
+
}, { rollback: true });
|
|
455
|
+
});
|
|
456
|
+
test("throws error when multiple records match criteria", async () => {
|
|
457
|
+
await db.transact(async (db) => {
|
|
458
|
+
await db.createMany("user", {
|
|
459
|
+
values: [
|
|
460
|
+
factory.user({ id: 1, name: "Alice" }),
|
|
461
|
+
factory.user({ id: 2, name: "Alice" }),
|
|
462
|
+
],
|
|
463
|
+
});
|
|
464
|
+
await expect(db.findOne("user", {
|
|
465
|
+
select: ["id"],
|
|
466
|
+
where: { name: "Alice" },
|
|
467
|
+
})).rejects.toThrow("Expected one row, but found more");
|
|
468
|
+
}, { rollback: true });
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
|
|
2
|
+
import { config } from "@casekit/orm2-fixtures";
|
|
3
|
+
import { $ilike } from "../operators.js";
|
|
4
|
+
import { orm } from "../orm.js";
|
|
5
|
+
import { mockLogger } from "./util/logger.js";
|
|
6
|
+
const uppercasename = () => ({
|
|
7
|
+
set: (_config, _modelName, set) => {
|
|
8
|
+
if ("name" in set && typeof set["name"] === "string") {
|
|
9
|
+
return { ...set, name: set["name"].toUpperCase() };
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return set;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
const addprefixtoname = () => ({
|
|
17
|
+
set: (_config, _modelName, set) => {
|
|
18
|
+
if ("name" in set && typeof set["name"] === "string") {
|
|
19
|
+
return { ...set, name: `prefix_${set["name"]}` };
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return set;
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
describe("set middleware", () => {
|
|
27
|
+
const logger = mockLogger();
|
|
28
|
+
let db;
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
logger.clear();
|
|
31
|
+
});
|
|
32
|
+
beforeAll(async () => {
|
|
33
|
+
db = orm({ ...config, logger }).middleware([
|
|
34
|
+
uppercasename(),
|
|
35
|
+
addprefixtoname(),
|
|
36
|
+
]);
|
|
37
|
+
await db.connect();
|
|
38
|
+
});
|
|
39
|
+
afterAll(async () => {
|
|
40
|
+
await db.close();
|
|
41
|
+
});
|
|
42
|
+
test("set in updateOne", async () => {
|
|
43
|
+
await db.transact(async (db) => {
|
|
44
|
+
const user = await db.createOne("user", {
|
|
45
|
+
values: {
|
|
46
|
+
id: 1,
|
|
47
|
+
name: "Test User",
|
|
48
|
+
email: "test@example.com",
|
|
49
|
+
role: "user",
|
|
50
|
+
},
|
|
51
|
+
returning: ["id", "name"],
|
|
52
|
+
});
|
|
53
|
+
const updatedUser = await db.updateOne("user", {
|
|
54
|
+
set: {
|
|
55
|
+
name: "russell",
|
|
56
|
+
email: "russell@example.com",
|
|
57
|
+
},
|
|
58
|
+
where: { id: user.id },
|
|
59
|
+
returning: ["id", "name", "email"],
|
|
60
|
+
});
|
|
61
|
+
expect(updatedUser).toEqual({
|
|
62
|
+
id: user.id,
|
|
63
|
+
name: "prefix_RUSSELL",
|
|
64
|
+
email: "russell@example.com",
|
|
65
|
+
});
|
|
66
|
+
}, { rollback: true });
|
|
67
|
+
});
|
|
68
|
+
test("set in updateMany", async () => {
|
|
69
|
+
await db.transact(async (db) => {
|
|
70
|
+
await db.createMany("user", {
|
|
71
|
+
values: [
|
|
72
|
+
{
|
|
73
|
+
id: 1,
|
|
74
|
+
name: "Test User 1",
|
|
75
|
+
email: "test1@example.com",
|
|
76
|
+
role: "user",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: 2,
|
|
80
|
+
name: "Test User 2",
|
|
81
|
+
email: "test2@example.com",
|
|
82
|
+
role: "user",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
returning: ["id", "name"],
|
|
86
|
+
});
|
|
87
|
+
const updatedUsers = await db.updateMany("user", {
|
|
88
|
+
set: {
|
|
89
|
+
name: "russell",
|
|
90
|
+
},
|
|
91
|
+
where: { email: { [$ilike]: "%example.com" } },
|
|
92
|
+
returning: ["id", "name", "email"],
|
|
93
|
+
});
|
|
94
|
+
expect(updatedUsers.map((u) => u.name)).toEqual([
|
|
95
|
+
"prefix_RUSSELL",
|
|
96
|
+
"prefix_RUSSELL",
|
|
97
|
+
]);
|
|
98
|
+
}, { rollback: true });
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|