1
1
import { NextRequest , NextResponse } from "next/server" ;
2
- import Component from "@/models/components.model" ;
2
+ import Component from "@/models/components.model" ;
3
3
import { connectDb } from "@/config/dbConfig/dbConfig" ;
4
4
import rateLimit from "@/config/ratelimit/ratelimit" ;
5
+ import { v2 as cloudinary } from 'cloudinary' ;
6
+ import { uploadImage } from "@/config/uploadImage/upload" ;
5
7
6
- type component = {
8
+ type Component = {
7
9
code : string ;
8
10
title : string ;
9
11
tags : string [ ] ;
10
12
description : string ;
11
13
author : string ;
14
+ previewUrl : string ;
12
15
status : string ;
13
16
installationGuide : string | null ;
14
17
usageGuide : string | null ;
15
18
props : string | null ;
16
19
}
17
20
21
+ cloudinary . config ( {
22
+ cloud_name : process . env . CLOUDINARY_CLOUD_NAME ,
23
+ api_key : process . env . CLOUDINARY_API_KEY ,
24
+ api_secret : process . env . CLOUDINARY_API_SECRET ,
25
+ secure : true ,
26
+ } ) ;
18
27
19
- export async function POST ( req :NextRequest , res : NextResponse ) {
28
+ export async function POST ( req : NextRequest ) {
20
29
try {
21
-
22
- if ( rateLimit ( req ) === false ) {
23
- return NextResponse . json ( { message :"Too many request try after some time" } , { status :429 } ) ;
30
+ if ( rateLimit ( req ) === false ) {
31
+ return NextResponse . json ( { message : "Too many requests, try after some time" } , { status : 429 } ) ;
24
32
}
25
33
26
- const reqBody = await req . json ( ) ;
27
- if ( ! reqBody . code || ! reqBody . title || ! reqBody . tags || ! reqBody . description || ! reqBody . author ) {
28
- return NextResponse . json ( { message :"all fields are required" } , { status :400 } ) ;
34
+ // Parse FormData instead of JSON
35
+ const formData = await req . formData ( ) ;
36
+
37
+ // Extract fields from FormData
38
+ const code = formData . get ( 'code' ) as string ;
39
+ const title = formData . get ( 'title' ) as string ;
40
+ const tags = formData . get ( 'tags' ) as string ;
41
+ const description = formData . get ( 'description' ) as string ;
42
+ const author = formData . get ( 'author' ) as string ;
43
+ const installationGuide = formData . get ( 'installationGuide' ) as string ;
44
+ const usageGuide = formData . get ( 'usageGuide' ) as string ;
45
+ const props = formData . get ( 'props' ) as string ;
46
+ const previewImage = formData . get ( 'previewImage' ) as File | null ;
47
+
48
+ // Validation
49
+ if ( ! code || ! title || ! tags || ! description || ! author ) {
50
+ return NextResponse . json ( { message : "All fields are required" } , { status : 400 } ) ;
29
51
}
30
52
31
- //check if code is not malicous
32
- if ( reqBody . code . length > 60 && reqBody . installationGuide . length <= 0 && reqBody . usageGuide . length <= 0 ) {
33
- return NextResponse . json ( { message :"code is long so installion guide and usage guide is required" } , { status :400 } ) ;
53
+ // Check if code is not malicious
54
+ if ( code . length > 60 && ( ! installationGuide || ! usageGuide ) ) {
55
+ return NextResponse . json ( {
56
+ message : "Code is long so installation guide and usage guide are required"
57
+ } , { status : 400 } ) ;
34
58
}
35
59
36
- const newComponent :component = {
37
- code :reqBody . code ,
38
- title :reqBody . title ,
39
- tags :reqBody . tags ,
40
- description :reqBody . description ,
41
- author :reqBody . author ,
42
- status :"pending" ,
43
- installationGuide :reqBody . installationGuide || null ,
44
- usageGuide :reqBody . usageGuide || null ,
45
- props :reqBody . props || null
60
+ let avatarUrl = '' ;
61
+
62
+ // Handle image upload if present
63
+ if ( previewImage ) {
64
+ // Validate file type
65
+ if ( ! previewImage . type . startsWith ( 'image/' ) ) {
66
+ return NextResponse . json ( {
67
+ message : "Invalid file type. Only images are allowed"
68
+ } , { status : 400 } ) ;
69
+ }
70
+
71
+ // Convert File to Buffer
72
+ const bytes = await previewImage . arrayBuffer ( ) ;
73
+ const buffer = Buffer . from ( bytes ) ;
74
+
75
+ // Upload to Cloudinary
76
+ try {
77
+ avatarUrl = await uploadImage ( buffer ) as string ;
78
+ console . log ( "Uploaded avatar URL:" , avatarUrl ) ;
79
+ } catch ( error ) {
80
+ console . error ( "Image upload failed:" , error ) ;
81
+ return NextResponse . json ( {
82
+ message : "Failed to upload image"
83
+ } , { status : 500 } ) ;
84
+ }
46
85
}
86
+
87
+ const newComponent : Component = {
88
+ code,
89
+ title,
90
+ tags : tags . split ( ',' ) . map ( tag => tag . trim ( ) ) , // Convert comma-separated string to array
91
+ description,
92
+ author,
93
+ previewUrl : avatarUrl ,
94
+ status : "pending" ,
95
+ installationGuide : installationGuide || null ,
96
+ usageGuide : usageGuide || null ,
97
+ props : props || null
98
+ } ;
99
+
100
+ console . log ( "New component:" , newComponent . previewUrl ) ;
47
101
48
102
await connectDb ( ) ;
49
- //save to db
50
103
const savedComponent = await Component . create ( newComponent ) ;
51
104
52
- return NextResponse . json ( { message :"code is under review . it will take less than 24hr to review " , savedComponent} , { status :201 } ) ;
105
+ return NextResponse . json ( {
106
+ message : "Code is under review. It will take less than 24hr to review" ,
107
+ savedComponent
108
+ } , { status : 201 } ) ;
53
109
54
-
55
- } catch ( error :any ) {
56
- return NextResponse . json ( { message :error . message } , { status :500 } ) ;
57
-
110
+ } catch ( error : any ) {
111
+ console . error ( "Error in POST handler:" , error ) ;
112
+ return NextResponse . json ( {
113
+ message : "Internal server error"
114
+ } , { status : 500 } ) ;
58
115
}
59
116
}
0 commit comments