@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,163 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { sql } from "@casekit/sql";
3
+ import { unindent } from "@casekit/unindent";
4
+ import { columnName, joinClause, orderByColumn, selectColumn, setClause, sqlValue, tableName, unnestPk, } from "./util.js";
5
+ describe("SQL utility functions", () => {
6
+ test("tableName should format table identifier correctly", () => {
7
+ const table = {
8
+ schema: "public",
9
+ name: "users",
10
+ alias: "u",
11
+ model: "user",
12
+ };
13
+ expect(tableName(table).text).toBe('"public"."users" AS "u"');
14
+ });
15
+ test("columnName should format column identifier correctly", () => {
16
+ const column = { table: "users", name: "id" };
17
+ expect(columnName(column).text).toBe('"users"."id"');
18
+ });
19
+ test("selectColumn should format column with alias", () => {
20
+ const column = {
21
+ table: "users",
22
+ name: "first_name",
23
+ alias: "name",
24
+ path: [],
25
+ };
26
+ expect(selectColumn(column).text).toBe('"users"."first_name" AS "name"');
27
+ });
28
+ test("sqlValue should create typed value", () => {
29
+ const typeValue = sqlValue("uuid");
30
+ expect(typeValue("123").text).toBe("$1::uuid");
31
+ });
32
+ test("unnestPk should format primary key array correctly", () => {
33
+ const pk = {
34
+ column: "id",
35
+ type: "uuid",
36
+ values: ["123", "456"],
37
+ };
38
+ expect(unnestPk(pk).text).toBe('UNNEST(ARRAY[$1::uuid, $2::uuid]) AS "id"');
39
+ });
40
+ test("joinClause should format INNER JOIN correctly for N:1 relation", () => {
41
+ const join = {
42
+ type: "INNER",
43
+ path: ["author"],
44
+ relation: "author",
45
+ table: {
46
+ schema: "public",
47
+ name: "users",
48
+ alias: "u",
49
+ model: "user",
50
+ },
51
+ columns: [
52
+ {
53
+ from: { table: "p", name: "author_id" },
54
+ to: { table: "u", name: "id" },
55
+ },
56
+ ],
57
+ };
58
+ expect(joinClause(join).pretty).toBe('JOIN "public"."users" AS "u" ON "p"."author_id" = "u"."id"');
59
+ });
60
+ test("joinClause should format LEFT JOIN correctly for N:1 relation", () => {
61
+ const join = {
62
+ type: "LEFT",
63
+ path: ["author"],
64
+ relation: "author",
65
+ table: {
66
+ schema: "public",
67
+ name: "users",
68
+ alias: "u",
69
+ model: "user",
70
+ },
71
+ columns: [
72
+ {
73
+ from: { table: "p", name: "author_id" },
74
+ to: { table: "u", name: "id" },
75
+ },
76
+ ],
77
+ };
78
+ expect(joinClause(join).pretty).toBe('LEFT JOIN "public"."users" AS "u" ON "p"."author_id" = "u"."id"');
79
+ });
80
+ test("joinClause should format LEFT JOIN correctly for N:1 relation with compound key", () => {
81
+ const join = {
82
+ type: "LEFT",
83
+ relation: "organization",
84
+ path: ["organization"],
85
+ table: {
86
+ schema: "public",
87
+ name: "organizations",
88
+ alias: "o",
89
+ model: "organization",
90
+ },
91
+ columns: [
92
+ {
93
+ from: { table: "u", name: "org_id" },
94
+ to: { table: "o", name: "id" },
95
+ },
96
+ {
97
+ from: { table: "u", name: "org_type" },
98
+ to: { table: "o", name: "type" },
99
+ },
100
+ ],
101
+ };
102
+ expect(joinClause(join).pretty).toBe(unindent `
103
+ LEFT JOIN "public"."organizations" AS "o" ON "u"."org_id" = "o"."id"
104
+ AND "u"."org_type" = "o"."type"
105
+ `);
106
+ });
107
+ test("joinClause should include where clause when provided for N:1 relation", () => {
108
+ const join = {
109
+ type: "LEFT",
110
+ relation: "author",
111
+ path: ["author"],
112
+ table: {
113
+ schema: "public",
114
+ name: "users",
115
+ alias: "u",
116
+ model: "user",
117
+ },
118
+ columns: [
119
+ {
120
+ from: { table: "p", name: "author_id" },
121
+ to: { table: "u", name: "id" },
122
+ },
123
+ ],
124
+ where: sql `"u"."deleted_at" IS NULL`,
125
+ };
126
+ expect(joinClause(join).pretty).toBe(unindent `
127
+ LEFT JOIN "public"."users" AS "u" ON "p"."author_id" = "u"."id"
128
+ AND "u"."deleted_at" IS NULL
129
+ `);
130
+ });
131
+ test("orderByColumn should format ASC order correctly", () => {
132
+ const orderBy = {
133
+ column: { table: "users", name: "created_at" },
134
+ direction: "ASC",
135
+ };
136
+ expect(orderByColumn(orderBy).pretty).toBe('"users"."created_at" ASC');
137
+ });
138
+ test("orderByColumn should format DESC order correctly", () => {
139
+ const orderBy = {
140
+ column: { table: "posts", name: "likes" },
141
+ direction: "DESC",
142
+ };
143
+ expect(orderByColumn(orderBy).pretty).toBe('"posts"."likes" DESC');
144
+ });
145
+ });
146
+ describe("setClause", () => {
147
+ test("setClause should format column and value correctly", () => {
148
+ const pair = ["first_name", "John"];
149
+ expect(setClause(pair).text).toBe('"first_name" = $1');
150
+ });
151
+ test("setClause should handle numbers", () => {
152
+ const pair = ["age", 25];
153
+ expect(setClause(pair).text).toBe('"age" = $1');
154
+ });
155
+ test("setClause should handle null values", () => {
156
+ const pair = ["deleted_at", null];
157
+ expect(setClause(pair).text).toBe('"deleted_at" = NULL');
158
+ });
159
+ test("setClause should handle boolean values", () => {
160
+ const pair = ["is_active", true];
161
+ expect(setClause(pair).text).toBe('"is_active" = TRUE');
162
+ });
163
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,304 @@
1
+ import pg from "pg";
2
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
3
+ import { normalizeConfig } from "@casekit/orm2-config";
4
+ import { models } from "@casekit/orm2-fixtures";
5
+ import { sql } from "@casekit/sql";
6
+ import { Connection, Transaction } from "../connection.js";
7
+ import { mockLogger } from "./util/logger.js";
8
+ describe("Connection", () => {
9
+ describe("without connection pooling", () => {
10
+ const logger = mockLogger();
11
+ let connection;
12
+ beforeEach(() => {
13
+ logger.clear();
14
+ connection = new Connection(normalizeConfig({
15
+ models: models,
16
+ pool: false,
17
+ logger: logger,
18
+ }));
19
+ });
20
+ afterEach(async () => {
21
+ if (connection.open) {
22
+ await connection.close();
23
+ }
24
+ });
25
+ test("opening and closing the connection", async () => {
26
+ await connection.connect();
27
+ expect(connection.open).toBe(true);
28
+ await connection.close();
29
+ expect(connection.open).toBe(false);
30
+ });
31
+ test("warning on trying to connect twice", async () => {
32
+ await connection.connect();
33
+ await connection.connect();
34
+ expect(logger.logs.warn[0]?.message).toEqual("Tried to connect, but connection is already open");
35
+ });
36
+ test("error on failing to connect", async () => {
37
+ const connection = new Connection(normalizeConfig({
38
+ models: models,
39
+ connection: {
40
+ user: "nonexistent",
41
+ password: "nonexistent",
42
+ database: "nonexistent",
43
+ host: "nonexistent",
44
+ port: 54321,
45
+ },
46
+ pool: false,
47
+ logger,
48
+ }));
49
+ await expect(connection.connect()).rejects.toThrowError();
50
+ expect(logger.logs.error[0]?.message).toEqual("Error connecting to database");
51
+ });
52
+ test("warning on trying to close twice", async () => {
53
+ await connection.connect();
54
+ await connection.close();
55
+ await connection.close();
56
+ expect(logger.logs.warn[0]?.message).toEqual("Tried to close connection, but it is already closed");
57
+ });
58
+ test("running a query", async () => {
59
+ await connection.connect();
60
+ const result = await connection.query(sql `SELECT ${1}::int as num`);
61
+ expect(result.rows[0]["num"]).toBe(1);
62
+ });
63
+ test("error on trying to run query without connecting", async () => {
64
+ await expect(connection.query(sql `SELECT ${1}::int as num`)).rejects.toThrowError("Tried to run query but not connected");
65
+ });
66
+ });
67
+ describe("with connection pooling", () => {
68
+ const logger = mockLogger();
69
+ let connection;
70
+ beforeEach(() => {
71
+ logger.clear();
72
+ connection = new Connection(normalizeConfig({
73
+ models: models,
74
+ pool: true,
75
+ logger,
76
+ }));
77
+ });
78
+ afterEach(async () => {
79
+ if (connection.open) {
80
+ await connection.close();
81
+ }
82
+ });
83
+ test("opening and closing the connection", async () => {
84
+ await connection.connect();
85
+ expect(connection.open).toBe(true);
86
+ await connection.close();
87
+ expect(connection.open).toBe(false);
88
+ });
89
+ test("warning on trying to connect twice", async () => {
90
+ await connection.connect();
91
+ await connection.connect();
92
+ expect(logger.logs.warn[0]?.message).toEqual("Tried to connect, but connection is already open");
93
+ });
94
+ test("warning on trying to close twice", async () => {
95
+ await connection.connect();
96
+ await connection.close();
97
+ await connection.close();
98
+ expect(logger.logs.warn[0]?.message).toEqual("Tried to close connection, but it is already closed");
99
+ });
100
+ test("running a query", async () => {
101
+ await connection.connect();
102
+ const result = await connection.query(sql `SELECT ${1}::int as num`);
103
+ expect(result.rows[0]["num"]).toBe(1);
104
+ });
105
+ });
106
+ });
107
+ describe("Transaction", () => {
108
+ describe("without connection pooling", () => {
109
+ const logger = mockLogger();
110
+ let connection;
111
+ let transaction;
112
+ beforeEach(async () => {
113
+ logger.clear();
114
+ connection = new Connection(normalizeConfig({
115
+ models: models,
116
+ pool: false,
117
+ logger,
118
+ }));
119
+ await connection.connect();
120
+ await connection.query(sql `
121
+ CREATE TABLE IF NOT EXISTS transaction_test_table (id int);
122
+ TRUNCATE transaction_test_table
123
+ `);
124
+ transaction = await connection.startTransaction();
125
+ });
126
+ afterEach(async () => {
127
+ await connection.query(sql `DROP TABLE IF EXISTS transaction_test_table`);
128
+ if (transaction.open) {
129
+ await transaction.rollback();
130
+ }
131
+ if (connection.open) {
132
+ await connection.close();
133
+ }
134
+ });
135
+ test("trying to start a transaction before connecting", async () => {
136
+ const connection = new Connection(normalizeConfig({
137
+ models: models,
138
+ pool: false,
139
+ }));
140
+ await expect(() => connection.startTransaction()).rejects.toThrowError("Tried to start transaction but not connected");
141
+ });
142
+ test("committing a transaction", async () => {
143
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
144
+ await transaction.commit();
145
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
146
+ expect(result.rows[0]["id"]).toBe(1);
147
+ });
148
+ test("trying to connect while in a transaction", async () => {
149
+ const tx = await connection.startTransaction();
150
+ await expect(() => tx.connect()).rejects.toThrowError("Cannot connect in transaction - already connected");
151
+ });
152
+ test("trying to close while in a transaction", async () => {
153
+ const tx = await connection.startTransaction();
154
+ await expect(() => tx.close()).rejects.toThrowError("Cannot close connection while in transaction");
155
+ });
156
+ test("trying to open a nested transaction before transaction has been opened", async () => {
157
+ const tx = new Transaction(normalizeConfig({
158
+ models: models,
159
+ pool: false,
160
+ }), new pg.Client());
161
+ await expect(tx.startTransaction()).rejects.toThrowError("Tried to open nested transaction but parent transaction is closed");
162
+ });
163
+ test("rolling back transaction", async () => {
164
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
165
+ await transaction.rollback();
166
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
167
+ expect(result.rows.length).toBe(0);
168
+ });
169
+ test("error on trying to commit twice", async () => {
170
+ await transaction.commit();
171
+ await expect(transaction.commit()).rejects.toThrowError("Tried to commit transaction but it is closed");
172
+ });
173
+ test("commiting a nested transaction then rolling back the parent transaction", async () => {
174
+ const nestedTx = await transaction.startTransaction();
175
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
176
+ await nestedTx.commit();
177
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
178
+ expect(innerResult.rows[0]["id"]).toBe(1);
179
+ await transaction.rollback();
180
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
181
+ expect(outerResult.rows.length).toBe(0);
182
+ });
183
+ test("commiting a nested transaction then committing the parent transaction", async () => {
184
+ const nestedTx = await transaction.startTransaction();
185
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
186
+ await nestedTx.commit();
187
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
188
+ expect(innerResult.rows[0]["id"]).toBe(1);
189
+ await transaction.commit();
190
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
191
+ expect(outerResult.rows[0]["id"]).toBe(1);
192
+ });
193
+ test("rolling back the nested transaction but committing the parent transaction", async () => {
194
+ const nestedTx = await transaction.startTransaction();
195
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
196
+ await nestedTx.rollback();
197
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
198
+ expect(innerResult.rows.length).toBe(0);
199
+ await transaction.commit();
200
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
201
+ expect(outerResult.rows.length).toBe(0);
202
+ });
203
+ test("rolling back on error", async () => {
204
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (2)`);
205
+ await expect(transaction.query(sql `SELECT * FROM non_existent_table`)).rejects.toThrowError('relation "non_existent_table" does not exist');
206
+ expect(logger.logs.error[0]?.message).toEqual("Error running query");
207
+ expect(logger.logs.error[1]?.message).toEqual("Rolling back transaction due to error");
208
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
209
+ expect(result.rows.length).toBe(0);
210
+ });
211
+ });
212
+ describe("with connection pooling", () => {
213
+ const logger = mockLogger();
214
+ let connection;
215
+ let transaction;
216
+ beforeEach(async () => {
217
+ logger.clear();
218
+ connection = new Connection(normalizeConfig({
219
+ models: models,
220
+ pool: true,
221
+ logger,
222
+ }));
223
+ await connection.connect();
224
+ await connection.query(sql `
225
+ CREATE TABLE IF NOT EXISTS transaction_test_table (id int);
226
+ TRUNCATE transaction_test_table
227
+ `);
228
+ transaction = await connection.startTransaction();
229
+ });
230
+ afterEach(async () => {
231
+ if (transaction.open) {
232
+ await transaction.rollback();
233
+ }
234
+ if (connection.open) {
235
+ await connection.query(sql `DROP TABLE IF EXISTS transaction_test_table`);
236
+ await connection.close();
237
+ }
238
+ });
239
+ test("committing a transaction", async () => {
240
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
241
+ await transaction.commit();
242
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
243
+ expect(result.rows[0]["id"]).toBe(1);
244
+ });
245
+ test("rolling back transaction", async () => {
246
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
247
+ await transaction.rollback();
248
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
249
+ expect(result.rows.length).toBe(0);
250
+ });
251
+ test("error on trying to commit twice", async () => {
252
+ await transaction.commit();
253
+ await expect(transaction.commit()).rejects.toThrowError("Tried to commit transaction but it is closed");
254
+ });
255
+ test("commiting a nested transaction then rolling back the parent transaction", async () => {
256
+ const nestedTx = await transaction.startTransaction();
257
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
258
+ await nestedTx.commit();
259
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
260
+ expect(innerResult.rows[0]["id"]).toBe(1);
261
+ await transaction.rollback();
262
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
263
+ expect(outerResult.rows.length).toBe(0);
264
+ });
265
+ test("commiting a nested transaction then committing the parent transaction", async () => {
266
+ const nestedTx = await transaction.startTransaction();
267
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
268
+ await nestedTx.commit();
269
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
270
+ expect(innerResult.rows[0]["id"]).toBe(1);
271
+ await transaction.commit();
272
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
273
+ expect(outerResult.rows[0]["id"]).toBe(1);
274
+ });
275
+ test("rolling back the nested transaction but committing the parent transaction", async () => {
276
+ const nestedTx = await transaction.startTransaction();
277
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (1)`);
278
+ await nestedTx.rollback();
279
+ const innerResult = await transaction.query(sql `SELECT * FROM transaction_test_table`);
280
+ expect(innerResult.rows.length).toBe(0);
281
+ await transaction.commit();
282
+ const outerResult = await connection.query(sql `SELECT * FROM transaction_test_table`);
283
+ expect(outerResult.rows.length).toBe(0);
284
+ });
285
+ test("rolling back on error", async () => {
286
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (2)`);
287
+ await expect(transaction.query(sql `SELECT * FROM non_existent_table`)).rejects.toThrowError('relation "non_existent_table" does not exist');
288
+ expect(logger.logs.error[0]?.message).toEqual("Error running query");
289
+ const result = await connection.query(sql `SELECT * FROM transaction_test_table`);
290
+ expect(result.rows.length).toBe(0);
291
+ });
292
+ test("rolling back nested transaction on error", async () => {
293
+ const nestedTx = await transaction.startTransaction();
294
+ await nestedTx.query(sql `INSERT INTO transaction_test_table VALUES (2)`);
295
+ await expect(nestedTx.query(sql `SELECT * FROM non_existent_table`)).rejects.toThrowError('relation "non_existent_table" does not exist');
296
+ expect(logger.logs.error[0]?.message).toEqual("Error running query");
297
+ expect(logger.logs.error[1]?.message).toEqual("Rolling back transaction due to error");
298
+ await transaction.query(sql `INSERT INTO transaction_test_table VALUES (7)`);
299
+ const result = await transaction.query(sql `SELECT * FROM transaction_test_table`);
300
+ expect(result.rows.length).toBe(1);
301
+ expect(result.rows[0]["id"]).toBe(7);
302
+ });
303
+ });
304
+ });
@@ -0,0 +1 @@
1
+ export {};