@kurly-growth/growthman 0.1.2 → 0.1.5
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.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +6 -6
- package/.next/fallback-build-manifest.json +2 -2
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/server/app/_global-error/page/build-manifest.json +4 -4
- package/.next/server/app/_global-error/page.js +8 -8
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +2 -2
- package/.next/server/app/_global-error.rsc +8 -8
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_full.segment.rsc +8 -8
- package/.next/server/app/_global-error.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page/build-manifest.json +4 -4
- package/.next/server/app/_not-found/page.js +10 -10
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +10 -10
- package/.next/server/app/_not-found.segments/_full.segment.rsc +10 -10
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +5 -5
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/endpoints/[id]/route.js +5 -4
- package/.next/server/app/api/endpoints/[id]/route.js.nft.json +1 -1
- package/.next/server/app/api/endpoints/bulk/route.js +5 -4
- package/.next/server/app/api/endpoints/bulk/route.js.nft.json +1 -1
- package/.next/server/app/api/endpoints/import/route.js +5 -4
- package/.next/server/app/api/endpoints/import/route.js.nft.json +1 -1
- package/.next/server/app/api/endpoints/route.js +5 -4
- package/.next/server/app/api/endpoints/route.js.nft.json +1 -1
- package/.next/server/app/api/endpoints/sync/route.js +5 -4
- package/.next/server/app/api/endpoints/sync/route.js.nft.json +1 -1
- package/.next/server/app/api/mock/[...slug]/route.js +6 -5
- package/.next/server/app/api/mock/[...slug]/route.js.nft.json +1 -1
- package/.next/server/app/favicon.ico/route.js +4 -4
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +12 -12
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +12 -12
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +5 -5
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/page/build-manifest.json +4 -4
- package/.next/server/app/page/react-loadable-manifest.json +3 -3
- package/.next/server/app/page.js +12 -12
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/chunks/8e02f__pnpm_34c6253f._.js +3 -0
- package/.next/server/chunks/8e02f__pnpm_34c6253f._.js.map +1 -0
- package/.next/server/chunks/{8e02f_next_dist_esm_build_templates_app-route_2d5d7dcf.js → 9ca2c_next_dist_esm_build_templates_app-route_84087e8c.js} +2 -2
- package/.next/server/chunks/9ca2c_next_dist_esm_build_templates_app-route_84087e8c.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__094b2f2b._.js → [externals]__cf2ccb51._.js} +2 -2
- package/.next/server/chunks/[externals]__cf2ccb51._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__41261df4._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__41261df4._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__76e3e5c5._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__76e3e5c5._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__9f34b8fa._.js +129 -0
- package/.next/server/chunks/[root-of-the-server]__9f34b8fa._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__a757185b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__a757185b._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__e59e1188._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__e59e1188._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__e9fe7c9a._.js +21 -0
- package/.next/server/chunks/[root-of-the-server]__e9fe7c9a._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__eff896e6._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__eff896e6._.js.map +1 -0
- package/.next/server/chunks/ssr/{Desktop_Project_Web_growth-mock-server_4d3bfee7._.js → 9ca2c_next_dist_3cd898b4._.js} +3 -3
- package/.next/server/chunks/ssr/9ca2c_next_dist_3cd898b4._.js.map +1 -0
- package/.next/server/chunks/ssr/{8e02f_next_dist_client_components_builtin_forbidden_8e6242aa.js → 9ca2c_next_dist_client_components_builtin_forbidden_f49335c3.js} +2 -2
- package/.next/server/chunks/ssr/9ca2c_next_dist_client_components_builtin_forbidden_f49335c3.js.map +1 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_client_components_builtin_global-error_f88aa19b.js +3 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_client_components_builtin_global-error_f88aa19b.js.map +1 -0
- package/.next/server/chunks/ssr/{8e02f_next_dist_client_components_builtin_unauthorized_d6f465ad.js → 9ca2c_next_dist_client_components_builtin_unauthorized_e72efa43.js} +2 -2
- package/.next/server/chunks/ssr/9ca2c_next_dist_client_components_builtin_unauthorized_e72efa43.js.map +1 -0
- package/.next/server/chunks/ssr/{8e02f_next_dist_client_components_b780ac2a._.js → 9ca2c_next_dist_client_components_fcf027b5._.js} +2 -2
- package/.next/server/chunks/ssr/9ca2c_next_dist_client_components_fcf027b5._.js.map +1 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_d1e0d146._.js +3 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_d1e0d146._.js.map +1 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_dedb0e75._.js +6 -0
- package/.next/server/chunks/ssr/9ca2c_next_dist_dedb0e75._.js.map +1 -0
- package/.next/server/chunks/ssr/{8e02f_next_dist_a79dfbb1._.js → 9ca2c_next_dist_esm_build_templates_app-page_535865d4.js} +3 -3
- package/.next/server/chunks/ssr/9ca2c_next_dist_esm_build_templates_app-page_535865d4.js.map +1 -0
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_99247fbd._.js +3 -0
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_99247fbd._.js.map +1 -0
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_c7522028._.js +7 -0
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_c7522028._.js.map +1 -0
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_d48712e4._.js +4 -0
- package/.next/server/chunks/ssr/{8e02f_next_dist_a79dfbb1._.js.map → Desktop_Project_Web_growth-mock-server_d48712e4._.js.map} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__caa92361._.js → [root-of-the-server]__17853f53._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__18a26c10._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__18a26c10._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__c9e25af2._.js → [root-of-the-server]__307548a6._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__307548a6._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4390a85d._.js +10 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4390a85d._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__0715ef20._.js → [root-of-the-server]__6a5dc11f._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__6a5dc11f._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__e5032d8c._.js → [root-of-the-server]__92f5730f._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__92f5730f._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__c6e8de01._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__d2eb7012._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__d2eb7012._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__88eba3a3._.js → [root-of-the-server]__e3541a66._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__e3541a66._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__6f5c427b._.js → [root-of-the-server]__e5e3a413._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__e5e3a413._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__fb4cb1db._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__fb4cb1db._.js.map +1 -0
- package/.next/server/chunks/ssr/b9a5c_lucide-react_dist_esm_createLucideIcon_3a4054f7.js +3 -0
- package/.next/server/chunks/ssr/b9a5c_lucide-react_dist_esm_createLucideIcon_3a4054f7.js.map +1 -0
- package/.next/server/middleware-build-manifest.js +4 -4
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +2 -2
- package/.next/static/chunks/010e555b4a1dcd52.js +5 -0
- package/.next/static/chunks/0275b0ee12e7ce52.js +1 -0
- package/.next/static/chunks/33ea23f1243e96f0.js +1 -0
- package/.next/static/chunks/525197a7544b0e96.js +1 -0
- package/.next/static/chunks/560974ba92e6363e.js +5 -0
- package/.next/static/chunks/{31523f3a41fdf0b5.js → 6b128c466fac1211.js} +1 -1
- package/.next/static/chunks/8d6c35afc42e5d8e.js +1 -0
- package/.next/static/chunks/9fff2b37cf885aa6.js +1 -0
- package/.next/static/chunks/a6dad97d9634a72d.js.map +1 -1
- package/.next/static/chunks/bb9110e6d0dd8068.css +3 -0
- package/.next/static/chunks/{turbopack-7ea3b444f61e390f.js → turbopack-68dbd89b378e971c.js} +2 -2
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/.next/types/validator.ts +124 -0
- package/README.md +32 -1
- package/package.json +13 -2
- package/prisma/schema.prisma +1 -0
- package/.claude/settings.local.json +0 -10
- package/.next/server/chunks/8e02f_529f6098._.js +0 -3
- package/.next/server/chunks/8e02f_529f6098._.js.map +0 -1
- package/.next/server/chunks/8e02f_next_dist_esm_build_templates_app-route_2d5d7dcf.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__094b2f2b._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__0ecd8530._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__0ecd8530._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__5b9c1ed8._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__5b9c1ed8._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__5d7c02da._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__5d7c02da._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__88f1e82c._.js +0 -21
- package/.next/server/chunks/[root-of-the-server]__88f1e82c._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__a413808a._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__a413808a._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__fbfc7922._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__fbfc7922._.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_lucide-react_dist_esm_createLucideIcon_92babc87.js +0 -3
- package/.next/server/chunks/ssr/8e02f_lucide-react_dist_esm_createLucideIcon_92babc87.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_5f7af8e7._.js +0 -3
- package/.next/server/chunks/ssr/8e02f_next_dist_5f7af8e7._.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_8b7d79d3._.js +0 -6
- package/.next/server/chunks/ssr/8e02f_next_dist_8b7d79d3._.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_client_components_b780ac2a._.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_client_components_builtin_forbidden_8e6242aa.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_client_components_builtin_global-error_fef7daa4.js +0 -3
- package/.next/server/chunks/ssr/8e02f_next_dist_client_components_builtin_global-error_fef7daa4.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_client_components_builtin_unauthorized_d6f465ad.js.map +0 -1
- package/.next/server/chunks/ssr/8e02f_next_dist_esm_build_templates_app-page_aefc7b05.js +0 -4
- package/.next/server/chunks/ssr/8e02f_next_dist_esm_build_templates_app-page_aefc7b05.js.map +0 -1
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_192f26a7._.js +0 -3
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_192f26a7._.js.map +0 -1
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_4d3bfee7._.js.map +0 -1
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_e3bf5efe._.js +0 -7
- package/.next/server/chunks/ssr/Desktop_Project_Web_growth-mock-server_e3bf5efe._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0715ef20._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0c263e23._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0c263e23._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__2cf79de7._.js +0 -10
- package/.next/server/chunks/ssr/[root-of-the-server]__2cf79de7._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__5d3307e0._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__5d3307e0._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__6f5c427b._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__7f083271._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__7f083271._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__88eba3a3._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__c9e25af2._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__e5032d8c._.js.map +0 -1
- package/.next/static/chunks/3a3338ff069e0977.js +0 -5
- package/.next/static/chunks/68c20af4dfeb36d0.js +0 -1
- package/.next/static/chunks/77942ffae83b12ce.js +0 -1
- package/.next/static/chunks/81faf4667437d774.js +0 -1
- package/.next/static/chunks/8c554104dfee37e0.js +0 -5
- package/.next/static/chunks/ab3bc4985a0e98d2.css +0 -3
- package/.next/static/chunks/d71bf6d63636cd19.js +0 -1
- package/.next/static/chunks/f32c6649a0ca2698.js +0 -1
- package/CLAUDE.md +0 -58
- package/app/favicon.ico +0 -0
- package/app/globals.css +0 -125
- package/app/layout.tsx +0 -36
- package/app/page.tsx +0 -184
- package/components/endpoint-edit-dialog.tsx +0 -181
- package/components/endpoint-table.tsx +0 -133
- package/components/openapi-upload-dialog.tsx +0 -196
- package/components/ui/button.tsx +0 -62
- package/components/ui/checkbox.tsx +0 -32
- package/components/ui/dialog.tsx +0 -143
- package/components/ui/input.tsx +0 -21
- package/components/ui/label.tsx +0 -24
- package/components/ui/sonner.tsx +0 -37
- package/components/ui/table.tsx +0 -116
- package/components/ui/textarea.tsx +0 -18
- package/components.json +0 -22
- package/next-env.d.ts +0 -6
- package/pnpm-workspace.yaml +0 -4
- package/postcss.config.mjs +0 -7
- /package/.next/server/chunks/ssr/{[root-of-the-server]__caa92361._.js.map → [root-of-the-server]__17853f53._.js.map} +0 -0
- /package/.next/static/{xP3uHv1GK0YyrTIpyEo8D → ywToWYz8OMPylsW9u-DSJ}/_buildManifest.js +0 -0
- /package/.next/static/{xP3uHv1GK0YyrTIpyEo8D → ywToWYz8OMPylsW9u-DSJ}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{xP3uHv1GK0YyrTIpyEo8D → ywToWYz8OMPylsW9u-DSJ}/_ssgManifest.js +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,57534,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"warnOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},34893,(e,t,r)=>{"use strict";function n(e,t={}){if(t.onlyHashChange)return void e();let r=document.documentElement;if("smooth"!==r.dataset.scrollBehavior)return void e();let a=r.style.scrollBehavior;r.style.scrollBehavior="auto",t.dontForceLayout||r.getClientRects(),e(),r.style.scrollBehavior=a}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"disableSmoothScrollDuringRouteTransition",{enumerable:!0,get:function(){return n}}),e.r(57534)},80778,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"HTTPAccessFallbackBoundary",{enumerable:!0,get:function(){return l}});let n=e.r(13549),a=e.r(53500),o=n._(e.r(42043)),i=e.r(95276),s=e.r(71255);e.r(57534);let c=e.r(77713);class u extends o.default.Component{constructor(e){super(e),this.state={triggeredStatus:void 0,previousPathname:e.pathname}}componentDidCatch(){}static getDerivedStateFromError(e){if((0,s.isHTTPAccessFallbackError)(e))return{triggeredStatus:(0,s.getAccessFallbackHTTPStatus)(e)};throw e}static getDerivedStateFromProps(e,t){return e.pathname!==t.previousPathname&&t.triggeredStatus?{triggeredStatus:void 0,previousPathname:e.pathname}:{triggeredStatus:t.triggeredStatus,previousPathname:e.pathname}}render(){let{notFound:e,forbidden:t,unauthorized:r,children:n}=this.props,{triggeredStatus:o}=this.state,i={[s.HTTPAccessErrorStatus.NOT_FOUND]:e,[s.HTTPAccessErrorStatus.FORBIDDEN]:t,[s.HTTPAccessErrorStatus.UNAUTHORIZED]:r};if(o){let c=o===s.HTTPAccessErrorStatus.NOT_FOUND&&e,u=o===s.HTTPAccessErrorStatus.FORBIDDEN&&t,l=o===s.HTTPAccessErrorStatus.UNAUTHORIZED&&r;return c||u||l?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("meta",{name:"robots",content:"noindex"}),!1,i[o]]}):n}return n}}function l({notFound:e,forbidden:t,unauthorized:r,children:n}){let s=(0,i.useUntrackedPathname)(),l=(0,o.useContext)(c.MissingSlotContext);return e||t||r?(0,a.jsx)(u,{pathname:s,notFound:e,forbidden:t,unauthorized:r,missingSlots:l,children:n}):(0,a.jsx)(a.Fragment,{children:n})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},4427,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useRouterBFCache",{enumerable:!0,get:function(){return a}});let n=e.r(42043);function a(e,t){let[r,a]=(0,n.useState)(()=>({tree:e,stateKey:t,next:null}));if(r.tree===e)return r;let o={tree:e,stateKey:t,next:null},i=1,s=r,c=o;for(;null!==s&&i<1;){if(s.stateKey===t){c.next=s.next;break}{i++;let e={tree:s.tree,stateKey:s.stateKey,next:null};c.next=e,c=e}s=s.next}return a(o),o}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},68402,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"default",{enumerable:!0,get:function(){return w}});let n=e.r(17274),a=e.r(13549),o=e.r(53500),i=a._(e.r(42043)),s=n._(e.r(60710)),c=e.r(77713),u=e.r(52511),l=e.r(78731),d=e.r(1241),f=e.r(34893),p=e.r(43656),h=e.r(80778),m=e.r(67949),g=e.r(4427);e.r(31803);let y=e.r(80780),b=e.r(95907),P=e.r(31048),_=s.default.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,S=["bottom","height","left","right","top","width","x","y"];function v(e,t){let r=e.getBoundingClientRect();return r.top>=0&&r.top<=t}class O extends i.default.Component{componentDidMount(){this.handlePotentialScroll()}componentDidUpdate(){this.props.focusAndScrollRef.apply&&this.handlePotentialScroll()}render(){return this.props.children}constructor(...e){super(...e),this.handlePotentialScroll=()=>{let{focusAndScrollRef:e,segmentPath:t}=this.props;if(e.apply){if(0!==e.segmentPaths.length&&!e.segmentPaths.some(e=>t.every((t,r)=>(0,d.matchSegment)(t,e[r]))))return;let r=null,n=e.hashFragment;if(n&&(r="top"===n?document.body:document.getElementById(n)??document.getElementsByName(n)[0]),r||(r="undefined"==typeof window?null:(0,_.findDOMNode)(this)),!(r instanceof Element))return;for(;!(r instanceof HTMLElement)||function(e){if(["sticky","fixed"].includes(getComputedStyle(e).position))return!0;let t=e.getBoundingClientRect();return S.every(e=>0===t[e])}(r);){if(null===r.nextElementSibling)return;r=r.nextElementSibling}e.apply=!1,e.hashFragment=null,e.segmentPaths=[],(0,f.disableSmoothScrollDuringRouteTransition)(()=>{if(n)return void r.scrollIntoView();let e=document.documentElement,t=e.clientHeight;!v(r,t)&&(e.scrollTop=0,v(r,t)||r.scrollIntoView())},{dontForceLayout:!0,onlyHashChange:e.onlyHashChange}),e.onlyHashChange=!1,r.focus()}}}}function R({segmentPath:e,children:t}){let r=(0,i.useContext)(c.GlobalLayoutRouterContext);if(!r)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});return(0,o.jsx)(O,{segmentPath:e,focusAndScrollRef:r.focusAndScrollRef,children:t})}function E({tree:e,segmentPath:t,debugNameContext:r,cacheNode:n,params:a,url:s,isActive:l}){let d,f=(0,i.useContext)(c.GlobalLayoutRouterContext);if((0,i.useContext)(y.NavigationPromisesContext),!f)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});let p=null!==n?n:(0,i.use)(u.unresolvedThenable),h=null!==p.prefetchRsc?p.prefetchRsc:p.rsc,m=(0,i.useDeferredValue)(p.rsc,h);if((0,P.isDeferredRsc)(m)){let e=(0,i.use)(m);null===e&&(0,i.use)(u.unresolvedThenable),d=e}else null===m&&(0,i.use)(u.unresolvedThenable),d=m;let g=d;return(0,o.jsx)(c.LayoutRouterContext.Provider,{value:{parentTree:e,parentCacheNode:p,parentSegmentPath:t,parentParams:a,debugNameContext:r,url:s,isActive:l},children:g})}function j({name:e,loading:t,children:r}){let n;if(n="object"==typeof t&&null!==t&&"function"==typeof t.then?(0,i.use)(t):t){let t=n[0],a=n[1],s=n[2];return(0,o.jsx)(i.Suspense,{name:e,fallback:(0,o.jsxs)(o.Fragment,{children:[a,s,t]}),children:r})}return(0,o.jsx)(o.Fragment,{children:r})}function w({parallelRouterKey:e,error:t,errorStyles:r,errorScripts:n,templateStyles:a,templateScripts:s,template:d,notFound:f,forbidden:y,unauthorized:P,segmentViewBoundaries:_}){let S=(0,i.useContext)(c.LayoutRouterContext);if(!S)throw Object.defineProperty(Error("invariant expected layout router to be mounted"),"__NEXT_ERROR_CODE",{value:"E56",enumerable:!1,configurable:!0});let{parentTree:v,parentCacheNode:O,parentSegmentPath:w,parentParams:C,url:T,isActive:x,debugNameContext:A}=S,M=O.parallelRoutes,D=M.get(e);D||(D=new Map,M.set(e,D));let F=v[0],I=null===w?[e]:w.concat([F,e]),k=v[1][e];void 0===k&&(0,i.use)(u.unresolvedThenable);let N=k[0],U=(0,m.createRouterCacheKey)(N,!0),B=(0,g.useRouterBFCache)(k,U),L=[];do{let e=B.tree,i=B.stateKey,u=e[0],g=(0,m.createRouterCacheKey)(u),_=D.get(g)??null,S=C;if(Array.isArray(u)){let e=u[0],t=u[1],r=u[2],n=(0,b.getParamValueFromCacheKey)(t,r);null!==n&&(S={...C,[e]:n})}let v=function(e){if("/"===e)return"/";if("string"==typeof e)if("(slot)"===e)return;else return e+"/";return e[1]+"/"}(u),w=v??A,M=void 0===v?void 0:A,F=O.loading,k=(0,o.jsxs)(c.TemplateContext.Provider,{value:(0,o.jsxs)(R,{segmentPath:I,children:[(0,o.jsx)(l.ErrorBoundary,{errorComponent:t,errorStyles:r,errorScripts:n,children:(0,o.jsx)(j,{name:M,loading:F,children:(0,o.jsx)(h.HTTPAccessFallbackBoundary,{notFound:f,forbidden:y,unauthorized:P,children:(0,o.jsxs)(p.RedirectBoundary,{children:[(0,o.jsx)(E,{url:T,tree:e,params:S,cacheNode:_,segmentPath:I,debugNameContext:w,isActive:x&&i===U}),null]})})})}),null]}),children:[a,s,d]},i);L.push(k),B=B.next}while(null!==B)return L}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},1359,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"default",{enumerable:!0,get:function(){return s}});let n=e.r(13549),a=e.r(53500),o=n._(e.r(42043)),i=e.r(77713);function s(){let e=(0,o.useContext)(i.TemplateContext);return(0,a.jsx)(a.Fragment,{children:e})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},36505,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return a}});let n=new WeakMap;function a(e){let t=n.get(e);if(t)return t;let r=Promise.resolve(e);return n.set(e,r),r}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},33727,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(36505).createRenderSearchParamsFromClient;("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},97911,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderParamsFromClient",{enumerable:!0,get:function(){return a}});let n=new WeakMap;function a(e){let t=n.get(e);if(t)return t;let r=Promise.resolve(e);return n.set(e,r),r}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},77577,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRenderParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(97911).createRenderParamsFromClient;("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},60982,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ReflectAdapter",{enumerable:!0,get:function(){return n}});class n{static get(e,t,r){let n=Reflect.get(e,t,r);return"function"==typeof n?n.bind(e):n}static set(e,t,r,n){return Reflect.set(e,t,r,n)}static has(e,t){return Reflect.has(e,t)}static deleteProperty(e,t){return Reflect.deleteProperty(e,t)}}},85480,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createDedupedByCallsiteServerErrorLoggerDev",{enumerable:!0,get:function(){return c}});let n=function(e,t){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var r=a(void 0);if(r&&r.has(e))return r.get(e);var n={__proto__:null},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var s=o?Object.getOwnPropertyDescriptor(e,i):null;s&&(s.get||s.set)?Object.defineProperty(n,i,s):n[i]=e[i]}return n.default=e,r&&r.set(e,n),n}(e.r(42043));function a(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,r=new WeakMap;return(a=function(e){return e?r:t})(e)}let o={current:null},i="function"==typeof n.cache?n.cache:e=>e,s=console.warn;function c(e){return function(...t){s(e(...t))}}i(e=>{try{s(o.current)}finally{o.current=null}})},90127,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={describeHasCheckingStringProperty:function(){return s},describeStringPropertyAccess:function(){return i},wellKnownProperties:function(){return c}};for(var a in n)Object.defineProperty(r,a,{enumerable:!0,get:n[a]});let o=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function i(e,t){return o.test(t)?`\`${e}.${t}\``:`\`${e}[${JSON.stringify(t)}]\``}function s(e,t){let r=JSON.stringify(t);return`\`Reflect.has(${e}, ${r})\`, \`${r} in ${e}\`, or similar`}let c=new Set(["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","valueOf","toLocaleString","then","catch","finally","status","displayName","_debugInfo","toJSON","$$typeof","__esModule"])},21059,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"afterTaskAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(38981).createAsyncLocalStorage)()},56279,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"afterTaskAsyncStorage",{enumerable:!0,get:function(){return n.afterTaskAsyncStorageInstance}});let n=e.r(21059)},29592,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={isRequestAPICallableInsideAfter:function(){return u},throwForSearchParamsAccessInUseCache:function(){return c},throwWithStaticGenerationBailoutErrorWithDynamicError:function(){return s}};for(var a in n)Object.defineProperty(r,a,{enumerable:!0,get:n[a]});let o=e.r(26619),i=e.r(56279);function s(e,t){throw Object.defineProperty(new o.StaticGenBailoutError(`Route ${e} with \`dynamic = "error"\` couldn't be rendered statically because it used ${t}. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`),"__NEXT_ERROR_CODE",{value:"E543",enumerable:!1,configurable:!0})}function c(e,t){let r=Object.defineProperty(Error(`Route ${e.route} used \`searchParams\` inside "use cache". Accessing dynamic request data inside a cache scope is not supported. If you need some search params inside a cached function await \`searchParams\` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`),"__NEXT_ERROR_CODE",{value:"E842",enumerable:!1,configurable:!0});throw Error.captureStackTrace(r,t),e.invalidDynamicUsageError??=r,r}function u(){let e=i.afterTaskAsyncStorage.getStore();return(null==e?void 0:e.rootTaskSpawnPhase)==="action"}},81523,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n,a={RenderStage:function(){return c},StagedRenderingController:function(){return u}};for(var o in a)Object.defineProperty(r,o,{enumerable:!0,get:a[o]});let i=e.r(87721),s=e.r(53404);var c=((n={})[n.Before=1]="Before",n[n.Static=2]="Static",n[n.Runtime=3]="Runtime",n[n.Dynamic=4]="Dynamic",n[n.Abandoned=5]="Abandoned",n);class u{constructor(e=null,t){this.abortSignal=e,this.hasRuntimePrefetch=t,this.currentStage=1,this.staticInterruptReason=null,this.runtimeInterruptReason=null,this.staticStageEndTime=1/0,this.runtimeStageEndTime=1/0,this.runtimeStageListeners=[],this.dynamicStageListeners=[],this.runtimeStagePromise=(0,s.createPromiseWithResolvers)(),this.dynamicStagePromise=(0,s.createPromiseWithResolvers)(),this.mayAbandon=!1,e&&(e.addEventListener("abort",()=>{let{reason:t}=e;this.currentStage<3&&(this.runtimeStagePromise.promise.catch(l),this.runtimeStagePromise.reject(t)),(this.currentStage<4||5===this.currentStage)&&(this.dynamicStagePromise.promise.catch(l),this.dynamicStagePromise.reject(t))},{once:!0}),this.mayAbandon=!0)}onStage(e,t){if(this.currentStage>=e)t();else if(3===e)this.runtimeStageListeners.push(t);else if(4===e)this.dynamicStageListeners.push(t);else throw Object.defineProperty(new i.InvariantError(`Invalid render stage: ${e}`),"__NEXT_ERROR_CODE",{value:"E881",enumerable:!1,configurable:!0})}canSyncInterrupt(){if(1===this.currentStage)return!1;let e=this.hasRuntimePrefetch?4:3;return this.currentStage<e}syncInterruptCurrentStageWithReason(e){if(1!==this.currentStage){if(this.mayAbandon)return this.abandonRenderImpl();switch(this.currentStage){case 2:this.staticInterruptReason=e,this.advanceStage(4);return;case 3:this.hasRuntimePrefetch&&(this.runtimeInterruptReason=e,this.advanceStage(4));return}}}getStaticInterruptReason(){return this.staticInterruptReason}getRuntimeInterruptReason(){return this.runtimeInterruptReason}getStaticStageEndTime(){return this.staticStageEndTime}getRuntimeStageEndTime(){return this.runtimeStageEndTime}abandonRender(){if(!this.mayAbandon)throw Object.defineProperty(new i.InvariantError("`abandonRender` called on a stage controller that cannot be abandoned."),"__NEXT_ERROR_CODE",{value:"E938",enumerable:!1,configurable:!0});this.abandonRenderImpl()}abandonRenderImpl(){let{currentStage:e}=this;switch(e){case 2:this.currentStage=5,this.resolveRuntimeStage();return;case 3:this.currentStage=5;return}}advanceStage(e){if(e<=this.currentStage)return;let t=this.currentStage;if(this.currentStage=e,t<3&&e>=3&&(this.staticStageEndTime=performance.now()+performance.timeOrigin,this.resolveRuntimeStage()),t<4&&e>=4){this.runtimeStageEndTime=performance.now()+performance.timeOrigin,this.resolveDynamicStage();return}}resolveRuntimeStage(){let e=this.runtimeStageListeners;for(let t=0;t<e.length;t++)e[t]();e.length=0,this.runtimeStagePromise.resolve()}resolveDynamicStage(){let e=this.dynamicStageListeners;for(let t=0;t<e.length;t++)e[t]();e.length=0,this.dynamicStagePromise.resolve()}getStagePromise(e){switch(e){case 3:return this.runtimeStagePromise.promise;case 4:return this.dynamicStagePromise.promise;default:throw Object.defineProperty(new i.InvariantError(`Invalid render stage: ${e}`),"__NEXT_ERROR_CODE",{value:"E881",enumerable:!1,configurable:!0})}}waitForStage(e){return this.getStagePromise(e)}delayUntilStage(e,t,r){var n,a,o;let i,s=(n=this.getStagePromise(e),a=t,o=r,i=new Promise((e,t)=>{n.then(e.bind(null,o),t)}),void 0!==a&&(i.displayName=a),i);return this.abortSignal&&s.catch(l),s}}function l(){}},55882,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={createPrerenderSearchParamsForClientPage:function(){return g},createSearchParamsFromClient:function(){return p},createServerSearchParamsForMetadata:function(){return h},createServerSearchParamsForServerPage:function(){return m},makeErroringSearchParamsForUseCache:function(){return S}};for(var a in n)Object.defineProperty(r,a,{enumerable:!0,get:n[a]});let o=e.r(60982),i=e.r(47990),s=e.r(70979),c=e.r(87721),u=e.r(56890),l=e.r(85480),d=e.r(90127),f=e.r(29592);function p(e,t){let r=s.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return y(t,r);case"prerender-runtime":throw Object.defineProperty(new c.InvariantError("createSearchParamsFromClient should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E769",enumerable:!1,configurable:!0});case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new c.InvariantError("createSearchParamsFromClient should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E739",enumerable:!1,configurable:!0});case"request":return b(e,t,r)}(0,s.throwInvariantForMissingStore)()}e.r(81523);let h=m;function m(e,t){let r=s.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return y(t,r);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new c.InvariantError("createServerSearchParamsForServerPage should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E747",enumerable:!1,configurable:!0});case"prerender-runtime":var n,a;return n=e,a=r,(0,i.delayUntilRuntimeStage)(a,v(n));case"request":return b(e,t,r)}(0,s.throwInvariantForMissingStore)()}function g(e){if(e.forceStatic)return Promise.resolve({});let t=s.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":return(0,u.makeHangingPromise)(t.renderSignal,e.route,"`searchParams`");case"prerender-runtime":throw Object.defineProperty(new c.InvariantError("createPrerenderSearchParamsForClientPage should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E768",enumerable:!1,configurable:!0});case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new c.InvariantError("createPrerenderSearchParamsForClientPage should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E746",enumerable:!1,configurable:!0});case"prerender-ppr":case"prerender-legacy":case"request":return Promise.resolve({})}(0,s.throwInvariantForMissingStore)()}function y(e,t){if(e.forceStatic)return Promise.resolve({});switch(t.type){case"prerender":case"prerender-client":var r=e,n=t;let a=P.get(n);if(a)return a;let s=(0,u.makeHangingPromise)(n.renderSignal,r.route,"`searchParams`"),c=new Proxy(s,{get(e,t,r){if(Object.hasOwn(s,t))return o.ReflectAdapter.get(e,t,r);switch(t){case"then":return(0,i.annotateDynamicAccess)("`await searchParams`, `searchParams.then`, or similar",n),o.ReflectAdapter.get(e,t,r);case"status":return(0,i.annotateDynamicAccess)("`use(searchParams)`, `searchParams.status`, or similar",n),o.ReflectAdapter.get(e,t,r);default:return o.ReflectAdapter.get(e,t,r)}}});return P.set(n,c),c;case"prerender-ppr":case"prerender-legacy":var l=e,d=t;let p=P.get(l);if(p)return p;let h=Promise.resolve({}),m=new Proxy(h,{get(e,t,r){if(Object.hasOwn(h,t))return o.ReflectAdapter.get(e,t,r);if("string"==typeof t&&"then"===t){let e="`await searchParams`, `searchParams.then`, or similar";l.dynamicShouldError?(0,f.throwWithStaticGenerationBailoutErrorWithDynamicError)(l.route,e):"prerender-ppr"===d.type?(0,i.postponeWithTracking)(l.route,e,d.dynamicTracking):(0,i.throwToInterruptStaticGeneration)(e,l,d)}return o.ReflectAdapter.get(e,t,r)}});return P.set(l,m),m;default:return t}}function b(e,t,r){return t.forceStatic?Promise.resolve({}):v(e)}let P=new WeakMap,_=new WeakMap;function S(e){let t=_.get(e);if(t)return t;let r=Promise.resolve({}),n=new Proxy(r,{get:function t(n,a,i){return Object.hasOwn(r,a)||"string"!=typeof a||"then"!==a&&d.wellKnownProperties.has(a)||(0,f.throwForSearchParamsAccessInUseCache)(e,t),o.ReflectAdapter.get(n,a,i)}});return _.set(e,n),n}function v(e){let t=P.get(e);if(t)return t;let r=Promise.resolve(e);return P.set(e,r),r}(0,l.createDedupedByCallsiteServerErrorLoggerDev)(function(e,t){let r=e?`Route "${e}" `:"This route ";return Object.defineProperty(Error(`${r}used ${t}. \`searchParams\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`),"__NEXT_ERROR_CODE",{value:"E848",enumerable:!1,configurable:!0})})},13650,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"dynamicAccessAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(38981).createAsyncLocalStorage)()},1929,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"dynamicAccessAsyncStorage",{enumerable:!0,get:function(){return n.dynamicAccessAsyncStorageInstance}});let n=e.r(13650)},70198,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={createParamsFromClient:function(){return h},createPrerenderParamsForClientSegment:function(){return b},createServerParamsForMetadata:function(){return m},createServerParamsForRoute:function(){return g},createServerParamsForServerSegment:function(){return y}};for(var a in n)Object.defineProperty(r,a,{enumerable:!0,get:n[a]});let o=e.r(38908),i=e.r(60982),s=e.r(47990),c=e.r(70979),u=e.r(87721),l=e.r(90127),d=e.r(56890),f=e.r(85480),p=e.r(1929);function h(e,t){let r=c.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,t,r);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new u.InvariantError("createParamsFromClient should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E736",enumerable:!1,configurable:!0});case"prerender-runtime":throw Object.defineProperty(new u.InvariantError("createParamsFromClient should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E770",enumerable:!1,configurable:!0});case"request":return O(e)}(0,c.throwInvariantForMissingStore)()}e.r(81523);let m=y;function g(e,t){let r=c.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,t,r);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new u.InvariantError("createServerParamsForRoute should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E738",enumerable:!1,configurable:!0});case"prerender-runtime":return _(e,r);case"request":return O(e)}(0,c.throwInvariantForMissingStore)()}function y(e,t){let r=c.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,t,r);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new u.InvariantError("createServerParamsForServerSegment should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E743",enumerable:!1,configurable:!0});case"prerender-runtime":return _(e,r);case"request":return O(e)}(0,c.throwInvariantForMissingStore)()}function b(e){let t=o.workAsyncStorage.getStore();if(!t)throw Object.defineProperty(new u.InvariantError("Missing workStore in createPrerenderParamsForClientSegment"),"__NEXT_ERROR_CODE",{value:"E773",enumerable:!1,configurable:!0});let r=c.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":let n=r.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return(0,d.makeHangingPromise)(r.renderSignal,t.route,"`params`")}break;case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new u.InvariantError("createPrerenderParamsForClientSegment should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E734",enumerable:!1,configurable:!0})}return Promise.resolve(e)}function P(e,t,r){switch(r.type){case"prerender":case"prerender-client":{let n=r.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return function(e,t,r){let n=S.get(e);if(n)return n;let a=new Proxy((0,d.makeHangingPromise)(r.renderSignal,t.route,"`params`"),v);return S.set(e,a),a}(e,t,r)}break}case"prerender-ppr":{let n=r.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return function(e,t,r,n){let a=S.get(e);if(a)return a;let o={...e},i=Promise.resolve(o);return S.set(e,i),Object.keys(e).forEach(e=>{l.wellKnownProperties.has(e)||t.has(e)&&Object.defineProperty(o,e,{get(){let t=(0,l.describeStringPropertyAccess)("params",e);"prerender-ppr"===n.type?(0,s.postponeWithTracking)(r.route,t,n.dynamicTracking):(0,s.throwToInterruptStaticGeneration)(t,r,n)},enumerable:!0})}),i}(e,n,t,r)}}}return O(e)}function _(e,t){return(0,s.delayUntilRuntimeStage)(t,O(e))}let S=new WeakMap,v={get:function(e,t,r){if("then"===t||"catch"===t||"finally"===t){let n=i.ReflectAdapter.get(e,t,r);return({[t]:(...t)=>{let r=p.dynamicAccessAsyncStorage.getStore();return r&&r.abortController.abort(Object.defineProperty(Error("Accessed fallback `params` during prerendering."),"__NEXT_ERROR_CODE",{value:"E691",enumerable:!1,configurable:!0})),new Proxy(n.apply(e,t),v)}})[t]}return i.ReflectAdapter.get(e,t,r)}};function O(e){let t=S.get(e);if(t)return t;let r=Promise.resolve(e);return S.set(e,r),r}(0,f.createDedupedByCallsiteServerErrorLoggerDev)(function(e,t){let r=e?`Route "${e}" `:"This route ";return Object.defineProperty(Error(`${r}used ${t}. \`params\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`),"__NEXT_ERROR_CODE",{value:"E834",enumerable:!1,configurable:!0})})},91060,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ClientPageRoot",{enumerable:!0,get:function(){return u}});let n=e.r(53500),a=e.r(87721),o=e.r(77713),i=e.r(42043),s=e.r(95907),c=e.r(80780);function u({Component:t,serverProvidedParams:r}){let u,l;if(null!==r)u=r.searchParams,l=r.params;else{let e=(0,i.use)(o.LayoutRouterContext);l=null!==e?e.parentParams:{},u=(0,s.urlSearchParamsToParsedUrlQuery)((0,i.use)(c.SearchParamsContext))}if("undefined"==typeof window){let r,o,{workAsyncStorage:i}=e.r(38908),s=i.getStore();if(!s)throw Object.defineProperty(new a.InvariantError("Expected workStore to exist when handling searchParams in a client Page."),"__NEXT_ERROR_CODE",{value:"E564",enumerable:!1,configurable:!0});let{createSearchParamsFromClient:c}=e.r(55882);r=c(u,s);let{createParamsFromClient:d}=e.r(70198);return o=d(l,s),(0,n.jsx)(t,{params:o,searchParams:r})}{let{createRenderSearchParamsFromClient:r}=e.r(33727),a=r(u),{createRenderParamsFromClient:o}=e.r(77577),i=o(l);return(0,n.jsx)(t,{params:i,searchParams:a})}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},48344,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ClientSegmentRoot",{enumerable:!0,get:function(){return s}});let n=e.r(53500),a=e.r(87721),o=e.r(77713),i=e.r(42043);function s({Component:t,slots:r,serverProvidedParams:s}){let c;if(null!==s)c=s.params;else{let e=(0,i.use)(o.LayoutRouterContext);c=null!==e?e.parentParams:{}}if("undefined"==typeof window){let o,{workAsyncStorage:i}=e.r(38908),s=i.getStore();if(!s)throw Object.defineProperty(new a.InvariantError("Expected workStore to exist when handling params in a client segment such as a Layout or Template."),"__NEXT_ERROR_CODE",{value:"E600",enumerable:!1,configurable:!0});let{createParamsFromClient:u}=e.r(70198);return o=u(c,s),(0,n.jsx)(t,{...r,params:o})}{let{createRenderParamsFromClient:a}=e.r(77577),o=a(c);return(0,n.jsx)(t,{...r,params:o})}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},18521,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"IconMark",{enumerable:!0,get:function(){return a}});let n=e.r(53500),a=()=>"undefined"!=typeof window?null:(0,n.jsx)("meta",{name:"«nxt-icon»"})}]);
|
package/CLAUDE.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Development Commands
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm dev # Start dev server (http://localhost:3000)
|
|
9
|
-
pnpm dev:clean # Reset DB with seed data and start dev server
|
|
10
|
-
pnpm build # Build for production
|
|
11
|
-
pnpm lint # Run ESLint
|
|
12
|
-
pnpm db:seed # Seed the database
|
|
13
|
-
pnpm db:reset # Reset database with migrations
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Architecture Overview
|
|
17
|
-
|
|
18
|
-
This is a **Mock Server Dashboard** - a Next.js 16 application that allows users to create, manage, and serve mock API endpoints stored in PostgreSQL via Prisma.
|
|
19
|
-
|
|
20
|
-
### Core Concept
|
|
21
|
-
|
|
22
|
-
1. Users define mock endpoints (path, method, status code, response body) through a web UI
|
|
23
|
-
2. These endpoints are stored in the `MockEndpoint` table
|
|
24
|
-
3. Requests to `/api/mock/*` are dynamically matched against stored endpoints using `path-to-regexp`
|
|
25
|
-
|
|
26
|
-
### Key Components
|
|
27
|
-
|
|
28
|
-
- **`/app/api/mock/[...slug]/route.ts`** - Catch-all route that handles all mock requests. Matches incoming requests against stored endpoints using pattern matching (supports path parameters like `:id`)
|
|
29
|
-
|
|
30
|
-
- **`/app/api/endpoints/`** - CRUD API for managing mock endpoints
|
|
31
|
-
- `route.ts` - GET (list all), POST (create)
|
|
32
|
-
- `[id]/route.ts` - PUT (update), DELETE
|
|
33
|
-
- `import/route.ts` - Bulk import from OpenAPI spec
|
|
34
|
-
- `sync/route.ts` - Sync endpoints with external spec
|
|
35
|
-
|
|
36
|
-
- **`/lib/openapi-parser.ts`** - Parses OpenAPI 3.x specs and generates mock response data based on schema definitions. Handles `$ref`, `allOf`, `oneOf`, `anyOf`, and generates type-appropriate mock values.
|
|
37
|
-
|
|
38
|
-
- **`/components/`** - React components for the dashboard UI
|
|
39
|
-
- `endpoint-table.tsx` - Display list of endpoints
|
|
40
|
-
- `endpoint-edit-dialog.tsx` - Create/edit endpoint with Monaco editor for JSON
|
|
41
|
-
- `openapi-upload-dialog.tsx` - Import endpoints from OpenAPI spec
|
|
42
|
-
|
|
43
|
-
### Database Schema
|
|
44
|
-
|
|
45
|
-
Single table `MockEndpoint` with unique constraint on `(path, method)`:
|
|
46
|
-
- `path` - Express-style route (e.g., `/v1/users/:id`)
|
|
47
|
-
- `method` - HTTP method
|
|
48
|
-
- `statusCode` - Response status code
|
|
49
|
-
- `responseBody` - JSON response data
|
|
50
|
-
|
|
51
|
-
### Tech Stack
|
|
52
|
-
|
|
53
|
-
- Next.js 16 (App Router)
|
|
54
|
-
- React 19
|
|
55
|
-
- Prisma with PostgreSQL
|
|
56
|
-
- Tailwind CSS 4
|
|
57
|
-
- Radix UI + shadcn/ui components
|
|
58
|
-
- Monaco Editor for JSON editing
|
package/app/favicon.ico
DELETED
|
Binary file
|
package/app/globals.css
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "tw-animate-css";
|
|
3
|
-
|
|
4
|
-
@custom-variant dark (&:is(.dark *));
|
|
5
|
-
|
|
6
|
-
@theme inline {
|
|
7
|
-
--color-background: var(--background);
|
|
8
|
-
--color-foreground: var(--foreground);
|
|
9
|
-
--font-sans: var(--font-geist-sans);
|
|
10
|
-
--font-mono: var(--font-geist-mono);
|
|
11
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
12
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
13
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
14
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
15
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
16
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
17
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
18
|
-
--color-sidebar: var(--sidebar);
|
|
19
|
-
--color-chart-5: var(--chart-5);
|
|
20
|
-
--color-chart-4: var(--chart-4);
|
|
21
|
-
--color-chart-3: var(--chart-3);
|
|
22
|
-
--color-chart-2: var(--chart-2);
|
|
23
|
-
--color-chart-1: var(--chart-1);
|
|
24
|
-
--color-ring: var(--ring);
|
|
25
|
-
--color-input: var(--input);
|
|
26
|
-
--color-border: var(--border);
|
|
27
|
-
--color-destructive: var(--destructive);
|
|
28
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
29
|
-
--color-accent: var(--accent);
|
|
30
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
31
|
-
--color-muted: var(--muted);
|
|
32
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
33
|
-
--color-secondary: var(--secondary);
|
|
34
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
35
|
-
--color-primary: var(--primary);
|
|
36
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
37
|
-
--color-popover: var(--popover);
|
|
38
|
-
--color-card-foreground: var(--card-foreground);
|
|
39
|
-
--color-card: var(--card);
|
|
40
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
41
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
42
|
-
--radius-lg: var(--radius);
|
|
43
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
44
|
-
--radius-2xl: calc(var(--radius) + 8px);
|
|
45
|
-
--radius-3xl: calc(var(--radius) + 12px);
|
|
46
|
-
--radius-4xl: calc(var(--radius) + 16px);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
:root {
|
|
50
|
-
--radius: 0.625rem;
|
|
51
|
-
--background: oklch(1 0 0);
|
|
52
|
-
--foreground: oklch(0.145 0 0);
|
|
53
|
-
--card: oklch(1 0 0);
|
|
54
|
-
--card-foreground: oklch(0.145 0 0);
|
|
55
|
-
--popover: oklch(1 0 0);
|
|
56
|
-
--popover-foreground: oklch(0.145 0 0);
|
|
57
|
-
--primary: oklch(0.205 0 0);
|
|
58
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
59
|
-
--secondary: oklch(0.97 0 0);
|
|
60
|
-
--secondary-foreground: oklch(0.205 0 0);
|
|
61
|
-
--muted: oklch(0.97 0 0);
|
|
62
|
-
--muted-foreground: oklch(0.556 0 0);
|
|
63
|
-
--accent: oklch(0.97 0 0);
|
|
64
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
65
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
66
|
-
--border: oklch(0.922 0 0);
|
|
67
|
-
--input: oklch(0.922 0 0);
|
|
68
|
-
--ring: oklch(0.708 0 0);
|
|
69
|
-
--chart-1: oklch(0.646 0.222 41.116);
|
|
70
|
-
--chart-2: oklch(0.6 0.118 184.704);
|
|
71
|
-
--chart-3: oklch(0.398 0.07 227.392);
|
|
72
|
-
--chart-4: oklch(0.828 0.189 84.429);
|
|
73
|
-
--chart-5: oklch(0.769 0.188 70.08);
|
|
74
|
-
--sidebar: oklch(0.985 0 0);
|
|
75
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
76
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
77
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
78
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
79
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
80
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
81
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.dark {
|
|
85
|
-
--background: oklch(0.145 0 0);
|
|
86
|
-
--foreground: oklch(0.985 0 0);
|
|
87
|
-
--card: oklch(0.205 0 0);
|
|
88
|
-
--card-foreground: oklch(0.985 0 0);
|
|
89
|
-
--popover: oklch(0.205 0 0);
|
|
90
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
91
|
-
--primary: oklch(0.922 0 0);
|
|
92
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
93
|
-
--secondary: oklch(0.269 0 0);
|
|
94
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
95
|
-
--muted: oklch(0.269 0 0);
|
|
96
|
-
--muted-foreground: oklch(0.708 0 0);
|
|
97
|
-
--accent: oklch(0.269 0 0);
|
|
98
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
99
|
-
--destructive: oklch(0.704 0.191 22.216);
|
|
100
|
-
--border: oklch(1 0 0 / 10%);
|
|
101
|
-
--input: oklch(1 0 0 / 15%);
|
|
102
|
-
--ring: oklch(0.556 0 0);
|
|
103
|
-
--chart-1: oklch(0.488 0.243 264.376);
|
|
104
|
-
--chart-2: oklch(0.696 0.17 162.48);
|
|
105
|
-
--chart-3: oklch(0.769 0.188 70.08);
|
|
106
|
-
--chart-4: oklch(0.627 0.265 303.9);
|
|
107
|
-
--chart-5: oklch(0.645 0.246 16.439);
|
|
108
|
-
--sidebar: oklch(0.205 0 0);
|
|
109
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
110
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
111
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
112
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
113
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
114
|
-
--sidebar-border: oklch(1 0 0 / 10%);
|
|
115
|
-
--sidebar-ring: oklch(0.556 0 0);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
@layer base {
|
|
119
|
-
* {
|
|
120
|
-
@apply border-border outline-ring/50;
|
|
121
|
-
}
|
|
122
|
-
body {
|
|
123
|
-
@apply bg-background text-foreground;
|
|
124
|
-
}
|
|
125
|
-
}
|
package/app/layout.tsx
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Metadata } from "next";
|
|
2
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
-
import { Toaster } from "@/components/ui/sonner";
|
|
4
|
-
import "./globals.css";
|
|
5
|
-
|
|
6
|
-
const geistSans = Geist({
|
|
7
|
-
variable: "--font-geist-sans",
|
|
8
|
-
subsets: ["latin"],
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const geistMono = Geist_Mono({
|
|
12
|
-
variable: "--font-geist-mono",
|
|
13
|
-
subsets: ["latin"],
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export const metadata: Metadata = {
|
|
17
|
-
title: "Growthman",
|
|
18
|
-
description: "Local mock API server with UI dashboard",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default function RootLayout({
|
|
22
|
-
children,
|
|
23
|
-
}: Readonly<{
|
|
24
|
-
children: React.ReactNode;
|
|
25
|
-
}>) {
|
|
26
|
-
return (
|
|
27
|
-
<html lang="en">
|
|
28
|
-
<body
|
|
29
|
-
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
30
|
-
>
|
|
31
|
-
{children}
|
|
32
|
-
<Toaster />
|
|
33
|
-
</body>
|
|
34
|
-
</html>
|
|
35
|
-
);
|
|
36
|
-
}
|
package/app/page.tsx
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useState, useEffect, useCallback } from 'react'
|
|
4
|
-
import { MockEndpoint } from '@/types/endpoint'
|
|
5
|
-
import { EndpointTable } from '@/components/endpoint-table'
|
|
6
|
-
import { EndpointEditDialog } from '@/components/endpoint-edit-dialog'
|
|
7
|
-
import { OpenAPIUploadDialog } from '@/components/openapi-upload-dialog'
|
|
8
|
-
import { Button } from '@/components/ui/button'
|
|
9
|
-
import { toast } from 'sonner'
|
|
10
|
-
|
|
11
|
-
export default function Home() {
|
|
12
|
-
const [endpoints, setEndpoints] = useState<MockEndpoint[]>([])
|
|
13
|
-
const [loading, setLoading] = useState(true)
|
|
14
|
-
const [editDialogOpen, setEditDialogOpen] = useState(false)
|
|
15
|
-
const [uploadDialogOpen, setUploadDialogOpen] = useState(false)
|
|
16
|
-
const [selectedEndpoint, setSelectedEndpoint] = useState<MockEndpoint | null>(null)
|
|
17
|
-
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
|
|
18
|
-
|
|
19
|
-
const fetchEndpoints = useCallback(async () => {
|
|
20
|
-
try {
|
|
21
|
-
const response = await fetch('/api/endpoints')
|
|
22
|
-
const data = await response.json()
|
|
23
|
-
setEndpoints(data)
|
|
24
|
-
} catch (error) {
|
|
25
|
-
console.error('Failed to fetch endpoints:', error)
|
|
26
|
-
} finally {
|
|
27
|
-
setLoading(false)
|
|
28
|
-
}
|
|
29
|
-
}, [])
|
|
30
|
-
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
fetchEndpoints()
|
|
33
|
-
}, [fetchEndpoints])
|
|
34
|
-
|
|
35
|
-
const handleEdit = (endpoint: MockEndpoint) => {
|
|
36
|
-
setSelectedEndpoint(endpoint)
|
|
37
|
-
setEditDialogOpen(true)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const handleCreate = () => {
|
|
41
|
-
setSelectedEndpoint(null)
|
|
42
|
-
setEditDialogOpen(true)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const handleDelete = async (id: string) => {
|
|
46
|
-
if (!confirm('Are you sure you want to delete this endpoint?')) return
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const response = await fetch(`/api/endpoints/${id}`, { method: 'DELETE' })
|
|
50
|
-
if (!response.ok) throw new Error('Failed to delete')
|
|
51
|
-
setSelectedIds((prev) => {
|
|
52
|
-
const newSet = new Set(prev)
|
|
53
|
-
newSet.delete(id)
|
|
54
|
-
return newSet
|
|
55
|
-
})
|
|
56
|
-
toast.success('Endpoint deleted successfully')
|
|
57
|
-
fetchEndpoints()
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error('Failed to delete endpoint:', error)
|
|
60
|
-
toast.error('Failed to delete endpoint')
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const handleBulkDelete = async () => {
|
|
65
|
-
if (selectedIds.size === 0) return
|
|
66
|
-
if (!confirm(`Are you sure you want to delete ${selectedIds.size} endpoint(s)?`)) return
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const response = await fetch('/api/endpoints/bulk', {
|
|
70
|
-
method: 'DELETE',
|
|
71
|
-
headers: { 'Content-Type': 'application/json' },
|
|
72
|
-
body: JSON.stringify({ ids: Array.from(selectedIds) }),
|
|
73
|
-
})
|
|
74
|
-
if (!response.ok) throw new Error('Failed to delete')
|
|
75
|
-
const count = selectedIds.size
|
|
76
|
-
setSelectedIds(new Set())
|
|
77
|
-
toast.success(`${count} endpoint(s) deleted successfully`)
|
|
78
|
-
fetchEndpoints()
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.error('Failed to delete endpoints:', error)
|
|
81
|
-
toast.error('Failed to delete endpoints')
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const handleSave = async (endpoint: Partial<MockEndpoint> & { id?: string }) => {
|
|
86
|
-
try {
|
|
87
|
-
const isUpdate = !!endpoint.id
|
|
88
|
-
const response = isUpdate
|
|
89
|
-
? await fetch(`/api/endpoints/${endpoint.id}`, {
|
|
90
|
-
method: 'PUT',
|
|
91
|
-
headers: { 'Content-Type': 'application/json' },
|
|
92
|
-
body: JSON.stringify(endpoint),
|
|
93
|
-
})
|
|
94
|
-
: await fetch('/api/endpoints', {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: { 'Content-Type': 'application/json' },
|
|
97
|
-
body: JSON.stringify(endpoint),
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
if (!response.ok) {
|
|
101
|
-
const data = await response.json()
|
|
102
|
-
throw new Error(data.error || 'Failed to save')
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
toast.success(isUpdate ? 'Endpoint updated successfully' : 'Endpoint created successfully')
|
|
106
|
-
fetchEndpoints()
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.error('Failed to save endpoint:', error)
|
|
109
|
-
toast.error(error instanceof Error ? error.message : 'Failed to save endpoint')
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return (
|
|
114
|
-
<div className="min-h-screen bg-gray-50">
|
|
115
|
-
<div className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
|
|
116
|
-
<div className="flex justify-between items-center mb-8">
|
|
117
|
-
<div>
|
|
118
|
-
<h1 className="text-3xl font-bold text-gray-900">Growthman</h1>
|
|
119
|
-
<p className="mt-1 text-gray-500">
|
|
120
|
-
Manage your mock API endpoints
|
|
121
|
-
</p>
|
|
122
|
-
</div>
|
|
123
|
-
<div className="flex gap-3">
|
|
124
|
-
<Button variant="outline" onClick={() => setUploadDialogOpen(true)}>
|
|
125
|
-
Import OpenAPI
|
|
126
|
-
</Button>
|
|
127
|
-
<Button onClick={handleCreate}>
|
|
128
|
-
+ New Endpoint
|
|
129
|
-
</Button>
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
{selectedIds.size > 0 && (
|
|
134
|
-
<div className="mb-4 flex items-center gap-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
|
|
135
|
-
<span className="text-sm text-blue-800">
|
|
136
|
-
{selectedIds.size} endpoint(s) selected
|
|
137
|
-
</span>
|
|
138
|
-
<Button
|
|
139
|
-
variant="destructive"
|
|
140
|
-
size="sm"
|
|
141
|
-
onClick={handleBulkDelete}
|
|
142
|
-
>
|
|
143
|
-
Delete Selected
|
|
144
|
-
</Button>
|
|
145
|
-
<Button
|
|
146
|
-
variant="ghost"
|
|
147
|
-
size="sm"
|
|
148
|
-
onClick={() => setSelectedIds(new Set())}
|
|
149
|
-
>
|
|
150
|
-
Clear Selection
|
|
151
|
-
</Button>
|
|
152
|
-
</div>
|
|
153
|
-
)}
|
|
154
|
-
|
|
155
|
-
<div className="bg-white shadow rounded-lg">
|
|
156
|
-
{loading ? (
|
|
157
|
-
<div className="p-8 text-center text-gray-500">Loading...</div>
|
|
158
|
-
) : (
|
|
159
|
-
<EndpointTable
|
|
160
|
-
endpoints={endpoints}
|
|
161
|
-
onEdit={handleEdit}
|
|
162
|
-
onDelete={handleDelete}
|
|
163
|
-
selectedIds={selectedIds}
|
|
164
|
-
onSelectionChange={setSelectedIds}
|
|
165
|
-
/>
|
|
166
|
-
)}
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
<EndpointEditDialog
|
|
171
|
-
endpoint={selectedEndpoint}
|
|
172
|
-
open={editDialogOpen}
|
|
173
|
-
onOpenChange={setEditDialogOpen}
|
|
174
|
-
onSave={handleSave}
|
|
175
|
-
/>
|
|
176
|
-
|
|
177
|
-
<OpenAPIUploadDialog
|
|
178
|
-
open={uploadDialogOpen}
|
|
179
|
-
onOpenChange={setUploadDialogOpen}
|
|
180
|
-
onImportComplete={fetchEndpoints}
|
|
181
|
-
/>
|
|
182
|
-
</div>
|
|
183
|
-
)
|
|
184
|
-
}
|
|
@@ -1,181 +0,0 @@
|
|
|
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
|
-
}
|