neoorm 0.8.0 → 0.8.2

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 (380) hide show
  1. package/README.md +13 -6
  2. package/dist/bin/neoorm.d.ts +1 -1
  3. package/dist/bin/neoorm.d.ts.map +1 -1
  4. package/dist/bin/neoorm.js +148 -75
  5. package/dist/bin/neoorm.js.map +1 -1
  6. package/dist/codegen/diff-manifest.d.ts.map +1 -1
  7. package/dist/codegen/diff-manifest.js +106 -4
  8. package/dist/codegen/diff-manifest.js.map +1 -1
  9. package/dist/codegen/generate-summary.d.ts +5 -1
  10. package/dist/codegen/generate-summary.d.ts.map +1 -1
  11. package/dist/codegen/generate-summary.js +10 -1
  12. package/dist/codegen/generate-summary.js.map +1 -1
  13. package/dist/codegen/generate.d.ts +24 -4
  14. package/dist/codegen/generate.d.ts.map +1 -1
  15. package/dist/codegen/generate.js +150 -13
  16. package/dist/codegen/generate.js.map +1 -1
  17. package/dist/codegen/manifest-relations.d.ts +2 -0
  18. package/dist/codegen/manifest-relations.d.ts.map +1 -1
  19. package/dist/codegen/manifest-relations.js +2 -1
  20. package/dist/codegen/manifest-relations.js.map +1 -1
  21. package/dist/codegen/schema-to-manifest.d.ts +1 -1
  22. package/dist/codegen/schema-to-manifest.d.ts.map +1 -1
  23. package/dist/codegen/schema-to-manifest.js +349 -29
  24. package/dist/codegen/schema-to-manifest.js.map +1 -1
  25. package/dist/codegen/validation/emit-elysia.d.ts +4 -0
  26. package/dist/codegen/validation/emit-elysia.d.ts.map +1 -0
  27. package/dist/codegen/validation/emit-elysia.js +304 -0
  28. package/dist/codegen/validation/emit-elysia.js.map +1 -0
  29. package/dist/codegen/validation/emit-typebox.d.ts +4 -0
  30. package/dist/codegen/validation/emit-typebox.d.ts.map +1 -0
  31. package/dist/codegen/validation/emit-typebox.js +360 -0
  32. package/dist/codegen/validation/emit-typebox.js.map +1 -0
  33. package/dist/codegen/validation/emit-zod.d.ts +4 -0
  34. package/dist/codegen/validation/emit-zod.d.ts.map +1 -0
  35. package/dist/codegen/validation/emit-zod.js +288 -0
  36. package/dist/codegen/validation/emit-zod.js.map +1 -0
  37. package/dist/codegen/validation/from-manifest.d.ts +5 -0
  38. package/dist/codegen/validation/from-manifest.d.ts.map +1 -0
  39. package/dist/codegen/validation/from-manifest.js +284 -0
  40. package/dist/codegen/validation/from-manifest.js.map +1 -0
  41. package/dist/codegen/validation/infer.d.ts +47 -0
  42. package/dist/codegen/validation/infer.d.ts.map +1 -0
  43. package/dist/codegen/validation/infer.js +2 -0
  44. package/dist/codegen/validation/infer.js.map +1 -0
  45. package/dist/codegen/validation/json-generic-types.d.ts +7 -0
  46. package/dist/codegen/validation/json-generic-types.d.ts.map +1 -0
  47. package/dist/codegen/validation/json-generic-types.js +295 -0
  48. package/dist/codegen/validation/json-generic-types.js.map +1 -0
  49. package/dist/codegen/validation/types.d.ts +84 -0
  50. package/dist/codegen/validation/types.d.ts.map +1 -0
  51. package/dist/codegen/validation/types.js +6 -0
  52. package/dist/codegen/validation/types.js.map +1 -0
  53. package/dist/config.d.ts +8 -0
  54. package/dist/config.d.ts.map +1 -1
  55. package/dist/config.js +30 -0
  56. package/dist/config.js.map +1 -1
  57. package/dist/datasource-provider.d.ts +5 -1
  58. package/dist/datasource-provider.d.ts.map +1 -1
  59. package/dist/datasource-provider.js +21 -2
  60. package/dist/datasource-provider.js.map +1 -1
  61. package/dist/dialect/column-kind-support.d.ts +9 -0
  62. package/dist/dialect/column-kind-support.d.ts.map +1 -0
  63. package/dist/dialect/column-kind-support.js +25 -0
  64. package/dist/dialect/column-kind-support.js.map +1 -0
  65. package/dist/dialect/fk.d.ts +30 -1
  66. package/dist/dialect/fk.d.ts.map +1 -1
  67. package/dist/dialect/fk.js +113 -0
  68. package/dist/dialect/fk.js.map +1 -1
  69. package/dist/dialect/index.d.ts +6 -1
  70. package/dist/dialect/index.d.ts.map +1 -1
  71. package/dist/dialect/index.js +5 -0
  72. package/dist/dialect/index.js.map +1 -1
  73. package/dist/dialect/mariadb.d.ts +4 -0
  74. package/dist/dialect/mariadb.d.ts.map +1 -0
  75. package/dist/dialect/mariadb.js +15 -0
  76. package/dist/dialect/mariadb.js.map +1 -0
  77. package/dist/dialect/mariadb.test.d.ts +2 -0
  78. package/dist/dialect/mariadb.test.d.ts.map +1 -0
  79. package/dist/dialect/mariadb.test.js +151 -0
  80. package/dist/dialect/mariadb.test.js.map +1 -0
  81. package/dist/dialect/mysql-family.d.ts +14 -0
  82. package/dist/dialect/mysql-family.d.ts.map +1 -0
  83. package/dist/dialect/mysql-family.js +453 -0
  84. package/dist/dialect/mysql-family.js.map +1 -0
  85. package/dist/dialect/mysql.d.ts +6 -0
  86. package/dist/dialect/mysql.d.ts.map +1 -0
  87. package/dist/dialect/mysql.js +16 -0
  88. package/dist/dialect/mysql.js.map +1 -0
  89. package/dist/dialect/mysql.test.d.ts +2 -0
  90. package/dist/dialect/mysql.test.d.ts.map +1 -0
  91. package/dist/dialect/mysql.test.js +211 -0
  92. package/dist/dialect/mysql.test.js.map +1 -0
  93. package/dist/dialect/placeholders.d.ts +7 -0
  94. package/dist/dialect/placeholders.d.ts.map +1 -0
  95. package/dist/dialect/placeholders.js +18 -0
  96. package/dist/dialect/placeholders.js.map +1 -0
  97. package/dist/dialect/postgres.d.ts +2 -1
  98. package/dist/dialect/postgres.d.ts.map +1 -1
  99. package/dist/dialect/postgres.js +93 -30
  100. package/dist/dialect/postgres.js.map +1 -1
  101. package/dist/dialect/resolve.d.ts +13 -0
  102. package/dist/dialect/resolve.d.ts.map +1 -0
  103. package/dist/dialect/resolve.js +66 -0
  104. package/dist/dialect/resolve.js.map +1 -0
  105. package/dist/dialect/shared.d.ts +8 -1
  106. package/dist/dialect/shared.d.ts.map +1 -1
  107. package/dist/dialect/shared.js +37 -0
  108. package/dist/dialect/shared.js.map +1 -1
  109. package/dist/dialect/sqlite.d.ts.map +1 -1
  110. package/dist/dialect/sqlite.js +50 -18
  111. package/dist/dialect/sqlite.js.map +1 -1
  112. package/dist/dialect/sqlite.test.js +43 -1
  113. package/dist/dialect/sqlite.test.js.map +1 -1
  114. package/dist/dialect/types.d.ts +60 -3
  115. package/dist/dialect/types.d.ts.map +1 -1
  116. package/dist/docs/pages.d.ts.map +1 -1
  117. package/dist/docs/pages.js +5 -0
  118. package/dist/docs/pages.js.map +1 -1
  119. package/dist/docs/render.js +1 -1
  120. package/dist/index.d.ts +6 -3
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +5 -2
  123. package/dist/index.js.map +1 -1
  124. package/dist/init/scaffold.d.ts +2 -1
  125. package/dist/init/scaffold.d.ts.map +1 -1
  126. package/dist/init/scaffold.js.map +1 -1
  127. package/dist/init/templates.d.ts +3 -2
  128. package/dist/init/templates.d.ts.map +1 -1
  129. package/dist/init/templates.js +19 -9
  130. package/dist/init/templates.js.map +1 -1
  131. package/dist/introspect/group-fks.d.ts +24 -0
  132. package/dist/introspect/group-fks.d.ts.map +1 -0
  133. package/dist/introspect/group-fks.js +48 -0
  134. package/dist/introspect/group-fks.js.map +1 -0
  135. package/dist/introspect/mysql/to-manifest.d.ts +4 -0
  136. package/dist/introspect/mysql/to-manifest.d.ts.map +1 -0
  137. package/dist/introspect/mysql/to-manifest.js +317 -0
  138. package/dist/introspect/mysql/to-manifest.js.map +1 -0
  139. package/dist/introspect/pull.d.ts +1 -0
  140. package/dist/introspect/pull.d.ts.map +1 -1
  141. package/dist/introspect/pull.js +186 -9
  142. package/dist/introspect/pull.js.map +1 -1
  143. package/dist/introspect/queries.d.ts +11 -1
  144. package/dist/introspect/queries.d.ts.map +1 -1
  145. package/dist/introspect/queries.js +43 -12
  146. package/dist/introspect/queries.js.map +1 -1
  147. package/dist/introspect/sqlite/to-manifest.d.ts.map +1 -1
  148. package/dist/introspect/sqlite/to-manifest.js +99 -26
  149. package/dist/introspect/sqlite/to-manifest.js.map +1 -1
  150. package/dist/introspect/to-manifest.d.ts.map +1 -1
  151. package/dist/introspect/to-manifest.js +154 -28
  152. package/dist/introspect/to-manifest.js.map +1 -1
  153. package/dist/migrate/dev-lock.d.ts +15 -0
  154. package/dist/migrate/dev-lock.d.ts.map +1 -0
  155. package/dist/migrate/dev-lock.js +101 -0
  156. package/dist/migrate/dev-lock.js.map +1 -0
  157. package/dist/migrate/runner.d.ts.map +1 -1
  158. package/dist/migrate/runner.js +143 -51
  159. package/dist/migrate/runner.js.map +1 -1
  160. package/dist/plugins/builtin.d.ts +62 -12
  161. package/dist/plugins/builtin.d.ts.map +1 -1
  162. package/dist/plugins/builtin.js +378 -30
  163. package/dist/plugins/builtin.js.map +1 -1
  164. package/dist/plugins/index.d.ts +1 -0
  165. package/dist/plugins/index.d.ts.map +1 -1
  166. package/dist/plugins/index.js.map +1 -1
  167. package/dist/plugins/json/operators.d.ts.map +1 -1
  168. package/dist/plugins/json/operators.js +69 -3
  169. package/dist/plugins/json/operators.js.map +1 -1
  170. package/dist/plugins/postgis/columns.d.ts.map +1 -1
  171. package/dist/plugins/postgis/columns.js +52 -0
  172. package/dist/plugins/postgis/columns.js.map +1 -1
  173. package/dist/plugins/postgis/columns.test.js +13 -0
  174. package/dist/plugins/postgis/columns.test.js.map +1 -1
  175. package/dist/plugins/postgis/operators.d.ts.map +1 -1
  176. package/dist/plugins/postgis/operators.js +15 -3
  177. package/dist/plugins/postgis/operators.js.map +1 -1
  178. package/dist/plugins/types.d.ts +3 -0
  179. package/dist/plugins/types.d.ts.map +1 -1
  180. package/dist/runtime/client.d.ts +31 -4
  181. package/dist/runtime/client.d.ts.map +1 -1
  182. package/dist/runtime/client.js +131 -6
  183. package/dist/runtime/client.js.map +1 -1
  184. package/dist/runtime/driver.d.ts +2 -0
  185. package/dist/runtime/driver.d.ts.map +1 -1
  186. package/dist/runtime/driver.js +12 -0
  187. package/dist/runtime/driver.js.map +1 -1
  188. package/dist/runtime/error-hints.d.ts.map +1 -1
  189. package/dist/runtime/error-hints.js +37 -10
  190. package/dist/runtime/error-hints.js.map +1 -1
  191. package/dist/runtime/executor.d.ts +1 -0
  192. package/dist/runtime/executor.d.ts.map +1 -1
  193. package/dist/runtime/executor.js +7 -1
  194. package/dist/runtime/executor.js.map +1 -1
  195. package/dist/runtime/mariadb-driver.d.ts +25 -0
  196. package/dist/runtime/mariadb-driver.d.ts.map +1 -0
  197. package/dist/runtime/mariadb-driver.js +103 -0
  198. package/dist/runtime/mariadb-driver.js.map +1 -0
  199. package/dist/runtime/mysql-driver.d.ts +25 -0
  200. package/dist/runtime/mysql-driver.d.ts.map +1 -0
  201. package/dist/runtime/mysql-driver.js +101 -0
  202. package/dist/runtime/mysql-driver.js.map +1 -0
  203. package/dist/runtime/mysql-error.d.ts +15 -0
  204. package/dist/runtime/mysql-error.d.ts.map +1 -0
  205. package/dist/runtime/mysql-error.js +119 -0
  206. package/dist/runtime/mysql-error.js.map +1 -0
  207. package/dist/runtime/mysql-family-pool.d.ts +50 -0
  208. package/dist/runtime/mysql-family-pool.d.ts.map +1 -0
  209. package/dist/runtime/mysql-family-pool.js +52 -0
  210. package/dist/runtime/mysql-family-pool.js.map +1 -0
  211. package/dist/runtime/mysql-family-pool.test.d.ts +2 -0
  212. package/dist/runtime/mysql-family-pool.test.d.ts.map +1 -0
  213. package/dist/runtime/mysql-family-pool.test.js +169 -0
  214. package/dist/runtime/mysql-family-pool.test.js.map +1 -0
  215. package/dist/runtime/mysql-placeholders.d.ts +18 -0
  216. package/dist/runtime/mysql-placeholders.d.ts.map +1 -0
  217. package/dist/runtime/mysql-placeholders.js +133 -0
  218. package/dist/runtime/mysql-placeholders.js.map +1 -0
  219. package/dist/runtime/mysql-placeholders.test.d.ts +2 -0
  220. package/dist/runtime/mysql-placeholders.test.d.ts.map +1 -0
  221. package/dist/runtime/mysql-placeholders.test.js +33 -0
  222. package/dist/runtime/mysql-placeholders.test.js.map +1 -0
  223. package/dist/runtime/query/aggregate.d.ts.map +1 -1
  224. package/dist/runtime/query/aggregate.js +3 -3
  225. package/dist/runtime/query/aggregate.js.map +1 -1
  226. package/dist/runtime/query/compile-aggregate.d.ts +1 -1
  227. package/dist/runtime/query/compile-aggregate.d.ts.map +1 -1
  228. package/dist/runtime/query/compile-aggregate.js +33 -28
  229. package/dist/runtime/query/compile-aggregate.js.map +1 -1
  230. package/dist/runtime/query/compile-where.d.ts +9 -9
  231. package/dist/runtime/query/compile-where.d.ts.map +1 -1
  232. package/dist/runtime/query/compile-where.js +108 -76
  233. package/dist/runtime/query/compile-where.js.map +1 -1
  234. package/dist/runtime/query/compile-write.d.ts +9 -9
  235. package/dist/runtime/query/compile-write.d.ts.map +1 -1
  236. package/dist/runtime/query/compile-write.js +77 -63
  237. package/dist/runtime/query/compile-write.js.map +1 -1
  238. package/dist/runtime/query/count.d.ts.map +1 -1
  239. package/dist/runtime/query/count.js +4 -1
  240. package/dist/runtime/query/count.js.map +1 -1
  241. package/dist/runtime/query/create.d.ts.map +1 -1
  242. package/dist/runtime/query/create.js +38 -12
  243. package/dist/runtime/query/create.js.map +1 -1
  244. package/dist/runtime/query/cursor.d.ts +1 -1
  245. package/dist/runtime/query/cursor.d.ts.map +1 -1
  246. package/dist/runtime/query/cursor.js +6 -7
  247. package/dist/runtime/query/cursor.js.map +1 -1
  248. package/dist/runtime/query/delete.d.ts.map +1 -1
  249. package/dist/runtime/query/delete.js +41 -15
  250. package/dist/runtime/query/delete.js.map +1 -1
  251. package/dist/runtime/query/execute.d.ts +1 -0
  252. package/dist/runtime/query/execute.d.ts.map +1 -1
  253. package/dist/runtime/query/execute.js +23 -8
  254. package/dist/runtime/query/execute.js.map +1 -1
  255. package/dist/runtime/query/find-or-create.d.ts +1 -1
  256. package/dist/runtime/query/find-or-create.d.ts.map +1 -1
  257. package/dist/runtime/query/find-or-create.js +16 -8
  258. package/dist/runtime/query/find-or-create.js.map +1 -1
  259. package/dist/runtime/query/find.d.ts +2 -0
  260. package/dist/runtime/query/find.d.ts.map +1 -1
  261. package/dist/runtime/query/find.js +116 -68
  262. package/dist/runtime/query/find.js.map +1 -1
  263. package/dist/runtime/query/group-by.d.ts.map +1 -1
  264. package/dist/runtime/query/group-by.js.map +1 -1
  265. package/dist/runtime/query/mutation-returning.d.ts +10 -0
  266. package/dist/runtime/query/mutation-returning.d.ts.map +1 -0
  267. package/dist/runtime/query/mutation-returning.js +85 -0
  268. package/dist/runtime/query/mutation-returning.js.map +1 -0
  269. package/dist/runtime/query/paginate.d.ts.map +1 -1
  270. package/dist/runtime/query/paginate.js +3 -3
  271. package/dist/runtime/query/paginate.js.map +1 -1
  272. package/dist/runtime/query/projection.d.ts.map +1 -1
  273. package/dist/runtime/query/projection.js +1 -1
  274. package/dist/runtime/query/projection.js.map +1 -1
  275. package/dist/runtime/query/relation-join.d.ts +5 -0
  276. package/dist/runtime/query/relation-join.d.ts.map +1 -0
  277. package/dist/runtime/query/relation-join.js +26 -0
  278. package/dist/runtime/query/relation-join.js.map +1 -0
  279. package/dist/runtime/query/relation-planner.d.ts +1 -1
  280. package/dist/runtime/query/relation-planner.d.ts.map +1 -1
  281. package/dist/runtime/query/relation-planner.js +72 -58
  282. package/dist/runtime/query/relation-planner.js.map +1 -1
  283. package/dist/runtime/query/relation-writes.d.ts +2 -2
  284. package/dist/runtime/query/relation-writes.d.ts.map +1 -1
  285. package/dist/runtime/query/relation-writes.js +272 -116
  286. package/dist/runtime/query/relation-writes.js.map +1 -1
  287. package/dist/runtime/query/table-index.d.ts +1 -1
  288. package/dist/runtime/query/table-index.d.ts.map +1 -1
  289. package/dist/runtime/query/table-index.js +17 -10
  290. package/dist/runtime/query/table-index.js.map +1 -1
  291. package/dist/runtime/query/unique.d.ts +3 -0
  292. package/dist/runtime/query/unique.d.ts.map +1 -1
  293. package/dist/runtime/query/unique.js +26 -6
  294. package/dist/runtime/query/unique.js.map +1 -1
  295. package/dist/runtime/query/unique.test.js +110 -7
  296. package/dist/runtime/query/unique.test.js.map +1 -1
  297. package/dist/runtime/query/update.d.ts.map +1 -1
  298. package/dist/runtime/query/update.js +89 -23
  299. package/dist/runtime/query/update.js.map +1 -1
  300. package/dist/runtime/query/updated-at.js +2 -2
  301. package/dist/runtime/query/updated-at.js.map +1 -1
  302. package/dist/runtime/query/upsert.d.ts.map +1 -1
  303. package/dist/runtime/query/upsert.js +29 -5
  304. package/dist/runtime/query/upsert.js.map +1 -1
  305. package/dist/runtime/sqlite-open.js +1 -1
  306. package/dist/runtime/sqlite-open.js.map +1 -1
  307. package/dist/runtime/transaction.d.ts +1 -0
  308. package/dist/runtime/transaction.d.ts.map +1 -1
  309. package/dist/runtime/transaction.js +8 -0
  310. package/dist/runtime/transaction.js.map +1 -1
  311. package/dist/runtime/types.d.ts +10 -2
  312. package/dist/runtime/types.d.ts.map +1 -1
  313. package/dist/schema/column-constraints.d.ts +26 -0
  314. package/dist/schema/column-constraints.d.ts.map +1 -0
  315. package/dist/schema/column-constraints.js +143 -0
  316. package/dist/schema/column-constraints.js.map +1 -0
  317. package/dist/schema/column.d.ts +92 -3
  318. package/dist/schema/column.d.ts.map +1 -1
  319. package/dist/schema/column.js +17 -11
  320. package/dist/schema/column.js.map +1 -1
  321. package/dist/schema/index.d.ts +9 -6
  322. package/dist/schema/index.d.ts.map +1 -1
  323. package/dist/schema/index.js +8 -2
  324. package/dist/schema/index.js.map +1 -1
  325. package/dist/schema/json-column.d.ts +9 -0
  326. package/dist/schema/json-column.d.ts.map +1 -0
  327. package/dist/schema/json-column.js +11 -0
  328. package/dist/schema/json-column.js.map +1 -0
  329. package/dist/schema/many-to-many.d.ts +1 -1
  330. package/dist/schema/many-to-many.d.ts.map +1 -1
  331. package/dist/schema/nested-relation-types.d.ts +10 -9
  332. package/dist/schema/nested-relation-types.d.ts.map +1 -1
  333. package/dist/schema/relation-types.d.ts +80 -19
  334. package/dist/schema/relation-types.d.ts.map +1 -1
  335. package/dist/schema/relation.d.ts +11 -1
  336. package/dist/schema/relation.d.ts.map +1 -1
  337. package/dist/schema/relation.js +6 -0
  338. package/dist/schema/relation.js.map +1 -1
  339. package/dist/schema/table.d.ts +74 -11
  340. package/dist/schema/table.d.ts.map +1 -1
  341. package/dist/schema/table.js +93 -7
  342. package/dist/schema/table.js.map +1 -1
  343. package/dist/schema/types.d.ts +7 -6
  344. package/dist/schema/types.d.ts.map +1 -1
  345. package/dist/sql/builder.d.ts +13 -3
  346. package/dist/sql/builder.d.ts.map +1 -1
  347. package/dist/sql/builder.js +155 -5
  348. package/dist/sql/builder.js.map +1 -1
  349. package/dist/sql/index.d.ts +1 -0
  350. package/dist/sql/index.d.ts.map +1 -1
  351. package/dist/sql/index.js.map +1 -1
  352. package/dist/sql/qualify-tables.d.ts +15 -0
  353. package/dist/sql/qualify-tables.d.ts.map +1 -0
  354. package/dist/sql/qualify-tables.js +206 -0
  355. package/dist/sql/qualify-tables.js.map +1 -0
  356. package/dist/sql/template.d.ts +5 -0
  357. package/dist/sql/template.d.ts.map +1 -1
  358. package/dist/sql/template.js +23 -3
  359. package/dist/sql/template.js.map +1 -1
  360. package/dist/utils/load-ts.d.ts +2 -1
  361. package/dist/utils/load-ts.d.ts.map +1 -1
  362. package/dist/utils/load-ts.js +13 -1
  363. package/dist/utils/load-ts.js.map +1 -1
  364. package/docs/cli.md +4 -4
  365. package/docs/configuration.md +12 -5
  366. package/docs/elysia.md +131 -0
  367. package/docs/errors.md +1 -1
  368. package/docs/examples.md +4 -2
  369. package/docs/getting-started.md +28 -2
  370. package/docs/mariadb.md +149 -0
  371. package/docs/migrations.md +5 -3
  372. package/docs/mysql.md +134 -0
  373. package/docs/plugins.md +2 -0
  374. package/docs/queries.md +14 -11
  375. package/docs/relations.md +19 -4
  376. package/docs/schema.md +100 -9
  377. package/docs/sqlite.md +14 -2
  378. package/docs/typebox.md +139 -0
  379. package/docs/zod.md +128 -0
  380. package/package.json +33 -3
@@ -1,11 +1,13 @@
1
- import { postgresDialect, quoteIdentifier, tableRef, } from "../../dialect/postgres.js";
1
+ import { parseFkTarget, relationFkPairs } from "../../dialect/fk.js";
2
+ import { joinPlaceholders } from "../../dialect/placeholders.js";
3
+ import { postgresDialect } from "../../dialect/postgres.js";
2
4
  import { compileError } from "../compile-error.js";
3
5
  import { QueryErrorCode } from "../error-codes.js";
4
6
  import { buildInsertManyQuery, buildInsertManyValueRows, dataToSqlValues, } from "./compile.js";
5
7
  import { runQuery } from "./execute.js";
6
- import { findOrCreatePk } from "./find-or-create.js";
8
+ import { findOrCreatePk, findOrCreateRecord } from "./find-or-create.js";
7
9
  import { findM2M, findRelation, tableOwnsFkColumn } from "./manifest-lookup.js";
8
- import { fillMissingPrimaryKeys, primaryKeySqlName, requireScalarPrimaryKey, rowScalarPkValue, targetRelationPkSql, } from "./primary-key.js";
10
+ import { fillMissingPrimaryKeys, primaryKeySqlName, primaryKeyTsNames, resolvePkWhere, targetRelationPkSql, } from "./primary-key.js";
9
11
  import { columnBySqlName, columnByTsName, getTableIndex, requireTable, requireTsColumn, } from "./table-index.js";
10
12
  const RELATION_WRITE_KEYS = [
11
13
  "delete",
@@ -56,31 +58,148 @@ function connectPkError(table, pkTsName, detail) {
56
58
  code: QueryErrorCode.missing_primary_key,
57
59
  tableAccessor: table.accessor,
58
60
  tableSqlName: table.sqlName,
59
- columnTsName: pkTsName,
61
+ ...(pkTsName !== undefined ? { columnTsName: pkTsName } : {}),
60
62
  });
61
63
  }
62
- function readConnectPk(item, pkTsName, table) {
63
- if (!item || typeof item !== "object" || Array.isArray(item)) {
64
- connectPkError(table, pkTsName, `Relation connect requires { ${pkTsName}: ... } for table "${table.accessor}"`);
64
+ function normalizeConnectPks(runtime, targetAccessor, value) {
65
+ const table = requireTable(runtime.manifest, targetAccessor, "select");
66
+ const tableIndex = getTableIndex(runtime.tableIndex, targetAccessor);
67
+ if (value == null || value === false)
68
+ return [];
69
+ const items = Array.isArray(value) ? value : [value];
70
+ return items.map((item) => {
71
+ if (!item || typeof item !== "object" || Array.isArray(item)) {
72
+ const pkNames = primaryKeyTsNames(table, tableIndex);
73
+ connectPkError(table, pkNames[0], `Relation connect requires { ${pkNames.join(", ")} } for table "${table.accessor}"`);
74
+ }
75
+ return resolvePkWhere(table, item, tableIndex);
76
+ });
77
+ }
78
+ function pkField(table, pk, tsName) {
79
+ const value = pk[tsName];
80
+ if (value == null) {
81
+ connectPkError(table, tsName, `Relation connect requires primary key "${tsName}" for table "${table.accessor}"`);
65
82
  }
66
- const id = item[pkTsName];
67
- if (id == null) {
68
- connectPkError(table, pkTsName, `Relation connect requires primary key "${pkTsName}" for table "${table.accessor}"`);
83
+ return value;
84
+ }
85
+ function assignOutgoingFkScalars(scalarData, rel, targetTable, targetIndex, record, nulls = false) {
86
+ for (const pair of relationFkPairs(rel)) {
87
+ if (nulls) {
88
+ scalarData[pair.fkColumn] = null;
89
+ continue;
90
+ }
91
+ const targetTs = columnBySqlName(targetIndex, targetTable, pair.targetColumn)
92
+ ?.tsName ??
93
+ columnByTsName(targetIndex, targetTable, pair.targetColumn)
94
+ ?.tsName ??
95
+ pair.targetColumn;
96
+ scalarData[pair.fkColumn] = pkField(targetTable, record, targetTs);
69
97
  }
70
- return String(id);
71
98
  }
72
- function normalizeIdList(value, pkTsName, table) {
73
- if (value == null || value === false)
74
- return [];
75
- if (Array.isArray(value)) {
76
- return value.map((item) => readConnectPk(item, pkTsName, table));
99
+ function childFkCreatePatch(rel, parentTable, parentRow, parentId) {
100
+ const assignment = inverseFkAssignments(rel, parentTable, parentRow, parentId);
101
+ const pairs = relationFkPairs(rel);
102
+ const patch = {};
103
+ for (let i = 0; i < pairs.length; i++) {
104
+ const pair = pairs[i];
105
+ if (!pair)
106
+ continue;
107
+ patch[pair.fkColumn] = assignment.values[i] ?? parentId;
77
108
  }
78
- return [readConnectPk(value, pkTsName, table)];
109
+ return patch;
79
110
  }
80
- function normalizeConnectIds(runtime, targetAccessor, value) {
81
- const table = requireTable(runtime.manifest, targetAccessor, "select");
82
- const { tsName } = requireScalarPrimaryKey(table, "connect", getTableIndex(runtime.tableIndex, targetAccessor));
83
- return normalizeIdList(value, tsName, table);
111
+ function inverseFkAssignments(rel, parentTable, parentRow, parentId) {
112
+ const pairs = relationFkPairs(rel);
113
+ const refs = rel.referencedSqlColumns && rel.referencedSqlColumns.length > 0
114
+ ? rel.referencedSqlColumns
115
+ : pairs.map((pair) => pair.targetColumn);
116
+ if (pairs.length <= 1) {
117
+ return {
118
+ sqlNames: [rel.fkSqlColumn],
119
+ values: [parentId],
120
+ };
121
+ }
122
+ const values = pairs.map((pair, i) => {
123
+ const ref = refs[i] ?? pair.targetColumn;
124
+ const col = parentTable.columns.find((item) => item.sqlName === ref || item.tsName === ref);
125
+ const value = parentRow?.[col?.tsName ?? ref];
126
+ return value ?? parentId;
127
+ });
128
+ return {
129
+ sqlNames: pairs.map((pair) => pair.fkSqlColumn),
130
+ values,
131
+ };
132
+ }
133
+ function fkTargetTsName(table, tableIndex, relation, throughFk) {
134
+ if (throughFk?.fkTarget) {
135
+ const { columnSql } = parseFkTarget(throughFk.fkTarget);
136
+ const col = columnBySqlName(tableIndex, table, columnSql) ??
137
+ columnByTsName(tableIndex, table, columnSql);
138
+ if (col)
139
+ return col.tsName;
140
+ }
141
+ const sql = targetRelationPkSql(table, relation);
142
+ const col = columnBySqlName(tableIndex, table, sql) ??
143
+ columnByTsName(tableIndex, table, sql);
144
+ if (col)
145
+ return col.tsName;
146
+ const names = primaryKeyTsNames(table, tableIndex);
147
+ const first = names[0];
148
+ if (!first) {
149
+ connectPkError(table, undefined, `No primary key defined for table "${table.accessor}"`);
150
+ }
151
+ return first;
152
+ }
153
+ function m2mOtherThroughColumn(runtime, m2m, parentAccessor) {
154
+ const throughTable = runtime.manifest.tables[m2m.throughAccessor];
155
+ if (!throughTable)
156
+ return undefined;
157
+ const throughIndex = getTableIndex(runtime.tableIndex, throughTable.accessor);
158
+ const isLeft = m2m.leftAccessor === parentAccessor;
159
+ const otherFkCol = isLeft ? m2m.rightFkColumn : m2m.leftFkColumn;
160
+ return columnBySqlName(throughIndex, throughTable, otherFkCol);
161
+ }
162
+ function m2mConnectFkValues(runtime, m2m, parentAccessor, targetAccessor, value) {
163
+ const pks = normalizeConnectPks(runtime, targetAccessor, value);
164
+ const targetTable = requireTable(runtime.manifest, targetAccessor, "select");
165
+ const targetIndex = getTableIndex(runtime.tableIndex, targetAccessor);
166
+ const throughFk = m2mOtherThroughColumn(runtime, m2m, parentAccessor);
167
+ const fkTs = fkTargetTsName(targetTable, targetIndex, undefined, throughFk);
168
+ return { pks, ids: extractFkValues(targetTable, pks, fkTs) };
169
+ }
170
+ function extractFkValues(table, pks, fkTsName) {
171
+ return pks.map((pk) => pkField(table, pk, fkTsName));
172
+ }
173
+ function sqlPkPredicate(dialect, table, tableIndex, pks, startParam) {
174
+ const tsNames = primaryKeyTsNames(table, tableIndex);
175
+ if (tsNames.length === 0 || pks.length === 0) {
176
+ connectPkError(table, undefined, `No primary key defined for table "${table.accessor}"`);
177
+ }
178
+ const quoted = tsNames.map((tsName) => {
179
+ const col = columnByTsName(tableIndex, table, tsName);
180
+ return dialect.quoteIdentifier(col?.sqlName ?? tsName);
181
+ });
182
+ if (tsNames.length === 1) {
183
+ const tsName = tsNames[0];
184
+ if (!tsName || !quoted[0]) {
185
+ connectPkError(table, tsName, `No primary key defined for table "${table.accessor}"`);
186
+ }
187
+ const placeholders = joinPlaceholders(dialect, pks.length, startParam);
188
+ return {
189
+ sql: `${quoted[0]} IN (${placeholders})`,
190
+ params: pks.map((pk) => pkField(table, pk, tsName)),
191
+ };
192
+ }
193
+ const params = [];
194
+ let index = startParam;
195
+ const groups = pks.map((pk) => {
196
+ const parts = tsNames.map((tsName, i) => {
197
+ params.push(pkField(table, pk, tsName));
198
+ return `${quoted[i]} = ${dialect.placeholder(index++)}`;
199
+ });
200
+ return `(${parts.join(" AND ")})`;
201
+ });
202
+ return { sql: `(${groups.join(" OR ")})`, params };
84
203
  }
85
204
  function normalizeCreateList(value) {
86
205
  if (!value)
@@ -109,10 +228,10 @@ export function splitScalarsAndRelationWrites(manifest, tableAccessor, table, da
109
228
  }
110
229
  return { scalarData, relationWrites };
111
230
  }
112
- export async function resolveConnectOrCreate(executor, runtime, targetAccessor, items) {
231
+ export async function resolveConnectOrCreate(executor, runtime, targetAccessor, items, fkTsName) {
113
232
  const ids = [];
114
233
  for (const item of items) {
115
- const id = await findOrCreatePk(executor, runtime, targetAccessor, item);
234
+ const id = await findOrCreatePk(executor, runtime, targetAccessor, item, fkTsName);
116
235
  ids.push(id);
117
236
  }
118
237
  return ids;
@@ -167,11 +286,11 @@ async function insertM2MLinks(executor, runtime, m2m, parentAccessor, parentId,
167
286
  const valueByKey = new Map(keys.map((key, i) => [key, values[i]]));
168
287
  return dataKeys.map((key) => valueByKey.get(key));
169
288
  });
170
- const { valueRows, values } = buildInsertManyValueRows(throughTable, dataKeys, rowValues, runtime.tableIndex);
289
+ const { valueRows, values } = buildInsertManyValueRows(throughTable, dataKeys, rowValues, runtime.tableIndex, dialect);
171
290
  const sql = buildInsertManyQuery(throughTable, dataKeys, valueRows, runtime.tableIndex, true, dialect);
172
291
  await runQuery(executor, runtime, { operation: "insert", tableAccessor: throughTable.accessor }, sql, values);
173
292
  }
174
- async function insertJunctionRows(executor, runtime, throughAccessor, leftFkCol, rightFkCol, leftId, rightIds) {
293
+ async function _insertJunctionRows(executor, runtime, throughAccessor, leftFkCol, _rightFkCol, leftId, rightIds) {
175
294
  const { manifest } = runtime;
176
295
  const m2m = manifest.manyToMany.find((m) => m.throughAccessor === throughAccessor);
177
296
  if (!m2m) {
@@ -181,6 +300,7 @@ async function insertJunctionRows(executor, runtime, throughAccessor, leftFkCol,
181
300
  await insertM2MLinks(executor, runtime, m2m, parentAccessor, leftId, rightIds);
182
301
  }
183
302
  async function deleteJunctionRows(executor, runtime, m2m, parentAccessor, parentId, rightIds) {
303
+ const dialect = runtime.dialect ?? postgresDialect;
184
304
  const { manifest } = runtime;
185
305
  const throughTable = manifest.tables[m2m.throughAccessor];
186
306
  if (!throughTable)
@@ -194,10 +314,10 @@ async function deleteJunctionRows(executor, runtime, m2m, parentAccessor, parent
194
314
  if (!parentCol || !otherCol)
195
315
  return;
196
316
  const params = [parentId];
197
- let sql = `DELETE FROM ${tableRef(throughTable)} WHERE ${quoteIdentifier(parentCol.sqlName)} = $1`;
317
+ let sql = `DELETE FROM ${dialect.tableRef(throughTable)} WHERE ${dialect.quoteIdentifier(parentCol.sqlName)} = ${dialect.placeholder(1)}`;
198
318
  if (rightIds && rightIds.length > 0) {
199
- const placeholders = rightIds.map((_, i) => `$${i + 2}`).join(", ");
200
- sql += ` AND ${quoteIdentifier(otherCol.sqlName)} IN (${placeholders})`;
319
+ const placeholders = joinPlaceholders(dialect, rightIds.length, 2);
320
+ sql += ` AND ${dialect.quoteIdentifier(otherCol.sqlName)} IN (${placeholders})`;
201
321
  params.push(...rightIds);
202
322
  }
203
323
  await runQuery(executor, runtime, { operation: "delete", tableAccessor: throughTable.accessor }, sql, params);
@@ -210,56 +330,63 @@ function childFkColumnMeta(targetTable, relation, tableIndex) {
210
330
  }
211
331
  return col;
212
332
  }
213
- async function connectInverseMany(executor, runtime, relation, parentId, childIds) {
333
+ async function connectInverseMany(executor, runtime, relation, parentId, childPks, parentTable, parentRow) {
334
+ const dialect = runtime.dialect ?? postgresDialect;
214
335
  const { manifest } = runtime;
215
336
  const targetTable = manifest.tables[relation.targetAccessor];
216
- if (!targetTable || childIds.length === 0)
337
+ if (!targetTable || childPks.length === 0)
217
338
  return;
218
- const fkCol = childFkColumnMeta(targetTable, relation, getTableIndex(runtime.tableIndex, targetTable.accessor));
219
- const placeholders = childIds.map((_, i) => `$${i + 2}`).join(", ");
220
- const targetPkCol = quoteIdentifier(targetRelationPkSql(targetTable, relation));
221
- await runQuery(executor, runtime, { operation: "update", tableAccessor: relation.targetAccessor }, `UPDATE ${tableRef(targetTable)} SET ${quoteIdentifier(fkCol.sqlName)} = $1 WHERE ${targetPkCol} IN (${placeholders})`, [parentId, ...childIds]);
339
+ const targetIndex = getTableIndex(runtime.tableIndex, targetTable.accessor);
340
+ const assignment = inverseFkAssignments(relation, parentTable ?? targetTable, parentRow, parentId);
341
+ const predicate = sqlPkPredicate(dialect, targetTable, targetIndex, childPks, assignment.values.length + 1);
342
+ const setSql = assignment.sqlNames
343
+ .map((sqlName, i) => `${dialect.quoteIdentifier(sqlName)} = ${dialect.placeholder(i + 1)}`)
344
+ .join(", ");
345
+ await runQuery(executor, runtime, { operation: "update", tableAccessor: relation.targetAccessor }, `UPDATE ${dialect.tableRef(targetTable)} SET ${setSql} WHERE ${predicate.sql}`, [...assignment.values, ...predicate.params]);
222
346
  }
223
- async function disconnectInverseMany(executor, runtime, relation, parentId, childIds) {
347
+ async function disconnectInverseMany(executor, runtime, relation, parentId, childPks) {
348
+ const dialect = runtime.dialect ?? postgresDialect;
224
349
  const { manifest } = runtime;
225
350
  const targetTable = manifest.tables[relation.targetAccessor];
226
351
  if (!targetTable)
227
352
  return;
228
- const fkCol = childFkColumnMeta(targetTable, relation, getTableIndex(runtime.tableIndex, targetTable.accessor));
353
+ const targetIndex = getTableIndex(runtime.tableIndex, targetTable.accessor);
354
+ const fkCol = childFkColumnMeta(targetTable, relation, targetIndex);
229
355
  if (!fkCol.nullable) {
230
356
  compileError(`Cannot disconnect relation ${relation.name}: FK column is not nullable`);
231
357
  }
232
358
  const params = [parentId];
233
- let sql = `UPDATE ${tableRef(targetTable)} SET ${quoteIdentifier(fkCol.sqlName)} = NULL WHERE ${quoteIdentifier(fkCol.sqlName)} = $1`;
234
- if (childIds && childIds.length > 0) {
235
- const placeholders = childIds.map((_, i) => `$${i + 2}`).join(", ");
236
- const targetPkCol = quoteIdentifier(targetRelationPkSql(targetTable, relation));
237
- sql += ` AND ${targetPkCol} IN (${placeholders})`;
238
- params.push(...childIds);
359
+ let sql = `UPDATE ${dialect.tableRef(targetTable)} SET ${dialect.quoteIdentifier(fkCol.sqlName)} = NULL WHERE ${dialect.quoteIdentifier(fkCol.sqlName)} = ${dialect.placeholder(1)}`;
360
+ if (childPks && childPks.length > 0) {
361
+ const predicate = sqlPkPredicate(dialect, targetTable, targetIndex, childPks, 2);
362
+ sql += ` AND ${predicate.sql}`;
363
+ params.push(...predicate.params);
239
364
  }
240
365
  await runQuery(executor, runtime, { operation: "update", tableAccessor: relation.targetAccessor }, sql, params);
241
366
  }
242
- async function setInverseMany(executor, runtime, relation, parentId, childIds) {
367
+ async function setInverseMany(executor, runtime, relation, parentId, childPks, parentTable, parentRow) {
243
368
  await disconnectInverseMany(executor, runtime, relation, parentId, undefined);
244
- await connectInverseMany(executor, runtime, relation, parentId, childIds);
369
+ await connectInverseMany(executor, runtime, relation, parentId, childPks, parentTable, parentRow);
245
370
  }
246
- async function deleteInverseManyChildren(executor, runtime, relation, parentId, childIds) {
371
+ async function deleteInverseManyChildren(executor, runtime, relation, parentId, childPks) {
372
+ const dialect = runtime.dialect ?? postgresDialect;
247
373
  const { manifest } = runtime;
248
374
  const targetTable = manifest.tables[relation.targetAccessor];
249
375
  if (!targetTable)
250
376
  return;
251
- const fkCol = childFkColumnMeta(targetTable, relation, getTableIndex(runtime.tableIndex, targetTable.accessor));
252
- const targetPkCol = quoteIdentifier(targetRelationPkSql(targetTable, relation));
377
+ const targetIndex = getTableIndex(runtime.tableIndex, targetTable.accessor);
378
+ const fkCol = childFkColumnMeta(targetTable, relation, targetIndex);
253
379
  const params = [parentId];
254
- let sql = `DELETE FROM ${tableRef(targetTable)} WHERE ${quoteIdentifier(fkCol.sqlName)} = $1`;
255
- if (childIds && childIds.length > 0) {
256
- const placeholders = childIds.map((_, i) => `$${i + 2}`).join(", ");
257
- sql += ` AND ${targetPkCol} IN (${placeholders})`;
258
- params.push(...childIds);
380
+ let sql = `DELETE FROM ${dialect.tableRef(targetTable)} WHERE ${dialect.quoteIdentifier(fkCol.sqlName)} = ${dialect.placeholder(1)}`;
381
+ if (childPks && childPks.length > 0) {
382
+ const predicate = sqlPkPredicate(dialect, targetTable, targetIndex, childPks, 2);
383
+ sql += ` AND ${predicate.sql}`;
384
+ params.push(...predicate.params);
259
385
  }
260
386
  await runQuery(executor, runtime, { operation: "delete", tableAccessor: relation.targetAccessor }, sql, params);
261
387
  }
262
388
  async function listM2MLinkedIds(executor, runtime, m2m, parentAccessor, parentId) {
389
+ const dialect = runtime.dialect ?? postgresDialect;
263
390
  const { manifest } = runtime;
264
391
  const throughTable = manifest.tables[m2m.throughAccessor];
265
392
  if (!throughTable)
@@ -272,10 +399,11 @@ async function listM2MLinkedIds(executor, runtime, m2m, parentAccessor, parentId
272
399
  const otherCol = columnBySqlName(throughIndex, throughTable, otherFkCol);
273
400
  if (!parentCol || !otherCol)
274
401
  return [];
275
- const rows = await runQuery(executor, runtime, { operation: "select", tableAccessor: throughTable.accessor }, `SELECT ${quoteIdentifier(otherCol.sqlName)} FROM ${tableRef(throughTable)} WHERE ${quoteIdentifier(parentCol.sqlName)} = $1`, [parentId]);
402
+ const rows = await runQuery(executor, runtime, { operation: "select", tableAccessor: throughTable.accessor }, `SELECT ${dialect.quoteIdentifier(otherCol.sqlName)} FROM ${dialect.tableRef(throughTable)} WHERE ${dialect.quoteIdentifier(parentCol.sqlName)} = ${dialect.placeholder(1)}`, [parentId]);
276
403
  return rows.map((row) => String(row[otherCol.sqlName] ?? row[otherCol.tsName]));
277
404
  }
278
- async function deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId, relatedIds) {
405
+ async function deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId, relatedIds, targetPks) {
406
+ const dialect = runtime.dialect ?? postgresDialect;
279
407
  const { manifest } = runtime;
280
408
  const isLeft = m2m.leftAccessor === tableAccessor;
281
409
  const targetAccessor = isLeft ? m2m.rightAccessor : m2m.leftAccessor;
@@ -287,29 +415,59 @@ async function deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId,
287
415
  if (ids.length === 0)
288
416
  return;
289
417
  await deleteJunctionRows(executor, runtime, m2m, tableAccessor, parentId, ids);
290
- const targetPkCol = quoteIdentifier(primaryKeySqlName(targetTable));
291
- const placeholders = ids.map((_, i) => `$${i + 1}`).join(", ");
292
- await runQuery(executor, runtime, { operation: "delete", tableAccessor: targetAccessor }, `DELETE FROM ${tableRef(targetTable)} WHERE ${targetPkCol} IN (${placeholders})`, ids);
418
+ const targetIndex = getTableIndex(runtime.tableIndex, targetAccessor);
419
+ if (targetPks && targetPks.length > 0) {
420
+ const predicate = sqlPkPredicate(dialect, targetTable, targetIndex, targetPks, 1);
421
+ await runQuery(executor, runtime, { operation: "delete", tableAccessor: targetAccessor }, `DELETE FROM ${dialect.tableRef(targetTable)} WHERE ${predicate.sql}`, predicate.params);
422
+ return;
423
+ }
424
+ const targetPkCol = dialect.quoteIdentifier(primaryKeySqlName(targetTable));
425
+ const placeholders = joinPlaceholders(dialect, ids.length);
426
+ await runQuery(executor, runtime, { operation: "delete", tableAccessor: targetAccessor }, `DELETE FROM ${dialect.tableRef(targetTable)} WHERE ${targetPkCol} IN (${placeholders})`, ids);
427
+ }
428
+ function assertExclusiveConnectOrCreate(value, relationName) {
429
+ if (!("connectOrCreate" in value))
430
+ return;
431
+ if ("connect" in value || "create" in value) {
432
+ compileError(`Relation "${relationName}" cannot mix connectOrCreate with connect or create`, { code: QueryErrorCode.invalid_nested_write });
433
+ }
293
434
  }
294
435
  async function executeToOneWrite(executor, runtime, table, scalarData, relationName, value, runCreate) {
295
436
  const { manifest } = runtime;
296
437
  const tableIndex = getTableIndex(runtime.tableIndex, table.accessor);
297
438
  const rel = findRelation(table, relationName, tableIndex);
298
- if (!rel || rel.cardinality !== "one")
439
+ if (rel?.cardinality !== "one")
440
+ return;
441
+ const targetTable = manifest.tables[rel.targetAccessor];
442
+ if (!targetTable)
443
+ compileError(`Unknown table: ${rel.targetAccessor}`);
444
+ const targetIndex = getTableIndex(runtime.tableIndex, rel.targetAccessor);
445
+ assertExclusiveConnectOrCreate(value, relationName);
446
+ if ("connectOrCreate" in value) {
447
+ const item = value.connectOrCreate;
448
+ if (!item || typeof item !== "object" || Array.isArray(item)) {
449
+ compileError(`Relation "${relationName}" connectOrCreate requires { where, create }`, { code: QueryErrorCode.invalid_nested_write });
450
+ }
451
+ const { record } = await findOrCreateRecord(executor, runtime, rel.targetAccessor, {
452
+ where: item.where,
453
+ create: item.create,
454
+ });
455
+ assignOutgoingFkScalars(scalarData, rel, targetTable, targetIndex, record);
299
456
  return;
457
+ }
300
458
  if ("connect" in value) {
301
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, value.connect);
302
- const id = ids[0];
303
- if (id === undefined) {
459
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, value.connect);
460
+ const pk = pks[0];
461
+ if (pk === undefined) {
304
462
  compileError(`Relation connect requires a primary key for table "${rel.targetAccessor}"`, {
305
463
  code: QueryErrorCode.missing_primary_key,
306
464
  tableAccessor: rel.targetAccessor,
307
465
  });
308
466
  }
309
- if (ids.length > 1) {
467
+ if (pks.length > 1) {
310
468
  compileError(`Cannot connect more than one record to to-one relation ${relationName}`);
311
469
  }
312
- scalarData[rel.fkColumn] = id;
470
+ assignOutgoingFkScalars(scalarData, rel, targetTable, targetIndex, pk);
313
471
  return;
314
472
  }
315
473
  if ("disconnect" in value) {
@@ -318,17 +476,14 @@ async function executeToOneWrite(executor, runtime, table, scalarData, relationN
318
476
  if (fkCol && !fkCol.nullable) {
319
477
  compileError(`Cannot disconnect relation ${relationName}: FK column is not nullable`);
320
478
  }
321
- scalarData[rel.fkColumn] = null;
479
+ assignOutgoingFkScalars(scalarData, rel, targetTable, targetIndex, {}, true);
322
480
  return;
323
481
  }
324
482
  if ("create" in value) {
325
483
  const created = await runCreate(executor, runtime, rel.targetAccessor, {
326
- data: value["create"],
484
+ data: value.create,
327
485
  });
328
- const targetTable = manifest.tables[rel.targetAccessor];
329
- if (!targetTable)
330
- compileError(`Unknown table: ${rel.targetAccessor}`);
331
- scalarData[rel.fkColumn] = rowScalarPkValue(created, targetTable);
486
+ assignOutgoingFkScalars(scalarData, rel, targetTable, targetIndex, created);
332
487
  }
333
488
  }
334
489
  export async function applyToOnePreWrites(executor, runtime, table, scalarData, relationWrites, runCreate) {
@@ -336,7 +491,7 @@ export async function applyToOnePreWrites(executor, runtime, table, scalarData,
336
491
  return;
337
492
  for (const write of relationWrites) {
338
493
  const rel = findRelation(table, write.relationName);
339
- if (!rel || rel.cardinality !== "one" || !tableOwnsFkColumn(table, rel))
494
+ if (rel?.cardinality !== "one" || !tableOwnsFkColumn(table, rel))
340
495
  continue;
341
496
  await executeToOneWrite(executor, runtime, table, scalarData, write.relationName, write.value, runCreate);
342
497
  }
@@ -349,27 +504,27 @@ async function executeM2MWrite(executor, runtime, tableAccessor, parentId, relat
349
504
  const isLeft = m2m.leftAccessor === tableAccessor;
350
505
  const targetAccessor = isLeft ? m2m.rightAccessor : m2m.leftAccessor;
351
506
  if ("delete" in value) {
352
- const del = value["delete"];
507
+ const del = value.delete;
353
508
  if (del === true) {
354
509
  await deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId, undefined);
355
510
  }
356
511
  else {
357
- const ids = normalizeConnectIds(runtime, targetAccessor, del);
358
- await deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId, ids);
512
+ const { pks, ids } = m2mConnectFkValues(runtime, m2m, tableAccessor, targetAccessor, del);
513
+ await deleteM2MRelated(executor, runtime, m2m, tableAccessor, parentId, ids, pks);
359
514
  }
360
515
  }
361
516
  if ("disconnect" in value) {
362
- const disconnect = value["disconnect"];
517
+ const disconnect = value.disconnect;
363
518
  if (disconnect === true) {
364
519
  await deleteJunctionRows(executor, runtime, m2m, tableAccessor, parentId);
365
520
  }
366
521
  else {
367
- const ids = normalizeConnectIds(runtime, targetAccessor, disconnect);
522
+ const { ids } = m2mConnectFkValues(runtime, m2m, tableAccessor, targetAccessor, disconnect);
368
523
  await deleteJunctionRows(executor, runtime, m2m, tableAccessor, parentId, ids);
369
524
  }
370
525
  }
371
526
  if ("set" in value) {
372
- const ids = normalizeConnectIds(runtime, targetAccessor, value["set"]);
527
+ const { ids } = m2mConnectFkValues(runtime, m2m, tableAccessor, targetAccessor, value.set);
373
528
  await deleteJunctionRows(executor, runtime, m2m, tableAccessor, parentId);
374
529
  if (ids.length > 0) {
375
530
  await insertM2MLinks(executor, runtime, m2m, tableAccessor, parentId, ids);
@@ -377,85 +532,88 @@ async function executeM2MWrite(executor, runtime, tableAccessor, parentId, relat
377
532
  return;
378
533
  }
379
534
  if ("connect" in value) {
380
- const ids = normalizeConnectIds(runtime, targetAccessor, value["connect"]);
535
+ const { ids } = m2mConnectFkValues(runtime, m2m, tableAccessor, targetAccessor, value.connect);
381
536
  if (ids.length > 0) {
382
537
  await insertM2MLinks(executor, runtime, m2m, tableAccessor, parentId, ids);
383
538
  }
384
539
  }
385
540
  if ("connectOrCreate" in value) {
386
- const items = value["connectOrCreate"];
387
- const ids = await resolveConnectOrCreate(executor, runtime, targetAccessor, items);
541
+ const items = value.connectOrCreate;
542
+ const targetTable = requireTable(runtime.manifest, targetAccessor, "select");
543
+ const targetIndex = getTableIndex(runtime.tableIndex, targetAccessor);
544
+ const throughFk = m2mOtherThroughColumn(runtime, m2m, tableAccessor);
545
+ const fkTs = fkTargetTsName(targetTable, targetIndex, undefined, throughFk);
546
+ const ids = await resolveConnectOrCreate(executor, runtime, targetAccessor, items, fkTs);
388
547
  if (ids.length > 0) {
389
548
  await insertM2MLinks(executor, runtime, m2m, tableAccessor, parentId, ids);
390
549
  }
391
550
  }
392
551
  }
393
- async function executeInverseManyWrite(executor, runtime, table, parentId, relationName, value, runCreate) {
552
+ async function executeInverseManyWrite(executor, runtime, table, parentId, relationName, value, runCreate, parentRow) {
394
553
  const { manifest } = runtime;
395
554
  const rel = findRelation(table, relationName);
396
- if (!rel ||
397
- rel.cardinality !== "many" ||
555
+ if (rel?.cardinality !== "many" ||
398
556
  findM2M(manifest, table.accessor, relationName)) {
399
557
  return;
400
558
  }
401
559
  if ("delete" in value) {
402
- const del = value["delete"];
560
+ const del = value.delete;
403
561
  if (del === true) {
404
562
  await deleteInverseManyChildren(executor, runtime, rel, parentId, undefined);
405
563
  }
406
564
  else {
407
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, del);
408
- await deleteInverseManyChildren(executor, runtime, rel, parentId, ids);
565
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, del);
566
+ await deleteInverseManyChildren(executor, runtime, rel, parentId, pks);
409
567
  }
410
568
  }
411
569
  if ("disconnect" in value) {
412
- const disconnect = value["disconnect"];
570
+ const disconnect = value.disconnect;
413
571
  if (disconnect === true) {
414
572
  await disconnectInverseMany(executor, runtime, rel, parentId, undefined);
415
573
  }
416
574
  else {
417
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, disconnect);
418
- await disconnectInverseMany(executor, runtime, rel, parentId, ids);
575
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, disconnect);
576
+ await disconnectInverseMany(executor, runtime, rel, parentId, pks);
419
577
  }
420
578
  }
421
579
  if ("set" in value) {
422
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, value["set"]);
423
- await setInverseMany(executor, runtime, rel, parentId, ids);
580
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, value.set);
581
+ await setInverseMany(executor, runtime, rel, parentId, pks, table, parentRow);
424
582
  return;
425
583
  }
426
584
  if ("connect" in value) {
427
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, value["connect"]);
428
- await connectInverseMany(executor, runtime, rel, parentId, ids);
585
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, value.connect);
586
+ await connectInverseMany(executor, runtime, rel, parentId, pks, table, parentRow);
429
587
  }
430
588
  if ("create" in value) {
431
- const items = normalizeCreateList(value["create"]);
589
+ const items = normalizeCreateList(value.create);
432
590
  for (const item of items) {
433
591
  await runCreate(executor, runtime, rel.targetAccessor, {
434
592
  data: {
435
593
  ...item,
436
- [rel.fkColumn]: parentId,
594
+ ...childFkCreatePatch(rel, table, parentRow, parentId),
437
595
  },
438
596
  });
439
597
  }
440
598
  }
441
599
  }
442
- async function executeInverseOneWrite(executor, runtime, table, parentId, relationName, value, runCreate) {
600
+ async function executeInverseOneWrite(executor, runtime, table, parentId, relationName, value, runCreate, parentRow) {
443
601
  const { manifest } = runtime;
444
602
  const rel = findRelation(table, relationName);
445
- if (!rel || rel.cardinality !== "one" || tableOwnsFkColumn(table, rel))
603
+ if (rel?.cardinality !== "one" || tableOwnsFkColumn(table, rel))
446
604
  return;
447
605
  const targetTable = manifest.tables[rel.targetAccessor];
448
606
  if (!targetTable)
449
607
  return;
450
608
  const fkCol = childFkColumnMeta(targetTable, rel);
451
609
  if ("delete" in value) {
452
- const del = value["delete"];
610
+ const del = value.delete;
453
611
  if (del === true) {
454
612
  await deleteInverseManyChildren(executor, runtime, rel, parentId, undefined);
455
613
  }
456
614
  else {
457
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, del);
458
- await deleteInverseManyChildren(executor, runtime, rel, parentId, ids);
615
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, del);
616
+ await deleteInverseManyChildren(executor, runtime, rel, parentId, pks);
459
617
  }
460
618
  }
461
619
  if ("disconnect" in value) {
@@ -465,26 +623,26 @@ async function executeInverseOneWrite(executor, runtime, table, parentId, relati
465
623
  await disconnectInverseMany(executor, runtime, rel, parentId, undefined);
466
624
  }
467
625
  if ("set" in value) {
468
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, value["set"]);
469
- const id = ids[0];
470
- if (id) {
626
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, value.set);
627
+ const pk = pks[0];
628
+ if (pk) {
471
629
  await disconnectInverseMany(executor, runtime, rel, parentId, undefined);
472
- await connectInverseMany(executor, runtime, rel, parentId, [id]);
630
+ await connectInverseMany(executor, runtime, rel, parentId, [pk], table, parentRow);
473
631
  }
474
632
  return;
475
633
  }
476
634
  if ("connect" in value) {
477
- const ids = normalizeConnectIds(runtime, rel.targetAccessor, value["connect"]);
478
- const id = ids[0];
479
- if (!id)
635
+ const pks = normalizeConnectPks(runtime, rel.targetAccessor, value.connect);
636
+ const pk = pks[0];
637
+ if (!pk)
480
638
  return;
481
- if (ids.length > 1) {
639
+ if (pks.length > 1) {
482
640
  compileError(`Cannot connect more than one record to one-to-one relation ${relationName}`);
483
641
  }
484
- await connectInverseMany(executor, runtime, rel, parentId, [id]);
642
+ await connectInverseMany(executor, runtime, rel, parentId, [pk], table, parentRow);
485
643
  }
486
644
  if ("create" in value) {
487
- const items = normalizeCreateList(value["create"]);
645
+ const items = normalizeCreateList(value.create);
488
646
  if (items.length > 1) {
489
647
  compileError(`Cannot create more than one record for one-to-one relation ${relationName}`);
490
648
  }
@@ -493,13 +651,13 @@ async function executeInverseOneWrite(executor, runtime, table, parentId, relati
493
651
  await runCreate(executor, runtime, rel.targetAccessor, {
494
652
  data: {
495
653
  ...item,
496
- [rel.fkColumn]: parentId,
654
+ ...childFkCreatePatch(rel, table, parentRow, parentId),
497
655
  },
498
656
  });
499
657
  }
500
658
  }
501
659
  }
502
- export async function executeRelationWrites(executor, runtime, tableAccessor, parentId, relationWrites, runCreate) {
660
+ export async function executeRelationWrites(executor, runtime, tableAccessor, parentId, relationWrites, runCreate, parentRow) {
503
661
  const { manifest } = runtime;
504
662
  const table = requireTable(manifest, tableAccessor, "select");
505
663
  for (const write of relationWrites) {
@@ -512,11 +670,11 @@ export async function executeRelationWrites(executor, runtime, tableAccessor, pa
512
670
  continue;
513
671
  if (rel.cardinality === "one") {
514
672
  if (!tableOwnsFkColumn(table, rel)) {
515
- await executeInverseOneWrite(executor, runtime, table, parentId, write.relationName, write.value, runCreate);
673
+ await executeInverseOneWrite(executor, runtime, table, parentId, write.relationName, write.value, runCreate, parentRow);
516
674
  }
517
675
  continue;
518
676
  }
519
- await executeInverseManyWrite(executor, runtime, table, parentId, write.relationName, write.value, runCreate);
677
+ await executeInverseManyWrite(executor, runtime, table, parentId, write.relationName, write.value, runCreate, parentRow);
520
678
  }
521
679
  }
522
680
  export function hasPostRelationWrites(table, manifest, tableAccessor, relationWrites) {
@@ -539,9 +697,7 @@ export function relationWritesNeedTransaction(table, manifest, tableAccessor, re
539
697
  }
540
698
  for (const write of relationWrites) {
541
699
  const rel = findRelation(table, write.relationName);
542
- if (!rel ||
543
- rel.cardinality !== "one" ||
544
- !tableOwnsFkColumn(table, rel)) {
700
+ if (rel?.cardinality !== "one" || !tableOwnsFkColumn(table, rel)) {
545
701
  continue;
546
702
  }
547
703
  if (typeof write.value === "object" &&