@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.
- package/LICENSE.MD +85 -0
- package/README.md +526 -0
- package/assets/banner.jpg +0 -0
- package/assets/banner_small.jpg +0 -0
- package/assets/logo_icon.svg +20 -0
- package/assets/logo_icon_rounded.svg +20 -0
- package/dist/LICENSE.MD +85 -0
- package/dist/README.md +526 -0
- package/dist/app/404/index.html +1 -0
- package/dist/app/404.html +1 -0
- package/dist/app/_next/static/chunks/041e1f03-56ae8a902a7f2fe6.js +24 -0
- package/dist/app/_next/static/chunks/1117-05479929a8da73e3.js +1 -0
- package/dist/app/_next/static/chunks/1299.77cc7b7b76b75cba.js +1 -0
- package/dist/app/_next/static/chunks/1303-35a96e9c9cdeab9d.js +1 -0
- package/dist/app/_next/static/chunks/1509-56ac00cdaaecdf53.js +1 -0
- package/dist/app/_next/static/chunks/1668-e3eabd0f6753c780.js +1 -0
- package/dist/app/_next/static/chunks/1783-d9fb550fd324300c.js +1 -0
- package/dist/app/_next/static/chunks/2117-29b5fa47421595ad.js +2 -0
- package/dist/app/_next/static/chunks/2344.35b46d2179a765b5.js +1 -0
- package/dist/app/_next/static/chunks/257.990da16794a31292.js +1 -0
- package/dist/app/_next/static/chunks/2676-73b0ee7c80073a84.js +1 -0
- package/dist/app/_next/static/chunks/3563-b8842744384391fe.js +1 -0
- package/dist/app/_next/static/chunks/363642f4-933b579ed3c85f60.js +1 -0
- package/dist/app/_next/static/chunks/3817-e20c8f0a0810fc95.js +1 -0
- package/dist/app/_next/static/chunks/3834.84944e390d902509.js +2 -0
- package/dist/app/_next/static/chunks/4043-3a30c8a75896f241.js +1 -0
- package/dist/app/_next/static/chunks/4225-14090c7c0cd9dec6.js +1 -0
- package/dist/app/_next/static/chunks/4438-c9a12ca15b6e9160.js +1 -0
- package/dist/app/_next/static/chunks/4458-679fd0c6884f456a.js +1 -0
- package/dist/app/_next/static/chunks/4475-8bdfbd536fba8c48.js +1 -0
- package/dist/app/_next/static/chunks/4883-8a924721bb21b3b0.js +1 -0
- package/dist/app/_next/static/chunks/489-683ab07188f9df2b.js +1 -0
- package/dist/app/_next/static/chunks/4952-1b97320cf61f3f21.js +1 -0
- package/dist/app/_next/static/chunks/5094-8d53e403235d4ca6.js +1 -0
- package/dist/app/_next/static/chunks/5101-3a146e0625747ad1.js +1 -0
- package/dist/app/_next/static/chunks/54a60aa6-d9747982e0a81f58.js +79 -0
- package/dist/app/_next/static/chunks/5650-f096291df402bfc2.js +1 -0
- package/dist/app/_next/static/chunks/600-539045311240f579.js +1 -0
- package/dist/app/_next/static/chunks/6170-803b82e19d3ade6d.js +89 -0
- package/dist/app/_next/static/chunks/6241-30d7169d1010e5a4.js +1 -0
- package/dist/app/_next/static/chunks/6530-a91e10cffa4200c4.js +1 -0
- package/dist/app/_next/static/chunks/6547-4bbbdb5c399aef1e.js +1 -0
- package/dist/app/_next/static/chunks/6712-781937c53a2c49da.js +1 -0
- package/dist/app/_next/static/chunks/6fcbdc68-90be1a5480b8d353.js +1 -0
- package/dist/app/_next/static/chunks/70e0d97a-aeaf0cdc26ba1a58.js +1 -0
- package/dist/app/_next/static/chunks/7214-5154a89d08d24dde.js +1 -0
- package/dist/app/_next/static/chunks/7324-b53229c59a640880.js +10 -0
- package/dist/app/_next/static/chunks/7636-66424f0b51d350e9.js +1 -0
- package/dist/app/_next/static/chunks/7874-39a3f2541165a675.js +1 -0
- package/dist/app/_next/static/chunks/7982-9da12b83f11e3f5f.js +1 -0
- package/dist/app/_next/static/chunks/8213a2eb-da25a3b3c5521b2b.js +1 -0
- package/dist/app/_next/static/chunks/8473-6598318371eca31b.js +1 -0
- package/dist/app/_next/static/chunks/8640fa6b-72e43370f68e5587.js +1 -0
- package/dist/app/_next/static/chunks/9090-3ef676f29c95f1c7.js +1 -0
- package/dist/app/_next/static/chunks/9124-a02f9e209e6e3cce.js +1 -0
- package/dist/app/_next/static/chunks/926-156f32067d111d6b.js +1 -0
- package/dist/app/_next/static/chunks/9487-b17481605e513b83.js +1 -0
- package/dist/app/_next/static/chunks/9599-a7e572bb88c3392b.js +1 -0
- package/dist/app/_next/static/chunks/9881-419697138376e755.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/all-activity/page-8917930b4d663405.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/email-log/page-b27a6ee32782d7df.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/notifications/page-b7eda523ede2702c.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/page-1cfa62d1caedaed0.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/sessions/page-3e21e20db90aeff7.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/workflow-executions/page-27bcc26b747fb29b.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/activity-log/workflow-logs/page-9f9e9e952aef436e.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/change-password/page-8d61aa499eabb127.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/dashboard/page-1ceeac9e72997a8a.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/data-browser/page-8cda2b57759dd670.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/file-manager/page-8c6f1b1da66ad7e4.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/layout-f70d225b2759c998.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/migrations/page-aacec8f7cfb40ab2.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/permissions/page-828110cfcde429c6.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/project/page-420e794bb76bd204.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/roles/page-9001d02b28f70708.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/schema/page-899574f35091dd58.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/tasks/page-ad7ab3e27c83f44f.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/templates/edit/page-bd83414cb8c4cb04.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/templates/page-3181447f8772b1d3.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/settings/tenants/page-ef9bfbacef5a1d73.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/users/invites/page-480306b7b2bbac7e.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/users/list/page-74da51254c2606b3.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/users/page-e99c6f0b915001b2.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/users/preferences/page-1a935630ce8f2b12.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/users/user-roles/page-901dfb8ea1f39ca8.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/workflows/detail/page-9a6b839aea688ca4.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/workflows/edit/page-11774efbc2fecae2.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/workflows/execution/page-8ec1aea90412c03d.js +1 -0
- package/dist/app/_next/static/chunks/app/(authenticated)/workflows/page-88bc5b36ccb0a1f7.js +1 -0
- package/dist/app/_next/static/chunks/app/(public)/forgot-password/page-ed263fd46ef81c20.js +1 -0
- package/dist/app/_next/static/chunks/app/(public)/layout-f538977545844af8.js +1 -0
- package/dist/app/_next/static/chunks/app/(public)/login/page-c0a10b137f346096.js +1 -0
- package/dist/app/_next/static/chunks/app/(public)/register/page-4cb7644893efd9b3.js +1 -0
- package/dist/app/_next/static/chunks/app/_not-found/page-653f8815b78256cc.js +1 -0
- package/dist/app/_next/static/chunks/app/layout-591ca7a3e16528a1.js +1 -0
- package/dist/app/_next/static/chunks/app/page-dd19d124b5fa2577.js +1 -0
- package/dist/app/_next/static/chunks/c37d3baf.c2ff165f5b02c692.js +1 -0
- package/dist/app/_next/static/chunks/d0deef33.0379166a4ec23470.js +1 -0
- package/dist/app/_next/static/chunks/fd9d1056-54169f07cd680d6c.js +1 -0
- package/dist/app/_next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
- package/dist/app/_next/static/chunks/main-324e91f5a430cddf.js +1 -0
- package/dist/app/_next/static/chunks/main-app-55bcae20c77aaf0e.js +1 -0
- package/dist/app/_next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
- package/dist/app/_next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
- package/dist/app/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/app/_next/static/chunks/webpack-2c306566f7ee1b63.js +1 -0
- package/dist/app/_next/static/css/6c4002bae4e236b2.css +3 -0
- package/dist/app/_next/static/css/a275cc2b185e04f8.css +1 -0
- package/dist/app/_next/static/eCWhKA8XHqmB1zgFcEtN2/_buildManifest.js +1 -0
- package/dist/app/_next/static/eCWhKA8XHqmB1zgFcEtN2/_ssgManifest.js +1 -0
- package/dist/app/activity-log/all-activity/index.html +1 -0
- package/dist/app/activity-log/all-activity/index.txt +14 -0
- package/dist/app/activity-log/email-log/index.html +1 -0
- package/dist/app/activity-log/email-log/index.txt +14 -0
- package/dist/app/activity-log/index.html +1 -0
- package/dist/app/activity-log/index.txt +14 -0
- package/dist/app/activity-log/notifications/index.html +1 -0
- package/dist/app/activity-log/notifications/index.txt +14 -0
- package/dist/app/activity-log/sessions/index.html +1 -0
- package/dist/app/activity-log/sessions/index.txt +14 -0
- package/dist/app/activity-log/workflow-executions/index.html +1 -0
- package/dist/app/activity-log/workflow-executions/index.txt +14 -0
- package/dist/app/activity-log/workflow-logs/index.html +1 -0
- package/dist/app/activity-log/workflow-logs/index.txt +14 -0
- package/dist/app/change-password/index.html +1 -0
- package/dist/app/change-password/index.txt +14 -0
- package/dist/app/dashboard/index.html +1 -0
- package/dist/app/dashboard/index.txt +14 -0
- package/dist/app/data-browser/index.html +1 -0
- package/dist/app/data-browser/index.txt +14 -0
- package/dist/app/file-manager/index.html +1 -0
- package/dist/app/file-manager/index.txt +14 -0
- package/dist/app/forgot-password/index.html +1 -0
- package/dist/app/forgot-password/index.txt +13 -0
- package/dist/app/index.html +1 -0
- package/dist/app/index.txt +9 -0
- package/dist/app/login/index.html +1 -0
- package/dist/app/login/index.txt +13 -0
- package/dist/app/logo-dark.png +0 -0
- package/dist/app/logo-icon.svg +81 -0
- package/dist/app/logo-light.png +0 -0
- package/dist/app/register/index.html +1 -0
- package/dist/app/register/index.txt +13 -0
- package/dist/app/settings/migrations/index.html +1 -0
- package/dist/app/settings/migrations/index.txt +14 -0
- package/dist/app/settings/permissions/index.html +1 -0
- package/dist/app/settings/permissions/index.txt +14 -0
- package/dist/app/settings/project/index.html +1 -0
- package/dist/app/settings/project/index.txt +14 -0
- package/dist/app/settings/roles/index.html +1 -0
- package/dist/app/settings/roles/index.txt +14 -0
- package/dist/app/settings/schema/index.html +1 -0
- package/dist/app/settings/schema/index.txt +14 -0
- package/dist/app/settings/tasks/index.html +1 -0
- package/dist/app/settings/tasks/index.txt +14 -0
- package/dist/app/settings/templates/edit/index.html +1 -0
- package/dist/app/settings/templates/edit/index.txt +14 -0
- package/dist/app/settings/templates/index.html +1 -0
- package/dist/app/settings/templates/index.txt +14 -0
- package/dist/app/settings/tenants/index.html +1 -0
- package/dist/app/settings/tenants/index.txt +14 -0
- package/dist/app/users/index.html +1 -0
- package/dist/app/users/index.txt +14 -0
- package/dist/app/users/invites/index.html +1 -0
- package/dist/app/users/invites/index.txt +14 -0
- package/dist/app/users/list/index.html +1 -0
- package/dist/app/users/list/index.txt +14 -0
- package/dist/app/users/preferences/index.html +1 -0
- package/dist/app/users/preferences/index.txt +14 -0
- package/dist/app/users/user-roles/index.html +1 -0
- package/dist/app/users/user-roles/index.txt +14 -0
- package/dist/app/workflows/detail/index.html +1 -0
- package/dist/app/workflows/detail/index.txt +14 -0
- package/dist/app/workflows/edit/index.html +1 -0
- package/dist/app/workflows/edit/index.txt +14 -0
- package/dist/app/workflows/execution/index.html +1 -0
- package/dist/app/workflows/execution/index.txt +14 -0
- package/dist/app/workflows/index.html +1 -0
- package/dist/app/workflows/index.txt +14 -0
- package/dist/app.d.ts +36 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +546 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/adapters/baasix-adapter.d.ts +12 -0
- package/dist/auth/adapters/baasix-adapter.d.ts.map +1 -0
- package/dist/auth/adapters/baasix-adapter.js +318 -0
- package/dist/auth/adapters/baasix-adapter.js.map +1 -0
- package/dist/auth/adapters/index.d.ts +6 -0
- package/dist/auth/adapters/index.d.ts.map +1 -0
- package/dist/auth/adapters/index.js +5 -0
- package/dist/auth/adapters/index.js.map +1 -0
- package/dist/auth/core.d.ts +73 -0
- package/dist/auth/core.d.ts.map +1 -0
- package/dist/auth/core.js +528 -0
- package/dist/auth/core.js.map +1 -0
- package/dist/auth/index.d.ts +56 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +58 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth2/index.d.ts +5 -0
- package/dist/auth/oauth2/index.d.ts.map +1 -0
- package/dist/auth/oauth2/index.js +5 -0
- package/dist/auth/oauth2/index.js.map +1 -0
- package/dist/auth/oauth2/utils.d.ts +90 -0
- package/dist/auth/oauth2/utils.d.ts.map +1 -0
- package/dist/auth/oauth2/utils.js +167 -0
- package/dist/auth/oauth2/utils.js.map +1 -0
- package/dist/auth/providers/apple.d.ts +28 -0
- package/dist/auth/providers/apple.d.ts.map +1 -0
- package/dist/auth/providers/apple.js +192 -0
- package/dist/auth/providers/apple.js.map +1 -0
- package/dist/auth/providers/credential.d.ts +87 -0
- package/dist/auth/providers/credential.d.ts.map +1 -0
- package/dist/auth/providers/credential.js +162 -0
- package/dist/auth/providers/credential.js.map +1 -0
- package/dist/auth/providers/facebook.d.ts +26 -0
- package/dist/auth/providers/facebook.d.ts.map +1 -0
- package/dist/auth/providers/facebook.js +112 -0
- package/dist/auth/providers/facebook.js.map +1 -0
- package/dist/auth/providers/github.d.ts +29 -0
- package/dist/auth/providers/github.d.ts.map +1 -0
- package/dist/auth/providers/github.js +144 -0
- package/dist/auth/providers/github.js.map +1 -0
- package/dist/auth/providers/google.d.ts +32 -0
- package/dist/auth/providers/google.d.ts.map +1 -0
- package/dist/auth/providers/google.js +145 -0
- package/dist/auth/providers/google.js.map +1 -0
- package/dist/auth/providers/index.d.ts +22 -0
- package/dist/auth/providers/index.d.ts.map +1 -0
- package/dist/auth/providers/index.js +17 -0
- package/dist/auth/providers/index.js.map +1 -0
- package/dist/auth/routes.d.ts +63 -0
- package/dist/auth/routes.d.ts.map +1 -0
- package/dist/auth/routes.js +827 -0
- package/dist/auth/routes.js.map +1 -0
- package/dist/auth/services/index.d.ts +10 -0
- package/dist/auth/services/index.d.ts.map +1 -0
- package/dist/auth/services/index.js +7 -0
- package/dist/auth/services/index.js.map +1 -0
- package/dist/auth/services/session.d.ts +81 -0
- package/dist/auth/services/session.d.ts.map +1 -0
- package/dist/auth/services/session.js +186 -0
- package/dist/auth/services/session.js.map +1 -0
- package/dist/auth/services/token.d.ts +41 -0
- package/dist/auth/services/token.d.ts.map +1 -0
- package/dist/auth/services/token.js +44 -0
- package/dist/auth/services/token.js.map +1 -0
- package/dist/auth/services/verification.d.ts +77 -0
- package/dist/auth/services/verification.d.ts.map +1 -0
- package/dist/auth/services/verification.js +143 -0
- package/dist/auth/services/verification.js.map +1 -0
- package/dist/auth/types.d.ts +318 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +6 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/customTypes/arrays.d.ts +200 -0
- package/dist/customTypes/arrays.d.ts.map +1 -0
- package/dist/customTypes/arrays.js +309 -0
- package/dist/customTypes/arrays.js.map +1 -0
- package/dist/customTypes/index.d.ts +8 -0
- package/dist/customTypes/index.d.ts.map +1 -0
- package/dist/customTypes/index.js +11 -0
- package/dist/customTypes/index.js.map +1 -0
- package/dist/customTypes/postgis.d.ts +146 -0
- package/dist/customTypes/postgis.d.ts.map +1 -0
- package/dist/customTypes/postgis.js +315 -0
- package/dist/customTypes/postgis.js.map +1 -0
- package/dist/customTypes/ranges.d.ts +128 -0
- package/dist/customTypes/ranges.d.ts.map +1 -0
- package/dist/customTypes/ranges.js +257 -0
- package/dist/customTypes/ranges.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/0.1.0-alpha.0_initial_setup.d.ts +29 -0
- package/dist/migrations/0.1.0-alpha.0_initial_setup.d.ts.map +1 -0
- package/dist/migrations/0.1.0-alpha.0_initial_setup.js +72 -0
- package/dist/migrations/0.1.0-alpha.0_initial_setup.js.map +1 -0
- package/dist/migrations/_example_migration.d.ts +31 -0
- package/dist/migrations/_example_migration.d.ts.map +1 -0
- package/dist/migrations/_example_migration.js +75 -0
- package/dist/migrations/_example_migration.js.map +1 -0
- package/dist/plugins/definePlugin.d.ts +49 -0
- package/dist/plugins/definePlugin.d.ts.map +1 -0
- package/dist/plugins/definePlugin.js +131 -0
- package/dist/plugins/definePlugin.js.map +1 -0
- package/dist/plugins/softDelete.d.ts +179 -0
- package/dist/plugins/softDelete.d.ts.map +1 -0
- package/dist/plugins/softDelete.js +235 -0
- package/dist/plugins/softDelete.js.map +1 -0
- package/dist/routes/auth.route.d.ts +14 -0
- package/dist/routes/auth.route.d.ts.map +1 -0
- package/dist/routes/auth.route.js +421 -0
- package/dist/routes/auth.route.js.map +1 -0
- package/dist/routes/file.route.d.ts +7 -0
- package/dist/routes/file.route.d.ts.map +1 -0
- package/dist/routes/file.route.js +274 -0
- package/dist/routes/file.route.js.map +1 -0
- package/dist/routes/items.route.d.ts +7 -0
- package/dist/routes/items.route.d.ts.map +1 -0
- package/dist/routes/items.route.js +369 -0
- package/dist/routes/items.route.js.map +1 -0
- package/dist/routes/migration.route.d.ts +7 -0
- package/dist/routes/migration.route.d.ts.map +1 -0
- package/dist/routes/migration.route.js +225 -0
- package/dist/routes/migration.route.js.map +1 -0
- package/dist/routes/notification.route.d.ts +7 -0
- package/dist/routes/notification.route.d.ts.map +1 -0
- package/dist/routes/notification.route.js +124 -0
- package/dist/routes/notification.route.js.map +1 -0
- package/dist/routes/openapi.route.d.ts +7 -0
- package/dist/routes/openapi.route.d.ts.map +1 -0
- package/dist/routes/openapi.route.js +2169 -0
- package/dist/routes/openapi.route.js.map +1 -0
- package/dist/routes/permission.route.d.ts +7 -0
- package/dist/routes/permission.route.d.ts.map +1 -0
- package/dist/routes/permission.route.js +158 -0
- package/dist/routes/permission.route.js.map +1 -0
- package/dist/routes/realtime.route.d.ts +21 -0
- package/dist/routes/realtime.route.d.ts.map +1 -0
- package/dist/routes/realtime.route.js +243 -0
- package/dist/routes/realtime.route.js.map +1 -0
- package/dist/routes/reports.route.d.ts +7 -0
- package/dist/routes/reports.route.d.ts.map +1 -0
- package/dist/routes/reports.route.js +95 -0
- package/dist/routes/reports.route.js.map +1 -0
- package/dist/routes/schema.route.d.ts +7 -0
- package/dist/routes/schema.route.d.ts.map +1 -0
- package/dist/routes/schema.route.js +1780 -0
- package/dist/routes/schema.route.js.map +1 -0
- package/dist/routes/settings.route.d.ts +7 -0
- package/dist/routes/settings.route.d.ts.map +1 -0
- package/dist/routes/settings.route.js +154 -0
- package/dist/routes/settings.route.js.map +1 -0
- package/dist/routes/templates.route.d.ts +7 -0
- package/dist/routes/templates.route.d.ts.map +1 -0
- package/dist/routes/templates.route.js +91 -0
- package/dist/routes/templates.route.js.map +1 -0
- package/dist/routes/utils.route.d.ts +7 -0
- package/dist/routes/utils.route.d.ts.map +1 -0
- package/dist/routes/utils.route.js +33 -0
- package/dist/routes/utils.route.js.map +1 -0
- package/dist/routes/workflow.route.d.ts +7 -0
- package/dist/routes/workflow.route.d.ts.map +1 -0
- package/dist/routes/workflow.route.js +787 -0
- package/dist/routes/workflow.route.js.map +1 -0
- package/dist/services/AssetsService.d.ts +39 -0
- package/dist/services/AssetsService.d.ts.map +1 -0
- package/dist/services/AssetsService.js +255 -0
- package/dist/services/AssetsService.js.map +1 -0
- package/dist/services/CacheService.d.ts +169 -0
- package/dist/services/CacheService.d.ts.map +1 -0
- package/dist/services/CacheService.js +722 -0
- package/dist/services/CacheService.js.map +1 -0
- package/dist/services/FilesService.d.ts +30 -0
- package/dist/services/FilesService.d.ts.map +1 -0
- package/dist/services/FilesService.js +268 -0
- package/dist/services/FilesService.js.map +1 -0
- package/dist/services/HooksManager.d.ts +38 -0
- package/dist/services/HooksManager.d.ts.map +1 -0
- package/dist/services/HooksManager.js +165 -0
- package/dist/services/HooksManager.js.map +1 -0
- package/dist/services/ItemsService.d.ts +273 -0
- package/dist/services/ItemsService.d.ts.map +1 -0
- package/dist/services/ItemsService.js +2458 -0
- package/dist/services/ItemsService.js.map +1 -0
- package/dist/services/MailService.d.ts +76 -0
- package/dist/services/MailService.d.ts.map +1 -0
- package/dist/services/MailService.js +585 -0
- package/dist/services/MailService.js.map +1 -0
- package/dist/services/MigrationService.d.ts +243 -0
- package/dist/services/MigrationService.d.ts.map +1 -0
- package/dist/services/MigrationService.js +914 -0
- package/dist/services/MigrationService.js.map +1 -0
- package/dist/services/NotificationService.d.ts +35 -0
- package/dist/services/NotificationService.d.ts.map +1 -0
- package/dist/services/NotificationService.js +159 -0
- package/dist/services/NotificationService.js.map +1 -0
- package/dist/services/PermissionService.d.ts +128 -0
- package/dist/services/PermissionService.d.ts.map +1 -0
- package/dist/services/PermissionService.js +373 -0
- package/dist/services/PermissionService.js.map +1 -0
- package/dist/services/PluginManager.d.ts +138 -0
- package/dist/services/PluginManager.d.ts.map +1 -0
- package/dist/services/PluginManager.js +463 -0
- package/dist/services/PluginManager.js.map +1 -0
- package/dist/services/RealtimeService.d.ts +209 -0
- package/dist/services/RealtimeService.d.ts.map +1 -0
- package/dist/services/RealtimeService.js +978 -0
- package/dist/services/RealtimeService.js.map +1 -0
- package/dist/services/ReportService.d.ts +13 -0
- package/dist/services/ReportService.d.ts.map +1 -0
- package/dist/services/ReportService.js +91 -0
- package/dist/services/ReportService.js.map +1 -0
- package/dist/services/SettingsService.d.ts +60 -0
- package/dist/services/SettingsService.d.ts.map +1 -0
- package/dist/services/SettingsService.js +474 -0
- package/dist/services/SettingsService.js.map +1 -0
- package/dist/services/SocketService.d.ts +129 -0
- package/dist/services/SocketService.d.ts.map +1 -0
- package/dist/services/SocketService.js +600 -0
- package/dist/services/SocketService.js.map +1 -0
- package/dist/services/StatsService.d.ts +10 -0
- package/dist/services/StatsService.d.ts.map +1 -0
- package/dist/services/StatsService.js +40 -0
- package/dist/services/StatsService.js.map +1 -0
- package/dist/services/StorageService.d.ts +20 -0
- package/dist/services/StorageService.d.ts.map +1 -0
- package/dist/services/StorageService.js +164 -0
- package/dist/services/StorageService.js.map +1 -0
- package/dist/services/TasksService.d.ts +74 -0
- package/dist/services/TasksService.d.ts.map +1 -0
- package/dist/services/TasksService.js +404 -0
- package/dist/services/TasksService.js.map +1 -0
- package/dist/services/WorkflowService.d.ts +305 -0
- package/dist/services/WorkflowService.d.ts.map +1 -0
- package/dist/services/WorkflowService.js +1811 -0
- package/dist/services/WorkflowService.js.map +1 -0
- package/dist/templates/logo/logo.png +0 -0
- package/dist/templates/mails/default.liquid +23 -0
- package/dist/types/aggregation.d.ts +40 -0
- package/dist/types/aggregation.d.ts.map +1 -0
- package/dist/types/aggregation.js +6 -0
- package/dist/types/aggregation.js.map +1 -0
- package/dist/types/assets.d.ts +32 -0
- package/dist/types/assets.d.ts.map +1 -0
- package/dist/types/assets.js +6 -0
- package/dist/types/assets.js.map +1 -0
- package/dist/types/auth.d.ts +50 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +6 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/cache.d.ts +47 -0
- package/dist/types/cache.d.ts.map +1 -0
- package/dist/types/cache.js +6 -0
- package/dist/types/cache.js.map +1 -0
- package/dist/types/database.d.ts +16 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/database.js +6 -0
- package/dist/types/database.js.map +1 -0
- package/dist/types/fields.d.ts +71 -0
- package/dist/types/fields.d.ts.map +1 -0
- package/dist/types/fields.js +6 -0
- package/dist/types/fields.js.map +1 -0
- package/dist/types/files.d.ts +33 -0
- package/dist/types/files.d.ts.map +1 -0
- package/dist/types/files.js +6 -0
- package/dist/types/files.js.map +1 -0
- package/dist/types/hooks.d.ts +29 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +6 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/import-export.d.ts +62 -0
- package/dist/types/import-export.d.ts.map +1 -0
- package/dist/types/import-export.js +6 -0
- package/dist/types/import-export.js.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +58 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mail.d.ts +34 -0
- package/dist/types/mail.d.ts.map +1 -0
- package/dist/types/mail.js +6 -0
- package/dist/types/mail.js.map +1 -0
- package/dist/types/notifications.d.ts +16 -0
- package/dist/types/notifications.d.ts.map +1 -0
- package/dist/types/notifications.js +6 -0
- package/dist/types/notifications.js.map +1 -0
- package/dist/types/plugin.d.ts +351 -0
- package/dist/types/plugin.d.ts.map +1 -0
- package/dist/types/plugin.js +8 -0
- package/dist/types/plugin.js.map +1 -0
- package/dist/types/query.d.ts +71 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/query.js +6 -0
- package/dist/types/query.js.map +1 -0
- package/dist/types/relations.d.ts +111 -0
- package/dist/types/relations.d.ts.map +1 -0
- package/dist/types/relations.js +6 -0
- package/dist/types/relations.js.map +1 -0
- package/dist/types/reports.d.ts +17 -0
- package/dist/types/reports.d.ts.map +1 -0
- package/dist/types/reports.js +6 -0
- package/dist/types/reports.js.map +1 -0
- package/dist/types/schema.d.ts +26 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +6 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/seed.d.ts +27 -0
- package/dist/types/seed.d.ts.map +1 -0
- package/dist/types/seed.js +6 -0
- package/dist/types/seed.js.map +1 -0
- package/dist/types/services.d.ts +68 -0
- package/dist/types/services.d.ts.map +1 -0
- package/dist/types/services.js +6 -0
- package/dist/types/services.js.map +1 -0
- package/dist/types/settings.d.ts +36 -0
- package/dist/types/settings.d.ts.map +1 -0
- package/dist/types/settings.js +6 -0
- package/dist/types/settings.js.map +1 -0
- package/dist/types/sockets.d.ts +26 -0
- package/dist/types/sockets.d.ts.map +1 -0
- package/dist/types/sockets.js +6 -0
- package/dist/types/sockets.js.map +1 -0
- package/dist/types/sort.d.ts +25 -0
- package/dist/types/sort.d.ts.map +1 -0
- package/dist/types/sort.js +6 -0
- package/dist/types/sort.js.map +1 -0
- package/dist/types/spatial.d.ts +19 -0
- package/dist/types/spatial.d.ts.map +1 -0
- package/dist/types/spatial.js +6 -0
- package/dist/types/spatial.js.map +1 -0
- package/dist/types/stats.d.ts +21 -0
- package/dist/types/stats.d.ts.map +1 -0
- package/dist/types/stats.js +6 -0
- package/dist/types/stats.js.map +1 -0
- package/dist/types/storage.d.ts +19 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +6 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/types/tasks.d.ts +14 -0
- package/dist/types/tasks.d.ts.map +1 -0
- package/dist/types/tasks.js +6 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/types/utils.d.ts +54 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/utils.js +6 -0
- package/dist/types/utils.js.map +1 -0
- package/dist/types/workflow.d.ts +17 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +6 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/aggregationUtils.d.ts +192 -0
- package/dist/utils/aggregationUtils.d.ts.map +1 -0
- package/dist/utils/aggregationUtils.js +450 -0
- package/dist/utils/aggregationUtils.js.map +1 -0
- package/dist/utils/auth.d.ts +93 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/dist/utils/auth.js +557 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/cache.d.ts +64 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +464 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/common.d.ts +53 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +162 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/db.d.ts +101 -0
- package/dist/utils/db.d.ts.map +1 -0
- package/dist/utils/db.js +413 -0
- package/dist/utils/db.js.map +1 -0
- package/dist/utils/dirname.d.ts +30 -0
- package/dist/utils/dirname.d.ts.map +1 -0
- package/dist/utils/dirname.js +95 -0
- package/dist/utils/dirname.js.map +1 -0
- package/dist/utils/dynamicVariableResolver.d.ts +17 -0
- package/dist/utils/dynamicVariableResolver.d.ts.map +1 -0
- package/dist/utils/dynamicVariableResolver.js +262 -0
- package/dist/utils/dynamicVariableResolver.js.map +1 -0
- package/dist/utils/env.d.ts +38 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +80 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/errorHandler.d.ts +14 -0
- package/dist/utils/errorHandler.d.ts.map +1 -0
- package/dist/utils/errorHandler.js +79 -0
- package/dist/utils/errorHandler.js.map +1 -0
- package/dist/utils/fieldExpansion.d.ts +30 -0
- package/dist/utils/fieldExpansion.d.ts.map +1 -0
- package/dist/utils/fieldExpansion.js +145 -0
- package/dist/utils/fieldExpansion.js.map +1 -0
- package/dist/utils/fieldUtils.d.ts +179 -0
- package/dist/utils/fieldUtils.d.ts.map +1 -0
- package/dist/utils/fieldUtils.js +424 -0
- package/dist/utils/fieldUtils.js.map +1 -0
- package/dist/utils/filterOperators.d.ts +472 -0
- package/dist/utils/filterOperators.d.ts.map +1 -0
- package/dist/utils/filterOperators.js +1229 -0
- package/dist/utils/filterOperators.js.map +1 -0
- package/dist/utils/importUtils.d.ts +127 -0
- package/dist/utils/importUtils.d.ts.map +1 -0
- package/dist/utils/importUtils.js +437 -0
- package/dist/utils/importUtils.js.map +1 -0
- package/dist/utils/index.d.ts +75 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +101 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +41 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +217 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/orderUtils.d.ts +117 -0
- package/dist/utils/orderUtils.d.ts.map +1 -0
- package/dist/utils/orderUtils.js +249 -0
- package/dist/utils/orderUtils.js.map +1 -0
- package/dist/utils/queryBuilder.d.ts +118 -0
- package/dist/utils/queryBuilder.d.ts.map +1 -0
- package/dist/utils/queryBuilder.js +489 -0
- package/dist/utils/queryBuilder.js.map +1 -0
- package/dist/utils/relationLoader.d.ts +65 -0
- package/dist/utils/relationLoader.d.ts.map +1 -0
- package/dist/utils/relationLoader.js +1081 -0
- package/dist/utils/relationLoader.js.map +1 -0
- package/dist/utils/relationPathResolver.d.ts +30 -0
- package/dist/utils/relationPathResolver.d.ts.map +1 -0
- package/dist/utils/relationPathResolver.js +173 -0
- package/dist/utils/relationPathResolver.js.map +1 -0
- package/dist/utils/relationUtils.d.ts +139 -0
- package/dist/utils/relationUtils.d.ts.map +1 -0
- package/dist/utils/relationUtils.js +711 -0
- package/dist/utils/relationUtils.js.map +1 -0
- package/dist/utils/router.d.ts +6 -0
- package/dist/utils/router.d.ts.map +1 -0
- package/dist/utils/router.js +95 -0
- package/dist/utils/router.js.map +1 -0
- package/dist/utils/schema.d.ts +88 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +24 -0
- package/dist/utils/schema.js.map +1 -0
- package/dist/utils/schemaManager.d.ts +238 -0
- package/dist/utils/schemaManager.d.ts.map +1 -0
- package/dist/utils/schemaManager.js +1992 -0
- package/dist/utils/schemaManager.js.map +1 -0
- package/dist/utils/schemaValidator.d.ts +83 -0
- package/dist/utils/schemaValidator.d.ts.map +1 -0
- package/dist/utils/schemaValidator.js +491 -0
- package/dist/utils/schemaValidator.js.map +1 -0
- package/dist/utils/seed.d.ts +45 -0
- package/dist/utils/seed.d.ts.map +1 -0
- package/dist/utils/seed.js +248 -0
- package/dist/utils/seed.js.map +1 -0
- package/dist/utils/sessionCleanup.d.ts +10 -0
- package/dist/utils/sessionCleanup.d.ts.map +1 -0
- package/dist/utils/sessionCleanup.js +49 -0
- package/dist/utils/sessionCleanup.js.map +1 -0
- package/dist/utils/sortUtils.d.ts +117 -0
- package/dist/utils/sortUtils.d.ts.map +1 -0
- package/dist/utils/sortUtils.js +232 -0
- package/dist/utils/sortUtils.js.map +1 -0
- package/dist/utils/spatialUtils.d.ts +244 -0
- package/dist/utils/spatialUtils.d.ts.map +1 -0
- package/dist/utils/spatialUtils.js +359 -0
- package/dist/utils/spatialUtils.js.map +1 -0
- package/dist/utils/systemschema.d.ts +11040 -0
- package/dist/utils/systemschema.d.ts.map +1 -0
- package/dist/utils/systemschema.js +1777 -0
- package/dist/utils/systemschema.js.map +1 -0
- package/dist/utils/tenantUtils.d.ts +34 -0
- package/dist/utils/tenantUtils.d.ts.map +1 -0
- package/dist/utils/tenantUtils.js +124 -0
- package/dist/utils/tenantUtils.js.map +1 -0
- package/dist/utils/typeMapper.d.ts +25 -0
- package/dist/utils/typeMapper.d.ts.map +1 -0
- package/dist/utils/typeMapper.js +282 -0
- package/dist/utils/typeMapper.js.map +1 -0
- package/dist/utils/valueValidator.d.ts +60 -0
- package/dist/utils/valueValidator.d.ts.map +1 -0
- package/dist/utils/valueValidator.js +303 -0
- package/dist/utils/valueValidator.js.map +1 -0
- package/dist/utils/workflow.d.ts +87 -0
- package/dist/utils/workflow.d.ts.map +1 -0
- package/dist/utils/workflow.js +205 -0
- package/dist/utils/workflow.js.map +1 -0
- package/package.json +115 -0
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
import { sql } from 'drizzle-orm';
|
|
2
|
+
import { getDatabase } from './db.js';
|
|
3
|
+
/**
|
|
4
|
+
* Relation builder for dynamic schemas
|
|
5
|
+
*/
|
|
6
|
+
export class RelationBuilder {
|
|
7
|
+
relationsMap = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Store association definitions for a table
|
|
10
|
+
* Relations will be resolved at query time using Drizzle's query API
|
|
11
|
+
* Note: This merges with existing associations instead of replacing them
|
|
12
|
+
*/
|
|
13
|
+
storeAssociations(tableName, associations) {
|
|
14
|
+
console.log(`[RelationBuilder] Storing associations for ${tableName}:`, Object.keys(associations));
|
|
15
|
+
// Get existing associations for this table
|
|
16
|
+
const existing = this.relationsMap.get(tableName) || {};
|
|
17
|
+
// Merge new associations with existing ones
|
|
18
|
+
const merged = { ...existing, ...associations };
|
|
19
|
+
console.log(`[RelationBuilder] After merge, ${tableName} has:`, Object.keys(merged));
|
|
20
|
+
this.relationsMap.set(tableName, merged);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get associations for a table
|
|
24
|
+
*/
|
|
25
|
+
getAssociations(tableName) {
|
|
26
|
+
const assocs = this.relationsMap.get(tableName);
|
|
27
|
+
console.log(`[RelationBuilder] Retrieved associations for ${tableName}:`, assocs ? Object.keys(assocs) : 'none');
|
|
28
|
+
return assocs;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get all associations
|
|
32
|
+
*/
|
|
33
|
+
getAllAssociations() {
|
|
34
|
+
return this.relationsMap;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get foreign key column name for a relation
|
|
38
|
+
*/
|
|
39
|
+
getForeignKey(assoc, defaultKey) {
|
|
40
|
+
return assoc.foreignKey || defaultKey || `${assoc.model.toLowerCase()}Id`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if an association is a one-to-many type
|
|
44
|
+
*/
|
|
45
|
+
isOneToMany(assoc) {
|
|
46
|
+
return assoc.type === 'HasMany';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if an association is a many-to-one type
|
|
50
|
+
*/
|
|
51
|
+
isManyToOne(assoc) {
|
|
52
|
+
return assoc.type === 'BelongsTo';
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if an association is a many-to-many type
|
|
56
|
+
*/
|
|
57
|
+
isManyToMany(assoc) {
|
|
58
|
+
return assoc.type === 'BelongsToMany';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Singleton instance
|
|
63
|
+
*/
|
|
64
|
+
export const relationBuilder = new RelationBuilder();
|
|
65
|
+
/**
|
|
66
|
+
* Helper to create foreign key constraint SQL
|
|
67
|
+
*/
|
|
68
|
+
export function createForeignKeySQL(tableName, columnName, referencedTable, referencedColumn = 'id', onDelete = 'CASCADE', onUpdate = 'CASCADE') {
|
|
69
|
+
const constraintName = `fk_${tableName}_${columnName}`;
|
|
70
|
+
return `
|
|
71
|
+
ALTER TABLE "${tableName}"
|
|
72
|
+
ADD CONSTRAINT "${constraintName}"
|
|
73
|
+
FOREIGN KEY ("${columnName}")
|
|
74
|
+
REFERENCES "${referencedTable}"("${referencedColumn}")
|
|
75
|
+
ON DELETE ${onDelete}
|
|
76
|
+
ON UPDATE ${onUpdate}
|
|
77
|
+
`.trim();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Helper to check if a field is a polymorphic relation
|
|
81
|
+
*/
|
|
82
|
+
export function isPolymorphicRelation(assoc) {
|
|
83
|
+
return assoc.type === 'M2A' || assoc.polymorphic === true;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Helper to get polymorphic field names
|
|
87
|
+
*/
|
|
88
|
+
export function getPolymorphicFields(relationName) {
|
|
89
|
+
return {
|
|
90
|
+
typeField: `${relationName}Type`,
|
|
91
|
+
idField: `${relationName}Id`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build junction table for many-to-many relations
|
|
96
|
+
* Example: UserRoles for User <-> Role
|
|
97
|
+
*/
|
|
98
|
+
export function buildJunctionTable(table1Name, table2Name, table1Key = 'id', table2Key = 'id') {
|
|
99
|
+
const junctionName = `${table1Name}${table2Name}`;
|
|
100
|
+
const fk1 = `${table1Name}${table1Key.charAt(0).toUpperCase()}${table1Key.slice(1)}`;
|
|
101
|
+
const fk2 = `${table2Name}${table2Key.charAt(0).toUpperCase()}${table2Key.slice(1)}`;
|
|
102
|
+
return `
|
|
103
|
+
CREATE TABLE IF NOT EXISTS "${junctionName}" (
|
|
104
|
+
"${fk1}" UUID NOT NULL,
|
|
105
|
+
"${fk2}" UUID NOT NULL,
|
|
106
|
+
"createdAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
107
|
+
"updatedAt" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
108
|
+
PRIMARY KEY ("${fk1}", "${fk2}"),
|
|
109
|
+
FOREIGN KEY ("${fk1}") REFERENCES "${table1Name}"("${table1Key}") ON DELETE CASCADE,
|
|
110
|
+
FOREIGN KEY ("${fk2}") REFERENCES "${table2Name}"("${table2Key}") ON DELETE CASCADE
|
|
111
|
+
)
|
|
112
|
+
`.trim();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Convert Sequelize association type to Drizzle relation type
|
|
116
|
+
*/
|
|
117
|
+
export function sequelizeTosDrizzleRelationType(sequelizeType) {
|
|
118
|
+
switch (sequelizeType) {
|
|
119
|
+
case 'HasMany':
|
|
120
|
+
case 'BelongsToMany':
|
|
121
|
+
return 'many';
|
|
122
|
+
case 'HasOne':
|
|
123
|
+
case 'BelongsTo':
|
|
124
|
+
return 'one';
|
|
125
|
+
default:
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// Relational Data Processing
|
|
131
|
+
// ============================================================================
|
|
132
|
+
/**
|
|
133
|
+
* Process relational data - extract nested objects/arrays
|
|
134
|
+
* @param collection - Collection name
|
|
135
|
+
* @param data - Data to process
|
|
136
|
+
* @param service - Service instance
|
|
137
|
+
* @param ItemsServiceClass - ItemsService class for creating related service instances
|
|
138
|
+
*/
|
|
139
|
+
export async function processRelationalData(collection, data, service, ItemsServiceClass) {
|
|
140
|
+
console.log(`[RelationUtils] Processing relational data for ${collection}`);
|
|
141
|
+
const result = {};
|
|
142
|
+
const deferredHasMany = [];
|
|
143
|
+
const deferredM2M = [];
|
|
144
|
+
const deferredM2A = [];
|
|
145
|
+
// Get relation metadata for this collection
|
|
146
|
+
const associations = relationBuilder.getAssociations(collection);
|
|
147
|
+
console.log(`[RelationUtils] Associations for ${collection}:`, associations ? Object.keys(associations) : 'none');
|
|
148
|
+
if (!associations) {
|
|
149
|
+
// No relations defined, return data as-is
|
|
150
|
+
console.log(`[RelationUtils] No associations found for ${collection}, returning data as-is`);
|
|
151
|
+
return {
|
|
152
|
+
result: { ...data },
|
|
153
|
+
deferredHasMany,
|
|
154
|
+
deferredM2M,
|
|
155
|
+
deferredM2A
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// Process BelongsTo relationships first - they need to be created/resolved before main record
|
|
159
|
+
for (const [key, value] of Object.entries(data)) {
|
|
160
|
+
const association = associations[key];
|
|
161
|
+
if (!association || value == null) {
|
|
162
|
+
// Not a relation or value is null - include in result
|
|
163
|
+
result[key] = value;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (association.type === 'BelongsTo') {
|
|
167
|
+
console.log(`[RelationUtils] Processing BelongsTo relation: ${key}`);
|
|
168
|
+
// Use passed ItemsService class to create related service
|
|
169
|
+
const relatedService = new ItemsServiceClass(association.model, {
|
|
170
|
+
accountability: service.accountability,
|
|
171
|
+
tenant: service.tenant
|
|
172
|
+
});
|
|
173
|
+
const foreignKey = association.foreignKey || `${key}_Id`;
|
|
174
|
+
if (typeof value === 'object' && !value.id) {
|
|
175
|
+
// Create new related record
|
|
176
|
+
console.log(`[RelationUtils] Creating new ${association.model} for ${key}`);
|
|
177
|
+
const newRelatedId = await relatedService.createOne(value, { bypassPermissions: true });
|
|
178
|
+
console.log(`[RelationUtils] Created ${association.model} with ID:`, newRelatedId);
|
|
179
|
+
console.log(`[RelationUtils] Setting ${foreignKey} =`, newRelatedId);
|
|
180
|
+
result[foreignKey] = newRelatedId;
|
|
181
|
+
}
|
|
182
|
+
else if (typeof value === 'object' && value.id) {
|
|
183
|
+
// Reference existing record (optionally update it)
|
|
184
|
+
console.log(`[RelationUtils] Using existing ${association.model} ${value.id} for ${key}`);
|
|
185
|
+
// If there are other fields besides id, update the related record
|
|
186
|
+
const updateFields = { ...value };
|
|
187
|
+
delete updateFields.id;
|
|
188
|
+
if (Object.keys(updateFields).length > 0) {
|
|
189
|
+
await relatedService.updateOne(value.id, updateFields, { bypassPermissions: true });
|
|
190
|
+
}
|
|
191
|
+
result[foreignKey] = value.id;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Use existing record ID directly
|
|
195
|
+
result[foreignKey] = value;
|
|
196
|
+
}
|
|
197
|
+
// Don't include the relation name in result (we stored the foreignKey instead)
|
|
198
|
+
// delete result[key]; - already not added
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Not a BelongsTo - include in result for now, process later
|
|
202
|
+
result[key] = value;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Process HasMany, BelongsToMany, and M2A relationships - these are deferred
|
|
206
|
+
for (const [key, value] of Object.entries(data)) {
|
|
207
|
+
const association = associations[key];
|
|
208
|
+
if (!association || value == null)
|
|
209
|
+
continue;
|
|
210
|
+
// Check for M2A (polymorphic) relations first
|
|
211
|
+
// M2A is stored as HasMany with polymorphic: true
|
|
212
|
+
if (isPolymorphicRelation(association)) {
|
|
213
|
+
if (Array.isArray(value)) {
|
|
214
|
+
console.log(`[RelationUtils] Deferring M2A relation: ${key}`);
|
|
215
|
+
deferredM2A.push({ association: key, associationInfo: association, value });
|
|
216
|
+
}
|
|
217
|
+
// Remove from result
|
|
218
|
+
delete result[key];
|
|
219
|
+
}
|
|
220
|
+
else if (association.type === 'HasMany') {
|
|
221
|
+
if (Array.isArray(value)) {
|
|
222
|
+
console.log(`[RelationUtils] Deferring HasMany relation: ${key}`);
|
|
223
|
+
deferredHasMany.push({ association: key, associationInfo: association, value });
|
|
224
|
+
}
|
|
225
|
+
// Remove from result
|
|
226
|
+
delete result[key];
|
|
227
|
+
}
|
|
228
|
+
else if (association.type === 'BelongsToMany') {
|
|
229
|
+
if (Array.isArray(value)) {
|
|
230
|
+
console.log(`[RelationUtils] Deferring BelongsToMany relation: ${key}`);
|
|
231
|
+
deferredM2M.push({ association: key, associationInfo: association, value });
|
|
232
|
+
}
|
|
233
|
+
// Remove from result
|
|
234
|
+
delete result[key];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
console.log(`[RelationUtils] Processed relational data:`, {
|
|
238
|
+
resultKeys: Object.keys(result),
|
|
239
|
+
deferredHasManyCount: deferredHasMany.length,
|
|
240
|
+
deferredM2MCount: deferredM2M.length,
|
|
241
|
+
deferredM2ACount: deferredM2A.length
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
result,
|
|
245
|
+
deferredHasMany,
|
|
246
|
+
deferredM2M,
|
|
247
|
+
deferredM2A
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Handle HasMany relationship after main record is created
|
|
252
|
+
*
|
|
253
|
+
* @param item - The created/updated main record with its ID
|
|
254
|
+
* @param association - Name of the association
|
|
255
|
+
* @param associationInfo - Metadata about the association
|
|
256
|
+
* @param value - Array of related items to create/update
|
|
257
|
+
* @param service - The service instance
|
|
258
|
+
* @param ItemsServiceClass - ItemsService class for creating related service instances
|
|
259
|
+
* @param transaction - Optional transaction
|
|
260
|
+
*/
|
|
261
|
+
export async function handleHasManyRelationship(item, association, associationInfo, value, service, ItemsServiceClass, transaction) {
|
|
262
|
+
console.log(`[RelationUtils] Handling HasMany relationship: ${association}`);
|
|
263
|
+
if (!Array.isArray(value)) {
|
|
264
|
+
console.warn(`[RelationUtils] HasMany value is not an array for ${association}`);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
// Use passed ItemsService class to create related service
|
|
268
|
+
const relatedService = new ItemsServiceClass(associationInfo.model, {
|
|
269
|
+
accountability: service.accountability,
|
|
270
|
+
tenant: service.tenant
|
|
271
|
+
});
|
|
272
|
+
const foreignKey = associationInfo.foreignKey || `${service.collection.toLowerCase()}_Id`;
|
|
273
|
+
const parentId = item[service.primaryKey];
|
|
274
|
+
// Get existing related records
|
|
275
|
+
const existingRecordsResult = await relatedService.readByQuery({
|
|
276
|
+
filter: { [foreignKey]: { eq: parentId } }
|
|
277
|
+
}, true); // bypassPermissions
|
|
278
|
+
const existingRecords = existingRecordsResult.data || [];
|
|
279
|
+
// Create a set of existing IDs
|
|
280
|
+
const existingIds = new Set(existingRecords.map((record) => record.id));
|
|
281
|
+
// Create a set of IDs from the update value
|
|
282
|
+
const updateIds = new Set(value.filter(item => item.id).map(item => item.id));
|
|
283
|
+
// Find records to delete or unlink
|
|
284
|
+
const idsToDelete = [...existingIds].filter(id => !updateIds.has(id));
|
|
285
|
+
if (idsToDelete.length > 0) {
|
|
286
|
+
console.log(`[RelationUtils] Removing ${idsToDelete.length} orphaned HasMany records`);
|
|
287
|
+
// Check if foreign key is nullable by looking at schema
|
|
288
|
+
const { schemaManager } = await import('./schemaManager.js');
|
|
289
|
+
const targetSchema = await schemaManager.getSchemaDefinition(associationInfo.model);
|
|
290
|
+
const fkField = targetSchema?.fields?.[foreignKey];
|
|
291
|
+
const allowsNull = !fkField || fkField.allowNull !== false;
|
|
292
|
+
// For junction tables or non-nullable foreign keys, delete the records
|
|
293
|
+
// For nullable foreign keys, just set the FK to null (unlink)
|
|
294
|
+
// Check both the schema property and name suffix for backward compatibility
|
|
295
|
+
const isJunctionTable = targetSchema?.isJunction === true || associationInfo.model.endsWith('_junction');
|
|
296
|
+
if (isJunctionTable || !allowsNull) {
|
|
297
|
+
await Promise.all(idsToDelete.map(async (id) => {
|
|
298
|
+
await relatedService.deleteOne(id, { bypassPermissions: true, transaction });
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Set foreign key to null instead of deleting
|
|
303
|
+
await Promise.all(idsToDelete.map(async (id) => {
|
|
304
|
+
await relatedService.updateOne(id, { [foreignKey]: null }, { bypassPermissions: true, transaction });
|
|
305
|
+
}));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Create or update the related records
|
|
309
|
+
await Promise.all(value.map(async (relItem) => {
|
|
310
|
+
const data = { ...relItem };
|
|
311
|
+
// Set the foreign key to link to parent
|
|
312
|
+
data[foreignKey] = parentId;
|
|
313
|
+
if (relItem.id) {
|
|
314
|
+
// Update existing record
|
|
315
|
+
console.log(`[RelationUtils] Updating HasMany record ${relItem.id} for ${association}`);
|
|
316
|
+
await relatedService.updateOne(relItem.id, data, { bypassPermissions: true, transaction });
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
// Create new record
|
|
320
|
+
console.log(`[RelationUtils] Creating new HasMany record for ${association}`);
|
|
321
|
+
await relatedService.createOne(data, { bypassPermissions: true, transaction });
|
|
322
|
+
}
|
|
323
|
+
}));
|
|
324
|
+
console.log(`[RelationUtils] Completed HasMany relationship: ${association}`);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Handle M2M (BelongsToMany) relationship after main record is created
|
|
328
|
+
*
|
|
329
|
+
* @param item - The created/updated main record with its ID
|
|
330
|
+
* @param association - Name of the association
|
|
331
|
+
* @param associationInfo - Metadata about the association
|
|
332
|
+
* @param value - Array of related items (IDs or objects with IDs)
|
|
333
|
+
* @param service - The service instance
|
|
334
|
+
* @param ItemsServiceClass - ItemsService class for creating related service instances
|
|
335
|
+
* @param transaction - Optional transaction
|
|
336
|
+
*/
|
|
337
|
+
export async function handleM2MRelationship(item, association, associationInfo, value, service, ItemsServiceClass, transaction) {
|
|
338
|
+
console.log(`[RelationUtils] Handling M2M relationship: ${association}`);
|
|
339
|
+
if (!Array.isArray(value)) {
|
|
340
|
+
console.warn(`[RelationUtils] M2M value is not an array for ${association}`);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// Use statically imported getDatabase and sql
|
|
344
|
+
const db = getDatabase();
|
|
345
|
+
// Use transaction if provided, otherwise use db
|
|
346
|
+
const dbOrTx = transaction || db;
|
|
347
|
+
// Get junction table name from association metadata
|
|
348
|
+
const junctionTable = associationInfo.through || `${service.collection}_${associationInfo.model}_junction`;
|
|
349
|
+
console.log(`[RelationUtils] Using junction table: ${junctionTable}`);
|
|
350
|
+
// Define foreign key column names
|
|
351
|
+
const sourceKey = associationInfo.foreignKey || `${service.collection}_id`;
|
|
352
|
+
const targetKey = associationInfo.otherKey || `${associationInfo.model}_id`;
|
|
353
|
+
const parentId = item[service.primaryKey];
|
|
354
|
+
console.log(`[RelationUtils] M2M keys: sourceKey=${sourceKey}, targetKey=${targetKey}, parentId=${parentId}`);
|
|
355
|
+
// Process value array - create any new related records first
|
|
356
|
+
const processedIds = [];
|
|
357
|
+
for (const targetItem of value) {
|
|
358
|
+
if (typeof targetItem === 'object' && targetItem !== null) {
|
|
359
|
+
if (targetItem.id) {
|
|
360
|
+
// Existing record - just use the ID
|
|
361
|
+
processedIds.push(targetItem.id);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
// New record - create it first using passed ItemsService class
|
|
365
|
+
const relatedService = new ItemsServiceClass(associationInfo.model, {
|
|
366
|
+
accountability: service.accountability,
|
|
367
|
+
tenant: service.tenant
|
|
368
|
+
});
|
|
369
|
+
console.log(`[RelationUtils] Creating new ${associationInfo.model} for M2M relation`);
|
|
370
|
+
const newId = await relatedService.createOne(targetItem, { bypassPermissions: true, transaction });
|
|
371
|
+
processedIds.push(newId);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
// Direct ID
|
|
376
|
+
processedIds.push(targetItem);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// Clear existing relations for this record
|
|
380
|
+
console.log(`[RelationUtils] Clearing existing M2M relations in ${junctionTable}`);
|
|
381
|
+
await dbOrTx.execute(sql `
|
|
382
|
+
DELETE FROM "${sql.raw(junctionTable)}"
|
|
383
|
+
WHERE "${sql.raw(sourceKey)}" = ${parentId}
|
|
384
|
+
`);
|
|
385
|
+
// Create new junction records
|
|
386
|
+
if (processedIds.length > 0) {
|
|
387
|
+
console.log(`[RelationUtils] Creating ${processedIds.length} M2M junction records`);
|
|
388
|
+
for (const targetId of processedIds) {
|
|
389
|
+
await dbOrTx.execute(sql `
|
|
390
|
+
INSERT INTO "${sql.raw(junctionTable)}" ("${sql.raw(sourceKey)}", "${sql.raw(targetKey)}")
|
|
391
|
+
VALUES (${parentId}, ${targetId})
|
|
392
|
+
`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
console.log(`[RelationUtils] Completed M2M relationship: ${association}`);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Handle M2A (polymorphic) relationship after main record is created
|
|
399
|
+
*
|
|
400
|
+
* @param item - The created/updated main record with its ID
|
|
401
|
+
* @param association - Name of the association
|
|
402
|
+
* @param associationInfo - Metadata about the association
|
|
403
|
+
* @param value - Array of polymorphic relation items
|
|
404
|
+
* @param service - The service instance
|
|
405
|
+
* @param ItemsServiceClass - ItemsService class (not used in M2A but kept for consistency)
|
|
406
|
+
* @param transaction - Optional transaction
|
|
407
|
+
*/
|
|
408
|
+
export async function handleM2ARelationship(item, association, associationInfo, value, service, ItemsServiceClass, transaction) {
|
|
409
|
+
console.log(`[RelationUtils] Handling M2A relationship: ${association}`);
|
|
410
|
+
if (!Array.isArray(value)) {
|
|
411
|
+
console.warn(`[RelationUtils] M2A value is not an array for ${association}`);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
// Use statically imported getDatabase and sql
|
|
415
|
+
const db = getDatabase();
|
|
416
|
+
// Use transaction if provided, otherwise use db
|
|
417
|
+
const dbOrTx = transaction || db;
|
|
418
|
+
// M2A uses a polymorphic junction table
|
|
419
|
+
// The junction table name is stored in 'through' property
|
|
420
|
+
const junctionTable = associationInfo.through;
|
|
421
|
+
if (!junctionTable) {
|
|
422
|
+
console.error(`[RelationUtils] M2A relation ${association} missing 'through' property`);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
console.log(`[RelationUtils] Using M2A junction table: ${junctionTable}`);
|
|
426
|
+
// Define column names for polymorphic relation
|
|
427
|
+
const sourceKey = `${service.collection}_id`;
|
|
428
|
+
const targetKey = 'item_id'; // Polymorphic ID field
|
|
429
|
+
const typeKey = 'collection'; // Polymorphic type field
|
|
430
|
+
const parentId = item[service.primaryKey];
|
|
431
|
+
console.log(`[RelationUtils] M2A keys: sourceKey=${sourceKey}, targetKey=${targetKey}, typeKey=${typeKey}`);
|
|
432
|
+
// Clear existing relations for this record
|
|
433
|
+
console.log(`[RelationUtils] Clearing existing M2A relations in ${junctionTable}`);
|
|
434
|
+
await dbOrTx.execute(sql `
|
|
435
|
+
DELETE FROM "${sql.raw(junctionTable)}"
|
|
436
|
+
WHERE "${sql.raw(sourceKey)}" = ${parentId}
|
|
437
|
+
`);
|
|
438
|
+
// Create new polymorphic junction records
|
|
439
|
+
if (value.length > 0) {
|
|
440
|
+
console.log(`[RelationUtils] Creating ${value.length} M2A junction records`);
|
|
441
|
+
for (const item of value) {
|
|
442
|
+
// Extract the target type and ID
|
|
443
|
+
const targetType = item.type || item.collection;
|
|
444
|
+
const targetId = item.item_id || item.item || item.id;
|
|
445
|
+
if (!targetType || !targetId) {
|
|
446
|
+
console.warn(`[RelationUtils] Skipping invalid M2A item:`, item);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
console.log(`[RelationUtils] Creating M2A junction: ${sourceKey}=${parentId}, ${typeKey}=${targetType}, ${targetKey}=${targetId}`);
|
|
450
|
+
await dbOrTx.execute(sql `
|
|
451
|
+
INSERT INTO "${sql.raw(junctionTable)}" ("${sql.raw(sourceKey)}", "${sql.raw(typeKey)}", "${sql.raw(targetKey)}")
|
|
452
|
+
VALUES (${parentId}, ${targetType}, ${targetId})
|
|
453
|
+
`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
console.log(`[RelationUtils] Completed M2A relationship: ${association}`);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Handle related records before delete (CASCADE, SET NULL, etc.)
|
|
460
|
+
* Processes HasMany, HasOne, and BelongsToMany relationships based on onDelete settings
|
|
461
|
+
*/
|
|
462
|
+
export async function handleRelatedRecordsBeforeDelete(item, service, transaction) {
|
|
463
|
+
console.log(`[RelationUtils] Handling related records before delete for ${service.collection}`);
|
|
464
|
+
const associations = relationBuilder.getAssociations(service.collection);
|
|
465
|
+
if (!associations) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const db = getDatabase();
|
|
469
|
+
const dbOrTx = transaction || db;
|
|
470
|
+
for (const [associationName, association] of Object.entries(associations)) {
|
|
471
|
+
const onDelete = association.onDelete || 'CASCADE';
|
|
472
|
+
if (association.type === 'HasMany') {
|
|
473
|
+
await handleHasManyDelete(item, association, associationName, service, dbOrTx, onDelete);
|
|
474
|
+
}
|
|
475
|
+
else if (association.type === 'HasOne') {
|
|
476
|
+
await handleHasOneDelete(item, association, associationName, service, dbOrTx, onDelete);
|
|
477
|
+
}
|
|
478
|
+
else if (association.type === 'BelongsToMany') {
|
|
479
|
+
await handleBelongsToManyDelete(item, association, associationName, service, dbOrTx);
|
|
480
|
+
}
|
|
481
|
+
else if (isPolymorphicRelation(association)) {
|
|
482
|
+
await handleM2ADelete(item, association, associationName, service, dbOrTx);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Handle HasMany delete - CASCADE or SET NULL related records
|
|
488
|
+
*/
|
|
489
|
+
async function handleHasManyDelete(item, association, associationName, service, dbOrTx, onDelete) {
|
|
490
|
+
const { schemaManager } = await import('./schemaManager.js');
|
|
491
|
+
const targetTable = schemaManager.getTable(association.model);
|
|
492
|
+
if (!targetTable) {
|
|
493
|
+
console.warn(`[RelationUtils] Target table ${association.model} not found for HasMany delete`);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const foreignKey = association.foreignKey || `${service.collection.toLowerCase()}_Id`;
|
|
497
|
+
const parentId = item[service.primaryKey];
|
|
498
|
+
if (parentId === undefined || parentId === null) {
|
|
499
|
+
console.warn(`[RelationUtils] Cannot delete HasMany records - parentId is ${parentId}`);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
console.log(`[RelationUtils] HandleHasManyDelete: ${associationName}, onDelete=${onDelete}`);
|
|
503
|
+
if (onDelete === 'CASCADE') {
|
|
504
|
+
// Delete all related records
|
|
505
|
+
const fkColumn = targetTable[foreignKey];
|
|
506
|
+
if (fkColumn) {
|
|
507
|
+
const { eq } = await import('drizzle-orm');
|
|
508
|
+
await dbOrTx.delete(targetTable).where(eq(fkColumn, parentId));
|
|
509
|
+
console.log(`[RelationUtils] Cascaded delete for ${associationName}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else if (onDelete === 'SET NULL') {
|
|
513
|
+
// Set foreign key to null on related records
|
|
514
|
+
const fkColumn = targetTable[foreignKey];
|
|
515
|
+
if (fkColumn) {
|
|
516
|
+
const { eq } = await import('drizzle-orm');
|
|
517
|
+
await dbOrTx.update(targetTable).set({ [foreignKey]: null }).where(eq(fkColumn, parentId));
|
|
518
|
+
console.log(`[RelationUtils] Set null for ${associationName}`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
// RESTRICT and NO ACTION are handled by database constraints
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Handle HasOne delete - CASCADE or SET NULL the related record
|
|
525
|
+
*/
|
|
526
|
+
async function handleHasOneDelete(item, association, associationName, service, dbOrTx, onDelete) {
|
|
527
|
+
// HasOne delete works the same as HasMany, just for a single record
|
|
528
|
+
await handleHasManyDelete(item, association, associationName, service, dbOrTx, onDelete);
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Handle BelongsToMany delete - Remove junction table records
|
|
532
|
+
*/
|
|
533
|
+
async function handleBelongsToManyDelete(item, association, associationName, service, dbOrTx) {
|
|
534
|
+
const junctionTable = association.through;
|
|
535
|
+
if (!junctionTable) {
|
|
536
|
+
console.warn(`[RelationUtils] No junction table defined for ${associationName}`);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const sourceKey = association.foreignKey || `${service.collection}_id`;
|
|
540
|
+
const parentId = item[service.primaryKey];
|
|
541
|
+
if (parentId === undefined || parentId === null) {
|
|
542
|
+
console.warn(`[RelationUtils] Cannot delete M2M junction records - parentId is ${parentId}`);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
console.log(`[RelationUtils] Removing M2M junction records from ${junctionTable} for ${associationName}`);
|
|
546
|
+
await dbOrTx.execute(sql `
|
|
547
|
+
DELETE FROM "${sql.raw(junctionTable)}"
|
|
548
|
+
WHERE "${sql.raw(sourceKey)}" = ${parentId}
|
|
549
|
+
`);
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Handle M2A (polymorphic) delete - Remove polymorphic junction table records
|
|
553
|
+
*/
|
|
554
|
+
async function handleM2ADelete(item, association, associationName, service, dbOrTx) {
|
|
555
|
+
const junctionTable = association.through;
|
|
556
|
+
if (!junctionTable) {
|
|
557
|
+
console.warn(`[RelationUtils] No junction table defined for M2A ${associationName}`);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
const sourceKey = `${service.collection}_id`;
|
|
561
|
+
const parentId = item[service.primaryKey];
|
|
562
|
+
if (parentId === undefined || parentId === null) {
|
|
563
|
+
console.warn(`[RelationUtils] Cannot delete M2A junction records - parentId is ${parentId}`);
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
console.log(`[RelationUtils] Removing M2A junction records from ${junctionTable} for ${associationName}`);
|
|
567
|
+
await dbOrTx.execute(sql `
|
|
568
|
+
DELETE FROM "${sql.raw(junctionTable)}"
|
|
569
|
+
WHERE "${sql.raw(sourceKey)}" = ${parentId}
|
|
570
|
+
`);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Validate relational data - ensures referenced records exist
|
|
574
|
+
*/
|
|
575
|
+
export async function validateRelationalData(data, collection, service) {
|
|
576
|
+
console.log(`[RelationUtils] Validating relational data for ${collection}`);
|
|
577
|
+
const associations = relationBuilder.getAssociations(collection);
|
|
578
|
+
if (!associations) {
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
const errors = [];
|
|
582
|
+
for (const [key, value] of Object.entries(data)) {
|
|
583
|
+
const association = associations[key];
|
|
584
|
+
if (!association || value == null)
|
|
585
|
+
continue;
|
|
586
|
+
try {
|
|
587
|
+
await validateRelation(association, key, value, service);
|
|
588
|
+
}
|
|
589
|
+
catch (error) {
|
|
590
|
+
errors.push({ field: key, message: error.message });
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (errors.length > 0) {
|
|
594
|
+
const { APIError } = await import('./errorHandler.js');
|
|
595
|
+
throw new APIError('Validation failed for relational data', 400, errors);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Validate a single relation - check if referenced records exist
|
|
600
|
+
*/
|
|
601
|
+
async function validateRelation(association, fieldName, value, service) {
|
|
602
|
+
// Dynamically import ItemsService to avoid circular dependency
|
|
603
|
+
const { default: ItemsService } = await import('../services/ItemsService.js');
|
|
604
|
+
const relatedService = new ItemsService(association.model, {
|
|
605
|
+
accountability: service.accountability,
|
|
606
|
+
tenant: service.tenant
|
|
607
|
+
});
|
|
608
|
+
switch (association.type) {
|
|
609
|
+
case 'BelongsTo':
|
|
610
|
+
if (typeof value === 'object' && !value.id) {
|
|
611
|
+
// New record to be created - validate will happen during create
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
const id = typeof value === 'object' ? value.id : value;
|
|
616
|
+
try {
|
|
617
|
+
await relatedService.readOne(id, {}, true); // bypassPermissions
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
throw new Error(`Related record not found: ${id}`);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
break;
|
|
624
|
+
case 'HasMany':
|
|
625
|
+
case 'BelongsToMany':
|
|
626
|
+
if (!Array.isArray(value)) {
|
|
627
|
+
throw new Error(`Value must be an array for ${fieldName}`);
|
|
628
|
+
}
|
|
629
|
+
for (const item of value) {
|
|
630
|
+
if (typeof item === 'object' && !item.id) {
|
|
631
|
+
// New record to be created - validation will happen during create
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
const id = typeof item === 'object' ? item.id : item;
|
|
635
|
+
try {
|
|
636
|
+
await relatedService.readOne(id, {}, true); // bypassPermissions
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
throw new Error(`Related record not found: ${id}`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Resolve circular dependencies in data
|
|
647
|
+
* Detects BelongsTo relations that reference the parent record being created
|
|
648
|
+
*/
|
|
649
|
+
export async function resolveCircularDependencies(data, collection, service) {
|
|
650
|
+
console.log(`[RelationUtils] Resolving circular dependencies for ${collection}`);
|
|
651
|
+
const associations = relationBuilder.getAssociations(collection);
|
|
652
|
+
if (!associations) {
|
|
653
|
+
return { resolvedData: data, deferredFields: [] };
|
|
654
|
+
}
|
|
655
|
+
const resolvedData = { ...data };
|
|
656
|
+
const deferredFields = [];
|
|
657
|
+
for (const [key, value] of Object.entries(data)) {
|
|
658
|
+
const association = associations[key];
|
|
659
|
+
if (!association || value == null)
|
|
660
|
+
continue;
|
|
661
|
+
if (hasCircularDependency(association, value, service.primaryKey)) {
|
|
662
|
+
console.log(`[RelationUtils] Found circular dependency in ${key}`);
|
|
663
|
+
deferredFields.push({ field: key, value });
|
|
664
|
+
delete resolvedData[key];
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
console.log(`[RelationUtils] Resolved ${deferredFields.length} circular dependencies`);
|
|
668
|
+
return { resolvedData, deferredFields };
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Check if a value has circular dependency
|
|
672
|
+
* A circular dependency occurs when a BelongsTo relation references the parent's primary key
|
|
673
|
+
*/
|
|
674
|
+
function hasCircularDependency(association, value, primaryKey) {
|
|
675
|
+
if (association.type !== 'BelongsTo')
|
|
676
|
+
return false;
|
|
677
|
+
// Check if the value is an object that references the parent's primary key
|
|
678
|
+
// This happens when creating a record that has a BelongsTo pointing back to itself
|
|
679
|
+
return typeof value === 'object' && !value.id && value[primaryKey];
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Process deferred fields after main record creation
|
|
683
|
+
* Updates related records to link back to the newly created parent
|
|
684
|
+
*/
|
|
685
|
+
export async function processDeferredFields(item, deferredFields, service, transaction) {
|
|
686
|
+
if (deferredFields.length === 0)
|
|
687
|
+
return;
|
|
688
|
+
console.log(`[RelationUtils] Processing ${deferredFields.length} deferred fields`);
|
|
689
|
+
const associations = relationBuilder.getAssociations(service.collection);
|
|
690
|
+
if (!associations)
|
|
691
|
+
return;
|
|
692
|
+
// Dynamically import ItemsService to avoid circular dependency
|
|
693
|
+
const { default: ItemsService } = await import('../services/ItemsService.js');
|
|
694
|
+
for (const { field, value } of deferredFields) {
|
|
695
|
+
const association = associations[field];
|
|
696
|
+
if (!association)
|
|
697
|
+
continue;
|
|
698
|
+
// Create a service for the related model
|
|
699
|
+
const relatedService = new ItemsService(association.model, {
|
|
700
|
+
accountability: service.accountability,
|
|
701
|
+
tenant: service.tenant
|
|
702
|
+
});
|
|
703
|
+
// Update the related record to link to the new parent
|
|
704
|
+
const foreignKey = association.foreignKey || `${field}_Id`;
|
|
705
|
+
if (value[service.primaryKey]) {
|
|
706
|
+
console.log(`[RelationUtils] Updating deferred ${field}: setting ${foreignKey} = ${item[service.primaryKey]}`);
|
|
707
|
+
await relatedService.updateOne(value[service.primaryKey], { [foreignKey]: item[service.primaryKey] }, { transaction, bypassPermissions: true });
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
//# sourceMappingURL=relationUtils.js.map
|