d1s 0.2.11 → 0.2.13
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/dist/.next/.next/BUILD_ID +1 -1
- package/dist/.next/.next/app-build-manifest.json +28 -28
- package/dist/.next/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/.next/build-manifest.json +3 -3
- package/dist/.next/.next/cache/.rscinfo +1 -1
- package/dist/.next/.next/cache/.tsbuildinfo +1 -1
- 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/10.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/11.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/12.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/3.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/4.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/5.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/6.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/7.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/8.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/9.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/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/2.pack +0 -0
- package/dist/.next/.next/cache/webpack/server-production/3.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/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/.next/next-server.js.nft.json +1 -1
- package/dist/.next/.next/prerender-manifest.json +1 -1
- package/dist/.next/.next/required-server-files.json +1 -1
- package/dist/.next/.next/server/app/_not-found/page.js +1 -1
- package/dist/.next/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/_not-found.html +1 -1
- package/dist/.next/.next/server/app/_not-found.rsc +4 -4
- package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +3 -3
- package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +2 -2
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +4 -4
- package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +5 -5
- package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js +4 -4
- package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/query/route.js +3 -3
- package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/index.html +2 -2
- package/dist/.next/.next/server/app/index.rsc +5 -5
- package/dist/.next/.next/server/app/page.js +7 -7
- package/dist/.next/.next/server/app/page.js.nft.json +1 -1
- package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app-paths-manifest.json +1 -1
- package/dist/.next/.next/server/chunks/226.js +12 -12
- package/dist/.next/.next/server/chunks/391.js +1 -1
- package/dist/.next/.next/server/chunks/572.js +1 -0
- package/dist/.next/.next/server/chunks/992.js +3 -3
- package/dist/.next/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/.next/server/next-font-manifest.js +1 -1
- package/dist/.next/.next/server/next-font-manifest.json +1 -1
- package/dist/.next/.next/server/pages/404.html +1 -1
- package/dist/.next/.next/server/pages/500.html +1 -1
- package/dist/.next/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/.next/static/chunks/{576-c4daf274bb6469a1.js → 576-18a2209e1ed26aad.js} +1 -1
- package/dist/.next/.next/static/chunks/{92-c4466e0f1ca8a3a8.js → 92-5f7522943fcb72a8.js} +1 -1
- package/dist/.next/.next/static/chunks/app/{layout-be6ee67cf0c92654.js → layout-40ec07d04681ba81.js} +1 -1
- package/dist/.next/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +1 -0
- package/dist/.next/.next/static/chunks/app/page-f2bc307c0d8acdaa.js +1 -0
- package/dist/.next/.next/static/chunks/{main-app-fa35024de9bd9284.js → main-app-4506e88db72db4b7.js} +1 -1
- package/dist/.next/.next/static/css/{9f6c25c5400f83d3.css → 7c16f57d325d0d7d.css} +1 -1
- package/dist/.next/.next/static/ejYPqJ2kVicVp5EFWOZIC/_buildManifest.js +1 -0
- package/dist/.next/.next/static/ejYPqJ2kVicVp5EFWOZIC/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_buildManifest.js +1 -0
- package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_buildManifest.js +1 -0
- package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/.next/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/.next/.next/static/thaCy2qVeNqYYhdayr13C/_buildManifest.js +1 -0
- package/dist/.next/.next/static/thaCy2qVeNqYYhdayr13C/_ssgManifest.js +1 -0
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_buildManifest.js +1 -0
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_ssgManifest.js +1 -0
- package/dist/.next/.next/trace +3 -3
- package/dist/.next/.next/types/app/api/cloudflare/route.ts +1 -1
- package/dist/.next/.next/types/app/api/databases/route.ts +1 -1
- package/dist/.next/.next/types/app/api/migrations/sync/route.ts +1 -1
- package/dist/.next/.next/types/app/api/migrations/sync-files/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-data/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-remote/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/pull-remote/preview/route.ts +1 -1
- package/dist/.next/.next/types/app/api/push-remote/confirm/route.ts +1 -1
- package/dist/.next/.next/types/app/api/push-remote/preview/route.ts +1 -1
- package/dist/.next/.next/types/app/api/query/route.ts +1 -1
- package/dist/.next/.next/types/app/api/tables/[name]/route.ts +1 -1
- package/dist/.next/.next/types/app/api/tables/route.ts +1 -1
- package/dist/.next/.next/types/app/api/update/route.ts +1 -1
- package/dist/.next/.next/types/app/page.ts +1 -1
- package/dist/.next/BUILD_ID +1 -1
- package/dist/.next/app-build-manifest.json +28 -28
- package/dist/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/build-manifest.json +3 -3
- package/dist/.next/cache/.rscinfo +1 -1
- package/dist/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/cache/webpack/client-production/2.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack +0 -0
- package/dist/.next/cache/webpack/client-production/index.pack.old +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/next-minimal-server.js.nft.json +1 -1
- package/dist/.next/next-server.js.nft.json +1 -1
- package/dist/.next/prerender-manifest.json +1 -1
- package/dist/.next/required-server-files.json +1 -1
- package/dist/.next/server/app/_not-found/page.js +1 -1
- package/dist/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/_not-found.html +1 -1
- package/dist/.next/server/app/_not-found.rsc +4 -4
- package/dist/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/databases/route.js +1 -1
- package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route.js +3 -3
- package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/confirm/route.js +2 -2
- package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pull-remote/preview/route.js +4 -4
- package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/confirm/route.js +5 -5
- package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/push-remote/preview/route.js +4 -4
- package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/query/route.js +3 -3
- package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/tables/route.js +2 -2
- package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/index.html +2 -2
- package/dist/.next/server/app/index.rsc +5 -5
- package/dist/.next/server/app/page.js +7 -7
- package/dist/.next/server/app/page.js.nft.json +1 -1
- package/dist/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/.next/server/app-paths-manifest.json +1 -1
- package/dist/.next/server/chunks/226.js +12 -12
- package/dist/.next/server/chunks/391.js +1 -1
- package/dist/.next/server/chunks/572.js +1 -0
- package/dist/.next/server/chunks/992.js +3 -3
- package/dist/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/server/next-font-manifest.js +1 -1
- package/dist/.next/server/next-font-manifest.json +1 -1
- package/dist/.next/server/pages/404.html +1 -1
- package/dist/.next/server/pages/500.html +1 -1
- package/dist/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_buildManifest.js +1 -0
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_ssgManifest.js +1 -0
- package/dist/.next/static/chunks/{576-c4daf274bb6469a1.js → 576-18a2209e1ed26aad.js} +1 -1
- package/dist/.next/static/chunks/{92-c4466e0f1ca8a3a8.js → 92-5f7522943fcb72a8.js} +1 -1
- package/dist/.next/static/chunks/app/{layout-be6ee67cf0c92654.js → layout-40ec07d04681ba81.js} +1 -1
- package/dist/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +1 -0
- package/dist/.next/static/chunks/{main-app-fa35024de9bd9284.js → main-app-4506e88db72db4b7.js} +1 -1
- package/dist/.next/static/css/{9f6c25c5400f83d3.css → 7c16f57d325d0d7d.css} +1 -1
- package/dist/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/dist/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/dist/.next/trace +3 -14
- package/dist/.next/types/app/api/cloudflare/route.ts +1 -1
- package/dist/.next/types/app/api/databases/route.ts +1 -1
- package/dist/.next/types/app/api/migrations/sync/route.ts +1 -1
- package/dist/.next/types/app/api/migrations/sync-files/route.ts +1 -1
- package/dist/.next/types/app/api/pull-data/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/pull-remote/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/pull-remote/preview/route.ts +1 -1
- package/dist/.next/types/app/api/push-remote/confirm/route.ts +1 -1
- package/dist/.next/types/app/api/push-remote/preview/route.ts +1 -1
- package/dist/.next/types/app/api/query/route.ts +1 -1
- package/dist/.next/types/app/api/tables/[name]/route.ts +1 -1
- package/dist/.next/types/app/api/tables/route.ts +1 -1
- package/dist/.next/types/app/api/update/route.ts +1 -1
- package/dist/.next/types/app/page.ts +1 -1
- package/dist/app/api/tables/[name]/route.js +22 -10
- package/dist/app/globals.css +39 -0
- package/dist/d1-studio.js +2 -2
- package/dist/lib/data-type-handlers.js +426 -0
- package/dist/lib/sql-operations.js +32 -8
- package/dist/lib/sql-sanitizer.js +233 -0
- package/package.json +3 -9
- package/dist/.next/.next/server/chunks/90.js +0 -1
- package/dist/.next/.next/static/chunks/app/page-36ed30b2266617f3.js +0 -1
- package/dist/.next/server/chunks/90.js +0 -1
- package/dist/.next/static/chunks/app/page-36ed30b2266617f3.js +0 -1
- package/dist/app/app/api/cloudflare/route.js +0 -150
- package/dist/app/app/api/databases/route.js +0 -71
- package/dist/app/app/api/migrations/sync/route.js +0 -174
- package/dist/app/app/api/migrations/sync-files/route.js +0 -172
- package/dist/app/app/api/pull-data/confirm/route.js +0 -230
- package/dist/app/app/api/pull-remote/confirm/route.js +0 -278
- package/dist/app/app/api/pull-remote/preview/route.js +0 -144
- package/dist/app/app/api/push-remote/confirm/route.js +0 -196
- package/dist/app/app/api/push-remote/preview/route.js +0 -179
- package/dist/app/app/api/query/route.js +0 -168
- package/dist/app/app/api/tables/[name]/route.js +0 -174
- package/dist/app/app/api/tables/route.js +0 -178
- package/dist/app/app/api/update/route.js +0 -45
- package/dist/app/app/globals.css +0 -93
- package/dist/app/app/layout.jsx +0 -35
- package/dist/app/app/page.jsx +0 -34
- package/next.config.mjs +0 -18
- package/postcss.config.mjs +0 -8
- package/scripts/studio.js +0 -199
- package/scripts/test.js +0 -366
- package/src/app/api/cloudflare/route.js +0 -150
- package/src/app/api/databases/route.js +0 -71
- package/src/app/api/migrations/sync/route.js +0 -174
- package/src/app/api/migrations/sync-files/route.js +0 -172
- package/src/app/api/pull-data/confirm/route.js +0 -230
- package/src/app/api/pull-remote/confirm/route.js +0 -278
- package/src/app/api/pull-remote/preview/route.js +0 -144
- package/src/app/api/push-remote/confirm/route.js +0 -196
- package/src/app/api/push-remote/preview/route.js +0 -179
- package/src/app/api/query/route.js +0 -168
- package/src/app/api/tables/[name]/route.js +0 -174
- package/src/app/api/tables/route.js +0 -178
- package/src/app/api/update/route.js +0 -45
- package/src/app/globals.css +0 -93
- package/src/app/layout.jsx +0 -35
- package/src/app/page.jsx +0 -34
- package/src/components/cloudflare-credentials-modal.jsx +0 -94
- package/src/components/column-selector.jsx +0 -133
- package/src/components/column-sorting.jsx +0 -65
- package/src/components/delete-records-dialog.jsx +0 -64
- package/src/components/download-button.jsx +0 -205
- package/src/components/edit-error-alert.jsx +0 -30
- package/src/components/editable-cell.jsx +0 -163
- package/src/components/editable-row.jsx +0 -169
- package/src/components/environment-handler.jsx +0 -332
- package/src/components/environment-select.jsx +0 -62
- package/src/components/pull-preview-toast.jsx +0 -215
- package/src/components/push-error-alert.jsx +0 -72
- package/src/components/push-preview-toast.jsx +0 -183
- package/src/components/query-results.jsx +0 -112
- package/src/components/refresh-button.jsx +0 -61
- package/src/components/resize-columns.jsx +0 -101
- package/src/components/sidebar.jsx +0 -254
- package/src/components/sql-editor.jsx +0 -411
- package/src/components/sql-error-display.jsx +0 -167
- package/src/components/sync-migrations-button.jsx +0 -87
- package/src/components/table-error-dialog.jsx +0 -65
- package/src/components/table-toolbar.jsx +0 -285
- package/src/components/table-view.jsx +0 -843
- package/src/components/ui/alert.jsx +0 -47
- package/src/components/ui/button.jsx +0 -48
- package/src/components/ui/card.jsx +0 -50
- package/src/components/ui/checkbox.jsx +0 -24
- package/src/components/ui/collapsible.jsx +0 -11
- package/src/components/ui/dialog.jsx +0 -96
- package/src/components/ui/dropdown-menu.jsx +0 -158
- package/src/components/ui/input.jsx +0 -19
- package/src/components/ui/scroll-area.jsx +0 -40
- package/src/components/ui/select.jsx +0 -121
- package/src/components/ui/separator.jsx +0 -25
- package/src/components/ui/sheet.jsx +0 -109
- package/src/components/ui/sidebar.jsx +0 -620
- package/src/components/ui/skeleton.jsx +0 -14
- package/src/components/ui/table.jsx +0 -86
- package/src/components/ui/tabs.jsx +0 -43
- package/src/components/ui/toast.jsx +0 -86
- package/src/components/ui/toaster.jsx +0 -35
- package/src/components/ui/tooltip.jsx +0 -28
- package/src/components/update-banner.jsx +0 -93
- package/src/context/database-context.js +0 -510
- package/src/hooks/use-mobile.jsx +0 -19
- package/src/hooks/use-sql-error.ts +0 -23
- package/src/hooks/use-toast.js +0 -155
- package/src/lib/database-queue.js +0 -37
- package/src/lib/error.js +0 -20
- package/src/lib/find-wrangler-config.js +0 -74
- package/src/lib/license.js +0 -99
- package/src/lib/logger.js +0 -58
- package/src/lib/migrations.js +0 -415
- package/src/lib/parse-sql-error.js +0 -200
- package/src/lib/request-deduplication.js +0 -24
- package/src/lib/schema-operations.js +0 -106
- package/src/lib/sql-error-types.js +0 -14
- package/src/lib/sql-operations.js +0 -647
- package/src/lib/utils.js +0 -6
- package/src/lib/version-utils.js +0 -34
- /package/dist/.next/.next/static/{OUHnbB-64afrrZQL0Srn5 → FEsQ9jwPUQv5A3fwg6Opl}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{OUHnbB-64afrrZQL0Srn5 → FEsQ9jwPUQv5A3fwg6Opl}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{ZBTCAyp1kO5FdEHMU-Dw2 → Y9mYu4WBghepP5oT_3OdR}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{ZBTCAyp1kO5FdEHMU-Dw2 → Y9mYu4WBghepP5oT_3OdR}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{bHYW7fgIBDF8-Q33_WPoE → ae3gNmoSGm-R5LJC4UagI}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{bHYW7fgIBDF8-Q33_WPoE → ae3gNmoSGm-R5LJC4UagI}/_ssgManifest.js +0 -0
- /package/dist/.next/{static/ZBTCAyp1kO5FdEHMU-Dw2 → .next/static/bKfUJeuvAQlBmR3TjrfkH}/_buildManifest.js +0 -0
- /package/dist/.next/{static/ZBTCAyp1kO5FdEHMU-Dw2 → .next/static/bKfUJeuvAQlBmR3TjrfkH}/_ssgManifest.js +0 -0
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
|
-
import Editor from '@monaco-editor/react';
|
|
5
|
-
import { Loader2, Command, CornerDownLeft, GripHorizontal, ChevronDown } from 'lucide-react';
|
|
6
|
-
import { Button } from "@/components/ui/button";
|
|
7
|
-
import { useDatabase } from '@/context/database-context';
|
|
8
|
-
import { SQLResultsView, SQLErrorDisplay } from './query-results';
|
|
9
|
-
import {
|
|
10
|
-
DropdownMenu,
|
|
11
|
-
DropdownMenuContent,
|
|
12
|
-
DropdownMenuItem,
|
|
13
|
-
DropdownMenuTrigger,
|
|
14
|
-
} from "@/components/ui/dropdown-menu";
|
|
15
|
-
import { parseSQLError } from '@/lib/parse-sql-error';
|
|
16
|
-
|
|
17
|
-
// Helpful predefined queries
|
|
18
|
-
const HELPFUL_QUERIES = {
|
|
19
|
-
// Table listing queries
|
|
20
|
-
'Show Tables': `SELECT name
|
|
21
|
-
FROM sqlite_master
|
|
22
|
-
WHERE type='table'
|
|
23
|
-
AND name NOT LIKE 'sqlite_%';`,
|
|
24
|
-
|
|
25
|
-
// Schema queries
|
|
26
|
-
'Table Schema': `-- Table Schema
|
|
27
|
-
-- Replace table_name with your table name
|
|
28
|
-
PRAGMA table_info(table_name);`,
|
|
29
|
-
|
|
30
|
-
'Table Indexes': `-- Table Indexes
|
|
31
|
-
-- Replace table_name with your table name
|
|
32
|
-
SELECT
|
|
33
|
-
m.name as table_name,
|
|
34
|
-
i.name as index_name,
|
|
35
|
-
i.sql as index_definition
|
|
36
|
-
FROM sqlite_master m
|
|
37
|
-
JOIN sqlite_master i ON m.name = i.tbl_name
|
|
38
|
-
WHERE m.type = 'table'
|
|
39
|
-
AND i.type = 'index'
|
|
40
|
-
AND m.name = 'table_name';`,
|
|
41
|
-
|
|
42
|
-
'Foreign Keys': `-- Foreign Key Information
|
|
43
|
-
-- Replace table_name with your table name
|
|
44
|
-
PRAGMA foreign_key_list(table_name);`,
|
|
45
|
-
|
|
46
|
-
// Data queries
|
|
47
|
-
'Table Data': `-- Table Data
|
|
48
|
-
-- Replace table_name with your table name
|
|
49
|
-
SELECT * FROM table_name LIMIT 100;`,
|
|
50
|
-
|
|
51
|
-
'Row Count': `-- Row Count
|
|
52
|
-
-- Replace table_name with your table name
|
|
53
|
-
SELECT COUNT(*) as total_rows FROM table_name;`,
|
|
54
|
-
|
|
55
|
-
'Column Stats': `-- Column Statistics
|
|
56
|
-
-- Replace table_name and column_name with your values
|
|
57
|
-
SELECT
|
|
58
|
-
COUNT(*) as total_rows,
|
|
59
|
-
COUNT(column_name) as non_null_count,
|
|
60
|
-
COUNT(DISTINCT column_name) as unique_values,
|
|
61
|
-
MIN(column_name) as min_value,
|
|
62
|
-
MAX(column_name) as max_value
|
|
63
|
-
FROM table_name;`,
|
|
64
|
-
|
|
65
|
-
// Schema modification
|
|
66
|
-
'Create Table': `CREATE TABLE IF NOT EXISTS new_table (
|
|
67
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
68
|
-
name TEXT NOT NULL,
|
|
69
|
-
email TEXT UNIQUE,
|
|
70
|
-
status TEXT CHECK(status IN ('active', 'inactive')) DEFAULT 'active',
|
|
71
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
-- Create indexes
|
|
75
|
-
CREATE INDEX idx_new_table_name ON new_table(name);
|
|
76
|
-
CREATE UNIQUE INDEX idx_new_table_email ON new_table(email);`,
|
|
77
|
-
|
|
78
|
-
'Create View': `-- Create a view
|
|
79
|
-
CREATE VIEW view_name AS
|
|
80
|
-
SELECT column1, column2
|
|
81
|
-
FROM table_name
|
|
82
|
-
WHERE condition;`
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
// Query categories for organization
|
|
86
|
-
const QUERY_CATEGORIES = {
|
|
87
|
-
'Schema Information': ['Show Tables', 'Table Schema', 'Table Indexes', 'Foreign Keys'],
|
|
88
|
-
'Data Queries': ['Table Data', 'Row Count', 'Column Stats'],
|
|
89
|
-
'Schema Modification': ['Create Table', 'Create View']
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
function QueryTemplateMenu({ onSelectQuery }) {
|
|
93
|
-
return (
|
|
94
|
-
<DropdownMenu>
|
|
95
|
-
<DropdownMenuTrigger asChild>
|
|
96
|
-
<Button variant="outline" size="sm">
|
|
97
|
-
Query Templates
|
|
98
|
-
<ChevronDown className="ml-2 h-4 w-4" />
|
|
99
|
-
</Button>
|
|
100
|
-
</DropdownMenuTrigger>
|
|
101
|
-
<DropdownMenuContent align="start" className="w-72">
|
|
102
|
-
{Object.entries(QUERY_CATEGORIES).map(([category, queryNames]) => (
|
|
103
|
-
<React.Fragment key={category}>
|
|
104
|
-
<div className="px-2 py-1.5 text-sm font-semibold text-neutral-900 font-sans">
|
|
105
|
-
{category}
|
|
106
|
-
</div>
|
|
107
|
-
{queryNames.map((queryName) => (
|
|
108
|
-
<DropdownMenuItem
|
|
109
|
-
key={queryName}
|
|
110
|
-
onClick={() => onSelectQuery(queryName)}
|
|
111
|
-
className="font-sans text-neutral-800"
|
|
112
|
-
>
|
|
113
|
-
{queryName}
|
|
114
|
-
</DropdownMenuItem>
|
|
115
|
-
))}
|
|
116
|
-
</React.Fragment>
|
|
117
|
-
))}
|
|
118
|
-
</DropdownMenuContent>
|
|
119
|
-
</DropdownMenu>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function SQLEditor() {
|
|
124
|
-
const { executeQuery, refreshTables } = useDatabase();
|
|
125
|
-
const [queryResult, setQueryResult] = useState(null);
|
|
126
|
-
const [isExecuting, setIsExecuting] = useState(false);
|
|
127
|
-
const [editorHeight, setEditorHeight] = useState(300);
|
|
128
|
-
const [isResizing, setIsResizing] = useState(false);
|
|
129
|
-
const editorRef = useRef(null);
|
|
130
|
-
const panelRef = useRef(null);
|
|
131
|
-
|
|
132
|
-
// Update the height of the panel on editorHeight change
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
if (panelRef.current) {
|
|
135
|
-
panelRef.current.style.height = `${editorHeight}px`;
|
|
136
|
-
}
|
|
137
|
-
}, [editorHeight]);
|
|
138
|
-
|
|
139
|
-
// Resizing logic for editor
|
|
140
|
-
const startResizing = useCallback((mouseDownEvent) => {
|
|
141
|
-
mouseDownEvent.preventDefault();
|
|
142
|
-
|
|
143
|
-
const startHeight = editorHeight;
|
|
144
|
-
const startY = mouseDownEvent.pageY;
|
|
145
|
-
|
|
146
|
-
const onMouseMove = (mouseMoveEvent) => {
|
|
147
|
-
const currentY = mouseMoveEvent.pageY;
|
|
148
|
-
const newHeight = startHeight + (currentY - startY);
|
|
149
|
-
const minHeight = 100;
|
|
150
|
-
const maxHeight = window.innerHeight * 0.8;
|
|
151
|
-
|
|
152
|
-
setEditorHeight(Math.min(Math.max(newHeight, minHeight), maxHeight));
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const onMouseUp = () => {
|
|
156
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
157
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
document.addEventListener("mousemove", onMouseMove);
|
|
161
|
-
document.addEventListener("mouseup", onMouseUp);
|
|
162
|
-
}, [editorHeight]);
|
|
163
|
-
|
|
164
|
-
// Execute query and refresh tables
|
|
165
|
-
const executeQueryAndRefresh = async () => {
|
|
166
|
-
if (!editorRef.current) return;
|
|
167
|
-
|
|
168
|
-
const query = editorRef.current.getValue().trim().replace(/;+$/, '');
|
|
169
|
-
if (!query) {
|
|
170
|
-
setQueryResult({
|
|
171
|
-
success: false,
|
|
172
|
-
error: { message: "Query cannot be empty." },
|
|
173
|
-
});
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
setIsExecuting(true);
|
|
179
|
-
setQueryResult(null);
|
|
180
|
-
|
|
181
|
-
const data = await executeQuery(query);
|
|
182
|
-
const isSchemaModifying = /^(CREATE|DROP|ALTER)\s+TABLE/i.test(query);
|
|
183
|
-
if (isSchemaModifying) {
|
|
184
|
-
await refreshTables();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
let results = [];
|
|
188
|
-
|
|
189
|
-
// --- Updated extraction logic ---
|
|
190
|
-
if (data.results) {
|
|
191
|
-
if (Array.isArray(data.results)) {
|
|
192
|
-
// Check for the columns/values shape (typical for schema queries)
|
|
193
|
-
if (
|
|
194
|
-
data.results.length > 0 &&
|
|
195
|
-
data.results[0]?.columns &&
|
|
196
|
-
data.results[0]?.values
|
|
197
|
-
) {
|
|
198
|
-
const resultSet = data.results[0];
|
|
199
|
-
results = resultSet.values.map((row) =>
|
|
200
|
-
resultSet.columns.reduce((acc, col, idx) => {
|
|
201
|
-
acc[col] = row[idx];
|
|
202
|
-
return acc;
|
|
203
|
-
}, {})
|
|
204
|
-
);
|
|
205
|
-
} else {
|
|
206
|
-
// If we have one element with a "results" property, unwrap it.
|
|
207
|
-
if (
|
|
208
|
-
data.results.length === 1 &&
|
|
209
|
-
data.results[0].results &&
|
|
210
|
-
Array.isArray(data.results[0].results)
|
|
211
|
-
) {
|
|
212
|
-
results = data.results[0].results;
|
|
213
|
-
} else {
|
|
214
|
-
// Otherwise, assume data.results is already an array of row objects.
|
|
215
|
-
results = data.results;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
} else if (data.results.columns && data.results.values) {
|
|
219
|
-
const resultSet = data.results;
|
|
220
|
-
results = resultSet.values.map((row) =>
|
|
221
|
-
resultSet.columns.reduce((acc, col, idx) => {
|
|
222
|
-
acc[col] = row[idx];
|
|
223
|
-
return acc;
|
|
224
|
-
}, {})
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
} else if (data.result && data.result.results) {
|
|
228
|
-
if (Array.isArray(data.result.results)) {
|
|
229
|
-
if (
|
|
230
|
-
data.result.results.length > 0 &&
|
|
231
|
-
data.result.results[0]?.columns &&
|
|
232
|
-
data.result.results[0]?.values
|
|
233
|
-
) {
|
|
234
|
-
const resultSet = data.result.results[0];
|
|
235
|
-
results = resultSet.values.map((row) =>
|
|
236
|
-
resultSet.columns.reduce((acc, col, idx) => {
|
|
237
|
-
acc[col] = row[idx];
|
|
238
|
-
return acc;
|
|
239
|
-
}, {})
|
|
240
|
-
);
|
|
241
|
-
} else {
|
|
242
|
-
if (
|
|
243
|
-
data.result.results.length === 1 &&
|
|
244
|
-
data.result.results[0].results &&
|
|
245
|
-
Array.isArray(data.result.results[0].results)
|
|
246
|
-
) {
|
|
247
|
-
results = data.result.results[0].results;
|
|
248
|
-
} else {
|
|
249
|
-
results = data.result.results;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
} else if (data.result.results.columns && data.result.results.values) {
|
|
253
|
-
const resultSet = data.result.results;
|
|
254
|
-
results = resultSet.values.map((row) =>
|
|
255
|
-
resultSet.columns.reduce((acc, col, idx) => {
|
|
256
|
-
acc[col] = row[idx];
|
|
257
|
-
return acc;
|
|
258
|
-
}, {})
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
// --- End updated extraction logic ---
|
|
263
|
-
|
|
264
|
-
setQueryResult({
|
|
265
|
-
success: true,
|
|
266
|
-
results,
|
|
267
|
-
});
|
|
268
|
-
} catch (error) {
|
|
269
|
-
const parsedError = parseSQLError(error) || { message: 'An unknown error occurred', details: {} };
|
|
270
|
-
setQueryResult({
|
|
271
|
-
success: false,
|
|
272
|
-
error: parsedError,
|
|
273
|
-
});
|
|
274
|
-
} finally {
|
|
275
|
-
setIsExecuting(false);
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
const renderQueryResult = () => {
|
|
280
|
-
if (isExecuting) {
|
|
281
|
-
return (
|
|
282
|
-
<div className="flex items-center text-sm text-neutral-700">
|
|
283
|
-
<Loader2 className="h-4 w-4 animate-spin mr-2 font-sans" />
|
|
284
|
-
Running your query...
|
|
285
|
-
</div>
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (!queryResult) {
|
|
290
|
-
return <div className="text-sm text-neutral-500 font-sans">Run the query to see the results.</div>;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (!queryResult.success) {
|
|
294
|
-
console.debug("SQLEditor - Rendering error:", queryResult.error);
|
|
295
|
-
return <SQLErrorDisplay error={queryResult.error} />;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const results = queryResult.results;
|
|
299
|
-
if (!results || results.length === 0) {
|
|
300
|
-
return <div className="text-sm text-neutral-900 font-sans">Success. No results to display.</div>;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
return (
|
|
304
|
-
<SQLResultsView
|
|
305
|
-
query={editorRef.current?.getValue() || ''}
|
|
306
|
-
results={results}
|
|
307
|
-
/>
|
|
308
|
-
);
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return (
|
|
313
|
-
<div className="h-full flex flex-col bg-white text-neutral-900 font-sans">
|
|
314
|
-
{/* Toolbar */}
|
|
315
|
-
<div className="px-4 py-2 bg-neutral-100 border-b flex items-center gap-4">
|
|
316
|
-
<QueryTemplateMenu
|
|
317
|
-
onSelectQuery={(queryType) => {
|
|
318
|
-
if (editorRef.current) {
|
|
319
|
-
// Normalize the queryType to match HELPFUL_QUERIES keys
|
|
320
|
-
const formattedQueryType = Object.keys(HELPFUL_QUERIES).find(
|
|
321
|
-
(key) => key.toLowerCase() === queryType.toLowerCase()
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
if (formattedQueryType) {
|
|
325
|
-
const query = HELPFUL_QUERIES[formattedQueryType];
|
|
326
|
-
editorRef.current.setValue(query);
|
|
327
|
-
editorRef.current.focus();
|
|
328
|
-
} else {
|
|
329
|
-
console.warn(`Query template not found for: ${queryType}`);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}}
|
|
333
|
-
/>
|
|
334
|
-
</div>
|
|
335
|
-
|
|
336
|
-
{/* Query Editor */}
|
|
337
|
-
<div
|
|
338
|
-
ref={panelRef}
|
|
339
|
-
className="relative pt-2 overflow-hidden"
|
|
340
|
-
style={{ height: `${editorHeight}px`, minHeight: '100px' }}
|
|
341
|
-
>
|
|
342
|
-
<Editor
|
|
343
|
-
height="100%"
|
|
344
|
-
language="sql"
|
|
345
|
-
options={{
|
|
346
|
-
minimap: { enabled: false },
|
|
347
|
-
fontSize: 14,
|
|
348
|
-
wordWrap: "on",
|
|
349
|
-
automaticLayout: true,
|
|
350
|
-
lineNumbers: "on",
|
|
351
|
-
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
352
|
-
}}
|
|
353
|
-
onMount={(editor) => {
|
|
354
|
-
editorRef.current = editor;
|
|
355
|
-
// Ensure that the "monaco" global is available.
|
|
356
|
-
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
|
|
357
|
-
executeQueryAndRefresh();
|
|
358
|
-
});
|
|
359
|
-
}}
|
|
360
|
-
/>
|
|
361
|
-
</div>
|
|
362
|
-
|
|
363
|
-
{/* Resizer */}
|
|
364
|
-
<div
|
|
365
|
-
className={`relative h-0.5 cursor-row-resize bg-neutral-200 group ${
|
|
366
|
-
isResizing ? "bg-neutral-300" : "hover:bg-neutral-300"
|
|
367
|
-
}`}
|
|
368
|
-
onMouseDown={(e) => {
|
|
369
|
-
setIsResizing(true);
|
|
370
|
-
startResizing(e);
|
|
371
|
-
}}
|
|
372
|
-
onMouseUp={() => setIsResizing(false)}
|
|
373
|
-
>
|
|
374
|
-
<div
|
|
375
|
-
className={`absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-neutral-900 rounded-sm px-0.5
|
|
376
|
-
${isResizing ? "visible" : "invisible group-hover:visible"}`}
|
|
377
|
-
>
|
|
378
|
-
<GripHorizontal className="h-3 w-3 text-white" />
|
|
379
|
-
</div>
|
|
380
|
-
</div>
|
|
381
|
-
|
|
382
|
-
{/* Query Results */}
|
|
383
|
-
<div className="px-4 py-3 bg-neutral-100 border-b font-sans">
|
|
384
|
-
<div className="flex justify-between items-center">
|
|
385
|
-
<h3 className="text-sm font-medium">Results</h3>
|
|
386
|
-
<Button
|
|
387
|
-
size="sm"
|
|
388
|
-
onClick={executeQueryAndRefresh}
|
|
389
|
-
disabled={isExecuting}
|
|
390
|
-
className="flex items-center gap-1 text-sm font-medium"
|
|
391
|
-
>
|
|
392
|
-
Run
|
|
393
|
-
{isExecuting ? (
|
|
394
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
395
|
-
) : (
|
|
396
|
-
<>
|
|
397
|
-
<Command className="h-4 w-4" />
|
|
398
|
-
<CornerDownLeft className="h-4 w-4" />
|
|
399
|
-
</>
|
|
400
|
-
)}
|
|
401
|
-
</Button>
|
|
402
|
-
</div>
|
|
403
|
-
</div>
|
|
404
|
-
|
|
405
|
-
{/* Render Query Results */}
|
|
406
|
-
<div className="flex-1 overflow-auto p-4 bg-white">
|
|
407
|
-
{renderQueryResult()}
|
|
408
|
-
</div>
|
|
409
|
-
</div>
|
|
410
|
-
);
|
|
411
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
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 };
|
|
@@ -1,87 +0,0 @@
|
|
|
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;
|