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,843 @@
1
+ // components/table-view.jsx
2
+ 'use client';
3
+
4
+ import React, {
5
+ useState,
6
+ useEffect,
7
+ useRef,
8
+ useCallback
9
+ } from 'react';
10
+ import {
11
+ Table,
12
+ TableBody,
13
+ TableCell,
14
+ TableHead,
15
+ TableHeader,
16
+ TableRow
17
+ } from '@/components/ui/table';
18
+ import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area';
19
+ import { Alert, AlertDescription } from '@/components/ui/alert';
20
+ import { Checkbox } from '@/components/ui/checkbox';
21
+ import { Loader2, AlertCircle } from 'lucide-react';
22
+ import { useDatabase } from '@/context/database-context';
23
+ import TableToolbar from './table-toolbar';
24
+ import { EditableCell } from './editable-cell';
25
+ import { EditableRow } from './editable-row';
26
+ import DeleteRecordsDialog from './delete-records-dialog';
27
+ import { DatabaseErrorDialog } from './table-error-dialog';
28
+ import { useToast } from '@/hooks/use-toast';
29
+ import { parseSQLError } from '@/lib/parse-sql-error';
30
+ import { ResizableTable, ResizableHeader } from './resize-columns';
31
+ import { SortableHeader, sortData } from './column-sorting';
32
+
33
+ export function TableView({ tableName }) {
34
+ // Database context and utilities
35
+ const {
36
+ executeQuery,
37
+ getCachedTable,
38
+ updateTableCache,
39
+ invalidateTable,
40
+ switchTable,
41
+ activeTable,
42
+ updateTableData
43
+ } = useDatabase();
44
+ const { toast } = useToast();
45
+
46
+ // Table state
47
+ const [data, setData] = useState(() => []);
48
+ const [schema, setSchema] = useState([]);
49
+ const [totalRows, setTotalRows] = useState(0);
50
+ const [isTableLoading, setIsTableLoading] = useState(true);
51
+ const [isSaving, setIsSaving] = useState(false);
52
+ const [error, setError] = useState(null);
53
+
54
+ // Edit states
55
+ const [editedCells, setEditedCells] = useState(new Map());
56
+ const [editedRows, setEditedRows] = useState(new Set());
57
+ const [newRecords, setNewRecords] = useState([]);
58
+
59
+ // Pagination state
60
+ const [currentPage, setCurrentPage] = useState(1);
61
+ const [rowsPerPage, setRowsPerPage] = useState(50);
62
+ const [totalPages, setTotalPages] = useState(1);
63
+
64
+ // Selection state
65
+ const [selectedRows, setSelectedRows] = useState(new Set());
66
+ const checkboxRef = useRef(null);
67
+
68
+ // Delete dialog state
69
+ const [showDeleteDialog, setShowDeleteDialog] = useState(false);
70
+ const [isDeleting, setIsDeleting] = useState(false);
71
+ const [deleteError, setDeleteError] = useState(null);
72
+
73
+ // Database error dialog state
74
+ const [showDatabaseError, setShowDatabaseError] = useState(false);
75
+ const [databaseError, setDatabaseError] = useState(null);
76
+
77
+ // Sorting state
78
+ const [sortConfigs, setSortConfigs] = useState({});
79
+
80
+ // Instead of reading from localStorage during initial render,
81
+ // we initialize with fallback values.
82
+ const [columnWidths, setColumnWidths] = useState({});
83
+ const [visibleColumns, setVisibleColumns] = useState([]);
84
+
85
+ // On mount (client only) load saved values from localStorage
86
+ useEffect(() => {
87
+ if (tableName && typeof window !== 'undefined') {
88
+ const savedWidths = localStorage.getItem(`table-widths-${tableName}`);
89
+ if (savedWidths) {
90
+ setColumnWidths(JSON.parse(savedWidths));
91
+ }
92
+ const savedColumns = localStorage.getItem(`table-columns-${tableName}`);
93
+ if (savedColumns) {
94
+ try {
95
+ setVisibleColumns(JSON.parse(savedColumns));
96
+ } catch (e) {
97
+ setVisibleColumns([]);
98
+ }
99
+ }
100
+ }
101
+ }, [tableName]);
102
+
103
+ // Load data with proper cache handling
104
+ const loadTableData = useCallback(async (forceFetch = false) => {
105
+ if (!tableName) return;
106
+
107
+ // First check cache with correct page and limit
108
+ const cached = getCachedTable(tableName, currentPage, rowsPerPage);
109
+
110
+ if (cached && !forceFetch) {
111
+ setData(cached.data);
112
+ setSchema(cached.schema);
113
+ setTotalRows(cached.meta.total);
114
+ setTotalPages(cached.meta.totalPages);
115
+ return;
116
+ }
117
+
118
+ // Only show loading state for fresh fetches
119
+ setIsTableLoading(true);
120
+ setError(null);
121
+ setSelectedRows(new Set());
122
+
123
+ try {
124
+ const result = await switchTable(tableName, {
125
+ page: currentPage,
126
+ limit: rowsPerPage,
127
+ forceFetch
128
+ });
129
+
130
+ // If the returned meta doesn't have the correct page number, override it:
131
+ result.meta.page = currentPage;
132
+
133
+ setData(Array.isArray(result.data) ? result.data : []);
134
+ setSchema(result.schema || []);
135
+ setTotalRows(result.meta.total);
136
+ setTotalPages(result.meta.totalPages);
137
+
138
+ return true;
139
+ } catch (err) {
140
+ console.error('Error loading table data:', err);
141
+ setError(err.message || String(err));
142
+ toast({
143
+ variant: 'destructive',
144
+ title: 'Error',
145
+ description: `Failed to load table: ${err.message}`
146
+ });
147
+ throw err;
148
+ } finally {
149
+ setIsTableLoading(false);
150
+ }
151
+ }, [
152
+ tableName,
153
+ currentPage,
154
+ rowsPerPage,
155
+ getCachedTable,
156
+ switchTable,
157
+ toast,
158
+ visibleColumns.length
159
+ ]);
160
+
161
+ // Handle column visibility
162
+ const handleColumnToggle = useCallback((columnName) => {
163
+ setVisibleColumns(prev => {
164
+ const newVisibleColumns = prev.includes(columnName)
165
+ ? prev.filter(col => col !== columnName)
166
+ : [...prev, columnName];
167
+
168
+ localStorage.setItem(
169
+ `table-columns-${tableName}`,
170
+ JSON.stringify(newVisibleColumns)
171
+ );
172
+
173
+ return newVisibleColumns;
174
+ });
175
+ }, [tableName]);
176
+
177
+ // Handle column resize
178
+ const handleColumnResize = useCallback((column, newWidth) => {
179
+ setColumnWidths(prev => {
180
+ const updated = { ...prev, [column]: newWidth };
181
+ localStorage.setItem(`table-widths-${tableName}`, JSON.stringify(updated));
182
+ return updated;
183
+ });
184
+ }, [tableName]);
185
+
186
+ // Handle refresh (explicit user action)
187
+ const handleRefresh = useCallback(async () => {
188
+ try {
189
+ setSelectedRows(new Set());
190
+ invalidateTable(tableName);
191
+ await loadTableData(true);
192
+
193
+ toast({
194
+ title: 'Success',
195
+ description: 'Table data refreshed'
196
+ });
197
+ } catch (error) {
198
+ console.error('Refresh failed:', error);
199
+ toast({
200
+ variant: 'destructive',
201
+ title: 'Refresh Failed',
202
+ description: error.message
203
+ });
204
+ }
205
+ }, [
206
+ loadTableData,
207
+ invalidateTable,
208
+ tableName,
209
+ toast
210
+ ]);
211
+
212
+ // Handle sorting
213
+ const handleSort = useCallback((column, direction) => {
214
+ setSortConfigs(prev => ({
215
+ ...prev,
216
+ [column]: direction
217
+ }));
218
+
219
+ const sortedData = sortData(data, column, direction);
220
+ setData(sortedData);
221
+
222
+ // Update cache with sorted data using the correct arguments:
223
+ // tableName, new data array, schema, and meta.
224
+ const currentCache = getCachedTable(tableName);
225
+ if (currentCache) {
226
+ updateTableCache(
227
+ tableName,
228
+ sortedData,
229
+ currentCache.schema,
230
+ { ...currentCache.meta, currentPage, limit: rowsPerPage },
231
+ currentPage,
232
+ rowsPerPage
233
+ );
234
+ }
235
+ }, [data, tableName, getCachedTable, updateTableCache]);
236
+
237
+ // Start editing a cell
238
+ const handleStartEdit = useCallback((rowIndex, column, originalValue) => {
239
+ const cellKey = `${rowIndex}-${column}`;
240
+ setEditedCells((prev) =>
241
+ new Map(prev).set(cellKey, {
242
+ value: originalValue,
243
+ originalValue
244
+ })
245
+ );
246
+ setEditedRows((prev) => new Set(prev).add(rowIndex));
247
+ }, []);
248
+
249
+ // Handle cell value change
250
+ const handleCellChange = useCallback(
251
+ (rowIndex, column, value) => {
252
+ const cellKey = `${rowIndex}-${column}`;
253
+ const row = data[rowIndex];
254
+ const originalValue =
255
+ editedCells.get(cellKey)?.originalValue ?? row[column];
256
+
257
+ if (value === originalValue) {
258
+ // If value is back to original, remove from edited cells
259
+ const newEditedCells = new Map(editedCells);
260
+ newEditedCells.delete(cellKey);
261
+ setEditedCells(newEditedCells);
262
+
263
+ // Check if row has any other edits
264
+ const hasOtherEdits = Array.from(newEditedCells.keys()).some((key) =>
265
+ key.startsWith(`${rowIndex}-`)
266
+ );
267
+ if (!hasOtherEdits) {
268
+ const newEditedRows = new Set(editedRows);
269
+ newEditedRows.delete(rowIndex);
270
+ setEditedRows(newEditedRows);
271
+ }
272
+ } else {
273
+ // Add or update edit
274
+ setEditedCells((prev) =>
275
+ new Map(prev).set(cellKey, {
276
+ value,
277
+ originalValue
278
+ })
279
+ );
280
+ setEditedRows((prev) => new Set(prev).add(rowIndex));
281
+ }
282
+ },
283
+ [data, editedCells, editedRows]
284
+ );
285
+
286
+ // Add record handlers
287
+ const handleAddRecord = useCallback(() => {
288
+ setNewRecords((prev) => [...prev, {}]);
289
+ }, []);
290
+
291
+ const handleRemoveNewRecord = useCallback((index) => {
292
+ setNewRecords((prev) => prev.filter((_, i) => i !== index));
293
+ }, []);
294
+
295
+ const handleNewRecordChange = useCallback((index, record) => {
296
+ setNewRecords((prev) => {
297
+ const updated = [...prev];
298
+ updated[index] = record;
299
+ return updated;
300
+ });
301
+ }, []);
302
+
303
+ // Modified handleSaveChanges function
304
+ const handleSaveChanges = async (forceUpdate = false) => {
305
+ setIsSaving(true);
306
+ try {
307
+ // ===== Save New Records =====
308
+ if (newRecords.length > 0) {
309
+ let addedCount = 0;
310
+
311
+ // Get datetime columns from schema
312
+ const datetimeColumns = schema
313
+ .filter((col) => col.type.toLowerCase() === 'datetime')
314
+ .map((col) => col.name);
315
+
316
+ for (const record of newRecords) {
317
+ let columnsToInsert = Object.keys(record).filter(
318
+ (col) =>
319
+ record[col] !== null &&
320
+ record[col] !== '' &&
321
+ record[col] !== 'null'
322
+ );
323
+
324
+ datetimeColumns.forEach((col) => {
325
+ if (!columnsToInsert.includes(col)) {
326
+ columnsToInsert.push(col);
327
+ }
328
+ });
329
+
330
+ if (columnsToInsert.length === 0) continue;
331
+
332
+ const values = columnsToInsert.map((col) => {
333
+ if (datetimeColumns.includes(col)) {
334
+ return 'CURRENT_TIMESTAMP';
335
+ }
336
+
337
+ const value = record[col];
338
+ if (value === null || value === '' || value === 'null') return 'NULL';
339
+ return `'${value.toString().replace(/'/g, "''")}'`;
340
+ });
341
+
342
+ const insertQuery = `INSERT INTO ${tableName} (${columnsToInsert.join(
343
+ ', '
344
+ )}) VALUES (${values.join(', ')});`;
345
+
346
+ await executeQuery(insertQuery);
347
+ addedCount++;
348
+ }
349
+
350
+ if (addedCount > 0) {
351
+ // Fetch fresh data after insert using updateTableData
352
+ const result = await updateTableData(tableName);
353
+ setData(result.data);
354
+ setTotalRows(result.meta.total);
355
+ setTotalPages(Math.ceil(result.meta.total / rowsPerPage));
356
+
357
+ toast({
358
+ title: 'Success',
359
+ description: `Added ${addedCount} ${
360
+ addedCount === 1 ? 'record' : 'records'
361
+ }`
362
+ });
363
+ }
364
+ setNewRecords([]);
365
+ }
366
+
367
+ // ===== Save Edited Cells =====
368
+ if (editedCells.size > 0 && (forceUpdate || !databaseError)) {
369
+ const primaryKeyColumn = schema.find((col) => col.pk === 1)?.name;
370
+ if (!primaryKeyColumn) {
371
+ throw new Error('No primary key found in table schema');
372
+ }
373
+
374
+ const rowUpdates = new Map();
375
+ editedCells.forEach((edit, cellKey) => {
376
+ const [rowIndex, column] = cellKey.split('-');
377
+ const row = data[rowIndex];
378
+ if (!rowUpdates.has(row[primaryKeyColumn])) {
379
+ rowUpdates.set(row[primaryKeyColumn], new Map());
380
+ }
381
+ rowUpdates.get(row[primaryKeyColumn]).set(column, edit.value);
382
+ });
383
+
384
+ let updatedCount = 0;
385
+
386
+ for (const [primaryKeyValue, updates] of rowUpdates) {
387
+ const setClauses = Array.from(updates.entries())
388
+ .map(([column, value]) => {
389
+ if (value === null || value === '' || value === 'null') {
390
+ return `${column} = NULL`;
391
+ } else if (value === 'CURRENT_TIMESTAMP') {
392
+ return `${column} = CURRENT_TIMESTAMP`;
393
+ } else {
394
+ return `${column} = '${value.toString().replace(/'/g, "''")}'`;
395
+ }
396
+ })
397
+ .join(', ');
398
+
399
+ const updateQuery = `
400
+ UPDATE ${tableName}
401
+ SET ${setClauses}
402
+ WHERE ${primaryKeyColumn} = ${primaryKeyValue};
403
+ `;
404
+
405
+ await executeQuery(updateQuery);
406
+ updatedCount++;
407
+ }
408
+
409
+ if (updatedCount > 0) {
410
+ // Fetch fresh data after update using updateTableData
411
+ const result = await updateTableData(tableName);
412
+ setData(result.data);
413
+ setTotalRows(result.meta.total);
414
+ setTotalPages(Math.ceil(result.meta.total / rowsPerPage));
415
+
416
+ toast({
417
+ title: 'Success',
418
+ description: `Updated ${updatedCount} ${
419
+ updatedCount === 1 ? 'record' : 'records'
420
+ }`
421
+ });
422
+ }
423
+ }
424
+
425
+ // Clear edit states
426
+ setEditedCells(new Map());
427
+ setEditedRows(new Set());
428
+ setDatabaseError(null);
429
+ } catch (error) {
430
+
431
+ const parsedError = parseSQLError(error);
432
+ const errorData = {
433
+ ...parsedError,
434
+ stderr: error.stderr,
435
+ stdout: error.stdout
436
+ };
437
+
438
+ setDatabaseError(errorData);
439
+ setShowDatabaseError(true);
440
+
441
+ } finally {
442
+ setIsSaving(false);
443
+ }
444
+ };
445
+
446
+ // Handle delete records with cache update
447
+ const handleDeleteRecords = useCallback(async () => {
448
+ setIsDeleting(true);
449
+ setDeleteError(null);
450
+
451
+ if (!tableName) return; // Early return if no table selected
452
+
453
+ setIsDeleting(true);
454
+ setDeleteError(null);
455
+
456
+ try {
457
+ const primaryKeyColumn = schema.find((col) => col.pk === 1)?.name;
458
+ if (!primaryKeyColumn) {
459
+ throw new Error('No primary key found in table schema');
460
+ }
461
+
462
+ // Store current table name to ensure we don't switch
463
+ const currentTableName = tableName;
464
+
465
+ const selectedValues = Array.from(selectedRows).map((index) => {
466
+ const row = data[index];
467
+ return row[primaryKeyColumn];
468
+ });
469
+
470
+ if (selectedValues.length === 0) return;
471
+
472
+ const deleteQuery = `DELETE FROM ${tableName} WHERE ${primaryKeyColumn} IN (${selectedValues.join(
473
+ ','
474
+ )});`;
475
+ await executeQuery(deleteQuery);
476
+
477
+ // Update local state
478
+ const deletedSet = new Set(selectedValues);
479
+ const updatedData = data.filter((row) => !deletedSet.has(row[primaryKeyColumn]));
480
+ setData(updatedData);
481
+ setTotalRows((prev) => prev - selectedValues.length);
482
+ setTotalPages(Math.ceil((totalRows - selectedValues.length) / rowsPerPage));
483
+
484
+ // Update cache with the correct arguments:
485
+ // new data array, the same schema, and updated meta.
486
+ const currentCache = getCachedTable(tableName);
487
+ if (currentCache) {
488
+ updateTableCache(
489
+ tableName,
490
+ updatedData,
491
+ currentCache.schema,
492
+ {
493
+ ...currentCache.meta,
494
+ total: currentCache.meta.total - selectedValues.length
495
+ }
496
+ );
497
+ }
498
+
499
+ // If current page becomes empty and it's not the first page
500
+ if (currentPage > 1 && data.length === selectedValues.length) {
501
+ setCurrentPage((prev) => prev - 1);
502
+ await loadTableData();
503
+ }
504
+
505
+ setShowDeleteDialog(false);
506
+ setSelectedRows(new Set());
507
+
508
+ toast({
509
+ title: 'Success',
510
+ description: `Successfully deleted ${selectedValues.length} ${
511
+ selectedValues.length === 1 ? 'record' : 'records'
512
+ }`
513
+ });
514
+ } catch (error) {
515
+ console.error('Delete operation failed:', error);
516
+ setDeleteError(error.message || String(error));
517
+ } finally {
518
+ setIsDeleting(false);
519
+ }
520
+ }, [
521
+ tableName,
522
+ selectedRows,
523
+ data,
524
+ schema,
525
+ executeQuery,
526
+ updateTableData,
527
+ loadTableData,
528
+ currentPage,
529
+ rowsPerPage,
530
+ totalRows,
531
+ toast,
532
+ getCachedTable,
533
+ updateTableCache
534
+ ]);
535
+
536
+ // Handle discard changes
537
+ const handleDiscardChanges = () => {
538
+ setEditedCells(new Map());
539
+ setEditedRows(new Set());
540
+ setNewRecords([]);
541
+ setDatabaseError(null);
542
+
543
+ toast({
544
+ description: 'Changes discarded'
545
+ });
546
+ };
547
+
548
+ // Initialize table data
549
+ useEffect(() => {
550
+ if (!tableName) return;
551
+
552
+ // Clear states only when tableName changes
553
+ setEditedCells(new Map());
554
+ setEditedRows(new Set());
555
+ setNewRecords([]);
556
+ setError(null);
557
+ setSelectedRows(new Set());
558
+ setCurrentPage(1); // Always start at page 1 for a new table
559
+
560
+ // Look up the cache using page 1
561
+ const cached = getCachedTable(tableName, 1, rowsPerPage);
562
+ if (cached) {
563
+ setData(cached.data);
564
+ setSchema(cached.schema);
565
+ setTotalRows(cached.meta.total);
566
+ setTotalPages(cached.meta.totalPages);
567
+ setVisibleColumns((prev) => {
568
+ if (prev.length) return prev;
569
+ const columns = cached.schema.map((col) => col.name);
570
+ localStorage.setItem(`table-columns-${tableName}`, JSON.stringify(columns));
571
+ return columns;
572
+ });
573
+ } else {
574
+ loadTableData(false);
575
+ }
576
+ // Note: The dependency array now only depends on tableName (and rowsPerPage if needed)
577
+ }, [tableName, rowsPerPage]);
578
+
579
+ // Monitor active table changes
580
+ useEffect(() => {
581
+ if (activeTable === tableName) {
582
+ const cached = getCachedTable(tableName);
583
+ if (cached) {
584
+ setData(cached.data);
585
+ setSchema(cached.schema);
586
+ setTotalRows(cached.meta.total);
587
+ setTotalPages(cached.meta.totalPages);
588
+ }
589
+ }
590
+ }, [activeTable, tableName, getCachedTable]);
591
+
592
+ // Handle pagination
593
+ useEffect(() => {
594
+ if (tableName && !isTableLoading) {
595
+ // Pass the correct page and limit to the cache lookup
596
+ const cached = getCachedTable(tableName, currentPage, rowsPerPage);
597
+
598
+ if (!cached || currentPage !== cached.meta?.currentPage) {
599
+ loadTableData(false);
600
+ }
601
+ }
602
+ }, [
603
+ tableName,
604
+ currentPage,
605
+ rowsPerPage,
606
+ isTableLoading,
607
+ loadTableData,
608
+ getCachedTable]
609
+ );
610
+
611
+ // Update checkbox indeterminate state
612
+ useEffect(() => {
613
+ if (checkboxRef.current) {
614
+ checkboxRef.current.indeterminate =
615
+ selectedRows.size > 0 && selectedRows.size < data.length;
616
+ }
617
+ }, [selectedRows.size, data.length]);
618
+
619
+ // Row selection handlers
620
+ const handleSelectAll = useCallback(
621
+ (checked) => {
622
+ setSelectedRows(checked ? new Set(data.map((_, index) => index)) : new Set());
623
+ },
624
+ [data]
625
+ );
626
+
627
+ const handleRowSelect = useCallback((index, checked) => {
628
+ setSelectedRows((prev) => {
629
+ const newSelected = new Set(prev);
630
+ if (checked) {
631
+ newSelected.add(index);
632
+ } else {
633
+ newSelected.delete(index);
634
+ }
635
+ return newSelected;
636
+ });
637
+ }, []);
638
+
639
+ const handleColumnsResize = useCallback((newWidths) => {
640
+ setColumnWidths(newWidths);
641
+ localStorage.setItem(`table-widths-${tableName}`, JSON.stringify(newWidths));
642
+ }, [tableName]);
643
+
644
+ // Filter schema based on visible columns
645
+ const visibleSchema = schema.filter(col => visibleColumns.includes(col.name));
646
+
647
+ const hasChanges = editedCells.size > 0 || newRecords.length > 0;
648
+
649
+ // Error display
650
+ if (error) {
651
+ return (
652
+ <div className="p-4">
653
+ <Alert variant="destructive">
654
+ <AlertCircle className="h-4 w-4" />
655
+ <AlertDescription>Failed to load table: {error}</AlertDescription>
656
+ </Alert>
657
+ </div>
658
+ );
659
+ }
660
+
661
+ return (
662
+ <div className="h-full flex flex-col">
663
+ <TableToolbar
664
+ selectedCount={selectedRows.size}
665
+ totalRows={totalRows}
666
+ currentPage={currentPage}
667
+ totalPages={totalPages}
668
+ rowsPerPage={rowsPerPage}
669
+ onPageChange={setCurrentPage}
670
+ onRowsPerPageChange={setRowsPerPage}
671
+ onAdd={handleAddRecord}
672
+ onDelete={() => setShowDeleteDialog(true)}
673
+ onRefresh={handleRefresh}
674
+ tableName={tableName}
675
+ disabled={hasChanges}
676
+ editCount={editedCells.size}
677
+ newRecordsCount={newRecords.length}
678
+ isSaving={isSaving}
679
+ onSaveChanges={handleSaveChanges}
680
+ onDiscardChanges={handleDiscardChanges}
681
+ schema={schema}
682
+ visibleColumns={visibleColumns}
683
+ onColumnToggle={handleColumnToggle}
684
+ />
685
+
686
+ <ResizableTable columns={schema} onColumnsResize={handleColumnResize}>
687
+ <div className="relative flex-1 overflow-hidden bg-background font-mono">
688
+ <ScrollArea className="w-full h-screen">
689
+ <div className="relative w-max min-w-fit pb-4">
690
+ <Table>
691
+ {!isTableLoading && (
692
+ <TableHeader className="bg-neutral-100 sticky top-0 z-30">
693
+ <TableRow>
694
+ <TableHead className="w-10 p-0 border-r border-neutral-200">
695
+ <div className="py-0.5 px-3 flex items-center">
696
+ <Checkbox
697
+ ref={checkboxRef}
698
+ checked={selectedRows.size === data.length && data.length > 0}
699
+ onCheckedChange={handleSelectAll}
700
+ disabled={hasChanges}
701
+ />
702
+ </div>
703
+ </TableHead>
704
+ {visibleSchema.map((col) => (
705
+ <ResizableHeader
706
+ key={col.name}
707
+ width={columnWidths[col.name] || 150}
708
+ onResize={(width) => handleColumnResize(col.name, width)}
709
+ className="py-0.5 whitespace-nowrap border-r border-neutral-200"
710
+ >
711
+ <SortableHeader
712
+ column={col.name}
713
+ sortConfig={sortConfigs}
714
+ onSort={handleSort}
715
+ >
716
+ <span className="text-xs font-bold text-foreground">
717
+ {col.name}
718
+ </span>
719
+ <span className="text-xs text-muted-foreground">
720
+ {col.type?.toLowerCase()}
721
+ </span>
722
+ </SortableHeader>
723
+ </ResizableHeader>
724
+ ))}
725
+ </TableRow>
726
+ </TableHeader>
727
+ )}
728
+
729
+ <TableBody>
730
+ {isTableLoading && (
731
+ <TableRow className="hover:bg-transparent">
732
+ <TableCell
733
+ colSpan={visibleSchema.length + 1}
734
+ className="h-[calc(100vh-200px)]"
735
+ >
736
+ <div className="h-full w-full flex items-center justify-center">
737
+ <Loader2 className="h-6 w-6 animate-spin text-primary" />
738
+ </div>
739
+ </TableCell>
740
+ </TableRow>
741
+ )}
742
+
743
+ {!isTableLoading && (
744
+ <>
745
+ {/* Render New Records */}
746
+ {newRecords.map((record, index) => (
747
+ <EditableRow
748
+ key={`new-${index}`}
749
+ schema={visibleSchema}
750
+ onRemove={() => handleRemoveNewRecord(index)}
751
+ onChange={(record) => handleNewRecordChange(index, record)}
752
+ />
753
+ ))}
754
+
755
+ {/* Only show "Table is empty" message when there is no data */}
756
+ {data.length === 0 && newRecords.length === 0 ? (
757
+ <TableRow className="hover:bg-transparent">
758
+ <TableCell
759
+ colSpan={visibleSchema.length + 1}
760
+ className="h-[calc(100vh-200px)] text-center text-muted-foreground"
761
+ >
762
+ Table is empty
763
+ </TableCell>
764
+ </TableRow>
765
+ ) : (
766
+ data.map((row, index) => (
767
+ <TableRow
768
+ key={index}
769
+ className={`${selectedRows.has(index) ? 'bg-muted/50' : ''}`}
770
+ >
771
+ <TableCell className="p-0">
772
+ <div className="px-3 py-2.5 flex items-center">
773
+ <Checkbox
774
+ checked={selectedRows.has(index)}
775
+ onCheckedChange={(checked) => handleRowSelect(index, checked)}
776
+ disabled={hasChanges}
777
+ />
778
+ </div>
779
+ </TableCell>
780
+ {visibleSchema.map((col) => {
781
+ const cellKey = `${index}-${col.name}`;
782
+ const editState = editedCells.get(cellKey);
783
+ return (
784
+ <EditableCell
785
+ key={col.name}
786
+ value={editState ? editState.value : row[col.name]}
787
+ row={row}
788
+ column={col.name}
789
+ schema={schema}
790
+ onChange={(value) => handleCellChange(index, col.name, value)}
791
+ onStartEdit={(originalValue) =>
792
+ handleStartEdit(index, col.name, originalValue)
793
+ }
794
+ isEditing={editedCells.has(cellKey)}
795
+ style={{ width: `${columnWidths[col.name] || 150}px` }}
796
+ />
797
+ );
798
+ })}
799
+ </TableRow>
800
+ ))
801
+ )}
802
+ </>
803
+ )}
804
+ </TableBody>
805
+ </Table>
806
+
807
+ <ScrollBar orientation="horizontal" />
808
+ </div>
809
+ </ScrollArea>
810
+ </div>
811
+ </ResizableTable>
812
+
813
+ {/* Delete Dialog */}
814
+ <DeleteRecordsDialog
815
+ isOpen={showDeleteDialog}
816
+ onClose={() => {
817
+ setShowDeleteDialog(false);
818
+ setDeleteError(null);
819
+ }}
820
+ onConfirm={handleDeleteRecords}
821
+ selectedCount={selectedRows.size}
822
+ tableName={tableName}
823
+ isDeleting={isDeleting}
824
+ error={deleteError}
825
+ />
826
+
827
+ {/* Database Error Dialog */}
828
+ <DatabaseErrorDialog
829
+ isOpen={showDatabaseError}
830
+ onClose={() => setShowDatabaseError(false)}
831
+ error={databaseError}
832
+ onOpenInSQL={() => {
833
+ setShowDatabaseError(false);
834
+ }}
835
+ onUpdateAnyway={async () => {
836
+ setShowDatabaseError(false);
837
+ await handleSaveChanges(true); // Force update
838
+ }}
839
+ showSQLOption={databaseError?.type === 'NULLABLE_PK'}
840
+ />
841
+ </div>
842
+ );
843
+ }