d1s 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/README.md +7 -0
  2. package/dist/.next/.next/BUILD_ID +1 -0
  3. package/dist/.next/.next/app-build-manifest.json +109 -0
  4. package/dist/.next/.next/app-path-routes-manifest.json +1 -0
  5. package/dist/.next/.next/build-manifest.json +33 -0
  6. package/dist/.next/.next/cache/.rscinfo +1 -0
  7. package/dist/.next/.next/cache/.tsbuildinfo +1 -0
  8. package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
  9. package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
  10. package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
  11. package/dist/.next/.next/cache/webpack/client-production/index.pack +0 -0
  12. package/dist/.next/.next/cache/webpack/client-production/index.pack.old +0 -0
  13. package/dist/.next/.next/cache/webpack/edge-server-production/0.pack +0 -0
  14. package/dist/.next/.next/cache/webpack/edge-server-production/index.pack +0 -0
  15. package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
  16. package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
  17. package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
  18. package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
  19. package/dist/.next/.next/diagnostics/build-diagnostics.json +6 -0
  20. package/dist/.next/.next/diagnostics/framework.json +1 -0
  21. package/dist/.next/.next/export-marker.json +1 -0
  22. package/dist/.next/.next/images-manifest.json +1 -0
  23. package/dist/.next/.next/next-minimal-server.js.nft.json +1 -0
  24. package/dist/.next/.next/next-server.js.nft.json +1 -0
  25. package/dist/.next/.next/package.json +1 -0
  26. package/dist/.next/.next/prerender-manifest.json +1 -0
  27. package/dist/.next/.next/react-loadable-manifest.json +1 -0
  28. package/dist/.next/.next/required-server-files.json +1 -0
  29. package/dist/.next/.next/routes-manifest.json +1 -0
  30. package/dist/.next/.next/server/app/_not-found/page.js +1 -0
  31. package/dist/.next/.next/server/app/_not-found/page.js.nft.json +1 -0
  32. package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  33. package/dist/.next/.next/server/app/_not-found.html +1 -0
  34. package/dist/.next/.next/server/app/_not-found.meta +8 -0
  35. package/dist/.next/.next/server/app/_not-found.rsc +16 -0
  36. package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -0
  37. package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +1 -0
  38. package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -0
  39. package/dist/.next/.next/server/app/api/databases/route.js +1 -0
  40. package/dist/.next/.next/server/app/api/databases/route.js.nft.json +1 -0
  41. package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -0
  42. package/dist/.next/.next/server/app/api/migrations/sync/route.js +12 -0
  43. package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -0
  44. package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -0
  45. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +1 -0
  46. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -0
  47. package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -0
  48. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +1 -0
  49. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -0
  50. package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -0
  51. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +1 -0
  52. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -0
  53. package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -0
  54. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +14 -0
  55. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -0
  56. package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -0
  57. package/dist/.next/.next/server/app/api/push-remote/preview/route.js +14 -0
  58. package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -0
  59. package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -0
  60. package/dist/.next/.next/server/app/api/query/route.js +8 -0
  61. package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -0
  62. package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -0
  63. package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -0
  64. package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -0
  65. package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -0
  66. package/dist/.next/.next/server/app/api/tables/route.js +7 -0
  67. package/dist/.next/.next/server/app/api/tables/route.js.nft.json +1 -0
  68. package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -0
  69. package/dist/.next/.next/server/app/index.html +3 -0
  70. package/dist/.next/.next/server/app/index.meta +7 -0
  71. package/dist/.next/.next/server/app/index.rsc +20 -0
  72. package/dist/.next/.next/server/app/page.js +58 -0
  73. package/dist/.next/.next/server/app/page.js.nft.json +1 -0
  74. package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -0
  75. package/dist/.next/.next/server/app-paths-manifest.json +15 -0
  76. package/dist/.next/.next/server/chunks/336.js +1 -0
  77. package/dist/.next/.next/server/chunks/627.js +6 -0
  78. package/dist/.next/.next/server/chunks/638.js +13 -0
  79. package/dist/.next/.next/server/chunks/801.js +55 -0
  80. package/dist/.next/.next/server/chunks/973.js +2 -0
  81. package/dist/.next/.next/server/chunks/992.js +3 -0
  82. package/dist/.next/.next/server/functions-config-manifest.json +1 -0
  83. package/dist/.next/.next/server/interception-route-rewrite-manifest.js +1 -0
  84. package/dist/.next/.next/server/middleware-build-manifest.js +1 -0
  85. package/dist/.next/.next/server/middleware-manifest.json +6 -0
  86. package/dist/.next/.next/server/middleware-react-loadable-manifest.js +1 -0
  87. package/dist/.next/.next/server/next-font-manifest.js +1 -0
  88. package/dist/.next/.next/server/next-font-manifest.json +1 -0
  89. package/dist/.next/.next/server/pages/404.html +1 -0
  90. package/dist/.next/.next/server/pages/500.html +1 -0
  91. package/dist/.next/.next/server/pages/_app.js +1 -0
  92. package/dist/.next/.next/server/pages/_app.js.nft.json +1 -0
  93. package/dist/.next/.next/server/pages/_document.js +1 -0
  94. package/dist/.next/.next/server/pages/_document.js.nft.json +1 -0
  95. package/dist/.next/.next/server/pages/_error.js +1 -0
  96. package/dist/.next/.next/server/pages/_error.js.nft.json +1 -0
  97. package/dist/.next/.next/server/pages-manifest.json +1 -0
  98. package/dist/.next/.next/server/server-reference-manifest.js +1 -0
  99. package/dist/.next/.next/server/server-reference-manifest.json +1 -0
  100. package/dist/.next/.next/server/webpack-runtime.js +1 -0
  101. package/dist/.next/.next/static/ODMSSwVqLoDcBgbFHUjr8/_buildManifest.js +1 -0
  102. package/dist/.next/.next/static/ODMSSwVqLoDcBgbFHUjr8/_ssgManifest.js +1 -0
  103. package/dist/.next/.next/static/chunks/422-6fa3c14fc64ad67b.js +1 -0
  104. package/dist/.next/.next/static/chunks/4bd1b696-8c908eb707f85a27.js +1 -0
  105. package/dist/.next/.next/static/chunks/517-3b698a5d3da06ff7.js +2 -0
  106. package/dist/.next/.next/static/chunks/692-ede418e1d28a1394.js +1 -0
  107. package/dist/.next/.next/static/chunks/735-c9144179c6bd7d06.js +1 -0
  108. package/dist/.next/.next/static/chunks/92-c4466e0f1ca8a3a8.js +1 -0
  109. package/dist/.next/.next/static/chunks/app/_not-found/page-b786c3dd79ad15a5.js +1 -0
  110. package/dist/.next/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +1 -0
  111. package/dist/.next/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +1 -0
  112. package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +1 -0
  113. package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +1 -0
  114. package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +1 -0
  115. package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +1 -0
  116. package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +1 -0
  117. package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +1 -0
  118. package/dist/.next/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +1 -0
  119. package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +1 -0
  120. package/dist/.next/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +1 -0
  121. package/dist/.next/.next/static/chunks/app/layout-8360fab69b848283.js +1 -0
  122. package/dist/.next/.next/static/chunks/app/page-75081ac7a88cb706.js +1 -0
  123. package/dist/.next/.next/static/chunks/framework-d29117d969504448.js +1 -0
  124. package/dist/.next/.next/static/chunks/main-8d0ab17774ffa031.js +1 -0
  125. package/dist/.next/.next/static/chunks/main-app-d36cdfb402b40f13.js +1 -0
  126. package/dist/.next/.next/static/chunks/pages/_app-d23763e3e6c904ff.js +1 -0
  127. package/dist/.next/.next/static/chunks/pages/_error-9b7125ad1a1e68fa.js +1 -0
  128. package/dist/.next/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  129. package/dist/.next/.next/static/chunks/webpack-c76ac1e586b2802a.js +1 -0
  130. package/dist/.next/.next/static/css/c51a7ef325e30c16.css +3 -0
  131. package/dist/.next/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  132. package/dist/.next/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  133. package/dist/.next/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  134. package/dist/.next/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  135. package/dist/.next/.next/trace +3 -0
  136. package/dist/.next/.next/types/app/api/cloudflare/route.ts +347 -0
  137. package/dist/.next/.next/types/app/api/databases/route.ts +347 -0
  138. package/dist/.next/.next/types/app/api/migrations/sync/route.ts +347 -0
  139. package/dist/.next/.next/types/app/api/migrations/sync-files/route.ts +347 -0
  140. package/dist/.next/.next/types/app/api/pull-remote/confirm/route.ts +347 -0
  141. package/dist/.next/.next/types/app/api/pull-remote/preview/route.ts +347 -0
  142. package/dist/.next/.next/types/app/api/push-remote/confirm/route.ts +347 -0
  143. package/dist/.next/.next/types/app/api/push-remote/preview/route.ts +347 -0
  144. package/dist/.next/.next/types/app/api/query/route.ts +347 -0
  145. package/dist/.next/.next/types/app/api/tables/[name]/route.ts +347 -0
  146. package/dist/.next/.next/types/app/api/tables/route.ts +347 -0
  147. package/dist/.next/.next/types/app/page.ts +84 -0
  148. package/dist/.next/.next/types/cache-life.d.ts +141 -0
  149. package/dist/.next/.next/types/package.json +1 -0
  150. package/dist/.next/BUILD_ID +1 -0
  151. package/dist/.next/app-build-manifest.json +109 -0
  152. package/dist/.next/app-path-routes-manifest.json +1 -0
  153. package/dist/.next/build-manifest.json +33 -0
  154. package/dist/.next/cache/.rscinfo +1 -0
  155. package/dist/.next/cache/.tsbuildinfo +1 -0
  156. package/dist/.next/cache/webpack/client-production/0.pack +0 -0
  157. package/dist/.next/cache/webpack/client-production/index.pack +0 -0
  158. package/dist/.next/cache/webpack/edge-server-production/0.pack +0 -0
  159. package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
  160. package/dist/.next/cache/webpack/server-production/0.pack +0 -0
  161. package/dist/.next/cache/webpack/server-production/index.pack +0 -0
  162. package/dist/.next/diagnostics/build-diagnostics.json +6 -0
  163. package/dist/.next/diagnostics/framework.json +1 -0
  164. package/dist/.next/export-marker.json +1 -0
  165. package/dist/.next/images-manifest.json +1 -0
  166. package/dist/.next/next-minimal-server.js.nft.json +1 -0
  167. package/dist/.next/next-server.js.nft.json +1 -0
  168. package/dist/.next/package.json +1 -0
  169. package/dist/.next/prerender-manifest.json +1 -0
  170. package/dist/.next/react-loadable-manifest.json +1 -0
  171. package/dist/.next/required-server-files.json +1 -0
  172. package/dist/.next/routes-manifest.json +1 -0
  173. package/dist/.next/server/app/_not-found/page.js +1 -0
  174. package/dist/.next/server/app/_not-found/page.js.nft.json +1 -0
  175. package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  176. package/dist/.next/server/app/_not-found.html +1 -0
  177. package/dist/.next/server/app/_not-found.meta +8 -0
  178. package/dist/.next/server/app/_not-found.rsc +16 -0
  179. package/dist/.next/server/app/api/cloudflare/route.js +1 -0
  180. package/dist/.next/server/app/api/cloudflare/route.js.nft.json +1 -0
  181. package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -0
  182. package/dist/.next/server/app/api/databases/route.js +1 -0
  183. package/dist/.next/server/app/api/databases/route.js.nft.json +1 -0
  184. package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -0
  185. package/dist/.next/server/app/api/migrations/sync/route.js +12 -0
  186. package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -0
  187. package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -0
  188. package/dist/.next/server/app/api/migrations/sync-files/route.js +1 -0
  189. package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -0
  190. package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -0
  191. package/dist/.next/server/app/api/pull-remote/confirm/route.js +1 -0
  192. package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -0
  193. package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -0
  194. package/dist/.next/server/app/api/pull-remote/preview/route.js +1 -0
  195. package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -0
  196. package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -0
  197. package/dist/.next/server/app/api/push-remote/confirm/route.js +14 -0
  198. package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -0
  199. package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -0
  200. package/dist/.next/server/app/api/push-remote/preview/route.js +14 -0
  201. package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -0
  202. package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -0
  203. package/dist/.next/server/app/api/query/route.js +8 -0
  204. package/dist/.next/server/app/api/query/route.js.nft.json +1 -0
  205. package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -0
  206. package/dist/.next/server/app/api/tables/[name]/route.js +5 -0
  207. package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -0
  208. package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -0
  209. package/dist/.next/server/app/api/tables/route.js +7 -0
  210. package/dist/.next/server/app/api/tables/route.js.nft.json +1 -0
  211. package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -0
  212. package/dist/.next/server/app/index.html +3 -0
  213. package/dist/.next/server/app/index.meta +7 -0
  214. package/dist/.next/server/app/index.rsc +20 -0
  215. package/dist/.next/server/app/page.js +58 -0
  216. package/dist/.next/server/app/page.js.nft.json +1 -0
  217. package/dist/.next/server/app/page_client-reference-manifest.js +1 -0
  218. package/dist/.next/server/app-paths-manifest.json +15 -0
  219. package/dist/.next/server/chunks/336.js +1 -0
  220. package/dist/.next/server/chunks/627.js +6 -0
  221. package/dist/.next/server/chunks/638.js +13 -0
  222. package/dist/.next/server/chunks/801.js +55 -0
  223. package/dist/.next/server/chunks/973.js +2 -0
  224. package/dist/.next/server/chunks/992.js +3 -0
  225. package/dist/.next/server/functions-config-manifest.json +1 -0
  226. package/dist/.next/server/interception-route-rewrite-manifest.js +1 -0
  227. package/dist/.next/server/middleware-build-manifest.js +1 -0
  228. package/dist/.next/server/middleware-manifest.json +6 -0
  229. package/dist/.next/server/middleware-react-loadable-manifest.js +1 -0
  230. package/dist/.next/server/next-font-manifest.js +1 -0
  231. package/dist/.next/server/next-font-manifest.json +1 -0
  232. package/dist/.next/server/pages/404.html +1 -0
  233. package/dist/.next/server/pages/500.html +1 -0
  234. package/dist/.next/server/pages/_app.js +1 -0
  235. package/dist/.next/server/pages/_app.js.nft.json +1 -0
  236. package/dist/.next/server/pages/_document.js +1 -0
  237. package/dist/.next/server/pages/_document.js.nft.json +1 -0
  238. package/dist/.next/server/pages/_error.js +1 -0
  239. package/dist/.next/server/pages/_error.js.nft.json +1 -0
  240. package/dist/.next/server/pages-manifest.json +1 -0
  241. package/dist/.next/server/server-reference-manifest.js +1 -0
  242. package/dist/.next/server/server-reference-manifest.json +1 -0
  243. package/dist/.next/server/webpack-runtime.js +1 -0
  244. package/dist/.next/static/OmPVuV0d1lrcjSBQzxkdH/_buildManifest.js +1 -0
  245. package/dist/.next/static/OmPVuV0d1lrcjSBQzxkdH/_ssgManifest.js +1 -0
  246. package/dist/.next/static/chunks/422-6fa3c14fc64ad67b.js +1 -0
  247. package/dist/.next/static/chunks/4bd1b696-8c908eb707f85a27.js +1 -0
  248. package/dist/.next/static/chunks/517-3b698a5d3da06ff7.js +2 -0
  249. package/dist/.next/static/chunks/692-ede418e1d28a1394.js +1 -0
  250. package/dist/.next/static/chunks/735-c9144179c6bd7d06.js +1 -0
  251. package/dist/.next/static/chunks/92-c4466e0f1ca8a3a8.js +1 -0
  252. package/dist/.next/static/chunks/app/_not-found/page-b786c3dd79ad15a5.js +1 -0
  253. package/dist/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +1 -0
  254. package/dist/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +1 -0
  255. package/dist/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +1 -0
  256. package/dist/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +1 -0
  257. package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +1 -0
  258. package/dist/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +1 -0
  259. package/dist/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +1 -0
  260. package/dist/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +1 -0
  261. package/dist/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +1 -0
  262. package/dist/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +1 -0
  263. package/dist/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +1 -0
  264. package/dist/.next/static/chunks/app/layout-8360fab69b848283.js +1 -0
  265. package/dist/.next/static/chunks/app/page-75081ac7a88cb706.js +1 -0
  266. package/dist/.next/static/chunks/framework-d29117d969504448.js +1 -0
  267. package/dist/.next/static/chunks/main-8d0ab17774ffa031.js +1 -0
  268. package/dist/.next/static/chunks/main-app-d36cdfb402b40f13.js +1 -0
  269. package/dist/.next/static/chunks/pages/_app-d23763e3e6c904ff.js +1 -0
  270. package/dist/.next/static/chunks/pages/_error-9b7125ad1a1e68fa.js +1 -0
  271. package/dist/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  272. package/dist/.next/static/chunks/webpack-c76ac1e586b2802a.js +1 -0
  273. package/dist/.next/static/css/c51a7ef325e30c16.css +3 -0
  274. package/dist/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  275. package/dist/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  276. package/dist/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  277. package/dist/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  278. package/dist/.next/trace +13 -0
  279. package/dist/.next/types/app/api/cloudflare/route.ts +347 -0
  280. package/dist/.next/types/app/api/databases/route.ts +347 -0
  281. package/dist/.next/types/app/api/migrations/sync/route.ts +347 -0
  282. package/dist/.next/types/app/api/migrations/sync-files/route.ts +347 -0
  283. package/dist/.next/types/app/api/pull-remote/confirm/route.ts +347 -0
  284. package/dist/.next/types/app/api/pull-remote/preview/route.ts +347 -0
  285. package/dist/.next/types/app/api/push-remote/confirm/route.ts +347 -0
  286. package/dist/.next/types/app/api/push-remote/preview/route.ts +347 -0
  287. package/dist/.next/types/app/api/query/route.ts +347 -0
  288. package/dist/.next/types/app/api/tables/[name]/route.ts +347 -0
  289. package/dist/.next/types/app/api/tables/route.ts +347 -0
  290. package/dist/.next/types/app/page.ts +84 -0
  291. package/dist/.next/types/cache-life.d.ts +141 -0
  292. package/dist/.next/types/package.json +1 -0
  293. package/dist/app/api/cloudflare/route.js +146 -0
  294. package/dist/app/api/databases/route.js +72 -0
  295. package/dist/app/api/migrations/sync/route.js +172 -0
  296. package/dist/app/api/migrations/sync-files/route.js +172 -0
  297. package/dist/app/api/pull-remote/confirm/route.js +277 -0
  298. package/dist/app/api/pull-remote/preview/route.js +143 -0
  299. package/dist/app/api/push-remote/confirm/route.js +196 -0
  300. package/dist/app/api/push-remote/preview/route.js +178 -0
  301. package/dist/app/api/query/route.js +160 -0
  302. package/dist/app/api/tables/[name]/route.js +173 -0
  303. package/dist/app/api/tables/route.js +174 -0
  304. package/dist/app/app/api/cloudflare/route.js +146 -0
  305. package/dist/app/app/api/databases/route.js +72 -0
  306. package/dist/app/app/api/migrations/sync/route.js +172 -0
  307. package/dist/app/app/api/migrations/sync-files/route.js +172 -0
  308. package/dist/app/app/api/pull-remote/confirm/route.js +277 -0
  309. package/dist/app/app/api/pull-remote/preview/route.js +143 -0
  310. package/dist/app/app/api/push-remote/confirm/route.js +196 -0
  311. package/dist/app/app/api/push-remote/preview/route.js +178 -0
  312. package/dist/app/app/api/query/route.js +160 -0
  313. package/dist/app/app/api/tables/[name]/route.js +173 -0
  314. package/dist/app/app/api/tables/route.js +174 -0
  315. package/dist/app/app/globals.css +93 -0
  316. package/dist/app/app/layout.jsx +35 -0
  317. package/dist/app/app/page.jsx +37 -0
  318. package/dist/app/globals.css +93 -0
  319. package/dist/app/layout.jsx +35 -0
  320. package/dist/app/page.jsx +37 -0
  321. package/dist/d1-studio.js +344 -0
  322. package/dist/lib/database-queue.js +33 -0
  323. package/dist/lib/error.js +20 -0
  324. package/dist/lib/find-wrangler-config.js +67 -0
  325. package/dist/lib/license.js +99 -0
  326. package/dist/lib/migrations.js +415 -0
  327. package/dist/lib/parse-sql-error.js +200 -0
  328. package/dist/lib/request-deduplication.js +24 -0
  329. package/dist/lib/schema-operations.js +103 -0
  330. package/dist/lib/sql-error-types.js +14 -0
  331. package/dist/lib/sql-operations.js +557 -0
  332. package/dist/lib/utils.js +6 -0
  333. package/next.config.mjs +18 -0
  334. package/package.json +97 -0
  335. package/postcss.config.mjs +8 -0
  336. package/scripts/studio.js +344 -0
  337. package/scripts/test.js +168 -0
  338. package/src/app/api/cloudflare/route.js +146 -0
  339. package/src/app/api/databases/route.js +72 -0
  340. package/src/app/api/migrations/sync/route.js +172 -0
  341. package/src/app/api/migrations/sync-files/route.js +172 -0
  342. package/src/app/api/pull-remote/confirm/route.js +277 -0
  343. package/src/app/api/pull-remote/preview/route.js +143 -0
  344. package/src/app/api/push-remote/confirm/route.js +196 -0
  345. package/src/app/api/push-remote/preview/route.js +178 -0
  346. package/src/app/api/query/route.js +160 -0
  347. package/src/app/api/tables/[name]/route.js +173 -0
  348. package/src/app/api/tables/route.js +174 -0
  349. package/src/app/globals.css +93 -0
  350. package/src/app/layout.jsx +35 -0
  351. package/src/app/page.jsx +37 -0
  352. package/src/components/cloudflare-credentials-modal.jsx +94 -0
  353. package/src/components/column-selector.jsx +133 -0
  354. package/src/components/column-sorting.jsx +65 -0
  355. package/src/components/delete-records-dialog.jsx +64 -0
  356. package/src/components/download-button.jsx +205 -0
  357. package/src/components/edit-error-alert.jsx +30 -0
  358. package/src/components/editable-cell.jsx +163 -0
  359. package/src/components/editable-row.jsx +169 -0
  360. package/src/components/environment-handler.jsx +278 -0
  361. package/src/components/environment-select.jsx +59 -0
  362. package/src/components/pull-preview-toast.jsx +188 -0
  363. package/src/components/push-error-alert.jsx +72 -0
  364. package/src/components/push-preview-toast.jsx +183 -0
  365. package/src/components/query-results.jsx +112 -0
  366. package/src/components/refresh-button.jsx +61 -0
  367. package/src/components/resize-columns.jsx +101 -0
  368. package/src/components/sidebar.jsx +236 -0
  369. package/src/components/sql-editor.jsx +411 -0
  370. package/src/components/sql-error-display.jsx +167 -0
  371. package/src/components/sync-migrations-button.jsx +87 -0
  372. package/src/components/table-error-dialog.jsx +65 -0
  373. package/src/components/table-toolbar.jsx +285 -0
  374. package/src/components/table-view.jsx +843 -0
  375. package/src/components/ui/alert.jsx +47 -0
  376. package/src/components/ui/button.jsx +48 -0
  377. package/src/components/ui/card.jsx +50 -0
  378. package/src/components/ui/checkbox.jsx +24 -0
  379. package/src/components/ui/collapsible.jsx +11 -0
  380. package/src/components/ui/dialog.jsx +96 -0
  381. package/src/components/ui/dropdown-menu.jsx +158 -0
  382. package/src/components/ui/input.jsx +19 -0
  383. package/src/components/ui/scroll-area.jsx +40 -0
  384. package/src/components/ui/select.jsx +121 -0
  385. package/src/components/ui/separator.jsx +25 -0
  386. package/src/components/ui/sheet.jsx +109 -0
  387. package/src/components/ui/sidebar.jsx +620 -0
  388. package/src/components/ui/skeleton.jsx +14 -0
  389. package/src/components/ui/table.jsx +86 -0
  390. package/src/components/ui/tabs.jsx +43 -0
  391. package/src/components/ui/toast.jsx +86 -0
  392. package/src/components/ui/toaster.jsx +35 -0
  393. package/src/components/ui/tooltip.jsx +28 -0
  394. package/src/context/database-context.js +510 -0
  395. package/src/hooks/use-mobile.jsx +19 -0
  396. package/src/hooks/use-sql-error.ts +23 -0
  397. package/src/hooks/use-toast.js +155 -0
  398. package/src/lib/database-queue.js +33 -0
  399. package/src/lib/error.js +20 -0
  400. package/src/lib/find-wrangler-config.js +67 -0
  401. package/src/lib/license.js +99 -0
  402. package/src/lib/migrations.js +415 -0
  403. package/src/lib/parse-sql-error.js +200 -0
  404. package/src/lib/request-deduplication.js +24 -0
  405. package/src/lib/schema-operations.js +103 -0
  406. package/src/lib/sql-error-types.js +14 -0
  407. package/src/lib/sql-operations.js +557 -0
  408. package/src/lib/utils.js +6 -0
@@ -0,0 +1,277 @@
1
+ // api/pull-remote/confirm/route.js
2
+
3
+ import { NextResponse } from 'next/server';
4
+ import { writeFile, mkdir, readdir, unlink } from 'fs/promises';
5
+ import path from 'path';
6
+ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
+ import {
8
+ executeSQL,
9
+ ErrorTypes,
10
+ formatSQLStatement,
11
+ getMigrationFileContent
12
+ } from '@/lib/sql-operations';
13
+ import { getCurrentSchema, analyzeDependencies } from '@/lib/schema-operations';
14
+ import { initMigrationsTable, recordMigration, getRemoteMigrations } from '@/lib/migrations.js';
15
+
16
+ /**
17
+ * Applies the pull migrations by:
18
+ * 1. Fetching remote migration metadata.
19
+ * 2. For each remote migration, fetching the migration file content from remote.
20
+ * 3. Staging the migration files.
21
+ * 4. Performing a destructive update on local objects.
22
+ * 5. Resetting the local migrations table.
23
+ * 6. Applying staged migrations sequentially (writing files, recording and executing them).
24
+ * 7. Replacing the local migrations folder with the staged files.
25
+ *
26
+ * This completely replaces the local state with the remote state.
27
+ *
28
+ * @param {string} projectDir - The project directory.
29
+ * @param {string} accountId - Cloudflare account ID.
30
+ * @param {string} apiToken - Cloudflare API token.
31
+ * @param {string} databaseName - The target D1 database name.
32
+ * @returns {object} Details of applied migrations.
33
+ */
34
+ async function applyPullMigrations(projectDir, accountId, apiToken, databaseName) {
35
+ const env = {
36
+ ...process.env,
37
+ CLOUDFLARE_API_TOKEN: apiToken,
38
+ CLOUDFLARE_ACCOUNT_ID: accountId
39
+ };
40
+
41
+ try {
42
+ // Define paths for the main migrations folder and a temporary staging folder.
43
+ const migrationsDir = path.join(projectDir, 'migrations');
44
+ const stagingDir = path.join(projectDir, 'migrations-temp');
45
+
46
+ // Ensure both directories exist.
47
+ await mkdir(migrationsDir, { recursive: true });
48
+ await mkdir(stagingDir, { recursive: true });
49
+
50
+ // Clear out any existing files in the staging folder.
51
+ const stagedFilesList = await readdir(stagingDir).catch(() => []);
52
+ await Promise.all(stagedFilesList.map(file => unlink(path.join(stagingDir, file))));
53
+
54
+ // --- STEP 1: Fetch remote migration metadata ---
55
+ console.log('Fetching remote migration metadata...');
56
+ const remoteMigrations = await getRemoteMigrations(projectDir, databaseName, env);
57
+ console.log('Remote migration metadata:', remoteMigrations);
58
+
59
+ // --- STEP 2: For each remote migration, fetch its file content ---
60
+ console.log('Fetching migration file content from remote...');
61
+ const stagedFiles = new Map();
62
+ for (const migration of remoteMigrations) {
63
+ try {
64
+ const migrationFileName = migration.name; // Use the remote migration's name.
65
+ const content = await getMigrationFileContent(projectDir, databaseName, migrationFileName, env);
66
+ stagedFiles.set(migrationFileName, content);
67
+ console.log(`Staged migration file: ${migrationFileName}`);
68
+ await writeFile(path.join(stagingDir, migrationFileName), content, 'utf8');
69
+ } catch (fileError) {
70
+ console.error(`Error fetching content for migration ${migration.name}:`, fileError);
71
+ throw new Error(`Failed to fetch migration file content for ${migration.name}`);
72
+ }
73
+ }
74
+
75
+ // --- STEP 3: Fetch local schema for destructive update ---
76
+ console.log('Fetching local schema for destructive update...');
77
+ const currentSchema = await getCurrentSchema(projectDir, databaseName, env, false);
78
+ const tableSchema = currentSchema.filter(obj =>
79
+ obj.type === 'table' && obj.name && obj.name.toLowerCase() !== 'if'
80
+ );
81
+ console.log('Local table schema:', tableSchema);
82
+ const dropOrder = tableSchema.length > 0
83
+ ? analyzeDependencies(
84
+ tableSchema.map(obj => ({
85
+ tableName: obj.name,
86
+ sql: obj.sql,
87
+ type: obj.type
88
+ }))
89
+ )
90
+ : [];
91
+ console.log('Computed drop order:', dropOrder);
92
+
93
+ // --- STEP 4: Destructive update (all-or-nothing) ---
94
+ console.log('Beginning destructive update...');
95
+ try {
96
+ console.log('Disabling foreign keys...');
97
+ await executeSQL(projectDir, databaseName, 'PRAGMA foreign_keys=OFF;', env, false);
98
+
99
+ // Drop triggers.
100
+ const triggers = currentSchema.filter(obj => obj.type === 'trigger');
101
+ for (const trigger of triggers) {
102
+ console.log(`Dropping trigger: ${trigger.name}`);
103
+ await executeSQL(
104
+ projectDir,
105
+ databaseName,
106
+ formatSQLStatement(`DROP TRIGGER IF EXISTS ${trigger.name}`),
107
+ env,
108
+ false
109
+ );
110
+ }
111
+ // Drop indexes.
112
+ const indexes = currentSchema.filter(obj => obj.type === 'index');
113
+ for (const index of indexes) {
114
+ console.log(`Dropping index: ${index.name}`);
115
+ await executeSQL(
116
+ projectDir,
117
+ databaseName,
118
+ formatSQLStatement(`DROP INDEX IF EXISTS ${index.name}`),
119
+ env,
120
+ false
121
+ );
122
+ }
123
+ // Drop tables in reverse dependency order.
124
+ for (const tableName of dropOrder.reverse()) {
125
+ console.log(`Dropping table: ${tableName}`);
126
+ await executeSQL(
127
+ projectDir,
128
+ databaseName,
129
+ formatSQLStatement(`DROP TABLE IF EXISTS ${tableName}`),
130
+ env,
131
+ false
132
+ );
133
+ }
134
+ console.log('Re-enabling foreign keys...');
135
+ await executeSQL(projectDir, databaseName, 'PRAGMA foreign_keys=ON;', env, false);
136
+ } catch (dropError) {
137
+ throw new Error(`Error dropping existing objects: ${dropError.message}`);
138
+ }
139
+
140
+ // --- STEP 5: Reset the local migrations table ---
141
+ try {
142
+ console.log('Resetting local migrations table...');
143
+ await initMigrationsTable(projectDir, databaseName, 'local', true);
144
+ } catch (initError) {
145
+ throw new Error(`Error resetting migrations table: ${initError.message}`);
146
+ }
147
+
148
+ // --- STEP 6: Apply staged migrations ---
149
+ // (Transactions removed because D1 operates in auto-commit mode)
150
+ const appliedPreview = { preview: [] };
151
+ let currentFilename = '';
152
+ try {
153
+ for (const [filename, content] of stagedFiles.entries()) {
154
+ currentFilename = filename;
155
+ console.log(`Applying migration: ${filename}`);
156
+ // Write the migration file to the main migrations folder.
157
+ await writeFile(path.join(migrationsDir, filename), content, 'utf8');
158
+
159
+ // Compute a checksum from the content.
160
+ const checksum = require('crypto')
161
+ .createHash('sha256')
162
+ .update(content)
163
+ .digest('hex');
164
+
165
+ console.log(`Recording migration: ${filename} with checksum ${checksum}`);
166
+ await recordMigration(
167
+ projectDir,
168
+ databaseName,
169
+ { name: filename, checksum },
170
+ env,
171
+ false
172
+ );
173
+
174
+ // Execute the migration SQL on the local database.
175
+ await executeSQL(projectDir, databaseName, content, env, false);
176
+
177
+ appliedPreview.preview.push({ migration: filename, action: 'applied' });
178
+ }
179
+ } catch (applyError) {
180
+ throw new Error(`Error applying migration ${currentFilename}: ${applyError.message}`);
181
+ }
182
+
183
+ // --- STEP 7: Replace main migrations folder with staged files ---
184
+ console.log('Replacing main migrations folder with staged files...');
185
+ const mainFiles = await readdir(migrationsDir).catch(() => []);
186
+ if (mainFiles.length) {
187
+ for (const file of mainFiles) {
188
+ console.log(`Deleting local migration file: ${file}`);
189
+ await unlink(path.join(migrationsDir, file));
190
+ }
191
+ }
192
+ for (const [filename, content] of stagedFiles.entries()) {
193
+ console.log(`Copying staged file ${filename} to main migrations folder`);
194
+ await writeFile(path.join(migrationsDir, filename), content, 'utf8');
195
+ }
196
+
197
+ console.log('Pull migration applied successfully.');
198
+ return {
199
+ appliedMigrations: Array.from(stagedFiles.keys()),
200
+ details: appliedPreview
201
+ };
202
+ } catch (error) {
203
+ console.error('Pull migration error:', error);
204
+ throw error;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * POST handler for pull-remote confirm.
210
+ * Reads the Wrangler configuration (via findWranglerConfig) to obtain the D1 database name,
211
+ * then applies the pull migrations.
212
+ */
213
+ export async function POST(req) {
214
+ try {
215
+ const { accountId, apiToken } = await req.json();
216
+ const projectDir = process.env.D1_PROJECT_DIR;
217
+ if (!projectDir) {
218
+ return NextResponse.json({
219
+ success: false,
220
+ error: {
221
+ type: ErrorTypes.VALIDATION_ERROR,
222
+ message: 'Project directory not configured'
223
+ }
224
+ }, { status: 500 });
225
+ }
226
+ const wranglerResult = await findWranglerConfig(projectDir);
227
+ if (!wranglerResult || !wranglerResult.config) {
228
+ return NextResponse.json({
229
+ success: false,
230
+ error: {
231
+ type: ErrorTypes.VALIDATION_ERROR,
232
+ message: 'Could not find Wrangler configuration'
233
+ }
234
+ }, { status: 400 });
235
+ }
236
+ const config = wranglerResult.config;
237
+ if (!config.d1_databases?.length) {
238
+ return NextResponse.json({
239
+ success: false,
240
+ error: {
241
+ type: ErrorTypes.VALIDATION_ERROR,
242
+ message: 'No D1 databases configured'
243
+ }
244
+ }, { status: 400 });
245
+ }
246
+ const databaseName = config.d1_databases[0].database_name;
247
+ const result = await applyPullMigrations(projectDir, accountId, apiToken, databaseName);
248
+ return NextResponse.json({
249
+ success: true,
250
+ message: 'Pull migrations applied successfully',
251
+ details: result
252
+ });
253
+ } catch (error) {
254
+ console.error('Pull remote confirm error:', error);
255
+ return NextResponse.json({
256
+ success: false,
257
+ error: {
258
+ type: error.type || ErrorTypes.EXECUTION_ERROR,
259
+ message: error.message || 'Failed to apply pull migrations',
260
+ details: error.details || {
261
+ suggestions: [
262
+ 'Check your Cloudflare credentials',
263
+ 'Verify database permissions',
264
+ 'Ensure all migration files are accessible'
265
+ ]
266
+ }
267
+ }
268
+ }, { status: 500 });
269
+ }
270
+ }
271
+
272
+ /**
273
+ * OPTIONS handler for pre-flight requests.
274
+ */
275
+ export async function OPTIONS() {
276
+ return new NextResponse(null, { status: 204 });
277
+ }
@@ -0,0 +1,143 @@
1
+ // api/pull-remote/preview/route.js
2
+
3
+ import { NextResponse } from 'next/server';
4
+ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
5
+ import { ErrorTypes,} from '@/lib/sql-operations';
6
+ import { getCurrentSchema, analyzeDependencies } from '@/lib/schema-operations';
7
+ import { getRemoteMigrations } from '@/lib/migrations.js';
8
+
9
+ /**
10
+ * Generates a preview for pulling remote migrations.
11
+ * Retrieves the remote schema and migration metadata, orders tables by dependency,
12
+ * and builds a preview object that lists which tables will be created and which migrations will be tracked.
13
+ *
14
+ * @param {string} projectDir - The project directory path.
15
+ * @param {string} accountId - Cloudflare account ID.
16
+ * @param {string} apiToken - Cloudflare API token.
17
+ * @param {string} databaseName - The target D1 database name.
18
+ * @returns {object} Preview object containing migration details.
19
+ */
20
+ async function generatePullPreview(projectDir, accountId, apiToken, databaseName) {
21
+ const env = {
22
+ ...process.env,
23
+ CLOUDFLARE_API_TOKEN: apiToken,
24
+ CLOUDFLARE_ACCOUNT_ID: accountId
25
+ };
26
+
27
+ try {
28
+ // Get the remote schema and migration metadata using provided helpers
29
+ const remoteSchema = await getCurrentSchema(projectDir, databaseName, env, true);
30
+ const remoteMigrations = await getRemoteMigrations(projectDir, databaseName, env);
31
+
32
+ // Analyze dependencies to order tables for creation
33
+ const orderedTables = analyzeDependencies(remoteSchema);
34
+
35
+ // Build the preview object
36
+ const preview = {
37
+ preview: [],
38
+ totalTables: remoteSchema.length,
39
+ totalMigrations: remoteMigrations.length
40
+ };
41
+
42
+ // Add each table (ordered by dependency) to the preview list
43
+ orderedTables.forEach((tableName, index) => {
44
+ const table = remoteSchema.find(t => t.name === tableName);
45
+ if (table) {
46
+ preview.preview.push({
47
+ name: tableName,
48
+ type: 'table',
49
+ action: 'will be created',
50
+ order: index + 1
51
+ });
52
+ }
53
+ });
54
+
55
+ // Add migration records to the preview.
56
+ // Since remote migrations do not include a checksum, we omit it.
57
+ remoteMigrations.forEach(migration => {
58
+ preview.preview.push({
59
+ name: migration.name,
60
+ type: 'migration',
61
+ action: 'will be tracked'
62
+ });
63
+ });
64
+
65
+ return preview;
66
+ } catch (error) {
67
+ console.error('Pull preview generation error:', error);
68
+ throw error;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * POST handler for pull-remote preview.
74
+ * Reads the Wrangler configuration (via findWranglerConfig) to get the D1 database name,
75
+ * then generates a preview of the migrations to be pulled.
76
+ */
77
+ export async function POST(req) {
78
+ try {
79
+ const { accountId, apiToken } = await req.json();
80
+ const projectDir = process.env.D1_PROJECT_DIR;
81
+
82
+ if (!projectDir) {
83
+ return NextResponse.json({
84
+ success: false,
85
+ error: {
86
+ type: ErrorTypes.VALIDATION_ERROR,
87
+ message: 'Project directory not configured'
88
+ }
89
+ }, { status: 500 });
90
+ }
91
+
92
+ // Load Wrangler configuration.
93
+ const wranglerResult = await findWranglerConfig(projectDir);
94
+ if (!wranglerResult || !wranglerResult.config) {
95
+ return NextResponse.json({
96
+ success: false,
97
+ error: {
98
+ type: ErrorTypes.VALIDATION_ERROR,
99
+ message: 'Could not find Wrangler configuration'
100
+ }
101
+ }, { status: 400 });
102
+ }
103
+ const config = wranglerResult.config;
104
+
105
+ // Ensure that at least one D1 database is configured.
106
+ if (!config.d1_databases?.length) {
107
+ return NextResponse.json({
108
+ success: false,
109
+ error: {
110
+ type: ErrorTypes.VALIDATION_ERROR,
111
+ message: 'No D1 databases configured'
112
+ }
113
+ }, { status: 400 });
114
+ }
115
+
116
+ // Use the first D1 database's name from the configuration.
117
+ const databaseName = config.d1_databases[0].database_name;
118
+ const preview = await generatePullPreview(projectDir, accountId, apiToken, databaseName);
119
+
120
+ return NextResponse.json({
121
+ success: true,
122
+ message: 'Pull migration preview generated',
123
+ details: preview
124
+ });
125
+ } catch (error) {
126
+ console.error('Pull remote preview error:', error);
127
+ return NextResponse.json({
128
+ success: false,
129
+ error: {
130
+ type: error.type || ErrorTypes.EXECUTION_ERROR,
131
+ message: error.message || 'Failed to generate pull migration preview',
132
+ details: error.details
133
+ }
134
+ }, { status: 500 });
135
+ }
136
+ }
137
+
138
+ /**
139
+ * OPTIONS handler for pre-flight requests.
140
+ */
141
+ export async function OPTIONS() {
142
+ return new NextResponse(null, { status: 204 });
143
+ }
@@ -0,0 +1,196 @@
1
+ // api/push-remote/confirm/route.js
2
+
3
+ import { NextResponse } from 'next/server';
4
+ import { readFile, readdir } from 'fs/promises';
5
+ import path from 'path';
6
+ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
+ import { executeSQL, ErrorTypes, tableExists, parseStatement, removeSQLComments } from '@/lib/sql-operations';
8
+ import { validateMigrationFile } from '@/lib/migrations.js';
9
+
10
+ async function pushToRemote(projectDir, accountId, apiToken, databaseName, preview = false) {
11
+ const env = {
12
+ ...process.env,
13
+ CLOUDFLARE_ACCOUNT_ID: accountId,
14
+ CLOUDFLARE_API_TOKEN: apiToken,
15
+ };
16
+
17
+ try {
18
+ // Create local migrations table (with checksum) and remote migrations table (without checksum)
19
+ const localCreateMigrationsTable = `
20
+ CREATE TABLE IF NOT EXISTS d1_migrations (
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ name TEXT NOT NULL UNIQUE,
23
+ checksum TEXT NOT NULL,
24
+ applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
25
+ );
26
+ `;
27
+ const remoteCreateMigrationsTable = `
28
+ CREATE TABLE IF NOT EXISTS d1_migrations (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ name TEXT NOT NULL UNIQUE,
31
+ applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
32
+ );
33
+ `;
34
+ await executeSQL(projectDir, databaseName, localCreateMigrationsTable);
35
+ await executeSQL(projectDir, databaseName, remoteCreateMigrationsTable, env, true);
36
+
37
+ // Get remote migration records using applied_at.
38
+ const remoteMigrations = await executeSQL(
39
+ projectDir,
40
+ databaseName,
41
+ 'SELECT name FROM d1_migrations ORDER BY applied_at;',
42
+ env,
43
+ true
44
+ );
45
+ const parseResults = (stdout) => {
46
+ try {
47
+ const parsed = JSON.parse(stdout);
48
+ return parsed[0]?.results || [];
49
+ } catch {
50
+ return [];
51
+ }
52
+ };
53
+ const remoteMigrationsMap = new Map(
54
+ parseResults(remoteMigrations).map(m => [m.name, m])
55
+ );
56
+
57
+ // Read migration files from disk.
58
+ const migrationsDir = path.join(projectDir, 'migrations');
59
+ const files = await readdir(migrationsDir);
60
+ const migrationFiles = files.filter(f => f.endsWith('.sql')).sort();
61
+
62
+ const results = { applied: [], skipped: [], preview: [] };
63
+
64
+ // Process each migration file.
65
+ for (const migrationFile of migrationFiles) {
66
+ const fullPath = path.join(migrationsDir, migrationFile);
67
+ const previewRecord = { name: migrationFile, action: '', reason: '' };
68
+ try {
69
+ const validation = await validateMigrationFile(fullPath);
70
+ if (!validation.isValid) {
71
+ previewRecord.action = 'failed validation';
72
+ previewRecord.reason = 'Migration validation failed';
73
+ results.preview.push(previewRecord);
74
+ continue;
75
+ }
76
+ // For remote, compare by migration file name.
77
+ if (remoteMigrationsMap.has(migrationFile)) {
78
+ previewRecord.action = 'skipped';
79
+ previewRecord.reason = 'Already applied';
80
+ results.preview.push(previewRecord);
81
+ results.skipped.push({ name: migrationFile, reason: previewRecord.reason });
82
+ continue;
83
+ }
84
+ // Read the migration content.
85
+ let content = await readFile(fullPath, 'utf8');
86
+ // Strip out any header comments (lines starting with "--").
87
+ content = removeSQLComments(content);
88
+ // Parse the SQL content to extract details.
89
+ const parsedStatement = parseStatement(content);
90
+ const tableName = parsedStatement.tableName;
91
+
92
+ // Only if the migration is a CREATE_TABLE do we check for existing table.
93
+ if (parsedStatement.type === 'CREATE_TABLE' && tableName) {
94
+ const exists = await tableExists(projectDir, databaseName, env, tableName, true);
95
+ if (exists) {
96
+ previewRecord.action = 'skipped';
97
+ previewRecord.reason = `Table "${tableName}" already exists`;
98
+ results.skipped.push({ name: migrationFile, reason: previewRecord.reason });
99
+ results.preview.push(previewRecord);
100
+ continue;
101
+ }
102
+ }
103
+ // For ALTER_TABLE and other migrations, we do not skip based on table existence.
104
+ previewRecord.action = 'will be applied';
105
+ results.preview.push(previewRecord);
106
+ if (!preview) {
107
+ // Execute the migration SQL on the remote database.
108
+ await executeSQL(projectDir, databaseName, content, env, true);
109
+ // Record the migration on remote (without checksum).
110
+ await executeSQL(
111
+ projectDir,
112
+ databaseName,
113
+ `INSERT INTO d1_migrations (name) VALUES ('${migrationFile}');`,
114
+ env,
115
+ true
116
+ );
117
+ previewRecord.action = 'applied';
118
+ results.applied.push({ name: migrationFile });
119
+ }
120
+ } catch (err) {
121
+ // If error indicates the object already exists, mark as skipped.
122
+ const errMsg = err.message || '';
123
+ const errStderr = (err.details && err.details.stderr) || '';
124
+ if (errMsg.includes("already exists") || errStderr.includes("already exists")) {
125
+ previewRecord.action = 'skipped';
126
+ previewRecord.reason = 'Already applied';
127
+ results.skipped.push({ name: migrationFile, reason: previewRecord.reason });
128
+ } else {
129
+ previewRecord.action = 'failed';
130
+ previewRecord.reason = errMsg || 'Failed to apply migration';
131
+ results.skipped.push({ name: migrationFile, reason: previewRecord.reason });
132
+ }
133
+ results.preview.push(previewRecord);
134
+ }
135
+ }
136
+ console.log("Push Confirm Result (server):", results);
137
+ return { success: true, preview: false, applied: results.applied.length, skipped: results.skipped.length, details: results };
138
+ } catch (error) {
139
+ throw {
140
+ type: ErrorTypes.EXECUTION_ERROR,
141
+ message: error.message || 'Failed to push migrations',
142
+ details: error.details || { error: error.stderr || error.message }
143
+ };
144
+ }
145
+ }
146
+
147
+ export async function POST(req) {
148
+ try {
149
+ const { accountId, apiToken } = await req.json();
150
+ const projectDir = process.env.D1_PROJECT_DIR;
151
+ if (!projectDir) {
152
+ return NextResponse.json({
153
+ success: false,
154
+ error: { message: 'Project directory not configured', type: ErrorTypes.VALIDATION_ERROR }
155
+ }, { status: 500 });
156
+ }
157
+ const wranglerResult = await findWranglerConfig(projectDir);
158
+ if (!wranglerResult || !wranglerResult.config) {
159
+ return NextResponse.json({
160
+ success: false,
161
+ error: { message: 'Could not find Wrangler configuration', type: ErrorTypes.VALIDATION_ERROR }
162
+ }, { status: 400 });
163
+ }
164
+ const config = wranglerResult.config;
165
+ if (!config.d1_databases?.length) {
166
+ return NextResponse.json({
167
+ success: false,
168
+ error: { message: 'No D1 databases configured', type: ErrorTypes.VALIDATION_ERROR }
169
+ }, { status: 400 });
170
+ }
171
+ const databaseName = config.d1_databases[0].database_name;
172
+ // Force preview to be false for actual execution.
173
+ const result = await pushToRemote(projectDir, accountId, apiToken, databaseName, false);
174
+ return NextResponse.json({
175
+ success: true,
176
+ message: 'Successfully pushed migrations to remote',
177
+ details: result
178
+ });
179
+ } catch (error) {
180
+ console.error('Push to remote confirm error:', error);
181
+ return NextResponse.json({
182
+ success: false,
183
+ error: {
184
+ type: error.type || ErrorTypes.EXECUTION_ERROR,
185
+ message: error.message || 'Failed to push to remote',
186
+ details: error.details || { error: error.stderr || error.message }
187
+ }
188
+ }, { status: error.type === ErrorTypes.VALIDATION_ERROR ? 400 : 500 });
189
+ }
190
+ }
191
+
192
+ export async function OPTIONS() {
193
+ return new NextResponse(null, { status: 204 });
194
+ }
195
+
196
+