@kurly-growth/growthman 0.1.12 → 0.1.14

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 (287) hide show
  1. package/CLAUDE.md +58 -0
  2. package/app/globals.css +125 -0
  3. package/app/layout.tsx +36 -0
  4. package/app/page.tsx +213 -0
  5. package/bin/cli.js +41 -4
  6. package/components/api-test-dialog.tsx +222 -0
  7. package/components/endpoint-edit-dialog.tsx +181 -0
  8. package/components/endpoint-table.tsx +147 -0
  9. package/components/openapi-upload-dialog.tsx +213 -0
  10. package/components/ui/button.tsx +62 -0
  11. package/components/ui/checkbox.tsx +32 -0
  12. package/components/ui/dialog.tsx +143 -0
  13. package/components/ui/input.tsx +21 -0
  14. package/components/ui/label.tsx +24 -0
  15. package/components/ui/sonner.tsx +37 -0
  16. package/components/ui/table.tsx +116 -0
  17. package/components/ui/textarea.tsx +18 -0
  18. package/components.json +22 -0
  19. package/next-env.d.ts +6 -0
  20. package/package.json +10 -19
  21. package/pnpm-workspace.yaml +4 -0
  22. package/postcss.config.mjs +7 -0
  23. package/prisma/prisma/dev.db +0 -0
  24. package/.next/BUILD_ID +0 -1
  25. package/.next/app-path-routes-manifest.json +0 -12
  26. package/.next/build/chunks/[root-of-the-server]__51225daf._.js +0 -206
  27. package/.next/build/chunks/[root-of-the-server]__51225daf._.js.map +0 -8
  28. package/.next/build/chunks/[root-of-the-server]__974941ed._.js +0 -500
  29. package/.next/build/chunks/[root-of-the-server]__974941ed._.js.map +0 -11
  30. package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_6920245c._.js +0 -13
  31. package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_6920245c._.js.map +0 -5
  32. package/.next/build/chunks/[turbopack]_runtime.js +0 -795
  33. package/.next/build/chunks/[turbopack]_runtime.js.map +0 -10
  34. package/.next/build/chunks/node_modules_fe693df6._.js +0 -6758
  35. package/.next/build/chunks/node_modules_fe693df6._.js.map +0 -47
  36. package/.next/build/package.json +0 -1
  37. package/.next/build/postcss.js +0 -6
  38. package/.next/build/postcss.js.map +0 -5
  39. package/.next/build-manifest.json +0 -19
  40. package/.next/diagnostics/build-diagnostics.json +0 -6
  41. package/.next/diagnostics/framework.json +0 -1
  42. package/.next/export-marker.json +0 -6
  43. package/.next/fallback-build-manifest.json +0 -12
  44. package/.next/images-manifest.json +0 -66
  45. package/.next/next-minimal-server.js.nft.json +0 -1
  46. package/.next/next-server.js.nft.json +0 -1
  47. package/.next/package.json +0 -1
  48. package/.next/prerender-manifest.json +0 -114
  49. package/.next/required-server-files.js +0 -163
  50. package/.next/required-server-files.json +0 -163
  51. package/.next/routes-manifest.json +0 -109
  52. package/.next/server/app/_global-error/page/app-paths-manifest.json +0 -3
  53. package/.next/server/app/_global-error/page/build-manifest.json +0 -16
  54. package/.next/server/app/_global-error/page/next-font-manifest.json +0 -6
  55. package/.next/server/app/_global-error/page/react-loadable-manifest.json +0 -1
  56. package/.next/server/app/_global-error/page/server-reference-manifest.json +0 -4
  57. package/.next/server/app/_global-error/page.js +0 -11
  58. package/.next/server/app/_global-error/page.js.map +0 -5
  59. package/.next/server/app/_global-error/page.js.nft.json +0 -1
  60. package/.next/server/app/_global-error/page_client-reference-manifest.js +0 -2
  61. package/.next/server/app/_global-error.html +0 -2
  62. package/.next/server/app/_global-error.meta +0 -15
  63. package/.next/server/app/_global-error.rsc +0 -13
  64. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +0 -5
  65. package/.next/server/app/_global-error.segments/_full.segment.rsc +0 -13
  66. package/.next/server/app/_global-error.segments/_head.segment.rsc +0 -6
  67. package/.next/server/app/_global-error.segments/_index.segment.rsc +0 -4
  68. package/.next/server/app/_global-error.segments/_tree.segment.rsc +0 -1
  69. package/.next/server/app/_not-found/page/app-paths-manifest.json +0 -3
  70. package/.next/server/app/_not-found/page/build-manifest.json +0 -16
  71. package/.next/server/app/_not-found/page/next-font-manifest.json +0 -11
  72. package/.next/server/app/_not-found/page/react-loadable-manifest.json +0 -1
  73. package/.next/server/app/_not-found/page/server-reference-manifest.json +0 -4
  74. package/.next/server/app/_not-found/page.js +0 -14
  75. package/.next/server/app/_not-found/page.js.map +0 -5
  76. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  77. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -2
  78. package/.next/server/app/_not-found.html +0 -1
  79. package/.next/server/app/_not-found.meta +0 -16
  80. package/.next/server/app/_not-found.rsc +0 -15
  81. package/.next/server/app/_not-found.segments/_full.segment.rsc +0 -15
  82. package/.next/server/app/_not-found.segments/_head.segment.rsc +0 -6
  83. package/.next/server/app/_not-found.segments/_index.segment.rsc +0 -6
  84. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +0 -5
  85. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +0 -4
  86. package/.next/server/app/_not-found.segments/_tree.segment.rsc +0 -2
  87. package/.next/server/app/api/endpoints/[id]/route/app-paths-manifest.json +0 -3
  88. package/.next/server/app/api/endpoints/[id]/route/build-manifest.json +0 -11
  89. package/.next/server/app/api/endpoints/[id]/route/server-reference-manifest.json +0 -4
  90. package/.next/server/app/api/endpoints/[id]/route.js +0 -7
  91. package/.next/server/app/api/endpoints/[id]/route.js.map +0 -5
  92. package/.next/server/app/api/endpoints/[id]/route.js.nft.json +0 -1
  93. package/.next/server/app/api/endpoints/[id]/route_client-reference-manifest.js +0 -2
  94. package/.next/server/app/api/endpoints/bulk/route/app-paths-manifest.json +0 -3
  95. package/.next/server/app/api/endpoints/bulk/route/build-manifest.json +0 -11
  96. package/.next/server/app/api/endpoints/bulk/route/server-reference-manifest.json +0 -4
  97. package/.next/server/app/api/endpoints/bulk/route.js +0 -7
  98. package/.next/server/app/api/endpoints/bulk/route.js.map +0 -5
  99. package/.next/server/app/api/endpoints/bulk/route.js.nft.json +0 -1
  100. package/.next/server/app/api/endpoints/bulk/route_client-reference-manifest.js +0 -2
  101. package/.next/server/app/api/endpoints/import/route/app-paths-manifest.json +0 -3
  102. package/.next/server/app/api/endpoints/import/route/build-manifest.json +0 -11
  103. package/.next/server/app/api/endpoints/import/route/server-reference-manifest.json +0 -4
  104. package/.next/server/app/api/endpoints/import/route.js +0 -7
  105. package/.next/server/app/api/endpoints/import/route.js.map +0 -5
  106. package/.next/server/app/api/endpoints/import/route.js.nft.json +0 -1
  107. package/.next/server/app/api/endpoints/import/route_client-reference-manifest.js +0 -2
  108. package/.next/server/app/api/endpoints/route/app-paths-manifest.json +0 -3
  109. package/.next/server/app/api/endpoints/route/build-manifest.json +0 -11
  110. package/.next/server/app/api/endpoints/route/server-reference-manifest.json +0 -4
  111. package/.next/server/app/api/endpoints/route.js +0 -7
  112. package/.next/server/app/api/endpoints/route.js.map +0 -5
  113. package/.next/server/app/api/endpoints/route.js.nft.json +0 -1
  114. package/.next/server/app/api/endpoints/route_client-reference-manifest.js +0 -2
  115. package/.next/server/app/api/endpoints/sync/route/app-paths-manifest.json +0 -3
  116. package/.next/server/app/api/endpoints/sync/route/build-manifest.json +0 -11
  117. package/.next/server/app/api/endpoints/sync/route/server-reference-manifest.json +0 -4
  118. package/.next/server/app/api/endpoints/sync/route.js +0 -7
  119. package/.next/server/app/api/endpoints/sync/route.js.map +0 -5
  120. package/.next/server/app/api/endpoints/sync/route.js.nft.json +0 -1
  121. package/.next/server/app/api/endpoints/sync/route_client-reference-manifest.js +0 -2
  122. package/.next/server/app/api/mock/[...slug]/route/app-paths-manifest.json +0 -3
  123. package/.next/server/app/api/mock/[...slug]/route/build-manifest.json +0 -11
  124. package/.next/server/app/api/mock/[...slug]/route/server-reference-manifest.json +0 -4
  125. package/.next/server/app/api/mock/[...slug]/route.js +0 -8
  126. package/.next/server/app/api/mock/[...slug]/route.js.map +0 -5
  127. package/.next/server/app/api/mock/[...slug]/route.js.nft.json +0 -1
  128. package/.next/server/app/api/mock/[...slug]/route_client-reference-manifest.js +0 -2
  129. package/.next/server/app/favicon.ico/route/app-paths-manifest.json +0 -3
  130. package/.next/server/app/favicon.ico/route/build-manifest.json +0 -11
  131. package/.next/server/app/favicon.ico/route.js +0 -7
  132. package/.next/server/app/favicon.ico/route.js.map +0 -5
  133. package/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  134. package/.next/server/app/favicon.ico.meta +0 -1
  135. package/.next/server/app/index.html +0 -1
  136. package/.next/server/app/index.meta +0 -14
  137. package/.next/server/app/index.rsc +0 -21
  138. package/.next/server/app/index.segments/__PAGE__.segment.rsc +0 -9
  139. package/.next/server/app/index.segments/_full.segment.rsc +0 -21
  140. package/.next/server/app/index.segments/_head.segment.rsc +0 -6
  141. package/.next/server/app/index.segments/_index.segment.rsc +0 -6
  142. package/.next/server/app/index.segments/_tree.segment.rsc +0 -4
  143. package/.next/server/app/page/app-paths-manifest.json +0 -3
  144. package/.next/server/app/page/build-manifest.json +0 -16
  145. package/.next/server/app/page/next-font-manifest.json +0 -11
  146. package/.next/server/app/page/react-loadable-manifest.json +0 -8
  147. package/.next/server/app/page/server-reference-manifest.json +0 -4
  148. package/.next/server/app/page.js +0 -16
  149. package/.next/server/app/page.js.map +0 -5
  150. package/.next/server/app/page.js.nft.json +0 -1
  151. package/.next/server/app/page_client-reference-manifest.js +0 -2
  152. package/.next/server/app-paths-manifest.json +0 -12
  153. package/.next/server/chunks/1629d_next_dist_esm_build_templates_app-route_498527d5.js +0 -3
  154. package/.next/server/chunks/1629d_next_dist_esm_build_templates_app-route_498527d5.js.map +0 -1
  155. package/.next/server/chunks/[externals]__cf2ccb51._.js +0 -3
  156. package/.next/server/chunks/[externals]__cf2ccb51._.js.map +0 -1
  157. package/.next/server/chunks/[externals]_next_dist_8dbe5856._.js +0 -3
  158. package/.next/server/chunks/[externals]_next_dist_8dbe5856._.js.map +0 -1
  159. package/.next/server/chunks/[root-of-the-server]__3534fecc._.js +0 -3
  160. package/.next/server/chunks/[root-of-the-server]__3534fecc._.js.map +0 -1
  161. package/.next/server/chunks/[root-of-the-server]__461ea613._.js +0 -21
  162. package/.next/server/chunks/[root-of-the-server]__461ea613._.js.map +0 -1
  163. package/.next/server/chunks/[root-of-the-server]__4929acb0._.js +0 -129
  164. package/.next/server/chunks/[root-of-the-server]__4929acb0._.js.map +0 -1
  165. package/.next/server/chunks/[root-of-the-server]__909218aa._.js +0 -3
  166. package/.next/server/chunks/[root-of-the-server]__909218aa._.js.map +0 -1
  167. package/.next/server/chunks/[root-of-the-server]__a6c01a13._.js +0 -3
  168. package/.next/server/chunks/[root-of-the-server]__a6c01a13._.js.map +0 -1
  169. package/.next/server/chunks/[root-of-the-server]__db1127cf._.js +0 -3
  170. package/.next/server/chunks/[root-of-the-server]__db1127cf._.js.map +0 -1
  171. package/.next/server/chunks/[root-of-the-server]__e46f3e25._.js +0 -3
  172. package/.next/server/chunks/[root-of-the-server]__e46f3e25._.js.map +0 -1
  173. package/.next/server/chunks/[turbopack]_runtime.js +0 -795
  174. package/.next/server/chunks/[turbopack]_runtime.js.map +0 -10
  175. package/.next/server/chunks/_next-internal_server_app_api_endpoints_[id]_route_actions_b91cfc4c.js +0 -3
  176. package/.next/server/chunks/_next-internal_server_app_api_endpoints_[id]_route_actions_b91cfc4c.js.map +0 -1
  177. package/.next/server/chunks/_next-internal_server_app_api_endpoints_bulk_route_actions_560cc6cd.js +0 -3
  178. package/.next/server/chunks/_next-internal_server_app_api_endpoints_bulk_route_actions_560cc6cd.js.map +0 -1
  179. package/.next/server/chunks/_next-internal_server_app_api_endpoints_import_route_actions_f2444950.js +0 -3
  180. package/.next/server/chunks/_next-internal_server_app_api_endpoints_import_route_actions_f2444950.js.map +0 -1
  181. package/.next/server/chunks/_next-internal_server_app_api_endpoints_route_actions_49d8ad56.js +0 -3
  182. package/.next/server/chunks/_next-internal_server_app_api_endpoints_route_actions_49d8ad56.js.map +0 -1
  183. package/.next/server/chunks/_next-internal_server_app_api_endpoints_sync_route_actions_0f446550.js +0 -3
  184. package/.next/server/chunks/_next-internal_server_app_api_endpoints_sync_route_actions_0f446550.js.map +0 -1
  185. package/.next/server/chunks/_next-internal_server_app_api_mock_[___slug]_route_actions_be875f77.js +0 -3
  186. package/.next/server/chunks/_next-internal_server_app_api_mock_[___slug]_route_actions_be875f77.js.map +0 -1
  187. package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_353150a5.js +0 -3
  188. package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_353150a5.js.map +0 -1
  189. package/.next/server/chunks/node_modules__pnpm_a61fb769._.js +0 -3
  190. package/.next/server/chunks/node_modules__pnpm_a61fb769._.js.map +0 -1
  191. package/.next/server/chunks/ssr/1629d_next_dist_1a21bde7._.js +0 -6
  192. package/.next/server/chunks/ssr/1629d_next_dist_1a21bde7._.js.map +0 -1
  193. package/.next/server/chunks/ssr/1629d_next_dist_8dc31fba._.js +0 -3
  194. package/.next/server/chunks/ssr/1629d_next_dist_8dc31fba._.js.map +0 -1
  195. package/.next/server/chunks/ssr/1629d_next_dist_client_components_b01b33e4._.js +0 -3
  196. package/.next/server/chunks/ssr/1629d_next_dist_client_components_b01b33e4._.js.map +0 -1
  197. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_forbidden_4cab2078.js +0 -3
  198. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_forbidden_4cab2078.js.map +0 -1
  199. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_global-error_0d5cb623.js +0 -3
  200. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_global-error_0d5cb623.js.map +0 -1
  201. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_unauthorized_b8fbdcad.js +0 -3
  202. package/.next/server/chunks/ssr/1629d_next_dist_client_components_builtin_unauthorized_b8fbdcad.js.map +0 -1
  203. package/.next/server/chunks/ssr/1629d_next_dist_d78dee57._.js +0 -4
  204. package/.next/server/chunks/ssr/1629d_next_dist_d78dee57._.js.map +0 -1
  205. package/.next/server/chunks/ssr/1629d_next_dist_esm_build_templates_app-page_d4e9464b.js +0 -4
  206. package/.next/server/chunks/ssr/1629d_next_dist_esm_build_templates_app-page_d4e9464b.js.map +0 -1
  207. package/.next/server/chunks/ssr/67049_lucide-react_dist_esm_createLucideIcon_22fe2e14.js +0 -3
  208. package/.next/server/chunks/ssr/67049_lucide-react_dist_esm_createLucideIcon_22fe2e14.js.map +0 -1
  209. package/.next/server/chunks/ssr/[externals]_next_dist_server_app-render_work-async-storage_external_1f8eeae7.js +0 -3
  210. package/.next/server/chunks/ssr/[externals]_next_dist_server_app-render_work-async-storage_external_1f8eeae7.js.map +0 -1
  211. package/.next/server/chunks/ssr/[root-of-the-server]__14f4396a._.js +0 -10
  212. package/.next/server/chunks/ssr/[root-of-the-server]__14f4396a._.js.map +0 -1
  213. package/.next/server/chunks/ssr/[root-of-the-server]__3064bf15._.js +0 -3
  214. package/.next/server/chunks/ssr/[root-of-the-server]__3064bf15._.js.map +0 -1
  215. package/.next/server/chunks/ssr/[root-of-the-server]__4ff41ba3._.js +0 -4
  216. package/.next/server/chunks/ssr/[root-of-the-server]__4ff41ba3._.js.map +0 -1
  217. package/.next/server/chunks/ssr/[root-of-the-server]__57c5da8e._.js +0 -3
  218. package/.next/server/chunks/ssr/[root-of-the-server]__57c5da8e._.js.map +0 -1
  219. package/.next/server/chunks/ssr/[root-of-the-server]__67653b38._.js +0 -3
  220. package/.next/server/chunks/ssr/[root-of-the-server]__67653b38._.js.map +0 -1
  221. package/.next/server/chunks/ssr/[root-of-the-server]__7d48410d._.js +0 -3
  222. package/.next/server/chunks/ssr/[root-of-the-server]__7d48410d._.js.map +0 -1
  223. package/.next/server/chunks/ssr/[root-of-the-server]__a49eaf36._.js +0 -3
  224. package/.next/server/chunks/ssr/[root-of-the-server]__a49eaf36._.js.map +0 -1
  225. package/.next/server/chunks/ssr/[root-of-the-server]__b0617f51._.js +0 -3
  226. package/.next/server/chunks/ssr/[root-of-the-server]__b0617f51._.js.map +0 -1
  227. package/.next/server/chunks/ssr/[root-of-the-server]__cc026bde._.js +0 -3
  228. package/.next/server/chunks/ssr/[root-of-the-server]__cc026bde._.js.map +0 -1
  229. package/.next/server/chunks/ssr/[root-of-the-server]__d079898e._.js +0 -3
  230. package/.next/server/chunks/ssr/[root-of-the-server]__d079898e._.js.map +0 -1
  231. package/.next/server/chunks/ssr/[root-of-the-server]__d3649e47._.js +0 -3
  232. package/.next/server/chunks/ssr/[root-of-the-server]__d3649e47._.js.map +0 -1
  233. package/.next/server/chunks/ssr/[turbopack]_runtime.js +0 -795
  234. package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +0 -10
  235. package/.next/server/chunks/ssr/_9b6e3dc4._.js +0 -3
  236. package/.next/server/chunks/ssr/_9b6e3dc4._.js.map +0 -1
  237. package/.next/server/chunks/ssr/_a437ac52._.js +0 -7
  238. package/.next/server/chunks/ssr/_a437ac52._.js.map +0 -1
  239. package/.next/server/chunks/ssr/_b62b070d._.js +0 -4
  240. package/.next/server/chunks/ssr/_b62b070d._.js.map +0 -1
  241. package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_75761787.js +0 -3
  242. package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_75761787.js.map +0 -1
  243. package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_554ec2bf.js +0 -3
  244. package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_554ec2bf.js.map +0 -1
  245. package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_39d4fc33.js +0 -3
  246. package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_39d4fc33.js.map +0 -1
  247. package/.next/server/chunks/ssr/app_b9b1292a._.js +0 -3
  248. package/.next/server/chunks/ssr/app_b9b1292a._.js.map +0 -1
  249. package/.next/server/functions-config-manifest.json +0 -4
  250. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  251. package/.next/server/middleware-build-manifest.js +0 -20
  252. package/.next/server/middleware-manifest.json +0 -6
  253. package/.next/server/next-font-manifest.js +0 -1
  254. package/.next/server/next-font-manifest.json +0 -15
  255. package/.next/server/pages/404.html +0 -1
  256. package/.next/server/pages/500.html +0 -2
  257. package/.next/server/pages-manifest.json +0 -4
  258. package/.next/server/server-reference-manifest.js +0 -1
  259. package/.next/server/server-reference-manifest.json +0 -5
  260. package/.next/static/chunks/16403d658c649f0f.js +0 -1
  261. package/.next/static/chunks/2422cfacfdb28c2c.js +0 -5
  262. package/.next/static/chunks/42572c067be8ea0f.js +0 -1
  263. package/.next/static/chunks/5045da71379799ce.js +0 -1
  264. package/.next/static/chunks/6e04dfc4035d7150.js +0 -5
  265. package/.next/static/chunks/8155485116e3ff24.js +0 -1
  266. package/.next/static/chunks/a66e09a7c2336f67.js +0 -1
  267. package/.next/static/chunks/a6dad97d9634a72d.js +0 -1
  268. package/.next/static/chunks/a6dad97d9634a72d.js.map +0 -1
  269. package/.next/static/chunks/da3f3e4f37f68cee.css +0 -3
  270. package/.next/static/chunks/f1cfb69226717279.js +0 -1
  271. package/.next/static/chunks/turbopack-7027959231bb432a.js +0 -4
  272. package/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  273. package/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  274. package/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  275. package/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  276. package/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  277. package/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  278. package/.next/static/media/favicon.de6b30f1.ico +0 -0
  279. package/.next/static/tHhig3FrI32oLhNopN5Nj/_buildManifest.js +0 -11
  280. package/.next/static/tHhig3FrI32oLhNopN5Nj/_clientMiddlewareManifest.json +0 -1
  281. package/.next/static/tHhig3FrI32oLhNopN5Nj/_ssgManifest.js +0 -1
  282. package/.next/trace +0 -1
  283. package/.next/trace-build +0 -1
  284. package/.next/turbopack +0 -0
  285. package/.next/types/routes.d.ts +0 -78
  286. package/.next/types/validator.ts +0 -124
  287. /package/{.next/server/app/favicon.ico.body → app/favicon.ico} +0 -0
@@ -0,0 +1,222 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import dynamic from 'next/dynamic'
5
+ import { MockEndpoint } from '@/types/endpoint'
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ } from '@/components/ui/dialog'
12
+ import { Button } from '@/components/ui/button'
13
+ import { Input } from '@/components/ui/input'
14
+ import { Label } from '@/components/ui/label'
15
+
16
+ const MonacoEditor = dynamic(() => import('@monaco-editor/react'), {
17
+ ssr: false,
18
+ loading: () => <div className="h-[300px] bg-gray-100 animate-pulse rounded" />,
19
+ })
20
+
21
+ interface ApiTestDialogProps {
22
+ endpoint: MockEndpoint | null
23
+ open: boolean
24
+ onOpenChange: (open: boolean) => void
25
+ }
26
+
27
+ const methodColors: Record<string, string> = {
28
+ GET: 'bg-green-100 text-green-800',
29
+ POST: 'bg-blue-100 text-blue-800',
30
+ PUT: 'bg-yellow-100 text-yellow-800',
31
+ PATCH: 'bg-orange-100 text-orange-800',
32
+ DELETE: 'bg-red-100 text-red-800',
33
+ }
34
+
35
+ export function ApiTestDialog({
36
+ endpoint,
37
+ open,
38
+ onOpenChange,
39
+ }: ApiTestDialogProps) {
40
+ const [loading, setLoading] = useState(false)
41
+ const [response, setResponse] = useState<{
42
+ status: number
43
+ statusText: string
44
+ body: string
45
+ time: number
46
+ } | null>(null)
47
+ const [error, setError] = useState<string | null>(null)
48
+ const [pathParams, setPathParams] = useState<Record<string, string>>({})
49
+
50
+ const baseUrl = typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'
51
+
52
+ // Extract path parameters like :id, :userId from path
53
+ const extractPathParams = (path: string): string[] => {
54
+ const matches = path.match(/:(\w+)/g)
55
+ return matches ? matches.map((m) => m.slice(1)) : []
56
+ }
57
+
58
+ const paramNames = endpoint ? extractPathParams(endpoint.path) : []
59
+
60
+ // Build the actual URL with path parameters replaced
61
+ const buildUrl = (): string => {
62
+ if (!endpoint) return ''
63
+ let path = endpoint.path
64
+ for (const [key, value] of Object.entries(pathParams)) {
65
+ path = path.replace(`:${key}`, value || `:${key}`)
66
+ }
67
+ return `${baseUrl}/api/mock${path}`
68
+ }
69
+
70
+ const handleSend = async () => {
71
+ if (!endpoint) return
72
+
73
+ setLoading(true)
74
+ setError(null)
75
+ setResponse(null)
76
+
77
+ const startTime = performance.now()
78
+
79
+ try {
80
+ const res = await fetch(buildUrl(), {
81
+ method: endpoint.method,
82
+ })
83
+
84
+ const endTime = performance.now()
85
+ const body = await res.text()
86
+
87
+ let formattedBody = body
88
+ try {
89
+ formattedBody = JSON.stringify(JSON.parse(body), null, 2)
90
+ } catch {
91
+ // Not JSON, use as-is
92
+ }
93
+
94
+ setResponse({
95
+ status: res.status,
96
+ statusText: res.statusText,
97
+ body: formattedBody,
98
+ time: Math.round(endTime - startTime),
99
+ })
100
+ } catch (err) {
101
+ setError(err instanceof Error ? err.message : 'Request failed')
102
+ } finally {
103
+ setLoading(false)
104
+ }
105
+ }
106
+
107
+ const handleOpenChange = (isOpen: boolean) => {
108
+ if (!isOpen) {
109
+ setResponse(null)
110
+ setError(null)
111
+ setPathParams({})
112
+ }
113
+ onOpenChange(isOpen)
114
+ }
115
+
116
+ const getStatusColor = (status: number) => {
117
+ if (status >= 200 && status < 300) return 'text-green-600'
118
+ if (status >= 400 && status < 500) return 'text-yellow-600'
119
+ if (status >= 500) return 'text-red-600'
120
+ return 'text-gray-600'
121
+ }
122
+
123
+ if (!endpoint) return null
124
+
125
+ return (
126
+ <Dialog open={open} onOpenChange={handleOpenChange}>
127
+ <DialogContent className="sm:max-w-[700px] max-h-[90vh] flex flex-col">
128
+ <DialogHeader>
129
+ <DialogTitle className="flex items-center gap-3">
130
+ <span
131
+ className={`px-2 py-1 rounded text-xs font-medium ${methodColors[endpoint.method] || 'bg-gray-100'}`}
132
+ >
133
+ {endpoint.method}
134
+ </span>
135
+ <span>Test API</span>
136
+ </DialogTitle>
137
+ </DialogHeader>
138
+
139
+ <div className="flex flex-col gap-4 flex-1 overflow-hidden">
140
+ {/* URL Display */}
141
+ <div className="flex items-center gap-2">
142
+ <Input
143
+ readOnly
144
+ value={buildUrl()}
145
+ className="flex-1 font-mono text-sm bg-gray-50"
146
+ />
147
+ <Button onClick={handleSend} disabled={loading}>
148
+ {loading ? 'Sending...' : 'Send'}
149
+ </Button>
150
+ </div>
151
+
152
+ {/* Path Parameters */}
153
+ {paramNames.length > 0 && (
154
+ <div className="space-y-2 p-3 bg-gray-50 rounded-lg">
155
+ <Label className="text-sm font-medium">Path Parameters</Label>
156
+ <div className="grid gap-2">
157
+ {paramNames.map((param) => (
158
+ <div key={param} className="flex items-center gap-2">
159
+ <Label className="w-24 text-sm text-gray-600">:{param}</Label>
160
+ <Input
161
+ placeholder={`Enter ${param}`}
162
+ value={pathParams[param] || ''}
163
+ onChange={(e) =>
164
+ setPathParams((prev) => ({
165
+ ...prev,
166
+ [param]: e.target.value,
167
+ }))
168
+ }
169
+ className="flex-1"
170
+ />
171
+ </div>
172
+ ))}
173
+ </div>
174
+ </div>
175
+ )}
176
+
177
+ {/* Error Display */}
178
+ {error && (
179
+ <div className="p-3 bg-red-50 border border-red-200 rounded-lg">
180
+ <p className="text-red-600 text-sm">{error}</p>
181
+ </div>
182
+ )}
183
+
184
+ {/* Response Display */}
185
+ {response && (
186
+ <div className="flex-1 flex flex-col overflow-hidden">
187
+ <div className="flex items-center gap-4 mb-2">
188
+ <span className="text-sm font-medium">Response</span>
189
+ <span className={`text-sm font-medium ${getStatusColor(response.status)}`}>
190
+ {response.status} {response.statusText}
191
+ </span>
192
+ <span className="text-sm text-gray-500">{response.time}ms</span>
193
+ </div>
194
+ <div className="border rounded-md overflow-hidden flex-1">
195
+ <MonacoEditor
196
+ height="300px"
197
+ language="json"
198
+ theme="vs-dark"
199
+ value={response.body}
200
+ options={{
201
+ readOnly: true,
202
+ minimap: { enabled: false },
203
+ fontSize: 13,
204
+ scrollBeyondLastLine: false,
205
+ automaticLayout: true,
206
+ }}
207
+ />
208
+ </div>
209
+ </div>
210
+ )}
211
+
212
+ {/* Initial State */}
213
+ {!response && !error && !loading && (
214
+ <div className="flex-1 flex items-center justify-center text-gray-400 border-2 border-dashed rounded-lg">
215
+ Click Send to test the API
216
+ </div>
217
+ )}
218
+ </div>
219
+ </DialogContent>
220
+ </Dialog>
221
+ )
222
+ }
@@ -0,0 +1,181 @@
1
+ 'use client'
2
+
3
+ import { useState, useEffect } from 'react'
4
+ import dynamic from 'next/dynamic'
5
+ import { MockEndpoint } from '@/types/endpoint'
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogHeader,
10
+ DialogTitle,
11
+ DialogFooter,
12
+ } from '@/components/ui/dialog'
13
+ import { Button } from '@/components/ui/button'
14
+ import { Input } from '@/components/ui/input'
15
+ import { Label } from '@/components/ui/label'
16
+
17
+ const MonacoEditor = dynamic(() => import('@monaco-editor/react'), {
18
+ ssr: false,
19
+ loading: () => <div className="h-[400px] bg-gray-100 animate-pulse rounded" />,
20
+ })
21
+
22
+ interface EndpointEditDialogProps {
23
+ endpoint: MockEndpoint | null
24
+ open: boolean
25
+ onOpenChange: (open: boolean) => void
26
+ onSave: (endpoint: Partial<MockEndpoint> & { id?: string }) => void
27
+ }
28
+
29
+ const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
30
+
31
+ export function EndpointEditDialog({
32
+ endpoint,
33
+ open,
34
+ onOpenChange,
35
+ onSave,
36
+ }: EndpointEditDialogProps) {
37
+ const [path, setPath] = useState('')
38
+ const [method, setMethod] = useState('GET')
39
+ const [description, setDescription] = useState('')
40
+ const [statusCode, setStatusCode] = useState(200)
41
+ const [responseBody, setResponseBody] = useState('{}')
42
+ const [jsonError, setJsonError] = useState<string | null>(null)
43
+
44
+ useEffect(() => {
45
+ if (endpoint) {
46
+ setPath(endpoint.path)
47
+ setMethod(endpoint.method)
48
+ setDescription(endpoint.description || '')
49
+ setStatusCode(endpoint.statusCode)
50
+ setResponseBody(JSON.stringify(endpoint.responseBody, null, 2))
51
+ } else {
52
+ setPath('')
53
+ setMethod('GET')
54
+ setDescription('')
55
+ setStatusCode(200)
56
+ setResponseBody('{}')
57
+ }
58
+ setJsonError(null)
59
+ }, [endpoint, open])
60
+
61
+ const handleSave = () => {
62
+ try {
63
+ const parsedBody = JSON.parse(responseBody)
64
+ setJsonError(null)
65
+ onSave({
66
+ id: endpoint?.id,
67
+ path,
68
+ method,
69
+ description: description || null,
70
+ statusCode,
71
+ responseBody: parsedBody,
72
+ })
73
+ onOpenChange(false)
74
+ } catch {
75
+ setJsonError('Invalid JSON format')
76
+ }
77
+ }
78
+
79
+ return (
80
+ <Dialog open={open} onOpenChange={onOpenChange}>
81
+ <DialogContent className="sm:max-w-[70vw] h-[90vh] flex flex-col">
82
+ <DialogHeader>
83
+ <DialogTitle>
84
+ {endpoint ? 'Edit Endpoint' : 'Create New Endpoint'}
85
+ </DialogTitle>
86
+ </DialogHeader>
87
+
88
+ <div className="grid gap-4 py-4 flex-1 overflow-hidden">
89
+ <div className="flex items-center gap-4">
90
+ <Label htmlFor="method" className="w-28 text-right shrink-0">
91
+ Method
92
+ </Label>
93
+ <select
94
+ id="method"
95
+ value={method}
96
+ onChange={(e) => setMethod(e.target.value)}
97
+ className="flex-1 h-10 rounded-md border border-input bg-background px-3 py-2"
98
+ >
99
+ {HTTP_METHODS.map((m) => (
100
+ <option key={m} value={m}>
101
+ {m}
102
+ </option>
103
+ ))}
104
+ </select>
105
+ </div>
106
+
107
+ <div className="flex items-center gap-4">
108
+ <Label htmlFor="path" className="w-28 text-right shrink-0">
109
+ Path
110
+ </Label>
111
+ <Input
112
+ id="path"
113
+ value={path}
114
+ onChange={(e) => setPath(e.target.value)}
115
+ placeholder="/v1/users/:userId"
116
+ className="flex-1"
117
+ />
118
+ </div>
119
+
120
+ <div className="flex items-center gap-4">
121
+ <Label htmlFor="description" className="w-28 text-right shrink-0">
122
+ Description
123
+ </Label>
124
+ <Input
125
+ id="description"
126
+ value={description}
127
+ onChange={(e) => setDescription(e.target.value)}
128
+ placeholder="API description"
129
+ className="flex-1"
130
+ />
131
+ </div>
132
+
133
+ <div className="flex items-center gap-4">
134
+ <Label htmlFor="statusCode" className="w-28 text-right shrink-0">
135
+ Status Code
136
+ </Label>
137
+ <Input
138
+ id="statusCode"
139
+ type="number"
140
+ value={statusCode}
141
+ onChange={(e) => setStatusCode(Number(e.target.value))}
142
+ className="flex-1"
143
+ />
144
+ </div>
145
+
146
+ <div className="flex items-start gap-4">
147
+ <Label className="w-28 text-right shrink-0 pt-2">Response Body</Label>
148
+ <div className="flex-1">
149
+ <div className="border rounded-md overflow-hidden">
150
+ <MonacoEditor
151
+ height="calc(85vh - 320px)"
152
+ language="json"
153
+ theme="vs-dark"
154
+ value={responseBody}
155
+ onChange={(value) => setResponseBody(value || '{}')}
156
+ options={{
157
+ minimap: { enabled: false },
158
+ fontSize: 14,
159
+ formatOnPaste: true,
160
+ automaticLayout: true,
161
+ scrollBeyondLastLine: false,
162
+ }}
163
+ />
164
+ </div>
165
+ {jsonError && (
166
+ <p className="text-red-500 text-sm mt-2">{jsonError}</p>
167
+ )}
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <DialogFooter className="shrink-0">
173
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
174
+ Cancel
175
+ </Button>
176
+ <Button onClick={handleSave}>Save</Button>
177
+ </DialogFooter>
178
+ </DialogContent>
179
+ </Dialog>
180
+ )
181
+ }
@@ -0,0 +1,147 @@
1
+ 'use client'
2
+
3
+ import { MockEndpoint } from '@/types/endpoint'
4
+ import {
5
+ Table,
6
+ TableBody,
7
+ TableCell,
8
+ TableHead,
9
+ TableHeader,
10
+ TableRow,
11
+ } from '@/components/ui/table'
12
+ import { Button } from '@/components/ui/button'
13
+ import { Checkbox } from '@/components/ui/checkbox'
14
+
15
+ interface EndpointTableProps {
16
+ endpoints: MockEndpoint[]
17
+ onEdit: (endpoint: MockEndpoint) => void
18
+ onDelete: (id: string) => void
19
+ onTest: (endpoint: MockEndpoint) => void
20
+ selectedIds: Set<string>
21
+ onSelectionChange: (ids: Set<string>) => void
22
+ lastModifiedId?: string | null
23
+ }
24
+
25
+ const methodColors: Record<string, string> = {
26
+ GET: 'bg-green-100 text-green-800',
27
+ POST: 'bg-blue-100 text-blue-800',
28
+ PUT: 'bg-yellow-100 text-yellow-800',
29
+ PATCH: 'bg-orange-100 text-orange-800',
30
+ DELETE: 'bg-red-100 text-red-800',
31
+ }
32
+
33
+ export function EndpointTable({
34
+ endpoints,
35
+ onEdit,
36
+ onDelete,
37
+ onTest,
38
+ selectedIds,
39
+ onSelectionChange,
40
+ lastModifiedId,
41
+ }: EndpointTableProps) {
42
+ const allSelected = endpoints.length > 0 && endpoints.every((e) => selectedIds.has(e.id))
43
+ const someSelected = endpoints.some((e) => selectedIds.has(e.id)) && !allSelected
44
+
45
+ const handleSelectAll = (checked: boolean) => {
46
+ if (checked) {
47
+ onSelectionChange(new Set(endpoints.map((e) => e.id)))
48
+ } else {
49
+ onSelectionChange(new Set())
50
+ }
51
+ }
52
+
53
+ const handleSelectOne = (id: string, checked: boolean) => {
54
+ const newSet = new Set(selectedIds)
55
+ if (checked) {
56
+ newSet.add(id)
57
+ } else {
58
+ newSet.delete(id)
59
+ }
60
+ onSelectionChange(newSet)
61
+ }
62
+
63
+ return (
64
+ <Table>
65
+ <TableHeader>
66
+ <TableRow>
67
+ <TableHead className="w-[50px]">
68
+ <Checkbox
69
+ checked={allSelected}
70
+ ref={(el) => {
71
+ if (el) {
72
+ (el as unknown as HTMLInputElement).indeterminate = someSelected
73
+ }
74
+ }}
75
+ onCheckedChange={(checked) => handleSelectAll(checked === true)}
76
+ aria-label="Select all"
77
+ />
78
+ </TableHead>
79
+ <TableHead className="w-[100px]">Method</TableHead>
80
+ <TableHead>Path</TableHead>
81
+ <TableHead>Description</TableHead>
82
+ <TableHead className="w-[200px]">Actions</TableHead>
83
+ </TableRow>
84
+ </TableHeader>
85
+ <TableBody>
86
+ {endpoints.length === 0 ? (
87
+ <TableRow>
88
+ <TableCell colSpan={5} className="text-center text-gray-500">
89
+ No endpoints registered yet
90
+ </TableCell>
91
+ </TableRow>
92
+ ) : (
93
+ endpoints.map((endpoint) => (
94
+ <TableRow
95
+ key={endpoint.id}
96
+ className={lastModifiedId === endpoint.id ? 'bg-yellow-50' : ''}
97
+ >
98
+ <TableCell>
99
+ <Checkbox
100
+ checked={selectedIds.has(endpoint.id)}
101
+ onCheckedChange={(checked) => handleSelectOne(endpoint.id, checked === true)}
102
+ aria-label={`Select ${endpoint.path}`}
103
+ />
104
+ </TableCell>
105
+ <TableCell>
106
+ <span
107
+ className={`px-2 py-1 rounded text-xs font-medium ${methodColors[endpoint.method] || 'bg-gray-100'}`}
108
+ >
109
+ {endpoint.method}
110
+ </span>
111
+ </TableCell>
112
+ <TableCell className="font-mono text-sm">{endpoint.path}</TableCell>
113
+ <TableCell className="text-gray-600">
114
+ {endpoint.description || '-'}
115
+ </TableCell>
116
+ <TableCell>
117
+ <div className="flex gap-2">
118
+ <Button
119
+ variant="secondary"
120
+ size="sm"
121
+ onClick={() => onTest(endpoint)}
122
+ >
123
+ Test
124
+ </Button>
125
+ <Button
126
+ variant="outline"
127
+ size="sm"
128
+ onClick={() => onEdit(endpoint)}
129
+ >
130
+ Edit
131
+ </Button>
132
+ <Button
133
+ variant="destructive"
134
+ size="sm"
135
+ onClick={() => onDelete(endpoint.id)}
136
+ >
137
+ Delete
138
+ </Button>
139
+ </div>
140
+ </TableCell>
141
+ </TableRow>
142
+ ))
143
+ )}
144
+ </TableBody>
145
+ </Table>
146
+ )
147
+ }