shipd 0.1.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/LICENSE +21 -0
- package/README.md +205 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1366 -0
- package/docs-template/README.md +255 -0
- package/docs-template/[slug]/[subslug]/page.tsx +1242 -0
- package/docs-template/[slug]/page.tsx +422 -0
- package/docs-template/api/page.tsx +47 -0
- package/docs-template/components/docs/docs-category-page.tsx +162 -0
- package/docs-template/components/docs/docs-code-card.tsx +135 -0
- package/docs-template/components/docs/docs-header.tsx +69 -0
- package/docs-template/components/docs/docs-nav.ts +95 -0
- package/docs-template/components/docs/docs-sidebar.tsx +112 -0
- package/docs-template/components/docs/docs-toc.tsx +38 -0
- package/docs-template/components/ui/badge.tsx +47 -0
- package/docs-template/components/ui/button.tsx +60 -0
- package/docs-template/components/ui/card.tsx +93 -0
- package/docs-template/components/ui/sheet.tsx +140 -0
- package/docs-template/documentation/page.tsx +80 -0
- package/docs-template/layout.tsx +27 -0
- package/docs-template/lib/utils.ts +7 -0
- package/docs-template/page.tsx +360 -0
- package/package.json +66 -0
- package/template/.env.example +45 -0
- package/template/README.md +239 -0
- package/template/app/api/auth/[...all]/route.ts +4 -0
- package/template/app/api/chat/route.ts +16 -0
- package/template/app/api/subscription/route.ts +25 -0
- package/template/app/api/upload-image/route.ts +64 -0
- package/template/app/blog/[slug]/page.tsx +314 -0
- package/template/app/blog/page.tsx +107 -0
- package/template/app/dashboard/_components/chart-interactive.tsx +289 -0
- package/template/app/dashboard/_components/chatbot.tsx +39 -0
- package/template/app/dashboard/_components/mode-toggle.tsx +46 -0
- package/template/app/dashboard/_components/navbar.tsx +84 -0
- package/template/app/dashboard/_components/section-cards.tsx +102 -0
- package/template/app/dashboard/_components/sidebar.tsx +90 -0
- package/template/app/dashboard/_components/subscribe-button.tsx +49 -0
- package/template/app/dashboard/billing/page.tsx +277 -0
- package/template/app/dashboard/chat/page.tsx +73 -0
- package/template/app/dashboard/cli/page.tsx +260 -0
- package/template/app/dashboard/layout.tsx +24 -0
- package/template/app/dashboard/page.tsx +216 -0
- package/template/app/dashboard/payment/_components/manage-subscription.tsx +22 -0
- package/template/app/dashboard/payment/page.tsx +126 -0
- package/template/app/dashboard/settings/page.tsx +613 -0
- package/template/app/dashboard/upload/page.tsx +324 -0
- package/template/app/error.tsx +78 -0
- package/template/app/favicon.ico +0 -0
- package/template/app/globals.css +126 -0
- package/template/app/layout.tsx +135 -0
- package/template/app/not-found.tsx +45 -0
- package/template/app/page.tsx +28 -0
- package/template/app/pricing/_component/pricing-table.tsx +276 -0
- package/template/app/pricing/page.tsx +23 -0
- package/template/app/privacy-policy/page.tsx +280 -0
- package/template/app/robots.txt +12 -0
- package/template/app/sign-in/page.tsx +228 -0
- package/template/app/sign-up/page.tsx +243 -0
- package/template/app/sitemap.ts +62 -0
- package/template/app/success/page.tsx +123 -0
- package/template/app/terms-of-service/page.tsx +212 -0
- package/template/auth-schema.ts +47 -0
- package/template/components/homepage/cli-workflow-section.tsx +138 -0
- package/template/components/homepage/features-section.tsx +150 -0
- package/template/components/homepage/footer.tsx +53 -0
- package/template/components/homepage/hero-section.tsx +112 -0
- package/template/components/homepage/integrations.tsx +124 -0
- package/template/components/homepage/navigation.tsx +116 -0
- package/template/components/homepage/news-section.tsx +82 -0
- package/template/components/homepage/testimonials-section.tsx +34 -0
- package/template/components/logos/BetterAuth.tsx +21 -0
- package/template/components/logos/NeonPostgres.tsx +41 -0
- package/template/components/logos/Nextjs.tsx +72 -0
- package/template/components/logos/Polar.tsx +7 -0
- package/template/components/logos/TailwindCSS.tsx +27 -0
- package/template/components/logos/index.ts +6 -0
- package/template/components/logos/shadcnui.tsx +8 -0
- package/template/components/provider.tsx +8 -0
- package/template/components/ui/avatar.tsx +53 -0
- package/template/components/ui/badge.tsx +46 -0
- package/template/components/ui/button.tsx +59 -0
- package/template/components/ui/card.tsx +92 -0
- package/template/components/ui/chart.tsx +353 -0
- package/template/components/ui/checkbox.tsx +32 -0
- package/template/components/ui/dialog.tsx +135 -0
- package/template/components/ui/dropdown-menu.tsx +257 -0
- package/template/components/ui/form.tsx +167 -0
- package/template/components/ui/input.tsx +21 -0
- package/template/components/ui/label.tsx +24 -0
- package/template/components/ui/progress.tsx +31 -0
- package/template/components/ui/resizable.tsx +56 -0
- package/template/components/ui/select.tsx +185 -0
- package/template/components/ui/separator.tsx +28 -0
- package/template/components/ui/sheet.tsx +139 -0
- package/template/components/ui/skeleton.tsx +13 -0
- package/template/components/ui/sonner.tsx +25 -0
- package/template/components/ui/switch.tsx +31 -0
- package/template/components/ui/tabs.tsx +66 -0
- package/template/components/ui/textarea.tsx +18 -0
- package/template/components/ui/toggle-group.tsx +73 -0
- package/template/components/ui/toggle.tsx +47 -0
- package/template/components/ui/tooltip.tsx +61 -0
- package/template/components/user-profile.tsx +139 -0
- package/template/components.json +21 -0
- package/template/db/drizzle.ts +14 -0
- package/template/db/migrations/0000_worried_rawhide_kid.sql +77 -0
- package/template/db/migrations/meta/0000_snapshot.json +494 -0
- package/template/db/migrations/meta/_journal.json +13 -0
- package/template/db/schema.ts +85 -0
- package/template/drizzle.config.ts +13 -0
- package/template/emails/components/layout.tsx +181 -0
- package/template/emails/password-reset.tsx +67 -0
- package/template/emails/payment-failed.tsx +167 -0
- package/template/emails/subscription-confirmation.tsx +129 -0
- package/template/emails/welcome.tsx +100 -0
- package/template/eslint.config.mjs +16 -0
- package/template/hooks/use-mobile.ts +21 -0
- package/template/lib/auth-client.ts +8 -0
- package/template/lib/auth.ts +276 -0
- package/template/lib/email.ts +118 -0
- package/template/lib/polar-products.ts +49 -0
- package/template/lib/subscription.ts +148 -0
- package/template/lib/upload-image.ts +28 -0
- package/template/lib/utils.ts +6 -0
- package/template/middleware.ts +30 -0
- package/template/next-env.d.ts +5 -0
- package/template/next.config.ts +27 -0
- package/template/package.json +99 -0
- package/template/postcss.config.mjs +5 -0
- package/template/public/add.png +0 -0
- package/template/public/favicon.svg +4 -0
- package/template/public/file.svg +1 -0
- package/template/public/globe.svg +1 -0
- package/template/public/iphone.png +0 -0
- package/template/public/logo.png +0 -0
- package/template/public/next.svg +1 -0
- package/template/public/polar-sh.svg +1 -0
- package/template/public/shadcn-ui.svg +1 -0
- package/template/public/site.webmanifest +21 -0
- package/template/public/vercel.svg +1 -0
- package/template/public/window.svg +1 -0
- package/template/tailwind.config.ts +89 -0
- package/template/template.config.json +138 -0
- package/template/tsconfig.json +27 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Environment Variables
|
|
2
|
+
# Copy this file to .env.local and customize the values
|
|
3
|
+
|
|
4
|
+
# ⚠️ REQUIRED FOR BASIC FUNCTIONALITY:
|
|
5
|
+
# - DATABASE_URL (for data storage)
|
|
6
|
+
# - BETTER_AUTH_SECRET (for authentication)
|
|
7
|
+
# - GOOGLE_CLIENT_ID & GOOGLE_CLIENT_SECRET (for Google login)
|
|
8
|
+
|
|
9
|
+
# ℹ️ OPTIONAL SERVICES:
|
|
10
|
+
# - POLAR_* variables (only needed for subscription payments)
|
|
11
|
+
# - RESEND_API_KEY (only needed for transactional emails)
|
|
12
|
+
# - OPENAI_API_KEY (only needed for AI chat features)
|
|
13
|
+
# - R2_* variables (only needed for file uploads)
|
|
14
|
+
# - POSTHOG_* variables (only needed for analytics)
|
|
15
|
+
|
|
16
|
+
# The app will launch with these placeholder values, but configure real services for production
|
|
17
|
+
|
|
18
|
+
# Application
|
|
19
|
+
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
20
|
+
|
|
21
|
+
# Auth (Required)
|
|
22
|
+
BETTER_AUTH_SECRET=please-change-this-to-a-random-32-character-string-or-longer
|
|
23
|
+
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
|
|
24
|
+
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
|
25
|
+
|
|
26
|
+
# Database (Required)
|
|
27
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
|
|
28
|
+
|
|
29
|
+
# Payments (Optional - only needed if using this feature)
|
|
30
|
+
# Get your access token from https://polar.sh/dashboard/settings/api
|
|
31
|
+
# Required scopes: subscriptions:read, products:read, customers:read, checkouts:write, orders:read
|
|
32
|
+
POLAR_ACCESS_TOKEN=your-polar-access-token
|
|
33
|
+
POLAR_SUCCESS_URL=success
|
|
34
|
+
POLAR_WEBHOOK_SECRET=your-polar-webhook-secret
|
|
35
|
+
NEXT_PUBLIC_STARTER_TIER=your-starter-tier-id
|
|
36
|
+
NEXT_PUBLIC_STARTER_SLUG=your-organization-slug
|
|
37
|
+
|
|
38
|
+
# Email (Optional - only needed if using this feature)
|
|
39
|
+
# Get your API key from https://resend.com/api-keys
|
|
40
|
+
RESEND_API_KEY=re_your-resend-api-key
|
|
41
|
+
EMAIL_FROM=SaaS Scaffold <noreply@yourdomain.com>
|
|
42
|
+
|
|
43
|
+
# Analytics (Optional - only needed if using this feature)
|
|
44
|
+
NEXT_PUBLIC_POSTHOG_KEY=phc_your-posthog-project-key
|
|
45
|
+
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
{{PROJECT_DESCRIPTION}}
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
### 🔐 Authentication & User Management
|
|
8
|
+
- **Better Auth v1.2.8** - Modern authentication system
|
|
9
|
+
- Google OAuth integration
|
|
10
|
+
- Session management with database persistence
|
|
11
|
+
- User profile management with image uploads
|
|
12
|
+
- Account linking for multiple providers
|
|
13
|
+
|
|
14
|
+
### 💳 Subscription & Billing
|
|
15
|
+
- **Polar.sh** integration for subscription management
|
|
16
|
+
- Two-tier pricing: Starter ($99/month) & Professional ($499/month)
|
|
17
|
+
- Real-time webhook processing
|
|
18
|
+
- Customer portal for self-service billing
|
|
19
|
+
- Subscription status tracking (active, canceled, expired)
|
|
20
|
+
- Payment gating with elegant overlays
|
|
21
|
+
|
|
22
|
+
### 🤖 AI Integration
|
|
23
|
+
- **OpenAI** powered chatbot
|
|
24
|
+
- React Markdown rendering for rich responses
|
|
25
|
+
- Multi-step conversation support
|
|
26
|
+
- Integrated chat widget in dashboard
|
|
27
|
+
|
|
28
|
+
### 🎨 Modern UI/UX
|
|
29
|
+
- **Tailwind CSS v4** - Latest utility-first styling
|
|
30
|
+
- **shadcn/ui** components - Accessible, customizable
|
|
31
|
+
- **Radix UI** primitives - Unstyled, accessible components
|
|
32
|
+
- Dark/light theme support with smooth transitions
|
|
33
|
+
- Responsive design with mobile-first approach
|
|
34
|
+
- Loading skeletons and optimistic UI updates
|
|
35
|
+
|
|
36
|
+
### 🗄️ Database & Storage
|
|
37
|
+
- **Neon PostgreSQL** - Serverless database
|
|
38
|
+
- **Drizzle ORM** - Type-safe database toolkit
|
|
39
|
+
- **Cloudflare R2** - Scalable file storage with zero egress fees
|
|
40
|
+
- Database migrations with Drizzle Kit
|
|
41
|
+
- Drag & drop file uploads with progress tracking
|
|
42
|
+
|
|
43
|
+
### 📊 Analytics & Monitoring
|
|
44
|
+
- **PostHog** integration for product analytics
|
|
45
|
+
- User behavior tracking
|
|
46
|
+
- Custom event monitoring
|
|
47
|
+
- Error tracking and insights
|
|
48
|
+
|
|
49
|
+
## 🚀 Tech Stack
|
|
50
|
+
|
|
51
|
+
- **Framework**: Next.js 15.3.1 with App Router
|
|
52
|
+
- **Language**: TypeScript with strict mode
|
|
53
|
+
- **Styling**: Tailwind CSS v4 + shadcn/ui
|
|
54
|
+
- **Database**: Neon PostgreSQL + Drizzle ORM
|
|
55
|
+
- **Authentication**: Better Auth v1.2.8
|
|
56
|
+
- **Payments**: Polar.sh
|
|
57
|
+
- **AI**: OpenAI SDK
|
|
58
|
+
- **Storage**: Cloudflare R2
|
|
59
|
+
- **Analytics**: PostHog
|
|
60
|
+
- **Deployment**: Vercel (recommended)
|
|
61
|
+
|
|
62
|
+
## 📁 Project Structure
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
├── app/
|
|
66
|
+
│ ├── (auth)/ # Authentication pages
|
|
67
|
+
│ ├── dashboard/ # Protected dashboard area
|
|
68
|
+
│ │ ├── _components/ # Dashboard components
|
|
69
|
+
│ │ ├── chat/ # AI chat interface
|
|
70
|
+
│ │ ├── upload/ # File upload with R2
|
|
71
|
+
│ │ ├── payment/ # Subscription management
|
|
72
|
+
│ │ └── settings/ # User settings & billing
|
|
73
|
+
│ ├── pricing/ # Public pricing page
|
|
74
|
+
│ └── api/ # API routes
|
|
75
|
+
├── components/
|
|
76
|
+
│ ├── ui/ # shadcn/ui components
|
|
77
|
+
│ └── homepage/ # Landing page sections
|
|
78
|
+
├── lib/
|
|
79
|
+
│ ├── auth/ # Authentication config
|
|
80
|
+
│ ├── subscription.ts # Subscription utilities
|
|
81
|
+
│ └── upload-image.ts # R2 file upload utilities
|
|
82
|
+
└── db/
|
|
83
|
+
├── schema.ts # Database schema
|
|
84
|
+
└── drizzle.ts # Database connection
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 🛠️ Quick Start
|
|
88
|
+
|
|
89
|
+
### Prerequisites
|
|
90
|
+
- Node.js 18+
|
|
91
|
+
- PostgreSQL database (Neon recommended)
|
|
92
|
+
- Cloudflare R2 bucket for file storage
|
|
93
|
+
- Polar.sh account for subscriptions
|
|
94
|
+
- OpenAI API key for AI features
|
|
95
|
+
- Google OAuth credentials (optional)
|
|
96
|
+
|
|
97
|
+
### Installation
|
|
98
|
+
|
|
99
|
+
1. **Clone the repository**
|
|
100
|
+
```bash
|
|
101
|
+
git clone <repository-url>
|
|
102
|
+
cd {{PROJECT_NAME}}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
2. **Install dependencies**
|
|
106
|
+
```bash
|
|
107
|
+
npm install
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
3. **Environment Setup**
|
|
111
|
+
Create a `.env.local` file with:
|
|
112
|
+
```env
|
|
113
|
+
# Database
|
|
114
|
+
DATABASE_URL="your-neon-database-url"
|
|
115
|
+
|
|
116
|
+
# Authentication
|
|
117
|
+
BETTER_AUTH_SECRET="your-secret-key"
|
|
118
|
+
GOOGLE_CLIENT_ID="your-google-client-id"
|
|
119
|
+
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
|
120
|
+
|
|
121
|
+
# Polar.sh
|
|
122
|
+
POLAR_ACCESS_TOKEN="your-polar-access-token"
|
|
123
|
+
POLAR_WEBHOOK_SECRET="your-webhook-secret"
|
|
124
|
+
|
|
125
|
+
# OpenAI
|
|
126
|
+
OPENAI_API_KEY="your-openai-api-key"
|
|
127
|
+
|
|
128
|
+
# Cloudflare R2 Storage
|
|
129
|
+
CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
|
|
130
|
+
R2_UPLOAD_IMAGE_ACCESS_KEY_ID="your-r2-access-key-id"
|
|
131
|
+
R2_UPLOAD_IMAGE_SECRET_ACCESS_KEY="your-r2-secret-access-key"
|
|
132
|
+
R2_UPLOAD_IMAGE_BUCKET_NAME="your-r2-bucket-name"
|
|
133
|
+
|
|
134
|
+
# Polar.sh Pricing Tiers
|
|
135
|
+
NEXT_PUBLIC_STARTER_TIER="your-starter-product-id"
|
|
136
|
+
NEXT_PUBLIC_STARTER_SLUG="your-starter-slug"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
4. **Database Setup**
|
|
140
|
+
```bash
|
|
141
|
+
# Generate and run migrations
|
|
142
|
+
npx drizzle-kit generate
|
|
143
|
+
npx drizzle-kit push
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
5. **Cloudflare R2 Setup**
|
|
147
|
+
- Create a Cloudflare account and set up R2 storage
|
|
148
|
+
- Create a bucket for file uploads
|
|
149
|
+
- Generate API tokens with R2 permissions
|
|
150
|
+
- Configure CORS settings for your domain
|
|
151
|
+
|
|
152
|
+
6. **Polar.sh Setup**
|
|
153
|
+
- Create products for your pricing tiers
|
|
154
|
+
- Set up webhook endpoints for subscription events
|
|
155
|
+
- Configure your pricing structure
|
|
156
|
+
|
|
157
|
+
7. **Start Development Server**
|
|
158
|
+
```bash
|
|
159
|
+
npm run dev
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Open [http://localhost:3000](http://localhost:3000) to see your application.
|
|
163
|
+
|
|
164
|
+
## 🎯 Key Features Explained
|
|
165
|
+
|
|
166
|
+
### Subscription Management
|
|
167
|
+
- Automatic subscription status checking
|
|
168
|
+
- Payment gating for premium features
|
|
169
|
+
- Integration with Polar.sh customer portal
|
|
170
|
+
- Webhook handling for real-time updates
|
|
171
|
+
|
|
172
|
+
### AI Chat Integration
|
|
173
|
+
- Built-in chatbot with OpenAI
|
|
174
|
+
- Markdown rendering for rich responses
|
|
175
|
+
- Conversation history and context
|
|
176
|
+
|
|
177
|
+
### File Upload System
|
|
178
|
+
- **Cloudflare R2 integration** with S3-compatible API
|
|
179
|
+
- **Drag & drop interface** with visual feedback
|
|
180
|
+
- **File validation** - Type checking and size limits
|
|
181
|
+
- **Progress tracking** - Real-time upload progress
|
|
182
|
+
- **Image gallery** - View uploaded files with metadata
|
|
183
|
+
- **Copy URLs** - Easy sharing and integration
|
|
184
|
+
|
|
185
|
+
### Analytics & Tracking
|
|
186
|
+
- PostHog event tracking
|
|
187
|
+
- User behavior monitoring
|
|
188
|
+
- Custom analytics dashboard
|
|
189
|
+
|
|
190
|
+
## 🔧 Customization
|
|
191
|
+
|
|
192
|
+
### Adding New Features
|
|
193
|
+
1. Create components in `components/`
|
|
194
|
+
2. Add API routes in `app/api/`
|
|
195
|
+
3. Update database schema in `db/schema.ts`
|
|
196
|
+
4. Run `npx drizzle-kit generate` and `npx drizzle-kit push`
|
|
197
|
+
|
|
198
|
+
### Styling
|
|
199
|
+
- Modify `app/globals.css` for global styles
|
|
200
|
+
- Use Tailwind classes for component styling
|
|
201
|
+
- Customize theme in `tailwind.config.ts`
|
|
202
|
+
|
|
203
|
+
### Authentication
|
|
204
|
+
- Configure providers in `lib/auth/auth.ts`
|
|
205
|
+
- Add new OAuth providers as needed
|
|
206
|
+
- Customize user profile fields in database schema
|
|
207
|
+
|
|
208
|
+
## 📚 Learn More
|
|
209
|
+
|
|
210
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|
|
211
|
+
- [Better Auth Documentation](https://better-auth.com)
|
|
212
|
+
- [Polar.sh Documentation](https://docs.polar.sh)
|
|
213
|
+
- [Drizzle ORM Documentation](https://orm.drizzle.team)
|
|
214
|
+
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
|
215
|
+
|
|
216
|
+
## 🚀 Deployment
|
|
217
|
+
|
|
218
|
+
### Vercel (Recommended)
|
|
219
|
+
1. Connect your GitHub repository to Vercel
|
|
220
|
+
2. Add environment variables in Vercel dashboard
|
|
221
|
+
3. Deploy automatically on every push
|
|
222
|
+
|
|
223
|
+
### Manual Deployment
|
|
224
|
+
```bash
|
|
225
|
+
npm run build
|
|
226
|
+
npm start
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## 📄 License
|
|
230
|
+
|
|
231
|
+
This project is licensed under the MIT License.
|
|
232
|
+
|
|
233
|
+
## 🤝 Contributing
|
|
234
|
+
|
|
235
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
Built with ❤️ using Next.js and modern web technologies.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { openai } from "@ai-sdk/openai";
|
|
2
|
+
import { streamText } from "ai";
|
|
3
|
+
|
|
4
|
+
export async function POST(req: Request) {
|
|
5
|
+
const { messages } = await req.json();
|
|
6
|
+
|
|
7
|
+
const result = streamText({
|
|
8
|
+
model: openai.responses("gpt-4o"),
|
|
9
|
+
messages,
|
|
10
|
+
tools: {
|
|
11
|
+
web_search_preview: openai.tools.webSearchPreview(),
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return result.toDataStreamResponse();
|
|
16
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { auth } from "@/lib/auth";
|
|
2
|
+
import { getSubscriptionDetails } from "@/lib/subscription";
|
|
3
|
+
import { headers } from "next/headers";
|
|
4
|
+
import { NextResponse } from "next/server";
|
|
5
|
+
|
|
6
|
+
export async function GET() {
|
|
7
|
+
try {
|
|
8
|
+
const result = await auth.api.getSession({
|
|
9
|
+
headers: await headers(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (!result?.session?.userId) {
|
|
13
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const subscriptionDetails = await getSubscriptionDetails();
|
|
17
|
+
return NextResponse.json(subscriptionDetails);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error("Error fetching subscription details:", error);
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{ error: "Failed to fetch subscription details" },
|
|
22
|
+
{ status: 500 }
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -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
|
+
}
|