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,510 @@
1
+ // context/database-context.js
2
+ 'use client';
3
+
4
+ import React, {
5
+ createContext,
6
+ useContext,
7
+ useState,
8
+ useCallback,
9
+ useEffect,
10
+ useRef,
11
+ useMemo
12
+ } from 'react';
13
+ import { useToast } from '@/hooks/use-toast';
14
+ import { deduplicateRequest } from '@/lib/request-deduplication';
15
+
16
+ const DatabaseContext = createContext(undefined);
17
+
18
+ // Simple cache implementation
19
+ class TableCache {
20
+ constructor() {
21
+ this.cache = new Map();
22
+ }
23
+
24
+ get(tableName) {
25
+ const entry = this.cache.get(tableName);
26
+ if (!entry) return null;
27
+ return entry;
28
+ }
29
+
30
+ set(tableName, data, schema, meta) {
31
+ this.cache.set(tableName, {
32
+ data,
33
+ schema,
34
+ meta,
35
+ timestamp: Date.now()
36
+ });
37
+ }
38
+
39
+ update(tableName, data, schema, meta) {
40
+ const entry = this.cache.get(tableName);
41
+ if (entry) {
42
+ this.cache.set(tableName, {
43
+ data: data || entry.data,
44
+ schema: schema || entry.schema,
45
+ meta: meta || entry.meta,
46
+ timestamp: Date.now()
47
+ });
48
+ }
49
+ }
50
+
51
+ invalidate(tableName) {
52
+ this.cache.delete(tableName);
53
+ }
54
+
55
+ clear() {
56
+ this.cache.clear();
57
+ }
58
+ }
59
+
60
+ class OperationQueue {
61
+ constructor() {
62
+ this.queue = [];
63
+ this.processing = false;
64
+ }
65
+
66
+ async add(operation) {
67
+ return new Promise((resolve, reject) => {
68
+ this.queue.push({ operation, resolve, reject });
69
+ this.process();
70
+ });
71
+ }
72
+
73
+ async process() {
74
+ if (this.processing || this.queue.length === 0) return;
75
+
76
+ this.processing = true;
77
+ const { operation, resolve, reject } = this.queue.shift();
78
+
79
+ try {
80
+ const result = await operation();
81
+ resolve(result);
82
+ } catch (error) {
83
+ reject(error);
84
+ } finally {
85
+ this.processing = false;
86
+ this.process();
87
+ }
88
+ }
89
+ }
90
+
91
+ export function DatabaseProvider({ children }) {
92
+ const { toast } = useToast();
93
+ const [tables, setTables] = useState([]);
94
+ const [isLoading, setIsLoading] = useState(true);
95
+ const [error, setError] = useState(null);
96
+ const [currentDatabase, setCurrentDatabase] = useState(null);
97
+ const operationQueue = useRef(new OperationQueue());
98
+ const [activeTable, setActiveTable] = useState(null);
99
+ const tableCache = useRef(new TableCache()).current;
100
+
101
+ // Cache management functions
102
+ const getCachedTable = useCallback((tableName, page = 1, limit = 50) => {
103
+ const key = `table-${tableName}-${page}-${limit}`;
104
+ return tableCache.get(key);
105
+ }, []);
106
+
107
+ const invalidateTable = useCallback((tableName) => {
108
+ // Invalidate all keys that start with `table-${tableName}-`
109
+ tableCache.cache.forEach((_, key) => {
110
+ if (key.startsWith(`table-${tableName}-`)) {
111
+ tableCache.invalidate(key);
112
+ }
113
+ });
114
+ }, []);
115
+
116
+ const updateTableCache = useCallback((tableName, data, schema, meta, page = 1, limit = 50) => {
117
+ const key = `table-${tableName}-${page}-${limit}`;
118
+ tableCache.update(key, data, schema, meta);
119
+ }, []);
120
+
121
+ const executeQuery = useCallback(async (query) => {
122
+ const requestKey = `query-${query}`;
123
+
124
+ return deduplicateRequest(
125
+ requestKey,
126
+ async () => {
127
+ try {
128
+ const response = await fetch('/api/query', {
129
+ method: 'POST',
130
+ headers: { 'Content-Type': 'application/json' },
131
+ body: JSON.stringify({ query })
132
+ });
133
+
134
+ if (!response.ok) {
135
+ let errorMessage = 'Failed to execute query';
136
+ try {
137
+ const errorData = await response.json();
138
+ errorMessage = errorData?.error?.message || errorMessage;
139
+ } catch (e) {
140
+ // Ignore parsing errors
141
+ }
142
+ throw new Error(errorMessage);
143
+ }
144
+
145
+ const data = await response.json();
146
+ if (!data.success) {
147
+ throw new Error(data.error || 'Query execution failed');
148
+ }
149
+
150
+ return data;
151
+ } catch (error) {
152
+ throw error || new Error("An unknown error occurred");
153
+ }
154
+ },
155
+ 1000
156
+ );
157
+ }, []);
158
+
159
+ const fetchTableSchema = useCallback(async (tableName) => {
160
+ try {
161
+ const response = await fetch(`/api/tables/${tableName}`);
162
+ const data = await response.json();
163
+
164
+ if (!response.ok || !data.success) {
165
+ throw new Error(data.error || 'Failed to fetch table schema');
166
+ }
167
+
168
+ return data.schema || [];
169
+ } catch (error) {
170
+ console.error('Schema fetch error:', error);
171
+ toast({
172
+ variant: "destructive",
173
+ title: "Schema Fetch Failed",
174
+ description: error.message,
175
+ });
176
+ throw error;
177
+ }
178
+ }, [toast]);
179
+
180
+ // Fetch table data with deduplication
181
+ const fetchTableData = useCallback(async (tableName, options = {}) => {
182
+ const { forceFetch = false, page = 1, limit = 50 } = options;
183
+
184
+ const cacheKey = `table-${tableName}-${page}-${limit}`;
185
+ if (!forceFetch) {
186
+ const cached = tableCache.get(cacheKey);
187
+ if (cached) {
188
+ return cached;
189
+ }
190
+ }
191
+
192
+ // Generate unique request key based on table name and pagination
193
+ const requestKey = `table-${tableName}-${page}-${limit}`;
194
+
195
+ return deduplicateRequest(
196
+ requestKey,
197
+ async () => {
198
+ try {
199
+ const response = await fetch(
200
+ `/api/tables/${tableName}?page=${page}&limit=${limit}`,
201
+ {
202
+ headers: {
203
+ 'Cache-Control': 'no-cache',
204
+ 'Pragma': 'no-cache'
205
+ }
206
+ }
207
+ );
208
+
209
+ if (!response.ok) {
210
+ throw new Error('Failed to fetch table data');
211
+ }
212
+
213
+ const result = await response.json();
214
+ if (!result.success) {
215
+ throw new Error(result.error || 'Failed to fetch table data');
216
+ }
217
+
218
+ // Update cache with fresh data using the composite key
219
+ tableCache.set(cacheKey, result.data, result.schema, result.meta);
220
+
221
+ return result;
222
+ } catch (error) {
223
+ console.error('Error fetching table data:', error);
224
+ toast({
225
+ variant: "destructive",
226
+ title: "Data Fetch Failed",
227
+ description: error.message,
228
+ });
229
+ throw error;
230
+ }
231
+ },
232
+ 1000 // 1 second TTL for deduplication
233
+ );
234
+ }, [toast]);
235
+
236
+ const updateTableData = useCallback(async (tableName) => {
237
+ try {
238
+ tableCache.invalidate(tableName);
239
+ const result = await fetchTableData(tableName, { forceFetch: true });
240
+ return result;
241
+ } catch (error) {
242
+ console.error('Error updating table data:', error);
243
+ toast({
244
+ variant: "destructive",
245
+ title: "Update Failed",
246
+ description: error.message,
247
+ });
248
+ throw error;
249
+ }
250
+ }, [fetchTableData, toast]);
251
+
252
+ // Switch active table
253
+ const switchTable = useCallback(async (tableName, options = {}) => {
254
+ setActiveTable(tableName);
255
+ return await fetchTableData(tableName, options);
256
+ }, [fetchTableData]);
257
+
258
+ // Refresh tables list with deduplication
259
+ const refreshTables = useCallback(async () => {
260
+ return deduplicateRequest(
261
+ 'refresh-tables',
262
+ async () => {
263
+ setIsLoading(true);
264
+ setError(null);
265
+
266
+ try {
267
+ const response = await fetch('/api/tables');
268
+ if (!response.ok) {
269
+ throw new Error('Failed to fetch tables');
270
+ }
271
+
272
+ const data = await response.json();
273
+ if (data.error) {
274
+ throw new Error(data.error);
275
+ }
276
+
277
+ setTables(data.tables || []);
278
+ return data.tables || [];
279
+ } catch (err) {
280
+ setError(err.message);
281
+ toast({
282
+ variant: "destructive",
283
+ title: "Refresh Failed",
284
+ description: err.message,
285
+ });
286
+ throw err;
287
+ } finally {
288
+ setIsLoading(false);
289
+ }
290
+ },
291
+ 2000
292
+ );
293
+ }, [toast]);
294
+
295
+ // Table operations
296
+ const createTable = useCallback(async (query) => {
297
+ try {
298
+ await executeQuery(query);
299
+ tableCache.clear(); // Clear all cache since schema changed
300
+ await refreshTables();
301
+ toast({
302
+ title: "Success",
303
+ description: "Table created successfully",
304
+ });
305
+ } catch (error) {
306
+ toast({
307
+ variant: "destructive",
308
+ title: "Create Table Failed",
309
+ description: error.message,
310
+ });
311
+ throw new Error(`Failed to create table: ${error.message}`);
312
+ }
313
+ }, [executeQuery, refreshTables, toast]);
314
+
315
+ const dropTable = useCallback(async (tableName) => {
316
+ try {
317
+ await executeQuery(`DROP TABLE ${tableName};`);
318
+ tableCache.invalidate(tableName);
319
+ await refreshTables();
320
+ toast({
321
+ title: "Success",
322
+ description: "Table dropped successfully",
323
+ });
324
+ } catch (error) {
325
+ toast({
326
+ variant: "destructive",
327
+ title: "Drop Table Failed",
328
+ description: error.message,
329
+ });
330
+ throw new Error(`Failed to drop table: ${error.message}`);
331
+ }
332
+ }, [executeQuery, refreshTables, toast]);
333
+
334
+ const syncMigrations = useCallback(async (credentials) => {
335
+ try {
336
+ const response = await fetch('/api/migrations/sync', {
337
+ method: 'POST',
338
+ headers: {
339
+ 'Content-Type': 'application/json',
340
+ },
341
+ body: JSON.stringify(credentials)
342
+ });
343
+
344
+ if (!response.ok) {
345
+ const error = await response.json();
346
+ throw new Error(error.error?.message || 'Failed to sync migrations');
347
+ }
348
+
349
+ const result = await response.json();
350
+ toast({
351
+ title: "Success",
352
+ description: "Migrations synced successfully",
353
+ });
354
+ return result;
355
+ } catch (error) {
356
+ console.error('Error syncing migrations:', error);
357
+ toast({
358
+ variant: "destructive",
359
+ title: "Sync Failed",
360
+ description: error.message,
361
+ });
362
+ throw error;
363
+ }
364
+ }, [toast]);
365
+
366
+ const pullFromRemote = useCallback(async () => {
367
+ try {
368
+ const storedCreds = localStorage.getItem('cf_credentials');
369
+ if (!storedCreds) {
370
+ throw new Error('No Cloudflare credentials found. Please connect to Cloudflare first.');
371
+ }
372
+
373
+ const credentials = JSON.parse(storedCreds);
374
+ if (!credentials.accountId || !credentials.apiToken) {
375
+ throw new Error('Invalid credentials stored. Please reconnect to Cloudflare.');
376
+ }
377
+
378
+ // Call the confirm endpoint to actually apply the remote migrations
379
+ const response = await fetch('/api/pull-remote/confirm', {
380
+ method: 'POST',
381
+ headers: { 'Content-Type': 'application/json' },
382
+ body: JSON.stringify({
383
+ accountId: credentials.accountId,
384
+ apiToken: credentials.apiToken
385
+ })
386
+ });
387
+
388
+ const data = await response.json();
389
+
390
+ if (!response.ok || !data.success) {
391
+ throw new Error(data.error?.message || 'Failed to pull from remote');
392
+ }
393
+
394
+ // Clear local caches and refresh the table list to reflect the new state.
395
+ tableCache.clear();
396
+ await refreshTables();
397
+
398
+ toast({
399
+ title: "Success",
400
+ description: `Remote state applied successfully. Migrations applied: ${data.details.appliedMigrations.join(', ')}`,
401
+ });
402
+
403
+ return data;
404
+ } catch (error) {
405
+ console.error('Error pulling from remote:', error);
406
+ toast({
407
+ variant: "destructive",
408
+ title: "Pull Failed",
409
+ description: error.message,
410
+ });
411
+ throw error;
412
+ }
413
+ }, [refreshTables, toast]);
414
+
415
+ const pushToRemote = useCallback(async (credentials) => {
416
+ try {
417
+ const response = await fetch('/api/push-remote', {
418
+ method: 'POST',
419
+ headers: { 'Content-Type': 'application/json' },
420
+ body: JSON.stringify(credentials)
421
+ });
422
+
423
+ const data = await response.json();
424
+
425
+ if (!response.ok) {
426
+ throw new Error(data.error?.message || 'Failed to push to remote');
427
+ }
428
+
429
+ // // Show a success toast.
430
+ // toast({
431
+ // title: "Success",
432
+ // description: "Successfully pushed to remote",
433
+ // });
434
+
435
+ return data;
436
+ } catch (error) {
437
+ console.error('Error pushing to remote:', error);
438
+ // toast({
439
+ // variant: "destructive",
440
+ // title: "Push Failed",
441
+ // description: error.message,
442
+ // });
443
+ throw error;
444
+ }
445
+ }, [toast]);
446
+
447
+ // Initial load
448
+ useEffect(() => {
449
+ refreshTables();
450
+ return () => {
451
+ tableCache.clear(); // Clear cache on unmount
452
+ };
453
+ }, [refreshTables]);
454
+
455
+ const value = useMemo(() => ({
456
+ tables,
457
+ currentDatabase,
458
+ isLoading,
459
+ error,
460
+ activeTable,
461
+ refreshTables,
462
+ executeQuery,
463
+ fetchTableSchema,
464
+ fetchTableData,
465
+ updateTableData,
466
+ createTable,
467
+ dropTable,
468
+ syncMigrations,
469
+ pullFromRemote,
470
+ pushToRemote,
471
+ getCachedTable,
472
+ updateTableCache,
473
+ invalidateTable,
474
+ switchTable
475
+ }), [
476
+ tables,
477
+ currentDatabase,
478
+ isLoading,
479
+ error,
480
+ activeTable,
481
+ refreshTables,
482
+ executeQuery,
483
+ fetchTableSchema,
484
+ fetchTableData,
485
+ updateTableData,
486
+ createTable,
487
+ dropTable,
488
+ syncMigrations,
489
+ pullFromRemote,
490
+ pushToRemote,
491
+ getCachedTable,
492
+ updateTableCache,
493
+ invalidateTable,
494
+ switchTable
495
+ ]);
496
+
497
+ return (
498
+ <DatabaseContext.Provider value={value}>
499
+ {children}
500
+ </DatabaseContext.Provider>
501
+ );
502
+ }
503
+
504
+ export function useDatabase() {
505
+ const context = useContext(DatabaseContext);
506
+ if (!context) {
507
+ throw new Error('useDatabase must be used within a DatabaseProvider');
508
+ }
509
+ return context;
510
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange);
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,23 @@
1
+ // hooks/use-sql-error.js
2
+ import { useState, useCallback } from 'react';
3
+ import { parseSQLError } from '@/lib/parse-sql-error';
4
+
5
+ export function useSQLError() {
6
+ const [sqlError, setSQLError] = useState(null);
7
+
8
+ const handleSQLError = useCallback((error) => {
9
+ const parsedError = parseSQLError(error);
10
+ setSQLError(parsedError);
11
+ return parsedError;
12
+ }, []);
13
+
14
+ const clearSQLError = useCallback(() => {
15
+ setSQLError(null);
16
+ }, []);
17
+
18
+ return {
19
+ sqlError,
20
+ handleSQLError,
21
+ clearSQLError
22
+ };
23
+ }
@@ -0,0 +1,155 @@
1
+ "use client";
2
+ // Inspired by react-hot-toast library
3
+ import * as React from "react"
4
+
5
+ const TOAST_LIMIT = 1
6
+ const TOAST_REMOVE_DELAY = 1000000
7
+
8
+ const actionTypes = {
9
+ ADD_TOAST: "ADD_TOAST",
10
+ UPDATE_TOAST: "UPDATE_TOAST",
11
+ DISMISS_TOAST: "DISMISS_TOAST",
12
+ REMOVE_TOAST: "REMOVE_TOAST"
13
+ }
14
+
15
+ let count = 0
16
+
17
+ function genId() {
18
+ count = (count + 1) % Number.MAX_SAFE_INTEGER
19
+ return count.toString();
20
+ }
21
+
22
+ const toastTimeouts = new Map()
23
+
24
+ const addToRemoveQueue = (toastId) => {
25
+ if (toastTimeouts.has(toastId)) {
26
+ return
27
+ }
28
+
29
+ const timeout = setTimeout(() => {
30
+ toastTimeouts.delete(toastId)
31
+ dispatch({
32
+ type: "REMOVE_TOAST",
33
+ toastId: toastId,
34
+ })
35
+ }, TOAST_REMOVE_DELAY)
36
+
37
+ toastTimeouts.set(toastId, timeout)
38
+ }
39
+
40
+ export const reducer = (state, action) => {
41
+ switch (action.type) {
42
+ case "ADD_TOAST":
43
+ return {
44
+ ...state,
45
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
46
+ };
47
+
48
+ case "UPDATE_TOAST":
49
+ return {
50
+ ...state,
51
+ toasts: state.toasts.map((t) =>
52
+ t.id === action.toast.id ? { ...t, ...action.toast } : t),
53
+ };
54
+
55
+ case "DISMISS_TOAST": {
56
+ const { toastId } = action
57
+
58
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
59
+ // but I'll keep it here for simplicity
60
+ if (toastId) {
61
+ addToRemoveQueue(toastId)
62
+ } else {
63
+ state.toasts.forEach((toast) => {
64
+ addToRemoveQueue(toast.id)
65
+ })
66
+ }
67
+
68
+ return {
69
+ ...state,
70
+ toasts: state.toasts.map((t) =>
71
+ t.id === toastId || toastId === undefined
72
+ ? {
73
+ ...t,
74
+ open: false,
75
+ }
76
+ : t),
77
+ };
78
+ }
79
+ case "REMOVE_TOAST":
80
+ if (action.toastId === undefined) {
81
+ return {
82
+ ...state,
83
+ toasts: [],
84
+ }
85
+ }
86
+ return {
87
+ ...state,
88
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
89
+ };
90
+ }
91
+ }
92
+
93
+ const listeners = []
94
+
95
+ let memoryState = { toasts: [] }
96
+
97
+ function dispatch(action) {
98
+ memoryState = reducer(memoryState, action)
99
+ listeners.forEach((listener) => {
100
+ listener(memoryState)
101
+ })
102
+ }
103
+
104
+ function toast({
105
+ ...props
106
+ }) {
107
+ const id = genId()
108
+
109
+ const update = (props) =>
110
+ dispatch({
111
+ type: "UPDATE_TOAST",
112
+ toast: { ...props, id },
113
+ })
114
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
115
+
116
+ dispatch({
117
+ type: "ADD_TOAST",
118
+ toast: {
119
+ ...props,
120
+ id,
121
+ open: true,
122
+ onOpenChange: (open) => {
123
+ if (!open) dismiss()
124
+ },
125
+ },
126
+ })
127
+
128
+ return {
129
+ id: id,
130
+ dismiss,
131
+ update,
132
+ }
133
+ }
134
+
135
+ function useToast() {
136
+ const [state, setState] = React.useState(memoryState)
137
+
138
+ React.useEffect(() => {
139
+ listeners.push(setState)
140
+ return () => {
141
+ const index = listeners.indexOf(setState)
142
+ if (index > -1) {
143
+ listeners.splice(index, 1)
144
+ }
145
+ };
146
+ }, [state])
147
+
148
+ return {
149
+ ...state,
150
+ toast,
151
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }),
152
+ };
153
+ }
154
+
155
+ export { useToast, toast }