@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.
Files changed (45) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/DISCLAIMER.md +5 -0
  3. package/README.md +433 -0
  4. package/TODO.md +8 -61
  5. package/package.json +5 -3
  6. package/src/core/dialect.ts +81 -0
  7. package/src/core/index.ts +24 -0
  8. package/src/core/query/error.ts +15 -0
  9. package/src/core/query/joins.ts +663 -0
  10. package/src/core/query/projection.ts +136 -0
  11. package/src/core/query/where.ts +449 -0
  12. package/src/core/result.ts +303 -0
  13. package/src/core/runtime.ts +636 -0
  14. package/src/core/transform.ts +119 -0
  15. package/src/model/builder.ts +40 -6
  16. package/src/model/config.ts +9 -9
  17. package/src/model/format.ts +20 -8
  18. package/src/model/methods/exclude.ts +1 -7
  19. package/src/model/methods/return.ts +11 -11
  20. package/src/model/methods/select.ts +2 -8
  21. package/src/model/model.ts +10 -16
  22. package/src/model/query/error.ts +1 -0
  23. package/src/model/result.ts +137 -21
  24. package/src/types.ts +38 -0
  25. package/tests/base/count.test.ts +47 -0
  26. package/tests/base/delete.test.ts +90 -0
  27. package/tests/base/find.test.ts +209 -0
  28. package/tests/base/insert.test.ts +152 -0
  29. package/tests/base/relations.test.ts +593 -0
  30. package/tests/base/safe.test.ts +91 -0
  31. package/tests/base/update.test.ts +88 -0
  32. package/tests/base/upsert.test.ts +121 -0
  33. package/tests/base.ts +21 -0
  34. package/src/model/core/joins.ts +0 -364
  35. package/src/model/core/projection.ts +0 -61
  36. package/src/model/core/runtime.ts +0 -334
  37. package/src/model/core/thenable.ts +0 -94
  38. package/src/model/core/transform.ts +0 -65
  39. package/src/model/core/where.ts +0 -249
  40. package/src/model/core/with.ts +0 -28
  41. package/tests/builder-v2-mysql.type-test.ts +0 -51
  42. package/tests/builder-v2.type-test.ts +0 -336
  43. package/tests/builder.test.ts +0 -63
  44. package/tests/find.test.ts +0 -166
  45. package/tests/insert.test.ts +0 -247
@@ -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
- });
@@ -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
- });