d1s 0.2.1
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/README.md +7 -0
- package/dist/.next/.next/BUILD_ID +1 -0
- package/dist/.next/.next/app-build-manifest.json +109 -0
- package/dist/.next/.next/app-path-routes-manifest.json +1 -0
- package/dist/.next/.next/build-manifest.json +33 -0
- package/dist/.next/.next/cache/.rscinfo +1 -0
- package/dist/.next/.next/cache/.tsbuildinfo +1 -0
- package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/dist/.next/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/dist/.next/.next/diagnostics/build-diagnostics.json +6 -0
- package/dist/.next/.next/diagnostics/framework.json +1 -0
- package/dist/.next/.next/export-marker.json +1 -0
- package/dist/.next/.next/images-manifest.json +1 -0
- package/dist/.next/.next/next-minimal-server.js.nft.json +1 -0
- package/dist/.next/.next/next-server.js.nft.json +1 -0
- package/dist/.next/.next/package.json +1 -0
- package/dist/.next/.next/prerender-manifest.json +1 -0
- package/dist/.next/.next/react-loadable-manifest.json +1 -0
- package/dist/.next/.next/required-server-files.json +1 -0
- package/dist/.next/.next/routes-manifest.json +1 -0
- package/dist/.next/.next/server/app/_not-found/page.js +1 -0
- package/dist/.next/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/_not-found.html +1 -0
- package/dist/.next/.next/server/app/_not-found.meta +8 -0
- package/dist/.next/.next/server/app/_not-found.rsc +16 -0
- package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -0
- package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/databases/route.js +1 -0
- package/dist/.next/.next/server/app/api/databases/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync/route.js +12 -0
- package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +14 -0
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js +14 -0
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/query/route.js +8 -0
- package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -0
- package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/tables/route.js +7 -0
- package/dist/.next/.next/server/app/api/tables/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/index.html +3 -0
- package/dist/.next/.next/server/app/index.meta +7 -0
- package/dist/.next/.next/server/app/index.rsc +20 -0
- package/dist/.next/.next/server/app/page.js +58 -0
- package/dist/.next/.next/server/app/page.js.nft.json +1 -0
- package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app-paths-manifest.json +15 -0
- package/dist/.next/.next/server/chunks/336.js +1 -0
- package/dist/.next/.next/server/chunks/627.js +6 -0
- package/dist/.next/.next/server/chunks/638.js +13 -0
- package/dist/.next/.next/server/chunks/801.js +55 -0
- package/dist/.next/.next/server/chunks/973.js +2 -0
- package/dist/.next/.next/server/chunks/992.js +3 -0
- package/dist/.next/.next/server/functions-config-manifest.json +1 -0
- package/dist/.next/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/dist/.next/.next/server/middleware-build-manifest.js +1 -0
- package/dist/.next/.next/server/middleware-manifest.json +6 -0
- package/dist/.next/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/dist/.next/.next/server/next-font-manifest.js +1 -0
- package/dist/.next/.next/server/next-font-manifest.json +1 -0
- package/dist/.next/.next/server/pages/404.html +1 -0
- package/dist/.next/.next/server/pages/500.html +1 -0
- package/dist/.next/.next/server/pages/_app.js +1 -0
- package/dist/.next/.next/server/pages/_app.js.nft.json +1 -0
- package/dist/.next/.next/server/pages/_document.js +1 -0
- package/dist/.next/.next/server/pages/_document.js.nft.json +1 -0
- package/dist/.next/.next/server/pages/_error.js +1 -0
- package/dist/.next/.next/server/pages/_error.js.nft.json +1 -0
- package/dist/.next/.next/server/pages-manifest.json +1 -0
- package/dist/.next/.next/server/server-reference-manifest.js +1 -0
- package/dist/.next/.next/server/server-reference-manifest.json +1 -0
- package/dist/.next/.next/server/webpack-runtime.js +1 -0
- package/dist/.next/.next/static/ODMSSwVqLoDcBgbFHUjr8/_buildManifest.js +1 -0
- package/dist/.next/.next/static/ODMSSwVqLoDcBgbFHUjr8/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/chunks/422-6fa3c14fc64ad67b.js +1 -0
- package/dist/.next/.next/static/chunks/4bd1b696-8c908eb707f85a27.js +1 -0
- package/dist/.next/.next/static/chunks/517-3b698a5d3da06ff7.js +2 -0
- package/dist/.next/.next/static/chunks/692-ede418e1d28a1394.js +1 -0
- package/dist/.next/.next/static/chunks/735-c9144179c6bd7d06.js +1 -0
- package/dist/.next/.next/static/chunks/92-c4466e0f1ca8a3a8.js +1 -0
- package/dist/.next/.next/static/chunks/app/_not-found/page-b786c3dd79ad15a5.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +1 -0
- package/dist/.next/.next/static/chunks/app/layout-8360fab69b848283.js +1 -0
- package/dist/.next/.next/static/chunks/app/page-75081ac7a88cb706.js +1 -0
- package/dist/.next/.next/static/chunks/framework-d29117d969504448.js +1 -0
- package/dist/.next/.next/static/chunks/main-8d0ab17774ffa031.js +1 -0
- package/dist/.next/.next/static/chunks/main-app-d36cdfb402b40f13.js +1 -0
- package/dist/.next/.next/static/chunks/pages/_app-d23763e3e6c904ff.js +1 -0
- package/dist/.next/.next/static/chunks/pages/_error-9b7125ad1a1e68fa.js +1 -0
- package/dist/.next/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/.next/.next/static/chunks/webpack-c76ac1e586b2802a.js +1 -0
- package/dist/.next/.next/static/css/c51a7ef325e30c16.css +3 -0
- package/dist/.next/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/.next/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/.next/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/.next/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- package/dist/.next/.next/trace +3 -0
- package/dist/.next/.next/types/app/api/cloudflare/route.ts +347 -0
- package/dist/.next/.next/types/app/api/databases/route.ts +347 -0
- package/dist/.next/.next/types/app/api/migrations/sync/route.ts +347 -0
- package/dist/.next/.next/types/app/api/migrations/sync-files/route.ts +347 -0
- package/dist/.next/.next/types/app/api/pull-remote/confirm/route.ts +347 -0
- package/dist/.next/.next/types/app/api/pull-remote/preview/route.ts +347 -0
- package/dist/.next/.next/types/app/api/push-remote/confirm/route.ts +347 -0
- package/dist/.next/.next/types/app/api/push-remote/preview/route.ts +347 -0
- package/dist/.next/.next/types/app/api/query/route.ts +347 -0
- package/dist/.next/.next/types/app/api/tables/[name]/route.ts +347 -0
- package/dist/.next/.next/types/app/api/tables/route.ts +347 -0
- package/dist/.next/.next/types/app/page.ts +84 -0
- package/dist/.next/.next/types/cache-life.d.ts +141 -0
- package/dist/.next/.next/types/package.json +1 -0
- package/dist/.next/BUILD_ID +1 -0
- package/dist/.next/app-build-manifest.json +109 -0
- package/dist/.next/app-path-routes-manifest.json +1 -0
- package/dist/.next/build-manifest.json +33 -0
- package/dist/.next/cache/.rscinfo +1 -0
- package/dist/.next/cache/.tsbuildinfo +1 -0
- package/dist/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/diagnostics/build-diagnostics.json +6 -0
- package/dist/.next/diagnostics/framework.json +1 -0
- package/dist/.next/export-marker.json +1 -0
- package/dist/.next/images-manifest.json +1 -0
- package/dist/.next/next-minimal-server.js.nft.json +1 -0
- package/dist/.next/next-server.js.nft.json +1 -0
- package/dist/.next/package.json +1 -0
- package/dist/.next/prerender-manifest.json +1 -0
- package/dist/.next/react-loadable-manifest.json +1 -0
- package/dist/.next/required-server-files.json +1 -0
- package/dist/.next/routes-manifest.json +1 -0
- package/dist/.next/server/app/_not-found/page.js +1 -0
- package/dist/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/_not-found.html +1 -0
- package/dist/.next/server/app/_not-found.meta +8 -0
- package/dist/.next/server/app/_not-found.rsc +16 -0
- package/dist/.next/server/app/api/cloudflare/route.js +1 -0
- package/dist/.next/server/app/api/cloudflare/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/databases/route.js +1 -0
- package/dist/.next/server/app/api/databases/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/migrations/sync/route.js +12 -0
- package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/migrations/sync-files/route.js +1 -0
- package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/pull-remote/confirm/route.js +1 -0
- package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/pull-remote/preview/route.js +1 -0
- package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/push-remote/confirm/route.js +14 -0
- package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/push-remote/preview/route.js +14 -0
- package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/query/route.js +8 -0
- package/dist/.next/server/app/api/query/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/tables/[name]/route.js +5 -0
- package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/tables/route.js +7 -0
- package/dist/.next/server/app/api/tables/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/index.html +3 -0
- package/dist/.next/server/app/index.meta +7 -0
- package/dist/.next/server/app/index.rsc +20 -0
- package/dist/.next/server/app/page.js +58 -0
- package/dist/.next/server/app/page.js.nft.json +1 -0
- package/dist/.next/server/app/page_client-reference-manifest.js +1 -0
- package/dist/.next/server/app-paths-manifest.json +15 -0
- package/dist/.next/server/chunks/336.js +1 -0
- package/dist/.next/server/chunks/627.js +6 -0
- package/dist/.next/server/chunks/638.js +13 -0
- package/dist/.next/server/chunks/801.js +55 -0
- package/dist/.next/server/chunks/973.js +2 -0
- package/dist/.next/server/chunks/992.js +3 -0
- package/dist/.next/server/functions-config-manifest.json +1 -0
- package/dist/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/dist/.next/server/middleware-build-manifest.js +1 -0
- package/dist/.next/server/middleware-manifest.json +6 -0
- package/dist/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/dist/.next/server/next-font-manifest.js +1 -0
- package/dist/.next/server/next-font-manifest.json +1 -0
- package/dist/.next/server/pages/404.html +1 -0
- package/dist/.next/server/pages/500.html +1 -0
- package/dist/.next/server/pages/_app.js +1 -0
- package/dist/.next/server/pages/_app.js.nft.json +1 -0
- package/dist/.next/server/pages/_document.js +1 -0
- package/dist/.next/server/pages/_document.js.nft.json +1 -0
- package/dist/.next/server/pages/_error.js +1 -0
- package/dist/.next/server/pages/_error.js.nft.json +1 -0
- package/dist/.next/server/pages-manifest.json +1 -0
- package/dist/.next/server/server-reference-manifest.js +1 -0
- package/dist/.next/server/server-reference-manifest.json +1 -0
- package/dist/.next/server/webpack-runtime.js +1 -0
- package/dist/.next/static/OmPVuV0d1lrcjSBQzxkdH/_buildManifest.js +1 -0
- package/dist/.next/static/OmPVuV0d1lrcjSBQzxkdH/_ssgManifest.js +1 -0
- package/dist/.next/static/chunks/422-6fa3c14fc64ad67b.js +1 -0
- package/dist/.next/static/chunks/4bd1b696-8c908eb707f85a27.js +1 -0
- package/dist/.next/static/chunks/517-3b698a5d3da06ff7.js +2 -0
- package/dist/.next/static/chunks/692-ede418e1d28a1394.js +1 -0
- package/dist/.next/static/chunks/735-c9144179c6bd7d06.js +1 -0
- package/dist/.next/static/chunks/92-c4466e0f1ca8a3a8.js +1 -0
- package/dist/.next/static/chunks/app/_not-found/page-b786c3dd79ad15a5.js +1 -0
- package/dist/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +1 -0
- package/dist/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +1 -0
- package/dist/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +1 -0
- package/dist/.next/static/chunks/app/layout-8360fab69b848283.js +1 -0
- package/dist/.next/static/chunks/app/page-75081ac7a88cb706.js +1 -0
- package/dist/.next/static/chunks/framework-d29117d969504448.js +1 -0
- package/dist/.next/static/chunks/main-8d0ab17774ffa031.js +1 -0
- package/dist/.next/static/chunks/main-app-d36cdfb402b40f13.js +1 -0
- package/dist/.next/static/chunks/pages/_app-d23763e3e6c904ff.js +1 -0
- package/dist/.next/static/chunks/pages/_error-9b7125ad1a1e68fa.js +1 -0
- package/dist/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/.next/static/chunks/webpack-c76ac1e586b2802a.js +1 -0
- package/dist/.next/static/css/c51a7ef325e30c16.css +3 -0
- package/dist/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/dist/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/dist/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- package/dist/.next/trace +13 -0
- package/dist/.next/types/app/api/cloudflare/route.ts +347 -0
- package/dist/.next/types/app/api/databases/route.ts +347 -0
- package/dist/.next/types/app/api/migrations/sync/route.ts +347 -0
- package/dist/.next/types/app/api/migrations/sync-files/route.ts +347 -0
- package/dist/.next/types/app/api/pull-remote/confirm/route.ts +347 -0
- package/dist/.next/types/app/api/pull-remote/preview/route.ts +347 -0
- package/dist/.next/types/app/api/push-remote/confirm/route.ts +347 -0
- package/dist/.next/types/app/api/push-remote/preview/route.ts +347 -0
- package/dist/.next/types/app/api/query/route.ts +347 -0
- package/dist/.next/types/app/api/tables/[name]/route.ts +347 -0
- package/dist/.next/types/app/api/tables/route.ts +347 -0
- package/dist/.next/types/app/page.ts +84 -0
- package/dist/.next/types/cache-life.d.ts +141 -0
- package/dist/.next/types/package.json +1 -0
- package/dist/app/api/cloudflare/route.js +146 -0
- package/dist/app/api/databases/route.js +72 -0
- package/dist/app/api/migrations/sync/route.js +172 -0
- package/dist/app/api/migrations/sync-files/route.js +172 -0
- package/dist/app/api/pull-remote/confirm/route.js +277 -0
- package/dist/app/api/pull-remote/preview/route.js +143 -0
- package/dist/app/api/push-remote/confirm/route.js +196 -0
- package/dist/app/api/push-remote/preview/route.js +178 -0
- package/dist/app/api/query/route.js +160 -0
- package/dist/app/api/tables/[name]/route.js +173 -0
- package/dist/app/api/tables/route.js +174 -0
- package/dist/app/app/api/cloudflare/route.js +146 -0
- package/dist/app/app/api/databases/route.js +72 -0
- package/dist/app/app/api/migrations/sync/route.js +172 -0
- package/dist/app/app/api/migrations/sync-files/route.js +172 -0
- package/dist/app/app/api/pull-remote/confirm/route.js +277 -0
- package/dist/app/app/api/pull-remote/preview/route.js +143 -0
- package/dist/app/app/api/push-remote/confirm/route.js +196 -0
- package/dist/app/app/api/push-remote/preview/route.js +178 -0
- package/dist/app/app/api/query/route.js +160 -0
- package/dist/app/app/api/tables/[name]/route.js +173 -0
- package/dist/app/app/api/tables/route.js +174 -0
- package/dist/app/app/globals.css +93 -0
- package/dist/app/app/layout.jsx +35 -0
- package/dist/app/app/page.jsx +37 -0
- package/dist/app/globals.css +93 -0
- package/dist/app/layout.jsx +35 -0
- package/dist/app/page.jsx +37 -0
- package/dist/d1-studio.js +344 -0
- package/dist/lib/database-queue.js +33 -0
- package/dist/lib/error.js +20 -0
- package/dist/lib/find-wrangler-config.js +67 -0
- package/dist/lib/license.js +99 -0
- package/dist/lib/migrations.js +415 -0
- package/dist/lib/parse-sql-error.js +200 -0
- package/dist/lib/request-deduplication.js +24 -0
- package/dist/lib/schema-operations.js +103 -0
- package/dist/lib/sql-error-types.js +14 -0
- package/dist/lib/sql-operations.js +557 -0
- package/dist/lib/utils.js +6 -0
- package/next.config.mjs +18 -0
- package/package.json +97 -0
- package/postcss.config.mjs +8 -0
- package/scripts/studio.js +344 -0
- package/scripts/test.js +168 -0
- package/src/app/api/cloudflare/route.js +146 -0
- package/src/app/api/databases/route.js +72 -0
- package/src/app/api/migrations/sync/route.js +172 -0
- package/src/app/api/migrations/sync-files/route.js +172 -0
- package/src/app/api/pull-remote/confirm/route.js +277 -0
- package/src/app/api/pull-remote/preview/route.js +143 -0
- package/src/app/api/push-remote/confirm/route.js +196 -0
- package/src/app/api/push-remote/preview/route.js +178 -0
- package/src/app/api/query/route.js +160 -0
- package/src/app/api/tables/[name]/route.js +173 -0
- package/src/app/api/tables/route.js +174 -0
- package/src/app/globals.css +93 -0
- package/src/app/layout.jsx +35 -0
- package/src/app/page.jsx +37 -0
- package/src/components/cloudflare-credentials-modal.jsx +94 -0
- package/src/components/column-selector.jsx +133 -0
- package/src/components/column-sorting.jsx +65 -0
- package/src/components/delete-records-dialog.jsx +64 -0
- package/src/components/download-button.jsx +205 -0
- package/src/components/edit-error-alert.jsx +30 -0
- package/src/components/editable-cell.jsx +163 -0
- package/src/components/editable-row.jsx +169 -0
- package/src/components/environment-handler.jsx +278 -0
- package/src/components/environment-select.jsx +59 -0
- package/src/components/pull-preview-toast.jsx +188 -0
- package/src/components/push-error-alert.jsx +72 -0
- package/src/components/push-preview-toast.jsx +183 -0
- package/src/components/query-results.jsx +112 -0
- package/src/components/refresh-button.jsx +61 -0
- package/src/components/resize-columns.jsx +101 -0
- package/src/components/sidebar.jsx +236 -0
- package/src/components/sql-editor.jsx +411 -0
- package/src/components/sql-error-display.jsx +167 -0
- package/src/components/sync-migrations-button.jsx +87 -0
- package/src/components/table-error-dialog.jsx +65 -0
- package/src/components/table-toolbar.jsx +285 -0
- package/src/components/table-view.jsx +843 -0
- package/src/components/ui/alert.jsx +47 -0
- package/src/components/ui/button.jsx +48 -0
- package/src/components/ui/card.jsx +50 -0
- package/src/components/ui/checkbox.jsx +24 -0
- package/src/components/ui/collapsible.jsx +11 -0
- package/src/components/ui/dialog.jsx +96 -0
- package/src/components/ui/dropdown-menu.jsx +158 -0
- package/src/components/ui/input.jsx +19 -0
- package/src/components/ui/scroll-area.jsx +40 -0
- package/src/components/ui/select.jsx +121 -0
- package/src/components/ui/separator.jsx +25 -0
- package/src/components/ui/sheet.jsx +109 -0
- package/src/components/ui/sidebar.jsx +620 -0
- package/src/components/ui/skeleton.jsx +14 -0
- package/src/components/ui/table.jsx +86 -0
- package/src/components/ui/tabs.jsx +43 -0
- package/src/components/ui/toast.jsx +86 -0
- package/src/components/ui/toaster.jsx +35 -0
- package/src/components/ui/tooltip.jsx +28 -0
- package/src/context/database-context.js +510 -0
- package/src/hooks/use-mobile.jsx +19 -0
- package/src/hooks/use-sql-error.ts +23 -0
- package/src/hooks/use-toast.js +155 -0
- package/src/lib/database-queue.js +33 -0
- package/src/lib/error.js +20 -0
- package/src/lib/find-wrangler-config.js +67 -0
- package/src/lib/license.js +99 -0
- package/src/lib/migrations.js +415 -0
- package/src/lib/parse-sql-error.js +200 -0
- package/src/lib/request-deduplication.js +24 -0
- package/src/lib/schema-operations.js +103 -0
- package/src/lib/sql-error-types.js +14 -0
- package/src/lib/sql-operations.js +557 -0
- package/src/lib/utils.js +6 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// components/sql-error-display.jsx
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { AlertCircle, X, ChevronDown, ChevronUp } from 'lucide-react';
|
|
4
|
+
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
|
7
|
+
|
|
8
|
+
// Keep the original ErrorMessages mapping
|
|
9
|
+
const ErrorMessages = {
|
|
10
|
+
TABLE_EXISTS: {
|
|
11
|
+
title: 'Table Already Exists',
|
|
12
|
+
message: 'A table with this name already exists',
|
|
13
|
+
action: 'Use a different table name or DROP the existing table first'
|
|
14
|
+
},
|
|
15
|
+
TABLE_NOT_FOUND: {
|
|
16
|
+
title: 'Table Not Found',
|
|
17
|
+
message: 'The specified table does not exist',
|
|
18
|
+
action: 'Check the table name and ensure it exists'
|
|
19
|
+
},
|
|
20
|
+
SYNTAX_ERROR: {
|
|
21
|
+
title: 'Syntax Error',
|
|
22
|
+
message: 'There is a syntax error in your SQL query',
|
|
23
|
+
action: 'Check your query syntax and try again'
|
|
24
|
+
},
|
|
25
|
+
CONSTRAINT_ERROR: {
|
|
26
|
+
title: 'Constraint Violation',
|
|
27
|
+
message: 'The operation violates a database constraint',
|
|
28
|
+
action: 'Ensure your data meets all table constraints'
|
|
29
|
+
},
|
|
30
|
+
VALIDATION_ERROR: {
|
|
31
|
+
title: 'Invalid Query',
|
|
32
|
+
message: 'The query is not valid',
|
|
33
|
+
action: 'Check your query and try again'
|
|
34
|
+
},
|
|
35
|
+
SQL_ERROR: {
|
|
36
|
+
title: 'SQL Error',
|
|
37
|
+
message: 'An error occurred while executing the query',
|
|
38
|
+
action: 'Review your query and try again'
|
|
39
|
+
},
|
|
40
|
+
EXECUTION_ERROR: {
|
|
41
|
+
title: 'Execution Error',
|
|
42
|
+
message: 'An error occurred during query execution',
|
|
43
|
+
action: 'Ensure Node.js is installed and your environment is configured correctly'
|
|
44
|
+
},
|
|
45
|
+
UNKNOWN_ERROR: {
|
|
46
|
+
title: 'Unknown Error',
|
|
47
|
+
message: 'An unexpected error occurred',
|
|
48
|
+
action: 'Try again or contact support if the issue persists'
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export function SQLErrorDisplay({ error, onDismiss, onFixError }) {
|
|
53
|
+
const [showDetails, setShowDetails] = React.useState(true);
|
|
54
|
+
|
|
55
|
+
if (!error) return null;
|
|
56
|
+
|
|
57
|
+
const isSyntaxError = error.type === 'SYNTAX_ERROR';
|
|
58
|
+
const showQueryPreview = error.details?.originalQuery;
|
|
59
|
+
const showErrorLocation = isSyntaxError && error.details?.errorLocation;
|
|
60
|
+
|
|
61
|
+
// Get error info from ErrorMessages mapping
|
|
62
|
+
const errorInfo = ErrorMessages[error.type] || ErrorMessages.UNKNOWN_ERROR;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Alert variant="destructive" className="mt-4 mb-4">
|
|
66
|
+
<AlertCircle className="h-4 w-4" />
|
|
67
|
+
<AlertTitle className="flex items-center justify-between">
|
|
68
|
+
<span>{errorInfo.title}</span>
|
|
69
|
+
{onDismiss && (
|
|
70
|
+
<button
|
|
71
|
+
onClick={onDismiss}
|
|
72
|
+
className="p-1 hover:bg-destructive/10 rounded-full"
|
|
73
|
+
>
|
|
74
|
+
<X className="h-4 w-4" />
|
|
75
|
+
</button>
|
|
76
|
+
)}
|
|
77
|
+
</AlertTitle>
|
|
78
|
+
|
|
79
|
+
<AlertDescription className="mt-2">
|
|
80
|
+
<div className="font-medium">{error.message || errorInfo.message}</div>
|
|
81
|
+
|
|
82
|
+
<Collapsible
|
|
83
|
+
open={showDetails}
|
|
84
|
+
onOpenChange={setShowDetails}
|
|
85
|
+
className="space-y-2 mt-4"
|
|
86
|
+
>
|
|
87
|
+
<CollapsibleTrigger className="flex items-center gap-2 text-sm font-medium">
|
|
88
|
+
{showDetails ? (
|
|
89
|
+
<ChevronUp className="h-4 w-4" />
|
|
90
|
+
) : (
|
|
91
|
+
<ChevronDown className="h-4 w-4" />
|
|
92
|
+
)}
|
|
93
|
+
Error Details
|
|
94
|
+
</CollapsibleTrigger>
|
|
95
|
+
|
|
96
|
+
<CollapsibleContent className="space-y-4">
|
|
97
|
+
{showQueryPreview && (
|
|
98
|
+
<div className="mt-2">
|
|
99
|
+
<div className="text-sm font-medium mb-1">Query preview:</div>
|
|
100
|
+
<div className="relative">
|
|
101
|
+
<pre className="text-xs bg-destructive/10 p-2 rounded overflow-x-auto whitespace-pre-wrap">
|
|
102
|
+
{error.details.originalQuery}
|
|
103
|
+
</pre>
|
|
104
|
+
{showErrorLocation && (
|
|
105
|
+
<div
|
|
106
|
+
className="absolute left-0 top-0 w-full"
|
|
107
|
+
style={{
|
|
108
|
+
transform: `translateY(${Math.floor(error.details.offset / 50)}rem)`
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
<div
|
|
112
|
+
className="absolute h-4 w-2 bg-red-500"
|
|
113
|
+
style={{ left: `${(error.details.offset % 50) * 0.5}rem` }}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
)}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
)}
|
|
120
|
+
|
|
121
|
+
{(error.details?.suggestions || errorInfo.action) && (
|
|
122
|
+
<div className="mt-2">
|
|
123
|
+
<div className="text-sm font-medium mb-1">Suggestions:</div>
|
|
124
|
+
<ul className="list-disc pl-4 space-y-1">
|
|
125
|
+
{error.details?.suggestions ? (
|
|
126
|
+
error.details.suggestions.map((suggestion, index) => (
|
|
127
|
+
<li key={index} className="text-sm text-destructive-foreground/90">
|
|
128
|
+
{suggestion}
|
|
129
|
+
</li>
|
|
130
|
+
))
|
|
131
|
+
) : (
|
|
132
|
+
<li className="text-sm text-destructive-foreground/90">
|
|
133
|
+
{errorInfo.action}
|
|
134
|
+
</li>
|
|
135
|
+
)}
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
|
|
140
|
+
{error.details?.error && (
|
|
141
|
+
<div className="mt-2">
|
|
142
|
+
<div className="text-sm font-medium mb-1">Technical details:</div>
|
|
143
|
+
<pre className="text-xs bg-destructive/10 p-2 rounded overflow-x-auto">
|
|
144
|
+
{error.details.error}
|
|
145
|
+
</pre>
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
|
|
149
|
+
{onFixError && isSyntaxError && (
|
|
150
|
+
<div className="mt-4">
|
|
151
|
+
<Button
|
|
152
|
+
variant="outline"
|
|
153
|
+
size="sm"
|
|
154
|
+
onClick={() => onFixError(error.details.errorLocation)}
|
|
155
|
+
>
|
|
156
|
+
Go to Error Location
|
|
157
|
+
</Button>
|
|
158
|
+
</div>
|
|
159
|
+
)}
|
|
160
|
+
</CollapsibleContent>
|
|
161
|
+
</Collapsible>
|
|
162
|
+
</AlertDescription>
|
|
163
|
+
</Alert>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export { ErrorMessages };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// components/sync-migrations-button.jsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import React, { memo, useState } from 'react';
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import { FolderSync, Loader2 } from 'lucide-react';
|
|
7
|
+
import {
|
|
8
|
+
Tooltip,
|
|
9
|
+
TooltipContent,
|
|
10
|
+
TooltipProvider,
|
|
11
|
+
TooltipTrigger,
|
|
12
|
+
} from "@/components/ui/tooltip";
|
|
13
|
+
import { useToast } from "@/hooks/use-toast";
|
|
14
|
+
|
|
15
|
+
const SyncMigrationsButton = memo(({ tableName, onSync }) => {
|
|
16
|
+
const [isSyncing, setIsSyncing] = useState(false);
|
|
17
|
+
const { toast } = useToast();
|
|
18
|
+
|
|
19
|
+
// Only show for d1_migrations table
|
|
20
|
+
if (tableName !== 'd1_migrations') return null;
|
|
21
|
+
|
|
22
|
+
const handleSync = async () => {
|
|
23
|
+
try {
|
|
24
|
+
setIsSyncing(true);
|
|
25
|
+
const response = await fetch('/api/migrations/sync-files', {
|
|
26
|
+
method: 'POST'
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(data.error || 'Failed to sync migrations');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { added = [], removed = [] } = data.details || {};
|
|
36
|
+
|
|
37
|
+
toast({
|
|
38
|
+
title: "Migrations Synced",
|
|
39
|
+
description: `Added: ${added.length}, Removed: ${removed.length}`
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Refresh the table data if sync was successful
|
|
43
|
+
if (onSync) {
|
|
44
|
+
await onSync();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error('Error syncing migrations:', error);
|
|
49
|
+
toast({
|
|
50
|
+
variant: "destructive",
|
|
51
|
+
title: "Sync Failed",
|
|
52
|
+
description: error.message
|
|
53
|
+
});
|
|
54
|
+
} finally {
|
|
55
|
+
setIsSyncing(false);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<TooltipProvider>
|
|
61
|
+
<Tooltip>
|
|
62
|
+
<TooltipTrigger asChild>
|
|
63
|
+
<Button
|
|
64
|
+
variant="outline"
|
|
65
|
+
size="icon"
|
|
66
|
+
onClick={handleSync}
|
|
67
|
+
disabled={isSyncing}
|
|
68
|
+
className="h-8"
|
|
69
|
+
>
|
|
70
|
+
{isSyncing ? (
|
|
71
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
72
|
+
) : (
|
|
73
|
+
<FolderSync className="h-4 w-4" />
|
|
74
|
+
)}
|
|
75
|
+
</Button>
|
|
76
|
+
</TooltipTrigger>
|
|
77
|
+
<TooltipContent>
|
|
78
|
+
<p>Sync migration files with d1_migrations table</p>
|
|
79
|
+
</TooltipContent>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
</TooltipProvider>
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
SyncMigrationsButton.displayName = 'SyncMigrationsButton';
|
|
86
|
+
|
|
87
|
+
export default SyncMigrationsButton;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// components/table-error-dialog.jsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import {
|
|
6
|
+
Dialog,
|
|
7
|
+
DialogContent,
|
|
8
|
+
DialogHeader,
|
|
9
|
+
DialogTitle,
|
|
10
|
+
} from "@/components/ui/dialog";
|
|
11
|
+
import { Button } from "@/components/ui/button";
|
|
12
|
+
import { AlertCircle } from 'lucide-react';
|
|
13
|
+
|
|
14
|
+
// Simple function that focuses on just message display
|
|
15
|
+
function getErrorInfo(error) {
|
|
16
|
+
if (!error) {
|
|
17
|
+
return {
|
|
18
|
+
message: 'An unknown error occurred.',
|
|
19
|
+
icon: AlertCircle,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
message: error.message,
|
|
24
|
+
icon: AlertCircle,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function DatabaseErrorDialog({ isOpen, onClose, error }) {
|
|
29
|
+
if (!error || !isOpen) return null;
|
|
30
|
+
|
|
31
|
+
const { message, icon: Icon } = getErrorInfo(error);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
35
|
+
<DialogContent className="sm:max-w-md font-sans">
|
|
36
|
+
<DialogHeader>
|
|
37
|
+
<div className="flex items-center gap-2">
|
|
38
|
+
<Icon className="h-4 w-4 text-red-500" />
|
|
39
|
+
<DialogTitle>Error</DialogTitle>
|
|
40
|
+
</div>
|
|
41
|
+
</DialogHeader>
|
|
42
|
+
<div className="space-y-4">
|
|
43
|
+
<p className="bg-neutral-100 p-2 rounded-md text-neutral-900">
|
|
44
|
+
{message}
|
|
45
|
+
</p>
|
|
46
|
+
{error.details?.suggestions && (
|
|
47
|
+
<div className="text-sm space-y-1">
|
|
48
|
+
<p className="font-medium">Suggestions:</p>
|
|
49
|
+
<ul className="list-disc pl-4 space-y-1">
|
|
50
|
+
{error.details.suggestions.map((suggestion, index) => (
|
|
51
|
+
<li key={index}>{suggestion}</li>
|
|
52
|
+
))}
|
|
53
|
+
</ul>
|
|
54
|
+
</div>
|
|
55
|
+
)}
|
|
56
|
+
</div>
|
|
57
|
+
<div className="flex justify-end gap-2 mt-4">
|
|
58
|
+
<Button variant="default" onClick={onClose}>
|
|
59
|
+
Got it
|
|
60
|
+
</Button>
|
|
61
|
+
</div>
|
|
62
|
+
</DialogContent>
|
|
63
|
+
</Dialog>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// components/table-toolbar.jsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import React, { memo } from 'react';
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import {
|
|
7
|
+
Select,
|
|
8
|
+
SelectContent,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectTrigger,
|
|
11
|
+
SelectValue,
|
|
12
|
+
} from "@/components/ui/select";
|
|
13
|
+
import {
|
|
14
|
+
ArrowLeft,
|
|
15
|
+
ArrowRight,
|
|
16
|
+
SlidersHorizontal,
|
|
17
|
+
Columns,
|
|
18
|
+
Loader2
|
|
19
|
+
} from 'lucide-react';
|
|
20
|
+
import {
|
|
21
|
+
Tooltip,
|
|
22
|
+
TooltipContent,
|
|
23
|
+
TooltipProvider,
|
|
24
|
+
TooltipTrigger,
|
|
25
|
+
} from "@/components/ui/tooltip";
|
|
26
|
+
import RefreshButton from './refresh-button';
|
|
27
|
+
import SyncMigrationsButton from './sync-migrations-button';
|
|
28
|
+
import DownloadButton from './download-button';
|
|
29
|
+
import ColumnSelector from './column-selector';
|
|
30
|
+
|
|
31
|
+
const StaticControls = memo(({
|
|
32
|
+
onAdd,
|
|
33
|
+
onDelete,
|
|
34
|
+
selectedCount,
|
|
35
|
+
disabled,
|
|
36
|
+
newRecordsCount,
|
|
37
|
+
schema,
|
|
38
|
+
visibleColumns,
|
|
39
|
+
onColumnToggle
|
|
40
|
+
}) => (
|
|
41
|
+
<div className="flex items-center space-x-2">
|
|
42
|
+
<TooltipProvider>
|
|
43
|
+
<Tooltip>
|
|
44
|
+
<TooltipTrigger asChild>
|
|
45
|
+
{/* Wrapping the disabled button in a span so the tooltip can trigger */}
|
|
46
|
+
<span>
|
|
47
|
+
<Button
|
|
48
|
+
size="sm"
|
|
49
|
+
variant="outline"
|
|
50
|
+
className="font-semibold opacity-50 cursor-not-allowed"
|
|
51
|
+
disabled
|
|
52
|
+
>
|
|
53
|
+
<SlidersHorizontal className="h-4 w-4" />
|
|
54
|
+
Filters
|
|
55
|
+
</Button>
|
|
56
|
+
</span>
|
|
57
|
+
</TooltipTrigger>
|
|
58
|
+
<TooltipContent>
|
|
59
|
+
<p>Filters are not available yet. Coming soon!</p>
|
|
60
|
+
</TooltipContent>
|
|
61
|
+
</Tooltip>
|
|
62
|
+
</TooltipProvider>
|
|
63
|
+
|
|
64
|
+
<ColumnSelector
|
|
65
|
+
schema={schema}
|
|
66
|
+
visibleColumns={visibleColumns}
|
|
67
|
+
onColumnToggle={onColumnToggle}
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<div className="h-4 border-r mx-2" />
|
|
71
|
+
|
|
72
|
+
<Button
|
|
73
|
+
size="sm"
|
|
74
|
+
variant="default"
|
|
75
|
+
className="font-semibold"
|
|
76
|
+
onClick={onAdd}
|
|
77
|
+
>
|
|
78
|
+
Add record
|
|
79
|
+
</Button>
|
|
80
|
+
|
|
81
|
+
{selectedCount > 0 && (
|
|
82
|
+
<Button
|
|
83
|
+
size="sm"
|
|
84
|
+
className="font-semibold"
|
|
85
|
+
onClick={onDelete}
|
|
86
|
+
variant="destructive"
|
|
87
|
+
disabled={disabled || newRecordsCount > 0}
|
|
88
|
+
>
|
|
89
|
+
Delete {selectedCount} {selectedCount === 1 ? 'record' : 'records'}
|
|
90
|
+
</Button>
|
|
91
|
+
)}
|
|
92
|
+
</div>
|
|
93
|
+
));
|
|
94
|
+
|
|
95
|
+
const RowCount = memo(({ totalRows }) => (
|
|
96
|
+
<span className="text-sm text-neutral-600">
|
|
97
|
+
{totalRows} {totalRows === 1 ? 'row' : 'rows'}
|
|
98
|
+
</span>
|
|
99
|
+
));
|
|
100
|
+
|
|
101
|
+
const PaginationControls = memo(({
|
|
102
|
+
currentPage,
|
|
103
|
+
totalPages,
|
|
104
|
+
onPageChange,
|
|
105
|
+
disabled,
|
|
106
|
+
newRecordsCount
|
|
107
|
+
}) => (
|
|
108
|
+
<div className="flex items-center space-x-2">
|
|
109
|
+
<Button
|
|
110
|
+
variant="ghost"
|
|
111
|
+
size="icon"
|
|
112
|
+
onClick={() => {
|
|
113
|
+
console.log("Pagination: navigating to previous page", currentPage - 1);
|
|
114
|
+
onPageChange(currentPage - 1);
|
|
115
|
+
}}
|
|
116
|
+
disabled={currentPage === 1 || disabled || newRecordsCount > 0}
|
|
117
|
+
className="h-8"
|
|
118
|
+
>
|
|
119
|
+
<ArrowLeft className="h-4 w-4" />
|
|
120
|
+
</Button>
|
|
121
|
+
<span className="text-sm">
|
|
122
|
+
Page {currentPage} of {totalPages}
|
|
123
|
+
</span>
|
|
124
|
+
<Button
|
|
125
|
+
variant="ghost"
|
|
126
|
+
size="icon"
|
|
127
|
+
onClick={() => {
|
|
128
|
+
console.log("Pagination: navigating to next page", currentPage + 1);
|
|
129
|
+
onPageChange(currentPage + 1);
|
|
130
|
+
}}
|
|
131
|
+
disabled={currentPage === totalPages || disabled || newRecordsCount > 0}
|
|
132
|
+
className="h-8"
|
|
133
|
+
>
|
|
134
|
+
<ArrowRight className="h-4 w-4" />
|
|
135
|
+
</Button>
|
|
136
|
+
</div>
|
|
137
|
+
));
|
|
138
|
+
|
|
139
|
+
const RowsPerPageSelect = memo(({ value, onValueChange, disabled, newRecordsCount }) => (
|
|
140
|
+
<Select
|
|
141
|
+
value={value.toString()}
|
|
142
|
+
onValueChange={onValueChange}
|
|
143
|
+
disabled={disabled || newRecordsCount > 0}
|
|
144
|
+
>
|
|
145
|
+
<SelectTrigger className="w-20 h-8">
|
|
146
|
+
<SelectValue />
|
|
147
|
+
</SelectTrigger>
|
|
148
|
+
<SelectContent>
|
|
149
|
+
<SelectItem value="50">50</SelectItem>
|
|
150
|
+
<SelectItem value="100">100</SelectItem>
|
|
151
|
+
<SelectItem value="250">250</SelectItem>
|
|
152
|
+
</SelectContent>
|
|
153
|
+
</Select>
|
|
154
|
+
));
|
|
155
|
+
|
|
156
|
+
const SaveDiscardButtons = memo(({ onSave, onDiscard, totalChanges, isSaving }) => (
|
|
157
|
+
<div className="flex items-center gap-2">
|
|
158
|
+
<Button
|
|
159
|
+
size="sm"
|
|
160
|
+
variant="ghost"
|
|
161
|
+
className="font-semibold"
|
|
162
|
+
onClick={onDiscard}
|
|
163
|
+
disabled={isSaving}
|
|
164
|
+
>
|
|
165
|
+
Discard changes
|
|
166
|
+
</Button>
|
|
167
|
+
<Button
|
|
168
|
+
size="sm"
|
|
169
|
+
className="font-semibold bg-green-600 hover:bg-green-700"
|
|
170
|
+
variant="default"
|
|
171
|
+
onClick={onSave}
|
|
172
|
+
disabled={isSaving}
|
|
173
|
+
>
|
|
174
|
+
{isSaving ? (
|
|
175
|
+
<>
|
|
176
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
177
|
+
Saving...
|
|
178
|
+
</>
|
|
179
|
+
) : (
|
|
180
|
+
`Save ${totalChanges} ${totalChanges === 1 ? 'change' : 'changes'}`
|
|
181
|
+
)}
|
|
182
|
+
</Button>
|
|
183
|
+
</div>
|
|
184
|
+
));
|
|
185
|
+
|
|
186
|
+
const TableToolbar = ({
|
|
187
|
+
selectedCount = 0,
|
|
188
|
+
onAdd,
|
|
189
|
+
onDelete,
|
|
190
|
+
onRefresh,
|
|
191
|
+
totalRows = 0,
|
|
192
|
+
currentPage = 1,
|
|
193
|
+
totalPages = 1,
|
|
194
|
+
onPageChange,
|
|
195
|
+
rowsPerPage = 50,
|
|
196
|
+
onRowsPerPageChange,
|
|
197
|
+
tableName,
|
|
198
|
+
onDownloadStart,
|
|
199
|
+
onDownloadComplete,
|
|
200
|
+
disabled = false,
|
|
201
|
+
editCount = 0,
|
|
202
|
+
newRecordsCount = 0,
|
|
203
|
+
onSaveChanges,
|
|
204
|
+
onDiscardChanges,
|
|
205
|
+
isSaving = false,
|
|
206
|
+
schema,
|
|
207
|
+
visibleColumns,
|
|
208
|
+
onColumnToggle,
|
|
209
|
+
}) => {
|
|
210
|
+
const handleRowsPerPageChange = (value) => {
|
|
211
|
+
const newRowsPerPage = parseInt(value, 10);
|
|
212
|
+
onRowsPerPageChange(newRowsPerPage);
|
|
213
|
+
onPageChange(1); // Reset to first page when rows per page changes
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const totalChanges = editCount + newRecordsCount;
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<div className="flex items-center justify-between p-3 border-b bg-background font-sans">
|
|
220
|
+
<div className="flex items-center justify-between w-full">
|
|
221
|
+
<StaticControls
|
|
222
|
+
onAdd={onAdd}
|
|
223
|
+
onDelete={onDelete}
|
|
224
|
+
selectedCount={selectedCount}
|
|
225
|
+
disabled={disabled || isSaving}
|
|
226
|
+
newRecordsCount={newRecordsCount}
|
|
227
|
+
schema={schema}
|
|
228
|
+
visibleColumns={visibleColumns}
|
|
229
|
+
onColumnToggle={onColumnToggle}
|
|
230
|
+
/>
|
|
231
|
+
|
|
232
|
+
<div className="flex items-center gap-4">
|
|
233
|
+
{totalChanges > 0 ? (
|
|
234
|
+
<SaveDiscardButtons
|
|
235
|
+
onSave={onSaveChanges}
|
|
236
|
+
onDiscard={onDiscardChanges}
|
|
237
|
+
totalChanges={totalChanges}
|
|
238
|
+
isSaving={isSaving}
|
|
239
|
+
/>
|
|
240
|
+
) : (
|
|
241
|
+
<div className="flex items-center space-x-2">
|
|
242
|
+
<RowCount totalRows={totalRows} />
|
|
243
|
+
|
|
244
|
+
<PaginationControls
|
|
245
|
+
currentPage={currentPage}
|
|
246
|
+
totalPages={totalPages}
|
|
247
|
+
onPageChange={onPageChange}
|
|
248
|
+
disabled={disabled}
|
|
249
|
+
newRecordsCount={newRecordsCount}
|
|
250
|
+
/>
|
|
251
|
+
|
|
252
|
+
<RowsPerPageSelect
|
|
253
|
+
value={rowsPerPage}
|
|
254
|
+
onValueChange={handleRowsPerPageChange}
|
|
255
|
+
disabled={disabled}
|
|
256
|
+
newRecordsCount={newRecordsCount}
|
|
257
|
+
/>
|
|
258
|
+
|
|
259
|
+
<RefreshButton
|
|
260
|
+
onRefresh={onRefresh}
|
|
261
|
+
disabled={disabled}
|
|
262
|
+
/>
|
|
263
|
+
|
|
264
|
+
<SyncMigrationsButton
|
|
265
|
+
tableName={tableName}
|
|
266
|
+
onSync={onRefresh}
|
|
267
|
+
disabled={disabled}
|
|
268
|
+
/>
|
|
269
|
+
|
|
270
|
+
<DownloadButton
|
|
271
|
+
tableName={tableName}
|
|
272
|
+
onDownloadStart={onDownloadStart}
|
|
273
|
+
onDownloadComplete={onDownloadComplete}
|
|
274
|
+
disabled={disabled}
|
|
275
|
+
/>
|
|
276
|
+
</div>
|
|
277
|
+
)}
|
|
278
|
+
</div>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
TableToolbar.displayName = 'TableToolbar';
|
|
285
|
+
export default memo(TableToolbar);
|