@casekit/orm2 0.0.0-20250322230249

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 (275) hide show
  1. package/build/builders/buildCount.d.ts +23 -0
  2. package/build/builders/buildCount.js +63 -0
  3. package/build/builders/buildCount.test.d.ts +1 -0
  4. package/build/builders/buildCount.test.js +144 -0
  5. package/build/builders/buildCreate.d.ts +5 -0
  6. package/build/builders/buildCreate.js +28 -0
  7. package/build/builders/buildCreate.test.d.ts +1 -0
  8. package/build/builders/buildCreate.test.js +47 -0
  9. package/build/builders/buildDelete.d.ts +5 -0
  10. package/build/builders/buildDelete.js +28 -0
  11. package/build/builders/buildDelete.test.d.ts +1 -0
  12. package/build/builders/buildDelete.test.js +108 -0
  13. package/build/builders/buildFind.d.ts +8 -0
  14. package/build/builders/buildFind.js +185 -0
  15. package/build/builders/buildFind.test.d.ts +1 -0
  16. package/build/builders/buildFind.test.js +263 -0
  17. package/build/builders/buildUpdate.d.ts +5 -0
  18. package/build/builders/buildUpdate.js +34 -0
  19. package/build/builders/buildUpdate.test.d.ts +1 -0
  20. package/build/builders/buildUpdate.test.js +130 -0
  21. package/build/builders/buildWhere.d.ts +6 -0
  22. package/build/builders/buildWhere.js +63 -0
  23. package/build/builders/buildWhere.test.d.ts +1 -0
  24. package/build/builders/buildWhere.test.js +154 -0
  25. package/build/builders/types.d.ts +87 -0
  26. package/build/builders/types.js +1 -0
  27. package/build/connection.d.ts +31 -0
  28. package/build/connection.js +206 -0
  29. package/build/index.d.ts +10 -0
  30. package/build/index.js +5 -0
  31. package/build/operators.d.ts +59 -0
  32. package/build/operators.js +44 -0
  33. package/build/orm.count.d.ts +14 -0
  34. package/build/orm.count.js +22 -0
  35. package/build/orm.createMany.d.ts +5 -0
  36. package/build/orm.createMany.js +26 -0
  37. package/build/orm.createOne.d.ts +5 -0
  38. package/build/orm.createOne.js +34 -0
  39. package/build/orm.d.ts +81 -0
  40. package/build/orm.deleteMany.d.ts +5 -0
  41. package/build/orm.deleteMany.js +26 -0
  42. package/build/orm.deleteOne.d.ts +5 -0
  43. package/build/orm.deleteOne.js +32 -0
  44. package/build/orm.findMany.d.ts +8 -0
  45. package/build/orm.findMany.js +64 -0
  46. package/build/orm.findOne.d.ts +5 -0
  47. package/build/orm.findOne.js +20 -0
  48. package/build/orm.js +243 -0
  49. package/build/orm.restrict.d.ts +6 -0
  50. package/build/orm.restrict.js +52 -0
  51. package/build/orm.updateMany.d.ts +5 -0
  52. package/build/orm.updateMany.js +29 -0
  53. package/build/orm.updateOne.d.ts +5 -0
  54. package/build/orm.updateOne.js +35 -0
  55. package/build/sql/countToSql.d.ts +3 -0
  56. package/build/sql/countToSql.js +11 -0
  57. package/build/sql/countToSql.test.d.ts +1 -0
  58. package/build/sql/countToSql.test.js +218 -0
  59. package/build/sql/createToSql.d.ts +3 -0
  60. package/build/sql/createToSql.js +27 -0
  61. package/build/sql/createToSql.test.d.ts +1 -0
  62. package/build/sql/createToSql.test.js +186 -0
  63. package/build/sql/deleteToSql.d.ts +3 -0
  64. package/build/sql/deleteToSql.js +15 -0
  65. package/build/sql/deleteToSql.test.d.ts +1 -0
  66. package/build/sql/deleteToSql.test.js +93 -0
  67. package/build/sql/findToSql.d.ts +3 -0
  68. package/build/sql/findToSql.js +33 -0
  69. package/build/sql/findToSql.test.d.ts +1 -0
  70. package/build/sql/findToSql.test.js +409 -0
  71. package/build/sql/updateToSql.d.ts +3 -0
  72. package/build/sql/updateToSql.js +16 -0
  73. package/build/sql/updateToSql.test.d.ts +1 -0
  74. package/build/sql/updateToSql.test.js +165 -0
  75. package/build/sql/util.d.ts +11 -0
  76. package/build/sql/util.js +36 -0
  77. package/build/sql/util.test.d.ts +1 -0
  78. package/build/sql/util.test.js +163 -0
  79. package/build/tests/connection.test.d.ts +1 -0
  80. package/build/tests/connection.test.js +304 -0
  81. package/build/tests/datatypes.test.d.ts +1 -0
  82. package/build/tests/datatypes.test.js +239 -0
  83. package/build/tests/operators.test.d.ts +1 -0
  84. package/build/tests/operators.test.js +125 -0
  85. package/build/tests/orm.count.middleware.test.d.ts +1 -0
  86. package/build/tests/orm.count.middleware.test.js +132 -0
  87. package/build/tests/orm.count.test-d.d.ts +1 -0
  88. package/build/tests/orm.count.test-d.js +60 -0
  89. package/build/tests/orm.count.test.d.ts +1 -0
  90. package/build/tests/orm.count.test.js +151 -0
  91. package/build/tests/orm.createMany.middleware.test.d.ts +1 -0
  92. package/build/tests/orm.createMany.middleware.test.js +63 -0
  93. package/build/tests/orm.createMany.test-d.d.ts +1 -0
  94. package/build/tests/orm.createMany.test-d.js +131 -0
  95. package/build/tests/orm.createMany.test.d.ts +1 -0
  96. package/build/tests/orm.createMany.test.js +392 -0
  97. package/build/tests/orm.createOne.middleware.test.d.ts +1 -0
  98. package/build/tests/orm.createOne.middleware.test.js +54 -0
  99. package/build/tests/orm.createOne.test-d.d.ts +1 -0
  100. package/build/tests/orm.createOne.test-d.js +113 -0
  101. package/build/tests/orm.createOne.test.d.ts +1 -0
  102. package/build/tests/orm.createOne.test.js +268 -0
  103. package/build/tests/orm.deleteMany.middleware.test.d.ts +1 -0
  104. package/build/tests/orm.deleteMany.middleware.test.js +77 -0
  105. package/build/tests/orm.deleteMany.test-d.d.ts +1 -0
  106. package/build/tests/orm.deleteMany.test-d.js +179 -0
  107. package/build/tests/orm.deleteMany.test.d.ts +1 -0
  108. package/build/tests/orm.deleteMany.test.js +394 -0
  109. package/build/tests/orm.deleteOne.middleware.test.d.ts +1 -0
  110. package/build/tests/orm.deleteOne.middleware.test.js +61 -0
  111. package/build/tests/orm.deleteOne.test-d.d.ts +1 -0
  112. package/build/tests/orm.deleteOne.test-d.js +179 -0
  113. package/build/tests/orm.deleteOne.test.d.ts +1 -0
  114. package/build/tests/orm.deleteOne.test.js +360 -0
  115. package/build/tests/orm.findMany.includeManyToMany.test.d.ts +1 -0
  116. package/build/tests/orm.findMany.includeManyToMany.test.js +335 -0
  117. package/build/tests/orm.findMany.includeManyToOne.test.d.ts +1 -0
  118. package/build/tests/orm.findMany.includeManyToOne.test.js +286 -0
  119. package/build/tests/orm.findMany.includeOneToMany.test.d.ts +1 -0
  120. package/build/tests/orm.findMany.includeOneToMany.test.js +530 -0
  121. package/build/tests/orm.findMany.middleware.test.d.ts +1 -0
  122. package/build/tests/orm.findMany.middleware.test.js +66 -0
  123. package/build/tests/orm.findMany.offsetLimit.test.d.ts +1 -0
  124. package/build/tests/orm.findMany.offsetLimit.test.js +108 -0
  125. package/build/tests/orm.findMany.orderBy.test.d.ts +1 -0
  126. package/build/tests/orm.findMany.orderBy.test.js +304 -0
  127. package/build/tests/orm.findMany.select.test.d.ts +1 -0
  128. package/build/tests/orm.findMany.select.test.js +278 -0
  129. package/build/tests/orm.findMany.test-d.d.ts +1 -0
  130. package/build/tests/orm.findMany.test-d.js +374 -0
  131. package/build/tests/orm.findMany.where.test.d.ts +1 -0
  132. package/build/tests/orm.findMany.where.test.js +383 -0
  133. package/build/tests/orm.findOne.middleware.test.d.ts +1 -0
  134. package/build/tests/orm.findOne.middleware.test.js +57 -0
  135. package/build/tests/orm.findOne.test-d.d.ts +1 -0
  136. package/build/tests/orm.findOne.test-d.js +377 -0
  137. package/build/tests/orm.findOne.test.d.ts +1 -0
  138. package/build/tests/orm.findOne.test.js +247 -0
  139. package/build/tests/orm.restrict.test-d.d.ts +1 -0
  140. package/build/tests/orm.restrict.test-d.js +105 -0
  141. package/build/tests/orm.restrict.test.d.ts +1 -0
  142. package/build/tests/orm.restrict.test.js +259 -0
  143. package/build/tests/orm.transact.test.d.ts +1 -0
  144. package/build/tests/orm.transact.test.js +48 -0
  145. package/build/tests/orm.updateMany.middleware.test.d.ts +1 -0
  146. package/build/tests/orm.updateMany.middleware.test.js +72 -0
  147. package/build/tests/orm.updateMany.test.d.ts +1 -0
  148. package/build/tests/orm.updateMany.test.js +210 -0
  149. package/build/tests/orm.updateOne.middleware.test.d.ts +1 -0
  150. package/build/tests/orm.updateOne.middleware.test.js +62 -0
  151. package/build/tests/orm.updateOne.test.d.ts +1 -0
  152. package/build/tests/orm.updateOne.test.js +209 -0
  153. package/build/tests/util/db.d.ts +1571 -0
  154. package/build/tests/util/db.js +10 -0
  155. package/build/tests/util/logger.d.ts +19 -0
  156. package/build/tests/util/logger.js +40 -0
  157. package/build/types/BaseFindParams.d.ts +1 -0
  158. package/build/types/BaseFindParams.js +1 -0
  159. package/build/types/CountParams.d.ts +16 -0
  160. package/build/types/CountParams.js +1 -0
  161. package/build/types/CountParams.test-d.d.ts +1 -0
  162. package/build/types/CountParams.test-d.js +89 -0
  163. package/build/types/CreateManyParams.d.ts +11 -0
  164. package/build/types/CreateManyParams.js +1 -0
  165. package/build/types/CreateManyParams.test-d.d.ts +1 -0
  166. package/build/types/CreateManyParams.test-d.js +83 -0
  167. package/build/types/CreateManyResult.d.ts +5 -0
  168. package/build/types/CreateManyResult.js +1 -0
  169. package/build/types/CreateManyResult.test-d.d.ts +1 -0
  170. package/build/types/CreateManyResult.test-d.js +22 -0
  171. package/build/types/CreateOneParams.d.ts +11 -0
  172. package/build/types/CreateOneParams.js +1 -0
  173. package/build/types/CreateOneParams.test-d.d.ts +1 -0
  174. package/build/types/CreateOneParams.test-d.js +56 -0
  175. package/build/types/CreateOneResult.d.ts +5 -0
  176. package/build/types/CreateOneResult.js +1 -0
  177. package/build/types/CreateOneResult.test-d.d.ts +1 -0
  178. package/build/types/CreateOneResult.test-d.js +23 -0
  179. package/build/types/CreateValues.d.ts +6 -0
  180. package/build/types/CreateValues.js +1 -0
  181. package/build/types/CreateValues.test-d.d.ts +1 -0
  182. package/build/types/CreateValues.test-d.js +60 -0
  183. package/build/types/DeleteManyResult.d.ts +5 -0
  184. package/build/types/DeleteManyResult.js +1 -0
  185. package/build/types/DeleteManyResult.test-d.d.ts +1 -0
  186. package/build/types/DeleteManyResult.test-d.js +23 -0
  187. package/build/types/DeleteOneResult.d.ts +5 -0
  188. package/build/types/DeleteOneResult.js +1 -0
  189. package/build/types/DeleteOneResult.test-d.d.ts +1 -0
  190. package/build/types/DeleteOneResult.test-d.js +23 -0
  191. package/build/types/DeleteParams.d.ts +7 -0
  192. package/build/types/DeleteParams.js +1 -0
  193. package/build/types/DeleteParams.test-d.d.ts +1 -0
  194. package/build/types/DeleteParams.test-d.js +46 -0
  195. package/build/types/FindParams.d.ts +22 -0
  196. package/build/types/FindParams.js +1 -0
  197. package/build/types/FindParams.test-d.d.ts +1 -0
  198. package/build/types/FindParams.test-d.js +107 -0
  199. package/build/types/FindResult.d.ts +13 -0
  200. package/build/types/FindResult.js +1 -0
  201. package/build/types/FindResult.test-d.d.ts +1 -0
  202. package/build/types/FindResult.test-d.js +30 -0
  203. package/build/types/IncludeClause.d.ts +5 -0
  204. package/build/types/IncludeClause.js +1 -0
  205. package/build/types/IncludeClause.test-d.d.ts +1 -0
  206. package/build/types/IncludeClause.test-d.js +69 -0
  207. package/build/types/Middleware.d.ts +51 -0
  208. package/build/types/Middleware.js +37 -0
  209. package/build/types/OptionalValues.d.ts +4 -0
  210. package/build/types/OptionalValues.js +1 -0
  211. package/build/types/OptionalValues.test-d.d.ts +1 -0
  212. package/build/types/OptionalValues.test-d.js +12 -0
  213. package/build/types/OrderByClause.d.ts +9 -0
  214. package/build/types/OrderByClause.js +1 -0
  215. package/build/types/OrderByClause.test-d.d.ts +1 -0
  216. package/build/types/OrderByClause.test-d.js +44 -0
  217. package/build/types/RequiredValues.d.ts +4 -0
  218. package/build/types/RequiredValues.js +1 -0
  219. package/build/types/RequiredValues.test-d.d.ts +1 -0
  220. package/build/types/RequiredValues.test-d.js +22 -0
  221. package/build/types/RestrictModels.d.ts +23 -0
  222. package/build/types/RestrictModels.js +1 -0
  223. package/build/types/RestrictModels.test-d.d.ts +1 -0
  224. package/build/types/RestrictModels.test-d.js +44 -0
  225. package/build/types/ReturningClause.d.ts +3 -0
  226. package/build/types/ReturningClause.js +1 -0
  227. package/build/types/ReturningClause.test-d.d.ts +1 -0
  228. package/build/types/ReturningClause.test-d.js +15 -0
  229. package/build/types/SelectClause.d.ts +3 -0
  230. package/build/types/SelectClause.js +1 -0
  231. package/build/types/SelectClause.test-d.d.ts +1 -0
  232. package/build/types/SelectClause.test-d.js +15 -0
  233. package/build/types/UpdateManyResult.d.ts +5 -0
  234. package/build/types/UpdateManyResult.js +1 -0
  235. package/build/types/UpdateManyResult.test-d.d.ts +1 -0
  236. package/build/types/UpdateManyResult.test-d.js +15 -0
  237. package/build/types/UpdateOneResult.d.ts +5 -0
  238. package/build/types/UpdateOneResult.js +1 -0
  239. package/build/types/UpdateOneResult.test-d.d.ts +1 -0
  240. package/build/types/UpdateOneResult.test-d.js +15 -0
  241. package/build/types/UpdateParams.d.ts +9 -0
  242. package/build/types/UpdateParams.js +1 -0
  243. package/build/types/UpdateParams.test-d.d.ts +1 -0
  244. package/build/types/UpdateParams.test-d.js +29 -0
  245. package/build/types/UpdateValues.d.ts +6 -0
  246. package/build/types/UpdateValues.js +1 -0
  247. package/build/types/UpdateValues.test-d.d.ts +1 -0
  248. package/build/types/UpdateValues.test-d.js +33 -0
  249. package/build/types/WhereClause.d.ts +29 -0
  250. package/build/types/WhereClause.js +1 -0
  251. package/build/types/WhereClause.test-d.d.ts +1 -0
  252. package/build/types/WhereClause.test-d.js +137 -0
  253. package/build/util/getIncludedToManySubqueries.d.ts +12 -0
  254. package/build/util/getIncludedToManySubqueries.js +63 -0
  255. package/build/util/getIncludedToManySubqueries.test.d.ts +1 -0
  256. package/build/util/getIncludedToManySubqueries.test.js +121 -0
  257. package/build/util/getLateralJoinValues.d.ts +4 -0
  258. package/build/util/getLateralJoinValues.js +30 -0
  259. package/build/util/getLateralJoinValues.test.d.ts +1 -0
  260. package/build/util/getLateralJoinValues.test.js +99 -0
  261. package/build/util/hasClauses.d.ts +1 -0
  262. package/build/util/hasClauses.js +9 -0
  263. package/build/util/hasClauses.test.d.ts +1 -0
  264. package/build/util/hasClauses.test.js +15 -0
  265. package/build/util/makeTableAlias.d.ts +1 -0
  266. package/build/util/makeTableAlias.js +10 -0
  267. package/build/util/makeTableAlias.test.d.ts +1 -0
  268. package/build/util/makeTableAlias.test.js +18 -0
  269. package/build/util/resultSchema.d.ts +10 -0
  270. package/build/util/resultSchema.js +42 -0
  271. package/build/util/rowToObject.d.ts +8 -0
  272. package/build/util/rowToObject.js +10 -0
  273. package/build/util/rowToObject.test.d.ts +1 -0
  274. package/build/util/rowToObject.test.js +68 -0
  275. package/package.json +67 -0
@@ -0,0 +1,108 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
2
+ import { createTestDB } from "./util/db.js";
3
+ describe("findMany: offset and limit", () => {
4
+ const { db, logger, factory } = createTestDB();
5
+ beforeEach(() => {
6
+ logger.clear();
7
+ });
8
+ beforeAll(async () => {
9
+ await db.connect();
10
+ });
11
+ afterAll(async () => {
12
+ await db.close();
13
+ });
14
+ test("uses offset to skip records", async () => {
15
+ await db.transact(async (db) => {
16
+ await db.createMany("user", {
17
+ values: [
18
+ factory.user({ id: 1, name: "Alice" }),
19
+ factory.user({ id: 2, name: "Bob" }),
20
+ factory.user({ id: 3, name: "Charlie" }),
21
+ ],
22
+ });
23
+ const users = await db.findMany("user", {
24
+ select: ["id", "name"],
25
+ offset: 1,
26
+ orderBy: ["id"],
27
+ });
28
+ expect(users).toEqual([
29
+ { id: 2, name: "Bob" },
30
+ { id: 3, name: "Charlie" },
31
+ ]);
32
+ }, { rollback: true });
33
+ });
34
+ test("uses limit to restrict number of records", async () => {
35
+ await db.transact(async (db) => {
36
+ await db.createMany("user", {
37
+ values: [
38
+ factory.user({ id: 1, name: "Alice" }),
39
+ factory.user({ id: 2, name: "Bob" }),
40
+ factory.user({ id: 3, name: "Charlie" }),
41
+ ],
42
+ });
43
+ const users = await db.findMany("user", {
44
+ select: ["id", "name"],
45
+ limit: 2,
46
+ orderBy: ["id"],
47
+ });
48
+ expect(users).toEqual([
49
+ { id: 1, name: "Alice" },
50
+ { id: 2, name: "Bob" },
51
+ ]);
52
+ }, { rollback: true });
53
+ });
54
+ test("combines offset and limit", async () => {
55
+ await db.transact(async (db) => {
56
+ await db.createMany("user", {
57
+ values: [
58
+ factory.user({ id: 1, name: "Alice" }),
59
+ factory.user({ id: 2, name: "Bob" }),
60
+ factory.user({ id: 3, name: "Charlie" }),
61
+ factory.user({ id: 4, name: "Dave" }),
62
+ ],
63
+ });
64
+ const users = await db.findMany("user", {
65
+ select: ["id", "name"],
66
+ offset: 1,
67
+ limit: 2,
68
+ orderBy: ["id"],
69
+ });
70
+ expect(users).toEqual([
71
+ { id: 2, name: "Bob" },
72
+ { id: 3, name: "Charlie" },
73
+ ]);
74
+ }, { rollback: true });
75
+ });
76
+ test("handles offset beyond available records", async () => {
77
+ await db.transact(async (db) => {
78
+ await db.createMany("user", {
79
+ values: [
80
+ factory.user({ id: 1, name: "Alice" }),
81
+ factory.user({ id: 2, name: "Bob" }),
82
+ ],
83
+ });
84
+ const users = await db.findMany("user", {
85
+ select: ["id", "name"],
86
+ offset: 5,
87
+ orderBy: ["id"],
88
+ });
89
+ expect(users).toEqual([]);
90
+ }, { rollback: true });
91
+ });
92
+ test("throws error for negative offset", async () => {
93
+ await db.transact(async (db) => {
94
+ await expect(db.findMany("user", {
95
+ select: ["id", "name"],
96
+ offset: -1,
97
+ })).rejects.toThrow("OFFSET must not be negative");
98
+ }, { rollback: true });
99
+ });
100
+ test("throws error for negative limit", async () => {
101
+ await db.transact(async (db) => {
102
+ await expect(db.findMany("user", {
103
+ select: ["id", "name"],
104
+ limit: -1,
105
+ })).rejects.toThrow("LIMIT must not be negative");
106
+ }, { rollback: true });
107
+ });
108
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,304 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
2
+ import { createTestDB } from "./util/db.js";
3
+ describe("findMany: orderBy", () => {
4
+ const { db, logger, factory } = createTestDB();
5
+ beforeEach(() => {
6
+ logger.clear();
7
+ });
8
+ beforeAll(async () => {
9
+ await db.connect();
10
+ });
11
+ afterAll(async () => {
12
+ await db.close();
13
+ });
14
+ test("orders by a single column ascending by default", async () => {
15
+ await db.transact(async (db) => {
16
+ await db.createMany("user", {
17
+ values: [
18
+ factory.user({ id: 1, name: "Charlie" }),
19
+ factory.user({ id: 2, name: "Alice" }),
20
+ factory.user({ id: 3, name: "Bob" }),
21
+ ],
22
+ });
23
+ const users = await db.findMany("user", {
24
+ select: ["id", "name"],
25
+ orderBy: ["name"],
26
+ });
27
+ expect(users).toEqual([
28
+ { id: 2, name: "Alice" },
29
+ { id: 3, name: "Bob" },
30
+ { id: 1, name: "Charlie" },
31
+ ]);
32
+ }, { rollback: true });
33
+ });
34
+ test("orders by a single column with explicit direction", async () => {
35
+ await db.transact(async (db) => {
36
+ await db.createMany("user", {
37
+ values: [
38
+ factory.user({ id: 1, name: "Alice" }),
39
+ factory.user({ id: 2, name: "Bob" }),
40
+ factory.user({ id: 3, name: "Charlie" }),
41
+ ],
42
+ });
43
+ const users = await db.findMany("user", {
44
+ select: ["id", "name"],
45
+ orderBy: [["name", "desc"]],
46
+ });
47
+ expect(users).toEqual([
48
+ { id: 3, name: "Charlie" },
49
+ { id: 2, name: "Bob" },
50
+ { id: 1, name: "Alice" },
51
+ ]);
52
+ }, { rollback: true });
53
+ });
54
+ test("orders by multiple columns", async () => {
55
+ await db.transact(async (db) => {
56
+ await db.createMany("user", {
57
+ values: [
58
+ factory.user({ id: 1, role: "admin", name: "Charlie" }),
59
+ factory.user({ id: 2, role: "user", name: "Alice" }),
60
+ factory.user({ id: 3, role: "admin", name: "Bob" }),
61
+ factory.user({ id: 4, role: "user", name: "Bob" }),
62
+ ],
63
+ });
64
+ const users = await db.findMany("user", {
65
+ select: ["id", "name", "role"],
66
+ orderBy: [["role", "desc"], "name"],
67
+ });
68
+ expect(users).toEqual([
69
+ { id: 2, role: "user", name: "Alice" },
70
+ { id: 4, role: "user", name: "Bob" },
71
+ { id: 3, role: "admin", name: "Bob" },
72
+ { id: 1, role: "admin", name: "Charlie" },
73
+ ]);
74
+ }, { rollback: true });
75
+ });
76
+ test("handles null values in ordering", async () => {
77
+ await db.transact(async (db) => {
78
+ await db.createMany("user", {
79
+ values: [
80
+ factory.user({
81
+ id: 1,
82
+ name: "Alice",
83
+ deletedAt: new Date("2024-01-01"),
84
+ }),
85
+ factory.user({ id: 2, name: "Bob", deletedAt: null }),
86
+ factory.user({
87
+ id: 3,
88
+ name: "Charlie",
89
+ deletedAt: new Date("2023-12-31"),
90
+ }),
91
+ ],
92
+ });
93
+ const users = await db.findMany("user", {
94
+ select: ["id", "name", "deletedAt"],
95
+ orderBy: ["deletedAt"],
96
+ });
97
+ expect(users).toEqual([
98
+ {
99
+ id: 3,
100
+ name: "Charlie",
101
+ deletedAt: new Date("2023-12-31"),
102
+ },
103
+ { id: 1, name: "Alice", deletedAt: new Date("2024-01-01") },
104
+ { id: 2, name: "Bob", deletedAt: null },
105
+ ]);
106
+ }, { rollback: true });
107
+ });
108
+ test("orders json fields", async () => {
109
+ await db.transact(async (db) => {
110
+ await db.createMany("user", {
111
+ values: [
112
+ factory.user({ id: 1, preferences: { theme: "dark" } }),
113
+ factory.user({
114
+ id: 2,
115
+ preferences: { theme: "light" },
116
+ }),
117
+ factory.user({ id: 3, preferences: { theme: "auto" } }),
118
+ ],
119
+ });
120
+ const users = await db.findMany("user", {
121
+ select: ["id", "preferences"],
122
+ orderBy: ["preferences"],
123
+ });
124
+ expect(users).toEqual([
125
+ { id: 3, preferences: { theme: "auto" } },
126
+ { id: 1, preferences: { theme: "dark" } },
127
+ { id: 2, preferences: { theme: "light" } },
128
+ ]);
129
+ }, { rollback: true });
130
+ });
131
+ test("throws error when ordering by non-existent field", async () => {
132
+ await db.transact(async (db) => {
133
+ await expect(db.findMany("user", {
134
+ select: ["id"],
135
+ // @ts-expect-error - Testing runtime behavior
136
+ orderBy: ["nonexistentField"],
137
+ })).rejects.toThrow('Field "nonexistentField" not found in model "user"');
138
+ }, { rollback: true });
139
+ });
140
+ test("orders by array fields", async () => {
141
+ await db.transact(async (db) => {
142
+ await db.createOne("user", {
143
+ values: factory.user({ id: 1, name: "Charlie" }),
144
+ });
145
+ await db.createMany("post", {
146
+ values: [
147
+ factory.post({
148
+ id: 1,
149
+ tags: ["dev", "javascript"],
150
+ authorId: 1,
151
+ }),
152
+ factory.post({
153
+ id: 2,
154
+ tags: ["dev"],
155
+ authorId: 1,
156
+ }),
157
+ factory.post({
158
+ id: 3,
159
+ tags: ["javascript", "typescript"],
160
+ authorId: 1,
161
+ }),
162
+ ],
163
+ });
164
+ const posts = await db.findMany("post", {
165
+ select: ["id", "tags"],
166
+ orderBy: ["tags"],
167
+ });
168
+ expect(posts).toEqual([
169
+ { id: 2, tags: ["dev"] },
170
+ { id: 1, tags: ["dev", "javascript"] },
171
+ { id: 3, tags: ["javascript", "typescript"] },
172
+ ]);
173
+ }, { rollback: true });
174
+ });
175
+ test("orders by N:1 relation field ascending", async () => {
176
+ await db.transact(async (db) => {
177
+ await db.createMany("user", {
178
+ values: [
179
+ factory.user({ id: 1, name: "Charlie" }),
180
+ factory.user({ id: 2, name: "Alice" }),
181
+ factory.user({ id: 3, name: "Bob" }),
182
+ ],
183
+ });
184
+ await db.createMany("post", {
185
+ values: [
186
+ factory.post({
187
+ id: 1,
188
+ title: "Post 1",
189
+ authorId: 1,
190
+ }),
191
+ factory.post({
192
+ id: 2,
193
+ title: "Post 2",
194
+ authorId: 2,
195
+ }),
196
+ factory.post({
197
+ id: 3,
198
+ title: "Post 3",
199
+ authorId: 3,
200
+ }),
201
+ ],
202
+ });
203
+ const posts = await db.findMany("post", {
204
+ select: ["id", "title"],
205
+ include: { author: { select: ["name"] } },
206
+ orderBy: ["author.name"],
207
+ });
208
+ expect(posts).toEqual([
209
+ { id: 2, title: "Post 2", author: { name: "Alice" } },
210
+ { id: 3, title: "Post 3", author: { name: "Bob" } },
211
+ { id: 1, title: "Post 1", author: { name: "Charlie" } },
212
+ ]);
213
+ }, { rollback: true });
214
+ });
215
+ test("orders by N:1 relation field descending", async () => {
216
+ await db.transact(async (db) => {
217
+ await db.createMany("user", {
218
+ values: [
219
+ factory.user({ id: 1, name: "Charlie" }),
220
+ factory.user({ id: 2, name: "Alice" }),
221
+ factory.user({ id: 3, name: "Bob" }),
222
+ ],
223
+ });
224
+ await db.createMany("post", {
225
+ values: [
226
+ factory.post({
227
+ id: 1,
228
+ title: "Post 1",
229
+ authorId: 1,
230
+ }),
231
+ factory.post({
232
+ id: 2,
233
+ title: "Post 2",
234
+ authorId: 2,
235
+ }),
236
+ factory.post({
237
+ id: 3,
238
+ title: "Post 3",
239
+ authorId: 3,
240
+ }),
241
+ ],
242
+ });
243
+ const posts = await db.findMany("post", {
244
+ select: ["id", "title"],
245
+ include: { author: { select: ["name"] } },
246
+ orderBy: [["author.name", "desc"]],
247
+ });
248
+ expect(posts).toEqual([
249
+ { id: 1, title: "Post 1", author: { name: "Charlie" } },
250
+ { id: 3, title: "Post 3", author: { name: "Bob" } },
251
+ { id: 2, title: "Post 2", author: { name: "Alice" } },
252
+ ]);
253
+ }, { rollback: true });
254
+ });
255
+ test("orders by mix of direct and N:1 relation fields", async () => {
256
+ await db.transact(async (db) => {
257
+ await db.createMany("user", {
258
+ values: [
259
+ factory.user({ id: 1, name: "Alice" }),
260
+ factory.user({ id: 2, name: "Alice" }),
261
+ factory.user({ id: 3, name: "Bob" }),
262
+ ],
263
+ });
264
+ await db.createMany("post", {
265
+ values: [
266
+ factory.post({
267
+ id: 1,
268
+ title: "First Post",
269
+ authorId: 1,
270
+ }),
271
+ factory.post({
272
+ id: 2,
273
+ title: "Another Post",
274
+ authorId: 2,
275
+ }),
276
+ factory.post({
277
+ id: 3,
278
+ title: "Last Post",
279
+ authorId: 3,
280
+ }),
281
+ factory.post({
282
+ id: 4,
283
+ title: "New Post",
284
+ authorId: 1,
285
+ }),
286
+ ],
287
+ });
288
+ const posts = await db.findMany("post", {
289
+ select: ["id", "title"],
290
+ include: { author: { select: ["name"] } },
291
+ orderBy: [
292
+ ["author.name", "asc"],
293
+ ["title", "desc"],
294
+ ],
295
+ });
296
+ expect(posts).toEqual([
297
+ { id: 4, title: "New Post", author: { name: "Alice" } },
298
+ { id: 1, title: "First Post", author: { name: "Alice" } },
299
+ { id: 2, title: "Another Post", author: { name: "Alice" } },
300
+ { id: 3, title: "Last Post", author: { name: "Bob" } },
301
+ ]);
302
+ }, { rollback: true });
303
+ });
304
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,278 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
2
+ import { createTestDB } from "./util/db.js";
3
+ describe("findMany: select", () => {
4
+ const { db, logger, factory } = createTestDB();
5
+ beforeEach(() => {
6
+ logger.clear();
7
+ });
8
+ beforeAll(async () => {
9
+ await db.connect();
10
+ });
11
+ afterAll(async () => {
12
+ await db.close();
13
+ });
14
+ test("selected fields are returned", async () => {
15
+ await db.transact(async (db) => {
16
+ await db.createMany("user", {
17
+ values: [
18
+ factory.user({ id: 1, name: "Lynne Tillman" }),
19
+ factory.user({ id: 2, name: "Stewart Home" }),
20
+ factory.user({ id: 3, name: "Chinua Achebe" }),
21
+ ],
22
+ });
23
+ const users = await db.findMany("user", {
24
+ select: ["id", "name"],
25
+ orderBy: ["id"],
26
+ });
27
+ expect(users).toEqual([
28
+ { id: 1, name: "Lynne Tillman" },
29
+ { id: 2, name: "Stewart Home" },
30
+ { id: 3, name: "Chinua Achebe" },
31
+ ]);
32
+ }, { rollback: true });
33
+ });
34
+ test("primary key will not be returned if it is not selected", async () => {
35
+ await db.transact(async (db) => {
36
+ await db.createMany("user", {
37
+ values: [
38
+ factory.user({ id: 1, name: "Lynne Tillman" }),
39
+ factory.user({ id: 2, name: "Stewart Home" }),
40
+ ],
41
+ });
42
+ const selectedUsers = await db.findMany("user", {
43
+ select: ["name"],
44
+ orderBy: ["id"],
45
+ });
46
+ expect(selectedUsers).toEqual([
47
+ { name: "Lynne Tillman" },
48
+ { name: "Stewart Home" },
49
+ ]);
50
+ }, { rollback: true });
51
+ });
52
+ test("enum fields can be selected", async () => {
53
+ await db.transact(async (db) => {
54
+ await db.createMany("user", {
55
+ values: [
56
+ factory.user({ id: 1, role: "user" }),
57
+ factory.user({ id: 2, role: "admin" }),
58
+ ],
59
+ });
60
+ const users = await db.findMany("user", {
61
+ select: ["id", "role"],
62
+ orderBy: ["role"],
63
+ });
64
+ expect(users).toEqual([
65
+ { id: 2, role: "admin" },
66
+ { id: 1, role: "user" },
67
+ ]);
68
+ }, { rollback: true });
69
+ });
70
+ test("array fields can be selected", async () => {
71
+ await db.transact(async (db) => {
72
+ await db.createMany("user", {
73
+ values: [
74
+ factory.user({ id: 1, role: "user" }),
75
+ factory.user({ id: 2, role: "admin" }),
76
+ ],
77
+ });
78
+ await db.createMany("post", {
79
+ values: [
80
+ factory.post({
81
+ id: 3,
82
+ tags: ["foo", "bar"],
83
+ authorId: 1,
84
+ }),
85
+ factory.post({
86
+ id: 4,
87
+ tags: ["baz"],
88
+ authorId: 1,
89
+ }),
90
+ factory.post({
91
+ id: 5,
92
+ tags: [],
93
+ authorId: 2,
94
+ }),
95
+ ],
96
+ });
97
+ const posts = await db.findMany("post", {
98
+ select: ["id", "tags"],
99
+ orderBy: ["id"],
100
+ });
101
+ expect(posts).toEqual([
102
+ { id: 3, tags: ["foo", "bar"] },
103
+ { id: 4, tags: ["baz"] },
104
+ { id: 5, tags: [] },
105
+ ]);
106
+ }, { rollback: true });
107
+ });
108
+ test("json fields can be selected", async () => {
109
+ await db.transact(async (db) => {
110
+ await db.createMany("user", {
111
+ values: [
112
+ factory.user({ id: 1, role: "user" }),
113
+ factory.user({ id: 2, role: "admin" }),
114
+ ],
115
+ });
116
+ await db.createMany("post", {
117
+ values: [
118
+ factory.post({
119
+ id: 3,
120
+ authorId: 1,
121
+ metadata: {
122
+ foo: "a",
123
+ bar: [
124
+ { baz: "good", quux: true },
125
+ { baz: "bad", quux: false },
126
+ ],
127
+ },
128
+ }),
129
+ factory.post({
130
+ id: 4,
131
+ authorId: 1,
132
+ metadata: {
133
+ foo: "b",
134
+ bar: [],
135
+ },
136
+ }),
137
+ factory.post({
138
+ id: 5,
139
+ authorId: 2,
140
+ metadata: {
141
+ foo: "c",
142
+ bar: [{ baz: "indifferent", quux: true }],
143
+ },
144
+ }),
145
+ ],
146
+ });
147
+ const posts = await db.findMany("post", {
148
+ select: ["metadata"],
149
+ orderBy: ["id"],
150
+ });
151
+ expect(posts).toEqual([
152
+ {
153
+ metadata: {
154
+ foo: "a",
155
+ bar: [
156
+ { baz: "good", quux: true },
157
+ { baz: "bad", quux: false },
158
+ ],
159
+ },
160
+ },
161
+ { metadata: { foo: "b", bar: [] } },
162
+ {
163
+ metadata: {
164
+ foo: "c",
165
+ bar: [{ baz: "indifferent", quux: true }],
166
+ },
167
+ },
168
+ ]);
169
+ }, { rollback: true });
170
+ });
171
+ test("returns empty array when no records match", async () => {
172
+ await db.transact(async (db) => {
173
+ const users = await db.findMany("user", {
174
+ select: ["id", "name"],
175
+ });
176
+ expect(users).toEqual([]);
177
+ }, { rollback: true });
178
+ });
179
+ test("handles null values in selected fields correctly", async () => {
180
+ await db.transact(async (db) => {
181
+ await db.createMany("user", {
182
+ values: [
183
+ factory.user({
184
+ id: 1,
185
+ deletedAt: new Date("2024-01-21"),
186
+ }),
187
+ factory.user({ id: 2, deletedAt: null }),
188
+ ],
189
+ });
190
+ const users = await db.findMany("user", {
191
+ select: ["id", "deletedAt"],
192
+ orderBy: ["id"],
193
+ });
194
+ expect(users).toEqual([
195
+ { id: 1, deletedAt: new Date("2024-01-21") },
196
+ { id: 2, deletedAt: null },
197
+ ]);
198
+ }, { rollback: true });
199
+ });
200
+ test("can select all available fields", async () => {
201
+ await db.transact(async (db) => {
202
+ const user = factory.user({
203
+ id: 1,
204
+ name: "Test User",
205
+ email: "test@example.com",
206
+ role: "user",
207
+ preferences: { theme: "dark" },
208
+ createdAt: new Date(),
209
+ deletedAt: null,
210
+ });
211
+ await db.createOne("user", { values: user });
212
+ const users = await db.findMany("user", {
213
+ select: [
214
+ "id",
215
+ "name",
216
+ "email",
217
+ "role",
218
+ "preferences",
219
+ "createdAt",
220
+ "deletedAt",
221
+ ],
222
+ });
223
+ expect(users[0]).toEqual(user);
224
+ }, { rollback: true });
225
+ });
226
+ test("throws error when selecting from non-existent model", async () => {
227
+ await db.transact(async (db) => {
228
+ await expect(
229
+ // @ts-expect-error - Testing runtime behavior
230
+ db.findMany("invalid", {
231
+ select: ["id"],
232
+ })).rejects.toThrow(`Model "invalid" not found`);
233
+ }, { rollback: true });
234
+ });
235
+ test("throws error when selecting non-existent field", async () => {
236
+ await db.transact(async (db) => {
237
+ await expect(db.findMany("user", {
238
+ // @ts-expect-error - Testing runtime behavior
239
+ select: ["id", "nonexistentField"],
240
+ })).rejects.toThrow(`Field "nonexistentField" not found in model "user"`);
241
+ }, { rollback: true });
242
+ });
243
+ test("handles special characters in selected field values", async () => {
244
+ await db.transact(async (db) => {
245
+ await db.createMany("user", {
246
+ values: [
247
+ factory.user({ id: 1, name: "O'Connor" }),
248
+ factory.user({
249
+ id: 2,
250
+ name: "User; DROP TABLE users;",
251
+ }),
252
+ factory.user({ id: 3, name: "User with spaces" }),
253
+ ],
254
+ });
255
+ const users = await db.findMany("user", {
256
+ select: ["id", "name"],
257
+ orderBy: ["id"],
258
+ });
259
+ expect(users).toEqual([
260
+ { id: 1, name: "O'Connor" },
261
+ { id: 2, name: "User; DROP TABLE users;" },
262
+ { id: 3, name: "User with spaces" },
263
+ ]);
264
+ }, { rollback: true });
265
+ });
266
+ test("handles large text values in selected fields", async () => {
267
+ await db.transact(async (db) => {
268
+ const longText = "a".repeat(10000);
269
+ await db.createOne("user", {
270
+ values: factory.user({ id: 1, name: longText }),
271
+ });
272
+ const users = await db.findMany("user", {
273
+ select: ["id", "name"],
274
+ });
275
+ expect(users).toEqual([{ id: 1, name: longText }]);
276
+ }, { rollback: true });
277
+ });
278
+ });