d1s 0.2.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (403) hide show
  1. package/README.md +14 -1
  2. package/dist/.next/.next/BUILD_ID +1 -1
  3. package/dist/.next/.next/app-build-manifest.json +121 -79
  4. package/dist/.next/.next/app-path-routes-manifest.json +1 -1
  5. package/dist/.next/.next/build-manifest.json +7 -7
  6. package/dist/.next/.next/cache/.rscinfo +1 -1
  7. package/dist/.next/.next/cache/.tsbuildinfo +1 -1
  8. package/dist/.next/.next/cache/webpack/client-development/0.pack.gz +0 -0
  9. package/dist/.next/.next/cache/webpack/client-development/1.pack.gz +0 -0
  10. package/dist/.next/.next/cache/webpack/client-development/index.pack.gz +0 -0
  11. package/dist/.next/.next/cache/webpack/client-development/index.pack.gz.old +0 -0
  12. package/dist/.next/.next/cache/webpack/client-production/0.pack +0 -0
  13. package/dist/.next/.next/cache/webpack/client-production/1.pack +0 -0
  14. package/dist/.next/.next/cache/webpack/client-production/10.pack +0 -0
  15. package/dist/.next/.next/cache/webpack/client-production/11.pack +0 -0
  16. package/dist/.next/.next/cache/webpack/client-production/12.pack +0 -0
  17. package/dist/.next/.next/cache/webpack/client-production/2.pack +0 -0
  18. package/dist/.next/.next/cache/webpack/client-production/3.pack +0 -0
  19. package/dist/.next/.next/cache/webpack/client-production/4.pack +0 -0
  20. package/dist/.next/.next/cache/webpack/client-production/5.pack +0 -0
  21. package/dist/.next/.next/cache/webpack/client-production/6.pack +0 -0
  22. package/dist/.next/.next/cache/webpack/client-production/7.pack +0 -0
  23. package/dist/.next/.next/cache/webpack/client-production/8.pack +0 -0
  24. package/dist/.next/.next/cache/webpack/client-production/9.pack +0 -0
  25. package/dist/.next/.next/cache/webpack/client-production/index.pack +0 -0
  26. package/dist/.next/.next/cache/webpack/client-production/index.pack.old +0 -0
  27. package/dist/.next/.next/cache/webpack/edge-server-production/index.pack +0 -0
  28. package/dist/.next/.next/cache/webpack/server-development/0.pack.gz +0 -0
  29. package/dist/.next/.next/cache/webpack/server-development/1.pack.gz +0 -0
  30. package/dist/.next/.next/cache/webpack/server-development/index.pack.gz +0 -0
  31. package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
  32. package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
  33. package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
  34. package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
  35. package/dist/.next/.next/next-minimal-server.js.nft.json +1 -1
  36. package/dist/.next/.next/next-server.js.nft.json +1 -1
  37. package/dist/.next/.next/prerender-manifest.json +1 -1
  38. package/dist/.next/.next/react-loadable-manifest.json +11 -1
  39. package/dist/.next/.next/required-server-files.json +1 -1
  40. package/dist/.next/.next/routes-manifest.json +1 -1
  41. package/dist/.next/.next/server/app/_not-found/page.js +1 -1
  42. package/dist/.next/.next/server/app/_not-found/page.js.nft.json +1 -1
  43. package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  44. package/dist/.next/.next/server/app/_not-found.html +1 -1
  45. package/dist/.next/.next/server/app/_not-found.rsc +5 -5
  46. package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
  47. package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
  48. package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
  49. package/dist/.next/.next/server/app/api/databases/route.js +1 -1
  50. package/dist/.next/.next/server/app/api/databases/route.js.nft.json +1 -1
  51. package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
  52. package/dist/.next/.next/server/app/api/migrations/list/route.js +26 -0
  53. package/dist/.next/.next/server/app/api/migrations/list/route.js.nft.json +1 -0
  54. package/dist/.next/.next/server/app/api/migrations/list/route_client-reference-manifest.js +1 -0
  55. package/dist/.next/.next/server/app/api/migrations/sync/route.js +5 -5
  56. package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
  57. package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
  58. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +4 -4
  59. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
  60. package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
  61. package/dist/.next/.next/server/app/api/pro/route.js +1 -0
  62. package/dist/.next/.next/server/app/api/pro/route.js.nft.json +1 -0
  63. package/dist/.next/.next/server/app/api/pro/route_client-reference-manifest.js +1 -0
  64. package/dist/.next/.next/server/app/api/pull-data/confirm/route.js +1 -1
  65. package/dist/.next/.next/server/app/api/pull-data/confirm/route.js.nft.json +1 -1
  66. package/dist/.next/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
  67. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +4 -4
  68. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
  69. package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
  70. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +4 -4
  71. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
  72. package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
  73. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +6 -6
  74. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
  75. package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
  76. package/dist/.next/.next/server/app/api/push-remote/preview/route.js +6 -6
  77. package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
  78. package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
  79. package/dist/.next/.next/server/app/api/query/route.js +9 -9
  80. package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -1
  81. package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
  82. package/dist/.next/.next/server/app/api/schema/route.js +1 -0
  83. package/dist/.next/.next/server/app/api/schema/route.js.nft.json +1 -0
  84. package/dist/.next/.next/server/app/api/schema/route_client-reference-manifest.js +1 -0
  85. package/dist/.next/.next/server/app/api/tables/[name]/import/route.js +1 -0
  86. package/dist/.next/.next/server/app/api/tables/[name]/import/route.js.nft.json +1 -0
  87. package/dist/.next/.next/server/app/api/tables/[name]/import/route_client-reference-manifest.js +1 -0
  88. package/dist/.next/.next/server/app/api/tables/[name]/route.js +5 -5
  89. package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
  90. package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
  91. package/dist/.next/.next/server/app/api/tables/route.js +2 -2
  92. package/dist/.next/.next/server/app/api/tables/route.js.nft.json +1 -1
  93. package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
  94. package/dist/.next/.next/server/app/api/time-travel/preview/route.js +1 -0
  95. package/dist/.next/.next/server/app/api/time-travel/preview/route.js.nft.json +1 -0
  96. package/dist/.next/.next/server/app/api/time-travel/preview/route_client-reference-manifest.js +1 -0
  97. package/dist/.next/.next/server/app/api/time-travel/restore/route.js +1 -0
  98. package/dist/.next/.next/server/app/api/time-travel/restore/route.js.nft.json +1 -0
  99. package/dist/.next/.next/server/app/api/time-travel/restore/route_client-reference-manifest.js +1 -0
  100. package/dist/.next/.next/server/app/api/update/route.js +1 -1
  101. package/dist/.next/.next/server/app/api/update/route.js.nft.json +1 -1
  102. package/dist/.next/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  103. package/dist/.next/.next/server/app/index.html +5 -3
  104. package/dist/.next/.next/server/app/index.rsc +6 -6
  105. package/dist/.next/.next/server/app/page.js +15 -15
  106. package/dist/.next/.next/server/app/page.js.nft.json +1 -1
  107. package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -1
  108. package/dist/.next/.next/server/app-paths-manifest.json +10 -4
  109. package/dist/.next/.next/server/chunks/226.js +12 -12
  110. package/dist/.next/.next/server/chunks/391.js +1 -1
  111. package/dist/.next/.next/server/chunks/452.js +1 -1
  112. package/dist/.next/.next/server/chunks/487.js +1 -0
  113. package/dist/.next/.next/server/chunks/572.js +1 -1
  114. package/dist/.next/.next/server/chunks/992.js +3 -3
  115. package/dist/.next/{server/chunks/638.js → .next/server/chunks/994.js} +3 -3
  116. package/dist/.next/.next/server/middleware-build-manifest.js +1 -1
  117. package/dist/.next/.next/server/middleware-react-loadable-manifest.js +1 -1
  118. package/dist/.next/.next/server/next-font-manifest.js +1 -1
  119. package/dist/.next/.next/server/next-font-manifest.json +1 -1
  120. package/dist/.next/.next/server/pages/404.html +1 -1
  121. package/dist/.next/.next/server/pages/500.html +1 -1
  122. package/dist/.next/.next/server/pages-manifest.json +1 -1
  123. package/dist/.next/.next/server/server-reference-manifest.json +1 -1
  124. package/dist/.next/.next/static/-OO4tE7EKr8o62Bne-ODo/_buildManifest.js +1 -0
  125. package/dist/.next/.next/static/3kAeIJC56X7aw1Fk5_OXO/_buildManifest.js +1 -0
  126. package/dist/.next/.next/static/J8r9W6xxmYYvuKehItNuW/_buildManifest.js +1 -0
  127. package/dist/.next/.next/static/arc9h7hbaQzL1Dl0iuVrT/_buildManifest.js +1 -0
  128. package/dist/.next/.next/static/chunks/1a258343.3b3e7ba5ba0bd0d2.js +1 -0
  129. package/dist/.next/.next/static/chunks/345.8fc37569d5708622.js +1 -0
  130. package/dist/.next/.next/static/chunks/480-85b6c8ae3f51b156.js +1 -0
  131. package/dist/.next/.next/static/chunks/52.2cdc9bdb75e1fc2e.js +1 -0
  132. package/dist/.next/.next/static/chunks/803-a2fcfbd00e6b3b38.js +1 -0
  133. package/dist/.next/.next/static/chunks/{92-5f7522943fcb72a8.js → 92-a84bdac2be7c8d7a.js} +1 -1
  134. package/dist/.next/.next/static/chunks/app/api/cloudflare/route-d0c1dc2a9e7dce36.js +1 -0
  135. package/dist/.next/.next/static/chunks/app/api/databases/route-cd322321212797cf.js +1 -0
  136. package/dist/.next/.next/static/chunks/app/api/migrations/list/route-cd710ff75b6bcd02.js +1 -0
  137. package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-ee522f232b9f0a9c.js +1 -0
  138. package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-79ee2c26f87d3bc7.js +1 -0
  139. package/dist/.next/.next/static/chunks/app/api/pro/route-c90c1f901fc00d38.js +1 -0
  140. package/dist/.next/.next/static/chunks/app/api/pull-data/confirm/route-118764086af798f8.js +1 -0
  141. package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-2b0ade4ebfcea0bc.js +1 -0
  142. package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-342db7ea13e6f447.js +1 -0
  143. package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-b778c053bd515abd.js +1 -0
  144. package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-ab090482f299f57f.js +1 -0
  145. package/dist/.next/.next/static/chunks/app/api/query/route-4d21a8b1d34491f1.js +1 -0
  146. package/dist/.next/.next/static/chunks/app/api/schema/route-cb17a387d6b557ad.js +1 -0
  147. package/dist/.next/.next/static/chunks/app/api/tables/[name]/import/route-510472de7a5c29bd.js +1 -0
  148. package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-6a1fa95c303ce0de.js +1 -0
  149. package/dist/.next/.next/static/chunks/app/api/tables/route-daa975df4ea8e8f8.js +1 -0
  150. package/dist/.next/.next/static/chunks/app/api/time-travel/preview/route-5787d7e8f17bd539.js +1 -0
  151. package/dist/.next/.next/static/chunks/app/api/time-travel/restore/route-84b64a27e831e21c.js +1 -0
  152. package/dist/.next/.next/static/chunks/app/api/update/route-54ee900537982652.js +1 -0
  153. package/dist/.next/.next/static/chunks/app/{layout-40ec07d04681ba81.js → layout-f0ec4d636ee0f763.js} +1 -1
  154. package/dist/.next/.next/static/chunks/app/page-358bf2112802ff85.js +1 -0
  155. package/dist/.next/.next/static/chunks/webpack-024900a94af4f0a7.js +1 -0
  156. package/dist/.next/.next/static/css/2c165a0ede9b2442.css +3 -0
  157. package/dist/.next/.next/static/css/32df9a4d493f8b0f.css +31 -0
  158. package/dist/.next/.next/static/fiesjBWbrmSSyLf4biwrX/_buildManifest.js +1 -0
  159. package/dist/.next/.next/static/ft39e6W6vSgUL7peRo7pE/_buildManifest.js +1 -0
  160. package/dist/.next/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  161. package/dist/.next/.next/static/u7ssdTycF4iQ-w-pQZhxg/_buildManifest.js +1 -0
  162. package/dist/.next/.next/trace +3 -3
  163. package/dist/.next/.next/types/app/api/migrations/list/route.ts +347 -0
  164. package/dist/.next/.next/types/app/api/pro/route.ts +347 -0
  165. package/dist/.next/.next/types/app/api/schema/route.ts +347 -0
  166. package/dist/.next/.next/types/app/api/tables/[name]/import/route.ts +347 -0
  167. package/dist/.next/.next/types/app/api/time-travel/preview/route.ts +347 -0
  168. package/dist/.next/.next/types/app/api/time-travel/restore/route.ts +347 -0
  169. package/dist/.next/BUILD_ID +1 -1
  170. package/dist/.next/app-build-manifest.json +122 -80
  171. package/dist/.next/app-path-routes-manifest.json +1 -1
  172. package/dist/.next/build-manifest.json +7 -7
  173. package/dist/.next/cache/.rscinfo +1 -1
  174. package/dist/.next/cache/.tsbuildinfo +1 -1
  175. package/dist/.next/cache/webpack/client-production/0.pack +0 -0
  176. package/dist/.next/cache/webpack/client-production/index.pack +0 -0
  177. package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
  178. package/dist/.next/cache/webpack/server-production/0.pack +0 -0
  179. package/dist/.next/cache/webpack/server-production/index.pack +0 -0
  180. package/dist/.next/next-minimal-server.js.nft.json +1 -1
  181. package/dist/.next/next-server.js.nft.json +1 -1
  182. package/dist/.next/prerender-manifest.json +1 -1
  183. package/dist/.next/react-loadable-manifest.json +11 -1
  184. package/dist/.next/required-server-files.json +1 -1
  185. package/dist/.next/routes-manifest.json +1 -1
  186. package/dist/.next/server/app/_not-found/page.js +1 -1
  187. package/dist/.next/server/app/_not-found/page.js.nft.json +1 -1
  188. package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  189. package/dist/.next/server/app/_not-found.html +1 -1
  190. package/dist/.next/server/app/_not-found.rsc +5 -5
  191. package/dist/.next/server/app/api/cloudflare/route.js +1 -1
  192. package/dist/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
  193. package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
  194. package/dist/.next/server/app/api/databases/route.js +1 -1
  195. package/dist/.next/server/app/api/databases/route.js.nft.json +1 -1
  196. package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
  197. package/dist/.next/server/app/api/migrations/list/route.js +26 -0
  198. package/dist/.next/server/app/api/migrations/list/route.js.nft.json +1 -0
  199. package/dist/.next/server/app/api/migrations/list/route_client-reference-manifest.js +1 -0
  200. package/dist/.next/server/app/api/migrations/sync/route.js +5 -5
  201. package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
  202. package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
  203. package/dist/.next/server/app/api/migrations/sync-files/route.js +4 -4
  204. package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
  205. package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
  206. package/dist/.next/server/app/api/pro/route.js +1 -0
  207. package/dist/.next/server/app/api/pro/route.js.nft.json +1 -0
  208. package/dist/.next/server/app/api/pro/route_client-reference-manifest.js +1 -0
  209. package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -1
  210. package/dist/.next/server/app/api/pull-data/confirm/route.js.nft.json +1 -1
  211. package/dist/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -1
  212. package/dist/.next/server/app/api/pull-remote/confirm/route.js +4 -4
  213. package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
  214. package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
  215. package/dist/.next/server/app/api/pull-remote/preview/route.js +4 -4
  216. package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
  217. package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
  218. package/dist/.next/server/app/api/push-remote/confirm/route.js +6 -6
  219. package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
  220. package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
  221. package/dist/.next/server/app/api/push-remote/preview/route.js +6 -6
  222. package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
  223. package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
  224. package/dist/.next/server/app/api/query/route.js +9 -9
  225. package/dist/.next/server/app/api/query/route.js.nft.json +1 -1
  226. package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
  227. package/dist/.next/server/app/api/schema/route.js +1 -0
  228. package/dist/.next/server/app/api/schema/route.js.nft.json +1 -0
  229. package/dist/.next/server/app/api/schema/route_client-reference-manifest.js +1 -0
  230. package/dist/.next/server/app/api/tables/[name]/import/route.js +1 -0
  231. package/dist/.next/server/app/api/tables/[name]/import/route.js.nft.json +1 -0
  232. package/dist/.next/server/app/api/tables/[name]/import/route_client-reference-manifest.js +1 -0
  233. package/dist/.next/server/app/api/tables/[name]/route.js +5 -5
  234. package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
  235. package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
  236. package/dist/.next/server/app/api/tables/route.js +2 -2
  237. package/dist/.next/server/app/api/tables/route.js.nft.json +1 -1
  238. package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
  239. package/dist/.next/server/app/api/time-travel/preview/route.js +1 -0
  240. package/dist/.next/server/app/api/time-travel/preview/route.js.nft.json +1 -0
  241. package/dist/.next/server/app/api/time-travel/preview/route_client-reference-manifest.js +1 -0
  242. package/dist/.next/server/app/api/time-travel/restore/route.js +1 -0
  243. package/dist/.next/server/app/api/time-travel/restore/route.js.nft.json +1 -0
  244. package/dist/.next/server/app/api/time-travel/restore/route_client-reference-manifest.js +1 -0
  245. package/dist/.next/server/app/api/update/route.js +1 -1
  246. package/dist/.next/server/app/api/update/route.js.nft.json +1 -1
  247. package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  248. package/dist/.next/server/app/index.html +5 -3
  249. package/dist/.next/server/app/index.rsc +6 -6
  250. package/dist/.next/server/app/page.js +15 -15
  251. package/dist/.next/server/app/page.js.nft.json +1 -1
  252. package/dist/.next/server/app/page_client-reference-manifest.js +1 -1
  253. package/dist/.next/server/app-paths-manifest.json +11 -5
  254. package/dist/.next/server/chunks/226.js +12 -12
  255. package/dist/.next/server/chunks/391.js +1 -1
  256. package/dist/.next/server/chunks/452.js +1 -1
  257. package/dist/.next/server/chunks/487.js +1 -0
  258. package/dist/.next/server/chunks/572.js +1 -1
  259. package/dist/.next/server/chunks/992.js +3 -3
  260. package/dist/.next/{.next/server/chunks/638.js → server/chunks/994.js} +3 -3
  261. package/dist/.next/server/middleware-build-manifest.js +1 -1
  262. package/dist/.next/server/middleware-react-loadable-manifest.js +1 -1
  263. package/dist/.next/server/next-font-manifest.js +1 -1
  264. package/dist/.next/server/next-font-manifest.json +1 -1
  265. package/dist/.next/server/pages/404.html +1 -1
  266. package/dist/.next/server/pages/500.html +1 -1
  267. package/dist/.next/server/pages-manifest.json +1 -1
  268. package/dist/.next/server/server-reference-manifest.json +1 -1
  269. package/dist/.next/static/chunks/1a258343.3b3e7ba5ba0bd0d2.js +1 -0
  270. package/dist/.next/static/chunks/345.8fc37569d5708622.js +1 -0
  271. package/dist/.next/static/chunks/480-85b6c8ae3f51b156.js +1 -0
  272. package/dist/.next/static/chunks/52.2cdc9bdb75e1fc2e.js +1 -0
  273. package/dist/.next/static/chunks/803-a2fcfbd00e6b3b38.js +1 -0
  274. package/dist/.next/static/chunks/{92-5f7522943fcb72a8.js → 92-a84bdac2be7c8d7a.js} +1 -1
  275. package/dist/.next/static/chunks/app/api/cloudflare/route-d0c1dc2a9e7dce36.js +1 -0
  276. package/dist/.next/static/chunks/app/api/databases/route-cd322321212797cf.js +1 -0
  277. package/dist/.next/static/chunks/app/api/migrations/list/route-cd710ff75b6bcd02.js +1 -0
  278. package/dist/.next/static/chunks/app/api/migrations/sync/route-ee522f232b9f0a9c.js +1 -0
  279. package/dist/.next/static/chunks/app/api/migrations/sync-files/route-79ee2c26f87d3bc7.js +1 -0
  280. package/dist/.next/static/chunks/app/api/pro/route-c90c1f901fc00d38.js +1 -0
  281. package/dist/.next/static/chunks/app/api/pull-data/confirm/route-118764086af798f8.js +1 -0
  282. package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-2b0ade4ebfcea0bc.js +1 -0
  283. package/dist/.next/static/chunks/app/api/pull-remote/preview/route-342db7ea13e6f447.js +1 -0
  284. package/dist/.next/static/chunks/app/api/push-remote/confirm/route-b778c053bd515abd.js +1 -0
  285. package/dist/.next/static/chunks/app/api/push-remote/preview/route-ab090482f299f57f.js +1 -0
  286. package/dist/.next/static/chunks/app/api/query/route-4d21a8b1d34491f1.js +1 -0
  287. package/dist/.next/static/chunks/app/api/schema/route-cb17a387d6b557ad.js +1 -0
  288. package/dist/.next/static/chunks/app/api/tables/[name]/import/route-510472de7a5c29bd.js +1 -0
  289. package/dist/.next/static/chunks/app/api/tables/[name]/route-6a1fa95c303ce0de.js +1 -0
  290. package/dist/.next/static/chunks/app/api/tables/route-daa975df4ea8e8f8.js +1 -0
  291. package/dist/.next/static/chunks/app/api/time-travel/preview/route-5787d7e8f17bd539.js +1 -0
  292. package/dist/.next/static/chunks/app/api/time-travel/restore/route-84b64a27e831e21c.js +1 -0
  293. package/dist/.next/static/chunks/app/api/update/route-54ee900537982652.js +1 -0
  294. package/dist/.next/static/chunks/app/{layout-40ec07d04681ba81.js → layout-f0ec4d636ee0f763.js} +1 -1
  295. package/dist/.next/static/chunks/app/page-358bf2112802ff85.js +1 -0
  296. package/dist/.next/static/chunks/webpack-024900a94af4f0a7.js +1 -0
  297. package/dist/.next/static/css/2c165a0ede9b2442.css +3 -0
  298. package/dist/.next/static/css/32df9a4d493f8b0f.css +31 -0
  299. package/dist/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  300. package/dist/.next/static/zh4Fz2tbm8GRka4woRrGp/_buildManifest.js +1 -0
  301. package/dist/.next/trace +18 -3
  302. package/dist/.next/types/app/api/migrations/list/route.ts +347 -0
  303. package/dist/.next/types/app/api/pro/route.ts +347 -0
  304. package/dist/.next/types/app/api/schema/route.ts +347 -0
  305. package/dist/.next/types/app/api/tables/[name]/import/route.ts +347 -0
  306. package/dist/.next/types/app/api/time-travel/preview/route.ts +347 -0
  307. package/dist/.next/types/app/api/time-travel/restore/route.ts +347 -0
  308. package/dist/app/api/databases/route.js +2 -1
  309. package/dist/app/api/migrations/list/route.js +137 -0
  310. package/dist/app/api/migrations/sync-files/route.js +2 -1
  311. package/dist/app/api/pro/route.js +7 -0
  312. package/dist/app/api/pull-remote/confirm/route.js +138 -146
  313. package/dist/app/api/pull-remote/preview/route.js +49 -84
  314. package/dist/app/api/push-remote/confirm/route.js +31 -12
  315. package/dist/app/api/push-remote/preview/route.js +27 -12
  316. package/dist/app/api/query/route.js +24 -13
  317. package/dist/app/api/schema/route.js +63 -0
  318. package/dist/app/api/tables/[name]/import/route.js +112 -0
  319. package/dist/app/api/tables/[name]/route.js +38 -29
  320. package/dist/app/api/tables/route.js +29 -16
  321. package/dist/app/api/time-travel/preview/route.js +122 -0
  322. package/dist/app/api/time-travel/restore/route.js +106 -0
  323. package/dist/app/page.jsx +26 -8
  324. package/dist/d1-studio.js +129 -23
  325. package/dist/lib/license.js +99 -71
  326. package/dist/lib/local-db.js +223 -0
  327. package/dist/lib/migrations.js +40 -2
  328. package/dist/lib/parse-sql-error.js +99 -160
  329. package/dist/lib/sql-operations.js +28 -10
  330. package/dist/lib/telemetry.js +39 -0
  331. package/package.json +6 -2
  332. package/dist/.next/.next/cache/webpack/server-production/2.pack +0 -0
  333. package/dist/.next/.next/cache/webpack/server-production/3.pack +0 -0
  334. package/dist/.next/.next/static/FEsQ9jwPUQv5A3fwg6Opl/_buildManifest.js +0 -1
  335. package/dist/.next/.next/static/Y9mYu4WBghepP5oT_3OdR/_buildManifest.js +0 -1
  336. package/dist/.next/.next/static/ae3gNmoSGm-R5LJC4UagI/_buildManifest.js +0 -1
  337. package/dist/.next/.next/static/bKfUJeuvAQlBmR3TjrfkH/_buildManifest.js +0 -1
  338. package/dist/.next/.next/static/chunks/576-18a2209e1ed26aad.js +0 -1
  339. package/dist/.next/.next/static/chunks/735-b885dfec6353171d.js +0 -1
  340. package/dist/.next/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +0 -1
  341. package/dist/.next/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +0 -1
  342. package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +0 -1
  343. package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +0 -1
  344. package/dist/.next/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +0 -1
  345. package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +0 -1
  346. package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +0 -1
  347. package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +0 -1
  348. package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +0 -1
  349. package/dist/.next/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +0 -1
  350. package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +0 -1
  351. package/dist/.next/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +0 -1
  352. package/dist/.next/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +0 -1
  353. package/dist/.next/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +0 -1
  354. package/dist/.next/.next/static/chunks/app/page-f2bc307c0d8acdaa.js +0 -1
  355. package/dist/.next/.next/static/chunks/webpack-c76ac1e586b2802a.js +0 -1
  356. package/dist/.next/.next/static/css/7c16f57d325d0d7d.css +0 -3
  357. package/dist/.next/.next/static/ejYPqJ2kVicVp5EFWOZIC/_buildManifest.js +0 -1
  358. package/dist/.next/.next/static/gABGrAoO8IPArDo_Ns_7g/_buildManifest.js +0 -1
  359. package/dist/.next/.next/static/gh-QfIUVo4FTTduYCVKT6/_buildManifest.js +0 -1
  360. package/dist/.next/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  361. package/dist/.next/.next/static/thaCy2qVeNqYYhdayr13C/_buildManifest.js +0 -1
  362. package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_buildManifest.js +0 -1
  363. package/dist/.next/.next/static/ybCx6L6gHqtODbKmlhU-d/_ssgManifest.js +0 -1
  364. package/dist/.next/cache/webpack/client-production/1.pack +0 -0
  365. package/dist/.next/cache/webpack/client-production/2.pack +0 -0
  366. package/dist/.next/cache/webpack/client-production/index.pack.old +0 -0
  367. package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_buildManifest.js +0 -1
  368. package/dist/.next/static/IX-QLbm7scYnyqWeeimal/_ssgManifest.js +0 -1
  369. package/dist/.next/static/chunks/576-18a2209e1ed26aad.js +0 -1
  370. package/dist/.next/static/chunks/735-b885dfec6353171d.js +0 -1
  371. package/dist/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +0 -1
  372. package/dist/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +0 -1
  373. package/dist/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +0 -1
  374. package/dist/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +0 -1
  375. package/dist/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +0 -1
  376. package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +0 -1
  377. package/dist/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +0 -1
  378. package/dist/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +0 -1
  379. package/dist/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +0 -1
  380. package/dist/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +0 -1
  381. package/dist/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +0 -1
  382. package/dist/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +0 -1
  383. package/dist/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +0 -1
  384. package/dist/.next/static/chunks/app/page-f05cd0fc436bf9bc.js +0 -1
  385. package/dist/.next/static/chunks/webpack-c76ac1e586b2802a.js +0 -1
  386. package/dist/.next/static/css/7c16f57d325d0d7d.css +0 -3
  387. package/dist/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  388. /package/dist/.next/.next/static/{FEsQ9jwPUQv5A3fwg6Opl → -OO4tE7EKr8o62Bne-ODo}/_ssgManifest.js +0 -0
  389. /package/dist/.next/.next/static/{Y9mYu4WBghepP5oT_3OdR → 3kAeIJC56X7aw1Fk5_OXO}/_ssgManifest.js +0 -0
  390. /package/dist/.next/.next/static/{ae3gNmoSGm-R5LJC4UagI → J8r9W6xxmYYvuKehItNuW}/_ssgManifest.js +0 -0
  391. /package/dist/.next/.next/static/{bKfUJeuvAQlBmR3TjrfkH → arc9h7hbaQzL1Dl0iuVrT}/_ssgManifest.js +0 -0
  392. /package/dist/.next/.next/static/chunks/{4bd1b696-8c908eb707f85a27.js → 4bd1b696-124ea104c06f6cea.js} +0 -0
  393. /package/dist/.next/.next/static/chunks/{517-3b698a5d3da06ff7.js → 517-c876ce2f00030cd0.js} +0 -0
  394. /package/dist/.next/.next/static/chunks/{692-ede418e1d28a1394.js → 692-9e59d546afd11ec3.js} +0 -0
  395. /package/dist/.next/.next/static/chunks/app/_not-found/{page-b786c3dd79ad15a5.js → page-3e24b81707d98126.js} +0 -0
  396. /package/dist/.next/.next/static/{ejYPqJ2kVicVp5EFWOZIC → fiesjBWbrmSSyLf4biwrX}/_ssgManifest.js +0 -0
  397. /package/dist/.next/.next/static/{gABGrAoO8IPArDo_Ns_7g → ft39e6W6vSgUL7peRo7pE}/_ssgManifest.js +0 -0
  398. /package/dist/.next/.next/static/{gh-QfIUVo4FTTduYCVKT6 → u7ssdTycF4iQ-w-pQZhxg}/_ssgManifest.js +0 -0
  399. /package/dist/.next/static/chunks/{4bd1b696-8c908eb707f85a27.js → 4bd1b696-124ea104c06f6cea.js} +0 -0
  400. /package/dist/.next/static/chunks/{517-3b698a5d3da06ff7.js → 517-c876ce2f00030cd0.js} +0 -0
  401. /package/dist/.next/static/chunks/{692-ede418e1d28a1394.js → 692-9e59d546afd11ec3.js} +0 -0
  402. /package/dist/.next/static/chunks/app/_not-found/{page-b786c3dd79ad15a5.js → page-3e24b81707d98126.js} +0 -0
  403. /package/dist/.next/{.next/static/thaCy2qVeNqYYhdayr13C → static/zh4Fz2tbm8GRka4woRrGp}/_ssgManifest.js +0 -0
@@ -5,7 +5,9 @@ import { promisify } from 'util';
5
5
  import { exec } from 'child_process';
6
6
  import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
7
  import { dbQueue } from '@/lib/database-queue';
8
+ import { executeLocalSQL } from '@/lib/local-db.js';
8
9
  import logger from '@/lib/logger';
10
+ import { parseSQLError } from '@/lib/parse-sql-error';
9
11
  import { sanitizeTableName, sanitizeColumnName } from '@/lib/sql-sanitizer.js';
10
12
 
11
13
  const execAsync = promisify(exec);
@@ -17,27 +19,30 @@ export const dynamic = 'force-dynamic';
17
19
  let isProcessing = false;
18
20
 
19
21
  /**
20
- * Executes a D1 SQL query using Wrangler.
21
- * This function ensures that only one query is processed at a time.
22
+ * Executes a D1 SQL query, preferring direct SQLite access over the wrangler CLI.
22
23
  */
23
- async function executeD1Query(command, projectDir, databaseName) {
24
+ async function executeD1Query(sql, projectDir, dbConfig) {
25
+ // Try direct SQLite access first (fast path)
26
+ const localOutput = executeLocalSQL(projectDir, dbConfig, sql);
27
+ if (localOutput !== null) {
28
+ const parsed = JSON.parse(localOutput);
29
+ return parsed[0]?.results || [];
30
+ }
31
+
32
+ // Fall back to wrangler CLI
33
+ const databaseName = dbConfig.database_name;
24
34
  try {
25
- // Wait until any current query is finished.
26
35
  while (isProcessing) {
27
36
  await new Promise(resolve => setTimeout(resolve, 100));
28
37
  }
29
38
  isProcessing = true;
30
-
31
- // Escape double quotes in the command and execute the query
32
39
  const { stdout } = await execAsync(
33
- `wrangler d1 execute ${databaseName} --local --command="${command.replace(/"/g, '\\"')}" --json`,
40
+ `wrangler d1 execute ${databaseName} --local --command="${sql.replace(/"/g, '\\"')}" --json`,
34
41
  { cwd: projectDir }
35
42
  );
36
-
37
43
  const result = JSON.parse(stdout);
38
44
  return result[0]?.results || [];
39
45
  } catch (error) {
40
- logger.error('Query execution error:', error);
41
46
  throw error;
42
47
  } finally {
43
48
  isProcessing = false;
@@ -81,6 +86,8 @@ export async function GET(request, context) {
81
86
  const page = parseInt(searchParams.get('page')) || 1;
82
87
  const limit = parseInt(searchParams.get('limit')) || 50;
83
88
  const offset = (page - 1) * limit;
89
+ const isExport = searchParams.get('export') === 'true';
90
+ const dbParam = searchParams.get('db');
84
91
 
85
92
  const projectDir = process.env.D1_PROJECT_DIR;
86
93
  if (!projectDir) {
@@ -96,21 +103,23 @@ export async function GET(request, context) {
96
103
  if (!config.d1_databases?.length) {
97
104
  throw new Error('No D1 databases configured');
98
105
  }
99
- // Get the first D1 database name from the configuration
100
- const databaseName = config.d1_databases[0].database_name;
106
+ // Resolve target database use ?db param if provided, else fall back to first
107
+ const dbConfig = dbParam
108
+ ? config.d1_databases.find(d => d.database_name === dbParam)
109
+ : config.d1_databases[0];
110
+ if (!dbConfig) throw new Error(`Database not found: ${dbParam}`);
111
+ const databaseName = dbConfig.database_name;
101
112
 
102
113
  // Validate and sanitize table name to prevent SQL injection
103
114
  const sanitizedTableName = sanitizeTableName(name);
104
115
 
105
116
  // Get table schema using PRAGMA query (PRAGMA is safe from injection when table name is sanitized)
106
117
  const schemaQuery = `PRAGMA table_info(${sanitizedTableName});`;
107
- const schema = await executeD1Query(schemaQuery, projectDir, databaseName);
118
+ const schema = await executeD1Query(schemaQuery, projectDir, dbConfig);
108
119
 
109
- // Get the CREATE TABLE statement from sqlite_master using parameterized query approach
110
- const createTableQuery = `SELECT sql FROM sqlite_master WHERE type='table' AND name = ?;`;
111
- // Note: executeD1Query would need to support parameters, for now we sanitize the table name
120
+ // Get the CREATE TABLE statement from sqlite_master
112
121
  const createTableQuerySafe = `SELECT sql FROM sqlite_master WHERE type='table' AND name='${name.replace(/'/g, "''")}';`;
113
- const tableDefinition = await executeD1Query(createTableQuerySafe, projectDir, databaseName);
122
+ const tableDefinition = await executeD1Query(createTableQuerySafe, projectDir, dbConfig);
114
123
  const createTableSQL = tableDefinition[0]?.sql || '';
115
124
 
116
125
  // Extract CHECK constraints from the CREATE TABLE statement
@@ -124,23 +133,25 @@ export async function GET(request, context) {
124
133
 
125
134
  // Get total row count for the table (using sanitized table name)
126
135
  const countQuery = `SELECT COUNT(*) as total FROM ${sanitizedTableName};`;
127
- const countResult = await executeD1Query(countQuery, projectDir, databaseName);
136
+ const countResult = await executeD1Query(countQuery, projectDir, dbConfig);
128
137
  const totalRows = countResult[0]?.total || 0;
129
138
 
130
139
  // Fetch paginated data using the primary key column for ordering
131
140
  const primaryKeyColumn = schema.find(col => col.pk === 1)?.name || schema[0]?.name;
132
141
  const sanitizedPrimaryKey = primaryKeyColumn ? sanitizeColumnName(primaryKeyColumn) : '*';
133
-
134
- // Validate limit and offset to prevent injection through URL params
135
- const safeLimitNum = Math.max(1, Math.min(parseInt(limit) || 50, 1000)); // Cap at 1000 rows
142
+
143
+ // For exports, skip the 1000-row cap; otherwise cap to prevent huge reads
144
+ const safeLimitNum = isExport
145
+ ? Math.max(1, parseInt(limit) || 99999)
146
+ : Math.max(1, Math.min(parseInt(limit) || 50, 1000));
136
147
  const safeOffsetNum = Math.max(0, parseInt(offset) || 0);
137
-
148
+
138
149
  const dataQuery = `
139
- SELECT * FROM ${sanitizedTableName}
140
- ORDER BY ${sanitizedPrimaryKey} DESC
150
+ SELECT * FROM ${sanitizedTableName}
151
+ ORDER BY ${sanitizedPrimaryKey} DESC
141
152
  LIMIT ${safeLimitNum} OFFSET ${safeOffsetNum};
142
153
  `;
143
- const data = await executeD1Query(dataQuery, projectDir, databaseName);
154
+ const data = await executeD1Query(dataQuery, projectDir, dbConfig);
144
155
 
145
156
  return NextResponse.json({
146
157
  success: true,
@@ -158,13 +169,11 @@ export async function GET(request, context) {
158
169
  });
159
170
 
160
171
  } catch (error) {
161
- logger.error('Error handling request:', error);
172
+ const parsed = parseSQLError(error);
173
+ logger.error(`✗ ${parsed.message}`);
162
174
  return NextResponse.json({
163
175
  success: false,
164
- error: {
165
- message: error.message,
166
- details: error.stack
167
- }
176
+ error: { message: parsed.message }
168
177
  }, {
169
178
  status: error.message.includes('not configured') ? 500 :
170
179
  error.message.includes('not found') ? 404 : 500
@@ -4,6 +4,7 @@ import { NextResponse } from 'next/server';
4
4
  import { promisify } from 'util';
5
5
  import { exec } from 'child_process';
6
6
  import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
+ import { executeLocalSQL } from '@/lib/local-db.js';
7
8
  import logger from '@/lib/logger';
8
9
 
9
10
  const execAsync = promisify(exec);
@@ -75,10 +76,13 @@ async function retryWithTimeout(fn, retries = 3, timeout = 1000) {
75
76
  * GET handler for listing tables.
76
77
  * It uses the Wrangler configuration (via findWranglerConfig) to determine the D1 database.
77
78
  */
78
- export async function GET() {
79
+ export async function GET(request) {
79
80
  logger.logRequest('GET', '/api/tables');
80
81
 
81
82
  try {
83
+ const { searchParams } = new URL(request.url);
84
+ const dbParam = searchParams.get('db');
85
+
82
86
  const projectDir = process.env.D1_PROJECT_DIR;
83
87
 
84
88
  if (!projectDir) {
@@ -105,8 +109,14 @@ export async function GET() {
105
109
  { status: 404 }
106
110
  );
107
111
  }
108
- // Get the first D1 database name from the configuration
109
- const databaseName = config.d1_databases[0].database_name;
112
+ // Resolve target database use ?db param if provided, else fall back to first
113
+ const dbConfig = dbParam
114
+ ? config.d1_databases.find(d => d.database_name === dbParam)
115
+ : config.d1_databases[0];
116
+ if (!dbConfig) {
117
+ return NextResponse.json({ error: `Database not found: ${dbParam}` }, { status: 404 });
118
+ }
119
+ const databaseName = dbConfig.database_name;
110
120
 
111
121
  // SQL query to list non-system tables
112
122
  const query = `
@@ -117,19 +127,22 @@ export async function GET() {
117
127
  ORDER BY name;
118
128
  `;
119
129
 
120
- // Execute the query with a retry mechanism if the database is locked
121
- const { stdout } = await retryWithTimeout(async () => {
122
- return execAsync(
123
- `wrangler d1 execute ${databaseName} --local --command="${query}"`,
124
- {
125
- cwd: projectDir,
126
- timeout: 5000 // 5 second timeout
127
- }
128
- );
129
- });
130
-
131
- // Extract JSON from the command output and then extract table names
132
- const result = extractJSONFromOutput(stdout);
130
+ // Try direct SQLite access first (fast), fall back to wrangler CLI
131
+ let result;
132
+ const localOutput = executeLocalSQL(projectDir, dbConfig, query.trim());
133
+ if (localOutput !== null) {
134
+ result = JSON.parse(localOutput);
135
+ } else {
136
+ const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
137
+ const { stdout } = await retryWithTimeout(async () => {
138
+ return execAsync(
139
+ `${npxCmd} wrangler d1 execute ${databaseName} --local --json --command="${query.trim().replace(/\n\s*/g, ' ')}"`,
140
+ { cwd: projectDir, timeout: 10000 }
141
+ );
142
+ });
143
+ result = extractJSONFromOutput(stdout);
144
+ }
145
+
133
146
  const tables = extractTablesFromResult(result);
134
147
 
135
148
  return NextResponse.json({
@@ -0,0 +1,122 @@
1
+ // api/time-travel/preview/route.js
2
+ // GET → current bookmark + window info (no timestamp)
3
+ // POST → bookmark for a specific timestamp
4
+
5
+ import { NextResponse } from 'next/server';
6
+ import { promisify } from 'util';
7
+ import { exec } from 'child_process';
8
+ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
9
+ import logger from '@/lib/logger';
10
+
11
+ const execAsync = promisify(exec);
12
+
13
+ async function resolveDb(req) {
14
+ const { searchParams } = new URL(req.url);
15
+ const db = searchParams.get('db');
16
+ const projectDir = process.env.D1_PROJECT_DIR;
17
+ if (!projectDir) throw Object.assign(new Error('Project directory not configured'), { status: 500 });
18
+
19
+ const wranglerResult = await findWranglerConfig(projectDir);
20
+ if (!wranglerResult?.config) throw Object.assign(new Error('No Wrangler configuration found'), { status: 400 });
21
+
22
+ const config = wranglerResult.config;
23
+ if (!config.d1_databases?.length) throw Object.assign(new Error('No D1 databases configured'), { status: 400 });
24
+
25
+ const dbConfig = db
26
+ ? config.d1_databases.find(d => d.database_name === db)
27
+ : config.d1_databases[0];
28
+ if (!dbConfig) throw Object.assign(new Error(`Database not found: ${db}`), { status: 404 });
29
+
30
+ return { projectDir, databaseName: dbConfig.database_name };
31
+ }
32
+
33
+ function parseBookmark(raw) {
34
+ const clean = (raw || '').replace(/\x1B\[[0-9;]*m/g, '');
35
+ const jsonStart = clean.indexOf('{');
36
+ const jsonEnd = clean.lastIndexOf('}');
37
+ if (jsonStart !== -1 && jsonEnd !== -1) {
38
+ try {
39
+ const parsed = JSON.parse(clean.slice(jsonStart, jsonEnd + 1));
40
+ return parsed.bookmark ?? parsed.result?.bookmark ?? null;
41
+ } catch { /* fall through */ }
42
+ }
43
+ const match = clean.match(/bookmark[:\s]+([0-9a-f-]+)/i);
44
+ return match ? match[1] : null;
45
+ }
46
+
47
+ /** GET /api/time-travel/preview?db=name — returns current (latest) bookmark */
48
+ export async function GET(req) {
49
+ if (process.env.D1_IS_PRO !== 'true') {
50
+ return NextResponse.json({ success: false, error: { type: 'PRO_REQUIRED', message: 'Pro license required. Run: d1s --license YOUR-KEY' } }, { status: 402 });
51
+ }
52
+ try {
53
+ const { projectDir, databaseName } = await resolveDb(req);
54
+ const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
55
+ const command = `${npxCmd} wrangler d1 time-travel info ${databaseName} --json`;
56
+ logger.debug(`Time travel GET: ${command}`);
57
+
58
+ const { stdout } = await execAsync(command, {
59
+ cwd: projectDir, env: process.env,
60
+ maxBuffer: 1024 * 1024 * 4, shell: true,
61
+ });
62
+
63
+ const bookmark = parseBookmark(stdout);
64
+ return NextResponse.json({ success: true, currentBookmark: bookmark, databaseName });
65
+ } catch (error) {
66
+ const strip = s => (s || '').replace(/\x1B\[[0-9;]*m/g, '').trim();
67
+ const msg = strip(error.stderr) || strip(error.stdout) || strip(error.message) || 'Failed to get time travel info';
68
+ logger.error(`Time travel GET error: ${msg}`);
69
+ return NextResponse.json({ success: false, error: msg }, { status: error.status || 500 });
70
+ }
71
+ }
72
+
73
+ export async function POST(req) {
74
+ if (process.env.D1_IS_PRO !== 'true') {
75
+ return NextResponse.json({ success: false, error: { type: 'PRO_REQUIRED', message: 'Pro license required. Run: d1s --license YOUR-KEY' } }, { status: 402 });
76
+ }
77
+ try {
78
+ const body = await req.json();
79
+ const { timestamp } = body;
80
+ if (!timestamp) {
81
+ return NextResponse.json({ success: false, error: 'timestamp is required' }, { status: 400 });
82
+ }
83
+
84
+ // Re-use resolveDb but from body.db
85
+ const projectDir = process.env.D1_PROJECT_DIR;
86
+ if (!projectDir) return NextResponse.json({ success: false, error: 'Project directory not configured' }, { status: 500 });
87
+
88
+ const wranglerResult = await findWranglerConfig(projectDir);
89
+ if (!wranglerResult?.config) return NextResponse.json({ success: false, error: 'No Wrangler configuration found' }, { status: 400 });
90
+
91
+ const config = wranglerResult.config;
92
+ if (!config.d1_databases?.length) return NextResponse.json({ success: false, error: 'No D1 databases configured' }, { status: 400 });
93
+
94
+ const dbConfig = body.db
95
+ ? config.d1_databases.find(d => d.database_name === body.db)
96
+ : config.d1_databases[0];
97
+ if (!dbConfig) return NextResponse.json({ success: false, error: `Database not found: ${body.db}` }, { status: 404 });
98
+
99
+ const { database_name: databaseName } = dbConfig;
100
+ const unixTs = Math.floor(new Date(timestamp).getTime() / 1000);
101
+ const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';
102
+ const command = `${npxCmd} wrangler d1 time-travel info ${databaseName} --timestamp=${unixTs} --json`;
103
+ logger.debug(`Time travel POST: ${command}`);
104
+
105
+ const { stdout } = await execAsync(command, {
106
+ cwd: projectDir, env: process.env,
107
+ maxBuffer: 1024 * 1024 * 4, shell: true,
108
+ });
109
+
110
+ const bookmark = parseBookmark(stdout);
111
+ return NextResponse.json({ success: true, bookmark, databaseName });
112
+ } catch (error) {
113
+ const strip = s => (s || '').replace(/\x1B\[[0-9;]*m/g, '').trim();
114
+ const msg = strip(error.stderr) || strip(error.stdout) || strip(error.message) || 'Failed to get time travel info';
115
+ logger.error(`Time travel preview error: ${msg}`);
116
+ return NextResponse.json({ success: false, error: msg }, { status: 500 });
117
+ }
118
+ }
119
+
120
+ export async function OPTIONS() {
121
+ return new NextResponse(null, { status: 204 });
122
+ }
@@ -0,0 +1,106 @@
1
+ // api/time-travel/restore/route.js
2
+ // Calls `wrangler d1 time-travel restore` to roll back a remote D1 database.
3
+
4
+ import { NextResponse } from 'next/server';
5
+ import { promisify } from 'util';
6
+ import { exec } from 'child_process';
7
+ import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
8
+ import logger from '@/lib/logger';
9
+
10
+ const execAsync = promisify(exec);
11
+
12
+ export async function POST(req) {
13
+ if (process.env.D1_IS_PRO !== 'true') {
14
+ return NextResponse.json({ success: false, error: { type: 'PRO_REQUIRED', message: 'Pro license required. Run: d1s --license YOUR-KEY' } }, { status: 402 });
15
+ }
16
+ try {
17
+ const { db, bookmark, timestamp } = await req.json();
18
+
19
+ if (!bookmark && !timestamp) {
20
+ return NextResponse.json(
21
+ { success: false, error: 'bookmark or timestamp is required' },
22
+ { status: 400 }
23
+ );
24
+ }
25
+
26
+ const projectDir = process.env.D1_PROJECT_DIR;
27
+ if (!projectDir) {
28
+ return NextResponse.json({ success: false, error: 'Project directory not configured' }, { status: 500 });
29
+ }
30
+
31
+ const wranglerResult = await findWranglerConfig(projectDir);
32
+ if (!wranglerResult?.config) {
33
+ return NextResponse.json({ success: false, error: 'No Wrangler configuration found' }, { status: 400 });
34
+ }
35
+
36
+ const config = wranglerResult.config;
37
+ if (!config.d1_databases?.length) {
38
+ return NextResponse.json({ success: false, error: 'No D1 databases configured' }, { status: 400 });
39
+ }
40
+
41
+ const dbConfig = db
42
+ ? config.d1_databases.find(d => d.database_name === db)
43
+ : config.d1_databases[0];
44
+
45
+ if (!dbConfig) {
46
+ return NextResponse.json({ success: false, error: `Database not found: ${db}` }, { status: 404 });
47
+ }
48
+
49
+ const databaseName = dbConfig.database_name;
50
+ const isWindows = process.platform === 'win32';
51
+ const npxCmd = isWindows ? 'npx.cmd' : 'npx';
52
+
53
+ // Prefer explicit bookmark; fall back to timestamp
54
+ let command;
55
+ if (bookmark) {
56
+ command = `${npxCmd} wrangler d1 time-travel restore ${databaseName} --bookmark=${bookmark} --json`;
57
+ } else {
58
+ const unixTs = Math.floor(new Date(timestamp).getTime() / 1000);
59
+ command = `${npxCmd} wrangler d1 time-travel restore ${databaseName} --timestamp=${unixTs} --json`;
60
+ }
61
+
62
+ logger.debug('Time travel restore command:', command);
63
+
64
+ const { stdout, stderr } = await execAsync(command, {
65
+ cwd: projectDir,
66
+ env: process.env,
67
+ maxBuffer: 1024 * 1024 * 4,
68
+ shell: true,
69
+ timeout: 120000, // 2 min timeout for restore
70
+ });
71
+
72
+ const clean = stdout.replace(/\x1B\[[0-9;]*m/g, '');
73
+
74
+ // Try to extract undo bookmark from output
75
+ let undoBookmark = null;
76
+ const undoMatch = clean.match(/undo[^:]*bookmark[:\s]+([0-9a-f-]+)/i) ||
77
+ clean.match(/pre.?restore[^:]*bookmark[:\s]+([0-9a-f-]+)/i) ||
78
+ clean.match(/saved[^:]*bookmark[:\s]+([0-9a-f-]+)/i);
79
+ if (undoMatch) undoBookmark = undoMatch[1];
80
+
81
+ // Also try JSON parse
82
+ const jsonStart = clean.indexOf('{');
83
+ const jsonEnd = clean.lastIndexOf('}');
84
+ if (jsonStart !== -1 && jsonEnd !== -1) {
85
+ try {
86
+ const parsed = JSON.parse(clean.slice(jsonStart, jsonEnd + 1));
87
+ if (!undoBookmark) {
88
+ undoBookmark = parsed.undoBookmark ?? parsed.undo_bookmark ?? parsed.result?.undoBookmark ?? null;
89
+ }
90
+ } catch { /* ignore */ }
91
+ }
92
+
93
+ return NextResponse.json({ success: true, undoBookmark, databaseName });
94
+ } catch (error) {
95
+ const strip = s => (s || '').replace(/\x1B\[[0-9;]*m/g, '').trim();
96
+ const stderr = strip(error.stderr);
97
+ const stdout = strip(error.stdout);
98
+ const msg = stderr || stdout || strip(error.message) || 'Restore failed';
99
+ logger.error(`Time travel restore error: ${msg}`);
100
+ return NextResponse.json({ success: false, error: msg }, { status: 500 });
101
+ }
102
+ }
103
+
104
+ export async function OPTIONS() {
105
+ return new NextResponse(null, { status: 204 });
106
+ }
package/dist/app/page.jsx CHANGED
@@ -5,30 +5,48 @@ import { useState } from 'react';
5
5
  import { AppSidebar } from '../components/sidebar';
6
6
  import { SQLEditor } from '../components/sql-editor';
7
7
  import { TableView } from '../components/table-view';
8
+ import { MigrationsView } from '../components/migrations-view';
9
+ import { SchemaView } from '../components/schema-view';
10
+ import { TimeTravelView } from '../components/time-travel-view';
11
+ import { RemoteSyncView } from '../components/remote-sync-view';
12
+ import { StatusBar } from '../components/status-bar';
8
13
 
9
14
  export default function StudioPage() {
10
15
  const [currentView, setCurrentView] = useState('sql-editor');
11
16
  const [selectedTable, setSelectedTable] = useState(null);
17
+ const [initialSqlQuery, setInitialSqlQuery] = useState('');
12
18
 
13
19
  const handleTableSelect = (tableName) => {
14
20
  setSelectedTable(tableName);
15
21
  setCurrentView('table-view');
16
22
  };
17
23
 
24
+ const handleOpenInSQL = (sql) => {
25
+ setInitialSqlQuery(sql);
26
+ setCurrentView('sql-editor');
27
+ };
28
+
18
29
  return (
19
30
  <div className="flex h-screen bg-background">
20
- <AppSidebar
21
- className="w-64 border-r flex-shrink-0"
31
+ <AppSidebar
32
+ className="w-64 border-r flex-shrink-0"
22
33
  currentView={currentView}
23
34
  onNavigate={setCurrentView}
24
35
  onTableSelect={handleTableSelect}
25
36
  />
26
- <main className="flex-1 overflow-hidden">
27
- {currentView === 'sql-editor' && <SQLEditor />}
28
- {currentView === 'table-view' && selectedTable && (
29
- <TableView tableName={selectedTable} />
30
- )}
31
- </main>
37
+ <div className="flex-1 flex flex-col overflow-hidden">
38
+ <main className="flex-1 overflow-hidden">
39
+ {currentView === 'sql-editor' && <SQLEditor initialQuery={initialSqlQuery} />}
40
+ {currentView === 'schema' && <SchemaView />}
41
+ {currentView === 'migrations' && <MigrationsView />}
42
+ {currentView === 'time-travel' && <TimeTravelView />}
43
+ {currentView === 'remote-sync' && <RemoteSyncView />}
44
+ {currentView === 'table-view' && selectedTable && (
45
+ <TableView tableName={selectedTable} onOpenInSQL={handleOpenInSQL} />
46
+ )}
47
+ </main>
48
+ <StatusBar />
49
+ </div>
32
50
  </div>
33
51
  );
34
52
  }