d1s 0.2.10 → 0.2.12
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 +33 -33
- 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/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 +3 -3
- package/dist/.next/.next/server/app/index.rsc +5 -5
- package/dist/.next/.next/server/app/page.js +11 -13
- 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 +3 -3
- package/dist/.next/.next/server/chunks/226.js +12 -12
- package/dist/.next/.next/server/chunks/391.js +5 -5
- package/dist/.next/.next/server/chunks/452.js +1 -1
- package/dist/.next/.next/server/chunks/572.js +1 -0
- package/dist/.next/.next/server/chunks/627.js +3 -3
- package/dist/.next/.next/server/chunks/638.js +3 -3
- 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/pages/_app.js +1 -1
- package/dist/.next/.next/server/pages/_document.js +1 -1
- package/dist/.next/.next/server/pages/_error.js +1 -1
- package/dist/.next/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/.next/static/chunks/576-18a2209e1ed26aad.js +1 -0
- 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/{main-app-fa35024de9bd9284.js → main-app-4506e88db72db4b7.js} +1 -1
- package/dist/.next/.next/static/css/7c16f57d325d0d7d.css +3 -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/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 +32 -32
- 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 +3 -3
- package/dist/.next/server/app/index.rsc +5 -5
- package/dist/.next/server/app/page.js +11 -13
- 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 +2 -2
- package/dist/.next/server/chunks/226.js +12 -12
- package/dist/.next/server/chunks/391.js +5 -5
- package/dist/.next/server/chunks/452.js +1 -1
- package/dist/.next/server/chunks/572.js +1 -0
- package/dist/.next/server/chunks/627.js +3 -3
- package/dist/.next/server/chunks/638.js +3 -3
- 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/pages/_app.js +1 -1
- package/dist/.next/server/pages/_document.js +1 -1
- package/dist/.next/server/pages/_error.js +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-18a2209e1ed26aad.js +1 -0
- 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/7c16f57d325d0d7d.css +3 -0
- 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 -16
- 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/app/page.jsx +13 -23
- package/dist/d1-studio.js +34 -4
- 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/cache/webpack/server-production/2.pack +0 -0
- package/dist/.next/.next/server/chunks/90.js +0 -1
- package/dist/.next/.next/static/chunks/700-dc8f9f08b166c5e6.js +0 -1
- package/dist/.next/.next/static/chunks/app/page-16ec561fc8bebb5d.js +0 -1
- package/dist/.next/.next/static/css/0c512cea5f3d317a.css +0 -3
- package/dist/.next/server/chunks/90.js +0 -1
- package/dist/.next/static/chunks/700-dc8f9f08b166c5e6.js +0 -1
- package/dist/.next/static/chunks/app/page-16ec561fc8bebb5d.js +0 -1
- package/dist/.next/static/css/0c512cea5f3d317a.css +0 -3
- 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 -44
- package/next.config.mjs +0 -18
- package/postcss.config.mjs +0 -8
- package/scripts/studio.js +0 -169
- 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 -44
- 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/{5dBGGUmK5q7of4h5Rahrg → Y9mYu4WBghepP5oT_3OdR}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{5dBGGUmK5q7of4h5Rahrg → Y9mYu4WBghepP5oT_3OdR}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{PflNFnmFsNegSqhzjI6lA → ae3gNmoSGm-R5LJC4UagI}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{PflNFnmFsNegSqhzjI6lA → ae3gNmoSGm-R5LJC4UagI}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{p8875OZM4iDNsPzmoyLe7 → bKfUJeuvAQlBmR3TjrfkH}/_buildManifest.js +0 -0
- /package/dist/.next/.next/static/{p8875OZM4iDNsPzmoyLe7 → bKfUJeuvAQlBmR3TjrfkH}/_ssgManifest.js +0 -0
- /package/dist/.next/{static 2/5dBGGUmK5q7of4h5Rahrg → .next/static/ejYPqJ2kVicVp5EFWOZIC}/_buildManifest.js +0 -0
- /package/dist/.next/{static 2/5dBGGUmK5q7of4h5Rahrg → .next/static/ejYPqJ2kVicVp5EFWOZIC}/_ssgManifest.js +0 -0
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
// components/environemtn-handler.jsx
|
|
2
|
-
"use client";
|
|
3
|
-
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
import { useToast } from "@/hooks/use-toast";
|
|
6
|
-
import { useDatabase } from "@/context/database-context";
|
|
7
|
-
import PushPreviewToast from "./push-preview-toast";
|
|
8
|
-
import PullPreviewToast from "./pull-preview-toast";
|
|
9
|
-
|
|
10
|
-
const ErrorTypes = {
|
|
11
|
-
FOREIGN_KEY_ERROR: "FOREIGN_KEY_ERROR",
|
|
12
|
-
TABLE_EXISTS: "TABLE_EXISTS",
|
|
13
|
-
CONNECTION_ERROR: "CONNECTION_ERROR",
|
|
14
|
-
CONFIG_ERROR: "CONFIG_ERROR",
|
|
15
|
-
PULL_ERROR: "PULL_ERROR"
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export function useEnvironmentController() {
|
|
19
|
-
const [isConnecting, setIsConnecting] = useState(false);
|
|
20
|
-
const [isPushing, setIsPushing] = useState(false);
|
|
21
|
-
// New state for data pull status
|
|
22
|
-
const [isDataPulling, setIsDataPulling] = useState(false);
|
|
23
|
-
const [showPreview, setShowPreview] = useState(false);
|
|
24
|
-
const [previewData, setPreviewData] = useState(null);
|
|
25
|
-
const [previewError, setPreviewError] = useState(null);
|
|
26
|
-
const [previewType, setPreviewType] = useState(null);
|
|
27
|
-
const [previewSuccess, setPreviewSuccess] = useState(null);
|
|
28
|
-
const [environment, setEnvironment] = useState('local');
|
|
29
|
-
const { toast } = useToast();
|
|
30
|
-
const { refreshTables } = useDatabase();
|
|
31
|
-
|
|
32
|
-
const clearPreviewState = () => {
|
|
33
|
-
setShowPreview(false);
|
|
34
|
-
setPreviewData(null);
|
|
35
|
-
setPreviewError(null);
|
|
36
|
-
setPreviewType(null);
|
|
37
|
-
setPreviewSuccess(null);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Validate stored credentials
|
|
41
|
-
const validateStoredCredentials = async () => {
|
|
42
|
-
const storedCreds = localStorage.getItem("cf_credentials");
|
|
43
|
-
if (!storedCreds) return null;
|
|
44
|
-
try {
|
|
45
|
-
const credentials = JSON.parse(storedCreds);
|
|
46
|
-
const response = await fetch("/api/cloudflare", {
|
|
47
|
-
method: "POST",
|
|
48
|
-
headers: { "Content-Type": "application/json" },
|
|
49
|
-
body: JSON.stringify(credentials)
|
|
50
|
-
});
|
|
51
|
-
if (!response.ok) throw new Error("Invalid stored credentials");
|
|
52
|
-
const data = await response.json();
|
|
53
|
-
return { ...credentials, databaseId: data.database.id };
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error("Failed to validate stored credentials:", error);
|
|
56
|
-
localStorage.removeItem("cf_credentials");
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Push to remote preview
|
|
62
|
-
const pushToRemote = async () => {
|
|
63
|
-
try {
|
|
64
|
-
setPreviewType("push");
|
|
65
|
-
setShowPreview(true);
|
|
66
|
-
setIsPushing(true);
|
|
67
|
-
setPreviewError(null);
|
|
68
|
-
setPreviewSuccess(null);
|
|
69
|
-
setPreviewData({ preview: [] }); // show loading state
|
|
70
|
-
|
|
71
|
-
const credentials = await validateStoredCredentials();
|
|
72
|
-
if (!credentials) throw new Error('No valid credentials found');
|
|
73
|
-
|
|
74
|
-
const response = await fetch('/api/push-remote/preview', {
|
|
75
|
-
method: 'POST',
|
|
76
|
-
headers: { 'Content-Type': 'application/json' },
|
|
77
|
-
body: JSON.stringify(credentials)
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const data = await response.json();
|
|
81
|
-
if (!data.success) {
|
|
82
|
-
throw new Error(data.error?.message || 'Failed to generate preview');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
setPreviewData(data.details.details);
|
|
86
|
-
} catch (error) {
|
|
87
|
-
console.error('Push to remote preview failed:', error);
|
|
88
|
-
setPreviewError(error);
|
|
89
|
-
toast({
|
|
90
|
-
title: "Preview Failed",
|
|
91
|
-
description: error.message || 'Failed to generate preview',
|
|
92
|
-
variant: "destructive",
|
|
93
|
-
});
|
|
94
|
-
} finally {
|
|
95
|
-
setIsPushing(false);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// Update the confirmPush function:
|
|
100
|
-
const confirmPush = async () => {
|
|
101
|
-
try {
|
|
102
|
-
setIsPushing(true);
|
|
103
|
-
setPreviewError(null);
|
|
104
|
-
setPreviewSuccess(null);
|
|
105
|
-
|
|
106
|
-
const credentials = await validateStoredCredentials();
|
|
107
|
-
if (!credentials) throw new Error("No valid credentials found");
|
|
108
|
-
|
|
109
|
-
const response = await fetch("/api/push-remote/confirm", {
|
|
110
|
-
method: "POST",
|
|
111
|
-
headers: { "Content-Type": "application/json" },
|
|
112
|
-
body: JSON.stringify(credentials)
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const data = await response.json();
|
|
116
|
-
if (!data.success) {
|
|
117
|
-
throw new Error(data.error?.message || 'Failed to confirm push');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Update the preview data to show applied status
|
|
121
|
-
setPreviewData(prev => ({
|
|
122
|
-
...prev,
|
|
123
|
-
preview: prev.preview.map(item => ({
|
|
124
|
-
...item,
|
|
125
|
-
action: item.action === 'will be applied' ? 'applied' : item.action
|
|
126
|
-
}))
|
|
127
|
-
}));
|
|
128
|
-
|
|
129
|
-
setPreviewSuccess(`Applied ${data.details.applied} migration(s), skipped ${data.details.skipped}.`);
|
|
130
|
-
|
|
131
|
-
// Reset environment after success
|
|
132
|
-
setEnvironment('local');
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.error("Push to remote confirm failed:", error);
|
|
135
|
-
setPreviewError(error);
|
|
136
|
-
// Reset environment after error
|
|
137
|
-
setEnvironment('local');
|
|
138
|
-
} finally {
|
|
139
|
-
setIsPushing(false);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// Pull to remote preview
|
|
144
|
-
const pullToRemotePreview = async () => {
|
|
145
|
-
try {
|
|
146
|
-
setPreviewType("pull");
|
|
147
|
-
setShowPreview(true);
|
|
148
|
-
setIsPushing(true);
|
|
149
|
-
setPreviewError(null);
|
|
150
|
-
setPreviewSuccess(null);
|
|
151
|
-
setPreviewData({ preview: [] }); // show loading state
|
|
152
|
-
|
|
153
|
-
const credentials = await validateStoredCredentials();
|
|
154
|
-
if (!credentials) throw new Error("No valid credentials found");
|
|
155
|
-
|
|
156
|
-
const response = await fetch('/api/pull-remote/preview', {
|
|
157
|
-
method: 'POST',
|
|
158
|
-
headers: { 'Content-Type': 'application/json' },
|
|
159
|
-
body: JSON.stringify(credentials)
|
|
160
|
-
});
|
|
161
|
-
const data = await response.json();
|
|
162
|
-
if (!data.success) {
|
|
163
|
-
throw new Error(data.error?.message || 'Failed to generate pull preview');
|
|
164
|
-
}
|
|
165
|
-
setPreviewData(data.details);
|
|
166
|
-
} catch (error) {
|
|
167
|
-
console.error('Pull to remote preview failed:', error);
|
|
168
|
-
setPreviewError(error);
|
|
169
|
-
toast({
|
|
170
|
-
title: "Preview Failed",
|
|
171
|
-
description: error.message || 'Failed to generate pull preview',
|
|
172
|
-
variant: "destructive",
|
|
173
|
-
});
|
|
174
|
-
} finally {
|
|
175
|
-
setIsPushing(false);
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// In confirmPull function, add environment reset:
|
|
180
|
-
const confirmPull = async () => {
|
|
181
|
-
try {
|
|
182
|
-
setIsPushing(true);
|
|
183
|
-
setEnvironment('pull'); // Ensure correct state during pull
|
|
184
|
-
setPreviewError(null);
|
|
185
|
-
setPreviewSuccess(null);
|
|
186
|
-
|
|
187
|
-
const credentials = await validateStoredCredentials();
|
|
188
|
-
if (!credentials) throw new Error("No valid credentials found");
|
|
189
|
-
|
|
190
|
-
const response = await fetch("/api/pull-remote/confirm", {
|
|
191
|
-
method: "POST",
|
|
192
|
-
headers: { "Content-Type": "application/json" },
|
|
193
|
-
body: JSON.stringify(credentials)
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const data = await response.json();
|
|
197
|
-
if (!data.success) {
|
|
198
|
-
throw new Error(data.error?.message || 'Failed to confirm pull');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
setPreviewSuccess(`Pull migrations applied successfully.`);
|
|
202
|
-
|
|
203
|
-
setPreviewData(prev => ({
|
|
204
|
-
...prev,
|
|
205
|
-
preview: prev.preview.map(item => ({
|
|
206
|
-
...item,
|
|
207
|
-
action: item.action === 'will be applied' ? 'applied' : item.action
|
|
208
|
-
}))
|
|
209
|
-
}));
|
|
210
|
-
|
|
211
|
-
await refreshTables();
|
|
212
|
-
|
|
213
|
-
} catch (error) {
|
|
214
|
-
console.error("Pull to remote confirm failed:", error);
|
|
215
|
-
setPreviewError(error);
|
|
216
|
-
} finally {
|
|
217
|
-
setIsPushing(false);
|
|
218
|
-
setEnvironment('local'); // Reset to local regardless of success/failure
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// In confirmDataPull function, add syncing state:
|
|
223
|
-
const confirmDataPull = async () => {
|
|
224
|
-
try {
|
|
225
|
-
setIsDataPulling(true);
|
|
226
|
-
setEnvironment('syncing'); // Set environment to syncing during data pull
|
|
227
|
-
setPreviewError(null);
|
|
228
|
-
setPreviewSuccess(null);
|
|
229
|
-
|
|
230
|
-
const credentials = await validateStoredCredentials();
|
|
231
|
-
if (!credentials) throw new Error("No valid credentials found");
|
|
232
|
-
|
|
233
|
-
const response = await fetch("/api/pull-data/confirm", {
|
|
234
|
-
method: "POST",
|
|
235
|
-
headers: { "Content-Type": "application/json" },
|
|
236
|
-
body: JSON.stringify(credentials)
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const data = await response.json();
|
|
240
|
-
if (!data.success) {
|
|
241
|
-
throw new Error(data.error?.message || 'Failed to confirm data pull');
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
setPreviewSuccess("Remote data synced successfully.");
|
|
245
|
-
await refreshTables();
|
|
246
|
-
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error("Data pull confirm failed:", error);
|
|
249
|
-
setPreviewError(error);
|
|
250
|
-
} finally {
|
|
251
|
-
setIsDataPulling(false);
|
|
252
|
-
setEnvironment('local'); // Reset to local regardless of success/failure
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// Connect to Cloudflare
|
|
257
|
-
async function connectToCloudflare(credentials) {
|
|
258
|
-
try {
|
|
259
|
-
setIsConnecting(true);
|
|
260
|
-
const response = await fetch("/api/cloudflare", {
|
|
261
|
-
method: "POST",
|
|
262
|
-
headers: { "Content-Type": "application/json" },
|
|
263
|
-
body: JSON.stringify(credentials)
|
|
264
|
-
});
|
|
265
|
-
const data = await response.json();
|
|
266
|
-
if (!response.ok) throw new Error(data.error || "Failed to connect to Cloudflare");
|
|
267
|
-
localStorage.setItem("cf_credentials", JSON.stringify({
|
|
268
|
-
...credentials,
|
|
269
|
-
databaseId: data.database.id
|
|
270
|
-
}));
|
|
271
|
-
toast({
|
|
272
|
-
title: "Connected to Cloudflare",
|
|
273
|
-
description: `Connected to database: ${data.database.name}`,
|
|
274
|
-
variant: "default"
|
|
275
|
-
});
|
|
276
|
-
} catch (error) {
|
|
277
|
-
toast({
|
|
278
|
-
title: "Connection Failed",
|
|
279
|
-
description: error.message || "Failed to connect to Cloudflare",
|
|
280
|
-
variant: "destructive"
|
|
281
|
-
});
|
|
282
|
-
throw error;
|
|
283
|
-
} finally {
|
|
284
|
-
setIsConnecting(false);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Update PreviewUI to pass onDataPull and isDataPulling for pull previews.
|
|
289
|
-
const PreviewUI = showPreview && (
|
|
290
|
-
previewType === "pull" ? (
|
|
291
|
-
<PullPreviewToast
|
|
292
|
-
preview={previewData?.preview || []}
|
|
293
|
-
onConfirm={confirmPull}
|
|
294
|
-
onDataPull={confirmDataPull} // pass the new data pull handler
|
|
295
|
-
onCancel={clearPreviewState}
|
|
296
|
-
isConfirming={isPushing}
|
|
297
|
-
isDataPulling={isDataPulling}
|
|
298
|
-
error={previewError}
|
|
299
|
-
success={previewSuccess}
|
|
300
|
-
isLoading={isPushing && !previewData?.preview?.length}
|
|
301
|
-
/>
|
|
302
|
-
) : (
|
|
303
|
-
<PushPreviewToast
|
|
304
|
-
preview={previewData?.preview || []}
|
|
305
|
-
onConfirm={confirmPush}
|
|
306
|
-
onCancel={clearPreviewState}
|
|
307
|
-
isConfirming={isPushing}
|
|
308
|
-
error={previewError}
|
|
309
|
-
success={previewSuccess}
|
|
310
|
-
isLoading={isPushing && !previewData?.preview?.length}
|
|
311
|
-
/>
|
|
312
|
-
)
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
isConnecting,
|
|
317
|
-
isPushing,
|
|
318
|
-
isDataPulling,
|
|
319
|
-
showPreview,
|
|
320
|
-
previewError,
|
|
321
|
-
environment, // Add this
|
|
322
|
-
setEnvironment, // Add this if needed
|
|
323
|
-
pushToRemote,
|
|
324
|
-
pullToRemotePreview,
|
|
325
|
-
confirmPull,
|
|
326
|
-
confirmDataPull, // export the new function
|
|
327
|
-
connectToCloudflare,
|
|
328
|
-
validateStoredCredentials,
|
|
329
|
-
PreviewUI
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Select,
|
|
3
|
-
SelectContent,
|
|
4
|
-
SelectItem,
|
|
5
|
-
SelectTrigger,
|
|
6
|
-
SelectValue
|
|
7
|
-
} from '@/components/ui/select';
|
|
8
|
-
import { HardDrive, Download, Upload, Loader2 } from 'lucide-react';
|
|
9
|
-
|
|
10
|
-
export function EnvironmentSelect({
|
|
11
|
-
value,
|
|
12
|
-
onValueChange,
|
|
13
|
-
isLoading,
|
|
14
|
-
disabled,
|
|
15
|
-
showPreview
|
|
16
|
-
}) {
|
|
17
|
-
return (
|
|
18
|
-
<Select
|
|
19
|
-
value={value}
|
|
20
|
-
onValueChange={onValueChange}
|
|
21
|
-
disabled={disabled || isLoading || showPreview}
|
|
22
|
-
>
|
|
23
|
-
<SelectTrigger className="w-full bg-white border-neutral-200 font-medium">
|
|
24
|
-
<div className="flex items-center gap-1 text-sm">
|
|
25
|
-
{isLoading || showPreview ? (
|
|
26
|
-
<>
|
|
27
|
-
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
|
|
28
|
-
<span className="text-muted-foreground font-medium">
|
|
29
|
-
{value === "pull" ? "Pulling..." :
|
|
30
|
-
value === "syncing" ? "Syncing..." :
|
|
31
|
-
value === "production" ? "Pushing..." :
|
|
32
|
-
"Loading..."}
|
|
33
|
-
</span>
|
|
34
|
-
</>
|
|
35
|
-
) : (
|
|
36
|
-
<SelectValue placeholder="Environment" className="w-full" />
|
|
37
|
-
)}
|
|
38
|
-
</div>
|
|
39
|
-
</SelectTrigger>
|
|
40
|
-
<SelectContent>
|
|
41
|
-
<SelectItem value="local">
|
|
42
|
-
<div className="flex items-center gap-2">
|
|
43
|
-
<HardDrive className="h-4 w-4" />
|
|
44
|
-
<span>Local</span>
|
|
45
|
-
</div>
|
|
46
|
-
</SelectItem>
|
|
47
|
-
<SelectItem value="pull">
|
|
48
|
-
<div className="flex items-center gap-2">
|
|
49
|
-
<Download className="h-4 w-4" />
|
|
50
|
-
<span>Pull remote</span>
|
|
51
|
-
</div>
|
|
52
|
-
</SelectItem>
|
|
53
|
-
<SelectItem value="production">
|
|
54
|
-
<div className="flex items-center gap-2">
|
|
55
|
-
<Upload className="h-4 w-4" />
|
|
56
|
-
<span>Push remote</span>
|
|
57
|
-
</div>
|
|
58
|
-
</SelectItem>
|
|
59
|
-
</SelectContent>
|
|
60
|
-
</Select>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
// components/pull-preview-toast.jsx
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useState } from "react";
|
|
4
|
-
import { Button } from "@/components/ui/button";
|
|
5
|
-
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
6
|
-
import { FileText, Loader2, X } from "lucide-react";
|
|
7
|
-
import { cn } from "@/lib/utils";
|
|
8
|
-
|
|
9
|
-
export function PullPreviewToast({
|
|
10
|
-
preview = [],
|
|
11
|
-
onConfirm,
|
|
12
|
-
onCancel,
|
|
13
|
-
onDataPull,
|
|
14
|
-
isConfirming,
|
|
15
|
-
isDataPulling,
|
|
16
|
-
error,
|
|
17
|
-
isLoading,
|
|
18
|
-
success,
|
|
19
|
-
}) {
|
|
20
|
-
console.log("PullPreviewToast rendered with:", {
|
|
21
|
-
previewLength: preview.length,
|
|
22
|
-
isConfirming,
|
|
23
|
-
error,
|
|
24
|
-
isLoading,
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
console.log("PullPreviewToast mounted/updated");
|
|
29
|
-
return () => console.log("PullPreviewToast unmounted");
|
|
30
|
-
}, []);
|
|
31
|
-
|
|
32
|
-
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
|
|
33
|
-
|
|
34
|
-
// Loading state
|
|
35
|
-
if (isLoading) {
|
|
36
|
-
console.log("Rendering loading state");
|
|
37
|
-
return (
|
|
38
|
-
<div className="fixed bottom-4 right-4 z-50 font-sans w-[600px]">
|
|
39
|
-
<div className="rounded-lg border p-4 shadow-lg bg-background">
|
|
40
|
-
<div className="flex items-start gap-3">
|
|
41
|
-
<Loader2 className="h-5 w-5 text-neutral-600 shrink-0 mt-0.5 animate-spin" />
|
|
42
|
-
<div className="flex-1 space-y-3">
|
|
43
|
-
<div className="space-y-1">
|
|
44
|
-
<p className="font-medium text-neutral-800">
|
|
45
|
-
Preparing Pull Migration
|
|
46
|
-
</p>
|
|
47
|
-
<p className="text-sm text-neutral-600">
|
|
48
|
-
Checking remote migrations...
|
|
49
|
-
</p>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!preview?.length) {
|
|
59
|
-
console.log("No preview data available");
|
|
60
|
-
return (
|
|
61
|
-
<div className="fixed bottom-4 right-4 z-50 w-[600px]">
|
|
62
|
-
<div className="rounded-lg border bg-destructive/15 p-4">
|
|
63
|
-
<div className="flex items-center gap-2">
|
|
64
|
-
<p className="text-sm font-medium text-destructive">
|
|
65
|
-
No preview data available
|
|
66
|
-
</p>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Filter migrations to only include files with a ".sql" extension
|
|
74
|
-
const sqlMigrations = preview.filter((item) => {
|
|
75
|
-
const migrationName = item.migration || item.name || "";
|
|
76
|
-
return migrationName.endsWith(".sql");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Count only SQL migrations for the header
|
|
80
|
-
const totalMigrations = sqlMigrations.length;
|
|
81
|
-
console.log("Migration stats:", { totalMigrations });
|
|
82
|
-
|
|
83
|
-
// Determine if sync button should be enabled
|
|
84
|
-
// Only enable if pull was successful and not currently pulling data
|
|
85
|
-
const isSyncEnabled = success && !isDataPulling && !error;
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<div className="fixed bottom-4 right-4 z-50 font-sans w-[600px]">
|
|
89
|
-
<div
|
|
90
|
-
className={cn(
|
|
91
|
-
"rounded-lg border p-4 shadow-lg",
|
|
92
|
-
error ? "bg-destructive/15" : "bg-background"
|
|
93
|
-
)}
|
|
94
|
-
>
|
|
95
|
-
<div className="flex items-start gap-x-1">
|
|
96
|
-
<div className="flex-1 space-y-3">
|
|
97
|
-
{/* Header with Close Button */}
|
|
98
|
-
<div className="space-y-1">
|
|
99
|
-
<div className="flex items-center justify-between">
|
|
100
|
-
<h5
|
|
101
|
-
className={cn(
|
|
102
|
-
"font-medium",
|
|
103
|
-
error ? "text-destructive" : "text-neutral-900"
|
|
104
|
-
)}
|
|
105
|
-
>
|
|
106
|
-
{error ? "Pull Migration Error" : "Pull Migration Preview"}
|
|
107
|
-
</h5>
|
|
108
|
-
<button
|
|
109
|
-
onClick={onCancel}
|
|
110
|
-
className="text-neutral-500 hover:text-neutral-900 p-1 rounded-md hover:bg-neutral-100"
|
|
111
|
-
>
|
|
112
|
-
<X className="h-4 w-4" />
|
|
113
|
-
</button>
|
|
114
|
-
</div>
|
|
115
|
-
<p
|
|
116
|
-
className={cn(
|
|
117
|
-
"text-sm",
|
|
118
|
-
error ? "text-destructive/80" : "text-neutral-700"
|
|
119
|
-
)}
|
|
120
|
-
>
|
|
121
|
-
{`${totalMigrations} migration(s) will be applied`}
|
|
122
|
-
</p>
|
|
123
|
-
{error && (
|
|
124
|
-
<p className="text-sm text-destructive font-medium mt-1">
|
|
125
|
-
{error.message}
|
|
126
|
-
</p>
|
|
127
|
-
)}
|
|
128
|
-
{success && (
|
|
129
|
-
<p className="text-sm text-green-700 font-medium mt-1">
|
|
130
|
-
{success}
|
|
131
|
-
</p>
|
|
132
|
-
)}
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
{/* Migration Details */}
|
|
136
|
-
<div>
|
|
137
|
-
<button
|
|
138
|
-
onClick={() => setIsDetailsOpen(!isDetailsOpen)}
|
|
139
|
-
className="text-sm font-medium hover:underline"
|
|
140
|
-
>
|
|
141
|
-
{isDetailsOpen ? "Hide Details" : "Show Details"}
|
|
142
|
-
</button>
|
|
143
|
-
|
|
144
|
-
{isDetailsOpen && (
|
|
145
|
-
<ScrollArea className="h-[480px] mt-2 rounded border border-neutral-200">
|
|
146
|
-
<div className="w-full">
|
|
147
|
-
<div className="bg-neutral-50 border-b px-4 py-2">
|
|
148
|
-
<div className="text-sm font-medium text-neutral-600">Migration</div>
|
|
149
|
-
</div>
|
|
150
|
-
<div>
|
|
151
|
-
{sqlMigrations.map((item, index) => (
|
|
152
|
-
<div
|
|
153
|
-
key={index}
|
|
154
|
-
className="px-4 py-2 border-b last:border-0"
|
|
155
|
-
>
|
|
156
|
-
<div className="font-mono text-xs">
|
|
157
|
-
{item.migration || item.name}
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
))}
|
|
161
|
-
</div>
|
|
162
|
-
</div>
|
|
163
|
-
</ScrollArea>
|
|
164
|
-
)}
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
{/* Action Buttons */}
|
|
168
|
-
<div className="flex flex-col gap-2 pt-1">
|
|
169
|
-
<div className="flex gap-2">
|
|
170
|
-
<Button
|
|
171
|
-
onClick={onConfirm}
|
|
172
|
-
disabled={isConfirming}
|
|
173
|
-
className={`flex-1 ${isConfirming ? "cursor-not-allowed opacity-50" : ""}`}
|
|
174
|
-
>
|
|
175
|
-
{isConfirming ? (
|
|
176
|
-
<>
|
|
177
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
178
|
-
Confirming...
|
|
179
|
-
</>
|
|
180
|
-
) : (
|
|
181
|
-
"Confirm Pull"
|
|
182
|
-
)}
|
|
183
|
-
</Button>
|
|
184
|
-
|
|
185
|
-
{/* Right column - Sync data and description */}
|
|
186
|
-
<div className="flex-1 flex flex-col gap-2">
|
|
187
|
-
<Button
|
|
188
|
-
onClick={onDataPull}
|
|
189
|
-
disabled={!isSyncEnabled}
|
|
190
|
-
variant="outline"
|
|
191
|
-
className={`w-full ${!isSyncEnabled ? "cursor-not-allowed opacity-50" : ""}`}
|
|
192
|
-
>
|
|
193
|
-
{isDataPulling ? (
|
|
194
|
-
<>
|
|
195
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
196
|
-
Syncing remote data...
|
|
197
|
-
</>
|
|
198
|
-
) : (
|
|
199
|
-
"Sync remote data"
|
|
200
|
-
)}
|
|
201
|
-
</Button>
|
|
202
|
-
<p className="text-xs text-neutral-500 text-center">
|
|
203
|
-
75 records per table
|
|
204
|
-
</p>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
</div>
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export default PullPreviewToast;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
// components/push-error-alert.jsx
|
|
2
|
-
'use client';
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { AlertCircle, X, ChevronDown, ChevronUp } from 'lucide-react';
|
|
6
|
-
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
7
|
-
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
|
8
|
-
|
|
9
|
-
export const PushErrorAlert = ({ error, onDismiss }) => {
|
|
10
|
-
const [showSuggestions, setShowSuggestions] = React.useState(true);
|
|
11
|
-
|
|
12
|
-
if (!error) return null;
|
|
13
|
-
|
|
14
|
-
// Ensure error message is visible by scrolling to it
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (error) {
|
|
17
|
-
const alertElement = document.querySelector('.alert-push-error');
|
|
18
|
-
alertElement?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
19
|
-
}
|
|
20
|
-
}, [error]);
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Alert variant="destructive" className="mt-4 mb-4 alert-push-error">
|
|
24
|
-
<AlertCircle className="h-4 w-4" />
|
|
25
|
-
<AlertTitle className="flex items-center justify-between">
|
|
26
|
-
<span>{error.message}</span>
|
|
27
|
-
{onDismiss && (
|
|
28
|
-
<button
|
|
29
|
-
onClick={onDismiss}
|
|
30
|
-
className="p-1 hover:bg-destructive/10 rounded-full"
|
|
31
|
-
>
|
|
32
|
-
<X className="h-4 w-4" />
|
|
33
|
-
</button>
|
|
34
|
-
)}
|
|
35
|
-
</AlertTitle>
|
|
36
|
-
|
|
37
|
-
<AlertDescription className="mt-2">
|
|
38
|
-
<Collapsible
|
|
39
|
-
open={showSuggestions}
|
|
40
|
-
onOpenChange={setShowSuggestions}
|
|
41
|
-
className="space-y-2"
|
|
42
|
-
>
|
|
43
|
-
<CollapsibleTrigger className="flex items-center gap-2 text-sm font-medium">
|
|
44
|
-
{showSuggestions ? (
|
|
45
|
-
<ChevronUp className="h-4 w-4" />
|
|
46
|
-
) : (
|
|
47
|
-
<ChevronDown className="h-4 w-4" />
|
|
48
|
-
)}
|
|
49
|
-
Suggested Actions
|
|
50
|
-
</CollapsibleTrigger>
|
|
51
|
-
|
|
52
|
-
<CollapsibleContent className="space-y-2">
|
|
53
|
-
{error.details?.suggestions?.map((suggestion, index) => (
|
|
54
|
-
<div
|
|
55
|
-
key={index}
|
|
56
|
-
className="text-sm text-destructive-foreground/80 pl-6"
|
|
57
|
-
>
|
|
58
|
-
• {suggestion}
|
|
59
|
-
</div>
|
|
60
|
-
))}
|
|
61
|
-
</CollapsibleContent>
|
|
62
|
-
</Collapsible>
|
|
63
|
-
|
|
64
|
-
{error.details?.error && (
|
|
65
|
-
<div className="mt-4 text-sm font-mono bg-destructive/10 p-2 rounded">
|
|
66
|
-
{error.details.error}
|
|
67
|
-
</div>
|
|
68
|
-
)}
|
|
69
|
-
</AlertDescription>
|
|
70
|
-
</Alert>
|
|
71
|
-
);
|
|
72
|
-
};
|