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,173 @@
|
|
|
1
|
+
// app/api/tables/[name]/route.js
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from 'next/server';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { exec } from 'child_process';
|
|
6
|
+
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
7
|
+
import { dbQueue } from '@/lib/database-queue';
|
|
8
|
+
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
|
|
11
|
+
export const runtime = 'nodejs';
|
|
12
|
+
export const dynamic = 'force-dynamic';
|
|
13
|
+
|
|
14
|
+
// Global query queue to prevent database locks
|
|
15
|
+
let isProcessing = false;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Executes a D1 SQL query using Wrangler.
|
|
19
|
+
* This function ensures that only one query is processed at a time.
|
|
20
|
+
*/
|
|
21
|
+
async function executeD1Query(command, projectDir, databaseName) {
|
|
22
|
+
try {
|
|
23
|
+
// Wait until any current query is finished.
|
|
24
|
+
while (isProcessing) {
|
|
25
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
26
|
+
}
|
|
27
|
+
isProcessing = true;
|
|
28
|
+
|
|
29
|
+
// Escape double quotes in the command and execute the query
|
|
30
|
+
const { stdout } = await execAsync(
|
|
31
|
+
`wrangler d1 execute ${databaseName} --local --command="${command.replace(/"/g, '\\"')}" --json`,
|
|
32
|
+
{ cwd: projectDir }
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const result = JSON.parse(stdout);
|
|
36
|
+
return result[0]?.results || [];
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error('Query execution error:', error);
|
|
39
|
+
throw error;
|
|
40
|
+
} finally {
|
|
41
|
+
isProcessing = false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Extracts CHECK constraints from a CREATE TABLE SQL statement.
|
|
47
|
+
*/
|
|
48
|
+
function extractCheckConstraints(createTableSQL) {
|
|
49
|
+
const checkConstraints = {};
|
|
50
|
+
const checkRegex = /CHECK\s*\(\s*(\w+)\s+IN\s*\((.*?)\)\s*\)/gi;
|
|
51
|
+
let match;
|
|
52
|
+
|
|
53
|
+
while ((match = checkRegex.exec(createTableSQL)) !== null) {
|
|
54
|
+
const columnName = match[1];
|
|
55
|
+
const values = match[2]
|
|
56
|
+
.split(',')
|
|
57
|
+
.map(value => value.trim().replace(/^'|'$/g, ''));
|
|
58
|
+
|
|
59
|
+
checkConstraints[columnName] = values;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return checkConstraints;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* GET handler for fetching table details, schema, and data.
|
|
67
|
+
* It retrieves the Wrangler configuration using the helper and uses that
|
|
68
|
+
* to determine the target D1 database.
|
|
69
|
+
*/
|
|
70
|
+
export async function GET(request, context) {
|
|
71
|
+
return dbQueue.add(async () => {
|
|
72
|
+
try {
|
|
73
|
+
// Extract table name from route parameters
|
|
74
|
+
const params = await context.params;
|
|
75
|
+
const { name } = params;
|
|
76
|
+
|
|
77
|
+
// Get pagination info from the query parameters
|
|
78
|
+
const { searchParams } = new URL(request.url);
|
|
79
|
+
const page = parseInt(searchParams.get('page')) || 1;
|
|
80
|
+
const limit = parseInt(searchParams.get('limit')) || 50;
|
|
81
|
+
const offset = (page - 1) * limit;
|
|
82
|
+
|
|
83
|
+
const projectDir = process.env.D1_PROJECT_DIR;
|
|
84
|
+
if (!projectDir) {
|
|
85
|
+
throw new Error('Project directory not configured');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Use the centralized helper to find Wrangler configuration
|
|
89
|
+
const wranglerResult = await findWranglerConfig(projectDir);
|
|
90
|
+
if (!wranglerResult || !wranglerResult.config) {
|
|
91
|
+
throw new Error('No Wrangler configuration file found');
|
|
92
|
+
}
|
|
93
|
+
const config = wranglerResult.config;
|
|
94
|
+
if (!config.d1_databases?.length) {
|
|
95
|
+
throw new Error('No D1 databases configured');
|
|
96
|
+
}
|
|
97
|
+
// Get the first D1 database name from the configuration
|
|
98
|
+
const databaseName = config.d1_databases[0].database_name;
|
|
99
|
+
|
|
100
|
+
// Get table schema using PRAGMA query
|
|
101
|
+
const schemaQuery = `PRAGMA table_info(${name});`;
|
|
102
|
+
const schema = await executeD1Query(schemaQuery, projectDir, databaseName);
|
|
103
|
+
|
|
104
|
+
// Get the CREATE TABLE statement from sqlite_master
|
|
105
|
+
const createTableQuery = `SELECT sql FROM sqlite_master WHERE type='table' AND name='${name}';`;
|
|
106
|
+
const tableDefinition = await executeD1Query(createTableQuery, projectDir, databaseName);
|
|
107
|
+
const createTableSQL = tableDefinition[0]?.sql || '';
|
|
108
|
+
|
|
109
|
+
// Extract CHECK constraints from the CREATE TABLE statement
|
|
110
|
+
const checkConstraints = extractCheckConstraints(createTableSQL);
|
|
111
|
+
|
|
112
|
+
// Merge constraints into the schema response
|
|
113
|
+
const enhancedSchema = schema.map(column => ({
|
|
114
|
+
...column,
|
|
115
|
+
check: checkConstraints[column.name] || null
|
|
116
|
+
}));
|
|
117
|
+
|
|
118
|
+
// Get total row count for the table
|
|
119
|
+
const countQuery = `SELECT COUNT(*) as total FROM ${name};`;
|
|
120
|
+
const countResult = await executeD1Query(countQuery, projectDir, databaseName);
|
|
121
|
+
const totalRows = countResult[0]?.total || 0;
|
|
122
|
+
|
|
123
|
+
// Fetch paginated data using the primary key column for ordering
|
|
124
|
+
const primaryKeyColumn = schema.find(col => col.pk === 1)?.name || schema[0]?.name;
|
|
125
|
+
const dataQuery = `
|
|
126
|
+
SELECT * FROM ${name}
|
|
127
|
+
ORDER BY ${primaryKeyColumn} DESC
|
|
128
|
+
LIMIT ${limit} OFFSET ${offset};
|
|
129
|
+
`;
|
|
130
|
+
const data = await executeD1Query(dataQuery, projectDir, databaseName);
|
|
131
|
+
|
|
132
|
+
return NextResponse.json({
|
|
133
|
+
success: true,
|
|
134
|
+
schema: enhancedSchema,
|
|
135
|
+
data,
|
|
136
|
+
meta: {
|
|
137
|
+
tableName: name,
|
|
138
|
+
total: totalRows,
|
|
139
|
+
page,
|
|
140
|
+
limit,
|
|
141
|
+
totalPages: Math.ceil(totalRows / limit),
|
|
142
|
+
rowCount: data.length,
|
|
143
|
+
columnCount: schema.length
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error('Error handling request:', error);
|
|
149
|
+
return NextResponse.json({
|
|
150
|
+
success: false,
|
|
151
|
+
error: {
|
|
152
|
+
message: error.message,
|
|
153
|
+
details: error.stack
|
|
154
|
+
}
|
|
155
|
+
}, {
|
|
156
|
+
status: error.message.includes('not configured') ? 500 :
|
|
157
|
+
error.message.includes('not found') ? 404 : 500
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function OPTIONS() {
|
|
164
|
+
return new NextResponse(null, {
|
|
165
|
+
status: 204,
|
|
166
|
+
headers: {
|
|
167
|
+
'Access-Control-Allow-Origin': '*',
|
|
168
|
+
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
|
169
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// app/api/tables/route.js
|
|
2
|
+
|
|
3
|
+
import { NextResponse } from 'next/server';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { exec } from 'child_process';
|
|
6
|
+
import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
|
|
7
|
+
|
|
8
|
+
const execAsync = promisify(exec);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Attempts to extract a JSON object from a string.
|
|
12
|
+
* First, it tries to parse the entire string.
|
|
13
|
+
* If that fails, it searches for a JSON portion within the string.
|
|
14
|
+
*/
|
|
15
|
+
function extractJSONFromOutput(stdout) {
|
|
16
|
+
try {
|
|
17
|
+
// First try to parse the entire output as JSON
|
|
18
|
+
return JSON.parse(stdout);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
// If that fails, try to find and parse just the JSON portion
|
|
21
|
+
const jsonStart = stdout.indexOf('[') !== -1 ?
|
|
22
|
+
stdout.indexOf('[') :
|
|
23
|
+
stdout.indexOf('{');
|
|
24
|
+
|
|
25
|
+
if (jsonStart === -1) return null;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const jsonStr = stdout.substring(jsonStart);
|
|
29
|
+
return JSON.parse(jsonStr);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Error parsing JSON portion:', error);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Extracts table names from the query result.
|
|
39
|
+
*/
|
|
40
|
+
function extractTablesFromResult(result) {
|
|
41
|
+
if (!result) return [];
|
|
42
|
+
|
|
43
|
+
if (Array.isArray(result) && result[0]?.results) {
|
|
44
|
+
return result[0].results.map(row => row.name);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (result.results?.[0]?.results) {
|
|
48
|
+
return result.results[0].results.map(row => row.name);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Retries a function if it fails with a timeout (e.g. due to a locked database).
|
|
56
|
+
*/
|
|
57
|
+
async function retryWithTimeout(fn, retries = 3, timeout = 1000) {
|
|
58
|
+
for (let i = 0; i < retries; i++) {
|
|
59
|
+
try {
|
|
60
|
+
return await fn();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (i === retries - 1) throw error;
|
|
63
|
+
if (error.message.includes('database is locked')) {
|
|
64
|
+
console.log(`Database locked, retrying in ${timeout}ms... (attempt ${i + 1}/${retries})`);
|
|
65
|
+
await new Promise(resolve => setTimeout(resolve, timeout));
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* GET handler for listing tables.
|
|
75
|
+
* It uses the Wrangler configuration (via findWranglerConfig) to determine the D1 database.
|
|
76
|
+
*/
|
|
77
|
+
export async function GET() {
|
|
78
|
+
try {
|
|
79
|
+
const projectDir = process.env.D1_PROJECT_DIR;
|
|
80
|
+
|
|
81
|
+
if (!projectDir) {
|
|
82
|
+
console.error('D1_PROJECT_DIR environment variable is not set');
|
|
83
|
+
return NextResponse.json(
|
|
84
|
+
{ error: 'Project directory not configured' },
|
|
85
|
+
{ status: 500 }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Use the centralized helper to get Wrangler configuration
|
|
90
|
+
const wranglerResult = await findWranglerConfig(projectDir);
|
|
91
|
+
if (!wranglerResult || !wranglerResult.config) {
|
|
92
|
+
return NextResponse.json(
|
|
93
|
+
{ error: 'No Wrangler configuration file found in project directory' },
|
|
94
|
+
{ status: 404 }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const config = wranglerResult.config;
|
|
98
|
+
if (!config.d1_databases?.length) {
|
|
99
|
+
return NextResponse.json(
|
|
100
|
+
{ error: 'No D1 databases configured in Wrangler configuration' },
|
|
101
|
+
{ status: 404 }
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
// Get the first D1 database name from the configuration
|
|
105
|
+
const databaseName = config.d1_databases[0].database_name;
|
|
106
|
+
|
|
107
|
+
// SQL query to list non-system tables
|
|
108
|
+
const query = `
|
|
109
|
+
SELECT name FROM sqlite_master
|
|
110
|
+
WHERE type='table'
|
|
111
|
+
AND name NOT LIKE 'sqlite_%'
|
|
112
|
+
AND name NOT LIKE '_cf_%'
|
|
113
|
+
ORDER BY name;
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
// Execute the query with a retry mechanism if the database is locked
|
|
117
|
+
const { stdout } = await retryWithTimeout(async () => {
|
|
118
|
+
return execAsync(
|
|
119
|
+
`wrangler d1 execute ${databaseName} --local --command="${query}"`,
|
|
120
|
+
{
|
|
121
|
+
cwd: projectDir,
|
|
122
|
+
timeout: 5000 // 5 second timeout
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Extract JSON from the command output and then extract table names
|
|
128
|
+
const result = extractJSONFromOutput(stdout);
|
|
129
|
+
const tables = extractTablesFromResult(result);
|
|
130
|
+
|
|
131
|
+
return NextResponse.json({
|
|
132
|
+
success: true,
|
|
133
|
+
tables,
|
|
134
|
+
debug: {
|
|
135
|
+
projectDir,
|
|
136
|
+
tableCount: tables.length
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('Error fetching tables:', error);
|
|
142
|
+
|
|
143
|
+
// Enhanced error response for troubleshooting
|
|
144
|
+
const errorResponse = {
|
|
145
|
+
error: 'Failed to fetch tables',
|
|
146
|
+
details: error.message,
|
|
147
|
+
debug: {
|
|
148
|
+
errorCode: error.code,
|
|
149
|
+
errorStack: error.stack,
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Check for specific error types (e.g., database locked)
|
|
154
|
+
if (error.message.includes('database is locked')) {
|
|
155
|
+
errorResponse.error = 'Database is temporarily locked';
|
|
156
|
+
errorResponse.retryAfter = 1000; // Suggest retry after 1 second
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return NextResponse.json(errorResponse, {
|
|
160
|
+
status: error.message.includes('database is locked') ? 503 : 500
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function OPTIONS() {
|
|
166
|
+
return new NextResponse(null, {
|
|
167
|
+
status: 204,
|
|
168
|
+
headers: {
|
|
169
|
+
'Access-Control-Allow-Origin': '*',
|
|
170
|
+
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
|
171
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
body {
|
|
6
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@layer base {
|
|
10
|
+
:root {
|
|
11
|
+
--background: 0 0% 100%;
|
|
12
|
+
--foreground: 240 10% 3.9%;
|
|
13
|
+
--card: 0 0% 100%;
|
|
14
|
+
--card-foreground: 240 10% 3.9%;
|
|
15
|
+
--popover: 0 0% 100%;
|
|
16
|
+
--popover-foreground: 240 10% 3.9%;
|
|
17
|
+
--primary: 240 5.9% 10%;
|
|
18
|
+
--primary-foreground: 0 0% 98%;
|
|
19
|
+
--secondary: 240 4.8% 95.9%;
|
|
20
|
+
--secondary-foreground: 240 5.9% 10%;
|
|
21
|
+
--muted: 240 4.8% 95.9%;
|
|
22
|
+
--muted-foreground: 240 3.8% 46.1%;
|
|
23
|
+
--accent: 240 4.8% 95.9%;
|
|
24
|
+
--accent-foreground: 240 5.9% 10%;
|
|
25
|
+
--destructive: 0 84.2% 60.2%;
|
|
26
|
+
--destructive-foreground: 0 0% 98%;
|
|
27
|
+
--border: 240 5.9% 90%;
|
|
28
|
+
--input: 240 5.9% 90%;
|
|
29
|
+
--ring: 240 10% 3.9%;
|
|
30
|
+
--chart-1: 12 76% 61%;
|
|
31
|
+
--chart-2: 173 58% 39%;
|
|
32
|
+
--chart-3: 197 37% 24%;
|
|
33
|
+
--chart-4: 43 74% 66%;
|
|
34
|
+
--chart-5: 27 87% 67%;
|
|
35
|
+
--radius: 0.5rem;
|
|
36
|
+
--sidebar-background: 0 0% 98%;
|
|
37
|
+
--sidebar-foreground: 240 5.3% 26.1%;
|
|
38
|
+
--sidebar-primary: 240 5.9% 10%;
|
|
39
|
+
--sidebar-primary-foreground: 0 0% 98%;
|
|
40
|
+
--sidebar-accent: 240 4.8% 95.9%;
|
|
41
|
+
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
42
|
+
--sidebar-border: 220 13% 91%;
|
|
43
|
+
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
44
|
+
}
|
|
45
|
+
.dark {
|
|
46
|
+
--background: 240 10% 3.9%;
|
|
47
|
+
--foreground: 0 0% 98%;
|
|
48
|
+
--card: 240 10% 3.9%;
|
|
49
|
+
--card-foreground: 0 0% 98%;
|
|
50
|
+
--popover: 240 10% 3.9%;
|
|
51
|
+
--popover-foreground: 0 0% 98%;
|
|
52
|
+
--primary: 0 0% 98%;
|
|
53
|
+
--primary-foreground: 240 5.9% 10%;
|
|
54
|
+
--secondary: 240 3.7% 15.9%;
|
|
55
|
+
--secondary-foreground: 0 0% 98%;
|
|
56
|
+
--muted: 240 3.7% 15.9%;
|
|
57
|
+
--muted-foreground: 240 5% 64.9%;
|
|
58
|
+
--accent: 240 3.7% 15.9%;
|
|
59
|
+
--accent-foreground: 0 0% 98%;
|
|
60
|
+
--destructive: 0 62.8% 30.6%;
|
|
61
|
+
--destructive-foreground: 0 0% 98%;
|
|
62
|
+
--border: 240 3.7% 15.9%;
|
|
63
|
+
--input: 240 3.7% 15.9%;
|
|
64
|
+
--ring: 240 4.9% 83.9%;
|
|
65
|
+
--chart-1: 220 70% 50%;
|
|
66
|
+
--chart-2: 160 60% 45%;
|
|
67
|
+
--chart-3: 30 80% 55%;
|
|
68
|
+
--chart-4: 280 65% 60%;
|
|
69
|
+
--chart-5: 340 75% 55%;
|
|
70
|
+
--sidebar-background: 240 5.9% 10%;
|
|
71
|
+
--sidebar-foreground: 240 4.8% 95.9%;
|
|
72
|
+
--sidebar-primary: 224.3 76.3% 48%;
|
|
73
|
+
--sidebar-primary-foreground: 0 0% 100%;
|
|
74
|
+
--sidebar-accent: 240 3.7% 15.9%;
|
|
75
|
+
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
76
|
+
--sidebar-border: 240 3.7% 15.9%;
|
|
77
|
+
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@layer base {
|
|
82
|
+
* {
|
|
83
|
+
@apply border-border;
|
|
84
|
+
}
|
|
85
|
+
body {
|
|
86
|
+
@apply bg-background text-foreground;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.table-fixed {
|
|
91
|
+
table-layout: fixed;
|
|
92
|
+
width: 100%;
|
|
93
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// app/layout.js
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
import { DatabaseProvider } from '@/context/database-context';
|
|
5
|
+
import { Toaster } from '@/components/ui/toaster'; // Change this import
|
|
6
|
+
|
|
7
|
+
const geistSans = Geist({
|
|
8
|
+
variable: "--font-geist-sans",
|
|
9
|
+
subsets: ["latin"],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const geistMono = Geist_Mono({
|
|
13
|
+
variable: "--font-geist-mono",
|
|
14
|
+
subsets: ["latin"],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const metadata = {
|
|
18
|
+
title: "d1-studio",
|
|
19
|
+
description: "Native D1 database studio.",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function RootLayout({ children }) {
|
|
23
|
+
return (
|
|
24
|
+
<html lang="en">
|
|
25
|
+
<body
|
|
26
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
27
|
+
>
|
|
28
|
+
<DatabaseProvider>
|
|
29
|
+
{children}
|
|
30
|
+
<Toaster /> {/* Add this component */}
|
|
31
|
+
</DatabaseProvider>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|
|
34
|
+
);
|
|
35
|
+
}
|
package/src/app/page.jsx
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// app/page.js
|
|
2
|
+
'use client'
|
|
3
|
+
|
|
4
|
+
import { AppSidebar } from '../components/sidebar';
|
|
5
|
+
import { SQLEditor } from '../components/sql-editor';
|
|
6
|
+
import { TableView } from '../components/table-view';
|
|
7
|
+
import { useState } from 'react';
|
|
8
|
+
|
|
9
|
+
export default function StudioPage() {
|
|
10
|
+
const [currentView, setCurrentView] = useState('sql-editor');
|
|
11
|
+
const [selectedTable, setSelectedTable] = useState(null);
|
|
12
|
+
|
|
13
|
+
// We don't need to handle push errors here anymore since we're using toasts
|
|
14
|
+
// The error handling is now managed by the useEnvironmentController hook
|
|
15
|
+
|
|
16
|
+
const handleTableSelect = (tableName) => {
|
|
17
|
+
setSelectedTable(tableName);
|
|
18
|
+
setCurrentView('table-view');
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="flex h-screen bg-background">
|
|
23
|
+
<AppSidebar
|
|
24
|
+
className="w-64 border-r flex-shrink-0"
|
|
25
|
+
currentView={currentView}
|
|
26
|
+
onNavigate={setCurrentView}
|
|
27
|
+
onTableSelect={handleTableSelect}
|
|
28
|
+
/>
|
|
29
|
+
<main className="flex-1 overflow-hidden">
|
|
30
|
+
{currentView === 'sql-editor' && <SQLEditor />}
|
|
31
|
+
{currentView === 'table-view' && selectedTable && (
|
|
32
|
+
<TableView tableName={selectedTable} />
|
|
33
|
+
)}
|
|
34
|
+
</main>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// components/cloudflare-credentials-modal.jsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import React, { useState } from 'react';
|
|
5
|
+
import {
|
|
6
|
+
Dialog,
|
|
7
|
+
DialogContent,
|
|
8
|
+
DialogDescription,
|
|
9
|
+
DialogHeader,
|
|
10
|
+
DialogTitle,
|
|
11
|
+
} from "@/components/ui/dialog";
|
|
12
|
+
import { Input } from "@/components/ui/input";
|
|
13
|
+
import { Button } from "@/components/ui/button";
|
|
14
|
+
import { Loader2 } from 'lucide-react';
|
|
15
|
+
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
16
|
+
|
|
17
|
+
export function CloudflareCredentialsModal({ open, onClose, onSubmit }) {
|
|
18
|
+
const [accountId, setAccountId] = useState('');
|
|
19
|
+
const [apiToken, setApiToken] = useState('');
|
|
20
|
+
const [error, setError] = useState('');
|
|
21
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
22
|
+
|
|
23
|
+
const handleSubmit = async (e) => {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
setError('');
|
|
26
|
+
setIsLoading(true);
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
await onSubmit({ accountId, apiToken });
|
|
30
|
+
// Store credentials in localStorage
|
|
31
|
+
localStorage.setItem('cf_credentials', JSON.stringify({
|
|
32
|
+
accountId,
|
|
33
|
+
apiToken
|
|
34
|
+
}));
|
|
35
|
+
onClose();
|
|
36
|
+
} catch (err) {
|
|
37
|
+
setError(err.message);
|
|
38
|
+
} finally {
|
|
39
|
+
setIsLoading(false);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Dialog open={open} onOpenChange={onClose}>
|
|
45
|
+
<DialogContent className="sm:max-w-md">
|
|
46
|
+
<DialogHeader>
|
|
47
|
+
<DialogTitle>Connect to Cloudflare</DialogTitle>
|
|
48
|
+
<DialogDescription>
|
|
49
|
+
Enter your Cloudflare credentials to push your database to production.
|
|
50
|
+
</DialogDescription>
|
|
51
|
+
</DialogHeader>
|
|
52
|
+
|
|
53
|
+
<form onSubmit={handleSubmit} className="space-y-4 mt-4">
|
|
54
|
+
{error && (
|
|
55
|
+
<Alert variant="destructive">
|
|
56
|
+
<AlertDescription>{error}</AlertDescription>
|
|
57
|
+
</Alert>
|
|
58
|
+
)}
|
|
59
|
+
|
|
60
|
+
<div className="space-y-2">
|
|
61
|
+
<label className="text-sm font-medium">Account ID</label>
|
|
62
|
+
<Input
|
|
63
|
+
placeholder="Your Cloudflare Account ID"
|
|
64
|
+
value={accountId}
|
|
65
|
+
onChange={(e) => setAccountId(e.target.value)}
|
|
66
|
+
required
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="space-y-2">
|
|
71
|
+
<label className="text-sm font-medium">API Token</label>
|
|
72
|
+
<Input
|
|
73
|
+
type="password"
|
|
74
|
+
placeholder="Your D1 Database API Token"
|
|
75
|
+
value={apiToken}
|
|
76
|
+
onChange={(e) => setApiToken(e.target.value)}
|
|
77
|
+
required
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div className="flex justify-end gap-3">
|
|
82
|
+
<Button type="button" variant="outline" onClick={onClose}>
|
|
83
|
+
Cancel
|
|
84
|
+
</Button>
|
|
85
|
+
<Button type="submit" disabled={isLoading}>
|
|
86
|
+
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
87
|
+
Connect
|
|
88
|
+
</Button>
|
|
89
|
+
</div>
|
|
90
|
+
</form>
|
|
91
|
+
</DialogContent>
|
|
92
|
+
</Dialog>
|
|
93
|
+
);
|
|
94
|
+
}
|