d1s 0.2.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/dist/.next/.next/BUILD_ID +1 -1
- package/dist/.next/.next/app-build-manifest.json +121 -79
- package/dist/.next/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/.next/build-manifest.json +7 -7
- package/dist/.next/.next/cache/.rscinfo +1 -1
- package/dist/.next/.next/cache/.tsbuildinfo +1 -1
- package/dist/.next/.next/cache/webpack/client-development/0.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/1.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/index.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/client-development/index.pack.gz.old +0 -0
- package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
- package/dist/.next/.next/cache/webpack/client-production/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-development/0.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/1.pack.gz +0 -0
- package/dist/.next/.next/cache/webpack/server-development/index.pack.gz +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/react-loadable-manifest.json +11 -1
- package/dist/.next/.next/required-server-files.json +1 -1
- package/dist/.next/.next/routes-manifest.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 +5 -5
- package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +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.js.nft.json +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/list/route.js +26 -0
- package/dist/.next/.next/server/app/api/migrations/list/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/migrations/list/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
- 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 +4 -4
- package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/pro/route.js +1 -0
- package/dist/.next/.next/server/app/api/pro/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/pro/route_client-reference-manifest.js +1 -0
- 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.js.nft.json +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 +4 -4
- package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- 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 +6 -6
- package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
- 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 +6 -6
- package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
- 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 +9 -9
- package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/schema/route.js +1 -0
- package/dist/.next/.next/server/app/api/schema/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/schema/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/import/route.js +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/import/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/import/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/.next/server/app/api/time-travel/preview/route.js +1 -0
- package/dist/.next/.next/server/app/api/time-travel/preview/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/time-travel/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/time-travel/restore/route.js +1 -0
- package/dist/.next/.next/server/app/api/time-travel/restore/route.js.nft.json +1 -0
- package/dist/.next/.next/server/app/api/time-travel/restore/route_client-reference-manifest.js +1 -0
- package/dist/.next/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/.next/server/app/api/update/route.js.nft.json +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 +5 -3
- package/dist/.next/.next/server/app/index.rsc +6 -6
- package/dist/.next/.next/server/app/page.js +15 -15
- 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 +10 -4
- 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/452.js +1 -1
- package/dist/.next/.next/server/chunks/487.js +1 -0
- package/dist/.next/.next/server/chunks/572.js +1 -1
- package/dist/.next/.next/server/chunks/992.js +3 -3
- package/dist/.next/{server/chunks/638.js → .next/server/chunks/994.js} +3 -3
- package/dist/.next/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/.next/server/middleware-react-loadable-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-manifest.json +1 -1
- package/dist/.next/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/.next/static/-OO4tE7EKr8o62Bne-ODo/_buildManifest.js +1 -0
- package/dist/.next/.next/static/3kAeIJC56X7aw1Fk5_OXO/_buildManifest.js +1 -0
- package/dist/.next/.next/static/J8r9W6xxmYYvuKehItNuW/_buildManifest.js +1 -0
- package/dist/.next/.next/static/arc9h7hbaQzL1Dl0iuVrT/_buildManifest.js +1 -0
- package/dist/.next/.next/static/chunks/1a258343.3b3e7ba5ba0bd0d2.js +1 -0
- package/dist/.next/.next/static/chunks/345.8fc37569d5708622.js +1 -0
- package/dist/.next/.next/static/chunks/480-85b6c8ae3f51b156.js +1 -0
- package/dist/.next/.next/static/chunks/52.2cdc9bdb75e1fc2e.js +1 -0
- package/dist/.next/.next/static/chunks/803-a2fcfbd00e6b3b38.js +1 -0
- package/dist/.next/.next/static/chunks/{92-5f7522943fcb72a8.js → 92-a84bdac2be7c8d7a.js} +1 -1
- package/dist/.next/.next/static/chunks/app/api/cloudflare/route-d0c1dc2a9e7dce36.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/databases/route-cd322321212797cf.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/list/route-cd710ff75b6bcd02.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-ee522f232b9f0a9c.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-79ee2c26f87d3bc7.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pro/route-c90c1f901fc00d38.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-data/confirm/route-118764086af798f8.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-2b0ade4ebfcea0bc.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-342db7ea13e6f447.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-b778c053bd515abd.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-ab090482f299f57f.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/query/route-4d21a8b1d34491f1.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/schema/route-cb17a387d6b557ad.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/[name]/import/route-510472de7a5c29bd.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-6a1fa95c303ce0de.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/tables/route-daa975df4ea8e8f8.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/time-travel/preview/route-5787d7e8f17bd539.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/time-travel/restore/route-84b64a27e831e21c.js +1 -0
- package/dist/.next/.next/static/chunks/app/api/update/route-54ee900537982652.js +1 -0
- package/dist/.next/.next/static/chunks/app/{layout-40ec07d04681ba81.js → layout-f0ec4d636ee0f763.js} +1 -1
- package/dist/.next/.next/static/chunks/app/page-358bf2112802ff85.js +1 -0
- package/dist/.next/.next/static/chunks/webpack-024900a94af4f0a7.js +1 -0
- package/dist/.next/.next/static/css/2c165a0ede9b2442.css +3 -0
- package/dist/.next/.next/static/css/32df9a4d493f8b0f.css +31 -0
- package/dist/.next/.next/static/fiesjBWbrmSSyLf4biwrX/_buildManifest.js +1 -0
- package/dist/.next/.next/static/ft39e6W6vSgUL7peRo7pE/_buildManifest.js +1 -0
- package/dist/.next/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/.next/.next/static/u7ssdTycF4iQ-w-pQZhxg/_buildManifest.js +1 -0
- package/dist/.next/.next/trace +3 -3
- package/dist/.next/.next/types/app/api/migrations/list/route.ts +347 -0
- package/dist/.next/.next/types/app/api/pro/route.ts +347 -0
- package/dist/.next/.next/types/app/api/schema/route.ts +347 -0
- package/dist/.next/.next/types/app/api/tables/[name]/import/route.ts +347 -0
- package/dist/.next/.next/types/app/api/time-travel/preview/route.ts +347 -0
- package/dist/.next/.next/types/app/api/time-travel/restore/route.ts +347 -0
- package/dist/.next/BUILD_ID +1 -1
- package/dist/.next/app-build-manifest.json +122 -80
- package/dist/.next/app-path-routes-manifest.json +1 -1
- package/dist/.next/build-manifest.json +7 -7
- 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/index.pack +0 -0
- package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/dist/.next/cache/webpack/server-production/0.pack +0 -0
- package/dist/.next/cache/webpack/server-production/index.pack +0 -0
- package/dist/.next/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/react-loadable-manifest.json +11 -1
- package/dist/.next/required-server-files.json +1 -1
- package/dist/.next/routes-manifest.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 +5 -5
- package/dist/.next/server/app/api/cloudflare/route.js +1 -1
- package/dist/.next/server/app/api/cloudflare/route.js.nft.json +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.js.nft.json +1 -1
- package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/migrations/list/route.js +26 -0
- package/dist/.next/server/app/api/migrations/list/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/migrations/list/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/migrations/sync/route.js +5 -5
- package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
- 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 +4 -4
- package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/pro/route.js +1 -0
- package/dist/.next/server/app/api/pro/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/pro/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -1
- package/dist/.next/server/app/api/pull-data/confirm/route.js.nft.json +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 +4 -4
- package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- 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 +6 -6
- package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
- 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 +6 -6
- package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
- 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 +9 -9
- package/dist/.next/server/app/api/query/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/schema/route.js +1 -0
- package/dist/.next/server/app/api/schema/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/schema/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/tables/[name]/import/route.js +1 -0
- package/dist/.next/server/app/api/tables/[name]/import/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/tables/[name]/import/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/tables/[name]/route.js +5 -5
- package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
- 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.js.nft.json +1 -1
- package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/api/time-travel/preview/route.js +1 -0
- package/dist/.next/server/app/api/time-travel/preview/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/time-travel/preview/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/time-travel/restore/route.js +1 -0
- package/dist/.next/server/app/api/time-travel/restore/route.js.nft.json +1 -0
- package/dist/.next/server/app/api/time-travel/restore/route_client-reference-manifest.js +1 -0
- package/dist/.next/server/app/api/update/route.js +1 -1
- package/dist/.next/server/app/api/update/route.js.nft.json +1 -1
- package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/.next/server/app/index.html +5 -3
- package/dist/.next/server/app/index.rsc +6 -6
- package/dist/.next/server/app/page.js +15 -15
- 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 +11 -5
- package/dist/.next/server/chunks/226.js +12 -12
- package/dist/.next/server/chunks/391.js +1 -1
- package/dist/.next/server/chunks/452.js +1 -1
- package/dist/.next/server/chunks/487.js +1 -0
- package/dist/.next/server/chunks/572.js +1 -1
- package/dist/.next/server/chunks/992.js +3 -3
- package/dist/.next/{.next/server/chunks/638.js → server/chunks/994.js} +3 -3
- package/dist/.next/server/middleware-build-manifest.js +1 -1
- package/dist/.next/server/middleware-react-loadable-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-manifest.json +1 -1
- package/dist/.next/server/server-reference-manifest.json +1 -1
- package/dist/.next/static/chunks/1a258343.3b3e7ba5ba0bd0d2.js +1 -0
- package/dist/.next/static/chunks/345.8fc37569d5708622.js +1 -0
- package/dist/.next/static/chunks/480-85b6c8ae3f51b156.js +1 -0
- package/dist/.next/static/chunks/52.2cdc9bdb75e1fc2e.js +1 -0
- package/dist/.next/static/chunks/803-a2fcfbd00e6b3b38.js +1 -0
- package/dist/.next/static/chunks/{92-5f7522943fcb72a8.js → 92-a84bdac2be7c8d7a.js} +1 -1
- package/dist/.next/static/chunks/app/api/cloudflare/route-d0c1dc2a9e7dce36.js +1 -0
- package/dist/.next/static/chunks/app/api/databases/route-cd322321212797cf.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/list/route-cd710ff75b6bcd02.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/sync/route-ee522f232b9f0a9c.js +1 -0
- package/dist/.next/static/chunks/app/api/migrations/sync-files/route-79ee2c26f87d3bc7.js +1 -0
- package/dist/.next/static/chunks/app/api/pro/route-c90c1f901fc00d38.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-data/confirm/route-118764086af798f8.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-2b0ade4ebfcea0bc.js +1 -0
- package/dist/.next/static/chunks/app/api/pull-remote/preview/route-342db7ea13e6f447.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/confirm/route-b778c053bd515abd.js +1 -0
- package/dist/.next/static/chunks/app/api/push-remote/preview/route-ab090482f299f57f.js +1 -0
- package/dist/.next/static/chunks/app/api/query/route-4d21a8b1d34491f1.js +1 -0
- package/dist/.next/static/chunks/app/api/schema/route-cb17a387d6b557ad.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/[name]/import/route-510472de7a5c29bd.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/[name]/route-6a1fa95c303ce0de.js +1 -0
- package/dist/.next/static/chunks/app/api/tables/route-daa975df4ea8e8f8.js +1 -0
- package/dist/.next/static/chunks/app/api/time-travel/preview/route-5787d7e8f17bd539.js +1 -0
- package/dist/.next/static/chunks/app/api/time-travel/restore/route-84b64a27e831e21c.js +1 -0
- package/dist/.next/static/chunks/app/api/update/route-54ee900537982652.js +1 -0
- package/dist/.next/static/chunks/app/{layout-40ec07d04681ba81.js → layout-f0ec4d636ee0f763.js} +1 -1
- package/dist/.next/static/chunks/app/page-358bf2112802ff85.js +1 -0
- package/dist/.next/static/chunks/webpack-024900a94af4f0a7.js +1 -0
- package/dist/.next/static/css/2c165a0ede9b2442.css +3 -0
- package/dist/.next/static/css/32df9a4d493f8b0f.css +31 -0
- package/dist/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/.next/static/zh4Fz2tbm8GRka4woRrGp/_buildManifest.js +1 -0
- package/dist/.next/trace +18 -3
- package/dist/.next/types/app/api/migrations/list/route.ts +347 -0
- package/dist/.next/types/app/api/pro/route.ts +347 -0
- package/dist/.next/types/app/api/schema/route.ts +347 -0
- package/dist/.next/types/app/api/tables/[name]/import/route.ts +347 -0
- package/dist/.next/types/app/api/time-travel/preview/route.ts +347 -0
- package/dist/.next/types/app/api/time-travel/restore/route.ts +347 -0
- package/dist/app/api/databases/route.js +2 -1
- package/dist/app/api/migrations/list/route.js +137 -0
- package/dist/app/api/migrations/sync-files/route.js +2 -1
- package/dist/app/api/pro/route.js +7 -0
- package/dist/app/api/pull-remote/confirm/route.js +138 -146
- package/dist/app/api/pull-remote/preview/route.js +49 -84
- package/dist/app/api/push-remote/confirm/route.js +31 -12
- package/dist/app/api/push-remote/preview/route.js +27 -12
- package/dist/app/api/query/route.js +24 -13
- package/dist/app/api/schema/route.js +63 -0
- package/dist/app/api/tables/[name]/import/route.js +112 -0
- package/dist/app/api/tables/[name]/route.js +38 -29
- package/dist/app/api/tables/route.js +29 -16
- package/dist/app/api/time-travel/preview/route.js +122 -0
- package/dist/app/api/time-travel/restore/route.js +106 -0
- package/dist/app/page.jsx +26 -8
- package/dist/d1-studio.js +129 -23
- package/dist/lib/license.js +99 -71
- package/dist/lib/local-db.js +223 -0
- package/dist/lib/migrations.js +40 -2
- package/dist/lib/parse-sql-error.js +99 -160
- package/dist/lib/sql-operations.js +28 -10
- package/dist/lib/telemetry.js +39 -0
- package/package.json +6 -2
- 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/static/FEsQ9jwPUQv5A3fwg6Opl/_buildManifest.js +0 -1
- package/dist/.next/.next/static/Y9mYu4WBghepP5oT_3OdR/_buildManifest.js +0 -1
- package/dist/.next/.next/static/ae3gNmoSGm-R5LJC4UagI/_buildManifest.js +0 -1
- package/dist/.next/.next/static/bKfUJeuvAQlBmR3TjrfkH/_buildManifest.js +0 -1
- package/dist/.next/.next/static/chunks/576-18a2209e1ed26aad.js +0 -1
- package/dist/.next/.next/static/chunks/735-b885dfec6353171d.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +0 -1
- package/dist/.next/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +0 -1
- package/dist/.next/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +0 -1
- package/dist/.next/.next/static/chunks/app/page-f2bc307c0d8acdaa.js +0 -1
- package/dist/.next/.next/static/chunks/webpack-c76ac1e586b2802a.js +0 -1
- package/dist/.next/.next/static/css/7c16f57d325d0d7d.css +0 -3
- package/dist/.next/.next/static/ejYPqJ2kVicVp5EFWOZIC/_buildManifest.js +0 -1
- package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_buildManifest.js +0 -1
- package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_buildManifest.js +0 -1
- package/dist/.next/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/.next/.next/static/thaCy2qVeNqYYhdayr13C/_buildManifest.js +0 -1
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_buildManifest.js +0 -1
- package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_ssgManifest.js +0 -1
- 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.old +0 -0
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_buildManifest.js +0 -1
- package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_ssgManifest.js +0 -1
- package/dist/.next/static/chunks/576-18a2209e1ed26aad.js +0 -1
- package/dist/.next/static/chunks/735-b885dfec6353171d.js +0 -1
- package/dist/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +0 -1
- package/dist/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +0 -1
- package/dist/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +0 -1
- package/dist/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +0 -1
- package/dist/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +0 -1
- package/dist/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +0 -1
- package/dist/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +0 -1
- package/dist/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +0 -1
- package/dist/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +0 -1
- package/dist/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +0 -1
- package/dist/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +0 -1
- package/dist/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +0 -1
- package/dist/.next/static/chunks/webpack-c76ac1e586b2802a.js +0 -1
- package/dist/.next/static/css/7c16f57d325d0d7d.css +0 -3
- package/dist/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- /package/dist/.next/.next/static/{FEsQ9jwPUQv5A3fwg6Opl → -OO4tE7EKr8o62Bne-ODo}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{Y9mYu4WBghepP5oT_3OdR → 3kAeIJC56X7aw1Fk5_OXO}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{ae3gNmoSGm-R5LJC4UagI → J8r9W6xxmYYvuKehItNuW}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{bKfUJeuvAQlBmR3TjrfkH → arc9h7hbaQzL1Dl0iuVrT}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/chunks/{4bd1b696-8c908eb707f85a27.js → 4bd1b696-124ea104c06f6cea.js} +0 -0
- /package/dist/.next/.next/static/chunks/{517-3b698a5d3da06ff7.js → 517-c876ce2f00030cd0.js} +0 -0
- /package/dist/.next/.next/static/chunks/{692-ede418e1d28a1394.js → 692-9e59d546afd11ec3.js} +0 -0
- /package/dist/.next/.next/static/chunks/app/_not-found/{page-b786c3dd79ad15a5.js → page-3e24b81707d98126.js} +0 -0
- /package/dist/.next/.next/static/{ejYPqJ2kVicVp5EFWOZIC → fiesjBWbrmSSyLf4biwrX}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{gABGrAoO8IPArDo_Ns_7g → ft39e6W6vSgUL7peRo7pE}/_ssgManifest.js +0 -0
- /package/dist/.next/.next/static/{gh-QfIUVo4FTTduYCVKT6 → u7ssdTycF4iQ-w-pQZhxg}/_ssgManifest.js +0 -0
- /package/dist/.next/static/chunks/{4bd1b696-8c908eb707f85a27.js → 4bd1b696-124ea104c06f6cea.js} +0 -0
- /package/dist/.next/static/chunks/{517-3b698a5d3da06ff7.js → 517-c876ce2f00030cd0.js} +0 -0
- /package/dist/.next/static/chunks/{692-ede418e1d28a1394.js → 692-9e59d546afd11ec3.js} +0 -0
- /package/dist/.next/static/chunks/app/_not-found/{page-b786c3dd79ad15a5.js → page-3e24b81707d98126.js} +0 -0
- /package/dist/.next/{.next/static/thaCy2qVeNqYYhdayr13C → static/zh4Fz2tbm8GRka4woRrGp}/_ssgManifest.js +0 -0
package/dist/d1-studio.js
CHANGED
|
@@ -2,14 +2,63 @@
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import open from 'open';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
-
import { dirname, join } from 'path';
|
|
5
|
+
import { dirname, join, resolve } from 'path';
|
|
6
|
+
import { existsSync, readFileSync } from 'fs';
|
|
7
|
+
import { homedir } from 'os';
|
|
6
8
|
import express from 'express';
|
|
7
9
|
import { createServer } from 'http';
|
|
8
10
|
import next from 'next';
|
|
9
11
|
import { findWranglerConfig } from './lib/find-wrangler-config.js';
|
|
10
12
|
import logger from './lib/logger.js';
|
|
13
|
+
import { activateLicense, getOrValidateLicense } from '../src/lib/license.js';
|
|
11
14
|
import updateNotifier from 'update-notifier';
|
|
12
15
|
import pkg from '../package.json' with { type: 'json' };
|
|
16
|
+
import { trackEvent } from '../src/lib/telemetry.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Detects wrangler credentials and optionally injects a Cloudflare API token.
|
|
20
|
+
*
|
|
21
|
+
* OAuth tokens from `wrangler login` are intentionally NOT injected as
|
|
22
|
+
* CLOUDFLARE_API_TOKEN — wrangler handles its own OAuth flow (including
|
|
23
|
+
* token refresh) when it finds the config file. Injecting the raw OAuth
|
|
24
|
+
* access token would bypass the refresh cycle and break auth when it expires.
|
|
25
|
+
*
|
|
26
|
+
* Only a real API token (api_token in the config, or CLOUDFLARE_API_TOKEN
|
|
27
|
+
* already in env) is injected so wrangler subprocesses inherit it explicitly.
|
|
28
|
+
*
|
|
29
|
+
* Returns 'injected' | 'oauth' | 'found' | null.
|
|
30
|
+
*/
|
|
31
|
+
function loadAndInjectWranglerCredentials() {
|
|
32
|
+
// If an explicit API token is already in the environment, nothing to do
|
|
33
|
+
if (process.env.CLOUDFLARE_API_TOKEN) return 'injected';
|
|
34
|
+
|
|
35
|
+
const home = homedir();
|
|
36
|
+
const candidates = [
|
|
37
|
+
join(home, 'Library', 'Preferences', '.wrangler', 'config', 'default.toml'), // macOS
|
|
38
|
+
join(home, '.config', '.wrangler', 'config', 'default.toml'), // Linux XDG
|
|
39
|
+
join(home, '.wrangler', 'config', 'default.toml'), // older versions
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
for (const configPath of candidates) {
|
|
43
|
+
if (!existsSync(configPath)) continue;
|
|
44
|
+
try {
|
|
45
|
+
const content = readFileSync(configPath, 'utf8');
|
|
46
|
+
// Only inject a Cloudflare API token (not an OAuth access token)
|
|
47
|
+
const apiMatch = content.match(/api_token\s*=\s*"([^"]+)"/);
|
|
48
|
+
if (apiMatch?.[1]) {
|
|
49
|
+
process.env.CLOUDFLARE_API_TOKEN = apiMatch[1];
|
|
50
|
+
return 'injected';
|
|
51
|
+
}
|
|
52
|
+
// OAuth credentials from `wrangler login` — wrangler reads these itself
|
|
53
|
+
if (/oauth_token\s*=\s*"[^"]+"/.test(content)) return 'oauth';
|
|
54
|
+
// File exists but no usable token
|
|
55
|
+
return 'found';
|
|
56
|
+
} catch {
|
|
57
|
+
// Ignore read/parse errors, try next candidate
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
13
62
|
|
|
14
63
|
// Check for debug flag
|
|
15
64
|
const hasDebugFlag = process.argv.includes('--debug');
|
|
@@ -18,6 +67,16 @@ if (hasDebugFlag) {
|
|
|
18
67
|
logger.debug('Debug mode enabled');
|
|
19
68
|
}
|
|
20
69
|
|
|
70
|
+
// Parse --dir <path> to let users point at a project without cd-ing into it
|
|
71
|
+
const dirFlagIndex = process.argv.indexOf('--dir');
|
|
72
|
+
const dirFlag = dirFlagIndex !== -1 && process.argv[dirFlagIndex + 1]
|
|
73
|
+
? resolve(process.argv[dirFlagIndex + 1])
|
|
74
|
+
: null;
|
|
75
|
+
|
|
76
|
+
// Parse --license KEY to activate a Pro license
|
|
77
|
+
const licenseFlagIndex = process.argv.indexOf('--license');
|
|
78
|
+
const licenseFlag = licenseFlagIndex !== -1 ? process.argv[licenseFlagIndex + 1] : null;
|
|
79
|
+
|
|
21
80
|
const notifier = updateNotifier({
|
|
22
81
|
pkg,
|
|
23
82
|
updateCheckInterval: 1000 * 60 * 60 * 24,
|
|
@@ -31,9 +90,8 @@ if (notifier.update) {
|
|
|
31
90
|
|
|
32
91
|
// Version-specific messages
|
|
33
92
|
const versionMessages = {
|
|
34
|
-
|
|
35
|
-
'0.
|
|
36
|
-
// Add more version messages as needed
|
|
93
|
+
'0.2.11': 'Fixed table toolbar and table view horizontal/vertical scroll issues',
|
|
94
|
+
'0.3.0': 'Per-db migrations_dir, seed exclusion from push, sidebar UX improvements',
|
|
37
95
|
};
|
|
38
96
|
|
|
39
97
|
// Create custom message
|
|
@@ -106,22 +164,21 @@ async function startServer(port, projectDirectory) {
|
|
|
106
164
|
}
|
|
107
165
|
|
|
108
166
|
async function startStudio() {
|
|
167
|
+
trackEvent('start', pkg.version); // fire-and-forget, never awaited
|
|
109
168
|
try {
|
|
110
169
|
logger.info(chalk.green('Initializing D1 Studio...'));
|
|
111
170
|
|
|
112
171
|
// Get wrangler configuration
|
|
113
172
|
try {
|
|
114
|
-
const userProjectPath = process.cwd();
|
|
115
|
-
if (!userProjectPath) {
|
|
116
|
-
logger.error(chalk.red('Error: Could not determine project directory'));
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
173
|
+
const userProjectPath = dirFlag || process.cwd();
|
|
119
174
|
|
|
120
175
|
const wranglerResult = await findWranglerConfig(userProjectPath);
|
|
121
176
|
if (!wranglerResult || !wranglerResult.config) {
|
|
122
|
-
logger.error(chalk.red(
|
|
123
|
-
logger.info(chalk.yellow('
|
|
124
|
-
logger.info(chalk.
|
|
177
|
+
logger.error(chalk.red(`\nError: No wrangler.toml found in: ${userProjectPath}`));
|
|
178
|
+
logger.info(chalk.yellow('\nTo fix this, either:'));
|
|
179
|
+
logger.info(chalk.cyan(' 1. cd into your Cloudflare Workers project, then run d1s'));
|
|
180
|
+
logger.info(chalk.cyan(' 2. Run d1s --dir /path/to/your-project'));
|
|
181
|
+
logger.info(chalk.gray('\nThe project must have a wrangler.toml with a [[d1_databases]] entry.'));
|
|
125
182
|
process.exit(1);
|
|
126
183
|
}
|
|
127
184
|
|
|
@@ -143,21 +200,53 @@ async function startStudio() {
|
|
|
143
200
|
logger.info(chalk.blue(` - ${db.database_name} (${db.binding})`));
|
|
144
201
|
});
|
|
145
202
|
|
|
203
|
+
const credStatus = loadAndInjectWranglerCredentials();
|
|
204
|
+
if (credStatus === 'injected') {
|
|
205
|
+
logger.info(chalk.green('\n✓ Cloudflare API token found — remote sync & time travel ready'));
|
|
206
|
+
} else if (credStatus === 'oauth') {
|
|
207
|
+
logger.info(chalk.green('\n✓ Cloudflare credentials found (wrangler login) — remote sync & time travel ready'));
|
|
208
|
+
} else if (credStatus === 'found') {
|
|
209
|
+
logger.info(chalk.yellow('\n⚠ Wrangler config found but no usable token — run ' + chalk.cyan('wrangler login') + ' to enable Pro remote features'));
|
|
210
|
+
} else {
|
|
211
|
+
logger.info(chalk.yellow('\n⚠ No Cloudflare credentials — run ' + chalk.cyan('wrangler login') + ' to enable remote sync & time travel'));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Validate license and set Pro status before starting the server
|
|
215
|
+
const license = await getOrValidateLicense();
|
|
216
|
+
process.env.D1_IS_PRO = license.isPro ? 'true' : 'false';
|
|
217
|
+
|
|
146
218
|
const port = 4000;
|
|
147
219
|
const url = `http://localhost:${port}`;
|
|
148
220
|
|
|
149
221
|
await startServer(port, projectPath);
|
|
150
222
|
|
|
151
223
|
logger.info(chalk.green(`
|
|
152
|
-
|
|
153
|
-
│
|
|
154
|
-
│
|
|
155
|
-
│
|
|
156
|
-
│ Local:
|
|
157
|
-
│
|
|
158
|
-
|
|
224
|
+
┌─────────────────────────────────────────────────────┐
|
|
225
|
+
│ │
|
|
226
|
+
│ d1-studio v${pkg.version} is ready │
|
|
227
|
+
│ │
|
|
228
|
+
│ Local: ${url} │
|
|
229
|
+
│ │
|
|
230
|
+
│ Free: Table browser · SQL editor · Schema │
|
|
231
|
+
│ Migrations · Import / Export │
|
|
232
|
+
│ Pro: Remote sync · Time travel │
|
|
233
|
+
│ Multi-database switcher │
|
|
234
|
+
│ │
|
|
235
|
+
└─────────────────────────────────────────────────────┘
|
|
159
236
|
`));
|
|
160
237
|
|
|
238
|
+
if (license.isPro) {
|
|
239
|
+
logger.info(chalk.green(` ✓ Pro features active — ${license.email}`));
|
|
240
|
+
} else {
|
|
241
|
+
logger.info(chalk.yellow(` Run ${chalk.cyan('d1s --license YOUR-KEY')} to unlock Pro features`));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Re-validate license every 4 hours in the background
|
|
245
|
+
setInterval(async () => {
|
|
246
|
+
const updated = await getOrValidateLicense().catch(() => null);
|
|
247
|
+
if (updated) process.env.D1_IS_PRO = updated.isPro ? 'true' : 'false';
|
|
248
|
+
}, 4 * 60 * 60 * 1000).unref();
|
|
249
|
+
|
|
161
250
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
162
251
|
|
|
163
252
|
try {
|
|
@@ -193,7 +282,24 @@ process.on('SIGTERM', () => {
|
|
|
193
282
|
process.exit(0);
|
|
194
283
|
});
|
|
195
284
|
|
|
196
|
-
|
|
197
|
-
logger.
|
|
198
|
-
|
|
199
|
-
|
|
285
|
+
if (licenseFlag) {
|
|
286
|
+
logger.info(chalk.blue('\nActivating license key...'));
|
|
287
|
+
activateLicense(licenseFlag)
|
|
288
|
+
.then((result) => {
|
|
289
|
+
logger.info(chalk.green('\n✓ License activated!'));
|
|
290
|
+
logger.info(chalk.white(` Plan: ${result.plan}`));
|
|
291
|
+
logger.info(chalk.white(` Email: ${result.email}`));
|
|
292
|
+
logger.info(chalk.white(` Expires: ${new Date(result.expiresAt).toLocaleDateString()}`));
|
|
293
|
+
logger.info(chalk.gray('\nRun d1s to start D1 Studio with Pro features.'));
|
|
294
|
+
process.exit(0);
|
|
295
|
+
})
|
|
296
|
+
.catch((err) => {
|
|
297
|
+
logger.error(chalk.red(`\n✗ Activation failed: ${err.message}`));
|
|
298
|
+
process.exit(1);
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
startStudio().catch((error) => {
|
|
302
|
+
logger.error(chalk.red(`\nFailed to start D1 Studio: ${error}`));
|
|
303
|
+
process.exit(1);
|
|
304
|
+
});
|
|
305
|
+
}
|
package/dist/lib/license.js
CHANGED
|
@@ -3,97 +3,125 @@ import os from 'os';
|
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
5
5
|
import { createHash } from 'crypto';
|
|
6
|
-
import { LicenseError } from './errors.js';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const LICENSE_API =
|
|
8
|
+
process.env.D1STUDIO_API_URL ||
|
|
9
|
+
(process.env.NODE_ENV === 'development' ? 'http://localhost:3001' : 'https://d1-studio.com');
|
|
10
|
+
|
|
11
|
+
const FOUR_HOURS_MS = 4 * 60 * 60 * 1000;
|
|
12
|
+
|
|
13
|
+
const LICENSE_DIR = join(os.homedir(), '.d1studio');
|
|
14
|
+
const LICENSE_PATH = join(LICENSE_DIR, 'license.json');
|
|
15
|
+
|
|
16
|
+
export function generateHardwareId() {
|
|
17
|
+
const info = {
|
|
10
18
|
platform: process.platform,
|
|
11
19
|
arch: process.arch,
|
|
12
20
|
cpus: os.cpus().length,
|
|
13
21
|
hostname: os.hostname(),
|
|
14
|
-
username: os.userInfo().username
|
|
22
|
+
username: os.userInfo().username,
|
|
15
23
|
};
|
|
16
|
-
|
|
17
|
-
const systemString = JSON.stringify(osInfo);
|
|
18
|
-
return createHash('sha256').update(systemString).digest('hex');
|
|
24
|
+
return createHash('sha256').update(JSON.stringify(info)).digest('hex');
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
const licenseDir = join(os.homedir(), '.d1studio');
|
|
23
|
-
const licensePath = join(licenseDir, 'license.json');
|
|
24
|
-
|
|
27
|
+
async function readLicenseFile() {
|
|
25
28
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (licenseData.hardwareId !== hardwareId) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return licenseData;
|
|
34
|
-
} catch (error) {
|
|
29
|
+
return JSON.parse(await readFile(LICENSE_PATH, 'utf8'));
|
|
30
|
+
} catch {
|
|
35
31
|
return null;
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
34
|
|
|
39
|
-
export async function saveLicenseFile(
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
export async function saveLicenseFile(data) {
|
|
36
|
+
await mkdir(LICENSE_DIR, { recursive: true });
|
|
37
|
+
await writeFile(LICENSE_PATH, JSON.stringify(data, null, 2));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Activates a license key for this machine.
|
|
42
|
+
* Called once when user passes --license KEY.
|
|
43
|
+
* Returns { valid, plan, email, expiresAt } on success.
|
|
44
|
+
*/
|
|
45
|
+
export async function activateLicense(key) {
|
|
46
|
+
const fingerprint = generateHardwareId();
|
|
42
47
|
|
|
48
|
+
const res = await fetch(`${LICENSE_API}/api/license/activate`, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
headers: { 'Content-Type': 'application/json' },
|
|
51
|
+
body: JSON.stringify({ key: key.trim().toUpperCase(), fingerprint }),
|
|
52
|
+
signal: AbortSignal.timeout(10000),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
let data;
|
|
43
56
|
try {
|
|
44
|
-
await
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
data = await res.json();
|
|
58
|
+
} catch {
|
|
59
|
+
throw new Error(`Server returned an invalid response (status ${res.status}). Is d1studio-web running?`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!res.ok || !data.valid) {
|
|
63
|
+
throw new Error(data.error || 'License activation failed');
|
|
48
64
|
}
|
|
65
|
+
|
|
66
|
+
await saveLicenseFile({
|
|
67
|
+
licenseKey: key.trim().toUpperCase(),
|
|
68
|
+
fingerprint,
|
|
69
|
+
email: data.email,
|
|
70
|
+
plan: data.plan,
|
|
71
|
+
expiresAt: data.expiresAt,
|
|
72
|
+
lastValidated: new Date().toISOString(),
|
|
73
|
+
isPro: true,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return data;
|
|
49
77
|
}
|
|
50
78
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Validates the stored license against the remote API.
|
|
81
|
+
* Main entry point — called on startup and every 4 hours.
|
|
82
|
+
* Returns { isPro: boolean, plan?, expiresAt?, email? }
|
|
83
|
+
*/
|
|
84
|
+
export async function getOrValidateLicense() {
|
|
85
|
+
const stored = await readLicenseFile();
|
|
86
|
+
if (!stored?.licenseKey) return { isPro: false };
|
|
87
|
+
|
|
88
|
+
const lastValidated = stored.lastValidated ? new Date(stored.lastValidated) : null;
|
|
89
|
+
const isStale = !lastValidated || Date.now() - lastValidated.getTime() > FOUR_HOURS_MS;
|
|
90
|
+
|
|
91
|
+
if (!isStale) {
|
|
92
|
+
return {
|
|
93
|
+
isPro: !!stored.isPro,
|
|
94
|
+
plan: stored.plan,
|
|
95
|
+
expiresAt: stored.expiresAt,
|
|
96
|
+
email: stored.email,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
55
99
|
|
|
100
|
+
// Stale — re-validate remotely
|
|
56
101
|
try {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
102
|
+
const res = await fetch(
|
|
103
|
+
`${LICENSE_API}/api/license/validate?key=${encodeURIComponent(stored.licenseKey)}`,
|
|
104
|
+
{ signal: AbortSignal.timeout(8000) }
|
|
105
|
+
);
|
|
106
|
+
const remote = await res.json();
|
|
107
|
+
const isPro = remote.valid === true;
|
|
108
|
+
|
|
109
|
+
await saveLicenseFile({
|
|
110
|
+
...stored,
|
|
111
|
+
isPro,
|
|
112
|
+
plan: remote.plan ?? stored.plan,
|
|
113
|
+
expiresAt: remote.expiresAt ?? stored.expiresAt,
|
|
114
|
+
lastValidated: new Date().toISOString(),
|
|
67
115
|
});
|
|
68
116
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return result;
|
|
79
|
-
|
|
80
|
-
} catch (error) {
|
|
81
|
-
if (error instanceof LicenseError) {
|
|
82
|
-
throw error;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (error.name === 'TypeError' && error.message.includes('fetch')) {
|
|
86
|
-
throw new LicenseError(
|
|
87
|
-
process.env.NODE_ENV === 'development'
|
|
88
|
-
? 'Unable to connect to local license validation service. Make sure the development server is running.'
|
|
89
|
-
: 'Unable to connect to license server. Please check your internet connection.',
|
|
90
|
-
'CONNECTION_ERROR'
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
throw new LicenseError(
|
|
95
|
-
'An unexpected error occurred during license validation',
|
|
96
|
-
'VALIDATION_ERROR'
|
|
97
|
-
);
|
|
117
|
+
return { isPro, plan: remote.plan, expiresAt: remote.expiresAt, email: stored.email };
|
|
118
|
+
} catch {
|
|
119
|
+
// Network error — honour existing cached status as grace period
|
|
120
|
+
return {
|
|
121
|
+
isPro: !!stored.isPro,
|
|
122
|
+
plan: stored.plan,
|
|
123
|
+
expiresAt: stored.expiresAt,
|
|
124
|
+
email: stored.email,
|
|
125
|
+
};
|
|
98
126
|
}
|
|
99
|
-
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// lib/local-db.js
|
|
2
|
+
// Direct SQLite access for local D1 databases via better-sqlite3.
|
|
3
|
+
// Falls back gracefully — callers receive null and can retry with wrangler CLI.
|
|
4
|
+
|
|
5
|
+
import crypto from 'crypto';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import logger from './logger.js';
|
|
10
|
+
|
|
11
|
+
const MINIFLARE_DIR = path.join('.wrangler', 'state', 'v3', 'd1', 'miniflare-D1DatabaseObject');
|
|
12
|
+
|
|
13
|
+
// Cache open Database instances: "projectDir:dbName" → Database
|
|
14
|
+
const dbCache = new Map();
|
|
15
|
+
|
|
16
|
+
function sha256(input) {
|
|
17
|
+
return crypto.createHash('sha256').update(input).digest('hex');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Locate the SQLite file for a given database config under projectDir.
|
|
22
|
+
* Wrangler/miniflare v3 stores D1 as:
|
|
23
|
+
* .wrangler/state/v3/d1/miniflare-D1DatabaseObject/{hash}.sqlite
|
|
24
|
+
*
|
|
25
|
+
* The hash is SHA256 of the namespace key. We try the most common formulas
|
|
26
|
+
* then fall back to a single-file directory scan.
|
|
27
|
+
*/
|
|
28
|
+
function findSqliteFile(projectDir, databaseConfig) {
|
|
29
|
+
const dir = path.join(projectDir, MINIFLARE_DIR);
|
|
30
|
+
if (!fs.existsSync(dir)) return null;
|
|
31
|
+
|
|
32
|
+
const { database_id, database_name, binding } = databaseConfig;
|
|
33
|
+
|
|
34
|
+
// Try known miniflare v3 hash formulas. Wrangler/miniflare derives the SQLite
|
|
35
|
+
// filename as sha256 of a namespace key — try all known patterns.
|
|
36
|
+
const ids = [database_id, database_name, binding].filter(Boolean);
|
|
37
|
+
const prefixes = [
|
|
38
|
+
'',
|
|
39
|
+
'miniflare-D1DatabaseObject:',
|
|
40
|
+
'D1DatabaseObject:',
|
|
41
|
+
'd1:',
|
|
42
|
+
];
|
|
43
|
+
const candidates = ids.flatMap(id =>
|
|
44
|
+
prefixes.map(prefix => sha256(`${prefix}${id}`))
|
|
45
|
+
).map(h => path.join(dir, `${h}.sqlite`));
|
|
46
|
+
|
|
47
|
+
const found = candidates.find(p => fs.existsSync(p));
|
|
48
|
+
if (found) return found;
|
|
49
|
+
|
|
50
|
+
// Fallback: scan for .sqlite files.
|
|
51
|
+
// Only use this for single-DB projects — if multiple files exist, returning
|
|
52
|
+
// the wrong one would mix up tables from different databases. In that case
|
|
53
|
+
// return null so the caller falls back to wrangler CLI (which knows the mapping).
|
|
54
|
+
const files = fs.readdirSync(dir)
|
|
55
|
+
.filter(f => f.endsWith('.sqlite'))
|
|
56
|
+
.map(f => ({ name: f, fullPath: path.join(dir, f), mtime: fs.statSync(path.join(dir, f)).mtimeMs }))
|
|
57
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
58
|
+
|
|
59
|
+
if (files.length === 1) {
|
|
60
|
+
return files[0].fullPath;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (files.length > 1) {
|
|
64
|
+
logger.debug(`[local-db] Multiple SQLite files, no hash matched — falling back to wrangler CLI. dir=${dir}, tried ids=${JSON.stringify(ids)}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
logger.debug(`[local-db] No SQLite files found. dir=${dir}, tried ids=${JSON.stringify(ids)}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns true if a local SQLite file exists for the given database config.
|
|
73
|
+
* Does NOT open the file — safe for status checks.
|
|
74
|
+
*/
|
|
75
|
+
export function hasLocalDb(projectDir, databaseConfig) {
|
|
76
|
+
return findSqliteFile(projectDir, databaseConfig) !== null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get (or create) a cached better-sqlite3 Database instance.
|
|
81
|
+
* Returns null if the SQLite file cannot be located.
|
|
82
|
+
*/
|
|
83
|
+
export function getLocalDb(projectDir, databaseConfig) {
|
|
84
|
+
const key = `${projectDir}:${databaseConfig.database_name}`;
|
|
85
|
+
// Always re-resolve the path so stale cache entries (wrong file) are evicted
|
|
86
|
+
const sqlitePath = findSqliteFile(projectDir, databaseConfig);
|
|
87
|
+
|
|
88
|
+
if (dbCache.has(key)) {
|
|
89
|
+
const cached = dbCache.get(key);
|
|
90
|
+
if (cached.path !== sqlitePath) {
|
|
91
|
+
// Path changed or is now null — evict stale entry
|
|
92
|
+
try { cached.db.close(); } catch {}
|
|
93
|
+
dbCache.delete(key);
|
|
94
|
+
} else {
|
|
95
|
+
// Same path — verify the connection is still responsive
|
|
96
|
+
try { cached.db.prepare('SELECT 1').get(); return cached.db; } catch { dbCache.delete(key); }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!sqlitePath) return null;
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const db = new Database(sqlitePath, { fileMustExist: false });
|
|
104
|
+
db.pragma('journal_mode = WAL');
|
|
105
|
+
db.pragma('foreign_keys = ON');
|
|
106
|
+
dbCache.set(key, { db, path: sqlitePath });
|
|
107
|
+
return db;
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Execute a SQL statement via better-sqlite3 and return a JSON string
|
|
115
|
+
* matching the shape wrangler d1 execute --json returns:
|
|
116
|
+
* [{ results: [...rows], success: true, meta: { ... } }]
|
|
117
|
+
*
|
|
118
|
+
* Returns null if the database file cannot be found (caller should fall back to wrangler CLI).
|
|
119
|
+
* Throws on SQL errors (same contract as executeSQL in sql-operations.js).
|
|
120
|
+
*/
|
|
121
|
+
export function executeLocalSQL(projectDir, databaseConfig, sql) {
|
|
122
|
+
const db = getLocalDb(projectDir, databaseConfig);
|
|
123
|
+
if (!db) return null;
|
|
124
|
+
|
|
125
|
+
const trimmed = sql.trim();
|
|
126
|
+
const upper = trimmed.toUpperCase().replace(/\s+/g, ' ');
|
|
127
|
+
|
|
128
|
+
// Multi-statement: split on ';' and run each — needed for DDL batches
|
|
129
|
+
const statements = trimmed
|
|
130
|
+
.split(';')
|
|
131
|
+
.map(s => s.trim())
|
|
132
|
+
.filter(Boolean);
|
|
133
|
+
|
|
134
|
+
if (statements.length > 1) {
|
|
135
|
+
// Run all statements in a single transaction, collect results
|
|
136
|
+
let allResults = [];
|
|
137
|
+
let totalChanges = 0;
|
|
138
|
+
let lastInsertRowid = 0;
|
|
139
|
+
|
|
140
|
+
const runAll = db.transaction(() => {
|
|
141
|
+
for (const stmt of statements) {
|
|
142
|
+
const u = stmt.toUpperCase().replace(/\s+/g, ' ');
|
|
143
|
+
const isRead = u.startsWith('SELECT') || u.startsWith('PRAGMA') || u.startsWith('EXPLAIN');
|
|
144
|
+
if (isRead) {
|
|
145
|
+
const rows = db.prepare(stmt).all();
|
|
146
|
+
allResults = allResults.concat(rows);
|
|
147
|
+
} else {
|
|
148
|
+
const info = db.prepare(stmt).run();
|
|
149
|
+
totalChanges += info.changes;
|
|
150
|
+
lastInsertRowid = info.lastInsertRowid;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
runAll();
|
|
156
|
+
return JSON.stringify([{
|
|
157
|
+
results: allResults,
|
|
158
|
+
success: true,
|
|
159
|
+
meta: { changes: totalChanges, last_row_id: lastInsertRowid, rows_read: allResults.length, rows_written: totalChanges }
|
|
160
|
+
}]);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Single statement
|
|
164
|
+
const isRead = upper.startsWith('SELECT') || upper.startsWith('PRAGMA') || upper.startsWith('EXPLAIN');
|
|
165
|
+
|
|
166
|
+
if (isRead) {
|
|
167
|
+
const rows = db.prepare(trimmed).all();
|
|
168
|
+
return JSON.stringify([{
|
|
169
|
+
results: rows,
|
|
170
|
+
success: true,
|
|
171
|
+
meta: { rows_read: rows.length, rows_written: 0, changed_db: false }
|
|
172
|
+
}]);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const info = db.prepare(trimmed).run();
|
|
176
|
+
return JSON.stringify([{
|
|
177
|
+
results: [],
|
|
178
|
+
success: true,
|
|
179
|
+
meta: {
|
|
180
|
+
changes: info.changes,
|
|
181
|
+
last_row_id: info.lastInsertRowid,
|
|
182
|
+
rows_read: 0,
|
|
183
|
+
rows_written: info.changes,
|
|
184
|
+
changed_db: info.changes > 0
|
|
185
|
+
}
|
|
186
|
+
}]);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Execute a batch INSERT using a better-sqlite3 transaction.
|
|
191
|
+
* rows: array of value arrays matching the columns order.
|
|
192
|
+
* Returns { changes } on success, null if DB file not found.
|
|
193
|
+
*/
|
|
194
|
+
export function executeLocalBatchInsert(projectDir, databaseConfig, sql, rows) {
|
|
195
|
+
const db = getLocalDb(projectDir, databaseConfig);
|
|
196
|
+
if (!db) return null;
|
|
197
|
+
|
|
198
|
+
const stmt = db.prepare(sql);
|
|
199
|
+
let totalChanges = 0;
|
|
200
|
+
|
|
201
|
+
const insertMany = db.transaction((records) => {
|
|
202
|
+
for (const row of records) {
|
|
203
|
+
const info = stmt.run(...row);
|
|
204
|
+
totalChanges += info.changes;
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
insertMany(rows);
|
|
209
|
+
return { changes: totalChanges };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Invalidate the cached Database instance for a given database.
|
|
214
|
+
* Call this if the SQLite file path may have changed (e.g. after wrangler reinit).
|
|
215
|
+
*/
|
|
216
|
+
export function invalidateLocalDb(projectDir, databaseName) {
|
|
217
|
+
const key = `${projectDir}:${databaseName}`;
|
|
218
|
+
const entry = dbCache.get(key);
|
|
219
|
+
if (entry) {
|
|
220
|
+
try { entry.db.close(); } catch { /* ignore */ }
|
|
221
|
+
dbCache.delete(key);
|
|
222
|
+
}
|
|
223
|
+
}
|