shipd 0.1.3 → 0.2.0
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/base-package/app/globals.css +126 -0
- package/base-package/app/layout.tsx +53 -0
- package/base-package/app/page.tsx +15 -0
- package/base-package/base.config.json +57 -0
- package/base-package/components/ui/avatar.tsx +53 -0
- package/base-package/components/ui/badge.tsx +46 -0
- package/base-package/components/ui/button.tsx +59 -0
- package/base-package/components/ui/card.tsx +92 -0
- package/base-package/components/ui/chart.tsx +353 -0
- package/base-package/components/ui/checkbox.tsx +32 -0
- package/base-package/components/ui/dialog.tsx +135 -0
- package/base-package/components/ui/dropdown-menu.tsx +257 -0
- package/base-package/components/ui/form.tsx +167 -0
- package/base-package/components/ui/input.tsx +21 -0
- package/base-package/components/ui/label.tsx +24 -0
- package/base-package/components/ui/progress.tsx +31 -0
- package/base-package/components/ui/resizable.tsx +56 -0
- package/base-package/components/ui/select.tsx +185 -0
- package/base-package/components/ui/separator.tsx +28 -0
- package/base-package/components/ui/sheet.tsx +139 -0
- package/base-package/components/ui/skeleton.tsx +13 -0
- package/base-package/components/ui/sonner.tsx +25 -0
- package/base-package/components/ui/switch.tsx +31 -0
- package/base-package/components/ui/tabs.tsx +66 -0
- package/base-package/components/ui/textarea.tsx +18 -0
- package/base-package/components/ui/toggle-group.tsx +73 -0
- package/base-package/components/ui/toggle.tsx +47 -0
- package/base-package/components/ui/tooltip.tsx +61 -0
- package/base-package/components.json +21 -0
- package/base-package/eslint.config.mjs +16 -0
- package/base-package/lib/utils.ts +6 -0
- package/base-package/middleware.ts +12 -0
- package/base-package/next.config.ts +27 -0
- package/base-package/package.json +49 -0
- package/base-package/postcss.config.mjs +5 -0
- package/base-package/public/favicon.svg +4 -0
- package/base-package/tailwind.config.ts +89 -0
- package/base-package/tsconfig.json +27 -0
- package/dist/index.js +1858 -956
- package/docs-template/README.md +74 -0
- package/features/ai-chat/README.md +316 -0
- package/features/ai-chat/app/api/chat/route.ts +16 -0
- package/features/ai-chat/app/dashboard/_components/chatbot.tsx +39 -0
- package/features/ai-chat/app/dashboard/chat/page.tsx +73 -0
- package/features/ai-chat/feature.config.json +22 -0
- package/features/analytics/README.md +364 -0
- package/features/analytics/feature.config.json +20 -0
- package/features/analytics/lib/posthog.ts +36 -0
- package/features/auth/README.md +409 -0
- package/features/auth/app/api/auth/[...all]/route.ts +4 -0
- package/features/auth/app/dashboard/layout.tsx +15 -0
- package/features/auth/app/dashboard/page.tsx +140 -0
- package/features/auth/app/sign-in/page.tsx +228 -0
- package/features/auth/app/sign-up/page.tsx +243 -0
- package/features/auth/auth-schema.ts +47 -0
- package/features/auth/components/auth/setup-instructions.tsx +123 -0
- package/features/auth/feature.config.json +33 -0
- package/features/auth/lib/auth-client.ts +8 -0
- package/features/auth/lib/auth.ts +295 -0
- package/features/auth/lib/email-stub.ts +55 -0
- package/features/auth/lib/email.ts +47 -0
- package/features/auth/middleware.patch.ts +43 -0
- package/features/database/README.md +312 -0
- package/features/database/db/drizzle.ts +48 -0
- package/features/database/db/schema.ts +21 -0
- package/features/database/drizzle.config.ts +13 -0
- package/features/database/feature.config.json +30 -0
- package/features/email/README.md +341 -0
- package/features/email/emails/components/layout.tsx +181 -0
- package/features/email/emails/password-reset.tsx +67 -0
- package/features/email/emails/payment-failed.tsx +167 -0
- package/features/email/emails/subscription-confirmation.tsx +129 -0
- package/features/email/emails/welcome.tsx +100 -0
- package/features/email/feature.config.json +22 -0
- package/features/email/lib/email.ts +118 -0
- package/features/file-upload/README.md +329 -0
- package/features/file-upload/app/api/upload-image/route.ts +64 -0
- package/features/file-upload/app/dashboard/upload/page.tsx +324 -0
- package/features/file-upload/feature.config.json +23 -0
- package/features/file-upload/lib/upload-image.ts +28 -0
- package/features/marketing-landing/README.md +333 -0
- package/features/marketing-landing/app/page.tsx +25 -0
- package/features/marketing-landing/components/homepage/cli-workflow-section.tsx +231 -0
- package/features/marketing-landing/components/homepage/features-section.tsx +152 -0
- package/features/marketing-landing/components/homepage/footer.tsx +53 -0
- package/features/marketing-landing/components/homepage/hero-section.tsx +112 -0
- package/features/marketing-landing/components/homepage/integrations.tsx +124 -0
- package/features/marketing-landing/components/homepage/navigation.tsx +116 -0
- package/features/marketing-landing/components/homepage/news-section.tsx +82 -0
- package/features/marketing-landing/components/homepage/pricing-section.tsx +98 -0
- package/features/marketing-landing/components/homepage/testimonials-section.tsx +34 -0
- package/features/marketing-landing/components/logos/BetterAuth.tsx +21 -0
- package/features/marketing-landing/components/logos/NeonPostgres.tsx +41 -0
- package/features/marketing-landing/components/logos/Nextjs.tsx +72 -0
- package/features/marketing-landing/components/logos/Polar.tsx +7 -0
- package/features/marketing-landing/components/logos/TailwindCSS.tsx +27 -0
- package/features/marketing-landing/components/logos/index.ts +6 -0
- package/features/marketing-landing/components/logos/shadcnui.tsx +8 -0
- package/features/marketing-landing/feature.config.json +23 -0
- package/features/payments/README.md +375 -0
- package/features/payments/app/api/subscription/route.ts +25 -0
- package/features/payments/app/dashboard/payment/_components/manage-subscription.tsx +22 -0
- package/features/payments/app/dashboard/payment/page.tsx +126 -0
- package/features/payments/app/success/page.tsx +123 -0
- package/features/payments/feature.config.json +31 -0
- package/features/payments/lib/polar-products.ts +49 -0
- package/features/payments/lib/subscription.ts +148 -0
- package/features/payments/payments-schema.ts +30 -0
- package/features/seo/README.md +302 -0
- package/features/seo/app/blog/[slug]/page.tsx +314 -0
- package/features/seo/app/blog/page.tsx +107 -0
- package/features/seo/app/robots.txt +13 -0
- package/features/seo/app/sitemap.ts +70 -0
- package/features/seo/feature.config.json +19 -0
- package/features/seo/lib/seo-utils.ts +163 -0
- package/package.json +3 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# File Upload Module - Integration Guide
|
|
2
|
+
|
|
3
|
+
**Module Version:** 1.0.0
|
|
4
|
+
**Last Updated:** 2025-12-22
|
|
5
|
+
**Standalone:** ✅ Yes (can work independently)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This module adds file upload functionality using Cloudflare R2 (S3-compatible object storage). It includes a drag-and-drop upload interface, progress tracking, and image preview.
|
|
12
|
+
|
|
13
|
+
**Key Features:**
|
|
14
|
+
- Cloudflare R2 integration (S3-compatible)
|
|
15
|
+
- Drag-and-drop file upload
|
|
16
|
+
- Image upload with validation
|
|
17
|
+
- Progress tracking
|
|
18
|
+
- File size validation (5MB max)
|
|
19
|
+
- Image preview gallery
|
|
20
|
+
- Public URL generation
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Files Added
|
|
25
|
+
|
|
26
|
+
### Pages/Routes
|
|
27
|
+
- `app/dashboard/upload/page.tsx` - File upload interface with drag-and-drop
|
|
28
|
+
|
|
29
|
+
### API Routes
|
|
30
|
+
- `app/api/upload-image/route.ts` - Image upload API endpoint
|
|
31
|
+
|
|
32
|
+
### Utilities/Libraries
|
|
33
|
+
- `lib/upload-image.ts` - R2 upload utility functions
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Dependencies
|
|
38
|
+
|
|
39
|
+
### Package Dependencies
|
|
40
|
+
The following packages will be added to `package.json`:
|
|
41
|
+
- `@aws-sdk/client-s3@^3.800.0` - AWS SDK for S3-compatible storage (R2)
|
|
42
|
+
|
|
43
|
+
### Required Modules
|
|
44
|
+
- None - File Upload module is standalone
|
|
45
|
+
|
|
46
|
+
### Optional Integration
|
|
47
|
+
- **Auth Module** - For protecting upload routes (works without it, but uploads should be protected)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Environment Variables
|
|
52
|
+
|
|
53
|
+
Add these to your `.env.local`:
|
|
54
|
+
|
|
55
|
+
```env
|
|
56
|
+
# File Upload (Cloudflare R2)
|
|
57
|
+
R2_UPLOAD_IMAGE_ACCESS_KEY_ID="your-r2-access-key-id"
|
|
58
|
+
R2_UPLOAD_IMAGE_SECRET_ACCESS_KEY="your-r2-secret-access-key"
|
|
59
|
+
CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
|
|
60
|
+
R2_UPLOAD_IMAGE_BUCKET_NAME="your-bucket-name"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Required Variables:**
|
|
64
|
+
- `R2_UPLOAD_IMAGE_ACCESS_KEY_ID` - R2 access key ID
|
|
65
|
+
- `R2_UPLOAD_IMAGE_SECRET_ACCESS_KEY` - R2 secret access key
|
|
66
|
+
- `CLOUDFLARE_ACCOUNT_ID` - Your Cloudflare account ID
|
|
67
|
+
- `R2_UPLOAD_IMAGE_BUCKET_NAME` - Your R2 bucket name
|
|
68
|
+
|
|
69
|
+
**Where to get them:**
|
|
70
|
+
- **Cloudflare R2**: [dash.cloudflare.com](https://dash.cloudflare.com) - Create R2 bucket and API tokens
|
|
71
|
+
- Create an R2 bucket in Cloudflare dashboard
|
|
72
|
+
- Generate API tokens with read/write permissions
|
|
73
|
+
- Get account ID from Cloudflare dashboard
|
|
74
|
+
|
|
75
|
+
**Note:** You'll also need to configure a public domain for your R2 bucket to generate public URLs. Update `lib/upload-image.ts` with your public R2 domain.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Manual Integration Steps
|
|
80
|
+
|
|
81
|
+
If you're appending this module to an existing project, follow these steps:
|
|
82
|
+
|
|
83
|
+
### Step 1: Install Dependencies
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install
|
|
87
|
+
# or
|
|
88
|
+
pnpm install
|
|
89
|
+
# or
|
|
90
|
+
yarn install
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The append command automatically adds missing dependencies to `package.json`, but you need to install them.
|
|
94
|
+
|
|
95
|
+
### Step 2: Set Up Cloudflare R2
|
|
96
|
+
|
|
97
|
+
1. Create a Cloudflare account (if you don't have one)
|
|
98
|
+
2. Navigate to R2 in the Cloudflare dashboard
|
|
99
|
+
3. Create a new R2 bucket
|
|
100
|
+
4. Generate API tokens with read/write permissions
|
|
101
|
+
5. Get your account ID from the dashboard
|
|
102
|
+
|
|
103
|
+
### Step 3: Configure Public Domain (Optional)
|
|
104
|
+
|
|
105
|
+
To generate public URLs, you need to configure a custom domain for your R2 bucket:
|
|
106
|
+
|
|
107
|
+
1. In R2 dashboard, go to your bucket settings
|
|
108
|
+
2. Configure a custom domain or use R2.dev domain
|
|
109
|
+
3. Update `lib/upload-image.ts` with your public domain:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const publicUrl = `https://your-custom-domain.com/${key}`;
|
|
113
|
+
// or
|
|
114
|
+
const publicUrl = `https://pub-xxxxx.r2.dev/${key}`;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Step 4: Add Environment Variables
|
|
118
|
+
|
|
119
|
+
1. Copy `.env.example` to `.env.local` (if not exists)
|
|
120
|
+
2. Add all required R2 environment variables
|
|
121
|
+
3. Restart dev server after adding env vars
|
|
122
|
+
|
|
123
|
+
### Step 5: Verify Installation
|
|
124
|
+
|
|
125
|
+
1. Check that `app/api/upload-image/route.ts` exists
|
|
126
|
+
2. Check that `app/dashboard/upload/page.tsx` exists
|
|
127
|
+
3. Check that `lib/upload-image.ts` exists
|
|
128
|
+
4. Start your dev server: `npm run dev`
|
|
129
|
+
5. Visit `http://localhost:3000/dashboard/upload` to test uploads
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Usage Examples
|
|
134
|
+
|
|
135
|
+
### Using the Upload Page
|
|
136
|
+
|
|
137
|
+
1. Navigate to `/dashboard/upload`
|
|
138
|
+
2. Drag and drop images or click to select
|
|
139
|
+
3. Watch upload progress
|
|
140
|
+
4. View uploaded images in the gallery
|
|
141
|
+
5. Copy image URLs or open in new tab
|
|
142
|
+
|
|
143
|
+
### Using Upload Function Programmatically
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { uploadImageAssets } from "@/lib/upload-image";
|
|
147
|
+
|
|
148
|
+
// Upload a file buffer
|
|
149
|
+
const buffer = Buffer.from(fileData);
|
|
150
|
+
const filename = "my-image.png";
|
|
151
|
+
const url = await uploadImageAssets(buffer, filename);
|
|
152
|
+
console.log("Uploaded to:", url);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Customizing Upload Limits
|
|
156
|
+
|
|
157
|
+
Edit `app/api/upload-image/route.ts` to change limits:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// Change max file size (default: 10MB)
|
|
161
|
+
const maxSizeInBytes = 20 * 1024 * 1024; // 20MB
|
|
162
|
+
|
|
163
|
+
// Change allowed MIME types
|
|
164
|
+
const allowedMimeTypes = [
|
|
165
|
+
"image/jpeg",
|
|
166
|
+
"image/png",
|
|
167
|
+
// Add more types
|
|
168
|
+
];
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Customization
|
|
174
|
+
|
|
175
|
+
### Styling
|
|
176
|
+
- Upload UI uses Tailwind CSS classes
|
|
177
|
+
- Customize colors in `tailwind.config.ts`
|
|
178
|
+
- Modify upload area styles in `app/dashboard/upload/page.tsx`
|
|
179
|
+
|
|
180
|
+
### Configuration
|
|
181
|
+
- File size limits in `app/api/upload-image/route.ts`
|
|
182
|
+
- Allowed file types in `app/api/upload-image/route.ts`
|
|
183
|
+
- Public URL generation in `lib/upload-image.ts`
|
|
184
|
+
|
|
185
|
+
### Features
|
|
186
|
+
- Drag-and-drop is built-in
|
|
187
|
+
- Progress tracking is automatic
|
|
188
|
+
- Image preview gallery is included
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Integration Points
|
|
193
|
+
|
|
194
|
+
### Files That May Need Manual Updates
|
|
195
|
+
|
|
196
|
+
**lib/upload-image.ts**:
|
|
197
|
+
- Update public URL domain to match your R2 bucket configuration
|
|
198
|
+
- Customize bucket settings if needed
|
|
199
|
+
|
|
200
|
+
**app/api/upload-image/route.ts**:
|
|
201
|
+
- Adjust file size limits
|
|
202
|
+
- Modify allowed file types
|
|
203
|
+
- Add authentication checks if needed
|
|
204
|
+
|
|
205
|
+
**Middleware** (if auth module installed):
|
|
206
|
+
- Upload routes should be protected
|
|
207
|
+
- Add `/dashboard/upload` to protected routes if needed
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Troubleshooting
|
|
212
|
+
|
|
213
|
+
### Common Issues
|
|
214
|
+
|
|
215
|
+
**Issue:** "R2_UPLOAD_IMAGE_ACCESS_KEY_ID is not defined" error
|
|
216
|
+
**Solution:**
|
|
217
|
+
- Add all R2 environment variables to `.env.local`
|
|
218
|
+
- Get credentials from Cloudflare R2 dashboard
|
|
219
|
+
- Restart dev server after adding env vars
|
|
220
|
+
|
|
221
|
+
**Issue:** Upload fails with "Access Denied"
|
|
222
|
+
**Solution:**
|
|
223
|
+
- Verify API tokens have correct permissions
|
|
224
|
+
- Check bucket name is correct
|
|
225
|
+
- Ensure account ID is correct
|
|
226
|
+
|
|
227
|
+
**Issue:** Public URLs not working
|
|
228
|
+
**Solution:**
|
|
229
|
+
- Configure public domain for R2 bucket
|
|
230
|
+
- Update `lib/upload-image.ts` with correct public domain
|
|
231
|
+
- Ensure bucket has public read access
|
|
232
|
+
|
|
233
|
+
**Issue:** "File too large" error
|
|
234
|
+
**Solution:**
|
|
235
|
+
- Check file size limits in `app/api/upload-image/route.ts`
|
|
236
|
+
- Adjust `maxSizeInBytes` if needed
|
|
237
|
+
- Client-side validation also checks 5MB limit
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Next Steps
|
|
242
|
+
|
|
243
|
+
After installing this module:
|
|
244
|
+
|
|
245
|
+
1. Set up Cloudflare R2 bucket
|
|
246
|
+
2. Generate API tokens
|
|
247
|
+
3. Add environment variables to `.env.local`
|
|
248
|
+
4. Configure public domain for bucket
|
|
249
|
+
5. Update public URL in `lib/upload-image.ts`
|
|
250
|
+
6. Test upload functionality
|
|
251
|
+
7. Add authentication if needed
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Related Modules
|
|
256
|
+
|
|
257
|
+
This module works well with:
|
|
258
|
+
- **Auth Module** - For protecting upload routes
|
|
259
|
+
|
|
260
|
+
**Note:** File Upload module is optional and standalone. No other modules are required.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Module Status
|
|
265
|
+
|
|
266
|
+
✅ **Standalone Package** - Can be installed independently
|
|
267
|
+
✅ **Drag & Drop** - Built-in drag-and-drop interface
|
|
268
|
+
✅ **Progress Tracking** - Real-time upload progress
|
|
269
|
+
✅ **Image Preview** - Gallery of uploaded images
|
|
270
|
+
✅ **Well Documented** - Comprehensive integration guide
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## AI Integration Prompt
|
|
275
|
+
|
|
276
|
+
**For AI Assistants:** Use this prompt to understand and integrate the File Upload module into an existing Next.js application.
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
The File Upload module has been appended to this Next.js project. Your task is to ensure it's properly integrated and functional.
|
|
280
|
+
|
|
281
|
+
**Installed Packages:**
|
|
282
|
+
- @aws-sdk/client-s3@^3.800.0 - AWS SDK for S3-compatible storage (Cloudflare R2)
|
|
283
|
+
|
|
284
|
+
**Files Added:**
|
|
285
|
+
- app/api/upload-image/route.ts - API route for handling image uploads (POST handler)
|
|
286
|
+
- app/dashboard/upload/page.tsx - File upload interface with drag-and-drop
|
|
287
|
+
- lib/upload-image.ts - R2 upload utility functions
|
|
288
|
+
|
|
289
|
+
**Environment Variables Required:**
|
|
290
|
+
- R2_UPLOAD_IMAGE_ACCESS_KEY_ID - Cloudflare R2 access key ID
|
|
291
|
+
- R2_UPLOAD_IMAGE_SECRET_ACCESS_KEY - Cloudflare R2 secret access key
|
|
292
|
+
- CLOUDFLARE_ACCOUNT_ID - Cloudflare account ID
|
|
293
|
+
- R2_UPLOAD_IMAGE_BUCKET_NAME - R2 bucket name
|
|
294
|
+
|
|
295
|
+
**Integration Steps:**
|
|
296
|
+
1. Verify app/api/upload-image/route.ts exists and exports POST handler
|
|
297
|
+
2. Check that upload page exists: app/dashboard/upload/page.tsx
|
|
298
|
+
3. Verify upload utility exists: lib/upload-image.ts
|
|
299
|
+
4. Ensure all R2 environment variables are set in .env.local
|
|
300
|
+
5. Test upload API: POST multipart/form-data with file to /api/upload-image
|
|
301
|
+
6. Test upload page: Visit /dashboard/upload
|
|
302
|
+
7. If auth module installed: Verify upload routes are protected
|
|
303
|
+
|
|
304
|
+
**Key Integration Points:**
|
|
305
|
+
- API route: Handles multipart/form-data, validates file type/size, uploads to R2
|
|
306
|
+
- File validation: Checks MIME type (image/jpeg, image/png, image/webp) and size (max 10MB)
|
|
307
|
+
- R2 client: Uses S3Client from @aws-sdk/client-s3 with R2 endpoint
|
|
308
|
+
- Public URLs: Generates public URLs for uploaded images (requires R2 public domain)
|
|
309
|
+
- Upload UI: Drag-and-drop interface with progress tracking and image preview gallery
|
|
310
|
+
|
|
311
|
+
**Dependencies:**
|
|
312
|
+
- OPTIONAL: Auth module (for protecting upload routes)
|
|
313
|
+
- No hard dependencies on other Shipd modules
|
|
314
|
+
|
|
315
|
+
**Common Issues to Check:**
|
|
316
|
+
- If "R2_UPLOAD_IMAGE_ACCESS_KEY_ID is not defined": Add all R2 env vars to .env.local
|
|
317
|
+
- If upload fails with "Access Denied": Verify R2 API tokens have correct permissions
|
|
318
|
+
- If public URLs not working: Configure public domain for R2 bucket and update lib/upload-image.ts
|
|
319
|
+
- If "File too large" error: Check file size limits in route.ts (default: 10MB)
|
|
320
|
+
|
|
321
|
+
**Next Steps After Integration:**
|
|
322
|
+
- Set up Cloudflare R2 bucket
|
|
323
|
+
- Generate R2 API tokens with read/write permissions
|
|
324
|
+
- Add all R2 environment variables to .env.local
|
|
325
|
+
- Configure public domain for bucket in Cloudflare dashboard
|
|
326
|
+
- Update public URL domain in lib/upload-image.ts
|
|
327
|
+
- Test upload functionality at /dashboard/upload
|
|
328
|
+
- Add authentication checks if needed
|
|
329
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { uploadImageAssets } from "@/lib/upload-image";
|
|
2
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
3
|
+
|
|
4
|
+
export const config = {
|
|
5
|
+
api: { bodyParser: false }, // Disable default body parsing
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export async function POST(req: NextRequest) {
|
|
9
|
+
try {
|
|
10
|
+
// Parse the form data
|
|
11
|
+
const formData = await req.formData();
|
|
12
|
+
const file = formData.get("file") as File | null;
|
|
13
|
+
|
|
14
|
+
if (!file) {
|
|
15
|
+
return NextResponse.json({ error: "No file provided" }, { status: 400 });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Validate MIME type - only allow image files
|
|
19
|
+
const allowedMimeTypes = [
|
|
20
|
+
"image/jpeg",
|
|
21
|
+
"image/jpg",
|
|
22
|
+
"image/png",
|
|
23
|
+
"image/gif",
|
|
24
|
+
"image/webp",
|
|
25
|
+
"image/svg+xml",
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
if (!allowedMimeTypes.includes(file.type)) {
|
|
29
|
+
return NextResponse.json(
|
|
30
|
+
{ error: "Invalid file type. Only image files are allowed." },
|
|
31
|
+
{ status: 400 },
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Validate file size - limit to 10MB
|
|
36
|
+
const maxSizeInBytes = 10 * 1024 * 1024; // 10MB
|
|
37
|
+
if (file.size > maxSizeInBytes) {
|
|
38
|
+
return NextResponse.json(
|
|
39
|
+
{ error: "File too large. Maximum size allowed is 10MB." },
|
|
40
|
+
{ status: 400 },
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Convert file to buffer
|
|
45
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
46
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
47
|
+
|
|
48
|
+
// Generate a unique filename with original extension
|
|
49
|
+
const fileExt = file.name.split(".").pop() || "";
|
|
50
|
+
const timestamp = Date.now();
|
|
51
|
+
const filename = `upload-${timestamp}.${fileExt || "png"}`;
|
|
52
|
+
|
|
53
|
+
// Upload the file
|
|
54
|
+
const url = await uploadImageAssets(buffer, filename);
|
|
55
|
+
|
|
56
|
+
return NextResponse.json({ url });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("Upload error:", error);
|
|
59
|
+
return NextResponse.json(
|
|
60
|
+
{ error: "Failed to process upload" },
|
|
61
|
+
{ status: 500 },
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|