d1s 0.2.6 → 0.2.9

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 (296) hide show
  1. package/README.md +3 -1
  2. package/dist/.next/.next/BUILD_ID +1 -1
  3. package/dist/.next/.next/app-build-manifest.json +38 -24
  4. package/dist/.next/.next/app-path-routes-manifest.json +1 -1
  5. package/dist/.next/.next/build-manifest.json +2 -2
  6. package/dist/.next/.next/cache/.rscinfo +1 -1
  7. package/dist/.next/.next/cache/.tsbuildinfo +1 -1
  8. package/dist/.next/.next/cache/webpack/client-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/index.pack +0 -0
  14. package/dist/.next/.next/cache/webpack/server-production/0.pack +0 -0
  15. package/dist/.next/.next/cache/webpack/server-production/index.pack +0 -0
  16. package/dist/.next/.next/next-minimal-server.js.nft.json +1 -1
  17. package/dist/.next/.next/next-server.js.nft.json +1 -1
  18. package/dist/.next/.next/prerender-manifest.json +1 -1
  19. package/dist/.next/.next/server/app/_not-found/page.js +1 -1
  20. package/dist/.next/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  21. package/dist/.next/.next/server/app/_not-found.html +1 -1
  22. package/dist/.next/.next/server/app/_not-found.rsc +4 -4
  23. package/dist/.next/.next/server/app/api/cloudflare/route.js +1 -1
  24. package/dist/.next/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
  25. package/dist/.next/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
  26. package/dist/.next/.next/server/app/api/databases/route.js +1 -1
  27. package/dist/.next/.next/server/app/api/databases/route.js.nft.json +1 -1
  28. package/dist/.next/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
  29. package/dist/.next/.next/server/app/api/migrations/sync/route.js +28 -3
  30. package/dist/.next/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
  31. package/dist/.next/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
  32. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js +26 -1
  33. package/dist/.next/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
  34. package/dist/.next/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
  35. package/dist/.next/.next/server/app/api/pull-data/confirm/route.js +1 -0
  36. package/dist/.next/.next/server/app/api/pull-data/confirm/route.js.nft.json +1 -0
  37. package/dist/.next/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -0
  38. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js +26 -1
  39. package/dist/.next/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
  40. package/dist/.next/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
  41. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js +26 -1
  42. package/dist/.next/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
  43. package/dist/.next/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
  44. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js +28 -3
  45. package/dist/.next/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
  46. package/dist/.next/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
  47. package/dist/.next/.next/server/app/api/push-remote/preview/route.js +28 -3
  48. package/dist/.next/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
  49. package/dist/.next/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
  50. package/dist/.next/.next/server/app/api/query/route.js +27 -2
  51. package/dist/.next/.next/server/app/api/query/route.js.nft.json +1 -1
  52. package/dist/.next/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
  53. package/dist/.next/.next/server/app/api/tables/[name]/route.js +4 -4
  54. package/dist/.next/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
  55. package/dist/.next/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
  56. package/dist/.next/.next/server/app/api/tables/route.js +2 -2
  57. package/dist/.next/.next/server/app/api/tables/route.js.nft.json +1 -1
  58. package/dist/.next/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
  59. package/dist/.next/.next/server/app/api/update/route.js +5 -0
  60. package/dist/.next/.next/server/app/api/update/route.js.nft.json +1 -0
  61. package/dist/.next/.next/server/app/api/update/route_client-reference-manifest.js +1 -0
  62. package/dist/.next/.next/server/app/index.html +3 -3
  63. package/dist/.next/.next/server/app/index.rsc +5 -5
  64. package/dist/.next/.next/server/app/page.js +13 -11
  65. package/dist/.next/.next/server/app/page_client-reference-manifest.js +1 -1
  66. package/dist/.next/.next/server/app-paths-manifest.json +5 -3
  67. package/dist/.next/.next/server/chunks/226.js +30 -0
  68. package/dist/.next/.next/server/chunks/336.js +1 -1
  69. package/dist/.next/.next/server/chunks/391.js +23 -0
  70. package/dist/.next/.next/server/chunks/452.js +1 -0
  71. package/dist/.next/.next/server/chunks/627.js +3 -3
  72. package/dist/.next/.next/server/chunks/638.js +3 -3
  73. package/dist/.next/.next/server/chunks/992.js +3 -3
  74. package/dist/.next/.next/server/pages/404.html +1 -1
  75. package/dist/.next/.next/server/pages/500.html +1 -1
  76. package/dist/.next/.next/server/pages/_app.js +1 -1
  77. package/dist/.next/.next/server/pages/_document.js +1 -1
  78. package/dist/.next/.next/server/pages/_error.js +1 -1
  79. package/dist/.next/.next/server/server-reference-manifest.json +1 -1
  80. package/dist/.next/.next/static/7XBqETNmhSxMXhw8iUpEa/_buildManifest.js +1 -0
  81. package/dist/.next/.next/static/chunks/176-9146975ef8699719.js +1 -0
  82. package/dist/.next/.next/static/chunks/{735-c9144179c6bd7d06.js → 735-b885dfec6353171d.js} +1 -1
  83. package/dist/.next/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +1 -0
  84. package/dist/.next/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +1 -0
  85. package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +1 -0
  86. package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +1 -0
  87. package/dist/.next/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +1 -0
  88. package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +1 -0
  89. package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +1 -0
  90. package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +1 -0
  91. package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +1 -0
  92. package/dist/.next/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +1 -0
  93. package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +1 -0
  94. package/dist/.next/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +1 -0
  95. package/dist/.next/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +1 -0
  96. package/dist/.next/.next/static/chunks/app/page-5990cb23b8bd27c4.js +1 -0
  97. package/dist/.next/.next/static/css/674bee6608c638e4.css +3 -0
  98. package/dist/.next/.next/trace +3 -3
  99. package/dist/.next/.next/types/app/api/pull-data/confirm/route.ts +347 -0
  100. package/dist/.next/.next/types/app/api/update/route.ts +347 -0
  101. package/dist/.next/BUILD_ID +1 -1
  102. package/dist/.next/app-build-manifest.json +36 -22
  103. package/dist/.next/app-path-routes-manifest.json +1 -1
  104. package/dist/.next/build-manifest.json +2 -2
  105. package/dist/.next/cache/.rscinfo +1 -1
  106. package/dist/.next/cache/.tsbuildinfo +1 -1
  107. package/dist/.next/cache/webpack/client-production/0.pack +0 -0
  108. package/dist/.next/cache/webpack/client-production/index.pack +0 -0
  109. package/dist/.next/cache/webpack/edge-server-production/index.pack +0 -0
  110. package/dist/.next/cache/webpack/server-production/0.pack +0 -0
  111. package/dist/.next/cache/webpack/server-production/index.pack +0 -0
  112. package/dist/.next/next-minimal-server.js.nft.json +1 -1
  113. package/dist/.next/next-server.js.nft.json +1 -1
  114. package/dist/.next/prerender-manifest.json +1 -1
  115. package/dist/.next/server/app/_not-found/page.js +1 -1
  116. package/dist/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  117. package/dist/.next/server/app/_not-found.html +1 -1
  118. package/dist/.next/server/app/_not-found.rsc +4 -4
  119. package/dist/.next/server/app/api/cloudflare/route.js +1 -1
  120. package/dist/.next/server/app/api/cloudflare/route.js.nft.json +1 -1
  121. package/dist/.next/server/app/api/cloudflare/route_client-reference-manifest.js +1 -1
  122. package/dist/.next/server/app/api/databases/route.js +1 -1
  123. package/dist/.next/server/app/api/databases/route.js.nft.json +1 -1
  124. package/dist/.next/server/app/api/databases/route_client-reference-manifest.js +1 -1
  125. package/dist/.next/server/app/api/migrations/sync/route.js +28 -3
  126. package/dist/.next/server/app/api/migrations/sync/route.js.nft.json +1 -1
  127. package/dist/.next/server/app/api/migrations/sync/route_client-reference-manifest.js +1 -1
  128. package/dist/.next/server/app/api/migrations/sync-files/route.js +26 -1
  129. package/dist/.next/server/app/api/migrations/sync-files/route.js.nft.json +1 -1
  130. package/dist/.next/server/app/api/migrations/sync-files/route_client-reference-manifest.js +1 -1
  131. package/dist/.next/server/app/api/pull-data/confirm/route.js +1 -0
  132. package/dist/.next/server/app/api/pull-data/confirm/route.js.nft.json +1 -0
  133. package/dist/.next/server/app/api/pull-data/confirm/route_client-reference-manifest.js +1 -0
  134. package/dist/.next/server/app/api/pull-remote/confirm/route.js +26 -1
  135. package/dist/.next/server/app/api/pull-remote/confirm/route.js.nft.json +1 -1
  136. package/dist/.next/server/app/api/pull-remote/confirm/route_client-reference-manifest.js +1 -1
  137. package/dist/.next/server/app/api/pull-remote/preview/route.js +26 -1
  138. package/dist/.next/server/app/api/pull-remote/preview/route.js.nft.json +1 -1
  139. package/dist/.next/server/app/api/pull-remote/preview/route_client-reference-manifest.js +1 -1
  140. package/dist/.next/server/app/api/push-remote/confirm/route.js +28 -3
  141. package/dist/.next/server/app/api/push-remote/confirm/route.js.nft.json +1 -1
  142. package/dist/.next/server/app/api/push-remote/confirm/route_client-reference-manifest.js +1 -1
  143. package/dist/.next/server/app/api/push-remote/preview/route.js +28 -3
  144. package/dist/.next/server/app/api/push-remote/preview/route.js.nft.json +1 -1
  145. package/dist/.next/server/app/api/push-remote/preview/route_client-reference-manifest.js +1 -1
  146. package/dist/.next/server/app/api/query/route.js +27 -2
  147. package/dist/.next/server/app/api/query/route.js.nft.json +1 -1
  148. package/dist/.next/server/app/api/query/route_client-reference-manifest.js +1 -1
  149. package/dist/.next/server/app/api/tables/[name]/route.js +4 -4
  150. package/dist/.next/server/app/api/tables/[name]/route.js.nft.json +1 -1
  151. package/dist/.next/server/app/api/tables/[name]/route_client-reference-manifest.js +1 -1
  152. package/dist/.next/server/app/api/tables/route.js +2 -2
  153. package/dist/.next/server/app/api/tables/route.js.nft.json +1 -1
  154. package/dist/.next/server/app/api/tables/route_client-reference-manifest.js +1 -1
  155. package/dist/.next/server/app/api/update/route.js +5 -0
  156. package/dist/.next/server/app/api/update/route.js.nft.json +1 -0
  157. package/dist/.next/server/app/api/update/route_client-reference-manifest.js +1 -0
  158. package/dist/.next/server/app/index.html +3 -3
  159. package/dist/.next/server/app/index.rsc +5 -5
  160. package/dist/.next/server/app/page.js +13 -11
  161. package/dist/.next/server/app/page_client-reference-manifest.js +1 -1
  162. package/dist/.next/server/app-paths-manifest.json +8 -6
  163. package/dist/.next/server/chunks/226.js +30 -0
  164. package/dist/.next/server/chunks/336.js +1 -1
  165. package/dist/.next/server/chunks/391.js +23 -0
  166. package/dist/.next/server/chunks/452.js +1 -0
  167. package/dist/.next/server/chunks/627.js +3 -3
  168. package/dist/.next/server/chunks/638.js +3 -3
  169. package/dist/.next/server/chunks/992.js +3 -3
  170. package/dist/.next/server/pages/404.html +1 -1
  171. package/dist/.next/server/pages/500.html +1 -1
  172. package/dist/.next/server/pages/_app.js +1 -1
  173. package/dist/.next/server/pages/_document.js +1 -1
  174. package/dist/.next/server/pages/_error.js +1 -1
  175. package/dist/.next/server/server-reference-manifest.json +1 -1
  176. package/dist/.next/static/MoZBULXFiTFzrY1JVK_Df/_buildManifest.js +1 -0
  177. package/dist/.next/static/chunks/176-9146975ef8699719.js +1 -0
  178. package/dist/.next/static/chunks/{735-c9144179c6bd7d06.js → 735-b885dfec6353171d.js} +1 -1
  179. package/dist/.next/static/chunks/app/api/cloudflare/route-b77846f372b01f38.js +1 -0
  180. package/dist/.next/static/chunks/app/api/databases/route-407794f8145d9a0b.js +1 -0
  181. package/dist/.next/static/chunks/app/api/migrations/sync/route-9f480f5590369a8f.js +1 -0
  182. package/dist/.next/static/chunks/app/api/migrations/sync-files/route-92010db279b4dd8e.js +1 -0
  183. package/dist/.next/static/chunks/app/api/pull-data/confirm/route-a02fe6d3cdd0a535.js +1 -0
  184. package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-f401a03507d1da50.js +1 -0
  185. package/dist/.next/static/chunks/app/api/pull-remote/preview/route-3c53814b5cb8b6b0.js +1 -0
  186. package/dist/.next/static/chunks/app/api/push-remote/confirm/route-8f359249e907c63b.js +1 -0
  187. package/dist/.next/static/chunks/app/api/push-remote/preview/route-b51bf94f39c17a9d.js +1 -0
  188. package/dist/.next/static/chunks/app/api/query/route-87bae2d4aebaf859.js +1 -0
  189. package/dist/.next/static/chunks/app/api/tables/[name]/route-d20ca163b9c03e7c.js +1 -0
  190. package/dist/.next/static/chunks/app/api/tables/route-0f46f911562abcdf.js +1 -0
  191. package/dist/.next/static/chunks/app/api/update/route-14edc1917760bce0.js +1 -0
  192. package/dist/.next/static/chunks/app/page-5990cb23b8bd27c4.js +1 -0
  193. package/dist/.next/static/css/674bee6608c638e4.css +3 -0
  194. package/dist/.next/trace +17 -14
  195. package/dist/.next/types/app/api/pull-data/confirm/route.ts +347 -0
  196. package/dist/.next/types/app/api/update/route.ts +347 -0
  197. package/dist/app/api/cloudflare/route.js +5 -1
  198. package/dist/app/api/databases/route.js +3 -4
  199. package/dist/app/api/migrations/sync/route.js +5 -3
  200. package/dist/app/api/pull-data/confirm/route.js +230 -0
  201. package/dist/app/api/pull-remote/confirm/route.js +24 -23
  202. package/dist/app/api/pull-remote/preview/route.js +4 -3
  203. package/dist/app/api/push-remote/preview/route.js +3 -2
  204. package/dist/app/api/query/route.js +11 -3
  205. package/dist/app/api/tables/[name]/route.js +3 -2
  206. package/dist/app/api/tables/route.js +6 -2
  207. package/dist/app/api/update/route.js +36 -0
  208. package/dist/app/app/api/cloudflare/route.js +5 -1
  209. package/dist/app/app/api/databases/route.js +3 -4
  210. package/dist/app/app/api/migrations/sync/route.js +5 -3
  211. package/dist/app/app/api/pull-data/confirm/route.js +230 -0
  212. package/dist/app/app/api/pull-remote/confirm/route.js +24 -23
  213. package/dist/app/app/api/pull-remote/preview/route.js +4 -3
  214. package/dist/app/app/api/push-remote/preview/route.js +3 -2
  215. package/dist/app/app/api/query/route.js +11 -3
  216. package/dist/app/app/api/tables/[name]/route.js +3 -2
  217. package/dist/app/app/api/tables/route.js +6 -2
  218. package/dist/app/app/api/update/route.js +36 -0
  219. package/dist/app/app/page.jsx +24 -14
  220. package/dist/app/page.jsx +24 -14
  221. package/dist/d1-studio.js +101 -58
  222. package/dist/lib/database-queue.js +34 -30
  223. package/dist/lib/find-wrangler-config.js +14 -8
  224. package/dist/lib/logger.js +44 -5
  225. package/dist/lib/migrations.js +4 -4
  226. package/dist/lib/schema-operations.js +4 -1
  227. package/dist/lib/sql-operations.js +85 -1
  228. package/package.json +3 -1
  229. package/scripts/studio.js +101 -58
  230. package/scripts/test.js +280 -82
  231. package/src/app/api/cloudflare/route.js +5 -1
  232. package/src/app/api/databases/route.js +3 -4
  233. package/src/app/api/migrations/sync/route.js +5 -3
  234. package/src/app/api/pull-data/confirm/route.js +230 -0
  235. package/src/app/api/pull-remote/confirm/route.js +24 -23
  236. package/src/app/api/pull-remote/preview/route.js +4 -3
  237. package/src/app/api/push-remote/preview/route.js +3 -2
  238. package/src/app/api/query/route.js +11 -3
  239. package/src/app/api/tables/[name]/route.js +3 -2
  240. package/src/app/api/tables/route.js +6 -2
  241. package/src/app/api/update/route.js +36 -0
  242. package/src/app/page.jsx +24 -14
  243. package/src/components/environment-handler.jsx +70 -16
  244. package/src/components/environment-select.jsx +6 -3
  245. package/src/components/pull-preview-toast.jsx +90 -63
  246. package/src/components/sidebar.jsx +25 -24
  247. package/src/components/update-banner.jsx +62 -0
  248. package/src/context/database-context.js +4 -4
  249. package/src/lib/database-queue.js +34 -30
  250. package/src/lib/find-wrangler-config.js +14 -8
  251. package/src/lib/logger.js +44 -5
  252. package/src/lib/migrations.js +4 -4
  253. package/src/lib/schema-operations.js +4 -1
  254. package/src/lib/sql-operations.js +85 -1
  255. package/dist/.next/.next/cache/webpack/client-production/3.pack +0 -0
  256. package/dist/.next/.next/cache/webpack/server-production/1.pack +0 -0
  257. package/dist/.next/.next/cache/webpack/server-production/2.pack +0 -0
  258. package/dist/.next/.next/cache/webpack/server-production/index.pack.old +0 -0
  259. package/dist/.next/.next/server/chunks/603.js +0 -55
  260. package/dist/.next/.next/server/chunks/686.js +0 -23
  261. package/dist/.next/.next/static/HsZ8OanS5v86DqC9rErO-/_buildManifest.js +0 -1
  262. package/dist/.next/.next/static/chunks/422-6fa3c14fc64ad67b.js +0 -1
  263. package/dist/.next/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +0 -1
  264. package/dist/.next/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +0 -1
  265. package/dist/.next/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +0 -1
  266. package/dist/.next/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +0 -1
  267. package/dist/.next/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +0 -1
  268. package/dist/.next/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +0 -1
  269. package/dist/.next/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +0 -1
  270. package/dist/.next/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +0 -1
  271. package/dist/.next/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +0 -1
  272. package/dist/.next/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +0 -1
  273. package/dist/.next/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +0 -1
  274. package/dist/.next/.next/static/chunks/app/page-79049bfa6cc07e11.js +0 -1
  275. package/dist/.next/.next/static/css/cf41da7a0d47f779.css +0 -3
  276. package/dist/.next/.next/static/q6WmQmyONe88bMN0_jrC2/_buildManifest.js +0 -1
  277. package/dist/.next/server/chunks/603.js +0 -55
  278. package/dist/.next/server/chunks/686.js +0 -23
  279. package/dist/.next/static/Tk1fnz_CXLavm23ZEeChG/_buildManifest.js +0 -1
  280. package/dist/.next/static/Tk1fnz_CXLavm23ZEeChG/_ssgManifest.js +0 -1
  281. package/dist/.next/static/chunks/422-6fa3c14fc64ad67b.js +0 -1
  282. package/dist/.next/static/chunks/app/api/cloudflare/route-3458d78022185d7f.js +0 -1
  283. package/dist/.next/static/chunks/app/api/databases/route-64255424877a9f72.js +0 -1
  284. package/dist/.next/static/chunks/app/api/migrations/sync/route-03766b3afcf043ba.js +0 -1
  285. package/dist/.next/static/chunks/app/api/migrations/sync-files/route-02fa291c8000dadf.js +0 -1
  286. package/dist/.next/static/chunks/app/api/pull-remote/confirm/route-7e05bb8920127abe.js +0 -1
  287. package/dist/.next/static/chunks/app/api/pull-remote/preview/route-0fa15f783e8a306c.js +0 -1
  288. package/dist/.next/static/chunks/app/api/push-remote/confirm/route-96691f1880e4ed14.js +0 -1
  289. package/dist/.next/static/chunks/app/api/push-remote/preview/route-a798679c67374552.js +0 -1
  290. package/dist/.next/static/chunks/app/api/query/route-e90d0030a5083e20.js +0 -1
  291. package/dist/.next/static/chunks/app/api/tables/[name]/route-1efe63e73b480e58.js +0 -1
  292. package/dist/.next/static/chunks/app/api/tables/route-3772b4f480c4b4a4.js +0 -1
  293. package/dist/.next/static/chunks/app/page-79049bfa6cc07e11.js +0 -1
  294. package/dist/.next/static/css/cf41da7a0d47f779.css +0 -3
  295. /package/dist/.next/.next/static/{HsZ8OanS5v86DqC9rErO- → 7XBqETNmhSxMXhw8iUpEa}/_ssgManifest.js +0 -0
  296. /package/dist/.next/{.next/static/q6WmQmyONe88bMN0_jrC2 → static/MoZBULXFiTFzrY1JVK_Df}/_ssgManifest.js +0 -0
@@ -11,15 +11,19 @@ import {
11
11
  import { handleSchemaChange } from '@/lib/migrations';
12
12
  import { isSchemaChange } from '@/lib/sql-operations';
13
13
  import { parseSQLError } from '@/lib/parse-sql-error';
14
+ import logger from '@/lib/logger';
14
15
 
15
16
  /**
16
17
  * API POST handler to execute SQL queries against the configured D1 database.
17
18
  */
18
19
  export async function POST(req) {
20
+ logger.logRequest('POST', '/api/query');
21
+
19
22
  try {
20
23
  // Ensure that the project directory is set.
21
24
  const projectDir = process.env.D1_PROJECT_DIR;
22
25
  if (!projectDir) {
26
+ logger.error('Project directory not configured');
23
27
  return NextResponse.json(
24
28
  { error: 'Project directory not configured' },
25
29
  { status: 500 }
@@ -28,7 +32,10 @@ export async function POST(req) {
28
32
 
29
33
  // Extract the SQL query from the request body.
30
34
  const { query } = await req.json();
31
- // console.log('Received query:', query);
35
+
36
+ if (logger.shouldLog('debug')) {
37
+ logger.debug('Received query:', query);
38
+ }
32
39
 
33
40
  if (!query?.trim()) {
34
41
  return NextResponse.json(
@@ -40,6 +47,7 @@ export async function POST(req) {
40
47
  // Retrieve the Wrangler configuration using the centralized helper.
41
48
  const wranglerResult = await findWranglerConfig(projectDir);
42
49
  if (!wranglerResult || !wranglerResult.config) {
50
+ logger.error('No Wrangler configuration file found');
43
51
  return NextResponse.json(
44
52
  { success: false, error: { message: 'No Wrangler configuration file found' } },
45
53
  { status: 404 }
@@ -94,7 +102,7 @@ export async function POST(req) {
94
102
  // Process schema changes and capture migrations.
95
103
  // The handleSchemaChange helper is responsible for executing the DDL statements.
96
104
  const migrations = await handleSchemaChange(projectDir, databaseName, statements);
97
- console.log('Schema changes processed:', migrations);
105
+ // console.log('Schema changes processed:', migrations);
98
106
 
99
107
  result = {
100
108
  success: true,
@@ -127,7 +135,7 @@ export async function POST(req) {
127
135
  return NextResponse.json(result);
128
136
 
129
137
  } catch (error) {
130
- console.error('Query execution error:', error);
138
+ logger.logError(error, 'query-route');
131
139
  const parsedError = parseSQLError(error);
132
140
 
133
141
  const statusCode =
@@ -5,6 +5,7 @@ import { promisify } from 'util';
5
5
  import { exec } from 'child_process';
6
6
  import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
7
  import { dbQueue } from '@/lib/database-queue';
8
+ import logger from '@/lib/logger';
8
9
 
9
10
  const execAsync = promisify(exec);
10
11
 
@@ -35,7 +36,7 @@ async function executeD1Query(command, projectDir, databaseName) {
35
36
  const result = JSON.parse(stdout);
36
37
  return result[0]?.results || [];
37
38
  } catch (error) {
38
- console.error('Query execution error:', error);
39
+ logger.error('Query execution error:', error);
39
40
  throw error;
40
41
  } finally {
41
42
  isProcessing = false;
@@ -145,7 +146,7 @@ export async function GET(request, context) {
145
146
  });
146
147
 
147
148
  } catch (error) {
148
- console.error('Error handling request:', error);
149
+ logger.error('Error handling request:', error);
149
150
  return NextResponse.json({
150
151
  success: false,
151
152
  error: {
@@ -4,6 +4,7 @@ import { NextResponse } from 'next/server';
4
4
  import { promisify } from 'util';
5
5
  import { exec } from 'child_process';
6
6
  import { findWranglerConfig } from '@/lib/find-wrangler-config.js';
7
+ import logger from '@/lib/logger';
7
8
 
8
9
  const execAsync = promisify(exec);
9
10
 
@@ -75,11 +76,13 @@ async function retryWithTimeout(fn, retries = 3, timeout = 1000) {
75
76
  * It uses the Wrangler configuration (via findWranglerConfig) to determine the D1 database.
76
77
  */
77
78
  export async function GET() {
79
+ logger.logRequest('GET', '/api/tables');
80
+
78
81
  try {
79
82
  const projectDir = process.env.D1_PROJECT_DIR;
80
83
 
81
84
  if (!projectDir) {
82
- console.error('D1_PROJECT_DIR environment variable is not set');
85
+ logger.error('D1_PROJECT_DIR environment variable is not set');
83
86
  return NextResponse.json(
84
87
  { error: 'Project directory not configured' },
85
88
  { status: 500 }
@@ -89,6 +92,7 @@ export async function GET() {
89
92
  // Use the centralized helper to get Wrangler configuration
90
93
  const wranglerResult = await findWranglerConfig(projectDir);
91
94
  if (!wranglerResult || !wranglerResult.config) {
95
+ logger.error('No Wrangler configuration file found');
92
96
  return NextResponse.json(
93
97
  { error: 'No Wrangler configuration file found in project directory' },
94
98
  { status: 404 }
@@ -138,7 +142,7 @@ export async function GET() {
138
142
  });
139
143
 
140
144
  } catch (error) {
141
- console.error('Error fetching tables:', error);
145
+ logger.logError(error, 'tables-route');
142
146
 
143
147
  // Enhanced error response for troubleshooting
144
148
  const errorResponse = {
@@ -0,0 +1,36 @@
1
+ // app/api/update/route.js
2
+ import { NextResponse } from 'next/server';
3
+ import updateNotifier from 'update-notifier';
4
+ import pkg from '../../../../package.json' assert { type: 'json' };
5
+
6
+ export async function GET() {
7
+ try {
8
+ // Create notifier instance with package info
9
+ const notifier = updateNotifier({
10
+ pkg,
11
+ updateCheckInterval: 1000 * 60 * 60 * 24 // Check once per day
12
+ });
13
+
14
+ // If there's an update, notifier.update will contain the update info
15
+ if (notifier.update) {
16
+ const { latest, current } = notifier.update;
17
+
18
+ // Only return update info if versions are different
19
+ if (latest !== current) {
20
+ return NextResponse.json({
21
+ update: {
22
+ latest,
23
+ current
24
+ }
25
+ });
26
+ }
27
+ }
28
+
29
+ // No update available
30
+ return NextResponse.json({ update: null });
31
+ } catch (error) {
32
+ console.error('Error checking for updates:', error);
33
+ // Return null on error to prevent banner from showing
34
+ return NextResponse.json({ update: null });
35
+ }
36
+ }
@@ -1,10 +1,11 @@
1
1
  // app/page.js
2
2
  'use client'
3
3
 
4
+ import { useState } from 'react';
4
5
  import { AppSidebar } from '../components/sidebar';
5
6
  import { SQLEditor } from '../components/sql-editor';
6
7
  import { TableView } from '../components/table-view';
7
- import { useState } from 'react';
8
+ import UpdateBanner from '@/components/update-banner';
8
9
 
9
10
  export default function StudioPage() {
10
11
  const [currentView, setCurrentView] = useState('sql-editor');
@@ -16,19 +17,28 @@ export default function StudioPage() {
16
17
  };
17
18
 
18
19
  return (
19
- <div className="min-h-screen bg-background">
20
- <AppSidebar
21
- className="w-64 border-r"
22
- currentView={currentView}
23
- onNavigate={setCurrentView}
24
- onTableSelect={handleTableSelect}
25
- />
26
- <main className="ml-64 h-screen">
27
- {currentView === 'sql-editor' && <SQLEditor />}
28
- {currentView === 'table-view' && selectedTable && (
29
- <TableView tableName={selectedTable} />
30
- )}
31
- </main>
20
+ <div className="flex flex-col min-h-screen bg-background">
21
+ {/* Banner */}
22
+ <UpdateBanner />
23
+
24
+ {/* Main layout */}
25
+ <div className="flex flex-1">
26
+ {/* Sidebar */}
27
+ <AppSidebar
28
+ className="w-64 border-r fixed h-[calc(100vh-var(--banner-height,0px))]"
29
+ currentView={currentView}
30
+ onNavigate={setCurrentView}
31
+ onTableSelect={handleTableSelect}
32
+ />
33
+
34
+ {/* Main content */}
35
+ <main className="ml-64 flex-1 h-[calc(100vh-var(--banner-height,0px))]">
36
+ {currentView === 'sql-editor' && <SQLEditor />}
37
+ {currentView === 'table-view' && selectedTable && (
38
+ <TableView tableName={selectedTable} />
39
+ )}
40
+ </main>
41
+ </div>
32
42
  </div>
33
43
  );
34
44
  }
package/dist/app/page.jsx CHANGED
@@ -1,10 +1,11 @@
1
1
  // app/page.js
2
2
  'use client'
3
3
 
4
+ import { useState } from 'react';
4
5
  import { AppSidebar } from '../components/sidebar';
5
6
  import { SQLEditor } from '../components/sql-editor';
6
7
  import { TableView } from '../components/table-view';
7
- import { useState } from 'react';
8
+ import UpdateBanner from '@/components/update-banner';
8
9
 
9
10
  export default function StudioPage() {
10
11
  const [currentView, setCurrentView] = useState('sql-editor');
@@ -16,19 +17,28 @@ export default function StudioPage() {
16
17
  };
17
18
 
18
19
  return (
19
- <div className="min-h-screen bg-background">
20
- <AppSidebar
21
- className="w-64 border-r"
22
- currentView={currentView}
23
- onNavigate={setCurrentView}
24
- onTableSelect={handleTableSelect}
25
- />
26
- <main className="ml-64 h-screen">
27
- {currentView === 'sql-editor' && <SQLEditor />}
28
- {currentView === 'table-view' && selectedTable && (
29
- <TableView tableName={selectedTable} />
30
- )}
31
- </main>
20
+ <div className="flex flex-col min-h-screen bg-background">
21
+ {/* Banner */}
22
+ <UpdateBanner />
23
+
24
+ {/* Main layout */}
25
+ <div className="flex flex-1">
26
+ {/* Sidebar */}
27
+ <AppSidebar
28
+ className="w-64 border-r fixed h-[calc(100vh-var(--banner-height,0px))]"
29
+ currentView={currentView}
30
+ onNavigate={setCurrentView}
31
+ onTableSelect={handleTableSelect}
32
+ />
33
+
34
+ {/* Main content */}
35
+ <main className="ml-64 flex-1 h-[calc(100vh-var(--banner-height,0px))]">
36
+ {currentView === 'sql-editor' && <SQLEditor />}
37
+ {currentView === 'table-view' && selectedTable && (
38
+ <TableView tableName={selectedTable} />
39
+ )}
40
+ </main>
41
+ </div>
32
42
  </div>
33
43
  );
34
44
  }
package/dist/d1-studio.js CHANGED
@@ -12,8 +12,20 @@ import { createServer } from 'http';
12
12
  import next from 'next';
13
13
  import { findWranglerConfig } from '../src/lib/find-wrangler-config.js';
14
14
  import logger from '../src/lib/logger.js';
15
+ import updateNotifier from 'update-notifier';
16
+ import pkg from '../package.json' with { type: 'json' };
17
+
18
+ // Check for debug flag
19
+ const hasDebugFlag = process.argv.includes('--debug');
20
+ if (hasDebugFlag) {
21
+ process.env.DEBUG = 'true';
22
+ logger.debug('Debug mode enabled');
23
+ }
24
+
25
+ const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 * 24 });
26
+ notifier.notify({ defer: false });
15
27
 
16
- // Compute the absolute path of this file and its directory.
28
+ // Compute the absolute path of this file and its directory
17
29
  const __filename = fileURLToPath(import.meta.url);
18
30
  const __dirname = dirname(__filename);
19
31
 
@@ -26,6 +38,70 @@ class LicenseError extends Error {
26
38
  }
27
39
  }
28
40
 
41
+ class StudioLicenseManager {
42
+ constructor() {
43
+ this.licenseDir = join(homedir(), '.d1studio');
44
+ this.licensePath = join(this.licenseDir, 'license.json');
45
+ }
46
+
47
+ async checkLicenseFile() {
48
+ try {
49
+ const licenseData = JSON.parse(await readFile(this.licensePath, 'utf8'));
50
+
51
+ // If no end_date or subscription_status, the license is valid (perpetual license)
52
+ if (!licenseData.end_date || !licenseData.subscription_status) {
53
+ return {
54
+ licenseData,
55
+ isValid: true,
56
+ isExpiringSoon: false
57
+ };
58
+ }
59
+
60
+ // Check subscription status first
61
+ if (licenseData.subscription_status !== 'active') {
62
+ return {
63
+ licenseData,
64
+ isValid: false,
65
+ isExpiringSoon: false
66
+ };
67
+ }
68
+
69
+ const endDate = new Date(licenseData.end_date);
70
+ const now = new Date();
71
+
72
+ // Check if subscription has ended
73
+ if (endDate < now) {
74
+ return {
75
+ licenseData,
76
+ isValid: false,
77
+ isExpiringSoon: false
78
+ };
79
+ }
80
+
81
+ // Check if subscription ends in next 7 days
82
+ const sevenDaysFromNow = new Date(now.getTime() + (7 * 24 * 60 * 60 * 1000));
83
+ const isExpiringSoon = endDate <= sevenDaysFromNow;
84
+
85
+ return {
86
+ licenseData,
87
+ isValid: true,
88
+ isExpiringSoon
89
+ };
90
+ } catch (error) {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ async saveLicenseFile(licenseData) {
96
+ try {
97
+ await mkdir(this.licenseDir, { recursive: true });
98
+ await writeFile(this.licensePath, JSON.stringify(licenseData, null, 2));
99
+ } catch (error) {
100
+ throw new LicenseError('Failed to save license information', 'SAVE_ERROR');
101
+ }
102
+ }
103
+ }
104
+
29
105
  async function generateHardwareId() {
30
106
  const osInfo = {
31
107
  platform: process.platform,
@@ -60,13 +136,6 @@ async function validateLicenseRemote(licenseKey, email, hardwareId) {
60
136
  );
61
137
  }
62
138
 
63
- if (result.end_date && new Date(result.end_date) < new Date()) {
64
- throw new LicenseError(
65
- 'Your subscription has expired. Please renew your license to continue using D1 Studio.',
66
- 'SUBSCRIPTION_EXPIRED'
67
- );
68
- }
69
-
70
139
  return result;
71
140
  } catch (error) {
72
141
  if (error instanceof LicenseError) {
@@ -87,35 +156,6 @@ async function validateLicenseRemote(licenseKey, email, hardwareId) {
87
156
  }
88
157
  }
89
158
 
90
- async function checkLicenseFile() {
91
- const licenseDir = join(homedir(), '.d1studio');
92
- const licensePath = join(licenseDir, 'license.json');
93
-
94
- try {
95
- const licenseData = JSON.parse(await readFile(licensePath, 'utf8'));
96
- const hardwareId = await generateHardwareId();
97
-
98
- if (licenseData.hardwareId !== hardwareId) {
99
- return null;
100
- }
101
- return licenseData;
102
- } catch (error) {
103
- return null;
104
- }
105
- }
106
-
107
- async function saveLicenseFile(licenseData) {
108
- const licenseDir = join(homedir(), '.d1studio');
109
- const licensePath = join(licenseDir, 'license.json');
110
-
111
- try {
112
- await mkdir(licenseDir, { recursive: true });
113
- await writeFile(licensePath, JSON.stringify(licenseData, null, 2));
114
- } catch (error) {
115
- throw new LicenseError('Failed to save license information', 'SAVE_ERROR');
116
- }
117
- }
118
-
119
159
  async function startServer(port, projectDirectory) {
120
160
  return new Promise((resolvePromise, rejectPromise) => {
121
161
  // Determine Next.js app directory based on environment:
@@ -170,20 +210,14 @@ async function startStudio() {
170
210
  try {
171
211
  logger.info(chalk.green('Initializing D1 Studio...'));
172
212
 
173
- // Validate license
174
- let licenseData = await checkLicenseFile();
175
- logger.debug(chalk.blue(`License data found: ${JSON.stringify(licenseData)}`));
176
-
177
- const TWELVE_HOURS_MS = 43200000; // 12 hours
178
- let shouldRevalidate = true;
179
- if (licenseData) {
180
- const lastCheck = new Date(licenseData.lastValidatedAt || licenseData.activatedAt);
181
- if (Date.now() - lastCheck.getTime() < TWELVE_HOURS_MS) {
182
- shouldRevalidate = false;
183
- }
184
- }
213
+ const licenseManager = new StudioLicenseManager();
185
214
 
186
- if (!licenseData || shouldRevalidate) {
215
+ // Check existing license
216
+ const licenseCheck = await licenseManager.checkLicenseFile();
217
+
218
+ // Handle license validation
219
+ if (!licenseCheck || !licenseCheck.isValid) {
220
+ // Prompt for license information if needed
187
221
  const { default: inquirer } = await import('inquirer');
188
222
  logger.info(chalk.yellow('\nPlease enter your D1 Studio license information:'));
189
223
 
@@ -205,9 +239,8 @@ async function startStudio() {
205
239
  },
206
240
  ]);
207
241
 
208
- logger.debug(chalk.blue(`Entered license information: ${JSON.stringify(answers)}`));
209
-
210
242
  const hardwareId = await generateHardwareId();
243
+
211
244
  try {
212
245
  const validation = await validateLicenseRemote(
213
246
  answers.licenseKey,
@@ -215,19 +248,29 @@ async function startStudio() {
215
248
  hardwareId
216
249
  );
217
250
 
218
- licenseData = {
251
+ // Save the complete validation response
252
+ await licenseManager.saveLicenseFile({
219
253
  licenseKey: answers.licenseKey,
220
254
  email: answers.email,
221
- activatedAt: new Date().toISOString(),
222
- endDate: validation.end_date || null
223
- };
255
+ hardwareId,
256
+ end_date: validation.end_date,
257
+ subscription_status: validation.subscription_status,
258
+ type: validation.licenseType,
259
+ activatedAt: new Date().toISOString()
260
+ });
224
261
 
225
- await saveLicenseFile(licenseData);
226
262
  logger.info(chalk.green('\nLicense activated successfully!'));
227
263
  } catch (error) {
228
264
  logger.error(chalk.red(`\nLicense validation failed: ${error.message}`));
229
265
  process.exit(1);
230
266
  }
267
+ } else if (licenseCheck.isExpiringSoon) {
268
+ // Show warning about expiring subscription
269
+ const endDate = new Date(licenseCheck.licenseData.end_date).toLocaleDateString();
270
+ logger.warn(chalk.yellow(`
271
+ ⚠️ Your subscription will expire on ${endDate}
272
+ Please renew your subscription at https://d1-studio.com to continue using D1 Studio.
273
+ `));
231
274
  }
232
275
 
233
276
  // Get wrangler configuration
@@ -317,4 +360,4 @@ process.on('SIGTERM', () => {
317
360
  startStudio().catch((error) => {
318
361
  logger.error(chalk.red(`\nFailed to start D1 Studio: ${error}`));
319
362
  process.exit(1);
320
- });
363
+ });
@@ -1,33 +1,37 @@
1
1
  // utils/database-queue.js
2
+
3
+ import logger from '@/lib/logger.js';
4
+
2
5
  class DatabaseQueue {
3
- constructor() {
4
- this.queue = [];
5
- this.isProcessing = false;
6
- }
6
+ constructor() {
7
+ this.queue = [];
8
+ this.isProcessing = false;
9
+ }
10
+
11
+ async add(operation) {
12
+ return new Promise((resolve, reject) => {
13
+ this.queue.push({ operation, resolve, reject });
14
+ this.processNext();
15
+ });
16
+ }
17
+
18
+ async processNext() {
19
+ if (this.isProcessing || this.queue.length === 0) return;
20
+
21
+ this.isProcessing = true;
22
+ const { operation, resolve, reject } = this.queue.shift();
23
+
24
+ try {
25
+ const result = await operation();
26
+ resolve(result);
27
+ } catch (error) {
28
+ logger.error('Error processing database queue operation:', error);
29
+ reject(error);
30
+ } finally {
31
+ this.isProcessing = false;
32
+ this.processNext();
33
+ }
34
+ }
35
+ }
7
36
 
8
- async add(operation) {
9
- return new Promise((resolve, reject) => {
10
- this.queue.push({ operation, resolve, reject });
11
- this.processNext();
12
- });
13
- }
14
-
15
- async processNext() {
16
- if (this.isProcessing || this.queue.length === 0) return;
17
-
18
- this.isProcessing = true;
19
- const { operation, resolve, reject } = this.queue.shift();
20
-
21
- try {
22
- const result = await operation();
23
- resolve(result);
24
- } catch (error) {
25
- reject(error);
26
- } finally {
27
- this.isProcessing = false;
28
- this.processNext();
29
- }
30
- }
31
- }
32
-
33
- export const dbQueue = new DatabaseQueue();
37
+ export const dbQueue = new DatabaseQueue();
@@ -1,12 +1,15 @@
1
- // lib/find-wrangler-config.js
2
1
  import { readFile } from 'fs/promises';
3
2
  import { findUp } from 'find-up';
4
3
  import { parse as parseToml } from '@iarna/toml';
5
4
  import stripJsonComments from 'strip-json-comments';
6
5
  import logger from './logger.js';
7
6
 
7
+ let cachedConfig = null;
8
+ let cachedProjectPath = null;
9
+
8
10
  /**
9
11
  * Finds and parses the Wrangler configuration file.
12
+ * This function caches the result so that the configuration is read and logged only once per project path.
10
13
  *
11
14
  * @param {string} userProjectPath - The path where to look for the config file
12
15
  * @returns {Promise<{config: object, projectPath: string}|null>}
@@ -17,8 +20,10 @@ export async function findWranglerConfig(userProjectPath) {
17
20
  throw new Error('Project path is required and must be a string');
18
21
  }
19
22
 
20
- // Uncomment the following line to log the search path if needed:
21
- // logger.debug(`Looking for wrangler configuration in: ${userProjectPath}`);
23
+ // Return the cached config if available for the same project path.
24
+ if (cachedConfig && cachedProjectPath === userProjectPath) {
25
+ return cachedConfig;
26
+ }
22
27
 
23
28
  // Define the possible configuration file names in priority order.
24
29
  const possibleFiles = ['wrangler.toml', 'wrangler.json', 'wrangler.jsonc'];
@@ -56,13 +61,14 @@ export async function findWranglerConfig(userProjectPath) {
56
61
  config = JSON.parse(configContent);
57
62
  }
58
63
 
59
- return {
60
- config,
61
- projectPath: userProjectPath
62
- };
64
+ // Cache the result.
65
+ cachedConfig = { config, projectPath: userProjectPath };
66
+ cachedProjectPath = userProjectPath;
67
+
68
+ return cachedConfig;
63
69
 
64
70
  } catch (error) {
65
71
  logger.error(`Error reading Wrangler configuration: ${error.message}`);
66
72
  throw error;
67
73
  }
68
- }
74
+ }
@@ -2,18 +2,57 @@ import winston from 'winston';
2
2
 
3
3
  const { combine, timestamp, printf, colorize } = winston.format;
4
4
 
5
- const logFormat = printf(({ level, message, timestamp }) => {
6
- return `${timestamp} ${level}: ${message}`;
5
+ const isDevelopment = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === undefined;
6
+ const isProduction = process.env.NODE_ENV === 'production';
7
+ // Check for DEBUG env var which is set by --debug flag
8
+ const isDebug = process.env.DEBUG === 'true';
9
+
10
+ const logFormat = printf(({ level, message, timestamp, ...metadata }) => {
11
+ let msg = `${timestamp} ${level}: ${message}`;
12
+ // Add metadata if present
13
+ if (Object.keys(metadata).length > 0) {
14
+ msg += ` ${JSON.stringify(metadata)}`;
15
+ }
16
+ return msg;
7
17
  });
8
18
 
9
19
  const logger = winston.createLogger({
10
- level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
20
+ // Set log level based on environment and debug flag
21
+ level: isDebug ? 'debug' : (isProduction ? 'warn' : 'info'),
11
22
  format: combine(
12
23
  timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
13
24
  colorize(),
14
25
  logFormat
15
26
  ),
16
- transports: [new winston.transports.Console()]
27
+ transports: [
28
+ new winston.transports.Console({
29
+ level: isDebug ? 'debug' : (isProduction ? 'warn' : 'info'),
30
+ silent: process.env.NODE_ENV === 'test'
31
+ })
32
+ ]
17
33
  });
18
34
 
19
- export default logger;
35
+ // Add helper methods
36
+ logger.logRequest = (method, path, params = {}) => {
37
+ logger.debug(`Request: ${method} ${path}`, params);
38
+ };
39
+
40
+ logger.logError = (error, source = 'unknown') => {
41
+ logger.error(`Error in ${source}: ${error.message}`, {
42
+ error: error.stack || error.message,
43
+ source
44
+ });
45
+ };
46
+
47
+ logger.shouldLog = (level) => {
48
+ const currentLevel = logger.level;
49
+ const levels = {
50
+ error: 0,
51
+ warn: 1,
52
+ info: 2,
53
+ debug: 3
54
+ };
55
+ return levels[level] <= levels[currentLevel];
56
+ };
57
+
58
+ export default logger;