@devvistatech/devvista-kit 0.0.10 → 0.0.13
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/CHANGELOG.md +12 -12
- package/LICENSE +6 -6
- package/README.md +55 -15
- package/app/ClientLayout.tsx +66 -0
- package/app/about/page.tsx +61 -298
- package/app/adRequest/page.tsx +625 -549
- package/app/admin-profile/page.tsx +123 -0
- package/app/analytics/page.tsx +382 -346
- package/app/api/about/route.ts +290 -306
- package/app/api/adRequest/route.ts +547 -567
- package/app/api/analytics/[reportType]/route.ts +274 -337
- package/app/api/bio/route.ts +297 -313
- package/app/api/blog/route.ts +288 -306
- package/app/api/chat/route.ts +14 -14
- package/app/api/contact/route.ts +409 -409
- package/app/api/contacts/route.ts +179 -224
- package/app/api/files/route.ts +415 -429
- package/app/api/gallery-data/route.ts +727 -735
- package/app/api/schedule/route.ts +439 -455
- package/app/api/signup/route.ts +129 -0
- package/app/api/sync-user/route.ts +306 -132
- package/app/api/trial-request/route.ts +297 -297
- package/app/api/verify-admin/route.ts +46 -0
- package/app/blog/[id]/page.tsx +307 -288
- package/app/blog/page.tsx +249 -216
- package/app/contact/page.tsx +284 -284
- package/app/faq/page.tsx +191 -191
- package/app/favicon.ico +0 -0
- package/app/gallery/page.tsx +336 -315
- package/app/globals.css +58 -58
- package/app/layout.tsx +59 -110
- package/app/not-found.tsx +20 -20
- package/app/page.tsx +47 -338
- package/app/products/constants/product.ts +27 -0
- package/app/products/page.tsx +296 -0
- package/app/products/productOne/page.tsx +266 -0
- package/app/products/productTwo/page.tsx +272 -0
- package/app/schedule/page.tsx +698 -660
- package/bin/init.js +207 -219
- package/components/addOns/functional/CalendlyWidget.tsx +107 -107
- package/components/addOns/functional/ClassList.tsx +149 -145
- package/components/addOns/functional/ClassPopup.tsx +398 -398
- package/components/addOns/functional/ContactForm.tsx +284 -284
- package/components/addOns/functional/NewUserAnalytics.tsx +100 -100
- package/components/addOns/functional/ProductList.tsx +1027 -0
- package/components/addOns/functional/aboutSections/AboutSection.tsx +581 -544
- package/components/addOns/functional/aboutSections/constants/aboutSection.ts +70 -65
- package/components/addOns/functional/banner/Banner.tsx +150 -0
- package/components/addOns/functional/banner/BannerDashboard.tsx +283 -0
- package/components/addOns/functional/bioSections/BioEditor.tsx +471 -0
- package/components/addOns/functional/bioSections/constants/bioEditor.ts +36 -0
- package/components/addOns/functional/blogSections/BlogDashboard.tsx +184 -184
- package/components/addOns/functional/blogSections/BlogFormPopUp.tsx +555 -554
- package/components/addOns/functional/blogSections/BlogList.tsx +148 -148
- package/components/addOns/functional/blogSections/BlogSidebar.tsx +58 -58
- package/components/addOns/functional/blogSections/constants/blogDashboard.ts +28 -28
- package/components/addOns/functional/blogSections/constants/blogFormPopUp.ts +97 -97
- package/components/addOns/functional/blogSections/constants/blogList.ts +22 -22
- package/components/addOns/functional/blogSections/constants/blogSidebar.ts +15 -15
- package/components/addOns/functional/{ImageDescCarousel.tsx → carousels/ImageDescCarousel.tsx} +839 -730
- package/components/addOns/functional/carousels/ProductDescCarousel.tsx +1129 -0
- package/components/addOns/functional/{ScheduleCarousel.tsx → carousels/ScheduleCarousel.tsx} +231 -171
- package/components/addOns/functional/carousels/constants.ts/productDescCarousel.ts +197 -0
- package/components/addOns/functional/carousels/constants.ts/scheduleCarousel.ts +20 -0
- package/components/addOns/functional/contactsDashboard/ContactsDashboard.tsx +366 -366
- package/components/addOns/functional/contactsDashboard/constants/contactsDashboard.ts +70 -70
- package/components/addOns/functional/fileUploaders/FileUploader.tsx +437 -0
- package/components/addOns/functional/fileUploaders/constants/fileUploader.ts +45 -0
- package/components/addOns/functional/galleries/GalleryComplex.tsx +1037 -836
- package/components/addOns/functional/galleries/GallerySimple.tsx +537 -509
- package/components/addOns/functional/galleries/ThreeSetGallery.tsx +260 -0
- package/components/addOns/functional/galleries/constants/galleryComplex.ts +106 -106
- package/components/addOns/functional/galleries/constants/gallerySimple.ts +76 -76
- package/components/addOns/functional/schedules/ScheduleGridOne.tsx +276 -262
- package/components/addOns/functional/schedules/ScheduleGridTwo.tsx +299 -294
- package/components/addOns/functional/schedules/ScheduleGridTwoBasic.tsx +293 -288
- package/components/addOns/functional/schedules/SchedulerForm.tsx +428 -428
- package/components/addOns/functional/schedules/constants/ScheduleGridTwo.ts +40 -40
- package/components/addOns/functional/schedules/constants/ScheduleGridTwoBasic.ts +40 -40
- package/components/addOns/functional/schedules/constants/SchedulerForm.ts +65 -65
- package/components/addOns/functional/schedules/constants/scheduleGridOne.ts +54 -54
- package/components/addOns/non-functional/AnnouncementBanner.tsx +46 -46
- package/components/addOns/non-functional/IconBubble.tsx +49 -49
- package/components/addOns/non-functional/SampleCarousel.tsx +204 -204
- package/components/addOns/non-functional/Testimonials.tsx +334 -334
- package/components/addOns/non-functional/ThreeSetGallery.tsx +63 -63
- package/components/addOns/non-functional/aboutSections/AboutSection.tsx +62 -62
- package/components/addOns/non-functional/aboutSections/constants/aboutSection.ts +24 -24
- package/components/addOns/non-functional/featureSections/FeaturesSection.tsx +74 -0
- package/components/addOns/non-functional/featureSections/constants/featuresSection.ts +30 -0
- package/components/addOns/non-functional/{Heros/HeroSection.tsx → heros/HomeHero.tsx} +144 -142
- package/components/addOns/non-functional/heros/ProductHero.tsx +111 -0
- package/components/addOns/non-functional/heros/constants/hero.ts +62 -0
- package/components/addOns/non-functional/imageCarousels/ProductSlider.tsx +117 -117
- package/components/addOns/non-functional/imageCarousels/ProgramCarousel.tsx +232 -232
- package/components/addOns/non-functional/imageCarousels/constants/programCarousel.ts +39 -39
- package/components/addOns/non-functional/imageCarousels/constants/programSlider.ts +36 -36
- package/components/addOns/non-functional/spinner.tsx +21 -21
- package/components/footers/footer.tsx +416 -453
- package/components/navBars/navbar.tsx +310 -310
- package/components/other/accordion.tsx +58 -58
- package/components/other/admin-menu.tsx +68 -68
- package/components/other/alert-dialog.tsx +141 -141
- package/components/other/alert.tsx +59 -59
- package/components/other/aspect-ratio.tsx +7 -7
- package/components/other/avatar.tsx +50 -50
- package/components/other/badge.tsx +36 -36
- package/components/other/breadcrumb.tsx +115 -115
- package/components/other/button.tsx +738 -738
- package/components/other/calendar.tsx +66 -66
- package/components/other/card.tsx +86 -86
- package/components/other/carousel.tsx +274 -274
- package/components/other/chart.tsx +363 -363
- package/components/other/checkbox.tsx +30 -30
- package/components/other/collapsible.tsx +11 -11
- package/components/other/command.tsx +155 -155
- package/components/other/context-menu.tsx +200 -200
- package/components/other/dialog.tsx +122 -122
- package/components/other/drawer.tsx +118 -118
- package/components/other/dropdown-menu.tsx +200 -200
- package/components/other/form.tsx +179 -179
- package/components/other/hover-card.tsx +29 -29
- package/components/other/input-otp.tsx +71 -71
- package/components/other/input.tsx +25 -25
- package/components/other/label.tsx +26 -26
- package/components/other/menubar.tsx +236 -236
- package/components/other/mobile-icon.tsx +21 -21
- package/components/other/navigation-menu.tsx +128 -128
- package/components/other/pagination.tsx +117 -117
- package/components/other/popover.tsx +31 -31
- package/components/other/progress.tsx +28 -28
- package/components/other/radio-group.tsx +44 -44
- package/components/other/resizable.tsx +45 -45
- package/components/other/scroll-area.tsx +48 -48
- package/components/other/select.tsx +160 -160
- package/components/other/separator.tsx +31 -31
- package/components/other/sheet.tsx +140 -140
- package/components/other/skeleton.tsx +15 -15
- package/components/other/slider.tsx +28 -28
- package/components/other/social-icons.tsx +39 -39
- package/components/other/sonner.tsx +31 -31
- package/components/other/switch.tsx +29 -29
- package/components/other/table.tsx +117 -117
- package/components/other/tabs.tsx +55 -55
- package/components/other/textarea.tsx +24 -24
- package/components/other/toast.tsx +122 -122
- package/components/other/toaster.tsx +35 -35
- package/components/other/toggle-group.tsx +61 -61
- package/components/other/toggle.tsx +45 -45
- package/components/other/tooltip.tsx +30 -30
- package/components/theme-provider.tsx +8 -8
- package/hooks/use-toast.ts +188 -188
- package/lib/auth/auth-context.tsx +225 -0
- package/lib/auth/auth-utils.tsx +30 -0
- package/lib/constants/about.ts +34 -34
- package/lib/constants/adRequest.ts +256 -113
- package/lib/constants/admin-profile.ts +12 -0
- package/lib/constants/contact.ts +40 -40
- package/lib/constants/faq.ts +34 -34
- package/lib/constants/gallery.ts +42 -42
- package/lib/constants/page.ts +69 -69
- package/lib/constants/schedule.ts +71 -71
- package/lib/google/google-analytics-tracking.tsx +44 -0
- package/lib/{google-analytics.tsx → google/google-analytics.tsx} +97 -97
- package/lib/types.ts +235 -0
- package/lib/utils/compressImage.tsx +32 -0
- package/middleware.ts +46 -42
- package/netlify.toml +5 -5
- package/next.config.js +10 -10
- package/package.json +117 -116
- package/public/images/test.png +0 -0
- package/tailwind.config.ts +89 -89
- package/tsconfig.json +23 -23
- package/components/addOns/functional/BioEditor.tsx +0 -447
- package/components/addOns/functional/FileUploader.tsx +0 -295
- package/components/addOns/non-functional/FeaturesSection.tsx +0 -63
- package/components/types.ts +0 -50
- package/dist/.next/types/app/api/about/route.js +0 -52
- package/dist/.next/types/app/api/blog/route.js +0 -52
- package/dist/.next/types/app/api/files/route.js +0 -52
- package/dist/.next/types/app/api/schedule/route.js +0 -52
- package/dist/.next/types/app/api/sync-user/route.js +0 -52
- package/dist/.next/types/app/layout.js +0 -22
- package/dist/.next/types/app/page.js +0 -22
- package/dist/app/about/page.jsx +0 -258
- package/dist/app/adRequest/page.jsx +0 -531
- package/dist/app/analytics/page.jsx +0 -298
- package/dist/app/api/about/route.js +0 -285
- package/dist/app/api/adRequest/route.js +0 -440
- package/dist/app/api/analytics/[reportType]/route.js +0 -357
- package/dist/app/api/bio/route.js +0 -293
- package/dist/app/api/blog/route.js +0 -366
- package/dist/app/api/chat/route.js +0 -58
- package/dist/app/api/contact/route.js +0 -163
- package/dist/app/api/contacts/route.js +0 -234
- package/dist/app/api/files/route.js +0 -444
- package/dist/app/api/gallery-data/route.js +0 -719
- package/dist/app/api/schedule/route.js +0 -461
- package/dist/app/api/sync-user/route.js +0 -186
- package/dist/app/api/trial-request/route.js +0 -165
- package/dist/app/blog/[id]/page.jsx +0 -312
- package/dist/app/blog/page.jsx +0 -210
- package/dist/app/constants/about.js +0 -32
- package/dist/app/constants/adRequest.js +0 -113
- package/dist/app/constants/contact.js +0 -40
- package/dist/app/constants/faq.js +0 -36
- package/dist/app/constants/gallery.js +0 -42
- package/dist/app/constants/page.js +0 -69
- package/dist/app/constants/schedule.js +0 -71
- package/dist/app/contact/page.jsx +0 -119
- package/dist/app/faq/page.jsx +0 -97
- package/dist/app/gallery/page.jsx +0 -281
- package/dist/app/layout.jsx +0 -45
- package/dist/app/not-found.jsx +0 -14
- package/dist/app/page.jsx +0 -324
- package/dist/app/schedule/page.jsx +0 -500
- package/dist/components/addOns/functional/BioEditor.jsx +0 -187
- package/dist/components/addOns/functional/CalendlyWidget.jsx +0 -61
- package/dist/components/addOns/functional/ClassList.jsx +0 -158
- package/dist/components/addOns/functional/ClassPopup.jsx +0 -300
- package/dist/components/addOns/functional/ContactForm.jsx +0 -219
- package/dist/components/addOns/functional/FileUploader.jsx +0 -222
- package/dist/components/addOns/functional/ImageDescCarousel.jsx +0 -491
- package/dist/components/addOns/functional/NewUserAnalytics.jsx +0 -71
- package/dist/components/addOns/functional/ScheduleCarousel.jsx +0 -68
- package/dist/components/addOns/functional/aboutSections/AboutSection.jsx +0 -372
- package/dist/components/addOns/functional/aboutSections/constants/aboutSection.js +0 -65
- package/dist/components/addOns/functional/blogSections/BlogDashboard.jsx +0 -111
- package/dist/components/addOns/functional/blogSections/BlogFormPopUp.jsx +0 -465
- package/dist/components/addOns/functional/blogSections/BlogList.jsx +0 -170
- package/dist/components/addOns/functional/blogSections/BlogSidebar.jsx +0 -35
- package/dist/components/addOns/functional/blogSections/constants/blogDashboard.js +0 -28
- package/dist/components/addOns/functional/blogSections/constants/blogFormPopUp.js +0 -97
- package/dist/components/addOns/functional/blogSections/constants/blogList.js +0 -22
- package/dist/components/addOns/functional/blogSections/constants/blogSidebar.js +0 -15
- package/dist/components/addOns/functional/contactsDashboard/ContactsDashboard.jsx +0 -355
- package/dist/components/addOns/functional/contactsDashboard/constants/contactsDashboard.js +0 -70
- package/dist/components/addOns/functional/galleries/GalleryComplex.jsx +0 -605
- package/dist/components/addOns/functional/galleries/GallerySimple.jsx +0 -363
- package/dist/components/addOns/functional/galleries/constants/galleryComplex.js +0 -106
- package/dist/components/addOns/functional/galleries/constants/gallerySimple.js +0 -76
- package/dist/components/addOns/functional/schedules/ScheduleGridOne.jsx +0 -167
- package/dist/components/addOns/functional/schedules/ScheduleGridTwo.jsx +0 -100
- package/dist/components/addOns/functional/schedules/ScheduleGridTwoBasic.jsx +0 -97
- package/dist/components/addOns/functional/schedules/SchedulerForm.jsx +0 -188
- package/dist/components/addOns/functional/schedules/constants/ScheduleGridTwo.js +0 -40
- package/dist/components/addOns/functional/schedules/constants/ScheduleGridTwoBasic.js +0 -40
- package/dist/components/addOns/functional/schedules/constants/SchedulerForm.js +0 -65
- package/dist/components/addOns/functional/schedules/constants/scheduleGridOne.js +0 -54
- package/dist/components/addOns/non-functional/AnnouncementBanner.jsx +0 -24
- package/dist/components/addOns/non-functional/FeaturesSection.jsx +0 -38
- package/dist/components/addOns/non-functional/HeroSection.jsx +0 -71
- package/dist/components/addOns/non-functional/Heros/HeroSection.jsx +0 -71
- package/dist/components/addOns/non-functional/IconBubble.jsx +0 -36
- package/dist/components/addOns/non-functional/SampleCarousel.jsx +0 -114
- package/dist/components/addOns/non-functional/Testimonials.jsx +0 -177
- package/dist/components/addOns/non-functional/ThreeSetGallery.jsx +0 -40
- package/dist/components/addOns/non-functional/aboutSections/AboutSection.jsx +0 -35
- package/dist/components/addOns/non-functional/aboutSections/constants/aboutSection.js +0 -24
- package/dist/components/addOns/non-functional/imageCarousels/ProductSlider.jsx +0 -80
- package/dist/components/addOns/non-functional/imageCarousels/ProgramCarousel.jsx +0 -155
- package/dist/components/addOns/non-functional/imageCarousels/constants/programCarousel.js +0 -39
- package/dist/components/addOns/non-functional/imageCarousels/constants/programSlider.js +0 -36
- package/dist/components/addOns/non-functional/spinner.jsx +0 -13
- package/dist/components/footers/footer.jsx +0 -217
- package/dist/components/navBars/navbar.jsx +0 -159
- package/dist/components/other/accordion.jsx +0 -40
- package/dist/components/other/admin-menu.jsx +0 -34
- package/dist/components/other/alert-dialog.jsx +0 -64
- package/dist/components/other/alert.jsx +0 -41
- package/dist/components/other/aspect-ratio.jsx +0 -4
- package/dist/components/other/avatar.jsx +0 -31
- package/dist/components/other/badge.jsx +0 -32
- package/dist/components/other/breadcrumb.jsx +0 -57
- package/dist/components/other/button.jsx +0 -322
- package/dist/components/other/calendar.jsx +0 -43
- package/dist/components/other/card.jsx +0 -44
- package/dist/components/other/carousel.jsx +0 -140
- package/dist/components/other/chart.jsx +0 -182
- package/dist/components/other/checkbox.jsx +0 -26
- package/dist/components/other/collapsible.jsx +0 -6
- package/dist/components/other/command.jsx +0 -68
- package/dist/components/other/context-menu.jsx +0 -88
- package/dist/components/other/dialog.jsx +0 -60
- package/dist/components/other/drawer.jsx +0 -60
- package/dist/components/other/dropdown-menu.jsx +0 -90
- package/dist/components/other/form.jsx +0 -89
- package/dist/components/other/hover-card.jsx +0 -23
- package/dist/components/other/input-otp.jsx +0 -46
- package/dist/components/other/input.jsx +0 -19
- package/dist/components/other/label.jsx +0 -23
- package/dist/components/other/login-popup.jsx +0 -1
- package/dist/components/other/menubar.jsx +0 -96
- package/dist/components/other/mobile-icon.jsx +0 -11
- package/dist/components/other/navigation-menu.jsx +0 -62
- package/dist/components/other/pagination.jsx +0 -63
- package/dist/components/other/popover.jsx +0 -25
- package/dist/components/other/progress.jsx +0 -23
- package/dist/components/other/radio-group.jsx +0 -31
- package/dist/components/other/resizable.jsx +0 -29
- package/dist/components/other/scroll-area.jsx +0 -36
- package/dist/components/other/select.jsx +0 -83
- package/dist/components/other/separator.jsx +0 -21
- package/dist/components/other/sheet.jsx +0 -74
- package/dist/components/other/signup-popup.jsx +0 -1
- package/dist/components/other/skeleton.jsx +0 -17
- package/dist/components/other/slider.jsx +0 -26
- package/dist/components/other/social-icons.jsx +0 -15
- package/dist/components/other/sonner.jsx +0 -27
- package/dist/components/other/switch.jsx +0 -23
- package/dist/components/other/table.jsx +0 -56
- package/dist/components/other/tabs.jsx +0 -32
- package/dist/components/other/textarea.jsx +0 -19
- package/dist/components/other/toast.jsx +0 -58
- package/dist/components/other/toaster.jsx +0 -31
- package/dist/components/other/toggle-group.jsx +0 -41
- package/dist/components/other/toggle.jsx +0 -39
- package/dist/components/other/tooltip.jsx +0 -24
- package/dist/components/theme-provider.jsx +0 -18
- package/dist/components/types.js +0 -1
- package/dist/hooks/use-toast.js +0 -135
- package/dist/lib/auth-context.jsx +0 -144
- package/dist/lib/constants/about.js +0 -32
- package/dist/lib/constants/adRequest.js +0 -113
- package/dist/lib/constants/contact.js +0 -40
- package/dist/lib/constants/faq.js +0 -36
- package/dist/lib/constants/gallery.js +0 -42
- package/dist/lib/constants/page.js +0 -69
- package/dist/lib/constants/schedule.js +0 -71
- package/dist/lib/google-analytics.jsx +0 -148
- package/dist/lib/utils.js +0 -9
- package/dist/lib/verify-user.js +0 -142
- package/dist/middleware.js +0 -37
- package/dist/tailwind.config.js +0 -86
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/lib/auth-context.tsx +0 -131
- package/lib/verify-user.ts +0 -118
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
|
|
4
|
+
export async function POST(req: NextRequest) {
|
|
5
|
+
const STRAPI_USER_LIST_API_URL = process.env.STRAPI_USER_LIST_API_URL;
|
|
6
|
+
const STRAPI_API_TOKEN = process.env.STRAPI_API_TOKEN;
|
|
7
|
+
const allowedOrigin = process.env.NEXT_PUBLIC_BASE_URL;
|
|
8
|
+
|
|
9
|
+
if (!STRAPI_USER_LIST_API_URL || !STRAPI_API_TOKEN || !allowedOrigin) {
|
|
10
|
+
console.error("POST /api/signup: Missing environment variables", {
|
|
11
|
+
hasStrapiUrl: !!STRAPI_USER_LIST_API_URL,
|
|
12
|
+
hasStrapiToken: !!STRAPI_API_TOKEN,
|
|
13
|
+
hasBaseUrl: !!allowedOrigin,
|
|
14
|
+
timestamp: new Date().toISOString(),
|
|
15
|
+
});
|
|
16
|
+
return NextResponse.json({ error: "Server configuration error" }, { status: 500 });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const headers = new Headers({
|
|
20
|
+
"Access-Control-Allow-Origin": allowedOrigin,
|
|
21
|
+
"Access-Control-Allow-Methods": "POST",
|
|
22
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (req.method === "OPTIONS") {
|
|
26
|
+
return new NextResponse(null, { status: 204, headers });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const requestId = crypto.randomUUID();
|
|
30
|
+
let body;
|
|
31
|
+
try {
|
|
32
|
+
body = await req.json();
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("POST /api/signup: Failed to parse request body", { requestId, error, timestamp: new Date().toISOString() });
|
|
35
|
+
return NextResponse.json({ error: "Invalid request body" }, { status: 400, headers });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const { authId, email, username } = body;
|
|
39
|
+
|
|
40
|
+
if (!authId || !email || !username) {
|
|
41
|
+
console.error("POST /api/signup: Missing required fields", { requestId, body, timestamp: new Date().toISOString() });
|
|
42
|
+
return NextResponse.json({ error: "Missing required fields: authId, email, or username" }, { status: 400, headers });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
46
|
+
if (!emailRegex.test(email)) {
|
|
47
|
+
console.error("POST /api/signup: Invalid email format", { requestId, email, timestamp: new Date().toISOString() });
|
|
48
|
+
return NextResponse.json({ error: "Invalid email format" }, { status: 400, headers });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
// Check if user exists by authId or email
|
|
53
|
+
const checkResponse = await fetch(
|
|
54
|
+
`${STRAPI_USER_LIST_API_URL}?filters[$or][0][authId][$eq]=${encodeURIComponent(authId)}&filters[$or][1][email][$eq]=${encodeURIComponent(email)}`,
|
|
55
|
+
{
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Bearer ${STRAPI_API_TOKEN}`,
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
if (!checkResponse.ok) {
|
|
64
|
+
console.error("POST /api/signup: Failed to check existing user:", {
|
|
65
|
+
requestId,
|
|
66
|
+
status: checkResponse.status,
|
|
67
|
+
timestamp: new Date().toISOString(),
|
|
68
|
+
});
|
|
69
|
+
return NextResponse.json({ error: "Failed to check existing user" }, { status: checkResponse.status, headers });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const checkResult = await checkResponse.json();
|
|
73
|
+
if (checkResult.data && checkResult.data.length > 0) {
|
|
74
|
+
return NextResponse.json(checkResult.data[0], { status: 200, headers });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Create new Strapi user
|
|
78
|
+
const strapiUserData = {
|
|
79
|
+
data: {
|
|
80
|
+
authId,
|
|
81
|
+
email,
|
|
82
|
+
username,
|
|
83
|
+
userRole: "user",
|
|
84
|
+
businessAdminId: null,
|
|
85
|
+
publishedAt: new Date().toISOString(),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const createResponse = await fetch(STRAPI_USER_LIST_API_URL, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: {
|
|
92
|
+
Authorization: `Bearer ${STRAPI_API_TOKEN}`,
|
|
93
|
+
"Content-Type": "application/json",
|
|
94
|
+
},
|
|
95
|
+
body: JSON.stringify(strapiUserData),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!createResponse.ok) {
|
|
99
|
+
const errorData = await createResponse.json();
|
|
100
|
+
console.error("POST /api/signup: Failed to create Strapi user:", {
|
|
101
|
+
requestId,
|
|
102
|
+
status: createResponse.status,
|
|
103
|
+
errorData,
|
|
104
|
+
timestamp: new Date().toISOString(),
|
|
105
|
+
});
|
|
106
|
+
return NextResponse.json({ error: errorData.error?.message || "Failed to create user" }, { status: createResponse.status, headers });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const newStrapiUser = await createResponse.json();
|
|
110
|
+
|
|
111
|
+
return NextResponse.json(newStrapiUser.data, { status: 201, headers });
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error("POST /api/signup: Error:", {
|
|
114
|
+
requestId,
|
|
115
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
});
|
|
118
|
+
return NextResponse.json(
|
|
119
|
+
{ error: "Internal server error", details: error instanceof Error ? error.message : "Unknown error" },
|
|
120
|
+
{ status: 500, headers }
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const config = {
|
|
126
|
+
api: {
|
|
127
|
+
bodyParser: true,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
@@ -1,132 +1,306 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { getAuth } from "@clerk/nextjs/server";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { getAuth } from "@clerk/nextjs/server";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
|
|
5
|
+
// GET handler for /api/sync-user: Retrieves a Strapi user by Clerk authId (user ID).
|
|
6
|
+
// This is called from the client to check if a user exists in Strapi.
|
|
7
|
+
export async function GET(req: NextRequest) {
|
|
8
|
+
// Retrieve the allowed origin for CORS from environment variables, default to 'http://localhost:3000'. TODO: add development mode check
|
|
9
|
+
const allowedOrigin = process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000';
|
|
10
|
+
// Environment variables for Strapi API integration.
|
|
11
|
+
const STRAPI_USER_LIST_API_URL = process.env.STRAPI_USER_LIST_API_URL;
|
|
12
|
+
const STRAPI_API_TOKEN = process.env.STRAPI_API_TOKEN;
|
|
13
|
+
// Extract the authId (Clerk user ID) from query parameters.
|
|
14
|
+
const authId = req.nextUrl.searchParams.get("authId");
|
|
15
|
+
|
|
16
|
+
// Validate required environment variables and authId; return 500 if missing.
|
|
17
|
+
if (!STRAPI_USER_LIST_API_URL || !STRAPI_API_TOKEN || !authId) {
|
|
18
|
+
console.error("GET /api/sync-user: Missing environment variables or authId", {
|
|
19
|
+
hasBaseUrl: !!allowedOrigin,
|
|
20
|
+
hasStrapiUrl: !!STRAPI_USER_LIST_API_URL,
|
|
21
|
+
hasStrapiToken: !!STRAPI_API_TOKEN,
|
|
22
|
+
hasAuthId: !!authId,
|
|
23
|
+
timestamp: new Date().toISOString(),
|
|
24
|
+
});
|
|
25
|
+
return NextResponse.json({ error: "Server configuration error or missing authId" }, { status: 500 });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Set CORS headers for the response.
|
|
29
|
+
const headers = new Headers({
|
|
30
|
+
"Access-Control-Allow-Origin": allowedOrigin,
|
|
31
|
+
"Access-Control-Allow-Methods": "GET",
|
|
32
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Fetch the user from Strapi using the authId filter.
|
|
37
|
+
const checkResponse = await fetch(
|
|
38
|
+
`${STRAPI_USER_LIST_API_URL}?filters[authId][$eq]=${encodeURIComponent(authId)}`,
|
|
39
|
+
{
|
|
40
|
+
headers: {
|
|
41
|
+
Authorization: `Bearer ${STRAPI_API_TOKEN}`,
|
|
42
|
+
"Content-Type": "application/json",
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// If Strapi fetch fails, log and return the error status.
|
|
48
|
+
if (!checkResponse.ok) {
|
|
49
|
+
console.error("GET /api/sync-user: Failed to fetch Strapi user", {
|
|
50
|
+
status: checkResponse.status,
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
});
|
|
53
|
+
return NextResponse.json({ error: "Failed to fetch user" }, { status: checkResponse.status, headers });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Parse the Strapi response.
|
|
57
|
+
const checkResult = await checkResponse.json();
|
|
58
|
+
// If a user is found (data array has at least one item), return the user data.
|
|
59
|
+
if (checkResult.data && checkResult.data.length > 0) {
|
|
60
|
+
const existingUser = checkResult.data[0];
|
|
61
|
+
// Return a sanitized version of the user object, excluding sensitive fields.
|
|
62
|
+
return NextResponse.json(
|
|
63
|
+
{
|
|
64
|
+
id: existingUser.id,
|
|
65
|
+
username: existingUser.username,
|
|
66
|
+
email: existingUser.email,
|
|
67
|
+
authId: existingUser.authId,
|
|
68
|
+
businessAdminId: existingUser.businessAdminId,
|
|
69
|
+
userRole: existingUser.userRole,
|
|
70
|
+
isAdmin: existingUser.isAdmin || false,
|
|
71
|
+
firstName: existingUser.firstName,
|
|
72
|
+
lastName: existingUser.lastName,
|
|
73
|
+
businessId: existingUser.businessId,
|
|
74
|
+
dateJoined: existingUser.dateJoined,
|
|
75
|
+
businessOwner: existingUser.businessOwner,
|
|
76
|
+
userStatus: existingUser.userStatus,
|
|
77
|
+
timezone: existingUser.timezone,
|
|
78
|
+
language: existingUser.language,
|
|
79
|
+
isVerified: existingUser.isVerified,
|
|
80
|
+
authProvider: existingUser.authProvider,
|
|
81
|
+
businessTitle: existingUser.businessTitle,
|
|
82
|
+
userTitle: existingUser.userTitle,
|
|
83
|
+
number: existingUser.number,
|
|
84
|
+
address: existingUser.address,
|
|
85
|
+
websiteUrl: existingUser.websiteUrl,
|
|
86
|
+
primaryBusinessColor: existingUser.primaryBusinessColor,
|
|
87
|
+
secondaryBusinessColor: existingUser.secondaryBusinessColor,
|
|
88
|
+
logoImage: existingUser.logoImage,
|
|
89
|
+
},
|
|
90
|
+
{ status: 200, headers }
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
// If no user found, return 404.
|
|
94
|
+
return NextResponse.json({ error: "User not found" }, { status: 404, headers });
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// Catch any unexpected errors, log them, and return 500.
|
|
97
|
+
console.error("GET /api/sync-user: Error:", {
|
|
98
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
99
|
+
timestamp: new Date().toISOString(),
|
|
100
|
+
});
|
|
101
|
+
return NextResponse.json(
|
|
102
|
+
{ error: "Internal server error", details: error instanceof Error ? error.message : "Unknown error" },
|
|
103
|
+
{ status: 500, headers }
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// POST handler for /api/sync-user: Verifies the current Clerk user and checks for existing Strapi user.
|
|
109
|
+
// This seems to be used for post-signup verification rather than creation (creation is handled elsewhere).
|
|
110
|
+
export async function POST(req: NextRequest) {
|
|
111
|
+
// Retrieve the allowed origin for CORS.
|
|
112
|
+
const allowedOrigin = process.env.NEXT_PUBLIC_BASE_URL;
|
|
113
|
+
if (!allowedOrigin) {
|
|
114
|
+
console.error("NEXT_PUBLIC_BASE_URL not configured", { timestamp: new Date().toISOString() });
|
|
115
|
+
return NextResponse.json({ error: "Server configuration error: Missing base URL" }, { status: 500 });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Set CORS headers for POST requests.
|
|
119
|
+
const headers = new Headers({
|
|
120
|
+
"Access-Control-Allow-Origin": allowedOrigin,
|
|
121
|
+
"Access-Control-Allow-Methods": "POST",
|
|
122
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Handle preflight OPTIONS request for CORS.
|
|
126
|
+
if (req.method === "OPTIONS") {
|
|
127
|
+
return new NextResponse(null, { status: 204, headers });
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Get the authenticated user ID from Clerk middleware.
|
|
131
|
+
const { userId } = getAuth(req);
|
|
132
|
+
if (!userId) {
|
|
133
|
+
console.error("No userId found", { timestamp: new Date().toISOString() });
|
|
134
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401, headers });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Generate a unique request ID for logging.
|
|
138
|
+
const requestId = crypto.randomUUID();
|
|
139
|
+
|
|
140
|
+
// Parse the request body (expected to contain authId, email, username).
|
|
141
|
+
let body;
|
|
142
|
+
try {
|
|
143
|
+
body = await req.json();
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.warn("Failed to parse request body", { requestId, error, timestamp: new Date().toISOString() });
|
|
146
|
+
return NextResponse.json({ error: "Invalid request body" }, { status: 400, headers });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Extract required fields from body.
|
|
150
|
+
const { authId, email, username } = body;
|
|
151
|
+
|
|
152
|
+
// Validate required fields; return 400 if missing.
|
|
153
|
+
if (!authId || !email || !username) {
|
|
154
|
+
console.error("Missing required fields", { requestId, body, timestamp: new Date().toISOString() });
|
|
155
|
+
return NextResponse.json({ error: "Missing required fields" }, { status: 400, headers });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Environment variables for integrations.
|
|
159
|
+
const STRAPI_USER_LIST_API_URL = process.env.STRAPI_USER_LIST_API_URL;
|
|
160
|
+
const STRAPI_API_TOKEN = process.env.STRAPI_API_TOKEN;
|
|
161
|
+
const CLERK_SECRET_KEY = process.env.CLERK_SECRET_KEY;
|
|
162
|
+
|
|
163
|
+
// Validate environment variables; return 500 if missing.
|
|
164
|
+
if (!STRAPI_USER_LIST_API_URL || !STRAPI_API_TOKEN || !CLERK_SECRET_KEY) {
|
|
165
|
+
console.error("Missing environment variables", {
|
|
166
|
+
requestId,
|
|
167
|
+
hasStrapiUrl: !!STRAPI_USER_LIST_API_URL,
|
|
168
|
+
hasStrapiToken: !!STRAPI_API_TOKEN,
|
|
169
|
+
hasClerkSecret: !!CLERK_SECRET_KEY,
|
|
170
|
+
timestamp: new Date().toISOString(),
|
|
171
|
+
});
|
|
172
|
+
return NextResponse.json({ error: "Server configuration error" }, { status: 500, headers });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
// Fetch the full Clerk user details using the userId from middleware (with 5s timeout).
|
|
177
|
+
const clerkController = new AbortController();
|
|
178
|
+
const clerkTimeout = setTimeout(() => clerkController.abort(), 5000);
|
|
179
|
+
const clerkResponse = await fetch(`https://api.clerk.dev/v1/users/${userId}`, {
|
|
180
|
+
headers: {
|
|
181
|
+
Authorization: `Bearer ${CLERK_SECRET_KEY}`,
|
|
182
|
+
"Content-Type": "application/json",
|
|
183
|
+
},
|
|
184
|
+
signal: clerkController.signal,
|
|
185
|
+
});
|
|
186
|
+
clearTimeout(clerkTimeout);
|
|
187
|
+
|
|
188
|
+
// If Clerk fetch fails, log and return 500.
|
|
189
|
+
if (!clerkResponse.ok) {
|
|
190
|
+
const errorText = await clerkResponse.text();
|
|
191
|
+
console.error("Failed to fetch Clerk user", {
|
|
192
|
+
requestId,
|
|
193
|
+
status: clerkResponse.status,
|
|
194
|
+
errorText,
|
|
195
|
+
timestamp: new Date().toISOString(),
|
|
196
|
+
});
|
|
197
|
+
return NextResponse.json({ error: "Failed to verify user" }, { status: 500, headers });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Parse Clerk user and ensure an email exists.
|
|
201
|
+
const clerkUser = await clerkResponse.json();
|
|
202
|
+
if (!clerkUser.email_addresses?.[0]?.email_address) {
|
|
203
|
+
console.error("No email found for user", { requestId, userId, timestamp: new Date().toISOString() });
|
|
204
|
+
return NextResponse.json({ error: "User email not found" }, { status: 400, headers });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Fetch Strapi user by authId (with 5s timeout).
|
|
208
|
+
const authIdController = new AbortController();
|
|
209
|
+
const authIdTimeout = setTimeout(() => authIdController.abort(), 5000);
|
|
210
|
+
const authIdResponse = await fetch(
|
|
211
|
+
`${STRAPI_USER_LIST_API_URL}?filters[authId][$eq]=${encodeURIComponent(authId)}`,
|
|
212
|
+
{
|
|
213
|
+
headers: {
|
|
214
|
+
Authorization: `Bearer ${STRAPI_API_TOKEN}`,
|
|
215
|
+
"Content-Type": "application/json",
|
|
216
|
+
},
|
|
217
|
+
signal: authIdController.signal,
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
clearTimeout(authIdTimeout);
|
|
221
|
+
|
|
222
|
+
// If Strapi fetch fails, log and return 500.
|
|
223
|
+
if (!authIdResponse.ok) {
|
|
224
|
+
const errorText = await authIdResponse.text();
|
|
225
|
+
console.error("Failed to fetch Strapi user by authId", {
|
|
226
|
+
requestId,
|
|
227
|
+
status: authIdResponse.status,
|
|
228
|
+
errorText,
|
|
229
|
+
timestamp: new Date().toISOString(),
|
|
230
|
+
});
|
|
231
|
+
return NextResponse.json({ error: "Failed to verify Strapi user" }, { status: 500, headers });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Parse Strapi response.
|
|
235
|
+
const authIdResult = await authIdResponse.json();
|
|
236
|
+
// If user exists, return the sanitized user data (similar to GET).
|
|
237
|
+
if (authIdResult.data && authIdResult.data.length > 0) {
|
|
238
|
+
const existingUser = authIdResult.data[0];
|
|
239
|
+
return NextResponse.json(
|
|
240
|
+
{
|
|
241
|
+
id: existingUser.id,
|
|
242
|
+
username: existingUser.username,
|
|
243
|
+
email: existingUser.email,
|
|
244
|
+
authId: existingUser.authId,
|
|
245
|
+
businessAdminId: existingUser.businessAdminId,
|
|
246
|
+
userRole: existingUser.userRole,
|
|
247
|
+
isAdmin: existingUser.isAdmin || false,
|
|
248
|
+
firstName: existingUser.firstName,
|
|
249
|
+
lastName: existingUser.lastName,
|
|
250
|
+
businessId: existingUser.businessId,
|
|
251
|
+
dateJoined: existingUser.dateJoined,
|
|
252
|
+
businessOwner: existingUser.businessOwner,
|
|
253
|
+
userStatus: existingUser.userStatus,
|
|
254
|
+
timezone: existingUser.timezone,
|
|
255
|
+
language: existingUser.language,
|
|
256
|
+
isVerified: existingUser.isVerified,
|
|
257
|
+
authProvider: existingUser.authProvider,
|
|
258
|
+
businessTitle: existingUser.businessTitle,
|
|
259
|
+
userTitle: existingUser.userTitle,
|
|
260
|
+
number: existingUser.number,
|
|
261
|
+
address: existingUser.address,
|
|
262
|
+
websiteUrl: existingUser.websiteUrl,
|
|
263
|
+
primaryBusinessColor: existingUser.primaryBusinessColor,
|
|
264
|
+
secondaryBusinessColor: existingUser.secondaryBusinessColor,
|
|
265
|
+
logoImage: existingUser.logoImage,
|
|
266
|
+
},
|
|
267
|
+
{ status: 200, headers }
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// If no user found, log warning and return 404.
|
|
272
|
+
console.warn("No Strapi user found for authId", { requestId, authId, timestamp: new Date().toISOString() });
|
|
273
|
+
return NextResponse.json({ error: "User not found in Strapi" }, { status: 404, headers });
|
|
274
|
+
} catch (error) {
|
|
275
|
+
// Catch any errors (e.g., timeouts, network issues), log, and return 500.
|
|
276
|
+
console.error("Error verifying or syncing user", {
|
|
277
|
+
requestId,
|
|
278
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
279
|
+
timestamp: new Date().toISOString(),
|
|
280
|
+
});
|
|
281
|
+
return NextResponse.json({ error: "Internal server error" }, { status: 500, headers });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Next.js API route configuration: Enable body parsing for JSON requests.
|
|
286
|
+
export const config = {
|
|
287
|
+
api: {
|
|
288
|
+
bodyParser: true,
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// Helper function to determine allowedOrigin based on environment
|
|
293
|
+
function getAllowedOrigin(): string {
|
|
294
|
+
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
|
|
295
|
+
|
|
296
|
+
if (baseUrl) {
|
|
297
|
+
return baseUrl;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (process.env.NODE_ENV === 'development') {
|
|
301
|
+
return 'http://localhost:3000'; // Or '*' for even more flexibility in dev
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// In production, fail explicitly if not set (prevents accidental '*' usage)
|
|
305
|
+
throw new Error('NEXT_PUBLIC_BASE_URL must be set in production');
|
|
306
|
+
}
|