@apisr/drizzle-model 0.0.4 → 2.0.1
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/CHANGELOG.md +22 -0
- package/DISCLAIMER.md +5 -0
- package/README.md +433 -0
- package/TODO.md +8 -61
- package/package.json +5 -3
- package/src/core/dialect.ts +81 -0
- package/src/core/index.ts +24 -0
- package/src/core/query/error.ts +15 -0
- package/src/core/query/joins.ts +663 -0
- package/src/core/query/projection.ts +136 -0
- package/src/core/query/where.ts +449 -0
- package/src/core/result.ts +303 -0
- package/src/core/runtime.ts +636 -0
- package/src/core/transform.ts +119 -0
- package/src/model/builder.ts +40 -6
- package/src/model/config.ts +9 -9
- package/src/model/format.ts +20 -8
- package/src/model/methods/exclude.ts +1 -7
- package/src/model/methods/return.ts +11 -11
- package/src/model/methods/select.ts +2 -8
- package/src/model/model.ts +10 -16
- package/src/model/query/error.ts +1 -0
- package/src/model/result.ts +137 -21
- package/src/types.ts +38 -0
- package/tests/base/count.test.ts +47 -0
- package/tests/base/delete.test.ts +90 -0
- package/tests/base/find.test.ts +209 -0
- package/tests/base/insert.test.ts +152 -0
- package/tests/base/relations.test.ts +593 -0
- package/tests/base/safe.test.ts +91 -0
- package/tests/base/update.test.ts +88 -0
- package/tests/base/upsert.test.ts +121 -0
- package/tests/base.ts +21 -0
- package/src/model/core/joins.ts +0 -364
- package/src/model/core/projection.ts +0 -61
- package/src/model/core/runtime.ts +0 -334
- package/src/model/core/thenable.ts +0 -94
- package/src/model/core/transform.ts +0 -65
- package/src/model/core/where.ts +0 -249
- package/src/model/core/with.ts +0 -28
- package/tests/builder-v2-mysql.type-test.ts +0 -51
- package/tests/builder-v2.type-test.ts +0 -336
- package/tests/builder.test.ts +0 -63
- package/tests/find.test.ts +0 -166
- package/tests/insert.test.ts +0 -247
package/tests/find.test.ts
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { and, eq, gte, like, or } from "drizzle-orm";
|
|
3
|
-
import { esc } from "@/model/query/operations";
|
|
4
|
-
import { modelBuilder } from "../src";
|
|
5
|
-
import { db } from "./db";
|
|
6
|
-
import { relations } from "./relations";
|
|
7
|
-
import * as schema from "./schema";
|
|
8
|
-
|
|
9
|
-
const model = modelBuilder({
|
|
10
|
-
schema,
|
|
11
|
-
db,
|
|
12
|
-
relations,
|
|
13
|
-
dialect: "PostgreSQL",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const userModel = model("user", {});
|
|
17
|
-
|
|
18
|
-
async function rawUsers(where?: any) {
|
|
19
|
-
if (where) {
|
|
20
|
-
return await db.select().from(schema.user).where(where);
|
|
21
|
-
}
|
|
22
|
-
return await db.select().from(schema.user);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function sortById<T extends { id: number }>(rows: T[]) {
|
|
26
|
-
return [...rows].sort((a, b) => a.id - b.id);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
describe("Model Find Test", () => {
|
|
30
|
-
test(".find | one filter", async () => {
|
|
31
|
-
// Eq to:
|
|
32
|
-
// await db.select().from(userTable).where(eq(userTable.name, "Alex"));
|
|
33
|
-
const raw = await userModel.where({ name: esc("Alex") }).findMany();
|
|
34
|
-
|
|
35
|
-
const expected = await rawUsers(eq(schema.user.name, "Alex"));
|
|
36
|
-
|
|
37
|
-
console.dir(raw, {
|
|
38
|
-
depth: null,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
expect(raw).toBeArray();
|
|
42
|
-
expect(raw[0]).toBeDefined();
|
|
43
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test(".find | no filters returns all users", async () => {
|
|
47
|
-
const raw = await userModel.findMany();
|
|
48
|
-
|
|
49
|
-
const expected = await rawUsers();
|
|
50
|
-
|
|
51
|
-
expect(raw).toBeArray();
|
|
52
|
-
expect(raw).toHaveLength((expected as any[]).length);
|
|
53
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
test(".find | multiple filters", async () => {
|
|
57
|
-
const raw = await userModel
|
|
58
|
-
.where({
|
|
59
|
-
name: esc("Alex"),
|
|
60
|
-
isVerified: esc(false),
|
|
61
|
-
age: esc(12),
|
|
62
|
-
})
|
|
63
|
-
.findMany();
|
|
64
|
-
|
|
65
|
-
const expected = await rawUsers(
|
|
66
|
-
and(
|
|
67
|
-
eq(schema.user.name, "Alex"),
|
|
68
|
-
eq(schema.user.isVerified, false),
|
|
69
|
-
eq(schema.user.age, 12)
|
|
70
|
-
)
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
console.dir(raw, {
|
|
74
|
-
depth: null,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
expect(raw).toBeArray();
|
|
78
|
-
expect(raw[0]).toBeDefined();
|
|
79
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test(".find | complex filters 01", async () => {
|
|
83
|
-
const raw = await userModel
|
|
84
|
-
.where({
|
|
85
|
-
name: {
|
|
86
|
-
or: [esc("Alex"), esc("Dino")],
|
|
87
|
-
},
|
|
88
|
-
})
|
|
89
|
-
.findMany();
|
|
90
|
-
|
|
91
|
-
const expected = await rawUsers(
|
|
92
|
-
or(eq(schema.user.name, "Alex"), eq(schema.user.name, "Dino"))
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
console.dir(raw, {
|
|
96
|
-
depth: null,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
expect(raw).toBeArray();
|
|
100
|
-
expect(raw[0]).toBeDefined();
|
|
101
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test(".find | complex filters 02", async () => {
|
|
105
|
-
const raw = await userModel
|
|
106
|
-
.where({
|
|
107
|
-
name: {
|
|
108
|
-
or: [esc("Alex"), esc("Dino"), esc("Anna")],
|
|
109
|
-
},
|
|
110
|
-
age: {
|
|
111
|
-
gte: esc(18),
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
|
-
.findMany();
|
|
115
|
-
|
|
116
|
-
const expected = await rawUsers(
|
|
117
|
-
and(
|
|
118
|
-
or(
|
|
119
|
-
eq(schema.user.name, "Alex"),
|
|
120
|
-
eq(schema.user.name, "Dino"),
|
|
121
|
-
eq(schema.user.name, "Anna")
|
|
122
|
-
),
|
|
123
|
-
gte(schema.user.age, 18)
|
|
124
|
-
)
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
console.dir(raw, {
|
|
128
|
-
depth: null,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
expect(raw).toBeArray();
|
|
132
|
-
expect(raw[0]).toBeDefined();
|
|
133
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test(".find | complex filters 03", async () => {
|
|
137
|
-
const raw = await userModel
|
|
138
|
-
.where({
|
|
139
|
-
name: {
|
|
140
|
-
like: esc("A%"),
|
|
141
|
-
},
|
|
142
|
-
})
|
|
143
|
-
.findMany();
|
|
144
|
-
|
|
145
|
-
const expected = await rawUsers(like(schema.user.name, "A%"));
|
|
146
|
-
|
|
147
|
-
console.dir(raw, {
|
|
148
|
-
depth: null,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
expect(raw).toBeArray();
|
|
152
|
-
expect(raw[0]).toBeDefined();
|
|
153
|
-
expect(sortById(raw as any)).toEqual(sortById(expected as any));
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
test(".findOne | returns a single matching user", async () => {
|
|
157
|
-
const anna = await userModel.where({ name: esc("Anna") }).findFirst();
|
|
158
|
-
|
|
159
|
-
const expected = (await rawUsers(eq(schema.user.name, "Anna")))[0];
|
|
160
|
-
|
|
161
|
-
expect(anna).toBeDefined();
|
|
162
|
-
expect((anna as any).id).toBe(5);
|
|
163
|
-
expect(anna?.email).toBe("an.na@example.com");
|
|
164
|
-
expect(anna as any).toEqual(expected as any);
|
|
165
|
-
});
|
|
166
|
-
});
|
package/tests/insert.test.ts
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { eq, inArray } from "drizzle-orm";
|
|
3
|
-
import { esc } from "@/model/query/operations";
|
|
4
|
-
import { modelBuilder } from "../src";
|
|
5
|
-
import { db } from "./db";
|
|
6
|
-
import { relations } from "./relations";
|
|
7
|
-
import * as schema from "./schema";
|
|
8
|
-
|
|
9
|
-
const model = modelBuilder({
|
|
10
|
-
schema,
|
|
11
|
-
db,
|
|
12
|
-
relations,
|
|
13
|
-
dialect: "PostgreSQL",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const postsModel = model("userPosts", {});
|
|
17
|
-
const userModel = model("user", {});
|
|
18
|
-
|
|
19
|
-
function sortById<T extends { id: number }>(rows: T[]) {
|
|
20
|
-
return [...rows].sort((a, b) => a.id - b.id);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
describe("Model Update/Delete/Upsert Test", () => {
|
|
24
|
-
test(".update | updates a single post", async () => {
|
|
25
|
-
const [seed] = (await postsModel
|
|
26
|
-
.insert({
|
|
27
|
-
title: "Update seed",
|
|
28
|
-
featured: false,
|
|
29
|
-
userId: 1,
|
|
30
|
-
})
|
|
31
|
-
.return()) as any[];
|
|
32
|
-
|
|
33
|
-
const updated = await postsModel
|
|
34
|
-
.where({ id: esc(seed.id) })
|
|
35
|
-
.update({
|
|
36
|
-
title: "Updated title",
|
|
37
|
-
featured: true,
|
|
38
|
-
})
|
|
39
|
-
.return();
|
|
40
|
-
|
|
41
|
-
const expected = await db
|
|
42
|
-
.select()
|
|
43
|
-
.from(schema.userPosts)
|
|
44
|
-
.where(eq(schema.userPosts.id, seed.id));
|
|
45
|
-
|
|
46
|
-
expect(updated).toBeArray();
|
|
47
|
-
expect((updated as any[])[0].id).toBe(seed.id);
|
|
48
|
-
expect((updated as any[])[0].title).toBe("Updated title");
|
|
49
|
-
expect((updated as any[])[0].featured).toBe(true);
|
|
50
|
-
expect((updated as any[])[0]).toEqual((expected as any[])[0]);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test(".delete | deletes a single post", async () => {
|
|
54
|
-
const [seed] = (await postsModel
|
|
55
|
-
.insert({
|
|
56
|
-
title: "Delete seed",
|
|
57
|
-
featured: null,
|
|
58
|
-
userId: 1,
|
|
59
|
-
})
|
|
60
|
-
.return()) as any[];
|
|
61
|
-
|
|
62
|
-
const deleted = await postsModel
|
|
63
|
-
.where({ id: esc(seed.id) })
|
|
64
|
-
.delete()
|
|
65
|
-
.return();
|
|
66
|
-
|
|
67
|
-
const expectedDeleted = await db
|
|
68
|
-
.select()
|
|
69
|
-
.from(schema.userPosts)
|
|
70
|
-
.where(eq(schema.userPosts.id, seed.id));
|
|
71
|
-
|
|
72
|
-
expect(deleted).toBeArray();
|
|
73
|
-
expect((deleted as any[])[0].id).toBe(seed.id);
|
|
74
|
-
expect(expectedDeleted).toHaveLength(0);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test(".upsert | inserts then updates by unique email", async () => {
|
|
78
|
-
const uniq = `${Date.now()}-${Math.random()}`;
|
|
79
|
-
const email = `upsert-${uniq}@example.com`;
|
|
80
|
-
|
|
81
|
-
const [created] = (await userModel
|
|
82
|
-
.upsert({
|
|
83
|
-
insert: {
|
|
84
|
-
name: "Upsert user",
|
|
85
|
-
email,
|
|
86
|
-
age: 10,
|
|
87
|
-
isVerified: false,
|
|
88
|
-
},
|
|
89
|
-
update: {
|
|
90
|
-
name: "Upsert user updated",
|
|
91
|
-
},
|
|
92
|
-
target: schema.user.email as any,
|
|
93
|
-
})
|
|
94
|
-
.return()) as any[];
|
|
95
|
-
|
|
96
|
-
const [updated] = (await userModel
|
|
97
|
-
.upsert({
|
|
98
|
-
insert: {
|
|
99
|
-
name: "Upsert user (ignored)",
|
|
100
|
-
email,
|
|
101
|
-
age: 10,
|
|
102
|
-
isVerified: false,
|
|
103
|
-
},
|
|
104
|
-
update: {
|
|
105
|
-
name: "Upsert user updated",
|
|
106
|
-
},
|
|
107
|
-
target: schema.user.email as any,
|
|
108
|
-
})
|
|
109
|
-
.return()) as any[];
|
|
110
|
-
|
|
111
|
-
const expected = await db
|
|
112
|
-
.select()
|
|
113
|
-
.from(schema.user)
|
|
114
|
-
.where(eq(schema.user.email, email));
|
|
115
|
-
|
|
116
|
-
expect(created).toBeDefined();
|
|
117
|
-
expect(updated).toBeDefined();
|
|
118
|
-
expect(updated.id).toBe(created.id);
|
|
119
|
-
expect(updated.name).toBe("Upsert user updated");
|
|
120
|
-
expect(updated).toEqual((expected as any[])[0]);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Returns new model
|
|
125
|
-
// postsModel.extend({
|
|
126
|
-
// query: {
|
|
127
|
-
// userId: 123,
|
|
128
|
-
// },
|
|
129
|
-
// });
|
|
130
|
-
|
|
131
|
-
// const userModel = model({
|
|
132
|
-
// table: userTable,
|
|
133
|
-
// db,
|
|
134
|
-
// });
|
|
135
|
-
|
|
136
|
-
describe("Model Insert Test", () => {
|
|
137
|
-
test(".insert | one entry", async () => {
|
|
138
|
-
const inserted: any = await postsModel
|
|
139
|
-
.insert({
|
|
140
|
-
title: "Hello world!",
|
|
141
|
-
featured: true,
|
|
142
|
-
userId: 1,
|
|
143
|
-
})
|
|
144
|
-
.return();
|
|
145
|
-
|
|
146
|
-
const expected = await db
|
|
147
|
-
.select()
|
|
148
|
-
.from(schema.userPosts)
|
|
149
|
-
.where(eq(schema.userPosts.id, (inserted as any[])[0].id));
|
|
150
|
-
|
|
151
|
-
console.dir(inserted, {
|
|
152
|
-
depth: null,
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
expect(inserted).toBeDefined();
|
|
156
|
-
expect(Array.isArray(inserted)).toBe(true);
|
|
157
|
-
expect((inserted as any[])[0]).toBeDefined();
|
|
158
|
-
expect((inserted as any[])[0].title).toBe("Hello world!");
|
|
159
|
-
expect((inserted as any[])[0].featured).toBe(true);
|
|
160
|
-
expect((inserted as any[])[0].userId).toBe(1);
|
|
161
|
-
expect((inserted as any[])[0].likes).toBe(0);
|
|
162
|
-
expect((inserted as any[])[0].views).toBe(0);
|
|
163
|
-
expect((inserted as any[])[0]).toEqual((expected as any[])[0]);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test(".insert | one entry with defaults", async () => {
|
|
167
|
-
const inserted: any = await postsModel
|
|
168
|
-
.insert({
|
|
169
|
-
title: "Post with defaults",
|
|
170
|
-
userId: 1,
|
|
171
|
-
})
|
|
172
|
-
.return();
|
|
173
|
-
|
|
174
|
-
const expected = await db
|
|
175
|
-
.select()
|
|
176
|
-
.from(schema.userPosts)
|
|
177
|
-
.where(eq(schema.userPosts.id, (inserted as any[])[0].id));
|
|
178
|
-
|
|
179
|
-
console.dir(inserted, {
|
|
180
|
-
depth: null,
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
expect(inserted).toBeDefined();
|
|
184
|
-
expect(Array.isArray(inserted)).toBe(true);
|
|
185
|
-
expect((inserted as any[])[0]).toBeDefined();
|
|
186
|
-
expect((inserted as any[])[0].title).toBe("Post with defaults");
|
|
187
|
-
expect((inserted as any[])[0].userId).toBe(1);
|
|
188
|
-
|
|
189
|
-
// description and featured are optional
|
|
190
|
-
expect((inserted as any[])[0].description).toBeNull();
|
|
191
|
-
expect((inserted as any[])[0].featured).toBeNull();
|
|
192
|
-
|
|
193
|
-
// likes and views should use table defaults
|
|
194
|
-
expect((inserted as any[])[0].likes).toBe(0);
|
|
195
|
-
expect((inserted as any[])[0].views).toBe(0);
|
|
196
|
-
expect((inserted as any[])[0]).toEqual((expected as any[])[0]);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test(".insert | multiple entries", async () => {
|
|
200
|
-
const inserted = await postsModel
|
|
201
|
-
.insert([
|
|
202
|
-
{
|
|
203
|
-
title: "First bulk post",
|
|
204
|
-
description: "First bulk description",
|
|
205
|
-
featured: false,
|
|
206
|
-
userId: 1,
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
title: "Second bulk post",
|
|
210
|
-
description: "Second bulk description",
|
|
211
|
-
featured: true,
|
|
212
|
-
userId: 1,
|
|
213
|
-
},
|
|
214
|
-
])
|
|
215
|
-
.return();
|
|
216
|
-
|
|
217
|
-
const ids = (inserted as any[]).map((x) => x.id);
|
|
218
|
-
const expected = await db
|
|
219
|
-
.select()
|
|
220
|
-
.from(schema.userPosts)
|
|
221
|
-
.where(inArray(schema.userPosts.id, ids));
|
|
222
|
-
|
|
223
|
-
console.dir(inserted, {
|
|
224
|
-
depth: null,
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
expect(inserted).toBeDefined();
|
|
228
|
-
expect(Array.isArray(inserted)).toBe(true);
|
|
229
|
-
expect(inserted as any[]).toHaveLength(2);
|
|
230
|
-
|
|
231
|
-
const [first, second] = inserted as any[];
|
|
232
|
-
|
|
233
|
-
expect(first.title).toBe("First bulk post");
|
|
234
|
-
expect(first.description).toBe("First bulk description");
|
|
235
|
-
expect(first.featured).toBe(false);
|
|
236
|
-
expect(first.likes).toBe(0);
|
|
237
|
-
expect(first.views).toBe(0);
|
|
238
|
-
|
|
239
|
-
expect(second.title).toBe("Second bulk post");
|
|
240
|
-
expect(second.description).toBe("Second bulk description");
|
|
241
|
-
expect(second.featured).toBe(true);
|
|
242
|
-
expect(second.likes).toBe(0);
|
|
243
|
-
expect(second.views).toBe(0);
|
|
244
|
-
|
|
245
|
-
expect(sortById(inserted as any)).toEqual(sortById(expected as any));
|
|
246
|
-
});
|
|
247
|
-
});
|