@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,394 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test, } from "vitest";
2
+ import { config } from "@casekit/orm2-fixtures";
3
+ import { $and, $in, $like, $or } from "../operators.js";
4
+ import { orm } from "../orm.js";
5
+ import { mockLogger } from "./util/logger.js";
6
+ describe("deleteMany", () => {
7
+ const logger = mockLogger();
8
+ let db;
9
+ beforeEach(() => {
10
+ logger.clear();
11
+ });
12
+ beforeAll(async () => {
13
+ db = orm({ ...config, logger });
14
+ await db.connect();
15
+ });
16
+ afterAll(async () => {
17
+ await db.close();
18
+ });
19
+ test("deletes multiple records and returns count when no returning clause specified", async () => {
20
+ await db.transact(async (db) => {
21
+ await db.createMany("user", {
22
+ values: [
23
+ {
24
+ id: 1,
25
+ name: "Delete User 1",
26
+ email: "delete1@example.com",
27
+ role: "user",
28
+ },
29
+ {
30
+ id: 2,
31
+ name: "Keep User 1",
32
+ email: "keep1@example.com",
33
+ role: "user",
34
+ },
35
+ {
36
+ id: 3,
37
+ name: "Delete User 2",
38
+ email: "delete2@example.com",
39
+ role: "admin",
40
+ },
41
+ {
42
+ id: 4,
43
+ name: "Keep User 2",
44
+ email: "keep2@example.com",
45
+ role: "user",
46
+ },
47
+ ],
48
+ });
49
+ const result = await db.deleteMany("user", {
50
+ where: { id: { [$in]: [1, 3] } },
51
+ });
52
+ expect(result).toBe(2);
53
+ const remainingUsers = await db.findMany("user", {
54
+ select: ["id", "name"],
55
+ orderBy: ["id"],
56
+ });
57
+ expect(remainingUsers).toHaveLength(2);
58
+ expect(remainingUsers).toEqual([
59
+ { id: 2, name: "Keep User 1" },
60
+ { id: 4, name: "Keep User 2" },
61
+ ]);
62
+ }, { rollback: true });
63
+ });
64
+ test("deletes multiple records and returns specified fields", async () => {
65
+ await db.transact(async (db) => {
66
+ await db.createMany("user", {
67
+ values: [
68
+ {
69
+ id: 1,
70
+ name: "Delete User 1",
71
+ email: "delete1@example.com",
72
+ role: "user",
73
+ },
74
+ {
75
+ id: 2,
76
+ name: "Delete User 2",
77
+ email: "delete2@example.com",
78
+ role: "admin",
79
+ },
80
+ {
81
+ id: 3,
82
+ name: "Keep User",
83
+ email: "keep@example.com",
84
+ role: "user",
85
+ },
86
+ ],
87
+ });
88
+ const deletedUsers = await db.deleteMany("user", {
89
+ where: { id: { [$in]: [1, 2] } },
90
+ returning: ["id", "name", "email", "role"],
91
+ });
92
+ expect(deletedUsers).toHaveLength(2);
93
+ expect(deletedUsers).toEqual([
94
+ {
95
+ id: 1,
96
+ name: "Delete User 1",
97
+ email: "delete1@example.com",
98
+ role: "user",
99
+ },
100
+ {
101
+ id: 2,
102
+ name: "Delete User 2",
103
+ email: "delete2@example.com",
104
+ role: "admin",
105
+ },
106
+ ]);
107
+ const remainingUser = await db.findOne("user", {
108
+ select: ["id", "name", "email", "role"],
109
+ where: { id: 3 },
110
+ });
111
+ expect(remainingUser).toEqual({
112
+ id: 3,
113
+ name: "Keep User",
114
+ email: "keep@example.com",
115
+ role: "user",
116
+ });
117
+ }, { rollback: true });
118
+ });
119
+ test("returns empty array when no records match delete criteria", async () => {
120
+ await db.transact(async (db) => {
121
+ await db.createMany("user", {
122
+ values: [
123
+ {
124
+ id: 1,
125
+ name: "Keep User 1",
126
+ email: "keep1@example.com",
127
+ role: "user",
128
+ },
129
+ {
130
+ id: 2,
131
+ name: "Keep User 2",
132
+ email: "keep2@example.com",
133
+ role: "admin",
134
+ },
135
+ ],
136
+ });
137
+ const result = await db.deleteMany("user", {
138
+ where: { id: 999999 },
139
+ returning: ["id", "name"],
140
+ });
141
+ expect(result).toEqual([]);
142
+ const remainingUsers = await db.findMany("user", {
143
+ select: ["id", "name"],
144
+ orderBy: ["id"],
145
+ });
146
+ expect(remainingUsers).toHaveLength(2);
147
+ expect(remainingUsers).toEqual([
148
+ { id: 1, name: "Keep User 1" },
149
+ { id: 2, name: "Keep User 2" },
150
+ ]);
151
+ }, { rollback: true });
152
+ });
153
+ test("returns zero when no records match delete criteria and no returning clause", async () => {
154
+ await db.transact(async (db) => {
155
+ await db.createMany("user", {
156
+ values: [
157
+ {
158
+ id: 1,
159
+ name: "Keep User 1",
160
+ email: "keep1@example.com",
161
+ role: "user",
162
+ },
163
+ {
164
+ id: 2,
165
+ name: "Keep User 2",
166
+ email: "keep2@example.com",
167
+ role: "admin",
168
+ },
169
+ ],
170
+ });
171
+ const result = await db.deleteMany("user", {
172
+ where: { id: 999999 },
173
+ });
174
+ expect(result).toBe(0);
175
+ const remainingUsers = await db.findMany("user", {
176
+ select: ["id"],
177
+ });
178
+ expect(remainingUsers).toHaveLength(2);
179
+ }, { rollback: true });
180
+ });
181
+ test("deletes records matching complex where clause including enum values", async () => {
182
+ await db.transact(async (db) => {
183
+ // Create test users with different roles and emails
184
+ await db.createMany("user", {
185
+ values: [
186
+ {
187
+ id: 1,
188
+ name: "Keep Regular User",
189
+ email: "keep@example.com",
190
+ role: "user",
191
+ },
192
+ {
193
+ id: 2,
194
+ name: "Delete Admin",
195
+ email: "admin@example.com",
196
+ role: "admin",
197
+ },
198
+ {
199
+ id: 3,
200
+ name: "Delete User",
201
+ email: "delete@example.com",
202
+ role: "user",
203
+ },
204
+ {
205
+ id: 4,
206
+ name: "Keep Another Admin",
207
+ email: "keep-admin@example.com",
208
+ role: "admin",
209
+ },
210
+ ],
211
+ });
212
+ const result = await db.deleteMany("user", {
213
+ where: {
214
+ [$or]: [
215
+ {
216
+ [$and]: [
217
+ { role: "admin" },
218
+ { email: { [$like]: "%@example.com" } },
219
+ { name: { [$like]: "%Delete%" } },
220
+ ],
221
+ },
222
+ { email: "delete@example.com" },
223
+ ],
224
+ },
225
+ returning: ["id", "role", "email"],
226
+ });
227
+ expect(result).toHaveLength(2);
228
+ expect(result).toEqual([
229
+ {
230
+ id: 2,
231
+ role: "admin",
232
+ email: "admin@example.com",
233
+ },
234
+ {
235
+ id: 3,
236
+ role: "user",
237
+ email: "delete@example.com",
238
+ },
239
+ ]);
240
+ const remainingUsers = await db.findMany("user", {
241
+ select: ["id", "name", "role"],
242
+ orderBy: ["id"],
243
+ });
244
+ expect(remainingUsers).toHaveLength(2);
245
+ expect(remainingUsers).toEqual([
246
+ {
247
+ id: 1,
248
+ name: "Keep Regular User",
249
+ role: "user",
250
+ },
251
+ {
252
+ id: 4,
253
+ name: "Keep Another Admin",
254
+ role: "admin",
255
+ },
256
+ ]);
257
+ }, { rollback: true });
258
+ });
259
+ test("handles array, enum, and JSON fields in returning clause", async () => {
260
+ await db.transact(async (db) => {
261
+ const user = await db.createOne("user", {
262
+ values: {
263
+ id: 1,
264
+ name: "Test User",
265
+ email: "test@example.com",
266
+ role: "user",
267
+ },
268
+ returning: ["id"],
269
+ });
270
+ await db.createMany("post", {
271
+ values: [
272
+ {
273
+ id: 1,
274
+ title: "Delete Post 1",
275
+ content: "Content 1",
276
+ authorId: user.id,
277
+ tags: ["delete", "test", "post1"],
278
+ metadata: {
279
+ foo: "a",
280
+ bar: [{ baz: "good", quux: true }],
281
+ },
282
+ },
283
+ {
284
+ id: 2,
285
+ title: "Delete Post 2",
286
+ content: "Content 2",
287
+ authorId: user.id,
288
+ tags: ["delete", "test", "post2"],
289
+ metadata: {
290
+ foo: "b",
291
+ bar: [{ baz: "bad", quux: false }],
292
+ },
293
+ },
294
+ {
295
+ id: 3,
296
+ title: "Keep Post",
297
+ content: "Content 3",
298
+ authorId: user.id,
299
+ tags: ["keep", "test"],
300
+ metadata: {
301
+ foo: "c",
302
+ bar: [{ baz: "indifferent", quux: true }],
303
+ },
304
+ },
305
+ ],
306
+ });
307
+ const result = await db.deleteMany("post", {
308
+ where: {
309
+ tags: {
310
+ [$in]: [
311
+ ["delete", "test", "post1"],
312
+ ["delete", "test", "post2"],
313
+ ],
314
+ },
315
+ },
316
+ returning: ["id", "tags", "metadata"],
317
+ });
318
+ expect(result).toHaveLength(2);
319
+ expect(result).toEqual([
320
+ {
321
+ id: 1,
322
+ tags: ["delete", "test", "post1"],
323
+ metadata: {
324
+ foo: "a",
325
+ bar: [{ baz: "good", quux: true }],
326
+ },
327
+ },
328
+ {
329
+ id: 2,
330
+ tags: ["delete", "test", "post2"],
331
+ metadata: {
332
+ foo: "b",
333
+ bar: [{ baz: "bad", quux: false }],
334
+ },
335
+ },
336
+ ]);
337
+ const remainingPost = await db.findOne("post", {
338
+ select: ["id", "title", "tags", "metadata"],
339
+ where: { id: 3 },
340
+ });
341
+ expect(remainingPost).toEqual({
342
+ id: 3,
343
+ title: "Keep Post",
344
+ tags: ["keep", "test"],
345
+ metadata: {
346
+ foo: "c",
347
+ bar: [{ baz: "indifferent", quux: true }],
348
+ },
349
+ });
350
+ }, { rollback: true });
351
+ });
352
+ test("throws error when deleting records would violate foreign key constraints", async () => {
353
+ await db.transact(async (db) => {
354
+ const users = await db.createMany("user", {
355
+ values: [
356
+ {
357
+ id: 1,
358
+ name: "User with Posts",
359
+ email: "posts@example.com",
360
+ role: "user",
361
+ },
362
+ {
363
+ id: 2,
364
+ name: "User to Delete",
365
+ email: "delete@example.com",
366
+ role: "user",
367
+ },
368
+ {
369
+ id: 3,
370
+ name: "Keep User",
371
+ email: "keep@example.com",
372
+ role: "admin",
373
+ },
374
+ ],
375
+ returning: ["id"],
376
+ });
377
+ await db.createOne("post", {
378
+ values: {
379
+ title: "Test Post",
380
+ content: "Content",
381
+ authorId: users[0].id,
382
+ },
383
+ });
384
+ await expect(db.deleteMany("user", {
385
+ where: { role: "user" },
386
+ })).rejects.toThrow();
387
+ const remainingUsers = await db.findMany("user", {
388
+ select: ["id"],
389
+ orderBy: ["id"],
390
+ });
391
+ expect(remainingUsers).toHaveLength(3);
392
+ }, { rollback: true });
393
+ });
394
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,61 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test, vi, } from "vitest";
2
+ import { config } from "@casekit/orm2-fixtures";
3
+ import { orm } from "../orm.js";
4
+ import { mockLogger } from "./util/logger.js";
5
+ describe("orm.deleteOne: middleware", () => {
6
+ const logger = mockLogger();
7
+ let db;
8
+ beforeEach(() => {
9
+ logger.clear();
10
+ });
11
+ beforeAll(async () => {
12
+ db = orm({ ...config, logger });
13
+ await db.connect();
14
+ });
15
+ afterAll(async () => {
16
+ await db.close();
17
+ });
18
+ describe("deleteOne middleware", () => {
19
+ test("it allows overriding the orm's deleteOne method", async () => {
20
+ await db.transact(async (db) => {
21
+ // Create a test user to delete
22
+ const user = await db.createOne("user", {
23
+ values: {
24
+ id: 1,
25
+ name: "Test User",
26
+ email: "test@example.com",
27
+ role: "user",
28
+ },
29
+ returning: ["id"],
30
+ });
31
+ const stub = vi.fn();
32
+ const dbWithMiddleware = db.middleware([
33
+ {
34
+ deleteOne: (db, table, query) => {
35
+ stub("called stub in middleware 1");
36
+ return db.deleteOne(table, query);
37
+ },
38
+ },
39
+ {
40
+ deleteOne: (db, table, query) => {
41
+ stub("called stub in middleware 2");
42
+ return db.deleteOne(table, query);
43
+ },
44
+ },
45
+ ]);
46
+ const result = await dbWithMiddleware.deleteOne("user", {
47
+ where: { id: user.id },
48
+ returning: ["id", "name"],
49
+ });
50
+ expect(result).toMatchObject({
51
+ id: 1,
52
+ name: "Test User",
53
+ });
54
+ expect(stub.mock.calls).toEqual([
55
+ ["called stub in middleware 1"],
56
+ ["called stub in middleware 2"],
57
+ ]);
58
+ }, { rollback: true });
59
+ });
60
+ });
61
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,179 @@
1
+ import { describe, expectTypeOf, test } from "vitest";
2
+ import { $gt, $is, $like, $or } from "../operators.js";
3
+ import { createTestDB } from "./util/db.js";
4
+ describe("deleteOne", () => {
5
+ const { db } = createTestDB();
6
+ test("returns a single record when returning clause is specified", () => {
7
+ expectTypeOf(db.deleteOne("post", {
8
+ where: { id: 1 },
9
+ returning: ["id", "title", "content"],
10
+ })).resolves.toEqualTypeOf();
11
+ });
12
+ test("returns number when no returning clause specified", () => {
13
+ expectTypeOf(db.deleteOne("post", {
14
+ where: { id: 1 },
15
+ })).resolves.toEqualTypeOf();
16
+ });
17
+ test("handles nullable fields in returning clause", () => {
18
+ expectTypeOf(db.deleteOne("post", {
19
+ where: { id: 1 },
20
+ returning: ["deletedAt"],
21
+ })).resolves.toEqualTypeOf();
22
+ });
23
+ test("handles array fields in where and returning clauses", () => {
24
+ expectTypeOf(db.deleteOne("post", {
25
+ where: {
26
+ tags: ["news", "tech"],
27
+ id: 1,
28
+ },
29
+ returning: ["tags", "id"],
30
+ })).resolves.toEqualTypeOf();
31
+ });
32
+ test("handles JSON fields in where and returning clauses", async () => {
33
+ // Test returning JSON fields
34
+ expectTypeOf(db.deleteOne("post", {
35
+ where: { id: 1 },
36
+ returning: ["metadata"],
37
+ })).resolves.toEqualTypeOf();
38
+ // Test user preferences JSON field
39
+ expectTypeOf(db.deleteOne("user", {
40
+ where: { id: 1 },
41
+ returning: ["preferences"],
42
+ })).resolves.toEqualTypeOf();
43
+ expectTypeOf(db.deleteOne("post", {
44
+ where: {
45
+ metadata: {
46
+ foo: "a",
47
+ bar: [
48
+ {
49
+ baz: "good",
50
+ quux: true,
51
+ },
52
+ ],
53
+ },
54
+ },
55
+ returning: ["metadata"],
56
+ })).resolves.toEqualTypeOf();
57
+ await db.deleteOne("post", {
58
+ where: {
59
+ metadata: {
60
+ // @ts-expect-error invalid enum value in JSON
61
+ foo: "invalid",
62
+ bar: [],
63
+ },
64
+ },
65
+ });
66
+ });
67
+ test("handles complex where clauses", () => {
68
+ expectTypeOf(db.deleteOne("post", {
69
+ where: {
70
+ id: { [$gt]: 100 },
71
+ [$or]: [
72
+ { title: { [$like]: "test%" } },
73
+ { tags: ["news", "tech"] },
74
+ ],
75
+ publishedAt: { [$is]: null },
76
+ },
77
+ returning: ["id"],
78
+ })).resolves.toEqualTypeOf();
79
+ });
80
+ test("enforces where clause is required", async () => {
81
+ // @ts-expect-error where clause is required
82
+ await db.deleteOne("post", {
83
+ returning: ["id"],
84
+ });
85
+ });
86
+ test("prevents invalid field names in where clause", async () => {
87
+ await db.deleteOne("post", {
88
+ where: {
89
+ // @ts-expect-error invalid field name
90
+ invalid: 1,
91
+ },
92
+ });
93
+ });
94
+ test("prevents invalid field names in returning clause", async () => {
95
+ await db.deleteOne("post", {
96
+ where: { id: 1 },
97
+ // @ts-expect-error invalid field name
98
+ returning: ["invalid"],
99
+ });
100
+ });
101
+ test("prevents invalid model names", async () => {
102
+ // @ts-expect-error invalid model name
103
+ await db.deleteOne("invalid", {
104
+ where: { id: 1 },
105
+ });
106
+ });
107
+ test("prevents invalid operator usage", async () => {
108
+ await db.deleteOne("post", {
109
+ where: {
110
+ // @ts-expect-error $like cannot be used with number
111
+ id: { [$like]: 100 },
112
+ },
113
+ });
114
+ });
115
+ test("handles enum fields in where and returning clauses", async () => {
116
+ // Test enum in where clause
117
+ expectTypeOf(db.deleteOne("user", {
118
+ where: { role: "admin" },
119
+ returning: ["role", "id"],
120
+ })).resolves.toEqualTypeOf();
121
+ // Test enum in JSON structure
122
+ expectTypeOf(db.deleteOne("post", {
123
+ where: {
124
+ metadata: {
125
+ foo: "a",
126
+ bar: [
127
+ {
128
+ baz: "good",
129
+ quux: true,
130
+ },
131
+ ],
132
+ },
133
+ },
134
+ returning: ["metadata"],
135
+ })).resolves.toEqualTypeOf();
136
+ await db.deleteOne("user", {
137
+ where: {
138
+ // @ts-expect-error invalid enum value for role
139
+ role: "superadmin",
140
+ },
141
+ });
142
+ await db.deleteOne("post", {
143
+ where: {
144
+ metadata: {
145
+ // @ts-expect-error invalid enum value in JSON metadata
146
+ foo: "invalid",
147
+ bar: [],
148
+ },
149
+ },
150
+ });
151
+ });
152
+ test("enforces field type constraints in where clause", async () => {
153
+ await db.deleteOne("post", {
154
+ where: {
155
+ // @ts-expect-error id must be number
156
+ id: "1",
157
+ },
158
+ });
159
+ await db.deleteOne("post", {
160
+ where: {
161
+ // @ts-expect-error tags must be string[]
162
+ tags: "tag1",
163
+ },
164
+ });
165
+ await db.deleteOne("user", {
166
+ where: {
167
+ // @ts-expect-error role must be "user" | "admin"
168
+ role: "superuser",
169
+ },
170
+ });
171
+ });
172
+ test("returned objects are deeply readonly", async () => {
173
+ const result = await db.deleteOne("post", {
174
+ where: { id: 1 },
175
+ returning: ["metadata"],
176
+ });
177
+ expectTypeOf(result).toEqualTypeOf();
178
+ });
179
+ });
@@ -0,0 +1 @@
1
+ export {};