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,169 @@
1
+ // components/editable-row.jsx
2
+ 'use client';
3
+
4
+ import React, { useState } from 'react';
5
+ import { TableRow, TableCell } from '@/components/ui/table';
6
+ import { Input } from '@/components/ui/input';
7
+ import { Checkbox } from '@/components/ui/checkbox';
8
+ import { Trash2 } from 'lucide-react';
9
+ import { Button } from '@/components/ui/button';
10
+ import {
11
+ Select,
12
+ SelectContent,
13
+ SelectItem,
14
+ SelectTrigger,
15
+ SelectValue,
16
+ } from "@/components/ui/select";
17
+
18
+ function cleanValue(value) {
19
+ return typeof value === 'string' ? value.replace(/^'|'$/g, '') : value;
20
+ }
21
+
22
+ export function EditableRow({
23
+ schema,
24
+ onRemove,
25
+ onChange,
26
+ showCheckbox = false,
27
+ initialData = {}
28
+ }) {
29
+ const [rowData, setRowData] = useState(() => {
30
+ return schema.reduce((acc, col) => {
31
+ let defaultValue = initialData[col.name] ?? null;
32
+ defaultValue = cleanValue(defaultValue);
33
+
34
+ if (defaultValue === null) {
35
+ if (col.dflt_value) {
36
+ defaultValue = cleanValue(col.dflt_value);
37
+ } else if (col.type.toUpperCase() === 'INTEGER') {
38
+ defaultValue = '';
39
+ } else if (col.type.toUpperCase() === 'TEXT') {
40
+ defaultValue = '';
41
+ }
42
+ }
43
+
44
+ acc[col.name] = defaultValue;
45
+ return acc;
46
+ }, {});
47
+ });
48
+
49
+ const handleChange = (column, value) => {
50
+ const newData = { ...rowData, [column]: value };
51
+ setRowData(newData);
52
+ onChange?.(newData);
53
+ };
54
+
55
+ const isBoolean = (col) => {
56
+ const type = col.type?.toLowerCase() || '';
57
+ return type === 'boolean' ||
58
+ type === 'bool' ||
59
+ (type === 'integer' && col.name.toLowerCase().startsWith('is_'));
60
+ };
61
+
62
+ return (
63
+ <TableRow className="bg-orange-50/50">
64
+ <TableCell className="w-10 p-0">
65
+ <div className="pl-1 flex items-center">
66
+ {showCheckbox ? (
67
+ <Checkbox disabled />
68
+ ) : (
69
+ <Button
70
+ variant="ghost"
71
+ size="icon"
72
+ className="h-8 w-8 text-orange-700 hover:text-orange-800"
73
+ onClick={onRemove}
74
+ >
75
+ <Trash2 className="h-4 w-4" />
76
+ </Button>
77
+ )}
78
+ </div>
79
+ </TableCell>
80
+ {schema.map((col) => {
81
+ const isPrimaryKey = col.pk === 1;
82
+ const allowedValues = col.check || null;
83
+
84
+ // Handle boolean fields
85
+ if (isBoolean(col)) {
86
+ // Parse default value from schema
87
+ let defaultBoolValue = 'false';
88
+ if (col.dflt_value !== null && col.dflt_value !== undefined) {
89
+ // Handle different formats of default values
90
+ const dfltVal = col.dflt_value.toString().toLowerCase();
91
+ defaultBoolValue = (
92
+ dfltVal === '1' ||
93
+ dfltVal === 'true' ||
94
+ dfltVal === "'true'" ||
95
+ dfltVal === '"true"'
96
+ ) ? 'true' : 'false';
97
+ }
98
+
99
+ // Use rowData if it exists, otherwise use default
100
+ const currentValue = rowData[col.name] !== null && rowData[col.name] !== undefined
101
+ ? (rowData[col.name] === 1 || rowData[col.name] === true || rowData[col.name] === 'true' ? 'true' : 'false')
102
+ : defaultBoolValue;
103
+
104
+ return (
105
+ <TableCell key={col.name} className="border-x border-neutral-200 p-0">
106
+ <div className="w-full">
107
+ <Select
108
+ value={currentValue}
109
+ onValueChange={(value) => handleChange(col.name, value === 'true' ? 1 : 0)}
110
+ // Removed disabled={isPrimaryKey} to allow editing
111
+ >
112
+ <SelectTrigger
113
+ className="w-full h-9 min-w-0 rounded-none border-0 bg-orange-50 text-orange-900"
114
+ title={`Default: ${defaultBoolValue}`}
115
+ >
116
+ <SelectValue placeholder={`Select ${col.name}`} />
117
+ </SelectTrigger>
118
+ <SelectContent className="min-w-[8rem]">
119
+ <SelectItem value="true">true</SelectItem>
120
+ <SelectItem value="false">false</SelectItem>
121
+ </SelectContent>
122
+ </Select>
123
+ </div>
124
+ </TableCell>
125
+ );
126
+ }
127
+
128
+ // Handle fields with check constraints
129
+ if (allowedValues?.length > 0) {
130
+ return (
131
+ <TableCell key={col.name} className="border-x border-neutral-200 p-0">
132
+ <div className="w-full">
133
+ <Select
134
+ value={rowData[col.name] ?? allowedValues[0]}
135
+ onValueChange={(value) => handleChange(col.name, value)}
136
+ // Removed disabled={isPrimaryKey} to allow editing
137
+ >
138
+ <SelectTrigger className="w-full h-9 min-w-0 rounded-none border-0 bg-orange-50 text-orange-900">
139
+ <SelectValue placeholder={`Select ${col.name}`} />
140
+ </SelectTrigger>
141
+ <SelectContent className="min-w-[8rem]">
142
+ {allowedValues.map(value => (
143
+ <SelectItem key={value} value={value}>
144
+ {value}
145
+ </SelectItem>
146
+ ))}
147
+ </SelectContent>
148
+ </Select>
149
+ </div>
150
+ </TableCell>
151
+ );
152
+ }
153
+
154
+ // Default input for other fields (primary key input is now editable)
155
+ return (
156
+ <TableCell key={col.name} className="border-x border-neutral-200 p-0">
157
+ <Input
158
+ value={rowData[col.name] ?? ''}
159
+ onChange={(e) => handleChange(col.name, e.target.value)}
160
+ className="w-full min-w-0 rounded-none border-0 px-2 bg-orange-50 text-orange-900"
161
+ placeholder={isPrimaryKey ? 'Auto-generated' : `Enter ${col.name}`}
162
+ // Removed disabled={isPrimaryKey} so primary key can be edited
163
+ />
164
+ </TableCell>
165
+ );
166
+ })}
167
+ </TableRow>
168
+ );
169
+ }
@@ -0,0 +1,278 @@
1
+ // components/environemtn-handler.jsx
2
+ "use client";
3
+
4
+ import { useState } from "react";
5
+ import { useToast } from "@/hooks/use-toast";
6
+ import { useDatabase } from "@/context/database-context";
7
+ import PushPreviewToast from "./push-preview-toast";
8
+ import PullPreviewToast from "./pull-preview-toast";
9
+
10
+ const ErrorTypes = {
11
+ FOREIGN_KEY_ERROR: "FOREIGN_KEY_ERROR",
12
+ TABLE_EXISTS: "TABLE_EXISTS",
13
+ CONNECTION_ERROR: "CONNECTION_ERROR",
14
+ CONFIG_ERROR: "CONFIG_ERROR",
15
+ PULL_ERROR: "PULL_ERROR"
16
+ };
17
+
18
+ export function useEnvironmentController() {
19
+ const [isConnecting, setIsConnecting] = useState(false);
20
+ const [isPushing, setIsPushing] = useState(false);
21
+ const [showPreview, setShowPreview] = useState(false);
22
+ const [previewData, setPreviewData] = useState(null);
23
+ const [previewError, setPreviewError] = useState(null);
24
+ const [previewType, setPreviewType] = useState(null); // "push" or "pull"
25
+ const [previewSuccess, setPreviewSuccess] = useState(null);
26
+ const { toast } = useToast();
27
+ const { refreshTables } = useDatabase();
28
+
29
+ const clearPreviewState = () => {
30
+ setShowPreview(false);
31
+ setPreviewData(null);
32
+ setPreviewError(null);
33
+ setPreviewType(null);
34
+ setPreviewSuccess(null);
35
+ };
36
+
37
+ // Validate stored credentials
38
+ const validateStoredCredentials = async () => {
39
+ const storedCreds = localStorage.getItem("cf_credentials");
40
+ if (!storedCreds) return null;
41
+ try {
42
+ const credentials = JSON.parse(storedCreds);
43
+ const response = await fetch("/api/cloudflare", {
44
+ method: "POST",
45
+ headers: { "Content-Type": "application/json" },
46
+ body: JSON.stringify(credentials)
47
+ });
48
+ if (!response.ok) throw new Error("Invalid stored credentials");
49
+ const data = await response.json();
50
+ return { ...credentials, databaseId: data.database.id };
51
+ } catch (error) {
52
+ console.error("Failed to validate stored credentials:", error);
53
+ localStorage.removeItem("cf_credentials");
54
+ return null;
55
+ }
56
+ };
57
+
58
+ // Push to remote preview
59
+ const pushToRemote = async () => {
60
+ try {
61
+ setPreviewType("push");
62
+ setShowPreview(true);
63
+ setIsPushing(true);
64
+ setPreviewError(null);
65
+ setPreviewSuccess(null);
66
+ setPreviewData({ preview: [] }); // show loading state
67
+
68
+ const credentials = await validateStoredCredentials();
69
+ if (!credentials) throw new Error('No valid credentials found');
70
+
71
+ const response = await fetch('/api/push-remote/preview', {
72
+ method: 'POST',
73
+ headers: { 'Content-Type': 'application/json' },
74
+ body: JSON.stringify(credentials)
75
+ });
76
+
77
+ const data = await response.json();
78
+ if (!data.success) {
79
+ throw new Error(data.error?.message || 'Failed to generate preview');
80
+ }
81
+
82
+ setPreviewData(data.details.details);
83
+ } catch (error) {
84
+ console.error('Push to remote preview failed:', error);
85
+ setPreviewError(error);
86
+ toast({
87
+ title: "Preview Failed",
88
+ description: error.message || 'Failed to generate preview',
89
+ variant: "destructive",
90
+ });
91
+ } finally {
92
+ setIsPushing(false);
93
+ }
94
+ };
95
+
96
+ // Confirm push
97
+ const confirmPush = async () => {
98
+ try {
99
+ setIsPushing(true);
100
+ setPreviewError(null);
101
+ setPreviewSuccess(null);
102
+
103
+ const credentials = await validateStoredCredentials();
104
+ if (!credentials) throw new Error("No valid credentials found");
105
+
106
+ const response = await fetch("/api/push-remote/confirm", {
107
+ method: "POST",
108
+ headers: { "Content-Type": "application/json" },
109
+ body: JSON.stringify(credentials)
110
+ });
111
+
112
+ const data = await response.json();
113
+ if (!data.success) {
114
+ throw new Error(data.error?.message || 'Failed to confirm push');
115
+ }
116
+
117
+ // Update the preview data to show applied status
118
+ setPreviewData(prev => ({
119
+ ...prev,
120
+ preview: prev.preview.map(item => ({
121
+ ...item,
122
+ action: item.action === 'will be applied' ? 'applied' : item.action
123
+ }))
124
+ }));
125
+
126
+ // Set success message instead of showing toast
127
+ setPreviewSuccess(`Applied ${data.details.applied} migration(s), skipped ${data.details.skipped}.`);
128
+ } catch (error) {
129
+ console.error("Push to remote confirm failed:", error);
130
+ setPreviewError(error);
131
+ } finally {
132
+ setIsPushing(false);
133
+ }
134
+ };
135
+
136
+ // Pull to remote preview
137
+ const pullToRemotePreview = async () => {
138
+ try {
139
+ setPreviewType("pull");
140
+ setShowPreview(true);
141
+ setIsPushing(true);
142
+ setPreviewError(null);
143
+ setPreviewSuccess(null);
144
+ setPreviewData({ preview: [] }); // show loading state
145
+
146
+ const credentials = await validateStoredCredentials();
147
+ if (!credentials) throw new Error("No valid credentials found");
148
+
149
+ const response = await fetch('/api/pull-remote/preview', {
150
+ method: 'POST',
151
+ headers: { 'Content-Type': 'application/json' },
152
+ body: JSON.stringify(credentials)
153
+ });
154
+ const data = await response.json();
155
+ if (!data.success) {
156
+ throw new Error(data.error?.message || 'Failed to generate pull preview');
157
+ }
158
+ setPreviewData(data.details);
159
+ } catch (error) {
160
+ console.error('Pull to remote preview failed:', error);
161
+ setPreviewError(error);
162
+ toast({
163
+ title: "Preview Failed",
164
+ description: error.message || 'Failed to generate pull preview',
165
+ variant: "destructive",
166
+ });
167
+ } finally {
168
+ setIsPushing(false);
169
+ }
170
+ };
171
+
172
+ // Confirm pull
173
+ const confirmPull = async () => {
174
+ try {
175
+ setIsPushing(true);
176
+ setPreviewError(null);
177
+
178
+ const credentials = await validateStoredCredentials();
179
+ if (!credentials) throw new Error("No valid credentials found");
180
+
181
+ const response = await fetch("/api/pull-remote/confirm", {
182
+ method: "POST",
183
+ headers: { "Content-Type": "application/json" },
184
+ body: JSON.stringify(credentials)
185
+ });
186
+
187
+ const data = await response.json();
188
+ if (!data.success) {
189
+ throw new Error(data.error?.message || 'Failed to confirm pull');
190
+ }
191
+
192
+ clearPreviewState();
193
+ toast({
194
+ title: "Migration Success",
195
+ description: `Pull migrations applied successfully.`,
196
+ });
197
+ await refreshTables();
198
+ } catch (error) {
199
+ console.error("Pull to remote confirm failed:", error);
200
+ setPreviewError(error);
201
+ toast({
202
+ title: "Migration Failed",
203
+ description: error.message || "Failed to pull migrations from remote",
204
+ variant: "destructive",
205
+ });
206
+ } finally {
207
+ setIsPushing(false);
208
+ }
209
+ };
210
+
211
+ // Connect to Cloudflare
212
+ async function connectToCloudflare(credentials) {
213
+ try {
214
+ setIsConnecting(true);
215
+ const response = await fetch("/api/cloudflare", {
216
+ method: "POST",
217
+ headers: { "Content-Type": "application/json" },
218
+ body: JSON.stringify(credentials)
219
+ });
220
+ const data = await response.json();
221
+ if (!response.ok) throw new Error(data.error || "Failed to connect to Cloudflare");
222
+ localStorage.setItem("cf_credentials", JSON.stringify({
223
+ ...credentials,
224
+ databaseId: data.database.id
225
+ }));
226
+ toast({
227
+ title: "Connected to Cloudflare",
228
+ description: `Connected to database: ${data.database.name}`,
229
+ variant: "default"
230
+ });
231
+ } catch (error) {
232
+ toast({
233
+ title: "Connection Failed",
234
+ description: error.message || "Failed to connect to Cloudflare",
235
+ variant: "destructive"
236
+ });
237
+ throw error;
238
+ } finally {
239
+ setIsConnecting(false);
240
+ }
241
+ }
242
+
243
+ const PreviewUI = showPreview && (
244
+ previewType === "pull" ? (
245
+ <PullPreviewToast
246
+ preview={previewData?.preview || []}
247
+ onConfirm={confirmPull}
248
+ onCancel={clearPreviewState}
249
+ isConfirming={isPushing}
250
+ error={previewError}
251
+ isLoading={isPushing && !previewData?.preview?.length}
252
+ />
253
+ ) : (
254
+ <PushPreviewToast
255
+ preview={previewData?.preview || []}
256
+ onConfirm={confirmPush}
257
+ onCancel={clearPreviewState}
258
+ isConfirming={isPushing}
259
+ error={previewError}
260
+ success={previewSuccess}
261
+ isLoading={isPushing && !previewData?.preview?.length}
262
+ />
263
+ )
264
+ );
265
+
266
+ return {
267
+ isConnecting,
268
+ isPushing,
269
+ showPreview,
270
+ previewError,
271
+ pushToRemote,
272
+ pullToRemotePreview,
273
+ confirmPull,
274
+ connectToCloudflare,
275
+ validateStoredCredentials,
276
+ PreviewUI
277
+ };
278
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ Select,
3
+ SelectContent,
4
+ SelectItem,
5
+ SelectTrigger,
6
+ SelectValue
7
+ } from '@/components/ui/select';
8
+ import { HardDrive, Download, Upload, Loader2 } from 'lucide-react';
9
+
10
+ export function EnvironmentSelect({
11
+ value,
12
+ onValueChange,
13
+ isLoading,
14
+ disabled,
15
+ showPreview
16
+ }) {
17
+ return (
18
+ <Select
19
+ value={value}
20
+ onValueChange={onValueChange}
21
+ disabled={disabled || isLoading || showPreview}
22
+ >
23
+ <SelectTrigger className="w-[104px] bg-white border-neutral-200 font-medium">
24
+ <div className="flex items-center gap-1 text-sm">
25
+ {isLoading || showPreview ? (
26
+ <>
27
+ <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
28
+ <span className="text-muted-foreground font-medium">
29
+ {value === "pull" ? "Pulling..." : "Pushing..."}
30
+ </span>
31
+ </>
32
+ ) : (
33
+ <SelectValue placeholder="Environment" />
34
+ )}
35
+ </div>
36
+ </SelectTrigger>
37
+ <SelectContent>
38
+ <SelectItem value="local">
39
+ <div className="flex items-center gap-2">
40
+ <HardDrive className="h-4 w-4" />
41
+ <span>Local</span>
42
+ </div>
43
+ </SelectItem>
44
+ <SelectItem value="pull">
45
+ <div className="flex items-center gap-2">
46
+ <Download className="h-4 w-4" />
47
+ <span>Pull remote</span>
48
+ </div>
49
+ </SelectItem>
50
+ <SelectItem value="production">
51
+ <div className="flex items-center gap-2">
52
+ <Upload className="h-4 w-4" />
53
+ <span>Push remote</span>
54
+ </div>
55
+ </SelectItem>
56
+ </SelectContent>
57
+ </Select>
58
+ );
59
+ }
@@ -0,0 +1,188 @@
1
+ "use client";
2
+
3
+ import React, { useEffect, useState } from "react";
4
+ import { Button } from "@/components/ui/button";
5
+ import { ScrollArea } from "@/components/ui/scroll-area";
6
+ import {
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ } from "@/components/ui/table";
14
+ import { FileText, Loader2 } from "lucide-react";
15
+ import { cn } from "@/lib/utils";
16
+
17
+ export function PullPreviewToast({
18
+ preview = [],
19
+ onConfirm,
20
+ onCancel,
21
+ isConfirming,
22
+ error,
23
+ isLoading,
24
+ }) {
25
+ console.log("PullPreviewToast rendered with:", {
26
+ previewLength: preview.length,
27
+ isConfirming,
28
+ error,
29
+ isLoading,
30
+ });
31
+
32
+ useEffect(() => {
33
+ console.log("PullPreviewToast mounted/updated");
34
+ return () => console.log("PullPreviewToast unmounted");
35
+ }, []);
36
+
37
+ const [isDetailsOpen, setIsDetailsOpen] = useState(false);
38
+
39
+ // Loading state
40
+ if (isLoading) {
41
+ console.log("Rendering loading state");
42
+ return (
43
+ <div className="fixed bottom-4 right-4 z-50 font-sans w-[600px]">
44
+ <div className="rounded-lg border p-4 shadow-lg bg-background">
45
+ <div className="flex items-start gap-3">
46
+ <Loader2 className="h-5 w-5 text-neutral-600 shrink-0 mt-0.5 animate-spin" />
47
+ <div className="flex-1 space-y-3">
48
+ <div className="space-y-1">
49
+ <p className="font-medium text-neutral-800">
50
+ Preparing Pull Migration
51
+ </p>
52
+ <p className="text-sm text-neutral-600">
53
+ Checking remote migrations...
54
+ </p>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ );
61
+ }
62
+
63
+ if (!preview?.length) {
64
+ console.log("No preview data available");
65
+ return (
66
+ <div className="fixed bottom-4 right-4 z-50 w-[600px]">
67
+ <div className="rounded-lg border bg-destructive/15 p-4">
68
+ <div className="flex items-center gap-2">
69
+ <FileText className="h-5 w-5 text-destructive" />
70
+ <p className="text-sm font-medium text-destructive">
71
+ No preview data available
72
+ </p>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ );
77
+ }
78
+
79
+ // Filter migrations to only include files with a ".sql" extension
80
+ const sqlMigrations = preview.filter((item) => {
81
+ const migrationName = item.migration || item.name || "";
82
+ return migrationName.endsWith(".sql");
83
+ });
84
+
85
+ // Count only SQL migrations for the header
86
+ const totalMigrations = sqlMigrations.length;
87
+ console.log("Migration stats:", { totalMigrations });
88
+
89
+ return (
90
+ <div className="fixed bottom-4 right-4 z-50 font-sans w-[600px]">
91
+ <div
92
+ className={cn(
93
+ "rounded-lg border p-4 shadow-lg",
94
+ error ? "bg-destructive/15" : "bg-background"
95
+ )}
96
+ >
97
+ <div className="flex items-start gap-3">
98
+ <div className="flex-1 space-y-3">
99
+ {/* Header */}
100
+ <div className="space-y-1">
101
+ <h5
102
+ className={cn(
103
+ "font-medium",
104
+ error ? "text-destructive" : "text-neutral-900"
105
+ )}
106
+ >
107
+ {error ? "Pull Migration Error" : "Pull Migration Preview"}
108
+ </h5>
109
+ <p
110
+ className={cn(
111
+ "text-sm",
112
+ error ? "text-destructive/80" : "text-neutral-700"
113
+ )}
114
+ >
115
+ {error
116
+ ? error.message
117
+ : `${totalMigrations} migration(s) will be applied`}
118
+ </p>
119
+ </div>
120
+
121
+ {/* Migration Details */}
122
+ <div>
123
+ <button
124
+ onClick={() => setIsDetailsOpen(!isDetailsOpen)}
125
+ className="text-sm font-medium hover:underline"
126
+ >
127
+ {isDetailsOpen ? "Hide Details" : "Show Details"}
128
+ </button>
129
+
130
+ {isDetailsOpen && (
131
+ <ScrollArea className="h-[480px] mt-2 rounded border border-neutral-200">
132
+ <Table>
133
+ <TableHeader>
134
+ <TableRow>
135
+ <TableHead className="w-[30px]"></TableHead>
136
+ <TableHead className="pl-0">Migration</TableHead>
137
+ </TableRow>
138
+ </TableHeader>
139
+ <TableBody>
140
+ {sqlMigrations.map((item, index) => (
141
+ <TableRow key={index}>
142
+ <TableCell className="w-[30px] pr-1 pl-2">
143
+ <FileText className="h-4 w-4" />
144
+ </TableCell>
145
+ <TableCell className="font-mono text-xs pr-5 pl-0.5">
146
+ {item.migration || item.name}
147
+ </TableCell>
148
+ </TableRow>
149
+ ))}
150
+ </TableBody>
151
+ </Table>
152
+ </ScrollArea>
153
+ )}
154
+ </div>
155
+
156
+ {/* Action Buttons */}
157
+ <div className="flex gap-2 pt-1">
158
+ <Button
159
+ onClick={onConfirm}
160
+ disabled={isConfirming}
161
+ className="flex-1"
162
+ >
163
+ {isConfirming ? (
164
+ <>
165
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
166
+ Confirming...
167
+ </>
168
+ ) : (
169
+ "Confirm Pull"
170
+ )}
171
+ </Button>
172
+ <Button
173
+ variant="outline"
174
+ onClick={onCancel}
175
+ disabled={isConfirming}
176
+ className="flex-1"
177
+ >
178
+ Cancel
179
+ </Button>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ );
186
+ }
187
+
188
+ export default PullPreviewToast;