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,647 +0,0 @@
|
|
|
1
|
-
// sql-operations.js
|
|
2
|
-
|
|
3
|
-
import { promisify } from 'util';
|
|
4
|
-
import { exec } from 'child_process';
|
|
5
|
-
import logger from '@/lib/logger';
|
|
6
|
-
|
|
7
|
-
const execAsync = promisify(exec);
|
|
8
|
-
|
|
9
|
-
// ---------------------------------------------------------------------
|
|
10
|
-
// Operation & Error Types (for schema changes and SQL execution)
|
|
11
|
-
// ---------------------------------------------------------------------
|
|
12
|
-
export const Operations = {
|
|
13
|
-
CREATE_TABLE: 'CREATE_TABLE',
|
|
14
|
-
ALTER_TABLE: 'ALTER_TABLE',
|
|
15
|
-
DROP_TABLE: 'DROP_TABLE',
|
|
16
|
-
CREATE_INDEX: 'CREATE_INDEX',
|
|
17
|
-
DROP_INDEX: 'DROP_INDEX',
|
|
18
|
-
DATA_MODIFICATION: 'DATA_MODIFICATION'
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const ErrorTypes = {
|
|
22
|
-
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
23
|
-
SYNTAX_ERROR: 'SYNTAX_ERROR',
|
|
24
|
-
EXECUTION_ERROR: 'EXECUTION_ERROR',
|
|
25
|
-
DEPENDENCY_ERROR: 'DEPENDENCY_ERROR'
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// ---------------------------------------------------------------------
|
|
29
|
-
// SQL Parsing and Validation
|
|
30
|
-
// ---------------------------------------------------------------------
|
|
31
|
-
|
|
32
|
-
export function isSchemaChange(statement) {
|
|
33
|
-
return statement.type !== Operations.DATA_MODIFICATION;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Enhanced parseStatement:
|
|
38
|
-
* Detects the type of SQL statement and, for ALTER TABLE, captures rename details.
|
|
39
|
-
*/
|
|
40
|
-
export function parseStatement(sql) {
|
|
41
|
-
const cleanSql = sql.trim().replace(/\s+/g, ' ');
|
|
42
|
-
const upperSql = cleanSql.toUpperCase();
|
|
43
|
-
|
|
44
|
-
if (upperSql.startsWith('CREATE TABLE')) {
|
|
45
|
-
// Optionally, you might want to capture column definitions here
|
|
46
|
-
return {
|
|
47
|
-
type: Operations.CREATE_TABLE,
|
|
48
|
-
tableName: extractTableName(cleanSql, 'CREATE TABLE'),
|
|
49
|
-
sql: cleanSql,
|
|
50
|
-
description: 'create-table'
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (upperSql.startsWith('ALTER TABLE')) {
|
|
55
|
-
const tableName = extractTableName(cleanSql, 'ALTER TABLE');
|
|
56
|
-
let description = '';
|
|
57
|
-
|
|
58
|
-
// Check for RENAME COLUMN operations first.
|
|
59
|
-
if (upperSql.includes('RENAME')) {
|
|
60
|
-
const renameMatch = cleanSql.match(/RENAME\s+(?:COLUMN\s+)?([\w$]+)\s+TO\s+([\w$]+)/i);
|
|
61
|
-
if (renameMatch) {
|
|
62
|
-
description = `rename-${renameMatch[1]}-to-${renameMatch[2]}`;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Check for ADD COLUMN operations.
|
|
66
|
-
else if (upperSql.includes('ADD COLUMN')) {
|
|
67
|
-
const addMatch = cleanSql.match(/ADD\s+COLUMN\s+([\w$]+)(\s+[\w()]+)?/i);
|
|
68
|
-
if (addMatch) {
|
|
69
|
-
// Capture column name and optionally the data type
|
|
70
|
-
const column = addMatch[1];
|
|
71
|
-
const dataType = addMatch[2] ? addMatch[2].trim().replace(/\s+/g, '-') : '';
|
|
72
|
-
description = dataType ? `add-${column}-${dataType}` : `add-${column}`;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Check for DROP COLUMN operations.
|
|
76
|
-
else if (upperSql.includes('DROP COLUMN')) {
|
|
77
|
-
const dropMatch = cleanSql.match(/DROP\s+COLUMN\s+([\w$]+)/i);
|
|
78
|
-
if (dropMatch) {
|
|
79
|
-
description = `drop-${dropMatch[1]}`;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Check for MODIFY COLUMN or CHANGE COLUMN operations.
|
|
83
|
-
else if (upperSql.includes('MODIFY COLUMN') || upperSql.includes('CHANGE COLUMN')) {
|
|
84
|
-
const modifyMatch = cleanSql.match(/(?:MODIFY|CHANGE)\s+COLUMN\s+([\w$]+)(\s+[\w()]+)?/i);
|
|
85
|
-
if (modifyMatch) {
|
|
86
|
-
const column = modifyMatch[1];
|
|
87
|
-
const newDefinition = modifyMatch[2] ? modifyMatch[2].trim().replace(/\s+/g, '-') : '';
|
|
88
|
-
description = newDefinition ? `modify-${column}-to-${newDefinition}` : `modify-${column}`;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
type: Operations.ALTER_TABLE,
|
|
94
|
-
tableName,
|
|
95
|
-
sql: cleanSql,
|
|
96
|
-
description // will be an empty string if none of the above matches
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (upperSql.startsWith('DROP TABLE')) {
|
|
101
|
-
return {
|
|
102
|
-
type: Operations.DROP_TABLE,
|
|
103
|
-
tableName: extractTableName(cleanSql, 'DROP TABLE'),
|
|
104
|
-
sql: cleanSql,
|
|
105
|
-
description: 'drop-table'
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (upperSql.startsWith('CREATE INDEX') || upperSql.startsWith('CREATE UNIQUE INDEX')) {
|
|
110
|
-
// Extract table name via the existing helper (if needed elsewhere)
|
|
111
|
-
const tableName = extractTableNameFromIndex(cleanSql);
|
|
112
|
-
// Extract the index name.
|
|
113
|
-
const indexMatch = cleanSql.match(/INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?([\w$]+)/i);
|
|
114
|
-
const indexName = indexMatch ? indexMatch[1] : '';
|
|
115
|
-
|
|
116
|
-
// For index migrations, simply use the index name as the description.
|
|
117
|
-
const description = indexName;
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
type: Operations.CREATE_INDEX,
|
|
121
|
-
tableName,
|
|
122
|
-
sql: cleanSql,
|
|
123
|
-
description // now simply the index name, e.g. "idx_technology_timestamp"
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (upperSql.startsWith('DROP INDEX')) {
|
|
129
|
-
const tableName = extractTableNameFromIndex(cleanSql);
|
|
130
|
-
const indexMatch = cleanSql.match(/DROP\s+INDEX\s+(?:IF\s+EXISTS\s+)?([\w$]+)/i);
|
|
131
|
-
const indexName = indexMatch ? indexMatch[1] : '';
|
|
132
|
-
return {
|
|
133
|
-
type: Operations.DROP_INDEX,
|
|
134
|
-
tableName,
|
|
135
|
-
sql: cleanSql,
|
|
136
|
-
description: indexName ? `drop-index-${indexName}` : 'drop-index'
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Default case: treat as data modification.
|
|
141
|
-
return {
|
|
142
|
-
type: Operations.DATA_MODIFICATION,
|
|
143
|
-
sql: cleanSql,
|
|
144
|
-
description: 'data-modification'
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function validateStatement(statement) {
|
|
149
|
-
if (statement.type !== Operations.DATA_MODIFICATION && !statement.tableName) {
|
|
150
|
-
throw {
|
|
151
|
-
type: ErrorTypes.VALIDATION_ERROR,
|
|
152
|
-
message: `Invalid SQL statement: unable to determine table name for "${statement.type}".`,
|
|
153
|
-
details: { sql: statement.sql }
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
return statement;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Helpers for extracting table names.
|
|
160
|
-
export function extractTableName(sql, prefix) {
|
|
161
|
-
const match = sql.match(new RegExp(`${prefix}\\s+(?:IF\\s+(?:NOT\\s+)?EXISTS\\s+)?([\\w_]+)`, 'i'));
|
|
162
|
-
return match ? match[1] : null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function extractTableNameFromIndex(sql) {
|
|
166
|
-
const match = sql.match(/ON\s+([\w_]+)/i);
|
|
167
|
-
return match ? match[1] : null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Improved helper to extract table name from migration filename.
|
|
172
|
-
* Handles patterns such as:
|
|
173
|
-
* - 0001_create-users-table.sql => table name: users
|
|
174
|
-
* - 0002_alter-orders-table.sql => table name: orders
|
|
175
|
-
* - 0003_create-index_orders.sql => table name: orders (for indexes)
|
|
176
|
-
*/
|
|
177
|
-
export async function extractTableNameFromMigration(filename) {
|
|
178
|
-
// Pattern 1: Matches filenames like "20250218072608_create-table_new_table.sql"
|
|
179
|
-
const createRegex1 = /^\d+_create[-_]table[_-](.+)\.sql$/i;
|
|
180
|
-
// Pattern 2: Matches filenames like "0001_create-books-table.sql"
|
|
181
|
-
const createRegex2 = /^\d+_create[-](.+)-table\.sql$/i;
|
|
182
|
-
|
|
183
|
-
// For alter migrations:
|
|
184
|
-
// Pattern 1: e.g., "20250218072608_alter-table_new_table_add-column_notes.sql"
|
|
185
|
-
const alterRegex1 = /^\d+_alter[-_]table[_-](.+?)(?:[_-].+)?\.sql$/i;
|
|
186
|
-
// Pattern 2: In case a similar alternate format exists.
|
|
187
|
-
const alterRegex2 = /^\d+_alter[-](.+?)-table(?:[_-].+)?\.sql$/i;
|
|
188
|
-
|
|
189
|
-
// Index migrations:
|
|
190
|
-
const indexRegex = /^\d+_create[-_]index[-_](.+)\.sql$/i;
|
|
191
|
-
|
|
192
|
-
let match = filename.match(createRegex1);
|
|
193
|
-
if (match) return match[1];
|
|
194
|
-
|
|
195
|
-
match = filename.match(createRegex2);
|
|
196
|
-
if (match) return match[1];
|
|
197
|
-
|
|
198
|
-
match = filename.match(alterRegex1);
|
|
199
|
-
if (match) return match[1];
|
|
200
|
-
|
|
201
|
-
match = filename.match(alterRegex2);
|
|
202
|
-
if (match) return match[1];
|
|
203
|
-
|
|
204
|
-
match = filename.match(indexRegex);
|
|
205
|
-
if (match) return match[1];
|
|
206
|
-
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function removeSQLComments(sql) {
|
|
211
|
-
return sql
|
|
212
|
-
.split('\n')
|
|
213
|
-
.filter(line => !line.trim().startsWith('--'))
|
|
214
|
-
.join('\n')
|
|
215
|
-
.trim();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Checks if a table already exists in the given database.
|
|
220
|
-
*
|
|
221
|
-
* @param {string} projectDir - The project directory.
|
|
222
|
-
* @param {string} databaseName - The D1 database name.
|
|
223
|
-
* @param {object} env - Environment variables.
|
|
224
|
-
* @param {string} tableName - The table name to check.
|
|
225
|
-
* @param {boolean} [remote=false] - Whether to check the remote database.
|
|
226
|
-
* @returns {Promise<boolean>} True if the table exists; otherwise, false.
|
|
227
|
-
*/
|
|
228
|
-
export async function tableExists(projectDir, databaseName, env, tableName, remote = false) {
|
|
229
|
-
// Query the sqlite_master table for the given table name.
|
|
230
|
-
const query = `SELECT name FROM sqlite_master WHERE type='table' AND name = '${tableName}' COLLATE NOCASE;`;
|
|
231
|
-
|
|
232
|
-
const result = await executeSQL(projectDir, databaseName, query, env, remote);
|
|
233
|
-
try {
|
|
234
|
-
const jsonStart = result.indexOf('[');
|
|
235
|
-
if (jsonStart !== -1) {
|
|
236
|
-
const jsonStr = result.substring(jsonStart);
|
|
237
|
-
const parsed = JSON.parse(jsonStr);
|
|
238
|
-
const results = parsed[0]?.results || [];
|
|
239
|
-
return results.length > 0;
|
|
240
|
-
}
|
|
241
|
-
return false;
|
|
242
|
-
} catch (e) {
|
|
243
|
-
console.error("Error parsing tableExists result:", e);
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Parse a full SQL query (multiple statements) into an array of parsed statement objects.
|
|
249
|
-
export function parseQuery(query) {
|
|
250
|
-
const noComments = query
|
|
251
|
-
.replace(/--.*$/gm, '')
|
|
252
|
-
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
253
|
-
.trim();
|
|
254
|
-
return noComments
|
|
255
|
-
.split(';')
|
|
256
|
-
.map(stmt => stmt.trim())
|
|
257
|
-
.filter(stmt => stmt.length > 0)
|
|
258
|
-
.map(stmt => parseStatement(stmt + ';'));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// ---------------------------------------------------------------------
|
|
262
|
-
// SQL Execution
|
|
263
|
-
// ---------------------------------------------------------------------
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Executes a SQL command via Wrangler.
|
|
267
|
-
* Supports both local and remote execution.
|
|
268
|
-
*/
|
|
269
|
-
export async function executeSQL(projectDir, databaseName, sql, env = {}, remote = false) {
|
|
270
|
-
try {
|
|
271
|
-
// Use let so we can modify the SQL if needed.
|
|
272
|
-
let cleanSQL = sql.trim().replace(/\s+/g, ' ');
|
|
273
|
-
const upperSQL = cleanSQL.toUpperCase();
|
|
274
|
-
|
|
275
|
-
// If it's an index creation and doesn't already have IF NOT EXISTS, add it.
|
|
276
|
-
if ((upperSQL.startsWith("CREATE INDEX") || upperSQL.startsWith("CREATE UNIQUE INDEX")) &&
|
|
277
|
-
!upperSQL.includes("IF NOT EXISTS")) {
|
|
278
|
-
if (upperSQL.startsWith("CREATE UNIQUE INDEX")) {
|
|
279
|
-
cleanSQL = cleanSQL.replace(/CREATE\s+UNIQUE\s+INDEX/i, "CREATE UNIQUE INDEX IF NOT EXISTS");
|
|
280
|
-
} else {
|
|
281
|
-
cleanSQL = cleanSQL.replace(/CREATE\s+INDEX/i, "CREATE INDEX IF NOT EXISTS");
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const isWindows = process.platform === 'win32';
|
|
286
|
-
const npxCommand = isWindows ? 'npx.cmd' : 'npx';
|
|
287
|
-
const executionFlag = remote ? '--remote' : '--local';
|
|
288
|
-
const command = `${npxCommand} wrangler d1 execute ${databaseName} ${executionFlag} --command="${cleanSQL.replace(/"/g, '\\"')}"`;
|
|
289
|
-
|
|
290
|
-
// Only log in development
|
|
291
|
-
if (logger.shouldLog('debug')) {
|
|
292
|
-
logger.debug('Executing command:', command);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const execOptions = {
|
|
296
|
-
cwd: projectDir,
|
|
297
|
-
env: { ...process.env, ...env },
|
|
298
|
-
maxBuffer: 1024 * 1024 * 10,
|
|
299
|
-
shell: true
|
|
300
|
-
};
|
|
301
|
-
// console.log('Executing command:', command);
|
|
302
|
-
const { stdout, stderr } = await execAsync(command, execOptions);
|
|
303
|
-
if (stderr && !stderr.includes('🌀')) {
|
|
304
|
-
throw new Error(stderr);
|
|
305
|
-
}
|
|
306
|
-
try {
|
|
307
|
-
const jsonStart = stdout.indexOf('[');
|
|
308
|
-
if (jsonStart !== -1) {
|
|
309
|
-
return stdout.substring(jsonStart);
|
|
310
|
-
}
|
|
311
|
-
} catch (parseError) {
|
|
312
|
-
console.warn('JSON parse warning:', parseError);
|
|
313
|
-
}
|
|
314
|
-
return stdout;
|
|
315
|
-
} catch (error) {
|
|
316
|
-
console.error('SQL Execution error:', error);
|
|
317
|
-
// Instead of creating a new error object, preserve the original error details
|
|
318
|
-
throw {
|
|
319
|
-
type: ErrorTypes.EXECUTION_ERROR,
|
|
320
|
-
message: 'Failed to execute SQL command',
|
|
321
|
-
details: {
|
|
322
|
-
command: error.cmd,
|
|
323
|
-
stderr: error.stderr,
|
|
324
|
-
stdout: error.stdout,
|
|
325
|
-
originalError: error.message,
|
|
326
|
-
suggestions: [
|
|
327
|
-
'Ensure Node.js and Wrangler are installed',
|
|
328
|
-
'Check npx in PATH',
|
|
329
|
-
'Verify the D1 database exists and is configured',
|
|
330
|
-
'Check wrangler.toml configuration'
|
|
331
|
-
]
|
|
332
|
-
}
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Fetches the latest `limit` records for a given table from the remote database.
|
|
339
|
-
*
|
|
340
|
-
* This implementation uses the executeSQL function with the remote flag enabled.
|
|
341
|
-
* It orders the results based on the provided ordering column. If no ordering column is provided,
|
|
342
|
-
* it falls back to the default "id" column.
|
|
343
|
-
*
|
|
344
|
-
* @param {string} projectDir - The project directory.
|
|
345
|
-
* @param {string} databaseName - The D1 database name.
|
|
346
|
-
* @param {string} tableName - The table to fetch records for.
|
|
347
|
-
* @param {object} env - Environment variables (including credentials).
|
|
348
|
-
* @param {number} limit - The number of records to fetch.
|
|
349
|
-
* @param {string} [orderingColumn="id"] - The column to order by.
|
|
350
|
-
* @returns {Promise<Array<object>>} Array of row objects.
|
|
351
|
-
*/
|
|
352
|
-
export async function fetchRemoteTableData(
|
|
353
|
-
projectDir,
|
|
354
|
-
databaseName,
|
|
355
|
-
tableName,
|
|
356
|
-
env,
|
|
357
|
-
limit,
|
|
358
|
-
orderingColumn = "id"
|
|
359
|
-
) {
|
|
360
|
-
// Use the provided ordering column; if not provided, default to "id".
|
|
361
|
-
const query = `SELECT * FROM "${tableName}" ORDER BY "${orderingColumn}" DESC LIMIT ${limit};`;
|
|
362
|
-
try {
|
|
363
|
-
// Execute the SQL command on the remote database.
|
|
364
|
-
const result = await executeSQL(projectDir, databaseName, query, env, true);
|
|
365
|
-
|
|
366
|
-
// ExecuteSQL returns stdout that should contain a JSON array starting from a '['.
|
|
367
|
-
const jsonStart = result.indexOf('[');
|
|
368
|
-
if (jsonStart === -1) {
|
|
369
|
-
throw new Error(`Unexpected result format: ${result}`);
|
|
370
|
-
}
|
|
371
|
-
const jsonStr = result.substring(jsonStart);
|
|
372
|
-
const parsed = JSON.parse(jsonStr);
|
|
373
|
-
// Assuming the structure: parsed[0].results contains the rows.
|
|
374
|
-
const rows = parsed[0]?.results || [];
|
|
375
|
-
return rows;
|
|
376
|
-
} catch (error) {
|
|
377
|
-
logger.error(`Error fetching remote data for table ${tableName}:`, error);
|
|
378
|
-
throw error;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Generates a bulk insert SQL statement for the specified table and rows.
|
|
384
|
-
*
|
|
385
|
-
* This function constructs a single INSERT statement that inserts multiple rows.
|
|
386
|
-
* It escapes single quotes in string values. You may need to extend this for
|
|
387
|
-
* additional data types (e.g., numbers, dates, booleans) or more complex structures.
|
|
388
|
-
*
|
|
389
|
-
* @param {string} tableName - The table to insert into.
|
|
390
|
-
* @param {Array<object>} rows - An array of objects, each representing a row.
|
|
391
|
-
* @returns {string} The bulk insert SQL statement.
|
|
392
|
-
*/
|
|
393
|
-
export function generateBulkInsertSQL(tableName, rows) {
|
|
394
|
-
if (!rows || rows.length === 0) return '';
|
|
395
|
-
|
|
396
|
-
// Get the list of columns from the first row object.
|
|
397
|
-
const columns = Object.keys(rows[0]);
|
|
398
|
-
const columnList = columns.map(col => `"${col}"`).join(', ');
|
|
399
|
-
|
|
400
|
-
// Build the values list for each row.
|
|
401
|
-
const valuesList = rows.map(row => {
|
|
402
|
-
const values = columns.map(col => {
|
|
403
|
-
const value = row[col];
|
|
404
|
-
if (value === null || value === undefined) return 'NULL';
|
|
405
|
-
// For simplicity, treat the value as a string.
|
|
406
|
-
return `'${String(value).replace(/'/g, "''")}'`;
|
|
407
|
-
}).join(', ');
|
|
408
|
-
return `(${values})`;
|
|
409
|
-
}).join(', ');
|
|
410
|
-
|
|
411
|
-
return `INSERT INTO "${tableName}" (${columnList}) VALUES ${valuesList};`;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// ---------------------------------------------------------------------
|
|
415
|
-
// SQL Formatting and Helper Functions
|
|
416
|
-
// ---------------------------------------------------------------------
|
|
417
|
-
|
|
418
|
-
export function formatSQLStatement(sql) {
|
|
419
|
-
const cleanSql = sql.trim();
|
|
420
|
-
const upperSql = cleanSql.toUpperCase();
|
|
421
|
-
if (upperSql.startsWith('CREATE TABLE')) return formatCreateTable(cleanSql);
|
|
422
|
-
if (upperSql.startsWith('CREATE INDEX') || upperSql.startsWith('CREATE UNIQUE INDEX'))
|
|
423
|
-
return formatCreateIndex(cleanSql);
|
|
424
|
-
if (upperSql.startsWith('ALTER TABLE')) return formatAlterTable(cleanSql);
|
|
425
|
-
if (upperSql.startsWith('DROP TABLE') || upperSql.startsWith('DROP INDEX'))
|
|
426
|
-
return formatDropStatement(cleanSql);
|
|
427
|
-
if (upperSql.startsWith('INSERT INTO')) return formatInsert(cleanSql);
|
|
428
|
-
if (upperSql.startsWith('UPDATE')) return formatUpdate(cleanSql);
|
|
429
|
-
if (upperSql.startsWith('DELETE FROM')) return formatDelete(cleanSql);
|
|
430
|
-
if (upperSql.startsWith('SELECT')) return formatSelect(cleanSql);
|
|
431
|
-
return cleanSql + ';';
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
export function formatCreateTable(sql) {
|
|
435
|
-
const match = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s*\(([\s\S]*)\)/i);
|
|
436
|
-
if (!match) return sql;
|
|
437
|
-
const [ , tableName, columnDefs ] = match;
|
|
438
|
-
const parts = splitSQLParts(columnDefs);
|
|
439
|
-
const definitions = parts.map(part => part.trim()).filter(Boolean);
|
|
440
|
-
return `CREATE TABLE ${tableName} (\n ${definitions.join(',\n ')}\n);`;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
export function formatDropStatement(sql) {
|
|
444
|
-
const match = sql.match(/DROP\s+(TABLE|INDEX)\s+(?:IF\s+EXISTS\s+)?(\w+)/i);
|
|
445
|
-
if (!match) return sql;
|
|
446
|
-
const [ , type, name ] = match;
|
|
447
|
-
return `DROP ${type} IF EXISTS ${name};`;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
export function formatCreateIndex(sql) {
|
|
451
|
-
const match = sql.match(/CREATE\s+(UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)\s+ON\s+(\w+)\s*\((.*)\)/i);
|
|
452
|
-
if (!match) return sql;
|
|
453
|
-
const [ , unique, indexName, tableName, columns ] = match;
|
|
454
|
-
const formattedColumns = columns.split(',').map(col => col.trim()).join(', ');
|
|
455
|
-
return `CREATE ${unique || ''}INDEX ${indexName} ON ${tableName} (${formattedColumns});`;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
export function formatAlterTable(sql) {
|
|
459
|
-
const match = sql.match(/ALTER\s+TABLE\s+(\w+)\s+(.*)/i);
|
|
460
|
-
if (!match) return sql;
|
|
461
|
-
const [ , tableName, alterations ] = match;
|
|
462
|
-
const parts = splitSQLParts(alterations);
|
|
463
|
-
if (parts.length === 1) return `ALTER TABLE ${tableName} ${parts[0]};`;
|
|
464
|
-
return `ALTER TABLE ${tableName}\n${parts.map((part, i) => ` ${part}${i < parts.length - 1 ? ',' : ';'}`).join('\n')}`;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
export function formatInsert(sql) {
|
|
468
|
-
const match = sql.match(/INSERT\s+INTO\s+(\w+)\s*(\([^)]+\))?\s*VALUES\s*(.+)/i);
|
|
469
|
-
if (!match) return sql;
|
|
470
|
-
const [ , table, columns, values ] = match;
|
|
471
|
-
const valueSets = splitSQLParts(values);
|
|
472
|
-
let formatted = `INSERT INTO ${table}${columns ? ` ${columns}` : ''}\nVALUES\n`;
|
|
473
|
-
formatted += valueSets.map((set, i) => ` ${set}${i < valueSets.length - 1 ? ',' : ';'}`).join('\n');
|
|
474
|
-
return formatted;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
export function formatUpdate(sql) {
|
|
478
|
-
const match = sql.match(/UPDATE\s+(\w+)\s+SET\s+(.+?)(?:\s+WHERE\s+(.+))?$/i);
|
|
479
|
-
if (!match) return sql;
|
|
480
|
-
const [ , table, sets, where ] = match;
|
|
481
|
-
const setClauses = splitSQLParts(sets);
|
|
482
|
-
let formatted = `UPDATE ${table}\nSET\n${setClauses.map(clause => ` ${clause.trim()}`).join(',\n')}`;
|
|
483
|
-
if (where) formatted += `\nWHERE\n ${where.trim()}`;
|
|
484
|
-
return formatted + ';';
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
export function formatDelete(sql) {
|
|
488
|
-
const match = sql.match(/DELETE\s+FROM\s+(\w+)(?:\s+WHERE\s+(.+))?$/i);
|
|
489
|
-
if (!match) return sql;
|
|
490
|
-
const [ , table, where ] = match;
|
|
491
|
-
let formatted = `DELETE FROM ${table}`;
|
|
492
|
-
if (where) formatted += `\nWHERE\n ${where.trim()}`;
|
|
493
|
-
return formatted + ';';
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
export function formatSelect(sql) {
|
|
497
|
-
const parts = sql.match(/SELECT\s+(.+?)\s+FROM\s+(.+?)(?:\s+WHERE\s+(.+?))?(?:\s+GROUP\s+BY\s+(.+?))?(?:\s+HAVING\s+(.+?))?(?:\s+ORDER\s+BY\s+(.+?))?(?:\s+LIMIT\s+(.+?))?$/i);
|
|
498
|
-
if (!parts) return sql;
|
|
499
|
-
const [ , columns, tables, where, groupBy, having, orderBy, limit ] = parts;
|
|
500
|
-
let formatted = `SELECT\n ${columns.split(',').map(c => c.trim()).join(',\n ')}\nFROM\n ${tables.trim()}`;
|
|
501
|
-
if (where) formatted += `\nWHERE\n ${where.trim()}`;
|
|
502
|
-
if (groupBy) formatted += `\nGROUP BY\n ${groupBy.trim()}`;
|
|
503
|
-
if (having) formatted += `\nHAVING\n ${having.trim()}`;
|
|
504
|
-
if (orderBy) formatted += `\nORDER BY\n ${orderBy.trim()}`;
|
|
505
|
-
if (limit) formatted += `\nLIMIT ${limit.trim()}`;
|
|
506
|
-
return formatted + ';';
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
export function splitSQLParts(sql) {
|
|
510
|
-
const parts = [];
|
|
511
|
-
let currentPart = '';
|
|
512
|
-
let parenCount = 0;
|
|
513
|
-
let inQuote = false;
|
|
514
|
-
let prevChar = '';
|
|
515
|
-
for (let char of sql) {
|
|
516
|
-
if (char === '"' && prevChar !== '\\') inQuote = !inQuote;
|
|
517
|
-
if (!inQuote) {
|
|
518
|
-
if (char === '(') parenCount++;
|
|
519
|
-
if (char === ')') parenCount--;
|
|
520
|
-
}
|
|
521
|
-
if (char === ',' && parenCount === 0 && !inQuote) {
|
|
522
|
-
parts.push(currentPart.trim());
|
|
523
|
-
currentPart = '';
|
|
524
|
-
} else {
|
|
525
|
-
currentPart += char;
|
|
526
|
-
}
|
|
527
|
-
prevChar = char;
|
|
528
|
-
}
|
|
529
|
-
if (currentPart.trim()) parts.push(currentPart.trim());
|
|
530
|
-
return parts;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Formats a full migration content by splitting statements and formatting each.
|
|
535
|
-
*/
|
|
536
|
-
export function formatMigrationContent(sql) {
|
|
537
|
-
const statements = sql.split(';').map(stmt => stmt.trim()).filter(stmt => stmt.length > 0);
|
|
538
|
-
return statements.map(stmt => formatSQLStatement(stmt)).join('\n\n') + '\n';
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Fetches the SQL content of a migration file from remote.
|
|
543
|
-
* This version does not use an extra dummy SELECT.
|
|
544
|
-
* It issues a harmless valid SQL statement (SELECT '' AS content;)
|
|
545
|
-
* alongside the migration directive, so that Wrangler executes the command.
|
|
546
|
-
*
|
|
547
|
-
* @param {string} projectDir - The project directory.
|
|
548
|
-
* @param {string} databaseName - The D1 database name.
|
|
549
|
-
* @param {string} filename - The migration filename.
|
|
550
|
-
* @param {object} env - Environment variables.
|
|
551
|
-
* @returns {Promise<string>} The migration file content.
|
|
552
|
-
*/
|
|
553
|
-
|
|
554
|
-
export async function getMigrationFileContent(projectDir, databaseName, migrationFile, env) {
|
|
555
|
-
try {
|
|
556
|
-
// Extract table name using improved helper
|
|
557
|
-
const tableName = await extractTableNameFromMigration(migrationFile);
|
|
558
|
-
let sql;
|
|
559
|
-
|
|
560
|
-
// For non-index migrations, try getting SQL from sqlite_master for table
|
|
561
|
-
if (tableName && !migrationFile.includes('create-index')) {
|
|
562
|
-
const result = await executeSQL(
|
|
563
|
-
projectDir,
|
|
564
|
-
databaseName,
|
|
565
|
-
`SELECT sql FROM sqlite_master WHERE type='table' AND name='${tableName}';`,
|
|
566
|
-
env,
|
|
567
|
-
true
|
|
568
|
-
);
|
|
569
|
-
|
|
570
|
-
try {
|
|
571
|
-
const parsed = JSON.parse(result);
|
|
572
|
-
sql = parsed[0]?.results?.[0]?.sql;
|
|
573
|
-
} catch (e) {
|
|
574
|
-
console.error('Error parsing sqlite_master result:', e);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// If we couldn't get the SQL from table and it's an index migration, try fetching via index name.
|
|
579
|
-
if (!sql && migrationFile.includes('create-index')) {
|
|
580
|
-
const indexMatch = migrationFile.match(/create-index[_-](.+)\.sql$/i);
|
|
581
|
-
if (indexMatch) {
|
|
582
|
-
let indexName = indexMatch[1]; // e.g. "idx_technology_timestamp-technology-timestamp"
|
|
583
|
-
let result = await executeSQL(
|
|
584
|
-
projectDir,
|
|
585
|
-
databaseName,
|
|
586
|
-
`SELECT sql FROM sqlite_master WHERE type='index' AND name='${indexName}' COLLATE NOCASE;`,
|
|
587
|
-
env,
|
|
588
|
-
true
|
|
589
|
-
);
|
|
590
|
-
let parsed = JSON.parse(result);
|
|
591
|
-
sql = parsed[0]?.results?.[0]?.sql;
|
|
592
|
-
// Fallback: if no result, try using only the part before the first hyphen.
|
|
593
|
-
if (!sql) {
|
|
594
|
-
const fallbackIndexName = indexName.split('-')[0]; // "idx_technology_timestamp"
|
|
595
|
-
result = await executeSQL(
|
|
596
|
-
projectDir,
|
|
597
|
-
databaseName,
|
|
598
|
-
`SELECT sql FROM sqlite_master WHERE type='index' AND name='${fallbackIndexName}' COLLATE NOCASE;`,
|
|
599
|
-
env,
|
|
600
|
-
true
|
|
601
|
-
);
|
|
602
|
-
parsed = JSON.parse(result);
|
|
603
|
-
sql = parsed[0]?.results?.[0]?.sql;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// If still no SQL and it's not an index migration, try a fallback query
|
|
609
|
-
if (!sql && tableName && !migrationFile.includes('create-index')) {
|
|
610
|
-
const result = await executeSQL(
|
|
611
|
-
projectDir,
|
|
612
|
-
databaseName,
|
|
613
|
-
`SELECT sql FROM sqlite_master WHERE name LIKE '%${tableName}%' LIMIT 1;`,
|
|
614
|
-
env,
|
|
615
|
-
true
|
|
616
|
-
);
|
|
617
|
-
try {
|
|
618
|
-
const parsed = JSON.parse(result);
|
|
619
|
-
sql = parsed[0]?.results?.[0]?.sql;
|
|
620
|
-
} catch (e) {
|
|
621
|
-
console.error('Error parsing fallback result:', e);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
if (!sql) {
|
|
626
|
-
throw new Error(`Could not retrieve SQL content for migration: ${migrationFile}`);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// Format and return the SQL
|
|
630
|
-
return sql + ';';
|
|
631
|
-
|
|
632
|
-
} catch (error) {
|
|
633
|
-
throw {
|
|
634
|
-
type: ErrorTypes.EXECUTION_ERROR,
|
|
635
|
-
message: `Failed to get migration file content: ${error.message}`,
|
|
636
|
-
details: {
|
|
637
|
-
file: migrationFile,
|
|
638
|
-
error: error.message,
|
|
639
|
-
suggestions: [
|
|
640
|
-
'Check if the table exists in the remote database',
|
|
641
|
-
'Verify the migration filename follows the expected pattern',
|
|
642
|
-
'Ensure you have permissions to access the remote database'
|
|
643
|
-
]
|
|
644
|
-
}
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
}
|
package/src/lib/utils.js
DELETED
package/src/lib/version-utils.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// lib/version-utils.js
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Compares semantic versions to determine if v2 is newer than v1
|
|
5
|
-
* @param {string} v1 - First version (e.g. "1.0.0")
|
|
6
|
-
* @param {string} v2 - Second version (e.g. "1.0.1")
|
|
7
|
-
* @returns {boolean} True if v2 is newer than v1
|
|
8
|
-
*/
|
|
9
|
-
export function isNewerVersion(v1, v2) {
|
|
10
|
-
if (!v1 || !v2) return false;
|
|
11
|
-
|
|
12
|
-
// Split versions by dots
|
|
13
|
-
const v1Parts = v1.split('.').map(Number);
|
|
14
|
-
const v2Parts = v2.split('.').map(Number);
|
|
15
|
-
|
|
16
|
-
// Compare major, minor, and patch versions
|
|
17
|
-
for (let i = 0; i < 3; i++) {
|
|
18
|
-
if (v2Parts[i] > v1Parts[i]) return true;
|
|
19
|
-
if (v2Parts[i] < v1Parts[i]) return false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// If we reach here, versions are equal
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Formats version strings for display by removing leading 'v' if present
|
|
28
|
-
* @param {string} version - The version string (e.g. "v1.0.0" or "1.0.0")
|
|
29
|
-
* @returns {string} Formatted version (e.g. "1.0.0")
|
|
30
|
-
*/
|
|
31
|
-
export function formatVersion(version) {
|
|
32
|
-
if (!version) return '';
|
|
33
|
-
return version.startsWith('v') ? version.substring(1) : version;
|
|
34
|
-
}
|
/package/dist/.next/.next/static/{OUHnbB-64afrrZQL0Srn5 → FEsQ9jwPUQv5A3fwg6Opl}/_buildManifest.js
RENAMED
|
File without changes
|
/package/dist/.next/.next/static/{OUHnbB-64afrrZQL0Srn5 → FEsQ9jwPUQv5A3fwg6Opl}/_ssgManifest.js
RENAMED
|
File without changes
|
/package/dist/.next/.next/static/{ZBTCAyp1kO5FdEHMU-Dw2 → Y9mYu4WBghepP5oT_3OdR}/_buildManifest.js
RENAMED
|
File without changes
|
/package/dist/.next/.next/static/{ZBTCAyp1kO5FdEHMU-Dw2 → Y9mYu4WBghepP5oT_3OdR}/_ssgManifest.js
RENAMED
|
File without changes
|
/package/dist/.next/.next/static/{bHYW7fgIBDF8-Q33_WPoE → ae3gNmoSGm-R5LJC4UagI}/_buildManifest.js
RENAMED
|
File without changes
|