@baasix/baasix 0.1.0

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 (666) hide show
  1. package/LICENSE.MD +85 -0
  2. package/README.md +526 -0
  3. package/assets/banner.jpg +0 -0
  4. package/assets/banner_small.jpg +0 -0
  5. package/assets/logo_icon.svg +20 -0
  6. package/assets/logo_icon_rounded.svg +20 -0
  7. package/dist/LICENSE.MD +85 -0
  8. package/dist/README.md +526 -0
  9. package/dist/app/404/index.html +1 -0
  10. package/dist/app/404.html +1 -0
  11. package/dist/app/_next/static/chunks/041e1f03-56ae8a902a7f2fe6.js +24 -0
  12. package/dist/app/_next/static/chunks/1117-05479929a8da73e3.js +1 -0
  13. package/dist/app/_next/static/chunks/1299.77cc7b7b76b75cba.js +1 -0
  14. package/dist/app/_next/static/chunks/1303-35a96e9c9cdeab9d.js +1 -0
  15. package/dist/app/_next/static/chunks/1509-56ac00cdaaecdf53.js +1 -0
  16. package/dist/app/_next/static/chunks/1668-e3eabd0f6753c780.js +1 -0
  17. package/dist/app/_next/static/chunks/1783-d9fb550fd324300c.js +1 -0
  18. package/dist/app/_next/static/chunks/2117-29b5fa47421595ad.js +2 -0
  19. package/dist/app/_next/static/chunks/2344.35b46d2179a765b5.js +1 -0
  20. package/dist/app/_next/static/chunks/257.990da16794a31292.js +1 -0
  21. package/dist/app/_next/static/chunks/2676-73b0ee7c80073a84.js +1 -0
  22. package/dist/app/_next/static/chunks/3563-b8842744384391fe.js +1 -0
  23. package/dist/app/_next/static/chunks/363642f4-933b579ed3c85f60.js +1 -0
  24. package/dist/app/_next/static/chunks/3817-e20c8f0a0810fc95.js +1 -0
  25. package/dist/app/_next/static/chunks/3834.84944e390d902509.js +2 -0
  26. package/dist/app/_next/static/chunks/4043-3a30c8a75896f241.js +1 -0
  27. package/dist/app/_next/static/chunks/4225-14090c7c0cd9dec6.js +1 -0
  28. package/dist/app/_next/static/chunks/4438-c9a12ca15b6e9160.js +1 -0
  29. package/dist/app/_next/static/chunks/4458-679fd0c6884f456a.js +1 -0
  30. package/dist/app/_next/static/chunks/4475-8bdfbd536fba8c48.js +1 -0
  31. package/dist/app/_next/static/chunks/4883-8a924721bb21b3b0.js +1 -0
  32. package/dist/app/_next/static/chunks/489-683ab07188f9df2b.js +1 -0
  33. package/dist/app/_next/static/chunks/4952-1b97320cf61f3f21.js +1 -0
  34. package/dist/app/_next/static/chunks/5094-8d53e403235d4ca6.js +1 -0
  35. package/dist/app/_next/static/chunks/5101-3a146e0625747ad1.js +1 -0
  36. package/dist/app/_next/static/chunks/54a60aa6-d9747982e0a81f58.js +79 -0
  37. package/dist/app/_next/static/chunks/5650-f096291df402bfc2.js +1 -0
  38. package/dist/app/_next/static/chunks/600-539045311240f579.js +1 -0
  39. package/dist/app/_next/static/chunks/6170-803b82e19d3ade6d.js +89 -0
  40. package/dist/app/_next/static/chunks/6241-30d7169d1010e5a4.js +1 -0
  41. package/dist/app/_next/static/chunks/6530-a91e10cffa4200c4.js +1 -0
  42. package/dist/app/_next/static/chunks/6547-4bbbdb5c399aef1e.js +1 -0
  43. package/dist/app/_next/static/chunks/6712-781937c53a2c49da.js +1 -0
  44. package/dist/app/_next/static/chunks/6fcbdc68-90be1a5480b8d353.js +1 -0
  45. package/dist/app/_next/static/chunks/70e0d97a-aeaf0cdc26ba1a58.js +1 -0
  46. package/dist/app/_next/static/chunks/7214-5154a89d08d24dde.js +1 -0
  47. package/dist/app/_next/static/chunks/7324-b53229c59a640880.js +10 -0
  48. package/dist/app/_next/static/chunks/7636-66424f0b51d350e9.js +1 -0
  49. package/dist/app/_next/static/chunks/7874-39a3f2541165a675.js +1 -0
  50. package/dist/app/_next/static/chunks/7982-9da12b83f11e3f5f.js +1 -0
  51. package/dist/app/_next/static/chunks/8213a2eb-da25a3b3c5521b2b.js +1 -0
  52. package/dist/app/_next/static/chunks/8473-6598318371eca31b.js +1 -0
  53. package/dist/app/_next/static/chunks/8640fa6b-72e43370f68e5587.js +1 -0
  54. package/dist/app/_next/static/chunks/9090-3ef676f29c95f1c7.js +1 -0
  55. package/dist/app/_next/static/chunks/9124-a02f9e209e6e3cce.js +1 -0
  56. package/dist/app/_next/static/chunks/926-156f32067d111d6b.js +1 -0
  57. package/dist/app/_next/static/chunks/9487-b17481605e513b83.js +1 -0
  58. package/dist/app/_next/static/chunks/9599-a7e572bb88c3392b.js +1 -0
  59. package/dist/app/_next/static/chunks/9881-419697138376e755.js +1 -0
  60. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/all-activity/page-8917930b4d663405.js +1 -0
  61. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/email-log/page-b27a6ee32782d7df.js +1 -0
  62. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/notifications/page-b7eda523ede2702c.js +1 -0
  63. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/page-1cfa62d1caedaed0.js +1 -0
  64. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/sessions/page-3e21e20db90aeff7.js +1 -0
  65. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/workflow-executions/page-27bcc26b747fb29b.js +1 -0
  66. package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/workflow-logs/page-9f9e9e952aef436e.js +1 -0
  67. package/dist/app/_next/static/chunks/app/(authenticated)/change-password/page-8d61aa499eabb127.js +1 -0
  68. package/dist/app/_next/static/chunks/app/(authenticated)/dashboard/page-1ceeac9e72997a8a.js +1 -0
  69. package/dist/app/_next/static/chunks/app/(authenticated)/data-browser/page-8cda2b57759dd670.js +1 -0
  70. package/dist/app/_next/static/chunks/app/(authenticated)/file-manager/page-8c6f1b1da66ad7e4.js +1 -0
  71. package/dist/app/_next/static/chunks/app/(authenticated)/layout-f70d225b2759c998.js +1 -0
  72. package/dist/app/_next/static/chunks/app/(authenticated)/settings/migrations/page-aacec8f7cfb40ab2.js +1 -0
  73. package/dist/app/_next/static/chunks/app/(authenticated)/settings/permissions/page-828110cfcde429c6.js +1 -0
  74. package/dist/app/_next/static/chunks/app/(authenticated)/settings/project/page-420e794bb76bd204.js +1 -0
  75. package/dist/app/_next/static/chunks/app/(authenticated)/settings/roles/page-9001d02b28f70708.js +1 -0
  76. package/dist/app/_next/static/chunks/app/(authenticated)/settings/schema/page-899574f35091dd58.js +1 -0
  77. package/dist/app/_next/static/chunks/app/(authenticated)/settings/tasks/page-ad7ab3e27c83f44f.js +1 -0
  78. package/dist/app/_next/static/chunks/app/(authenticated)/settings/templates/edit/page-bd83414cb8c4cb04.js +1 -0
  79. package/dist/app/_next/static/chunks/app/(authenticated)/settings/templates/page-3181447f8772b1d3.js +1 -0
  80. package/dist/app/_next/static/chunks/app/(authenticated)/settings/tenants/page-ef9bfbacef5a1d73.js +1 -0
  81. package/dist/app/_next/static/chunks/app/(authenticated)/users/invites/page-480306b7b2bbac7e.js +1 -0
  82. package/dist/app/_next/static/chunks/app/(authenticated)/users/list/page-74da51254c2606b3.js +1 -0
  83. package/dist/app/_next/static/chunks/app/(authenticated)/users/page-e99c6f0b915001b2.js +1 -0
  84. package/dist/app/_next/static/chunks/app/(authenticated)/users/preferences/page-1a935630ce8f2b12.js +1 -0
  85. package/dist/app/_next/static/chunks/app/(authenticated)/users/user-roles/page-901dfb8ea1f39ca8.js +1 -0
  86. package/dist/app/_next/static/chunks/app/(authenticated)/workflows/detail/page-9a6b839aea688ca4.js +1 -0
  87. package/dist/app/_next/static/chunks/app/(authenticated)/workflows/edit/page-11774efbc2fecae2.js +1 -0
  88. package/dist/app/_next/static/chunks/app/(authenticated)/workflows/execution/page-8ec1aea90412c03d.js +1 -0
  89. package/dist/app/_next/static/chunks/app/(authenticated)/workflows/page-88bc5b36ccb0a1f7.js +1 -0
  90. package/dist/app/_next/static/chunks/app/(public)/forgot-password/page-ed263fd46ef81c20.js +1 -0
  91. package/dist/app/_next/static/chunks/app/(public)/layout-f538977545844af8.js +1 -0
  92. package/dist/app/_next/static/chunks/app/(public)/login/page-c0a10b137f346096.js +1 -0
  93. package/dist/app/_next/static/chunks/app/(public)/register/page-4cb7644893efd9b3.js +1 -0
  94. package/dist/app/_next/static/chunks/app/_not-found/page-653f8815b78256cc.js +1 -0
  95. package/dist/app/_next/static/chunks/app/layout-591ca7a3e16528a1.js +1 -0
  96. package/dist/app/_next/static/chunks/app/page-dd19d124b5fa2577.js +1 -0
  97. package/dist/app/_next/static/chunks/c37d3baf.c2ff165f5b02c692.js +1 -0
  98. package/dist/app/_next/static/chunks/d0deef33.0379166a4ec23470.js +1 -0
  99. package/dist/app/_next/static/chunks/fd9d1056-54169f07cd680d6c.js +1 -0
  100. package/dist/app/_next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
  101. package/dist/app/_next/static/chunks/main-324e91f5a430cddf.js +1 -0
  102. package/dist/app/_next/static/chunks/main-app-55bcae20c77aaf0e.js +1 -0
  103. package/dist/app/_next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
  104. package/dist/app/_next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
  105. package/dist/app/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  106. package/dist/app/_next/static/chunks/webpack-2c306566f7ee1b63.js +1 -0
  107. package/dist/app/_next/static/css/6c4002bae4e236b2.css +3 -0
  108. package/dist/app/_next/static/css/a275cc2b185e04f8.css +1 -0
  109. package/dist/app/_next/static/eCWhKA8XHqmB1zgFcEtN2/_buildManifest.js +1 -0
  110. package/dist/app/_next/static/eCWhKA8XHqmB1zgFcEtN2/_ssgManifest.js +1 -0
  111. package/dist/app/activity-log/all-activity/index.html +1 -0
  112. package/dist/app/activity-log/all-activity/index.txt +14 -0
  113. package/dist/app/activity-log/email-log/index.html +1 -0
  114. package/dist/app/activity-log/email-log/index.txt +14 -0
  115. package/dist/app/activity-log/index.html +1 -0
  116. package/dist/app/activity-log/index.txt +14 -0
  117. package/dist/app/activity-log/notifications/index.html +1 -0
  118. package/dist/app/activity-log/notifications/index.txt +14 -0
  119. package/dist/app/activity-log/sessions/index.html +1 -0
  120. package/dist/app/activity-log/sessions/index.txt +14 -0
  121. package/dist/app/activity-log/workflow-executions/index.html +1 -0
  122. package/dist/app/activity-log/workflow-executions/index.txt +14 -0
  123. package/dist/app/activity-log/workflow-logs/index.html +1 -0
  124. package/dist/app/activity-log/workflow-logs/index.txt +14 -0
  125. package/dist/app/change-password/index.html +1 -0
  126. package/dist/app/change-password/index.txt +14 -0
  127. package/dist/app/dashboard/index.html +1 -0
  128. package/dist/app/dashboard/index.txt +14 -0
  129. package/dist/app/data-browser/index.html +1 -0
  130. package/dist/app/data-browser/index.txt +14 -0
  131. package/dist/app/file-manager/index.html +1 -0
  132. package/dist/app/file-manager/index.txt +14 -0
  133. package/dist/app/forgot-password/index.html +1 -0
  134. package/dist/app/forgot-password/index.txt +13 -0
  135. package/dist/app/index.html +1 -0
  136. package/dist/app/index.txt +9 -0
  137. package/dist/app/login/index.html +1 -0
  138. package/dist/app/login/index.txt +13 -0
  139. package/dist/app/logo-dark.png +0 -0
  140. package/dist/app/logo-icon.svg +81 -0
  141. package/dist/app/logo-light.png +0 -0
  142. package/dist/app/register/index.html +1 -0
  143. package/dist/app/register/index.txt +13 -0
  144. package/dist/app/settings/migrations/index.html +1 -0
  145. package/dist/app/settings/migrations/index.txt +14 -0
  146. package/dist/app/settings/permissions/index.html +1 -0
  147. package/dist/app/settings/permissions/index.txt +14 -0
  148. package/dist/app/settings/project/index.html +1 -0
  149. package/dist/app/settings/project/index.txt +14 -0
  150. package/dist/app/settings/roles/index.html +1 -0
  151. package/dist/app/settings/roles/index.txt +14 -0
  152. package/dist/app/settings/schema/index.html +1 -0
  153. package/dist/app/settings/schema/index.txt +14 -0
  154. package/dist/app/settings/tasks/index.html +1 -0
  155. package/dist/app/settings/tasks/index.txt +14 -0
  156. package/dist/app/settings/templates/edit/index.html +1 -0
  157. package/dist/app/settings/templates/edit/index.txt +14 -0
  158. package/dist/app/settings/templates/index.html +1 -0
  159. package/dist/app/settings/templates/index.txt +14 -0
  160. package/dist/app/settings/tenants/index.html +1 -0
  161. package/dist/app/settings/tenants/index.txt +14 -0
  162. package/dist/app/users/index.html +1 -0
  163. package/dist/app/users/index.txt +14 -0
  164. package/dist/app/users/invites/index.html +1 -0
  165. package/dist/app/users/invites/index.txt +14 -0
  166. package/dist/app/users/list/index.html +1 -0
  167. package/dist/app/users/list/index.txt +14 -0
  168. package/dist/app/users/preferences/index.html +1 -0
  169. package/dist/app/users/preferences/index.txt +14 -0
  170. package/dist/app/users/user-roles/index.html +1 -0
  171. package/dist/app/users/user-roles/index.txt +14 -0
  172. package/dist/app/workflows/detail/index.html +1 -0
  173. package/dist/app/workflows/detail/index.txt +14 -0
  174. package/dist/app/workflows/edit/index.html +1 -0
  175. package/dist/app/workflows/edit/index.txt +14 -0
  176. package/dist/app/workflows/execution/index.html +1 -0
  177. package/dist/app/workflows/execution/index.txt +14 -0
  178. package/dist/app/workflows/index.html +1 -0
  179. package/dist/app/workflows/index.txt +14 -0
  180. package/dist/app.d.ts +36 -0
  181. package/dist/app.d.ts.map +1 -0
  182. package/dist/app.js +546 -0
  183. package/dist/app.js.map +1 -0
  184. package/dist/auth/adapters/baasix-adapter.d.ts +12 -0
  185. package/dist/auth/adapters/baasix-adapter.d.ts.map +1 -0
  186. package/dist/auth/adapters/baasix-adapter.js +318 -0
  187. package/dist/auth/adapters/baasix-adapter.js.map +1 -0
  188. package/dist/auth/adapters/index.d.ts +6 -0
  189. package/dist/auth/adapters/index.d.ts.map +1 -0
  190. package/dist/auth/adapters/index.js +5 -0
  191. package/dist/auth/adapters/index.js.map +1 -0
  192. package/dist/auth/core.d.ts +73 -0
  193. package/dist/auth/core.d.ts.map +1 -0
  194. package/dist/auth/core.js +528 -0
  195. package/dist/auth/core.js.map +1 -0
  196. package/dist/auth/index.d.ts +56 -0
  197. package/dist/auth/index.d.ts.map +1 -0
  198. package/dist/auth/index.js +58 -0
  199. package/dist/auth/index.js.map +1 -0
  200. package/dist/auth/oauth2/index.d.ts +5 -0
  201. package/dist/auth/oauth2/index.d.ts.map +1 -0
  202. package/dist/auth/oauth2/index.js +5 -0
  203. package/dist/auth/oauth2/index.js.map +1 -0
  204. package/dist/auth/oauth2/utils.d.ts +90 -0
  205. package/dist/auth/oauth2/utils.d.ts.map +1 -0
  206. package/dist/auth/oauth2/utils.js +167 -0
  207. package/dist/auth/oauth2/utils.js.map +1 -0
  208. package/dist/auth/providers/apple.d.ts +28 -0
  209. package/dist/auth/providers/apple.d.ts.map +1 -0
  210. package/dist/auth/providers/apple.js +192 -0
  211. package/dist/auth/providers/apple.js.map +1 -0
  212. package/dist/auth/providers/credential.d.ts +87 -0
  213. package/dist/auth/providers/credential.d.ts.map +1 -0
  214. package/dist/auth/providers/credential.js +162 -0
  215. package/dist/auth/providers/credential.js.map +1 -0
  216. package/dist/auth/providers/facebook.d.ts +26 -0
  217. package/dist/auth/providers/facebook.d.ts.map +1 -0
  218. package/dist/auth/providers/facebook.js +112 -0
  219. package/dist/auth/providers/facebook.js.map +1 -0
  220. package/dist/auth/providers/github.d.ts +29 -0
  221. package/dist/auth/providers/github.d.ts.map +1 -0
  222. package/dist/auth/providers/github.js +144 -0
  223. package/dist/auth/providers/github.js.map +1 -0
  224. package/dist/auth/providers/google.d.ts +32 -0
  225. package/dist/auth/providers/google.d.ts.map +1 -0
  226. package/dist/auth/providers/google.js +145 -0
  227. package/dist/auth/providers/google.js.map +1 -0
  228. package/dist/auth/providers/index.d.ts +22 -0
  229. package/dist/auth/providers/index.d.ts.map +1 -0
  230. package/dist/auth/providers/index.js +17 -0
  231. package/dist/auth/providers/index.js.map +1 -0
  232. package/dist/auth/routes.d.ts +63 -0
  233. package/dist/auth/routes.d.ts.map +1 -0
  234. package/dist/auth/routes.js +827 -0
  235. package/dist/auth/routes.js.map +1 -0
  236. package/dist/auth/services/index.d.ts +10 -0
  237. package/dist/auth/services/index.d.ts.map +1 -0
  238. package/dist/auth/services/index.js +7 -0
  239. package/dist/auth/services/index.js.map +1 -0
  240. package/dist/auth/services/session.d.ts +81 -0
  241. package/dist/auth/services/session.d.ts.map +1 -0
  242. package/dist/auth/services/session.js +186 -0
  243. package/dist/auth/services/session.js.map +1 -0
  244. package/dist/auth/services/token.d.ts +41 -0
  245. package/dist/auth/services/token.d.ts.map +1 -0
  246. package/dist/auth/services/token.js +44 -0
  247. package/dist/auth/services/token.js.map +1 -0
  248. package/dist/auth/services/verification.d.ts +77 -0
  249. package/dist/auth/services/verification.d.ts.map +1 -0
  250. package/dist/auth/services/verification.js +143 -0
  251. package/dist/auth/services/verification.js.map +1 -0
  252. package/dist/auth/types.d.ts +318 -0
  253. package/dist/auth/types.d.ts.map +1 -0
  254. package/dist/auth/types.js +6 -0
  255. package/dist/auth/types.js.map +1 -0
  256. package/dist/customTypes/arrays.d.ts +200 -0
  257. package/dist/customTypes/arrays.d.ts.map +1 -0
  258. package/dist/customTypes/arrays.js +309 -0
  259. package/dist/customTypes/arrays.js.map +1 -0
  260. package/dist/customTypes/index.d.ts +8 -0
  261. package/dist/customTypes/index.d.ts.map +1 -0
  262. package/dist/customTypes/index.js +11 -0
  263. package/dist/customTypes/index.js.map +1 -0
  264. package/dist/customTypes/postgis.d.ts +146 -0
  265. package/dist/customTypes/postgis.d.ts.map +1 -0
  266. package/dist/customTypes/postgis.js +315 -0
  267. package/dist/customTypes/postgis.js.map +1 -0
  268. package/dist/customTypes/ranges.d.ts +128 -0
  269. package/dist/customTypes/ranges.d.ts.map +1 -0
  270. package/dist/customTypes/ranges.js +257 -0
  271. package/dist/customTypes/ranges.js.map +1 -0
  272. package/dist/index.d.ts +37 -0
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +42 -0
  275. package/dist/index.js.map +1 -0
  276. package/dist/migrations/0.1.0-alpha.0_initial_setup.d.ts +29 -0
  277. package/dist/migrations/0.1.0-alpha.0_initial_setup.d.ts.map +1 -0
  278. package/dist/migrations/0.1.0-alpha.0_initial_setup.js +72 -0
  279. package/dist/migrations/0.1.0-alpha.0_initial_setup.js.map +1 -0
  280. package/dist/migrations/_example_migration.d.ts +31 -0
  281. package/dist/migrations/_example_migration.d.ts.map +1 -0
  282. package/dist/migrations/_example_migration.js +75 -0
  283. package/dist/migrations/_example_migration.js.map +1 -0
  284. package/dist/plugins/definePlugin.d.ts +49 -0
  285. package/dist/plugins/definePlugin.d.ts.map +1 -0
  286. package/dist/plugins/definePlugin.js +131 -0
  287. package/dist/plugins/definePlugin.js.map +1 -0
  288. package/dist/plugins/softDelete.d.ts +179 -0
  289. package/dist/plugins/softDelete.d.ts.map +1 -0
  290. package/dist/plugins/softDelete.js +235 -0
  291. package/dist/plugins/softDelete.js.map +1 -0
  292. package/dist/routes/auth.route.d.ts +14 -0
  293. package/dist/routes/auth.route.d.ts.map +1 -0
  294. package/dist/routes/auth.route.js +421 -0
  295. package/dist/routes/auth.route.js.map +1 -0
  296. package/dist/routes/file.route.d.ts +7 -0
  297. package/dist/routes/file.route.d.ts.map +1 -0
  298. package/dist/routes/file.route.js +274 -0
  299. package/dist/routes/file.route.js.map +1 -0
  300. package/dist/routes/items.route.d.ts +7 -0
  301. package/dist/routes/items.route.d.ts.map +1 -0
  302. package/dist/routes/items.route.js +369 -0
  303. package/dist/routes/items.route.js.map +1 -0
  304. package/dist/routes/migration.route.d.ts +7 -0
  305. package/dist/routes/migration.route.d.ts.map +1 -0
  306. package/dist/routes/migration.route.js +225 -0
  307. package/dist/routes/migration.route.js.map +1 -0
  308. package/dist/routes/notification.route.d.ts +7 -0
  309. package/dist/routes/notification.route.d.ts.map +1 -0
  310. package/dist/routes/notification.route.js +124 -0
  311. package/dist/routes/notification.route.js.map +1 -0
  312. package/dist/routes/openapi.route.d.ts +7 -0
  313. package/dist/routes/openapi.route.d.ts.map +1 -0
  314. package/dist/routes/openapi.route.js +2169 -0
  315. package/dist/routes/openapi.route.js.map +1 -0
  316. package/dist/routes/permission.route.d.ts +7 -0
  317. package/dist/routes/permission.route.d.ts.map +1 -0
  318. package/dist/routes/permission.route.js +158 -0
  319. package/dist/routes/permission.route.js.map +1 -0
  320. package/dist/routes/realtime.route.d.ts +21 -0
  321. package/dist/routes/realtime.route.d.ts.map +1 -0
  322. package/dist/routes/realtime.route.js +243 -0
  323. package/dist/routes/realtime.route.js.map +1 -0
  324. package/dist/routes/reports.route.d.ts +7 -0
  325. package/dist/routes/reports.route.d.ts.map +1 -0
  326. package/dist/routes/reports.route.js +95 -0
  327. package/dist/routes/reports.route.js.map +1 -0
  328. package/dist/routes/schema.route.d.ts +7 -0
  329. package/dist/routes/schema.route.d.ts.map +1 -0
  330. package/dist/routes/schema.route.js +1780 -0
  331. package/dist/routes/schema.route.js.map +1 -0
  332. package/dist/routes/settings.route.d.ts +7 -0
  333. package/dist/routes/settings.route.d.ts.map +1 -0
  334. package/dist/routes/settings.route.js +154 -0
  335. package/dist/routes/settings.route.js.map +1 -0
  336. package/dist/routes/templates.route.d.ts +7 -0
  337. package/dist/routes/templates.route.d.ts.map +1 -0
  338. package/dist/routes/templates.route.js +91 -0
  339. package/dist/routes/templates.route.js.map +1 -0
  340. package/dist/routes/utils.route.d.ts +7 -0
  341. package/dist/routes/utils.route.d.ts.map +1 -0
  342. package/dist/routes/utils.route.js +33 -0
  343. package/dist/routes/utils.route.js.map +1 -0
  344. package/dist/routes/workflow.route.d.ts +7 -0
  345. package/dist/routes/workflow.route.d.ts.map +1 -0
  346. package/dist/routes/workflow.route.js +787 -0
  347. package/dist/routes/workflow.route.js.map +1 -0
  348. package/dist/services/AssetsService.d.ts +39 -0
  349. package/dist/services/AssetsService.d.ts.map +1 -0
  350. package/dist/services/AssetsService.js +255 -0
  351. package/dist/services/AssetsService.js.map +1 -0
  352. package/dist/services/CacheService.d.ts +169 -0
  353. package/dist/services/CacheService.d.ts.map +1 -0
  354. package/dist/services/CacheService.js +722 -0
  355. package/dist/services/CacheService.js.map +1 -0
  356. package/dist/services/FilesService.d.ts +30 -0
  357. package/dist/services/FilesService.d.ts.map +1 -0
  358. package/dist/services/FilesService.js +268 -0
  359. package/dist/services/FilesService.js.map +1 -0
  360. package/dist/services/HooksManager.d.ts +38 -0
  361. package/dist/services/HooksManager.d.ts.map +1 -0
  362. package/dist/services/HooksManager.js +165 -0
  363. package/dist/services/HooksManager.js.map +1 -0
  364. package/dist/services/ItemsService.d.ts +273 -0
  365. package/dist/services/ItemsService.d.ts.map +1 -0
  366. package/dist/services/ItemsService.js +2458 -0
  367. package/dist/services/ItemsService.js.map +1 -0
  368. package/dist/services/MailService.d.ts +76 -0
  369. package/dist/services/MailService.d.ts.map +1 -0
  370. package/dist/services/MailService.js +585 -0
  371. package/dist/services/MailService.js.map +1 -0
  372. package/dist/services/MigrationService.d.ts +243 -0
  373. package/dist/services/MigrationService.d.ts.map +1 -0
  374. package/dist/services/MigrationService.js +914 -0
  375. package/dist/services/MigrationService.js.map +1 -0
  376. package/dist/services/NotificationService.d.ts +35 -0
  377. package/dist/services/NotificationService.d.ts.map +1 -0
  378. package/dist/services/NotificationService.js +159 -0
  379. package/dist/services/NotificationService.js.map +1 -0
  380. package/dist/services/PermissionService.d.ts +128 -0
  381. package/dist/services/PermissionService.d.ts.map +1 -0
  382. package/dist/services/PermissionService.js +373 -0
  383. package/dist/services/PermissionService.js.map +1 -0
  384. package/dist/services/PluginManager.d.ts +138 -0
  385. package/dist/services/PluginManager.d.ts.map +1 -0
  386. package/dist/services/PluginManager.js +463 -0
  387. package/dist/services/PluginManager.js.map +1 -0
  388. package/dist/services/RealtimeService.d.ts +209 -0
  389. package/dist/services/RealtimeService.d.ts.map +1 -0
  390. package/dist/services/RealtimeService.js +978 -0
  391. package/dist/services/RealtimeService.js.map +1 -0
  392. package/dist/services/ReportService.d.ts +13 -0
  393. package/dist/services/ReportService.d.ts.map +1 -0
  394. package/dist/services/ReportService.js +91 -0
  395. package/dist/services/ReportService.js.map +1 -0
  396. package/dist/services/SettingsService.d.ts +60 -0
  397. package/dist/services/SettingsService.d.ts.map +1 -0
  398. package/dist/services/SettingsService.js +474 -0
  399. package/dist/services/SettingsService.js.map +1 -0
  400. package/dist/services/SocketService.d.ts +129 -0
  401. package/dist/services/SocketService.d.ts.map +1 -0
  402. package/dist/services/SocketService.js +600 -0
  403. package/dist/services/SocketService.js.map +1 -0
  404. package/dist/services/StatsService.d.ts +10 -0
  405. package/dist/services/StatsService.d.ts.map +1 -0
  406. package/dist/services/StatsService.js +40 -0
  407. package/dist/services/StatsService.js.map +1 -0
  408. package/dist/services/StorageService.d.ts +20 -0
  409. package/dist/services/StorageService.d.ts.map +1 -0
  410. package/dist/services/StorageService.js +164 -0
  411. package/dist/services/StorageService.js.map +1 -0
  412. package/dist/services/TasksService.d.ts +74 -0
  413. package/dist/services/TasksService.d.ts.map +1 -0
  414. package/dist/services/TasksService.js +404 -0
  415. package/dist/services/TasksService.js.map +1 -0
  416. package/dist/services/WorkflowService.d.ts +305 -0
  417. package/dist/services/WorkflowService.d.ts.map +1 -0
  418. package/dist/services/WorkflowService.js +1811 -0
  419. package/dist/services/WorkflowService.js.map +1 -0
  420. package/dist/templates/logo/logo.png +0 -0
  421. package/dist/templates/mails/default.liquid +23 -0
  422. package/dist/types/aggregation.d.ts +40 -0
  423. package/dist/types/aggregation.d.ts.map +1 -0
  424. package/dist/types/aggregation.js +6 -0
  425. package/dist/types/aggregation.js.map +1 -0
  426. package/dist/types/assets.d.ts +32 -0
  427. package/dist/types/assets.d.ts.map +1 -0
  428. package/dist/types/assets.js +6 -0
  429. package/dist/types/assets.js.map +1 -0
  430. package/dist/types/auth.d.ts +50 -0
  431. package/dist/types/auth.d.ts.map +1 -0
  432. package/dist/types/auth.js +6 -0
  433. package/dist/types/auth.js.map +1 -0
  434. package/dist/types/cache.d.ts +47 -0
  435. package/dist/types/cache.d.ts.map +1 -0
  436. package/dist/types/cache.js +6 -0
  437. package/dist/types/cache.js.map +1 -0
  438. package/dist/types/database.d.ts +16 -0
  439. package/dist/types/database.d.ts.map +1 -0
  440. package/dist/types/database.js +6 -0
  441. package/dist/types/database.js.map +1 -0
  442. package/dist/types/fields.d.ts +71 -0
  443. package/dist/types/fields.d.ts.map +1 -0
  444. package/dist/types/fields.js +6 -0
  445. package/dist/types/fields.js.map +1 -0
  446. package/dist/types/files.d.ts +33 -0
  447. package/dist/types/files.d.ts.map +1 -0
  448. package/dist/types/files.js +6 -0
  449. package/dist/types/files.js.map +1 -0
  450. package/dist/types/hooks.d.ts +29 -0
  451. package/dist/types/hooks.d.ts.map +1 -0
  452. package/dist/types/hooks.js +6 -0
  453. package/dist/types/hooks.js.map +1 -0
  454. package/dist/types/import-export.d.ts +62 -0
  455. package/dist/types/import-export.d.ts.map +1 -0
  456. package/dist/types/import-export.js +6 -0
  457. package/dist/types/import-export.js.map +1 -0
  458. package/dist/types/index.d.ts +31 -0
  459. package/dist/types/index.d.ts.map +1 -0
  460. package/dist/types/index.js +58 -0
  461. package/dist/types/index.js.map +1 -0
  462. package/dist/types/mail.d.ts +34 -0
  463. package/dist/types/mail.d.ts.map +1 -0
  464. package/dist/types/mail.js +6 -0
  465. package/dist/types/mail.js.map +1 -0
  466. package/dist/types/notifications.d.ts +16 -0
  467. package/dist/types/notifications.d.ts.map +1 -0
  468. package/dist/types/notifications.js +6 -0
  469. package/dist/types/notifications.js.map +1 -0
  470. package/dist/types/plugin.d.ts +351 -0
  471. package/dist/types/plugin.d.ts.map +1 -0
  472. package/dist/types/plugin.js +8 -0
  473. package/dist/types/plugin.js.map +1 -0
  474. package/dist/types/query.d.ts +71 -0
  475. package/dist/types/query.d.ts.map +1 -0
  476. package/dist/types/query.js +6 -0
  477. package/dist/types/query.js.map +1 -0
  478. package/dist/types/relations.d.ts +111 -0
  479. package/dist/types/relations.d.ts.map +1 -0
  480. package/dist/types/relations.js +6 -0
  481. package/dist/types/relations.js.map +1 -0
  482. package/dist/types/reports.d.ts +17 -0
  483. package/dist/types/reports.d.ts.map +1 -0
  484. package/dist/types/reports.js +6 -0
  485. package/dist/types/reports.js.map +1 -0
  486. package/dist/types/schema.d.ts +26 -0
  487. package/dist/types/schema.d.ts.map +1 -0
  488. package/dist/types/schema.js +6 -0
  489. package/dist/types/schema.js.map +1 -0
  490. package/dist/types/seed.d.ts +27 -0
  491. package/dist/types/seed.d.ts.map +1 -0
  492. package/dist/types/seed.js +6 -0
  493. package/dist/types/seed.js.map +1 -0
  494. package/dist/types/services.d.ts +68 -0
  495. package/dist/types/services.d.ts.map +1 -0
  496. package/dist/types/services.js +6 -0
  497. package/dist/types/services.js.map +1 -0
  498. package/dist/types/settings.d.ts +36 -0
  499. package/dist/types/settings.d.ts.map +1 -0
  500. package/dist/types/settings.js +6 -0
  501. package/dist/types/settings.js.map +1 -0
  502. package/dist/types/sockets.d.ts +26 -0
  503. package/dist/types/sockets.d.ts.map +1 -0
  504. package/dist/types/sockets.js +6 -0
  505. package/dist/types/sockets.js.map +1 -0
  506. package/dist/types/sort.d.ts +25 -0
  507. package/dist/types/sort.d.ts.map +1 -0
  508. package/dist/types/sort.js +6 -0
  509. package/dist/types/sort.js.map +1 -0
  510. package/dist/types/spatial.d.ts +19 -0
  511. package/dist/types/spatial.d.ts.map +1 -0
  512. package/dist/types/spatial.js +6 -0
  513. package/dist/types/spatial.js.map +1 -0
  514. package/dist/types/stats.d.ts +21 -0
  515. package/dist/types/stats.d.ts.map +1 -0
  516. package/dist/types/stats.js +6 -0
  517. package/dist/types/stats.js.map +1 -0
  518. package/dist/types/storage.d.ts +19 -0
  519. package/dist/types/storage.d.ts.map +1 -0
  520. package/dist/types/storage.js +6 -0
  521. package/dist/types/storage.js.map +1 -0
  522. package/dist/types/tasks.d.ts +14 -0
  523. package/dist/types/tasks.d.ts.map +1 -0
  524. package/dist/types/tasks.js +6 -0
  525. package/dist/types/tasks.js.map +1 -0
  526. package/dist/types/utils.d.ts +54 -0
  527. package/dist/types/utils.d.ts.map +1 -0
  528. package/dist/types/utils.js +6 -0
  529. package/dist/types/utils.js.map +1 -0
  530. package/dist/types/workflow.d.ts +17 -0
  531. package/dist/types/workflow.d.ts.map +1 -0
  532. package/dist/types/workflow.js +6 -0
  533. package/dist/types/workflow.js.map +1 -0
  534. package/dist/utils/aggregationUtils.d.ts +192 -0
  535. package/dist/utils/aggregationUtils.d.ts.map +1 -0
  536. package/dist/utils/aggregationUtils.js +450 -0
  537. package/dist/utils/aggregationUtils.js.map +1 -0
  538. package/dist/utils/auth.d.ts +93 -0
  539. package/dist/utils/auth.d.ts.map +1 -0
  540. package/dist/utils/auth.js +557 -0
  541. package/dist/utils/auth.js.map +1 -0
  542. package/dist/utils/cache.d.ts +64 -0
  543. package/dist/utils/cache.d.ts.map +1 -0
  544. package/dist/utils/cache.js +464 -0
  545. package/dist/utils/cache.js.map +1 -0
  546. package/dist/utils/common.d.ts +53 -0
  547. package/dist/utils/common.d.ts.map +1 -0
  548. package/dist/utils/common.js +162 -0
  549. package/dist/utils/common.js.map +1 -0
  550. package/dist/utils/db.d.ts +101 -0
  551. package/dist/utils/db.d.ts.map +1 -0
  552. package/dist/utils/db.js +413 -0
  553. package/dist/utils/db.js.map +1 -0
  554. package/dist/utils/dirname.d.ts +30 -0
  555. package/dist/utils/dirname.d.ts.map +1 -0
  556. package/dist/utils/dirname.js +95 -0
  557. package/dist/utils/dirname.js.map +1 -0
  558. package/dist/utils/dynamicVariableResolver.d.ts +17 -0
  559. package/dist/utils/dynamicVariableResolver.d.ts.map +1 -0
  560. package/dist/utils/dynamicVariableResolver.js +262 -0
  561. package/dist/utils/dynamicVariableResolver.js.map +1 -0
  562. package/dist/utils/env.d.ts +38 -0
  563. package/dist/utils/env.d.ts.map +1 -0
  564. package/dist/utils/env.js +80 -0
  565. package/dist/utils/env.js.map +1 -0
  566. package/dist/utils/errorHandler.d.ts +14 -0
  567. package/dist/utils/errorHandler.d.ts.map +1 -0
  568. package/dist/utils/errorHandler.js +79 -0
  569. package/dist/utils/errorHandler.js.map +1 -0
  570. package/dist/utils/fieldExpansion.d.ts +30 -0
  571. package/dist/utils/fieldExpansion.d.ts.map +1 -0
  572. package/dist/utils/fieldExpansion.js +145 -0
  573. package/dist/utils/fieldExpansion.js.map +1 -0
  574. package/dist/utils/fieldUtils.d.ts +179 -0
  575. package/dist/utils/fieldUtils.d.ts.map +1 -0
  576. package/dist/utils/fieldUtils.js +424 -0
  577. package/dist/utils/fieldUtils.js.map +1 -0
  578. package/dist/utils/filterOperators.d.ts +472 -0
  579. package/dist/utils/filterOperators.d.ts.map +1 -0
  580. package/dist/utils/filterOperators.js +1229 -0
  581. package/dist/utils/filterOperators.js.map +1 -0
  582. package/dist/utils/importUtils.d.ts +127 -0
  583. package/dist/utils/importUtils.d.ts.map +1 -0
  584. package/dist/utils/importUtils.js +437 -0
  585. package/dist/utils/importUtils.js.map +1 -0
  586. package/dist/utils/index.d.ts +75 -0
  587. package/dist/utils/index.d.ts.map +1 -0
  588. package/dist/utils/index.js +101 -0
  589. package/dist/utils/index.js.map +1 -0
  590. package/dist/utils/logger.d.ts +41 -0
  591. package/dist/utils/logger.d.ts.map +1 -0
  592. package/dist/utils/logger.js +217 -0
  593. package/dist/utils/logger.js.map +1 -0
  594. package/dist/utils/orderUtils.d.ts +117 -0
  595. package/dist/utils/orderUtils.d.ts.map +1 -0
  596. package/dist/utils/orderUtils.js +249 -0
  597. package/dist/utils/orderUtils.js.map +1 -0
  598. package/dist/utils/queryBuilder.d.ts +118 -0
  599. package/dist/utils/queryBuilder.d.ts.map +1 -0
  600. package/dist/utils/queryBuilder.js +489 -0
  601. package/dist/utils/queryBuilder.js.map +1 -0
  602. package/dist/utils/relationLoader.d.ts +65 -0
  603. package/dist/utils/relationLoader.d.ts.map +1 -0
  604. package/dist/utils/relationLoader.js +1081 -0
  605. package/dist/utils/relationLoader.js.map +1 -0
  606. package/dist/utils/relationPathResolver.d.ts +30 -0
  607. package/dist/utils/relationPathResolver.d.ts.map +1 -0
  608. package/dist/utils/relationPathResolver.js +173 -0
  609. package/dist/utils/relationPathResolver.js.map +1 -0
  610. package/dist/utils/relationUtils.d.ts +139 -0
  611. package/dist/utils/relationUtils.d.ts.map +1 -0
  612. package/dist/utils/relationUtils.js +711 -0
  613. package/dist/utils/relationUtils.js.map +1 -0
  614. package/dist/utils/router.d.ts +6 -0
  615. package/dist/utils/router.d.ts.map +1 -0
  616. package/dist/utils/router.js +95 -0
  617. package/dist/utils/router.js.map +1 -0
  618. package/dist/utils/schema.d.ts +88 -0
  619. package/dist/utils/schema.d.ts.map +1 -0
  620. package/dist/utils/schema.js +24 -0
  621. package/dist/utils/schema.js.map +1 -0
  622. package/dist/utils/schemaManager.d.ts +238 -0
  623. package/dist/utils/schemaManager.d.ts.map +1 -0
  624. package/dist/utils/schemaManager.js +1992 -0
  625. package/dist/utils/schemaManager.js.map +1 -0
  626. package/dist/utils/schemaValidator.d.ts +83 -0
  627. package/dist/utils/schemaValidator.d.ts.map +1 -0
  628. package/dist/utils/schemaValidator.js +491 -0
  629. package/dist/utils/schemaValidator.js.map +1 -0
  630. package/dist/utils/seed.d.ts +45 -0
  631. package/dist/utils/seed.d.ts.map +1 -0
  632. package/dist/utils/seed.js +248 -0
  633. package/dist/utils/seed.js.map +1 -0
  634. package/dist/utils/sessionCleanup.d.ts +10 -0
  635. package/dist/utils/sessionCleanup.d.ts.map +1 -0
  636. package/dist/utils/sessionCleanup.js +49 -0
  637. package/dist/utils/sessionCleanup.js.map +1 -0
  638. package/dist/utils/sortUtils.d.ts +117 -0
  639. package/dist/utils/sortUtils.d.ts.map +1 -0
  640. package/dist/utils/sortUtils.js +232 -0
  641. package/dist/utils/sortUtils.js.map +1 -0
  642. package/dist/utils/spatialUtils.d.ts +244 -0
  643. package/dist/utils/spatialUtils.d.ts.map +1 -0
  644. package/dist/utils/spatialUtils.js +359 -0
  645. package/dist/utils/spatialUtils.js.map +1 -0
  646. package/dist/utils/systemschema.d.ts +11040 -0
  647. package/dist/utils/systemschema.d.ts.map +1 -0
  648. package/dist/utils/systemschema.js +1777 -0
  649. package/dist/utils/systemschema.js.map +1 -0
  650. package/dist/utils/tenantUtils.d.ts +34 -0
  651. package/dist/utils/tenantUtils.d.ts.map +1 -0
  652. package/dist/utils/tenantUtils.js +124 -0
  653. package/dist/utils/tenantUtils.js.map +1 -0
  654. package/dist/utils/typeMapper.d.ts +25 -0
  655. package/dist/utils/typeMapper.d.ts.map +1 -0
  656. package/dist/utils/typeMapper.js +282 -0
  657. package/dist/utils/typeMapper.js.map +1 -0
  658. package/dist/utils/valueValidator.d.ts +60 -0
  659. package/dist/utils/valueValidator.d.ts.map +1 -0
  660. package/dist/utils/valueValidator.js +303 -0
  661. package/dist/utils/valueValidator.js.map +1 -0
  662. package/dist/utils/workflow.d.ts +87 -0
  663. package/dist/utils/workflow.d.ts.map +1 -0
  664. package/dist/utils/workflow.js +205 -0
  665. package/dist/utils/workflow.js.map +1 -0
  666. package/package.json +115 -0
@@ -0,0 +1,1081 @@
1
+ /**
2
+ * Relation Loader Module for Drizzle ORM
3
+ *
4
+ * This module provides utilities for building joins and loading related data
5
+ * in Drizzle ORM, matching Sequelize's include/association behavior.
6
+ *
7
+ * Features:
8
+ * - BelongsTo join building
9
+ * - HasOne join building
10
+ * - HasMany separate query loading
11
+ * - BelongsToMany (M2M) through junction tables
12
+ * - M2A polymorphic relations
13
+ * - Nested relation loading (include.include)
14
+ * - Relation filtering and ordering
15
+ */
16
+ import { sql, and, isNull } from 'drizzle-orm';
17
+ import { alias } from 'drizzle-orm/pg-core';
18
+ import { schemaManager } from './schemaManager.js';
19
+ import { relationBuilder } from './relationUtils.js';
20
+ import { drizzleWhere } from './queryBuilder.js';
21
+ /**
22
+ * Extract field paths and build include tree
23
+ *
24
+ * @param fields - Array of field paths (e.g., ['id', 'name', 'author.name', 'author.posts.title'])
25
+ * @param tableName - Main table name
26
+ * @returns Expanded fields result with includes
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const fields = ['id', 'title', 'author.name', 'author.posts.title'];
31
+ * const result = expandFieldsWithIncludes(fields, 'posts');
32
+ *
33
+ * // result.directFields: ['id', 'title']
34
+ * // result.includes: [
35
+ * // {
36
+ * // relation: 'author',
37
+ * // nested: [{ relation: 'posts', ... }]
38
+ * // }
39
+ * // ]
40
+ * ```
41
+ */
42
+ /**
43
+ * Expand nested wildcards recursively up to maxDepth levels
44
+ * Example: "Review.*.*" expands to include all Review fields and all nested relations
45
+ *
46
+ * @param relationName - The relation to expand (e.g., "Review")
47
+ * @param tableName - The source table name
48
+ * @param wildcardCount - Number of wildcards after relation (e.g., 2 for "Review.*.*")
49
+ * @param maxDepth - Maximum depth to expand (default 7)
50
+ * @param currentDepth - Current recursion depth (internal use)
51
+ * @returns IncludeConfig with expanded relations
52
+ */
53
+ function expandNestedWildcards(relationName, tableName, wildcardCount, maxDepth = 7, currentDepth = 0) {
54
+ // Stop if we've reached max depth
55
+ if (currentDepth >= maxDepth || wildcardCount === 0) {
56
+ return null;
57
+ }
58
+ // Get associations for the source table
59
+ const associations = relationBuilder.getAssociations(tableName);
60
+ if (!associations) {
61
+ console.warn(`No associations found for table '${tableName}'`);
62
+ return null;
63
+ }
64
+ const association = associations[relationName];
65
+ if (!association) {
66
+ console.warn(`Association '${relationName}' not found on ${tableName}`);
67
+ return null;
68
+ }
69
+ // Start building the include config
70
+ const config = {
71
+ relation: relationName,
72
+ attributes: ['*'], // First wildcard means all fields
73
+ include: []
74
+ };
75
+ // If we have more wildcards, expand nested relations
76
+ if (wildcardCount > 1) {
77
+ const targetTable = association.model;
78
+ const nestedAssociations = relationBuilder.getAssociations(targetTable);
79
+ if (nestedAssociations) {
80
+ // For each nested relation, recursively expand
81
+ for (const [nestedRelationName, nestedAssoc] of Object.entries(nestedAssociations)) {
82
+ const nestedConfig = expandNestedWildcards(nestedRelationName, targetTable, wildcardCount - 1, maxDepth, currentDepth + 1);
83
+ if (nestedConfig) {
84
+ config.include.push(nestedConfig);
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return config;
90
+ }
91
+ export function expandFieldsWithIncludes(fields, tableName) {
92
+ const directFields = [];
93
+ const relationMap = new Map();
94
+ for (const field of fields) {
95
+ if (field === '*') {
96
+ // Wildcard - get all direct fields
97
+ const schema = schemaManager.getSchema(tableName);
98
+ if (schema) {
99
+ const allFields = Object.keys(schema);
100
+ directFields.push(...allFields);
101
+ }
102
+ continue;
103
+ }
104
+ if (!field.includes('.')) {
105
+ // Direct field
106
+ if (!directFields.includes(field)) {
107
+ directFields.push(field);
108
+ }
109
+ }
110
+ else {
111
+ // Relational field (e.g., 'author.name' or 'author.posts.title')
112
+ const parts = field.split('.');
113
+ const relationName = parts[0];
114
+ const remainingPath = parts.slice(1).join('.');
115
+ // Check if this is a nested wildcard pattern (e.g., "Review.*.*")
116
+ const remainingParts = parts.slice(1);
117
+ const wildcardCount = remainingParts.filter(p => p === '*').length;
118
+ const isNestedWildcard = wildcardCount > 0 && remainingParts.every(p => p === '*');
119
+ if (isNestedWildcard && wildcardCount >= 2) {
120
+ // Handle nested wildcard expansion
121
+ const expandedConfig = expandNestedWildcards(relationName, tableName, wildcardCount);
122
+ if (expandedConfig) {
123
+ if (relationMap.has(relationName)) {
124
+ // Merge with existing config
125
+ const existing = relationMap.get(relationName);
126
+ if (!existing.attributes.includes('*')) {
127
+ existing.attributes.push('*');
128
+ }
129
+ // Merge includes
130
+ for (const nestedInc of expandedConfig.include) {
131
+ const existingNested = existing.include.find(inc => inc.relation === nestedInc.relation);
132
+ if (!existingNested) {
133
+ existing.include.push(nestedInc);
134
+ }
135
+ else {
136
+ // Merge nested includes recursively
137
+ mergeIncludeConfigs(existingNested, nestedInc);
138
+ }
139
+ }
140
+ }
141
+ else {
142
+ relationMap.set(relationName, expandedConfig);
143
+ }
144
+ }
145
+ continue;
146
+ }
147
+ if (!relationMap.has(relationName)) {
148
+ relationMap.set(relationName, {
149
+ relation: relationName,
150
+ attributes: [],
151
+ include: []
152
+ });
153
+ }
154
+ const includeConfig = relationMap.get(relationName);
155
+ if (parts.length === 2) {
156
+ // Direct field on related table (e.g., 'author.name' or 'author.*')
157
+ if (remainingPath === '*') {
158
+ // Wildcard - mark for expansion later
159
+ if (!includeConfig.attributes.includes('*')) {
160
+ includeConfig.attributes.push('*');
161
+ }
162
+ }
163
+ else if (!includeConfig.attributes.includes(remainingPath)) {
164
+ includeConfig.attributes.push(remainingPath);
165
+ }
166
+ }
167
+ else {
168
+ // Nested relation (e.g., 'author.posts.title' or 'employee.department.company.*')
169
+ // Recursively build nested include structure
170
+ buildNestedInclude(includeConfig, parts.slice(1));
171
+ }
172
+ }
173
+ }
174
+ // Process includes
175
+ const includes = [];
176
+ const relationPaths = new Map();
177
+ for (const [relationName, config] of relationMap) {
178
+ const processed = processIncludeConfig(config, tableName);
179
+ if (processed) {
180
+ includes.push(processed);
181
+ relationPaths.set(relationName, processed);
182
+ // Add nested relation paths
183
+ for (const nested of processed.nested) {
184
+ relationPaths.set(`${relationName}.${nested.relation}`, nested);
185
+ }
186
+ }
187
+ }
188
+ return {
189
+ directFields,
190
+ includes,
191
+ relationPaths
192
+ };
193
+ }
194
+ /**
195
+ * Recursively build nested include structure for deep relation paths
196
+ * E.g., for parts = ['department', 'company', '*'], creates:
197
+ * { relation: 'department', attributes: [], include: [
198
+ * { relation: 'company', attributes: ['*'], include: [] }
199
+ * ]}
200
+ */
201
+ function buildNestedInclude(config, parts) {
202
+ if (parts.length === 0)
203
+ return;
204
+ if (parts.length === 1) {
205
+ // This is a field/attribute, add it to the current config
206
+ if (!config.attributes.includes(parts[0])) {
207
+ config.attributes.push(parts[0]);
208
+ }
209
+ return;
210
+ }
211
+ // This is a nested relation
212
+ const nestedRelation = parts[0];
213
+ let nestedInclude = config.include.find(inc => inc.relation === nestedRelation);
214
+ if (!nestedInclude) {
215
+ nestedInclude = {
216
+ relation: nestedRelation,
217
+ attributes: [],
218
+ include: []
219
+ };
220
+ config.include.push(nestedInclude);
221
+ }
222
+ // Recursively build the rest of the path
223
+ buildNestedInclude(nestedInclude, parts.slice(1));
224
+ }
225
+ /**
226
+ * Merge two IncludeConfig objects recursively
227
+ */
228
+ function mergeIncludeConfigs(target, source) {
229
+ // Merge attributes
230
+ for (const attr of source.attributes || []) {
231
+ if (!target.attributes.includes(attr)) {
232
+ target.attributes.push(attr);
233
+ }
234
+ }
235
+ // Merge includes
236
+ for (const sourceNested of source.include || []) {
237
+ const targetNested = target.include.find(inc => inc.relation === sourceNested.relation);
238
+ if (!targetNested) {
239
+ target.include.push(sourceNested);
240
+ }
241
+ else {
242
+ mergeIncludeConfigs(targetNested, sourceNested);
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * Process include configuration into ProcessedInclude
248
+ */
249
+ function processIncludeConfig(config, sourceTableName, parentPath = '', sourceAlias // Alias of the source table (for nested relations)
250
+ ) {
251
+ // Get association info
252
+ const associations = relationBuilder.getAssociations(sourceTableName);
253
+ if (!associations) {
254
+ console.warn(`No associations found for table '${sourceTableName}'`);
255
+ return null;
256
+ }
257
+ const association = associations[config.relation];
258
+ if (!association) {
259
+ console.warn(`Association '${config.relation}' not found on ${sourceTableName}`);
260
+ return null;
261
+ }
262
+ // Get target table
263
+ const targetTable = schemaManager.getSchema(association.model);
264
+ if (!targetTable) {
265
+ console.warn(`Target table '${association.model}' not found`);
266
+ return null;
267
+ }
268
+ // Expand wildcard in attributes
269
+ let expandedAttributes = config.attributes || [];
270
+ if (expandedAttributes.includes('*')) {
271
+ // Remove the wildcard and add all actual fields
272
+ expandedAttributes = expandedAttributes.filter(attr => attr !== '*');
273
+ const allFields = Object.keys(targetTable);
274
+ expandedAttributes.push(...allFields);
275
+ }
276
+ else if (expandedAttributes.length === 0 && config.include && config.include.length > 0) {
277
+ // If no attributes specified but has nested includes, automatically include all fields
278
+ // This ensures junction tables in M2M relations can load nested data properly
279
+ // e.g., "tags.tags.name" should load junction table fields even without "tags.*"
280
+ const allFields = Object.keys(targetTable);
281
+ expandedAttributes.push(...allFields);
282
+ }
283
+ // Always ensure 'id' is included in attributes for relational queries
284
+ // This prevents SQL errors when joining/grouping by related records
285
+ if (expandedAttributes.length > 0 && !expandedAttributes.includes('id') && targetTable['id']) {
286
+ expandedAttributes.unshift('id');
287
+ }
288
+ // Create a unique alias for the target table
289
+ // For nested relations with same name (e.g., M2M junction.target where both named "chapters"),
290
+ // we need to include the parent path to avoid alias conflicts
291
+ // E.g., "chapters" vs "chapters__chapters" for nested same-name relations
292
+ const uniqueAlias = parentPath ? `${parentPath.replace(/\./g, '__')}__${config.relation}` : config.relation;
293
+ // Create an alias for the target table using the unique alias
294
+ // This allows joining the same table multiple times with different aliases
295
+ const aliasedTable = alias(targetTable, uniqueAlias);
296
+ // Build join condition based on relation type
297
+ // Use sourceAlias (if provided) for JOIN SQL, otherwise use sourceTableName
298
+ // This is critical for nested relations where the parent is aliased
299
+ const joinCondition = buildJoinCondition(association, sourceAlias || sourceTableName, uniqueAlias);
300
+ // Process where clause
301
+ // Use unique alias as tableName for proper alias resolution
302
+ let whereClause;
303
+ if (config.where) {
304
+ whereClause = drizzleWhere(config.where, {
305
+ tableName: uniqueAlias,
306
+ schema: aliasedTable
307
+ });
308
+ }
309
+ // Process nested includes
310
+ const nested = [];
311
+ if (config.include && config.include.length > 0) {
312
+ for (const nestedConfig of config.include) {
313
+ const processedNested = processIncludeConfig(nestedConfig, association.model, parentPath ? `${parentPath}.${config.relation}` : config.relation, uniqueAlias // Pass unique alias as the source alias for nested includes
314
+ );
315
+ if (processedNested) {
316
+ nested.push(processedNested);
317
+ }
318
+ }
319
+ }
320
+ // Determine if separate query needed (for HasMany and BelongsToMany)
321
+ // Both relation types require separate queries since they can't be efficiently joined
322
+ const separate = config.separate !== undefined
323
+ ? config.separate
324
+ : association.type === 'HasMany' || association.type === 'BelongsToMany';
325
+ return {
326
+ relation: config.relation,
327
+ relationType: association.type,
328
+ table: aliasedTable,
329
+ joinCondition,
330
+ where: whereClause,
331
+ attributes: expandedAttributes,
332
+ nested,
333
+ required: config.required || false,
334
+ separate,
335
+ alias: uniqueAlias // Store the unique alias for use in queries
336
+ };
337
+ }
338
+ /**
339
+ * Build join condition for an association
340
+ */
341
+ function buildJoinCondition(association, sourceTableName, relationName = '') {
342
+ const { type, foreignKey, model } = association;
343
+ const targetKey = association.targetKey || 'id';
344
+ // Use relationName as the table alias in JOIN conditions
345
+ // This allows joining the same table multiple times with different aliases
346
+ const targetTableName = relationName || model;
347
+ switch (type) {
348
+ case 'BelongsTo':
349
+ // Source.foreignKey = Target.targetKey (usually id)
350
+ return sql `${sql.raw(`"${sourceTableName}"."${foreignKey}"`)} = ${sql.raw(`"${targetTableName}"."${targetKey}"`)}`;
351
+ case 'HasOne':
352
+ case 'HasMany':
353
+ // Target.foreignKey = Source.id
354
+ return sql `${sql.raw(`"${targetTableName}"."${foreignKey}"`)} = ${sql.raw(`"${sourceTableName}"."id"`)}`;
355
+ case 'BelongsToMany':
356
+ // Requires junction table - handle separately
357
+ const { through, otherKey } = association;
358
+ if (through) {
359
+ // Source.id = Junction.foreignKey
360
+ // Junction.otherKey = Target.id
361
+ return sql `${sql.raw(`"${sourceTableName}"."id"`)} = ${sql.raw(`"${through}"."${foreignKey}"`)} AND ${sql.raw(`"${through}"."${otherKey}"`)} = ${sql.raw(`"${targetTableName}"."id"`)}`;
362
+ }
363
+ throw new Error(`BelongsToMany association '${relationName}' missing through table`);
364
+ case 'M2A':
365
+ // Polymorphic - Target.id = Source.foreignKey AND Target.type = Source.typeKey
366
+ const typeKey = association.typeKey || `${relationName}Type`;
367
+ const typeValue = association.typeValue || model;
368
+ return and(sql `${sql.raw(`"${targetTableName}"."id"`)} = ${sql.raw(`"${sourceTableName}"."${foreignKey}"`)}`, sql `${sql.raw(`"${sourceTableName}"."${typeKey}"`)} = ${typeValue}`) || sql `1=1`;
369
+ default:
370
+ throw new Error(`Unknown relation type: ${type}`);
371
+ }
372
+ }
373
+ /**
374
+ * Build LEFT JOIN clause for includes
375
+ * Only for BelongsTo and HasOne relations
376
+ * HasMany will use separate queries
377
+ */
378
+ export function buildJoinsForIncludes(includes) {
379
+ const joins = [];
380
+ for (const include of includes) {
381
+ if (include.separate) {
382
+ // Skip - will be loaded separately
383
+ continue;
384
+ }
385
+ if (include.relationType === 'BelongsTo' || include.relationType === 'HasOne') {
386
+ // Build LEFT JOIN or INNER JOIN
387
+ const joinType = include.required ? 'INNER JOIN' : 'LEFT JOIN';
388
+ const tableName = include.table;
389
+ let joinClause = sql `${sql.raw(joinType)} ${sql.raw(String(tableName))} ON ${include.joinCondition}`;
390
+ // Add WHERE conditions to join
391
+ if (include.where) {
392
+ joinClause = sql `${joinClause} AND ${include.where}`;
393
+ }
394
+ joins.push(joinClause);
395
+ // Process nested joins
396
+ if (include.nested.length > 0) {
397
+ const nestedJoins = buildJoinsForIncludes(include.nested);
398
+ joins.push(...nestedJoins);
399
+ }
400
+ }
401
+ }
402
+ return joins;
403
+ }
404
+ /**
405
+ * Load HasMany relations with separate queries
406
+ * This is more efficient than joining for one-to-many relations
407
+ */
408
+ export async function loadHasManyRelations(db, mainRecords, includes, sourceTableName) {
409
+ if (!mainRecords || mainRecords.length === 0) {
410
+ return mainRecords;
411
+ }
412
+ for (const include of includes) {
413
+ // If this include has nested HasMany relations, we need to load them even if this include itself is not separate
414
+ // Example: customer_products → product (BelongsTo) → product_contracts (HasMany)
415
+ if ((!include.separate || include.relationType !== 'HasMany') && include.nested.length > 0) {
416
+ // Check if there are nested HasMany relations
417
+ const hasNestedSeparate = include.nested.some(n => n.separate && n.relationType === 'HasMany');
418
+ if (hasNestedSeparate) {
419
+ // For BelongsTo/HasOne relations, the nested records are already loaded and attached
420
+ // We need to collect those nested records and call loadNestedRelationsForHasMany
421
+ const nestedRecords = [];
422
+ for (const mainRecord of mainRecords) {
423
+ const nestedRecord = mainRecord[include.relation];
424
+ if (nestedRecord) {
425
+ // For BelongsTo/HasOne, it's a single record
426
+ nestedRecords.push(nestedRecord);
427
+ }
428
+ }
429
+ if (nestedRecords.length > 0) {
430
+ // Get the target table name for this include
431
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
432
+ const association = associationsMap?.[include.relation];
433
+ if (association) {
434
+ // Recursively load HasMany relations for these nested records
435
+ await loadNestedRelationsForHasMany(db, nestedRecords, include.nested, association.model);
436
+ }
437
+ }
438
+ }
439
+ continue;
440
+ }
441
+ if (!include.separate || include.relationType !== 'HasMany') {
442
+ continue;
443
+ }
444
+ // Get association info
445
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
446
+ if (!associationsMap)
447
+ continue;
448
+ const association = associationsMap[include.relation];
449
+ if (!association)
450
+ continue;
451
+ // Skip polymorphic (M2A) relations - they're handled by loadM2ARelations
452
+ if (association.polymorphic) {
453
+ console.log(`[loadHasManyRelations] Skipping polymorphic relation: ${include.relation}`);
454
+ continue;
455
+ }
456
+ // Get primary key for source table (usually 'id' but could be different)
457
+ const sourceTable = schemaManager.getSchema(sourceTableName);
458
+ const sourcePrimaryKey = schemaManager.getPrimaryKey(sourceTableName) || 'id';
459
+ // Get IDs from main records using the correct primary key
460
+ const mainIds = mainRecords.map(r => r[sourcePrimaryKey]).filter(Boolean);
461
+ if (mainIds.length === 0)
462
+ continue;
463
+ // Build query for related records
464
+ const targetTable = include.table;
465
+ const foreignKey = association.foreignKey || `${sourceTableName}Id`;
466
+ // Build where clause: foreignKey IN (mainIds) AND optional filters
467
+ let whereConditions = [
468
+ sql `${sql.raw(`"${foreignKey}"`)} IN (${sql.join(mainIds.map(id => sql `${id}`), sql `, `)})`
469
+ ];
470
+ // Handle where filter
471
+ // If it's a FilterObject, rebuild it using the actual target table
472
+ // If it's SQL, it was built with an aliased table, so we can't use it directly - skip it
473
+ if (include.where) {
474
+ // Check if it's a FilterObject (has properties like AND, OR, field names)
475
+ // vs SQL object (has queryChunks property)
476
+ const isFilterObject = !('queryChunks' in include.where);
477
+ if (isFilterObject) {
478
+ // It's a FilterObject from relConditions - build SQL for target table
479
+ // Use include.alias if available for proper table alias reference in SQL
480
+ const filterJoins = [];
481
+ const rebuiltWhere = drizzleWhere(include.where, {
482
+ table: targetTable,
483
+ tableName: include.alias || association.model,
484
+ schema: targetTable,
485
+ joins: filterJoins
486
+ });
487
+ if (rebuiltWhere) {
488
+ whereConditions.push(rebuiltWhere);
489
+ }
490
+ // If the filter created joins, we need to apply them to the query
491
+ // For now, log a warning as this is an edge case
492
+ if (filterJoins.length > 0) {
493
+ console.warn('[loadHasManyRelations] Relation filters with nested paths not fully supported yet');
494
+ }
495
+ }
496
+ else {
497
+ // It's a SQL object built with an aliased table - we can't use it in a separate query
498
+ // Log a warning and skip it
499
+ console.warn('[loadHasManyRelations] SQL where filters built with aliases are not supported in separate queries');
500
+ }
501
+ }
502
+ // Check if target table has soft deletes (paranoid mode)
503
+ const isParanoid = schemaManager.isParanoid(association.model);
504
+ if (isParanoid) {
505
+ const deletedAtColumn = targetTable['deletedAt'];
506
+ if (deletedAtColumn) {
507
+ whereConditions.push(isNull(deletedAtColumn));
508
+ }
509
+ }
510
+ const whereClause = whereConditions.length > 1
511
+ ? and(...whereConditions)
512
+ : whereConditions[0];
513
+ // Build select columns - respect include.attributes
514
+ let selectColumns = {};
515
+ if (include.attributes && include.attributes.length > 0) {
516
+ // Select only specified attributes
517
+ for (const attr of include.attributes) {
518
+ const column = targetTable[attr];
519
+ if (column) {
520
+ selectColumns[attr] = column;
521
+ }
522
+ }
523
+ }
524
+ // Always include the foreign key so we can group by it
525
+ if (!selectColumns[foreignKey] && targetTable[foreignKey]) {
526
+ selectColumns[foreignKey] = targetTable[foreignKey];
527
+ }
528
+ // Always include 'id' for nested relations and proper record matching
529
+ if (!selectColumns['id'] && targetTable['id']) {
530
+ selectColumns['id'] = targetTable['id'];
531
+ }
532
+ // Execute query with specific columns or all columns
533
+ const relatedRecords = await db
534
+ .select(Object.keys(selectColumns).length > 0 ? selectColumns : undefined)
535
+ .from(targetTable)
536
+ .where(whereClause);
537
+ // Group by foreign key
538
+ const groupedRecords = new Map();
539
+ for (const record of relatedRecords) {
540
+ const fkValue = record[foreignKey];
541
+ if (!groupedRecords.has(fkValue)) {
542
+ groupedRecords.set(fkValue, []);
543
+ }
544
+ groupedRecords.get(fkValue).push(record);
545
+ }
546
+ // Attach to main records using correct primary key
547
+ for (const mainRecord of mainRecords) {
548
+ mainRecord[include.relation] = groupedRecords.get(mainRecord[sourcePrimaryKey]) || [];
549
+ }
550
+ // Load nested relations for the HasMany records
551
+ if (include.nested && include.nested.length > 0) {
552
+ await loadNestedRelationsForHasMany(db, relatedRecords, include.nested, association.model);
553
+ // Update grouped records with nested data using correct primary key
554
+ for (const mainRecord of mainRecords) {
555
+ const recordsForThis = groupedRecords.get(mainRecord[sourcePrimaryKey]) || [];
556
+ mainRecord[include.relation] = recordsForThis;
557
+ }
558
+ }
559
+ }
560
+ return mainRecords;
561
+ }
562
+ /**
563
+ * Load nested relations for HasMany records
564
+ * This handles nested includes within HasMany relations (e.g., userRoles.role)
565
+ */
566
+ async function loadNestedRelationsForHasMany(db, records, includes, sourceTableName) {
567
+ if (!records || records.length === 0) {
568
+ return;
569
+ }
570
+ for (const include of includes) {
571
+ // For BelongsTo and HasOne, we can load them directly
572
+ if (include.relationType === 'BelongsTo' || include.relationType === 'HasOne') {
573
+ // Get association info
574
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
575
+ if (!associationsMap)
576
+ continue;
577
+ const association = associationsMap[include.relation];
578
+ if (!association)
579
+ continue;
580
+ // Get foreign key values from records
581
+ const foreignKey = association.foreignKey;
582
+ const targetKey = association.targetKey || 'id';
583
+ const foreignKeyValues = records
584
+ .map(r => r[foreignKey])
585
+ .filter(v => v != null);
586
+ if (foreignKeyValues.length === 0)
587
+ continue;
588
+ // Load related records
589
+ const targetTable = include.table;
590
+ let whereConditions = [
591
+ sql `${sql.raw(`"${targetKey}"`)} IN (${sql.join([...new Set(foreignKeyValues)].map(id => sql `${id}`), sql `, `)})`
592
+ ];
593
+ // Handle where filter - check if it's a FilterObject or SQL
594
+ if (include.where) {
595
+ const isFilterObject = !('queryChunks' in include.where);
596
+ if (isFilterObject) {
597
+ // It's a FilterObject from relConditions - build SQL for target table
598
+ // Use include.alias if available for proper table alias reference in SQL
599
+ const filterJoins = [];
600
+ const rebuiltWhere = drizzleWhere(include.where, {
601
+ table: targetTable,
602
+ tableName: include.alias || association.model,
603
+ schema: targetTable,
604
+ joins: filterJoins
605
+ });
606
+ if (rebuiltWhere) {
607
+ whereConditions.push(rebuiltWhere);
608
+ }
609
+ }
610
+ else {
611
+ // It's already SQL
612
+ whereConditions.push(include.where);
613
+ }
614
+ }
615
+ const whereClause = whereConditions.length > 1
616
+ ? and(...whereConditions)
617
+ : whereConditions[0];
618
+ // Build select columns - respect include.attributes
619
+ let selectColumns = {};
620
+ if (include.attributes && include.attributes.length > 0) {
621
+ // Select only specified attributes
622
+ for (const attr of include.attributes) {
623
+ const column = targetTable[attr];
624
+ if (column) {
625
+ selectColumns[attr] = column;
626
+ }
627
+ }
628
+ }
629
+ // Always include the targetKey so we can match records
630
+ if (!selectColumns[targetKey] && targetTable[targetKey]) {
631
+ selectColumns[targetKey] = targetTable[targetKey];
632
+ }
633
+ // Always include 'id' for nested relations and proper record matching
634
+ if (!selectColumns['id'] && targetTable['id']) {
635
+ selectColumns['id'] = targetTable['id'];
636
+ }
637
+ // Execute query with specific columns or all columns
638
+ const relatedRecords = await db
639
+ .select(Object.keys(selectColumns).length > 0 ? selectColumns : undefined)
640
+ .from(targetTable)
641
+ .where(whereClause);
642
+ // Create a map of related records by target key
643
+ const relatedMap = new Map(relatedRecords.map((r) => [r[targetKey], r]));
644
+ // Attach to records
645
+ for (const record of records) {
646
+ const fkValue = record[foreignKey];
647
+ if (fkValue != null) {
648
+ if (include.relationType === 'BelongsTo') {
649
+ record[include.relation] = relatedMap.get(fkValue) || null;
650
+ }
651
+ else {
652
+ // HasOne
653
+ record[include.relation] = relatedMap.get(fkValue) || null;
654
+ }
655
+ }
656
+ else {
657
+ record[include.relation] = null;
658
+ }
659
+ }
660
+ // Recursively load nested includes
661
+ if (include.nested && include.nested.length > 0 && relatedRecords.length > 0) {
662
+ await loadNestedRelationsForHasMany(db, relatedRecords, include.nested, association.model);
663
+ }
664
+ }
665
+ else if (include.relationType === 'HasMany') {
666
+ // Check if this is a polymorphic (M2A) relation
667
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
668
+ const association = associationsMap?.[include.relation];
669
+ if (association?.polymorphic) {
670
+ // Handle M2A relations
671
+ await loadM2ARelations(db, records, [include], sourceTableName);
672
+ }
673
+ else {
674
+ // Recursively handle nested HasMany (non-polymorphic)
675
+ await loadHasManyRelations(db, records, [include], sourceTableName);
676
+ }
677
+ }
678
+ }
679
+ }
680
+ /**
681
+ * Load M2A (polymorphic) relations with junction table
682
+ */
683
+ export async function loadM2ARelations(db, mainRecords, includes, sourceTableName) {
684
+ if (!mainRecords || mainRecords.length === 0) {
685
+ return mainRecords;
686
+ }
687
+ for (const include of includes) {
688
+ // Only process polymorphic HasMany relations (M2A)
689
+ if (!include.separate || include.relationType !== 'HasMany') {
690
+ continue;
691
+ }
692
+ // Get association info
693
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
694
+ if (!associationsMap)
695
+ continue;
696
+ const association = associationsMap[include.relation];
697
+ if (!association || !association.polymorphic)
698
+ continue; // Only handle polymorphic
699
+ console.log(`[loadM2ARelations] Loading M2A relation: ${include.relation}`);
700
+ // Get junction table (target is the junction table for M2A)
701
+ const junctionTable = schemaManager.getSchema(association.model);
702
+ if (!junctionTable) {
703
+ console.warn(`Junction table '${association.model}' not found for M2A relation`);
704
+ continue;
705
+ }
706
+ // Get primary key for source table
707
+ const sourcePrimaryKey = schemaManager.getPrimaryKey(sourceTableName) || 'id';
708
+ const mainIds = mainRecords.map(r => r[sourcePrimaryKey]).filter(Boolean);
709
+ if (mainIds.length === 0)
710
+ continue;
711
+ const foreignKey = association.foreignKey || `${sourceTableName}_id`;
712
+ // Load junction records
713
+ const junctionRecords = await db
714
+ .select()
715
+ .from(junctionTable)
716
+ .where(sql `${sql.raw(`"${foreignKey}"`)} IN (${sql.join(mainIds.map(id => sql `${id}`), sql `, `)})`);
717
+ console.log(`[loadM2ARelations] Loaded ${junctionRecords.length} junction records`);
718
+ if (junctionRecords.length === 0) {
719
+ // No related records - set empty arrays
720
+ for (const mainRecord of mainRecords) {
721
+ mainRecord[include.relation] = [];
722
+ }
723
+ continue;
724
+ }
725
+ // Group junction records by collection type
726
+ const recordsByCollection = new Map();
727
+ for (const junctionRecord of junctionRecords) {
728
+ const collectionName = junctionRecord.collection;
729
+ if (!recordsByCollection.has(collectionName)) {
730
+ recordsByCollection.set(collectionName, []);
731
+ }
732
+ recordsByCollection.get(collectionName).push(junctionRecord);
733
+ }
734
+ console.log(`[loadM2ARelations] Collections found:`, Array.from(recordsByCollection.keys()));
735
+ // Determine which collections to load based on nested includes
736
+ // If nested includes are specified, only load those collections
737
+ // If no nested includes, load all collections found in junction records
738
+ let collectionsToLoad;
739
+ console.log(`[loadM2ARelations] include.nested:`, include.nested?.map(n => ({ relation: n.relation, attributes: n.attributes })));
740
+ if (include.nested && include.nested.length > 0) {
741
+ // Extract collection names from nested includes
742
+ collectionsToLoad = include.nested.map(n => n.relation);
743
+ console.log(`[loadM2ARelations] Loading only requested collections:`, collectionsToLoad);
744
+ }
745
+ else {
746
+ // Load all collections found
747
+ collectionsToLoad = Array.from(recordsByCollection.keys());
748
+ console.log(`[loadM2ARelations] Loading all collections found in junction records`);
749
+ }
750
+ // For each collection, load the target records
751
+ for (const collectionName of collectionsToLoad) {
752
+ const junctionRecs = recordsByCollection.get(collectionName);
753
+ if (!junctionRecs || junctionRecs.length === 0) {
754
+ console.log(`[loadM2ARelations] No junction records found for collection ${collectionName}`);
755
+ continue;
756
+ }
757
+ const targetTable = schemaManager.getSchema(collectionName);
758
+ if (!targetTable) {
759
+ console.warn(`Target table '${collectionName}' not found for M2A relation`);
760
+ continue;
761
+ }
762
+ const targetIds = junctionRecs.map(r => r.item_id).filter(Boolean);
763
+ if (targetIds.length === 0)
764
+ continue;
765
+ // Query target table
766
+ const targetRecords = await db
767
+ .select()
768
+ .from(targetTable)
769
+ .where(sql `"id" IN (${sql.join(targetIds.map(id => sql `${id}`), sql `, `)})`);
770
+ console.log(`[loadM2ARelations] Loaded ${targetRecords.length} records from ${collectionName}`);
771
+ // Create map of target records by ID
772
+ const targetMap = new Map(targetRecords.map((r) => [r.id, r]));
773
+ // Attach target records to junction records
774
+ for (const junctionRec of junctionRecs) {
775
+ const targetRecord = targetMap.get(junctionRec.item_id);
776
+ if (targetRecord) {
777
+ // Attach as nested object with collection name as key
778
+ junctionRec[collectionName] = targetRecord;
779
+ }
780
+ }
781
+ }
782
+ // Filter junction records to only include those with loaded collections
783
+ // This prevents returning junction records for collections we didn't load
784
+ // IMPORTANT: Do this BEFORE processing nested includes
785
+ const filteredJunctionRecords = junctionRecords.filter(jr => {
786
+ const hasLoadedCollection = collectionsToLoad.includes(jr.collection);
787
+ if (!hasLoadedCollection) {
788
+ console.log(`[loadM2ARelations] Filtering out junction record for unloaded collection: ${jr.collection}`);
789
+ }
790
+ return hasLoadedCollection;
791
+ });
792
+ console.log(`[loadM2ARelations] Filtered junction records count: ${filteredJunctionRecords.length} (from ${junctionRecords.length})`);
793
+ // Process nested includes on filtered junction records if any
794
+ if (include.nested && include.nested.length > 0) {
795
+ await loadNestedRelationsForHasMany(db, filteredJunctionRecords, // Use filtered records
796
+ include.nested, association.model);
797
+ }
798
+ // Group junction records by source ID
799
+ const groupedRecords = new Map();
800
+ for (const junctionRecord of filteredJunctionRecords) {
801
+ const sourceId = junctionRecord[foreignKey];
802
+ if (!groupedRecords.has(sourceId)) {
803
+ groupedRecords.set(sourceId, []);
804
+ }
805
+ groupedRecords.get(sourceId).push(junctionRecord);
806
+ }
807
+ // Attach to main records
808
+ for (const mainRecord of mainRecords) {
809
+ mainRecord[include.relation] = groupedRecords.get(mainRecord[sourcePrimaryKey]) || [];
810
+ }
811
+ console.log(`[loadM2ARelations] Completed M2A relation: ${include.relation}`);
812
+ }
813
+ return mainRecords;
814
+ }
815
+ /**
816
+ * Load BelongsToMany (M2M) relations with junction table
817
+ */
818
+ export async function loadBelongsToManyRelations(db, mainRecords, includes, sourceTableName) {
819
+ if (!mainRecords || mainRecords.length === 0) {
820
+ return mainRecords;
821
+ }
822
+ for (const include of includes) {
823
+ if (include.relationType !== 'BelongsToMany') {
824
+ continue;
825
+ }
826
+ // Get association info
827
+ const associationsMap = relationBuilder.getAssociations(sourceTableName);
828
+ if (!associationsMap)
829
+ continue;
830
+ const association = associationsMap[include.relation];
831
+ if (!association || !association.through)
832
+ continue;
833
+ // Get primary key for source table
834
+ const sourcePrimaryKey = schemaManager.getPrimaryKey(sourceTableName) || 'id';
835
+ // Get IDs from main records using correct primary key
836
+ const mainIds = mainRecords.map(r => r[sourcePrimaryKey]).filter(Boolean);
837
+ if (mainIds.length === 0)
838
+ continue;
839
+ // Get junction and target tables
840
+ const junctionTable = schemaManager.getSchema(association.through);
841
+ const targetTable = include.table;
842
+ if (!junctionTable) {
843
+ console.warn(`Junction table '${association.through}' not found`);
844
+ continue;
845
+ }
846
+ const foreignKey = association.foreignKey || `${sourceTableName}Id`; // Key in junction pointing to source
847
+ const otherKey = association.otherKey || `${association.model}Id`; // Key in junction pointing to target
848
+ // Query junction table
849
+ const junctionRecords = await db
850
+ .select()
851
+ .from(junctionTable)
852
+ .where(sql `${sql.raw(`"${foreignKey}"`)} IN (${sql.join(mainIds.map(id => sql `${id}`), sql `, `)})`);
853
+ // Get target IDs from junction
854
+ const targetIds = [...new Set(junctionRecords.map((r) => r[otherKey]))];
855
+ if (targetIds.length === 0) {
856
+ // No related records - set empty arrays
857
+ for (const mainRecord of mainRecords) {
858
+ mainRecord[include.relation] = [];
859
+ }
860
+ continue;
861
+ }
862
+ // Query target table
863
+ let whereConditions = [
864
+ sql `"id" IN (${sql.join(targetIds.map(id => sql `${id}`), sql `, `)})`
865
+ ];
866
+ if (include.where) {
867
+ whereConditions.push(include.where);
868
+ }
869
+ const whereClause = whereConditions.length > 1
870
+ ? and(...whereConditions)
871
+ : whereConditions[0];
872
+ // Build select columns - respect include.attributes
873
+ let selectColumns = {};
874
+ if (include.attributes && include.attributes.length > 0) {
875
+ // Select only specified attributes
876
+ for (const attr of include.attributes) {
877
+ const column = targetTable[attr];
878
+ if (column) {
879
+ selectColumns[attr] = column;
880
+ }
881
+ }
882
+ }
883
+ // Always include 'id' so we can map records
884
+ if (!selectColumns.id && targetTable.id) {
885
+ selectColumns.id = targetTable.id;
886
+ }
887
+ const targetRecords = await db
888
+ .select(Object.keys(selectColumns).length > 0 ? selectColumns : undefined)
889
+ .from(targetTable)
890
+ .where(whereClause);
891
+ // Create target records map
892
+ const targetMap = new Map(targetRecords.map((r) => [r.id, r]));
893
+ // Group by source ID
894
+ const groupedRecords = new Map();
895
+ for (const junctionRecord of junctionRecords) {
896
+ const sourceId = junctionRecord[foreignKey];
897
+ const targetId = junctionRecord[otherKey];
898
+ const targetRecord = targetMap.get(targetId);
899
+ if (targetRecord) {
900
+ if (!groupedRecords.has(sourceId)) {
901
+ groupedRecords.set(sourceId, []);
902
+ }
903
+ groupedRecords.get(sourceId).push(targetRecord);
904
+ }
905
+ }
906
+ // Attach to main records using correct primary key
907
+ for (const mainRecord of mainRecords) {
908
+ mainRecord[include.relation] = groupedRecords.get(mainRecord[sourcePrimaryKey]) || [];
909
+ }
910
+ }
911
+ return mainRecords;
912
+ }
913
+ /**
914
+ * Load all separate-query relations (HasMany, BelongsToMany)
915
+ */
916
+ /**
917
+ * Nest flattened BelongsTo/HasOne relation data from JOINs
918
+ * Converts { "category.name": "Electronics", "category.id": "123" }
919
+ * to { category: { name: "Electronics", id: "123" } }
920
+ */
921
+ export function nestJoinedRelations(records, includes, parentPath = '') {
922
+ if (!records || records.length === 0)
923
+ return records;
924
+ return records.map(record => {
925
+ const nested = { ...record };
926
+ // Process each include
927
+ for (const include of includes) {
928
+ // Skip separate queries (HasMany, BelongsToMany) - they're handled elsewhere
929
+ if (include.separate)
930
+ continue;
931
+ // Only nest BelongsTo and HasOne relations
932
+ if (include.relationType === 'BelongsTo' || include.relationType === 'HasOne') {
933
+ const relationName = include.relation;
934
+ const fullPath = parentPath ? `${parentPath}.${relationName}` : relationName;
935
+ const relationData = {};
936
+ let hasData = false;
937
+ let hasNonNullValue = false;
938
+ // Extract all fields for this relation from the full path
939
+ for (const key in record) {
940
+ if (key.startsWith(`${fullPath}.`)) {
941
+ const fieldName = key.substring(fullPath.length + 1);
942
+ relationData[fieldName] = record[key];
943
+ hasData = true;
944
+ // Check if at least one value is non-null
945
+ if (record[key] !== null && record[key] !== undefined) {
946
+ hasNonNullValue = true;
947
+ }
948
+ // Remove the flattened field
949
+ delete nested[key];
950
+ }
951
+ }
952
+ // Only add the nested object if it has data with at least one non-null value
953
+ // If all values are null, the foreign key was null, so set the relation to null
954
+ if (hasData) {
955
+ nested[relationName] = hasNonNullValue ? relationData : null;
956
+ }
957
+ // Recursively nest nested includes
958
+ // Note: We pass empty parentPath because the nested object's keys don't include the parent prefix
959
+ if (include.nested && include.nested.length > 0 && nested[relationName]) {
960
+ const nestedArray = [nested[relationName]];
961
+ const result = nestJoinedRelations(nestedArray, include.nested, '');
962
+ nested[relationName] = result[0];
963
+ }
964
+ }
965
+ }
966
+ return nested;
967
+ });
968
+ }
969
+ export async function loadSeparateRelations(db, mainRecords, includes, sourceTableName) {
970
+ // First, nest the joined BelongsTo/HasOne relations
971
+ const nestedRecords = nestJoinedRelations(mainRecords, includes);
972
+ // Load M2A (polymorphic) relations
973
+ await loadM2ARelations(db, nestedRecords, includes, sourceTableName);
974
+ // Then load HasMany relations
975
+ await loadHasManyRelations(db, nestedRecords, includes, sourceTableName);
976
+ // Load BelongsToMany relations
977
+ await loadBelongsToManyRelations(db, nestedRecords, includes, sourceTableName);
978
+ return nestedRecords;
979
+ }
980
+ /**
981
+ * Build complete select with joins
982
+ * Returns SELECT columns and JOIN clauses
983
+ */
984
+ export function buildSelectWithJoins(mainTable, directFields, includes) {
985
+ const selectColumns = {};
986
+ // Extract table name from PgTable object
987
+ // Drizzle stores table name in [Table.Symbol.Name] property
988
+ const mainTableName = mainTable[Symbol.for('drizzle:Name')] || mainTable._.name || 'unknown';
989
+ // Add direct fields from main table using actual column references
990
+ // This is required by Drizzle's select() method
991
+ for (const field of directFields) {
992
+ // Use the actual column from the table schema
993
+ const column = mainTable[field];
994
+ if (column) {
995
+ selectColumns[field] = column;
996
+ }
997
+ else {
998
+ console.warn(`[buildSelectWithJoins] Column '${field}' not found in table '${mainTableName}'`);
999
+ console.warn(`[buildSelectWithJoins] Available columns:`, Object.keys(mainTable).filter(k => !k.startsWith('_') && k !== Symbol.for('drizzle:Name')));
1000
+ }
1001
+ }
1002
+ // Add fields from joined relations
1003
+ for (const include of includes) {
1004
+ if (include.separate)
1005
+ continue; // Skip separate query relations
1006
+ const relationAlias = include.relation;
1007
+ const relationTable = include.table;
1008
+ for (const attr of include.attributes) {
1009
+ const columnKey = `${relationAlias}.${attr}`;
1010
+ // Use actual column from the relation table
1011
+ const column = relationTable[attr];
1012
+ if (column) {
1013
+ selectColumns[columnKey] = column;
1014
+ }
1015
+ else {
1016
+ console.warn(`Column '${attr}' not found in relation table '${relationAlias}'`);
1017
+ }
1018
+ }
1019
+ // Process nested includes
1020
+ if (include.nested.length > 0) {
1021
+ addNestedSelectColumns(selectColumns, include.nested, relationAlias);
1022
+ }
1023
+ }
1024
+ // Build join clauses
1025
+ const joins = buildJoinsForIncludes(includes);
1026
+ return { selectColumns, joins };
1027
+ }
1028
+ /**
1029
+ * Add nested relation columns to select
1030
+ */
1031
+ function addNestedSelectColumns(selectColumns, includes, parentPath = '') {
1032
+ for (const include of includes) {
1033
+ if (include.separate)
1034
+ continue;
1035
+ const relationAlias = include.relation;
1036
+ const relationTable = include.table;
1037
+ const fullPath = parentPath ? `${parentPath}.${relationAlias}` : relationAlias;
1038
+ for (const attr of include.attributes) {
1039
+ const columnKey = `${fullPath}.${attr}`;
1040
+ // Use actual column from the relation table
1041
+ const column = relationTable[attr];
1042
+ if (column) {
1043
+ selectColumns[columnKey] = column;
1044
+ }
1045
+ else {
1046
+ console.warn(`Column '${attr}' not found in nested relation table '${relationAlias}'`);
1047
+ }
1048
+ }
1049
+ if (include.nested.length > 0) {
1050
+ addNestedSelectColumns(selectColumns, include.nested, fullPath);
1051
+ }
1052
+ }
1053
+ }
1054
+ /**
1055
+ * Utility: Check if any include requires separate query
1056
+ */
1057
+ export function hasSeparateQueries(includes) {
1058
+ for (const include of includes) {
1059
+ if (include.separate)
1060
+ return true;
1061
+ if (include.nested.length > 0 && hasSeparateQueries(include.nested)) {
1062
+ return true;
1063
+ }
1064
+ }
1065
+ return false;
1066
+ }
1067
+ /**
1068
+ * Utility: Get all relation names from includes (flat list)
1069
+ */
1070
+ export function getRelationNames(includes) {
1071
+ const names = [];
1072
+ for (const include of includes) {
1073
+ names.push(include.relation);
1074
+ if (include.nested.length > 0) {
1075
+ const nestedNames = getRelationNames(include.nested);
1076
+ names.push(...nestedNames.map(n => `${include.relation}.${n}`));
1077
+ }
1078
+ }
1079
+ return names;
1080
+ }
1081
+ //# sourceMappingURL=relationLoader.js.map