@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,2169 @@
1
+ import env from "../utils/env.js";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import { schemaManager } from "../utils/schemaManager.js";
5
+ import { APIError } from "../utils/errorHandler.js";
6
+ import settingsService from "../services/SettingsService.js";
7
+ import { getProjectPath } from "../utils/dirname.js";
8
+ const registerEndpoint = (app) => {
9
+ // OpenAPI specification endpoint
10
+ app.get("/openapi", async (req, res, next) => {
11
+ try {
12
+ const projectInfo = await settingsService.getProjectInfo();
13
+ const baseUrl = projectInfo?.project?.url || "http://localhost:8056";
14
+ const openApiSpec = await generateOpenApiSpec(baseUrl);
15
+ res.status(200).json(openApiSpec);
16
+ }
17
+ catch (error) {
18
+ next(new APIError("Error generating OpenAPI specification", 500, error.message));
19
+ }
20
+ });
21
+ // Swagger UI endpoint
22
+ app.get("/docs", async (req, res) => {
23
+ const projectInfo = await settingsService.getProjectInfo();
24
+ const baseUrl = projectInfo?.project?.url || "http://localhost:8056";
25
+ const swaggerHtml = `
26
+ <!DOCTYPE html>
27
+ <html>
28
+ <head>
29
+ <title>Baasix API Documentation</title>
30
+ <link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui.css" />
31
+ <style>
32
+ html {
33
+ box-sizing: border-box;
34
+ overflow: -moz-scrollbars-vertical;
35
+ overflow-y: scroll;
36
+ }
37
+ *, *:before, *:after {
38
+ box-sizing: inherit;
39
+ }
40
+ body {
41
+ margin:0;
42
+ background: #fafafa;
43
+ }
44
+ </style>
45
+ </head>
46
+ <body>
47
+ <div id="swagger-ui"></div>
48
+ <script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-bundle.js"></script>
49
+ <script src="https://unpkg.com/swagger-ui-dist@5.0.0/swagger-ui-standalone-preset.js"></script>
50
+ <script>
51
+ window.onload = function() {
52
+ const ui = SwaggerUIBundle({
53
+ url: '${baseUrl}/openapi',
54
+ dom_id: '#swagger-ui',
55
+ deepLinking: true,
56
+ presets: [
57
+ SwaggerUIBundle.presets.apis,
58
+ SwaggerUIStandalonePreset
59
+ ],
60
+ plugins: [
61
+ SwaggerUIBundle.plugins.DownloadUrl
62
+ ],
63
+ layout: "StandaloneLayout",
64
+ tryItOutEnabled: false,
65
+ requestInterceptor: function(req) {
66
+ // Add any auth headers or other request modifications here
67
+ return req;
68
+ }
69
+ });
70
+ };
71
+ </script>
72
+ </body>
73
+ </html>`;
74
+ res.send(swaggerHtml);
75
+ });
76
+ };
77
+ function getSystemEndpoints() {
78
+ const authEndpoints = env.get("OPENAPI_INCLUDE_AUTH") === "true" ? [
79
+ // Auth endpoints
80
+ { path: "/auth/register", method: "POST", type: "system", category: "authentication", description: "Register a new user" },
81
+ { path: "/auth/login", method: "POST", type: "system", category: "authentication", description: "Login user" },
82
+ { path: "/auth/logout", method: "GET", type: "system", category: "authentication", description: "Logout user" },
83
+ { path: "/auth/me", method: "GET", type: "system", category: "authentication", description: "Get current user info" },
84
+ { path: "/auth/magiclink", method: "POST", type: "system", category: "authentication", description: "Send magic link" },
85
+ { path: "/auth/magiclink/{token}", method: "GET", type: "system", category: "authentication", description: "Login with magic link" },
86
+ ] : [];
87
+ const multiTenantEndpoints = env.get("OPENAPI_INCLUDE_MULTI_TENANT") === "true" ? [
88
+ // Multi-tenant endpoints
89
+ { path: "/auth/tenants", method: "GET", type: "system", category: "authentication", description: "Get user tenants" },
90
+ { path: "/auth/switch-tenant", method: "POST", type: "system", category: "authentication", description: "Switch user tenant" },
91
+ { path: "/auth/invite", method: "POST", type: "system", category: "authentication", description: "Send user invitation" },
92
+ { path: "/auth/accept-invite", method: "POST", type: "system", category: "authentication", description: "Accept user invitation" },
93
+ { path: "/auth/verify-invite/{token}", method: "GET", type: "system", category: "authentication", description: "Verify invitation token" },
94
+ ] : [];
95
+ const schemaEndpoints = env.get("OPENAPI_INCLUDE_SCHEMA") === "true" ? [
96
+ // Schema management endpoints
97
+ { path: "/schemas", method: "GET", type: "system", category: "schema", description: "Get all schemas" },
98
+ { path: "/schemas", method: "POST", type: "system", category: "schema", description: "Create new schema" },
99
+ { path: "/schemas/{collectionName}", method: "GET", type: "system", category: "schema", description: "Get specific schema" },
100
+ { path: "/schemas/{collectionName}", method: "DELETE", type: "system", category: "schema", description: "Delete schema" },
101
+ { path: "/schemas/{collectionName}/indexes", method: "POST", type: "system", category: "schema", description: "Create schema index" },
102
+ { path: "/schemas/{collectionName}/indexes/{indexName}", method: "DELETE", type: "system", category: "schema", description: "Delete schema index" },
103
+ { path: "/schemas/{sourceCollection}/relationships", method: "POST", type: "system", category: "schema", description: "Create relationship" },
104
+ { path: "/schemas/{sourceCollection}/relationships/{fieldName}", method: "DELETE", type: "system", category: "schema", description: "Delete relationship" },
105
+ { path: "/schemas-export", method: "GET", type: "system", category: "schema", description: "Export schemas" },
106
+ { path: "/schemas-import", method: "POST", type: "system", category: "schema", description: "Import schemas" },
107
+ ] : [];
108
+ const permissionEndpoints = env.get("OPENAPI_INCLUDE_PERMISSIONS") === "true" ? [
109
+ // Permission endpoints
110
+ { path: "/permissions", method: "GET", type: "system", category: "permissions", description: "Get permissions" },
111
+ { path: "/permissions", method: "POST", type: "system", category: "permissions", description: "Create permission" },
112
+ { path: "/permissions/{id}", method: "GET", type: "system", category: "permissions", description: "Get specific permission" },
113
+ { path: "/permissions/{id}", method: "DELETE", type: "system", category: "permissions", description: "Delete permission" },
114
+ { path: "/permissions/reload", method: "POST", type: "system", category: "permissions", description: "Reload permissions" },
115
+ // Permission management endpoints
116
+ { path: "/permissions-export", method: "GET", type: "system", category: "schema", description: "Export permissions" },
117
+ { path: "/permissions-import", method: "POST", type: "system", category: "schema", description: "Import permissions" },
118
+ { path: "/permissions-import-with-data", method: "POST", type: "system", category: "schema", description: "Import permissions with data" },
119
+ ] : [];
120
+ const settingsEndpoints = env.get("OPENAPI_INCLUDE_SETTINGS") === "true" ? [
121
+ // Settings endpoints
122
+ { path: "/", method: "GET", type: "system", category: "settings", description: "Get app info" },
123
+ { path: "/", method: "POST", type: "system", category: "settings", description: "Update app info" },
124
+ { path: "/settings/{id}", method: "GET", type: "system", category: "settings", description: "Get settings" },
125
+ { path: "/settings/reload", method: "POST", type: "system", category: "settings", description: "Reload settings" },
126
+ ] : [];
127
+ const utilsEndpoints = env.get("OPENAPI_INCLUDE_UTILS") === "true" ? [
128
+ // Utility endpoints
129
+ { path: "/utils/sort/{collection}", method: "POST", type: "system", category: "utils", description: "Sort items in collection" },
130
+ ] : [];
131
+ const notificationEndpoints = env.get("OPENAPI_INCLUDE_NOTIFICATIONS") === "true" ? [
132
+ // Notification endpoints
133
+ { path: "/notifications", method: "GET", type: "system", category: "notifications", description: "Get user notifications" },
134
+ { path: "/notifications", method: "DELETE", type: "system", category: "notifications", description: "Delete notifications" },
135
+ { path: "/notifications/unread/count", method: "GET", type: "system", category: "notifications", description: "Get unread notifications count" },
136
+ { path: "/notifications/mark-seen", method: "POST", type: "system", category: "notifications", description: "Mark notifications as seen" },
137
+ { path: "/notifications/send", method: "POST", type: "system", category: "notifications", description: "Send notifications (admin)" },
138
+ { path: "/notifications/cleanup", method: "POST", type: "system", category: "notifications", description: "Cleanup old notifications (admin)" },
139
+ ] : [];
140
+ const realtimeEndpoints = [
141
+ // Realtime WAL endpoints (PostgreSQL logical replication)
142
+ { path: "/realtime/status", method: "GET", type: "system", category: "realtime", description: "Get realtime service status (admin)" },
143
+ { path: "/realtime/config", method: "GET", type: "system", category: "realtime", description: "Get PostgreSQL replication configuration (admin)" },
144
+ { path: "/realtime/collections", method: "GET", type: "system", category: "realtime", description: "Get list of realtime-enabled collections (admin)" },
145
+ { path: "/realtime/collections/{collection}", method: "GET", type: "system", category: "realtime", description: "Check if collection has realtime enabled (admin)" },
146
+ { path: "/realtime/collections/{collection}/enable", method: "POST", type: "system", category: "realtime", description: "Enable realtime for collection (admin)" },
147
+ { path: "/realtime/collections/{collection}/disable", method: "POST", type: "system", category: "realtime", description: "Disable realtime for collection (admin)" },
148
+ { path: "/realtime/initialize", method: "POST", type: "system", category: "realtime", description: "Initialize realtime service manually (admin)" },
149
+ ];
150
+ const systemEndpoints = [
151
+ ...authEndpoints,
152
+ ...multiTenantEndpoints,
153
+ ...schemaEndpoints,
154
+ ...permissionEndpoints,
155
+ ...settingsEndpoints,
156
+ // File endpoints
157
+ { path: "/files", method: "GET", type: "system", category: "files", description: "Get all files" },
158
+ { path: "/files", method: "POST", type: "system", category: "files", description: "Upload file" },
159
+ { path: "/files/{id}", method: "GET", type: "system", category: "files", description: "Get specific file" },
160
+ { path: "/files/{id}", method: "PATCH", type: "system", category: "files", description: "Update file" },
161
+ { path: "/files/{id}", method: "DELETE", type: "system", category: "files", description: "Delete file" },
162
+ { path: "/files/upload-from-url", method: "POST", type: "system", category: "files", description: "Upload file from URL" },
163
+ { path: "/assets/{id}", method: "GET", type: "system", category: "files", description: "Get file asset" },
164
+ ...notificationEndpoints,
165
+ ...utilsEndpoints,
166
+ ...realtimeEndpoints,
167
+ ];
168
+ return systemEndpoints;
169
+ }
170
+ function getExtensionEndpoints() {
171
+ const extensionEndpoints = [];
172
+ const extensionsPath = getProjectPath("extensions");
173
+ if (!fs.existsSync(extensionsPath)) {
174
+ return extensionEndpoints;
175
+ }
176
+ try {
177
+ const extensionDirs = fs.readdirSync(extensionsPath);
178
+ for (const dir of extensionDirs) {
179
+ const fullPath = path.join(extensionsPath, dir);
180
+ if (fs.lstatSync(fullPath).isDirectory() && dir.startsWith("baasix-endpoint")) {
181
+ const indexPath = path.join(fullPath, "index.js");
182
+ if (fs.existsSync(indexPath)) {
183
+ try {
184
+ // Note: Extension modules are already loaded by router.ts using dynamic import
185
+ // We just need to know they exist for OpenAPI documentation
186
+ const endpointName = dir.replace("baasix-endpoint-", "");
187
+ extensionEndpoints.push({
188
+ path: `/${endpointName}`,
189
+ method: "GET", // Default method, could be enhanced to detect actual methods
190
+ type: "extension",
191
+ category: "custom",
192
+ description: `Custom endpoint: ${endpointName}`,
193
+ extensionId: dir
194
+ });
195
+ }
196
+ catch (error) {
197
+ console.warn(`Error reading extension ${dir}:`, error.message);
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+ catch (error) {
204
+ console.warn("Error reading extensions directory:", error.message);
205
+ }
206
+ return extensionEndpoints;
207
+ }
208
+ async function getCollectionEndpoints() {
209
+ const collectionEndpoints = [];
210
+ try {
211
+ const schemas = schemaManager.getAllSchemas();
212
+ for (const [collectionName, schemaRecord] of Object.entries(schemas)) {
213
+ // Skip system collections
214
+ if (collectionName.startsWith('baasix_')) {
215
+ continue;
216
+ }
217
+ // Standard CRUD endpoints for each collection
218
+ const crudEndpoints = [
219
+ { path: `/items/${collectionName}`, method: "GET", description: `Get all ${collectionName} items` },
220
+ { path: `/items/${collectionName}`, method: "POST", description: `Create new ${collectionName} item` },
221
+ { path: `/items/${collectionName}/{id}`, method: "GET", description: `Get specific ${collectionName} item` },
222
+ { path: `/items/${collectionName}/{id}`, method: "PUT", description: `Update ${collectionName} item` },
223
+ { path: `/items/${collectionName}/{id}`, method: "PATCH", description: `Partially update ${collectionName} item` },
224
+ { path: `/items/${collectionName}/{id}`, method: "DELETE", description: `Delete ${collectionName} item` }
225
+ ];
226
+ for (const endpoint of crudEndpoints) {
227
+ collectionEndpoints.push({
228
+ ...endpoint,
229
+ type: "collection",
230
+ category: "data",
231
+ collectionName: collectionName,
232
+ schema: schemaRecord
233
+ });
234
+ }
235
+ }
236
+ }
237
+ catch (error) {
238
+ console.warn("Error retrieving collection endpoints:", error.message);
239
+ }
240
+ return collectionEndpoints;
241
+ }
242
+ async function generateOpenApiSpec(baseUrl) {
243
+ const endpoints = [];
244
+ if (env.get("OPENAPI_ENABLED") === "false" || env.get("OPENAPI_ENABLED") === "0") {
245
+ throw new APIError("OpenAPI generation is disabled", 503);
246
+ }
247
+ // Get system endpoints
248
+ const systemEndpoints = getSystemEndpoints();
249
+ endpoints.push(...systemEndpoints);
250
+ // Get extension endpoints
251
+ const extensionEndpoints = getExtensionEndpoints();
252
+ endpoints.push(...extensionEndpoints);
253
+ // Get collection endpoints
254
+ const collectionEndpoints = await getCollectionEndpoints();
255
+ endpoints.push(...collectionEndpoints);
256
+ const RegisterRequest = env.get("MULTI_TENANT") === "true" ? {
257
+ type: "object",
258
+ properties: {
259
+ email: { type: "string", format: "email", description: "User email address" },
260
+ password: { type: "string", minLength: 8, description: "User password (minimum 8 characters)" },
261
+ firstName: { type: "string", description: "User first name" },
262
+ lastName: { type: "string", description: "User last name" },
263
+ tenant: {
264
+ type: "object",
265
+ description: "Tenant information (required in multi-tenant mode)",
266
+ properties: {
267
+ name: { type: "string", description: "Tenant name" }
268
+ }
269
+ },
270
+ roleName: { type: "string", description: "Role name to assign" },
271
+ inviteToken: { type: "string", description: "Invitation token if registering via invite" },
272
+ authMode: { type: "string", enum: ["jwt", "cookie"], default: "jwt", description: "Authentication mode" }
273
+ },
274
+ required: ["email", "password", "firstName"]
275
+ } : {
276
+ type: "object",
277
+ properties: {
278
+ email: { type: "string", format: "email", description: "User email address" },
279
+ password: { type: "string", minLength: 8, description: "User password (minimum 8 characters)" },
280
+ firstName: { type: "string", description: "User first name" },
281
+ lastName: { type: "string", description: "User last name" },
282
+ authMode: { type: "string", enum: ["jwt", "cookie"], default: "jwt", description: "Authentication mode" }
283
+ },
284
+ required: ["email", "password", "firstName"]
285
+ };
286
+ const openApiSpec = {
287
+ openapi: "3.0.3",
288
+ info: {
289
+ title: "Baasix API",
290
+ description: "Backend as a Service API with dynamic collections and system endpoints",
291
+ version: "1.0.0",
292
+ contact: {
293
+ name: "Baasix API Support"
294
+ }
295
+ },
296
+ servers: [
297
+ {
298
+ url: baseUrl,
299
+ description: "Baasix API Server"
300
+ }
301
+ ],
302
+ paths: {},
303
+ components: {
304
+ securitySchemes: {
305
+ bearerAuth: {
306
+ type: "http",
307
+ scheme: "bearer",
308
+ bearerFormat: "JWT"
309
+ },
310
+ cookieAuth: {
311
+ type: "apiKey",
312
+ in: "cookie",
313
+ name: "token"
314
+ }
315
+ },
316
+ schemas: {
317
+ Error: {
318
+ type: "object",
319
+ properties: {
320
+ message: { type: "string", description: "Error message" },
321
+ error: { type: "string", description: "Error details" },
322
+ statusCode: { type: "integer", description: "HTTP status code" }
323
+ },
324
+ required: ["message"]
325
+ },
326
+ PaginatedResponse: {
327
+ type: "object",
328
+ properties: {
329
+ data: {
330
+ type: "array",
331
+ items: {},
332
+ description: "Array of items"
333
+ },
334
+ totalCount: {
335
+ type: "integer",
336
+ description: "Total number of items available"
337
+ },
338
+ page: {
339
+ type: "integer",
340
+ description: "Current page number (1-based)"
341
+ },
342
+ limit: {
343
+ type: "integer",
344
+ description: "Number of items per page"
345
+ }
346
+ },
347
+ required: ["data"]
348
+ },
349
+ SingleItemResponse: {
350
+ type: "object",
351
+ properties: {
352
+ data: {
353
+ type: "object",
354
+ description: "Single item data"
355
+ }
356
+ },
357
+ required: ["data"]
358
+ },
359
+ CreateResponse: {
360
+ type: "object",
361
+ properties: {
362
+ data: {
363
+ type: "object",
364
+ properties: {
365
+ id: {
366
+ type: "string",
367
+ description: "ID of the created item"
368
+ }
369
+ },
370
+ required: ["id"]
371
+ }
372
+ },
373
+ required: ["data"]
374
+ },
375
+ // Auth Schemas
376
+ RegisterRequest: RegisterRequest,
377
+ LoginRequest: {
378
+ type: "object",
379
+ properties: {
380
+ email: { type: "string", format: "email", description: "User email address" },
381
+ password: { type: "string", description: "User password" },
382
+ authMode: { type: "string", enum: ["jwt", "cookie"], default: "jwt", description: "Authentication mode" },
383
+ otp: { type: "string", description: "One-time password (if 2FA is enabled)" }
384
+ },
385
+ required: ["email", "password"]
386
+ },
387
+ AuthResponse: {
388
+ type: "object",
389
+ properties: {
390
+ data: {
391
+ type: "object",
392
+ properties: {
393
+ access_token: { type: "string", description: "JWT access token" },
394
+ refresh_token: { type: "string", description: "JWT refresh token" },
395
+ expires: { type: "integer", description: "Token expiration timestamp" },
396
+ user: {
397
+ type: "object",
398
+ properties: {
399
+ id: { type: "string", description: "User ID" },
400
+ email: { type: "string", description: "User email" },
401
+ firstName: { type: "string", description: "User first name" },
402
+ lastName: { type: "string", description: "User last name" }
403
+ }
404
+ }
405
+ }
406
+ }
407
+ }
408
+ },
409
+ // ... (continuing in next part due to length)
410
+ }
411
+ },
412
+ security: [
413
+ { bearerAuth: [] },
414
+ { cookieAuth: [] }
415
+ ]
416
+ };
417
+ // Add comprehensive system schemas
418
+ openApiSpec.components.schemas = {
419
+ ...openApiSpec.components.schemas,
420
+ ...getSystemSchemas()
421
+ };
422
+ // Generate and add dynamic collection schemas
423
+ const collectionSchemas = generateCollectionSchemas(endpoints);
424
+ Object.assign(openApiSpec.components.schemas, collectionSchemas);
425
+ // Generate detailed paths with proper schemas
426
+ const pathGroups = {};
427
+ for (const endpoint of endpoints) {
428
+ const { path: endpointPath, method } = endpoint;
429
+ if (!pathGroups[endpointPath]) {
430
+ pathGroups[endpointPath] = {};
431
+ }
432
+ // Create detailed operation based on endpoint type and method
433
+ const operation = createDetailedOperation(endpoint);
434
+ pathGroups[endpointPath][method.toLowerCase()] = operation;
435
+ }
436
+ openApiSpec.paths = pathGroups;
437
+ return openApiSpec;
438
+ }
439
+ function getSystemSchemas() {
440
+ return {
441
+ // Schema Management
442
+ Schema: {
443
+ type: "object",
444
+ properties: {
445
+ collectionName: { type: "string", description: "Name of the collection" },
446
+ schema: {
447
+ type: "object",
448
+ description: "Schema definition",
449
+ properties: {
450
+ name: { type: "string", description: "Schema display name" },
451
+ fields: {
452
+ type: "object",
453
+ description: "Field definitions",
454
+ additionalProperties: {
455
+ type: "object",
456
+ properties: {
457
+ type: {
458
+ type: "string",
459
+ enum: ["String", "Integer", "Double", "Boolean", "UUID", "Date", "Text", "JSON"],
460
+ description: "Field data type"
461
+ },
462
+ allowNull: { type: "boolean", description: "Whether field can be null" },
463
+ defaultValue: { description: "Default value for the field" },
464
+ primaryKey: { type: "boolean", description: "Whether field is primary key" },
465
+ unique: { type: "boolean", description: "Whether field must be unique" },
466
+ relType: {
467
+ type: "string",
468
+ enum: ["BelongsTo", "HasMany", "HasOne", "BelongsToMany"],
469
+ description: "Relationship type"
470
+ },
471
+ target: { type: "string", description: "Target collection for relationships" },
472
+ foreignKey: { type: "string", description: "Foreign key field name" }
473
+ }
474
+ }
475
+ },
476
+ timestamps: { type: "boolean", description: "Whether to include createdAt/updatedAt fields" },
477
+ indexes: {
478
+ type: "array",
479
+ items: {
480
+ type: "object",
481
+ properties: {
482
+ name: { type: "string", description: "Index name" },
483
+ fields: {
484
+ type: "array",
485
+ items: { type: "string" },
486
+ description: "Fields included in the index"
487
+ },
488
+ unique: { type: "boolean", description: "Whether index is unique" }
489
+ }
490
+ }
491
+ }
492
+ }
493
+ },
494
+ createdAt: { type: "string", format: "date-time" },
495
+ updatedAt: { type: "string", format: "date-time" }
496
+ }
497
+ },
498
+ // File Management
499
+ FileUploadResponse: {
500
+ type: "object",
501
+ properties: {
502
+ data: {
503
+ type: "object",
504
+ properties: {
505
+ id: { type: "string", description: "File ID" },
506
+ filename_disk: { type: "string", description: "File name on disk" },
507
+ filename_download: { type: "string", description: "Original filename" },
508
+ title: { type: "string", description: "File title" },
509
+ type: { type: "string", description: "MIME type" },
510
+ filesize: { type: "integer", description: "File size in bytes" },
511
+ uploaded_on: { type: "string", format: "date-time", description: "Upload timestamp" }
512
+ }
513
+ }
514
+ }
515
+ },
516
+ // Notification specific responses
517
+ NotificationListResponse: {
518
+ type: "object",
519
+ properties: {
520
+ data: {
521
+ type: "array",
522
+ items: { $ref: "#/components/schemas/baasix_Notification" },
523
+ description: "List of notifications"
524
+ },
525
+ totalCount: { type: "integer", description: "Total number of notifications" },
526
+ page: { type: "integer", description: "Current page number" },
527
+ limit: { type: "integer", description: "Number of items per page" }
528
+ }
529
+ },
530
+ NotificationCountResponse: {
531
+ type: "object",
532
+ properties: {
533
+ count: { type: "integer", description: "Number of unread notifications" }
534
+ }
535
+ },
536
+ // Auth related request/response schemas
537
+ InviteRequest: {
538
+ type: "object",
539
+ properties: {
540
+ email: { type: "string", format: "email", description: "Email to invite" },
541
+ roleName: { type: "string", description: "Role to assign" },
542
+ tenant: { type: "object", description: "Tenant information" }
543
+ },
544
+ required: ["email", "roleName"]
545
+ },
546
+ SwitchTenantRequest: {
547
+ type: "object",
548
+ properties: {
549
+ tenantId: { type: "string", format: "uuid", description: "Tenant ID to switch to" }
550
+ },
551
+ required: ["tenantId"]
552
+ },
553
+ MagicLinkRequest: {
554
+ type: "object",
555
+ properties: {
556
+ email: { type: "string", format: "email", description: "Email address" },
557
+ link: { type: "string", description: "Magic link URL" },
558
+ mode: { type: "string", enum: ["link", "code"], description: "Mode of the magic link", default: "link" }
559
+ },
560
+ required: ["email"]
561
+ },
562
+ // System Models
563
+ baasix_SchemaDefinition: {
564
+ type: "object",
565
+ properties: {
566
+ collectionName: { type: "string", description: "Collection name (primary key)" },
567
+ schema: { type: "object", description: "JSON schema definition" },
568
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
569
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" }
570
+ },
571
+ required: ["collectionName", "schema"]
572
+ },
573
+ baasix_Role: {
574
+ type: "object",
575
+ properties: {
576
+ id: { type: "string", format: "uuid", description: "Role ID" },
577
+ name: { type: "string", description: "Role name" },
578
+ description: { type: "string", description: "Role description" },
579
+ isTenantSpecific: { type: "boolean", description: "Whether role is tenant-specific", default: true },
580
+ canInviteRoleIds: { type: "array", items: { type: "string" }, description: "Array of role IDs this role can invite" },
581
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
582
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
583
+ permissions: { type: "array", items: { $ref: "#/components/schemas/baasix_Permission" }, description: "Role permissions" },
584
+ userRoles: { type: "array", items: { $ref: "#/components/schemas/baasix_UserRole" }, description: "User role assignments" }
585
+ },
586
+ required: ["id", "name", "isTenantSpecific"]
587
+ },
588
+ baasix_Permission: {
589
+ type: "object",
590
+ properties: {
591
+ id: { type: "string", format: "uuid", description: "Permission ID" },
592
+ action: { type: "string", description: "Action (create, read, update, delete, etc.)" },
593
+ collection: { type: "string", description: "Collection name" },
594
+ role_Id: { type: "string", format: "uuid", description: "Role ID" },
595
+ fields: { type: "object", description: "Field-level permissions" },
596
+ defaultValues: { type: "object", description: "Default values for new items" },
597
+ conditions: { type: "object", description: "Access conditions" },
598
+ relConditions: { type: "object", description: "Relational conditions" },
599
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
600
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
601
+ role: { $ref: "#/components/schemas/baasix_Role", description: "Associated role" }
602
+ },
603
+ required: ["id", "action", "collection", "role_Id"]
604
+ },
605
+ baasix_UserRole: {
606
+ type: "object",
607
+ properties: {
608
+ id: { type: "string", format: "uuid", description: "UserRole ID" },
609
+ user_Id: { type: "string", format: "uuid", description: "User ID" },
610
+ role_Id: { type: "string", format: "uuid", description: "Role ID" },
611
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
612
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
613
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
614
+ user: { $ref: "#/components/schemas/baasix_User", description: "Associated user" },
615
+ role: { $ref: "#/components/schemas/baasix_Role", description: "Associated role" },
616
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" }
617
+ },
618
+ required: ["id", "user_Id", "role_Id"]
619
+ },
620
+ baasix_Tenant: {
621
+ type: "object",
622
+ properties: {
623
+ id: { type: "string", format: "uuid", description: "Tenant ID" },
624
+ name: { type: "string", description: "Tenant name" },
625
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
626
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
627
+ userRoles: { type: "array", items: { $ref: "#/components/schemas/baasix_UserRole" }, description: "User role assignments" }
628
+ },
629
+ required: ["id", "name"]
630
+ },
631
+ baasix_User: {
632
+ type: "object",
633
+ properties: {
634
+ id: { type: "string", format: "uuid", description: "User ID" },
635
+ firstName: { type: "string", description: "User first name" },
636
+ lastName: { type: "string", description: "User last name" },
637
+ fullName: { type: "string", description: "Calculated full name (virtual field)" },
638
+ phone: { type: "string", description: "User phone number" },
639
+ email: { type: "string", format: "email", description: "User email address" },
640
+ emailVerified: { type: "boolean", description: "Whether email is verified", default: false },
641
+ avatar_Id: { type: "string", format: "uuid", description: "Avatar file ID" },
642
+ lastAccess: { type: "string", format: "date-time", description: "Last access timestamp" },
643
+ status: { type: "string", enum: ["active", "inactive", "deleted", "suspended", "pending"], description: "User status", default: "active" },
644
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
645
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
646
+ userRoles: { type: "array", items: { $ref: "#/components/schemas/baasix_UserRole" }, description: "User role assignments" },
647
+ avatar: { $ref: "#/components/schemas/baasix_File", description: "Avatar file" }
648
+ },
649
+ required: ["id", "firstName"]
650
+ },
651
+ baasix_Account: {
652
+ type: "object",
653
+ description: "User authentication accounts (credential or OAuth providers)",
654
+ properties: {
655
+ id: { type: "string", format: "uuid", description: "Account ID" },
656
+ user_Id: { type: "string", format: "uuid", description: "Associated user ID" },
657
+ accountId: { type: "string", description: "Account ID from OAuth provider or same as user_Id for credential accounts" },
658
+ providerId: { type: "string", description: "Provider ID (e.g., 'credential', 'google', 'facebook', 'github', 'apple')" },
659
+ accessToken: { type: "string", description: "OAuth access token (sensitive, excluded from responses)" },
660
+ refreshToken: { type: "string", description: "OAuth refresh token (sensitive, excluded from responses)" },
661
+ accessTokenExpiresAt: { type: "string", format: "date-time", description: "Access token expiration timestamp" },
662
+ refreshTokenExpiresAt: { type: "string", format: "date-time", description: "Refresh token expiration timestamp" },
663
+ scope: { type: "string", description: "OAuth scope" },
664
+ idToken: { type: "string", description: "OAuth ID token (sensitive, excluded from responses)" },
665
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
666
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
667
+ user: { $ref: "#/components/schemas/baasix_User", description: "Associated user" }
668
+ },
669
+ required: ["id", "user_Id", "accountId", "providerId"]
670
+ },
671
+ baasix_Verification: {
672
+ type: "object",
673
+ description: "Verification tokens for email verification, password reset, and magic links",
674
+ properties: {
675
+ id: { type: "string", format: "uuid", description: "Verification ID" },
676
+ identifier: { type: "string", description: "Identifier (e.g., 'email-verification:user@example.com', 'magic-link:user@example.com')" },
677
+ value: { type: "string", description: "Token value (sensitive, excluded from responses)" },
678
+ expiresAt: { type: "string", format: "date-time", description: "Token expiration timestamp" },
679
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
680
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" }
681
+ },
682
+ required: ["id", "identifier", "value", "expiresAt"]
683
+ },
684
+ baasix_Sessions: {
685
+ type: "object",
686
+ properties: {
687
+ id: { type: "string", format: "uuid", description: "Session ID" },
688
+ token: { type: "string", description: "Session token" },
689
+ user_Id: { type: "string", format: "uuid", description: "User ID" },
690
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
691
+ expiresAt: { type: "string", format: "date-time", description: "Session expiration timestamp" },
692
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
693
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
694
+ user: { $ref: "#/components/schemas/baasix_User", description: "Associated user" },
695
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" }
696
+ },
697
+ required: ["id", "token", "user_Id", "expiresAt"]
698
+ },
699
+ baasix_File: {
700
+ type: "object",
701
+ properties: {
702
+ id: { type: "string", format: "uuid", description: "File ID" },
703
+ title: { type: "string", description: "File title" },
704
+ filename: { type: "string", description: "File name on disk" },
705
+ originalFilename: { type: "string", description: "Original filename" },
706
+ type: { type: "string", description: "MIME type" },
707
+ size: { type: "integer", description: "File size in bytes" },
708
+ description: { type: "string", description: "File description" },
709
+ storage: { type: "string", description: "Storage service used" },
710
+ width: { type: "integer", description: "Image width (if applicable)" },
711
+ height: { type: "integer", description: "Image height (if applicable)" },
712
+ metadata: { type: "object", description: "File metadata" },
713
+ userCreated_Id: { type: "string", format: "uuid", description: "User who created the file" },
714
+ userUpdated_Id: { type: "string", format: "uuid", description: "User who last updated the file" },
715
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
716
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
717
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
718
+ userCreated: { $ref: "#/components/schemas/baasix_User", description: "User who created the file" },
719
+ userUpdated: { $ref: "#/components/schemas/baasix_User", description: "User who last updated the file" },
720
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" }
721
+ },
722
+ required: ["id", "filename", "originalFilename", "type", "size", "storage"]
723
+ },
724
+ baasix_EmailLog: {
725
+ type: "object",
726
+ properties: {
727
+ id: { type: "string", format: "uuid", description: "Email log ID" },
728
+ email: { type: "string", format: "email", description: "Recipient email address" },
729
+ subject: { type: "string", description: "Email subject" },
730
+ templateName: { type: "string", description: "Email template name" },
731
+ sender: { type: "string", description: "Sender email address" },
732
+ status: { type: "string", description: "Email status" },
733
+ messageId: { type: "string", description: "Email message ID" },
734
+ errorMessage: { type: "string", description: "Error message if failed" },
735
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
736
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" }
737
+ },
738
+ required: ["id", "email", "subject"]
739
+ },
740
+ baasix_AuditLog: {
741
+ type: "object",
742
+ properties: {
743
+ id: { type: "string", format: "uuid", description: "Audit log ID" },
744
+ type: { type: "string", description: "Log type", default: "data" },
745
+ entity: { type: "string", description: "Entity name" },
746
+ entityId: { type: "string", description: "Entity ID" },
747
+ action: { type: "string", description: "Action performed" },
748
+ changes: { type: "object", description: "Changes made" },
749
+ ipaddress: { type: "string", description: "IP address" },
750
+ userId: { type: "string", format: "uuid", description: "User ID" },
751
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
752
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
753
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
754
+ user: { $ref: "#/components/schemas/baasix_User", description: "Associated user" },
755
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" }
756
+ },
757
+ required: ["id", "entity", "action"]
758
+ },
759
+ baasix_Notification: {
760
+ type: "object",
761
+ properties: {
762
+ id: { type: "string", format: "uuid", description: "Notification ID" },
763
+ type: { type: "string", description: "Notification type" },
764
+ title: { type: "string", description: "Notification title" },
765
+ message: { type: "string", description: "Notification message" },
766
+ seen: { type: "boolean", description: "Whether notification has been seen", default: false },
767
+ data: { type: "object", description: "Additional notification data" },
768
+ userId: { type: "string", format: "uuid", description: "User ID" },
769
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
770
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
771
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
772
+ user: { $ref: "#/components/schemas/baasix_User", description: "Associated user" },
773
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" }
774
+ },
775
+ required: ["id", "type", "title", "userId"]
776
+ },
777
+ baasix_Settings: {
778
+ type: "object",
779
+ properties: {
780
+ id: { type: "integer", description: "Settings ID (auto-increment)" },
781
+ project_name: { type: "string", description: "Project name", default: "Baasix Project" },
782
+ project_url: { type: "string", description: "Project URL" },
783
+ project_color: { type: "string", description: "Project color" },
784
+ project_logo_light_Id: { type: "string", format: "uuid", description: "Light logo file ID" },
785
+ project_logo_dark_Id: { type: "string", format: "uuid", description: "Dark logo file ID" },
786
+ project_favicon_Id: { type: "string", format: "uuid", description: "Favicon file ID" },
787
+ project_icon_Id: { type: "string", format: "uuid", description: "Icon file ID" },
788
+ email_icon_Id: { type: "string", format: "uuid", description: "Email icon file ID" },
789
+ email_signature: { type: "string", description: "Email signature" },
790
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
791
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
792
+ project_logo_light: { $ref: "#/components/schemas/baasix_File", description: "Light logo file" },
793
+ project_logo_dark: { $ref: "#/components/schemas/baasix_File", description: "Dark logo file" },
794
+ project_favicon: { $ref: "#/components/schemas/baasix_File", description: "Favicon file" },
795
+ project_icon: { $ref: "#/components/schemas/baasix_File", description: "Icon file" },
796
+ email_icon: { $ref: "#/components/schemas/baasix_File", description: "Email icon file" }
797
+ },
798
+ required: ["id", "project_name"]
799
+ },
800
+ baasix_Invite: {
801
+ type: "object",
802
+ properties: {
803
+ id: { type: "string", format: "uuid", description: "Invite ID" },
804
+ email: { type: "string", format: "email", description: "Email address of the invitee" },
805
+ role_Id: { type: "string", format: "uuid", description: "Role to assign when invitation is accepted" },
806
+ tenant_Id: { type: "string", format: "uuid", description: "Tenant ID" },
807
+ token: { type: "string", description: "Invitation token" },
808
+ expiresAt: { type: "string", format: "date-time", description: "Invitation expiration" },
809
+ invitedBy_Id: { type: "string", format: "uuid", description: "User who sent the invitation" },
810
+ acceptedAt: { type: "string", format: "date-time", description: "When invitation was accepted" },
811
+ status: { type: "string", enum: ["pending", "accepted", "expired", "revoked"], description: "Invitation status", default: "pending" },
812
+ createdAt: { type: "string", format: "date-time", description: "Creation timestamp" },
813
+ updatedAt: { type: "string", format: "date-time", description: "Update timestamp" },
814
+ role: { $ref: "#/components/schemas/baasix_Role", description: "Associated role" },
815
+ tenant: { $ref: "#/components/schemas/baasix_Tenant", description: "Associated tenant" },
816
+ invitedBy: { $ref: "#/components/schemas/baasix_User", description: "User who sent the invitation" }
817
+ },
818
+ required: ["id", "email", "role_Id", "token", "expiresAt", "invitedBy_Id"]
819
+ },
820
+ };
821
+ }
822
+ // Continue with helper functions...
823
+ // (Due to character limit, I'll provide the remaining functions in the next part)
824
+ function createDetailedOperation(endpoint) {
825
+ const { type } = endpoint;
826
+ if (type === "system") {
827
+ return createSystemEndpointOperation(endpoint);
828
+ }
829
+ else if (type === "collection") {
830
+ return createCollectionEndpointOperation(endpoint);
831
+ }
832
+ else if (type === "extension") {
833
+ return createExtensionEndpointOperation(endpoint);
834
+ }
835
+ return {
836
+ summary: endpoint.description,
837
+ tags: [endpoint.category],
838
+ responses: getStandardResponses()
839
+ };
840
+ }
841
+ function createSystemEndpointOperation(endpoint) {
842
+ const { path: endpointPath, method, description, category } = endpoint;
843
+ const methodLower = method.toLowerCase();
844
+ const operation = {
845
+ summary: description,
846
+ tags: [category],
847
+ responses: getStandardResponses()
848
+ };
849
+ // Add specific schemas for auth endpoints
850
+ if (endpointPath.startsWith("/auth/")) {
851
+ return createAuthEndpointOperation(endpoint);
852
+ }
853
+ // Add specific schemas for notification endpoints
854
+ if (endpointPath.startsWith("/notifications")) {
855
+ return createNotificationEndpointOperation(endpoint);
856
+ }
857
+ // Add specific schemas for schema management
858
+ if (endpointPath.startsWith("/schemas")) {
859
+ return createSchemaEndpointOperation(endpoint);
860
+ }
861
+ // Add specific schemas for file management
862
+ if (endpointPath.startsWith("/files")) {
863
+ return createFileEndpointOperation(endpoint);
864
+ }
865
+ // Add specific schemas for permission management
866
+ if (endpointPath.startsWith("/permissions")) {
867
+ return createPermissionEndpointOperation(endpoint);
868
+ }
869
+ // Add specific schemas for utils endpoints
870
+ if (endpointPath.startsWith("/utils")) {
871
+ return createUtilsEndpointOperation(endpoint);
872
+ }
873
+ // Add specific schemas for realtime endpoints
874
+ if (endpointPath.startsWith("/realtime")) {
875
+ return createRealtimeEndpointOperation(endpoint);
876
+ }
877
+ // Add parameters for endpoints with path parameters
878
+ if (endpointPath.includes("{id}")) {
879
+ operation.parameters = [{
880
+ name: "id",
881
+ in: "path",
882
+ required: true,
883
+ schema: { type: "string" },
884
+ description: "Resource ID"
885
+ }];
886
+ }
887
+ if (endpointPath.includes("{collectionName}")) {
888
+ operation.parameters = operation.parameters || [];
889
+ operation.parameters.push({
890
+ name: "collectionName",
891
+ in: "path",
892
+ required: true,
893
+ schema: { type: "string" },
894
+ description: "Collection name"
895
+ });
896
+ }
897
+ // Add request body for POST, PUT, PATCH methods
898
+ if (["post", "put", "patch"].includes(methodLower)) {
899
+ operation.requestBody = {
900
+ required: true,
901
+ content: {
902
+ "application/json": {
903
+ schema: { type: "object" }
904
+ }
905
+ }
906
+ };
907
+ }
908
+ return operation;
909
+ }
910
+ // Due to length constraints, I'll create a second file with the remaining helper functions
911
+ // Let me write the continuation...
912
+ function createAuthEndpointOperation(endpoint) {
913
+ const { path: endpointPath, method, description, category } = endpoint;
914
+ const methodLower = method.toLowerCase();
915
+ const operation = {
916
+ summary: description,
917
+ tags: [category],
918
+ responses: getStandardResponses()
919
+ };
920
+ // Specific auth endpoint configurations
921
+ if (endpointPath === "/auth/register" && methodLower === "post") {
922
+ operation.description = "Register a new user account. Supports both public registration and invite-based registration.";
923
+ operation.requestBody = {
924
+ required: true,
925
+ content: {
926
+ "application/json": {
927
+ schema: { $ref: "#/components/schemas/RegisterRequest" }
928
+ }
929
+ }
930
+ };
931
+ operation.responses["201"] = {
932
+ description: "User registered successfully",
933
+ content: {
934
+ "application/json": {
935
+ schema: { $ref: "#/components/schemas/AuthResponse" }
936
+ }
937
+ }
938
+ };
939
+ }
940
+ else if (endpointPath === "/auth/login" && methodLower === "post") {
941
+ operation.description = "Authenticate user and return access token. Supports JWT and cookie-based authentication.";
942
+ operation.requestBody = {
943
+ required: true,
944
+ content: {
945
+ "application/json": {
946
+ schema: { $ref: "#/components/schemas/LoginRequest" }
947
+ }
948
+ }
949
+ };
950
+ operation.responses["200"] = {
951
+ description: "Login successful",
952
+ content: {
953
+ "application/json": {
954
+ schema: { $ref: "#/components/schemas/AuthResponse" }
955
+ }
956
+ }
957
+ };
958
+ }
959
+ else if (endpointPath === "/auth/me" && methodLower === "get") {
960
+ operation.description = "Get current user information";
961
+ operation.responses["200"] = {
962
+ description: "Current user information",
963
+ content: {
964
+ "application/json": {
965
+ schema: {
966
+ type: "object",
967
+ properties: {
968
+ data: { $ref: "#/components/schemas/baasix_User" }
969
+ }
970
+ }
971
+ }
972
+ }
973
+ };
974
+ }
975
+ else if (endpointPath === "/auth/invite" && methodLower === "post") {
976
+ operation.description = "Send invitation to a user";
977
+ operation.requestBody = {
978
+ required: true,
979
+ content: {
980
+ "application/json": {
981
+ schema: { $ref: "#/components/schemas/InviteRequest" }
982
+ }
983
+ }
984
+ };
985
+ }
986
+ else if (endpointPath === "/auth/switch-tenant" && methodLower === "post") {
987
+ operation.description = "Switch to different tenant";
988
+ operation.requestBody = {
989
+ required: true,
990
+ content: {
991
+ "application/json": {
992
+ schema: { $ref: "#/components/schemas/SwitchTenantRequest" }
993
+ }
994
+ }
995
+ };
996
+ }
997
+ else if (endpointPath === "/auth/magiclink" && methodLower === "post") {
998
+ operation.description = "Send magic link for passwordless login";
999
+ operation.requestBody = {
1000
+ required: true,
1001
+ content: {
1002
+ "application/json": {
1003
+ schema: { $ref: "#/components/schemas/MagicLinkRequest" }
1004
+ }
1005
+ }
1006
+ };
1007
+ }
1008
+ else if (endpointPath.includes("{token}")) {
1009
+ operation.parameters = [{
1010
+ name: "token",
1011
+ in: "path",
1012
+ required: true,
1013
+ schema: { type: "string" },
1014
+ description: "Token parameter"
1015
+ }];
1016
+ }
1017
+ return operation;
1018
+ }
1019
+ function createNotificationEndpointOperation(endpoint) {
1020
+ const { path: endpointPath, method, description, category } = endpoint;
1021
+ const methodLower = method.toLowerCase();
1022
+ const operation = {
1023
+ summary: description,
1024
+ tags: [category],
1025
+ responses: getStandardResponses()
1026
+ };
1027
+ if (endpointPath === "/notifications" && methodLower === "get") {
1028
+ operation.description = "Get user notifications with pagination and filtering";
1029
+ operation.responses["200"] = {
1030
+ description: "List of notifications",
1031
+ content: {
1032
+ "application/json": {
1033
+ schema: { $ref: "#/components/schemas/NotificationListResponse" }
1034
+ }
1035
+ }
1036
+ };
1037
+ operation.parameters = [
1038
+ {
1039
+ name: "filter",
1040
+ in: "query",
1041
+ schema: { type: "string" },
1042
+ description: "JSON filter object for notifications"
1043
+ },
1044
+ {
1045
+ name: "sort",
1046
+ in: "query",
1047
+ schema: { type: "string" },
1048
+ description: "Sorting criteria"
1049
+ },
1050
+ {
1051
+ name: "limit",
1052
+ in: "query",
1053
+ schema: { type: "integer", default: 100 },
1054
+ description: "Number of notifications per page"
1055
+ },
1056
+ {
1057
+ name: "page",
1058
+ in: "query",
1059
+ schema: { type: "integer", default: 1 },
1060
+ description: "Page number"
1061
+ }
1062
+ ];
1063
+ }
1064
+ else if (endpointPath === "/notifications/unread/count" && methodLower === "get") {
1065
+ operation.description = "Get count of unread notifications";
1066
+ operation.responses["200"] = {
1067
+ description: "Unread notifications count",
1068
+ content: {
1069
+ "application/json": {
1070
+ schema: { $ref: "#/components/schemas/NotificationCountResponse" }
1071
+ }
1072
+ }
1073
+ };
1074
+ }
1075
+ else if (endpointPath === "/notifications/mark-seen" && methodLower === "post") {
1076
+ operation.description = "Mark notifications as seen";
1077
+ operation.requestBody = {
1078
+ required: false,
1079
+ content: {
1080
+ "application/json": {
1081
+ schema: {
1082
+ type: "object",
1083
+ properties: {
1084
+ notificationIds: {
1085
+ type: "array",
1086
+ items: { type: "string", format: "uuid" },
1087
+ description: "Optional array of specific notification IDs to mark as seen"
1088
+ }
1089
+ }
1090
+ }
1091
+ }
1092
+ }
1093
+ };
1094
+ }
1095
+ else if (endpointPath === "/notifications" && methodLower === "delete") {
1096
+ operation.description = "Delete notifications";
1097
+ operation.requestBody = {
1098
+ required: false,
1099
+ content: {
1100
+ "application/json": {
1101
+ schema: {
1102
+ type: "object",
1103
+ properties: {
1104
+ notificationIds: {
1105
+ type: "array",
1106
+ items: { type: "string", format: "uuid" },
1107
+ description: "Optional array of specific notification IDs to delete"
1108
+ }
1109
+ }
1110
+ }
1111
+ }
1112
+ }
1113
+ };
1114
+ }
1115
+ else if (endpointPath === "/notifications/send" && methodLower === "post") {
1116
+ operation.description = "Send notifications to users (admin only)";
1117
+ operation.requestBody = {
1118
+ required: true,
1119
+ content: {
1120
+ "application/json": {
1121
+ schema: {
1122
+ type: "object",
1123
+ properties: {
1124
+ type: { type: "string", description: "Notification type" },
1125
+ title: { type: "string", description: "Notification title" },
1126
+ message: { type: "string", description: "Notification message" },
1127
+ userIds: {
1128
+ type: "array",
1129
+ items: { type: "string", format: "uuid" },
1130
+ description: "Array of user IDs to notify"
1131
+ },
1132
+ data: { type: "object", description: "Additional notification data" }
1133
+ },
1134
+ required: ["type", "title", "message", "userIds"]
1135
+ }
1136
+ }
1137
+ }
1138
+ };
1139
+ }
1140
+ return operation;
1141
+ }
1142
+ function createFileEndpointOperation(endpoint) {
1143
+ const { path: endpointPath, method, description, category } = endpoint;
1144
+ const methodLower = method.toLowerCase();
1145
+ const operation = {
1146
+ summary: description,
1147
+ tags: [category],
1148
+ responses: getStandardResponses()
1149
+ };
1150
+ if (endpointPath === "/files" && methodLower === "get") {
1151
+ operation.description = "Get all files with pagination and filtering";
1152
+ operation.responses["200"] = {
1153
+ description: "List of files",
1154
+ content: {
1155
+ "application/json": {
1156
+ schema: {
1157
+ type: "object",
1158
+ properties: {
1159
+ data: {
1160
+ type: "array",
1161
+ items: { $ref: "#/components/schemas/baasix_File" }
1162
+ },
1163
+ totalCount: { type: "integer" }
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+ };
1169
+ }
1170
+ else if (endpointPath === "/files" && methodLower === "post") {
1171
+ operation.description = "Upload a file to the server. Supports multiple storage providers.";
1172
+ operation.requestBody = {
1173
+ required: true,
1174
+ content: {
1175
+ "multipart/form-data": {
1176
+ schema: {
1177
+ type: "object",
1178
+ properties: {
1179
+ file: { type: "string", format: "binary", description: "File to upload" },
1180
+ title: { type: "string", description: "Optional file title" },
1181
+ storage: { type: "string", description: "Storage service to use" }
1182
+ },
1183
+ required: ["file"]
1184
+ }
1185
+ }
1186
+ }
1187
+ };
1188
+ operation.responses["200"] = {
1189
+ description: "File uploaded successfully",
1190
+ content: {
1191
+ "application/json": {
1192
+ schema: { $ref: "#/components/schemas/FileUploadResponse" }
1193
+ }
1194
+ }
1195
+ };
1196
+ }
1197
+ else if (endpointPath === "/files/upload-from-url" && methodLower === "post") {
1198
+ operation.description = "Upload a file from a URL";
1199
+ operation.requestBody = {
1200
+ required: true,
1201
+ content: {
1202
+ "application/json": {
1203
+ schema: {
1204
+ type: "object",
1205
+ properties: {
1206
+ url: { type: "string", format: "uri", description: "URL of file to upload" },
1207
+ title: { type: "string", description: "Optional file title" },
1208
+ storage: { type: "string", description: "Storage service to use" }
1209
+ },
1210
+ required: ["url"]
1211
+ }
1212
+ }
1213
+ }
1214
+ };
1215
+ }
1216
+ else if (endpointPath.includes("{id}")) {
1217
+ operation.parameters = [{
1218
+ name: "id",
1219
+ in: "path",
1220
+ required: true,
1221
+ schema: { type: "string" },
1222
+ description: "File ID"
1223
+ }];
1224
+ if (methodLower === "get") {
1225
+ operation.responses["200"] = {
1226
+ description: "File details",
1227
+ content: {
1228
+ "application/json": {
1229
+ schema: {
1230
+ type: "object",
1231
+ properties: {
1232
+ data: { $ref: "#/components/schemas/baasix_File" }
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ };
1238
+ }
1239
+ else if (methodLower === "patch") {
1240
+ operation.description = "Update file metadata or replace file content";
1241
+ operation.requestBody = {
1242
+ required: false,
1243
+ content: {
1244
+ "multipart/form-data": {
1245
+ schema: {
1246
+ type: "object",
1247
+ properties: {
1248
+ file: { type: "string", format: "binary", description: "New file content (optional)" },
1249
+ title: { type: "string", description: "Updated file title" }
1250
+ }
1251
+ }
1252
+ }
1253
+ }
1254
+ };
1255
+ }
1256
+ }
1257
+ return operation;
1258
+ }
1259
+ function createSchemaEndpointOperation(endpoint) {
1260
+ const { path: endpointPath, method, description, category } = endpoint;
1261
+ const methodLower = method.toLowerCase();
1262
+ const operation = {
1263
+ summary: description,
1264
+ tags: [category],
1265
+ responses: getStandardResponses()
1266
+ };
1267
+ if (endpointPath === "/schemas" && methodLower === "get") {
1268
+ operation.description = "Retrieve all available schemas/collections in the system.";
1269
+ operation.responses["200"] = {
1270
+ description: "List of schemas",
1271
+ content: {
1272
+ "application/json": {
1273
+ schema: {
1274
+ type: "object",
1275
+ properties: {
1276
+ data: {
1277
+ type: "array",
1278
+ items: { $ref: "#/components/schemas/Schema" }
1279
+ },
1280
+ totalCount: { type: "integer" }
1281
+ }
1282
+ }
1283
+ }
1284
+ }
1285
+ };
1286
+ }
1287
+ else if (endpointPath === "/schemas" && methodLower === "post") {
1288
+ operation.description = "Create a new schema/collection";
1289
+ operation.requestBody = {
1290
+ required: true,
1291
+ content: {
1292
+ "application/json": {
1293
+ schema: {
1294
+ type: "object",
1295
+ properties: {
1296
+ collectionName: { type: "string", description: "Name of the collection" },
1297
+ schema: { $ref: "#/components/schemas/Schema/properties/schema" }
1298
+ },
1299
+ required: ["collectionName", "schema"]
1300
+ }
1301
+ }
1302
+ }
1303
+ };
1304
+ }
1305
+ else if (endpointPath.includes("{collectionName}")) {
1306
+ operation.parameters = [{
1307
+ name: "collectionName",
1308
+ in: "path",
1309
+ required: true,
1310
+ schema: { type: "string" },
1311
+ description: "Name of the collection/schema"
1312
+ }];
1313
+ if (methodLower === "get") {
1314
+ operation.description = "Get detailed schema definition for a specific collection.";
1315
+ operation.responses["200"] = {
1316
+ description: "Schema details",
1317
+ content: {
1318
+ "application/json": {
1319
+ schema: {
1320
+ type: "object",
1321
+ properties: {
1322
+ data: { $ref: "#/components/schemas/Schema" }
1323
+ }
1324
+ }
1325
+ }
1326
+ }
1327
+ };
1328
+ }
1329
+ }
1330
+ return operation;
1331
+ }
1332
+ function createExtensionEndpointOperation(endpoint) {
1333
+ return {
1334
+ summary: endpoint.description,
1335
+ description: "Custom endpoint provided by an extension. Refer to extension documentation for detailed parameters and responses.",
1336
+ tags: [endpoint.category],
1337
+ responses: getStandardResponses()
1338
+ };
1339
+ }
1340
+ function createPermissionEndpointOperation(endpoint) {
1341
+ const { path: endpointPath, method, description, category } = endpoint;
1342
+ const methodLower = method.toLowerCase();
1343
+ const operation = {
1344
+ summary: description,
1345
+ tags: [category],
1346
+ responses: getStandardResponses()
1347
+ };
1348
+ if (endpointPath === "/permissions" && methodLower === "get") {
1349
+ operation.description = "Get permissions with pagination and filtering";
1350
+ operation.responses["200"] = {
1351
+ description: "List of permissions",
1352
+ content: {
1353
+ "application/json": {
1354
+ schema: {
1355
+ type: "object",
1356
+ properties: {
1357
+ data: {
1358
+ type: "array",
1359
+ items: { $ref: "#/components/schemas/baasix_Permission" }
1360
+ },
1361
+ totalCount: { type: "integer" }
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ };
1367
+ }
1368
+ else if (endpointPath === "/permissions" && methodLower === "post") {
1369
+ operation.description = "Create new permission";
1370
+ operation.requestBody = {
1371
+ required: true,
1372
+ content: {
1373
+ "application/json": {
1374
+ schema: {
1375
+ type: "object",
1376
+ properties: {
1377
+ action: { type: "string", description: "Action (create, read, update, delete, etc.)" },
1378
+ collection: { type: "string", description: "Collection name" },
1379
+ role_Id: { type: "string", format: "uuid", description: "Role ID" },
1380
+ fields: { type: "object", description: "Field-level permissions" },
1381
+ conditions: { type: "object", description: "Access conditions" }
1382
+ },
1383
+ required: ["action", "collection", "role_Id"]
1384
+ }
1385
+ }
1386
+ }
1387
+ };
1388
+ }
1389
+ else if (endpointPath.includes("{id}")) {
1390
+ operation.parameters = [{
1391
+ name: "id",
1392
+ in: "path",
1393
+ required: true,
1394
+ schema: { type: "string" },
1395
+ description: "Permission ID"
1396
+ }];
1397
+ if (methodLower === "get") {
1398
+ operation.responses["200"] = {
1399
+ description: "Permission details",
1400
+ content: {
1401
+ "application/json": {
1402
+ schema: {
1403
+ type: "object",
1404
+ properties: {
1405
+ data: { $ref: "#/components/schemas/baasix_Permission" }
1406
+ }
1407
+ }
1408
+ }
1409
+ }
1410
+ };
1411
+ }
1412
+ }
1413
+ return operation;
1414
+ }
1415
+ function createUtilsEndpointOperation(endpoint) {
1416
+ const { path: endpointPath, method, description, category } = endpoint;
1417
+ const methodLower = method.toLowerCase();
1418
+ const operation = {
1419
+ summary: description,
1420
+ tags: [category],
1421
+ responses: getStandardResponses()
1422
+ };
1423
+ if (endpointPath === "/utils/sort/{collection}" && methodLower === "post") {
1424
+ operation.description = "Sort items within a collection by moving an item before/after another item";
1425
+ operation.parameters = [{
1426
+ name: "collection",
1427
+ in: "path",
1428
+ required: true,
1429
+ schema: { type: "string" },
1430
+ description: "Collection name to sort items in"
1431
+ }];
1432
+ operation.requestBody = {
1433
+ required: true,
1434
+ content: {
1435
+ "application/json": {
1436
+ schema: {
1437
+ type: "object",
1438
+ properties: {
1439
+ item: { type: "string", description: "ID of item to move" },
1440
+ to: { type: "string", description: "ID of target item to move relative to" }
1441
+ },
1442
+ required: ["item", "to"]
1443
+ }
1444
+ }
1445
+ }
1446
+ };
1447
+ }
1448
+ return operation;
1449
+ }
1450
+ function createCollectionEndpointOperation(endpoint) {
1451
+ const { path: endpointPath, method, description, collectionName } = endpoint;
1452
+ const methodLower = method.toLowerCase();
1453
+ const operation = {
1454
+ summary: description,
1455
+ description: getCollectionEndpointDescription(endpointPath, methodLower, collectionName),
1456
+ tags: ["data"],
1457
+ responses: getStandardResponses()
1458
+ };
1459
+ if (methodLower === "get" && !endpointPath.includes("{id}")) {
1460
+ // List endpoint
1461
+ operation.responses["200"] = {
1462
+ description: "List of items with pagination",
1463
+ content: {
1464
+ "application/json": {
1465
+ schema: {
1466
+ type: "object",
1467
+ properties: {
1468
+ data: {
1469
+ type: "array",
1470
+ items: { $ref: `#/components/schemas/${collectionName}` },
1471
+ description: `Array of ${collectionName} items`
1472
+ },
1473
+ totalCount: {
1474
+ type: "integer",
1475
+ description: "Total number of items available"
1476
+ },
1477
+ page: {
1478
+ type: "integer",
1479
+ description: "Current page number (1-based)"
1480
+ },
1481
+ limit: {
1482
+ type: "integer",
1483
+ description: "Number of items per page"
1484
+ }
1485
+ },
1486
+ required: ["data"]
1487
+ }
1488
+ }
1489
+ }
1490
+ };
1491
+ // Add comprehensive query parameters
1492
+ operation.parameters = [
1493
+ {
1494
+ name: "fields",
1495
+ in: "query",
1496
+ schema: { type: "string" },
1497
+ description: "Comma-separated list of fields to return. Use dot notation for nested/relational fields (e.g., 'name,email,category.name,user.profile.avatar')"
1498
+ },
1499
+ {
1500
+ name: "filter",
1501
+ in: "query",
1502
+ schema: { type: "string" },
1503
+ description: "JSON filter object. Supports operators: eq, ne, lt, lte, gt, gte, in, notIn, like, startsWith, endsWith, isNull, isNotNull, between, etc. Use fieldName or $fieldName$ syntax for fields (both supported) and relationName.fieldName for relational fields. Supports AND/OR logic. Examples: {\"name\":{\"eq\":\"test\"}} or {\"AND\":[{\"age\":{\"gte\":18}},{\"user.status\":{\"eq\":\"active\"}}]}"
1504
+ },
1505
+ {
1506
+ name: "sort",
1507
+ in: "query",
1508
+ schema: { type: "string" },
1509
+ description: "JSON array of sort objects. Each object specifies field and direction. Supports relational field sorting. Examples: [{\"name\":\"asc\"}] or [{\"createdAt\":\"desc\"},{\"user.name\":\"asc\"}] or [{\"category.name\":\"asc\",\"price\":\"desc\"}]"
1510
+ },
1511
+ {
1512
+ name: "limit",
1513
+ in: "query",
1514
+ schema: {
1515
+ type: "integer",
1516
+ minimum: -1,
1517
+ maximum: 1000,
1518
+ default: 100
1519
+ },
1520
+ description: "Number of items to return per page. Set to -1 to get all data without pagination (max 1000 for safety, default 100)"
1521
+ },
1522
+ {
1523
+ name: "page",
1524
+ in: "query",
1525
+ schema: {
1526
+ type: "integer",
1527
+ minimum: 1,
1528
+ default: 1
1529
+ },
1530
+ description: "Page number for pagination (1-based, default 1). Only used when limit is not -1"
1531
+ },
1532
+ {
1533
+ name: "search",
1534
+ in: "query",
1535
+ schema: { type: "string" },
1536
+ description: "Full-text search term. Searches across searchable fields in the collection."
1537
+ },
1538
+ {
1539
+ name: "searchFields",
1540
+ in: "query",
1541
+ schema: { type: "string" },
1542
+ description: "Comma-separated list of fields to search in. Only applies when 'search' parameter is used."
1543
+ },
1544
+ {
1545
+ name: "relConditions",
1546
+ in: "query",
1547
+ schema: { type: "string" },
1548
+ description: "JSON object for filtering related/nested data separately from main filter. Allows filtering on relationships after they're loaded. Field names can use either plain or $field$ syntax (both supported). Example: {\"relationName\":{\"field\":{\"eq\":\"value\"}},\"nestedRelation\":{\"field\":{\"gt\":100}}}"
1549
+ },
1550
+ {
1551
+ name: "aggregate",
1552
+ in: "query",
1553
+ schema: { type: "string" },
1554
+ description: "JSON object for aggregation operations. Example: {\"count\":\"*\",\"avg\":\"age\",\"sum\":\"amount\"}"
1555
+ },
1556
+ {
1557
+ name: "groupBy",
1558
+ in: "query",
1559
+ schema: { type: "string" },
1560
+ description: "Comma-separated list of fields to group by. Used with aggregate functions."
1561
+ }
1562
+ ];
1563
+ }
1564
+ else if (methodLower === "get" && endpointPath.includes("{id}")) {
1565
+ // Single item endpoint
1566
+ operation.responses["200"] = {
1567
+ description: "Single item details",
1568
+ content: {
1569
+ "application/json": {
1570
+ schema: {
1571
+ type: "object",
1572
+ properties: {
1573
+ data: {
1574
+ $ref: `#/components/schemas/${collectionName}`,
1575
+ description: `${collectionName} item details`
1576
+ }
1577
+ },
1578
+ required: ["data"]
1579
+ }
1580
+ }
1581
+ }
1582
+ };
1583
+ operation.parameters = [
1584
+ {
1585
+ name: "id",
1586
+ in: "path",
1587
+ required: true,
1588
+ schema: { type: "string" },
1589
+ description: "Unique identifier of the item"
1590
+ },
1591
+ {
1592
+ name: "fields",
1593
+ in: "query",
1594
+ schema: { type: "string" },
1595
+ description: "Comma-separated list of fields to return. Use dot notation for nested/relational fields (e.g., 'name,email,category.name,user.profile.avatar')"
1596
+ }
1597
+ ];
1598
+ }
1599
+ else if (methodLower === "post") {
1600
+ // Create endpoint
1601
+ operation.responses["201"] = {
1602
+ description: "Item created successfully",
1603
+ content: {
1604
+ "application/json": {
1605
+ schema: {
1606
+ type: "object",
1607
+ properties: {
1608
+ data: {
1609
+ $ref: `#/components/schemas/${collectionName}`,
1610
+ description: `Created ${collectionName} item`
1611
+ }
1612
+ },
1613
+ required: ["data"]
1614
+ }
1615
+ }
1616
+ }
1617
+ };
1618
+ operation.requestBody = {
1619
+ required: true,
1620
+ content: {
1621
+ "application/json": {
1622
+ schema: { $ref: `#/components/schemas/${collectionName}CreateRequest` }
1623
+ }
1624
+ }
1625
+ };
1626
+ }
1627
+ else if (["put", "patch"].includes(methodLower)) {
1628
+ // Update endpoints
1629
+ operation.responses["200"] = {
1630
+ description: "Item updated successfully",
1631
+ content: {
1632
+ "application/json": {
1633
+ schema: {
1634
+ type: "object",
1635
+ properties: {
1636
+ data: {
1637
+ $ref: `#/components/schemas/${collectionName}`,
1638
+ description: `Updated ${collectionName} item`
1639
+ }
1640
+ },
1641
+ required: ["data"]
1642
+ }
1643
+ }
1644
+ }
1645
+ };
1646
+ operation.parameters = [{
1647
+ name: "id",
1648
+ in: "path",
1649
+ required: true,
1650
+ schema: { type: "string" },
1651
+ description: "Unique identifier of the item to update"
1652
+ }];
1653
+ operation.requestBody = {
1654
+ required: true,
1655
+ content: {
1656
+ "application/json": {
1657
+ schema: {
1658
+ $ref: methodLower === "put" ?
1659
+ `#/components/schemas/${collectionName}UpdateRequest` :
1660
+ `#/components/schemas/${collectionName}PatchRequest`
1661
+ }
1662
+ }
1663
+ }
1664
+ };
1665
+ }
1666
+ else if (methodLower === "delete") {
1667
+ // Delete endpoint
1668
+ operation.responses["204"] = {
1669
+ description: "Item deleted successfully"
1670
+ };
1671
+ operation.parameters = [{
1672
+ name: "id",
1673
+ in: "path",
1674
+ required: true,
1675
+ schema: { type: "string" },
1676
+ description: "Unique identifier of the item to delete"
1677
+ }];
1678
+ }
1679
+ return operation;
1680
+ }
1681
+ // Helper function to convert Baasix field types to OpenAPI types
1682
+ function convertBaasixTypeToOpenApi(baasixType, field) {
1683
+ const typeMap = {
1684
+ 'String': { type: 'string' },
1685
+ 'Text': { type: 'string' },
1686
+ 'Integer': { type: 'integer', format: 'int32' },
1687
+ 'Double': { type: 'number', format: 'double' },
1688
+ 'Boolean': { type: 'boolean' },
1689
+ 'UUID': { type: 'string', format: 'uuid' },
1690
+ 'Date': { type: 'string', format: 'date-time' },
1691
+ 'JSON': { type: 'object' },
1692
+ 'ENUM': { type: 'string', enum: field.values || [] }
1693
+ };
1694
+ const openApiType = typeMap[baasixType] || { type: 'string' };
1695
+ if (field.defaultValue !== undefined) {
1696
+ openApiType.default = field.defaultValue;
1697
+ }
1698
+ if (baasixType === 'String' && field.length) {
1699
+ openApiType.maxLength = field.length;
1700
+ }
1701
+ return openApiType;
1702
+ }
1703
+ // Generate dynamic schemas for collections
1704
+ function generateCollectionSchemas(endpoints) {
1705
+ const collectionSchemas = {};
1706
+ for (const endpoint of endpoints) {
1707
+ if (endpoint.type === 'collection' && endpoint.schema) {
1708
+ const { collectionName, schema } = endpoint;
1709
+ if (!collectionSchemas[collectionName]) {
1710
+ const schemaDefinition = generateSchemaDefinition(schema, collectionName);
1711
+ collectionSchemas[collectionName] = schemaDefinition.item;
1712
+ collectionSchemas[`${collectionName}CreateRequest`] = schemaDefinition.createRequest;
1713
+ collectionSchemas[`${collectionName}UpdateRequest`] = schemaDefinition.updateRequest;
1714
+ collectionSchemas[`${collectionName}PatchRequest`] = schemaDefinition.patchRequest;
1715
+ }
1716
+ }
1717
+ }
1718
+ return collectionSchemas;
1719
+ }
1720
+ function generateSchemaDefinition(schema, collectionName) {
1721
+ const properties = {};
1722
+ const required = [];
1723
+ const createRequired = [];
1724
+ const relationships = {};
1725
+ // Process fields
1726
+ if (schema.fields) {
1727
+ for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
1728
+ // Skip system generated fields and relationships for create requests
1729
+ const isSystemGenerated = fieldDef.SystemGenerated === true || fieldDef.SystemGenerated === "true";
1730
+ const isRelationship = fieldDef.relType;
1731
+ if (isRelationship) {
1732
+ // Handle relationships with proper schema references
1733
+ const targetCollection = fieldDef.target;
1734
+ let schemaRef;
1735
+ if (targetCollection.startsWith('baasix_')) {
1736
+ // System collection - create a simplified reference
1737
+ schemaRef = {
1738
+ type: 'object',
1739
+ description: `${fieldDef.relType} relationship to ${targetCollection}`,
1740
+ readOnly: true
1741
+ };
1742
+ }
1743
+ else {
1744
+ // User collection - reference the schema if it exists
1745
+ if (fieldDef.relType === 'HasMany' || fieldDef.relType === 'BelongsToMany') {
1746
+ schemaRef = {
1747
+ type: 'array',
1748
+ items: { $ref: `#/components/schemas/${targetCollection}` },
1749
+ description: `${fieldDef.relType} relationship to ${targetCollection}`,
1750
+ readOnly: true
1751
+ };
1752
+ }
1753
+ else {
1754
+ schemaRef = {
1755
+ $ref: `#/components/schemas/${targetCollection}`,
1756
+ description: `${fieldDef.relType} relationship to ${targetCollection}`,
1757
+ readOnly: true
1758
+ };
1759
+ }
1760
+ }
1761
+ relationships[fieldName] = schemaRef;
1762
+ continue;
1763
+ }
1764
+ const openApiField = convertBaasixTypeToOpenApi(fieldDef.type, fieldDef);
1765
+ // Add description
1766
+ if (fieldDef.description) {
1767
+ openApiField.description = fieldDef.description;
1768
+ }
1769
+ else {
1770
+ openApiField.description = `${fieldName} field`;
1771
+ }
1772
+ // Add to properties
1773
+ properties[fieldName] = openApiField;
1774
+ // Handle required fields
1775
+ if (fieldDef.allowNull === false && !isSystemGenerated) {
1776
+ required.push(fieldName);
1777
+ if (!fieldDef.primaryKey && !fieldDef.defaultValue) {
1778
+ createRequired.push(fieldName);
1779
+ }
1780
+ }
1781
+ }
1782
+ }
1783
+ // Add timestamps if enabled
1784
+ if (schema.timestamps) {
1785
+ properties.createdAt = {
1786
+ type: 'string',
1787
+ format: 'date-time',
1788
+ description: 'Record creation timestamp',
1789
+ readOnly: true
1790
+ };
1791
+ properties.updatedAt = {
1792
+ type: 'string',
1793
+ format: 'date-time',
1794
+ description: 'Record last update timestamp',
1795
+ readOnly: true
1796
+ };
1797
+ }
1798
+ // Create the main item schema (for responses)
1799
+ const itemSchema = {
1800
+ type: 'object',
1801
+ properties: {
1802
+ ...properties,
1803
+ ...relationships
1804
+ }
1805
+ };
1806
+ if (required.length > 0) {
1807
+ itemSchema.required = required;
1808
+ }
1809
+ // Create request schemas (without read-only fields)
1810
+ const createProperties = {};
1811
+ const updateProperties = {};
1812
+ for (const [fieldName, fieldDef] of Object.entries(properties)) {
1813
+ const fd = fieldDef;
1814
+ if (!fd.readOnly) {
1815
+ // Only spread when the field definition is an object; otherwise assign directly
1816
+ if (fd && typeof fd === "object") {
1817
+ createProperties[fieldName] = { ...fd };
1818
+ updateProperties[fieldName] = { ...fd };
1819
+ }
1820
+ else {
1821
+ createProperties[fieldName] = fd;
1822
+ updateProperties[fieldName] = fd;
1823
+ }
1824
+ }
1825
+ }
1826
+ const createRequestSchema = {
1827
+ type: 'object',
1828
+ properties: createProperties,
1829
+ description: `Data for creating a new ${collectionName} item`
1830
+ };
1831
+ if (createRequired.length > 0) {
1832
+ createRequestSchema.required = createRequired;
1833
+ }
1834
+ const updateRequestSchema = {
1835
+ type: 'object',
1836
+ properties: updateProperties,
1837
+ description: `Complete data for updating a ${collectionName} item (all fields will be replaced)`
1838
+ };
1839
+ const patchRequestSchema = {
1840
+ type: 'object',
1841
+ properties: updateProperties,
1842
+ description: `Partial data for updating a ${collectionName} item (only provided fields will be updated)`
1843
+ };
1844
+ return {
1845
+ item: itemSchema,
1846
+ createRequest: createRequestSchema,
1847
+ updateRequest: updateRequestSchema,
1848
+ patchRequest: patchRequestSchema
1849
+ };
1850
+ }
1851
+ // Helper function to get standard responses
1852
+ function getStandardResponses() {
1853
+ return {
1854
+ "400": {
1855
+ description: "Bad Request - Invalid input parameters",
1856
+ content: {
1857
+ "application/json": {
1858
+ schema: {
1859
+ type: "object",
1860
+ properties: {
1861
+ error: { type: "string" },
1862
+ message: { type: "string" }
1863
+ }
1864
+ }
1865
+ }
1866
+ }
1867
+ },
1868
+ "401": {
1869
+ description: "Unauthorized - Authentication required",
1870
+ content: {
1871
+ "application/json": {
1872
+ schema: {
1873
+ type: "object",
1874
+ properties: {
1875
+ error: { type: "string" },
1876
+ message: { type: "string" }
1877
+ }
1878
+ }
1879
+ }
1880
+ }
1881
+ },
1882
+ "403": {
1883
+ description: "Forbidden - Insufficient permissions",
1884
+ content: {
1885
+ "application/json": {
1886
+ schema: {
1887
+ type: "object",
1888
+ properties: {
1889
+ error: { type: "string" },
1890
+ message: { type: "string" }
1891
+ }
1892
+ }
1893
+ }
1894
+ }
1895
+ },
1896
+ "404": {
1897
+ description: "Not Found - Resource does not exist",
1898
+ content: {
1899
+ "application/json": {
1900
+ schema: {
1901
+ type: "object",
1902
+ properties: {
1903
+ error: { type: "string" },
1904
+ message: { type: "string" }
1905
+ }
1906
+ }
1907
+ }
1908
+ }
1909
+ },
1910
+ "500": {
1911
+ description: "Internal Server Error",
1912
+ content: {
1913
+ "application/json": {
1914
+ schema: {
1915
+ type: "object",
1916
+ properties: {
1917
+ error: { type: "string" },
1918
+ message: { type: "string" }
1919
+ }
1920
+ }
1921
+ }
1922
+ }
1923
+ }
1924
+ };
1925
+ }
1926
+ // Helper function to get collection endpoint descriptions
1927
+ function getCollectionEndpointDescription(path, method, collectionName) {
1928
+ const methodDescriptions = {
1929
+ "get": path.includes("/{id}")
1930
+ ? `Get a specific ${collectionName} item by ID`
1931
+ : `Get list of ${collectionName} items with optional filtering, sorting, and pagination`,
1932
+ "post": `Create a new ${collectionName} item`,
1933
+ "put": `Update a ${collectionName} item (replace all fields)`,
1934
+ "patch": `Partially update a ${collectionName} item (update only provided fields)`,
1935
+ "delete": `Delete a ${collectionName} item by ID`
1936
+ };
1937
+ return methodDescriptions[method] || `${method.toUpperCase()} operation for ${collectionName}`;
1938
+ }
1939
+ function createRealtimeEndpointOperation(endpoint) {
1940
+ const { path: endpointPath, method, description, category } = endpoint;
1941
+ const methodLower = method.toLowerCase();
1942
+ const operation = {
1943
+ summary: description,
1944
+ tags: ["realtime"],
1945
+ security: [{ bearerAuth: [] }],
1946
+ responses: getStandardResponses()
1947
+ };
1948
+ if (endpointPath === "/realtime/status" && methodLower === "get") {
1949
+ operation.description = "Get the current status of the realtime WAL service including replication configuration";
1950
+ operation.responses["200"] = {
1951
+ description: "Realtime service status",
1952
+ content: {
1953
+ "application/json": {
1954
+ schema: {
1955
+ type: "object",
1956
+ properties: {
1957
+ data: {
1958
+ type: "object",
1959
+ properties: {
1960
+ initialized: { type: "boolean", description: "Whether the service is initialized" },
1961
+ connected: { type: "boolean", description: "Whether connected to PostgreSQL replication" },
1962
+ enabledCollections: {
1963
+ type: "array",
1964
+ items: { type: "string" },
1965
+ description: "List of collections with realtime enabled"
1966
+ },
1967
+ publicationName: { type: "string", description: "PostgreSQL publication name" },
1968
+ slotName: { type: "string", description: "PostgreSQL replication slot name" },
1969
+ walEnabled: { type: "boolean", description: "Whether WAL-based realtime is enabled" },
1970
+ replicationConfig: {
1971
+ type: "object",
1972
+ properties: {
1973
+ walLevel: { type: "string" },
1974
+ maxReplicationSlots: { type: "integer" },
1975
+ maxWalSenders: { type: "integer" },
1976
+ isConfigured: { type: "boolean" },
1977
+ issues: { type: "array", items: { type: "string" } }
1978
+ }
1979
+ }
1980
+ }
1981
+ }
1982
+ }
1983
+ }
1984
+ }
1985
+ }
1986
+ };
1987
+ }
1988
+ else if (endpointPath === "/realtime/config" && methodLower === "get") {
1989
+ operation.description = "Check PostgreSQL logical replication configuration requirements";
1990
+ operation.responses["200"] = {
1991
+ description: "PostgreSQL replication configuration",
1992
+ content: {
1993
+ "application/json": {
1994
+ schema: {
1995
+ type: "object",
1996
+ properties: {
1997
+ data: {
1998
+ type: "object",
1999
+ properties: {
2000
+ walLevel: { type: "string", description: "Current wal_level setting" },
2001
+ maxReplicationSlots: { type: "integer", description: "Maximum replication slots" },
2002
+ maxWalSenders: { type: "integer", description: "Maximum WAL senders" },
2003
+ isConfigured: { type: "boolean", description: "Whether all requirements are met" },
2004
+ issues: {
2005
+ type: "array",
2006
+ items: { type: "string" },
2007
+ description: "Configuration issues if any"
2008
+ }
2009
+ }
2010
+ }
2011
+ }
2012
+ }
2013
+ }
2014
+ }
2015
+ };
2016
+ }
2017
+ else if (endpointPath === "/realtime/collections" && methodLower === "get") {
2018
+ operation.description = "Get list of all collections that have realtime enabled";
2019
+ operation.responses["200"] = {
2020
+ description: "List of realtime-enabled collections",
2021
+ content: {
2022
+ "application/json": {
2023
+ schema: {
2024
+ type: "object",
2025
+ properties: {
2026
+ data: {
2027
+ type: "array",
2028
+ items: { type: "string" },
2029
+ description: "Collection names with realtime enabled"
2030
+ }
2031
+ }
2032
+ }
2033
+ }
2034
+ }
2035
+ };
2036
+ }
2037
+ else if (endpointPath === "/realtime/collections/{collection}" && methodLower === "get") {
2038
+ operation.description = "Check if a specific collection has realtime enabled";
2039
+ operation.parameters = [{
2040
+ name: "collection",
2041
+ in: "path",
2042
+ required: true,
2043
+ schema: { type: "string" },
2044
+ description: "Collection name"
2045
+ }];
2046
+ operation.responses["200"] = {
2047
+ description: "Collection realtime status",
2048
+ content: {
2049
+ "application/json": {
2050
+ schema: {
2051
+ type: "object",
2052
+ properties: {
2053
+ data: {
2054
+ type: "object",
2055
+ properties: {
2056
+ collection: { type: "string" },
2057
+ enabled: { type: "boolean" }
2058
+ }
2059
+ }
2060
+ }
2061
+ }
2062
+ }
2063
+ }
2064
+ };
2065
+ }
2066
+ else if (endpointPath === "/realtime/collections/{collection}/enable" && methodLower === "post") {
2067
+ operation.description = "Enable realtime for a collection. This adds the table to the PostgreSQL publication and starts streaming changes.";
2068
+ operation.parameters = [{
2069
+ name: "collection",
2070
+ in: "path",
2071
+ required: true,
2072
+ schema: { type: "string" },
2073
+ description: "Collection name to enable realtime for"
2074
+ }];
2075
+ operation.requestBody = {
2076
+ content: {
2077
+ "application/json": {
2078
+ schema: {
2079
+ type: "object",
2080
+ properties: {
2081
+ replicaIdentityFull: {
2082
+ type: "boolean",
2083
+ default: false,
2084
+ description: "Set REPLICA IDENTITY FULL to include old values on UPDATE/DELETE (requires table lock)"
2085
+ }
2086
+ }
2087
+ }
2088
+ }
2089
+ }
2090
+ };
2091
+ operation.responses["200"] = {
2092
+ description: "Realtime enabled successfully",
2093
+ content: {
2094
+ "application/json": {
2095
+ schema: {
2096
+ type: "object",
2097
+ properties: {
2098
+ data: {
2099
+ type: "object",
2100
+ properties: {
2101
+ message: { type: "string" },
2102
+ collection: { type: "string" },
2103
+ replicaIdentityFull: { type: "boolean" }
2104
+ }
2105
+ }
2106
+ }
2107
+ }
2108
+ }
2109
+ }
2110
+ };
2111
+ }
2112
+ else if (endpointPath === "/realtime/collections/{collection}/disable" && methodLower === "post") {
2113
+ operation.description = "Disable realtime for a collection. This removes the table from the PostgreSQL publication.";
2114
+ operation.parameters = [{
2115
+ name: "collection",
2116
+ in: "path",
2117
+ required: true,
2118
+ schema: { type: "string" },
2119
+ description: "Collection name to disable realtime for"
2120
+ }];
2121
+ operation.responses["200"] = {
2122
+ description: "Realtime disabled successfully",
2123
+ content: {
2124
+ "application/json": {
2125
+ schema: {
2126
+ type: "object",
2127
+ properties: {
2128
+ data: {
2129
+ type: "object",
2130
+ properties: {
2131
+ message: { type: "string" },
2132
+ collection: { type: "string" }
2133
+ }
2134
+ }
2135
+ }
2136
+ }
2137
+ }
2138
+ }
2139
+ };
2140
+ }
2141
+ else if (endpointPath === "/realtime/initialize" && methodLower === "post") {
2142
+ operation.description = "Manually initialize the realtime service if it was not auto-started";
2143
+ operation.responses["200"] = {
2144
+ description: "Realtime service initialized",
2145
+ content: {
2146
+ "application/json": {
2147
+ schema: {
2148
+ type: "object",
2149
+ properties: {
2150
+ data: {
2151
+ type: "object",
2152
+ properties: {
2153
+ message: { type: "string" },
2154
+ status: { type: "object" }
2155
+ }
2156
+ }
2157
+ }
2158
+ }
2159
+ }
2160
+ }
2161
+ };
2162
+ }
2163
+ return operation;
2164
+ }
2165
+ export default {
2166
+ id: "openapi",
2167
+ handler: registerEndpoint,
2168
+ };
2169
+ //# sourceMappingURL=openapi.route.js.map