stackpatch 1.1.2 → 1.1.4
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/README.md +123 -114
- package/bin/stackpatch.ts +2 -2441
- package/boilerplate/auth/app/auth/login/page.tsx +50 -24
- package/boilerplate/auth/app/auth/signup/page.tsx +69 -56
- package/boilerplate/auth/app/stackpatch/page.tsx +269 -0
- package/boilerplate/auth/components/auth-wrapper.tsx +61 -0
- package/package.json +4 -2
- package/src/auth/generator.ts +569 -0
- package/src/auth/index.ts +372 -0
- package/src/auth/setup.ts +293 -0
- package/src/commands/add.ts +112 -0
- package/src/commands/create.ts +128 -0
- package/src/commands/revert.ts +389 -0
- package/src/config.ts +52 -0
- package/src/fileOps/copy.ts +224 -0
- package/src/fileOps/layout.ts +304 -0
- package/src/fileOps/protected.ts +67 -0
- package/src/index.ts +215 -0
- package/src/manifest.ts +87 -0
- package/src/ui/logo.ts +24 -0
- package/src/ui/progress.ts +82 -0
- package/src/utils/dependencies.ts +114 -0
- package/src/utils/deps-check.ts +45 -0
- package/src/utils/files.ts +58 -0
- package/src/utils/paths.ts +217 -0
- package/src/utils/scanner.ts +109 -0
- package/boilerplate/auth/app/api/auth/[...nextauth]/route.ts +0 -124
- package/boilerplate/auth/app/api/auth/signup/route.ts +0 -45
- package/boilerplate/auth/app/dashboard/page.tsx +0 -82
- package/boilerplate/auth/app/login/page.tsx +0 -136
- package/boilerplate/auth/app/page.tsx +0 -48
- package/boilerplate/auth/components/auth-button.tsx +0 -43
- package/boilerplate/auth/components/auth-navbar.tsx +0 -118
- package/boilerplate/auth/components/protected-route.tsx +0 -74
- package/boilerplate/auth/components/session-provider.tsx +0 -11
- package/boilerplate/auth/middleware.ts +0 -51
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ StackPatch is a CLI tool that helps you quickly add production-ready features to
|
|
|
10
10
|
## ✨ Features
|
|
11
11
|
|
|
12
12
|
- 🚀 **Zero Configuration** - Add features with a single command
|
|
13
|
-
- 🔐 **Authentication** - Full
|
|
13
|
+
- 🔐 **Authentication** - Full Better Auth setup with customizable OAuth providers
|
|
14
14
|
- 🛡️ **Protected Routes** - Easy route protection with components or middleware
|
|
15
15
|
- 🎨 **UI Components** - Pre-built, production-ready components
|
|
16
16
|
- 📦 **Composable** - Add only what you need, when you need it
|
|
@@ -89,31 +89,40 @@ This will:
|
|
|
89
89
|
|
|
90
90
|
## 📖 What Gets Added
|
|
91
91
|
|
|
92
|
-
###
|
|
92
|
+
### Setup Flow
|
|
93
93
|
|
|
94
|
-
When you run `npx stackpatch add auth`, StackPatch:
|
|
94
|
+
When you run `npx stackpatch add auth`, StackPatch will guide you through an interactive setup:
|
|
95
95
|
|
|
96
|
-
1. **
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
1. **Session Mode**: Choose between Database (persistent sessions) or Stateless (JWT only)
|
|
97
|
+
2. **Database** (if database mode): Select PostgreSQL, MySQL, SQLite, or MongoDB
|
|
98
|
+
3. **ORM** (if database mode): Choose Drizzle, Prisma, or Raw SQL driver
|
|
99
|
+
4. **Auth Providers**: Enable Email/Password and select OAuth providers (Google, GitHub)
|
|
100
|
+
5. **UI Components**: Choose whether to add prebuilt login/signup pages
|
|
101
|
+
6. **Protected Routes**: Select which routes to protect (supports wildcards like `/dashboard/*`)
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
- ✅ NextAuth.js configuration with your selected providers
|
|
103
|
-
- ✅ Login and signup pages (`/auth/login`, `/auth/signup`)
|
|
104
|
-
- ✅ OAuth buttons for selected providers with email/password forms
|
|
105
|
-
- ✅ Protected route component (`components/protected-route.tsx` or `src/components/protected-route.tsx`)
|
|
106
|
-
- ✅ Middleware for route protection (`middleware.ts`)
|
|
107
|
-
- ✅ Session provider and toaster components
|
|
108
|
-
- ✅ Environment file template (`.env.example`)
|
|
103
|
+
### Files Generated
|
|
109
104
|
|
|
110
|
-
|
|
111
|
-
- Detects if your app is in `app/` or `src/app/`
|
|
112
|
-
- Places components in matching location (`components/` or `src/components/`)
|
|
113
|
-
- Uses your `tsconfig.json` path aliases for imports
|
|
114
|
-
- Generates correct import paths automatically
|
|
105
|
+
After the interactive setup, StackPatch automatically generates:
|
|
115
106
|
|
|
116
|
-
|
|
107
|
+
- ✅ **Better Auth configuration** (`lib/auth.ts` or `src/lib/auth.ts`)
|
|
108
|
+
- ✅ **Auth client utilities** (`lib/auth-client.ts` or `src/lib/auth-client.ts`)
|
|
109
|
+
- ✅ **Protected routes config** (`lib/protected-routes.ts` - only if protected routes are configured)
|
|
110
|
+
- ✅ **API route handler** (`app/api/auth/[...all]/route.ts`)
|
|
111
|
+
- ✅ **Middleware** (`middleware.ts` - only if protected routes are configured)
|
|
112
|
+
- ✅ **Login/Signup pages** (`app/auth/login/page.tsx`, `app/auth/signup/page.tsx` - if UI enabled)
|
|
113
|
+
- ✅ **Landing page** (`app/stackpatch/page.tsx` - if UI enabled)
|
|
114
|
+
- ✅ **Auth wrapper** (`components/auth-wrapper.tsx` - if UI enabled, added to layout.tsx)
|
|
115
|
+
- ✅ **Toaster component** (`components/toaster.tsx` - if UI enabled, added to layout.tsx)
|
|
116
|
+
- ✅ **Environment template** (`.env.example`)
|
|
117
|
+
|
|
118
|
+
### Smart File Placement
|
|
119
|
+
|
|
120
|
+
StackPatch automatically:
|
|
121
|
+
- ✅ Detects if your app is in `app/` or `src/app/`
|
|
122
|
+
- ✅ Places components in matching location (`components/` or `src/components/`)
|
|
123
|
+
- ✅ Uses your `tsconfig.json` path aliases for imports
|
|
124
|
+
- ✅ Generates correct import paths automatically
|
|
125
|
+
- ✅ Tracks all changes in `.stackpatch/manifest.json` for safe reversion
|
|
117
126
|
|
|
118
127
|
## 🔐 OAuth Setup
|
|
119
128
|
|
|
@@ -126,7 +135,7 @@ If you selected Google OAuth:
|
|
|
126
135
|
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
127
136
|
2. Create a project → APIs & Services → Credentials
|
|
128
137
|
3. Create OAuth client ID (Web application)
|
|
129
|
-
4. Add redirect URI: `http://localhost:3000/api/auth/callback/google`
|
|
138
|
+
4. Add redirect URI: `http://localhost:3000/api/auth/callback/google` (or your production URL)
|
|
130
139
|
5. Copy Client ID and Secret to `.env.local`:
|
|
131
140
|
```env
|
|
132
141
|
GOOGLE_CLIENT_ID=your_client_id
|
|
@@ -139,7 +148,7 @@ If you selected GitHub OAuth:
|
|
|
139
148
|
|
|
140
149
|
1. Go to [GitHub Developer Settings](https://github.com/settings/developers)
|
|
141
150
|
2. New OAuth App
|
|
142
|
-
3. Set callback URL: `http://localhost:3000/api/auth/callback/github`
|
|
151
|
+
3. Set callback URL: `http://localhost:3000/api/auth/callback/github` (or your production URL)
|
|
143
152
|
4. Copy Client ID and generate Secret
|
|
144
153
|
5. Add to `.env.local`:
|
|
145
154
|
```env
|
|
@@ -152,8 +161,8 @@ If you selected GitHub OAuth:
|
|
|
152
161
|
Your `.env.local` will include only the variables for providers you selected:
|
|
153
162
|
|
|
154
163
|
```env
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
BETTER_AUTH_SECRET=your_generated_secret
|
|
165
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
157
166
|
|
|
158
167
|
# Only included if you selected Google
|
|
159
168
|
GOOGLE_CLIENT_ID=your_google_client_id
|
|
@@ -164,85 +173,76 @@ GITHUB_CLIENT_ID=your_github_client_id
|
|
|
164
173
|
GITHUB_CLIENT_SECRET=your_github_client_secret
|
|
165
174
|
```
|
|
166
175
|
|
|
167
|
-
##
|
|
176
|
+
## 🛡️ Protecting Routes
|
|
168
177
|
|
|
169
|
-
|
|
170
|
-
- **
|
|
171
|
-
- **
|
|
178
|
+
StackPatch automatically protects routes based on your configuration. Routes are protected via:
|
|
179
|
+
- **Middleware** - Server-side protection with automatic redirects
|
|
180
|
+
- **AuthWrapper** - Client-side protection in your root layout
|
|
172
181
|
|
|
173
|
-
|
|
182
|
+
### How It Works
|
|
174
183
|
|
|
175
|
-
|
|
184
|
+
1. **During Setup**: You'll be prompted to select which routes to protect
|
|
185
|
+
2. **Automatic Protection**: StackPatch configures middleware and AuthWrapper automatically
|
|
186
|
+
3. **Redirects**: Unauthenticated users are redirected to `/auth/login?redirect=<original-path>`
|
|
187
|
+
4. **After Login**: Users are automatically redirected back to the original protected route
|
|
176
188
|
|
|
177
|
-
|
|
178
|
-
// app/layout.tsx or any page
|
|
179
|
-
import { AuthNavbar } from "@/components/auth-navbar";
|
|
180
|
-
|
|
181
|
-
export default function Layout({ children }) {
|
|
182
|
-
return (
|
|
183
|
-
<>
|
|
184
|
-
<AuthNavbar />
|
|
185
|
-
{children}
|
|
186
|
-
</>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
```
|
|
189
|
+
### Wildcard Routes
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
Use `/*` to protect a route and all its sub-routes:
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
- `/dashboard` → Protects only `/dashboard`
|
|
194
|
+
- `/dashboard/*` → Protects `/dashboard` and ALL sub-routes (`/dashboard/settings`, `/dashboard/users`, etc.)
|
|
194
195
|
|
|
195
|
-
|
|
196
|
+
**Examples:**
|
|
197
|
+
```
|
|
198
|
+
/dashboard/* → Protects /dashboard and all sub-routes
|
|
199
|
+
/admin/* → Protects /admin and all sub-routes
|
|
200
|
+
/profile → Protects only /profile (not sub-routes)
|
|
201
|
+
```
|
|
196
202
|
|
|
197
|
-
|
|
203
|
+
**To Modify Protected Routes:**
|
|
204
|
+
Edit `lib/protected-routes.ts` (or `src/lib/protected-routes.ts`):
|
|
198
205
|
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return (
|
|
206
|
-
<ProtectedRoute>
|
|
207
|
-
<AuthNavbar />
|
|
208
|
-
<h1>Protected Dashboard</h1>
|
|
209
|
-
</ProtectedRoute>
|
|
210
|
-
);
|
|
211
|
-
}
|
|
206
|
+
```ts
|
|
207
|
+
export const PROTECTED_ROUTES = [
|
|
208
|
+
"/dashboard/*", // Protects /dashboard and all sub-routes
|
|
209
|
+
"/admin/*", // Protects /admin and all sub-routes
|
|
210
|
+
"/profile", // Protects only /profile
|
|
211
|
+
] as const;
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
## ⚙️ Configuration Options
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
### Session Modes
|
|
217
217
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"/profile/:path*", // Protect all profile routes
|
|
224
|
-
],
|
|
225
|
-
};
|
|
226
|
-
```
|
|
218
|
+
**Database Mode** (Recommended for production):
|
|
219
|
+
- Persistent sessions stored in your database
|
|
220
|
+
- Supports session management and revocation
|
|
221
|
+
- Requires database setup (PostgreSQL, MySQL, SQLite, or MongoDB)
|
|
222
|
+
- Choose an ORM: Drizzle, Prisma, or Raw SQL
|
|
227
223
|
|
|
228
|
-
|
|
224
|
+
**Stateless Mode** (JWT/JWE):
|
|
225
|
+
- No database required
|
|
226
|
+
- Sessions stored in encrypted cookies
|
|
227
|
+
- Perfect for serverless deployments
|
|
228
|
+
- Limited session management features
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
### Email/Password Authentication
|
|
231
231
|
|
|
232
|
-
|
|
232
|
+
Email/password authentication works out of the box with Better Auth. If you selected database mode:
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
1. **Generate database schema**:
|
|
235
|
+
```bash
|
|
236
|
+
npx @better-auth/cli generate
|
|
237
|
+
# or
|
|
238
|
+
npx @better-auth/cli migrate
|
|
239
|
+
```
|
|
235
240
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- Replace the `authorize` function with database lookup
|
|
240
|
-
- Hash and compare passwords using bcrypt
|
|
241
|
-
4. **Create signup API** (`app/api/auth/signup/route.ts`):
|
|
242
|
-
- Hash passwords before storing
|
|
243
|
-
- Validate and create users in database
|
|
241
|
+
2. **Configure in `lib/auth.ts`** (already set up by StackPatch):
|
|
242
|
+
- Database adapter is configured based on your selection
|
|
243
|
+
- Email/password is enabled if you selected it
|
|
244
244
|
|
|
245
|
-
See
|
|
245
|
+
See Better Auth documentation for advanced configuration: https://better-auth.dev/docs
|
|
246
246
|
|
|
247
247
|
## 📁 File Locations
|
|
248
248
|
|
|
@@ -250,16 +250,20 @@ After running `npx stackpatch add auth`, you'll find files in locations that mat
|
|
|
250
250
|
|
|
251
251
|
### If your app is in `app/`:
|
|
252
252
|
- **Auth pages**: `app/auth/login/page.tsx`, `app/auth/signup/page.tsx`
|
|
253
|
-
- **
|
|
254
|
-
- **
|
|
253
|
+
- **Auth config**: `lib/auth.ts`, `lib/auth-client.ts`
|
|
254
|
+
- **Protected routes config**: `lib/protected-routes.ts`
|
|
255
|
+
- **API routes**: `app/api/auth/[...all]/route.ts`
|
|
256
|
+
- **Components**: `components/auth-wrapper.tsx`, `components/toaster.tsx`
|
|
255
257
|
- **Middleware**: `middleware.ts` (root)
|
|
256
258
|
- **Environment**: `.env.example`, `.env.local`
|
|
257
259
|
- **Tracking**: `.stackpatch/manifest.json` (for revert)
|
|
258
260
|
|
|
259
261
|
### If your app is in `src/app/`:
|
|
260
262
|
- **Auth pages**: `src/app/auth/login/page.tsx`, `src/app/auth/signup/page.tsx`
|
|
261
|
-
- **
|
|
262
|
-
- **
|
|
263
|
+
- **Auth config**: `src/lib/auth.ts`, `src/lib/auth-client.ts`
|
|
264
|
+
- **Protected routes config**: `src/lib/protected-routes.ts`
|
|
265
|
+
- **API routes**: `src/app/api/auth/[...all]/route.ts`
|
|
266
|
+
- **Components**: `src/components/auth-wrapper.tsx`, `src/components/toaster.tsx`
|
|
263
267
|
- **Middleware**: `middleware.ts` (root)
|
|
264
268
|
- **Environment**: `.env.example`, `.env.local`
|
|
265
269
|
- **Tracking**: `.stackpatch/manifest.json` (for revert)
|
|
@@ -271,36 +275,35 @@ StackPatch automatically detects your project structure and places files accordi
|
|
|
271
275
|
|
|
272
276
|
## 🔧 Customization
|
|
273
277
|
|
|
274
|
-
### Change
|
|
278
|
+
### Change Default Redirect After Login
|
|
275
279
|
|
|
276
|
-
|
|
280
|
+
The login/signup pages automatically redirect users based on:
|
|
281
|
+
1. The `redirect` query parameter (set by middleware when protecting routes)
|
|
282
|
+
2. Fallback to `/stackpatch` if no redirect parameter
|
|
277
283
|
|
|
278
|
-
|
|
279
|
-
pages: {
|
|
280
|
-
signIn: "/your-custom-login", // Change this
|
|
281
|
-
}
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Custom Protected Route Redirect
|
|
284
|
+
To change the fallback route, edit `app/auth/login/page.tsx` and `app/auth/signup/page.tsx`:
|
|
285
285
|
|
|
286
286
|
```tsx
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
</ProtectedRoute>
|
|
287
|
+
// Change the fallback route (default: "/stackpatch")
|
|
288
|
+
const redirectTo = searchParams.get("redirect") || "/your-custom-route";
|
|
290
289
|
```
|
|
291
290
|
|
|
292
291
|
### Protect API Routes
|
|
293
292
|
|
|
294
293
|
```ts
|
|
295
294
|
// app/api/protected/route.ts
|
|
296
|
-
import {
|
|
297
|
-
import {
|
|
295
|
+
import { auth } from "@/lib/auth";
|
|
296
|
+
import { headers } from "next/headers";
|
|
298
297
|
|
|
299
298
|
export async function GET() {
|
|
300
|
-
const session = await
|
|
301
|
-
|
|
299
|
+
const session = await auth.api.getSession({
|
|
300
|
+
headers: await headers(),
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
if (!session || !session.user) {
|
|
302
304
|
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
303
305
|
}
|
|
306
|
+
|
|
304
307
|
return Response.json({ data: "Protected data" });
|
|
305
308
|
}
|
|
306
309
|
```
|
|
@@ -310,7 +313,7 @@ export async function GET() {
|
|
|
310
313
|
### OAuth redirect_uri_mismatch
|
|
311
314
|
|
|
312
315
|
- Ensure redirect URIs match exactly in OAuth provider settings
|
|
313
|
-
- Check `
|
|
316
|
+
- Check `BETTER_AUTH_URL` matches your app URL (defaults to `http://localhost:3000` in development)
|
|
314
317
|
|
|
315
318
|
### OAuth buttons not working
|
|
316
319
|
|
|
@@ -346,11 +349,14 @@ your-project/
|
|
|
346
349
|
│ │ └── signup/page.tsx # Signup page
|
|
347
350
|
│ └── api/
|
|
348
351
|
│ └── auth/
|
|
349
|
-
│ └── [...
|
|
352
|
+
│ └── [...all]/route.ts # Better Auth API route
|
|
353
|
+
├── lib/
|
|
354
|
+
│ ├── auth.ts # Better Auth configuration
|
|
355
|
+
│ ├── auth-client.ts # Client-side auth utilities
|
|
356
|
+
│ └── protected-routes.ts # Protected routes configuration
|
|
350
357
|
├── components/
|
|
351
|
-
│ ├──
|
|
352
|
-
│
|
|
353
|
-
│ └── session-provider.tsx # Session provider
|
|
358
|
+
│ ├── auth-wrapper.tsx # Automatic route protection wrapper
|
|
359
|
+
│ └── toaster.tsx # Toast notifications
|
|
354
360
|
├── middleware.ts # Route protection middleware
|
|
355
361
|
├── .env.local # Your environment variables
|
|
356
362
|
└── .stackpatch/ # Tracking for revert (git-ignored)
|
|
@@ -369,11 +375,14 @@ your-project/
|
|
|
369
375
|
│ │ │ └── signup/page.tsx
|
|
370
376
|
│ │ └── api/
|
|
371
377
|
│ │ └── auth/
|
|
372
|
-
│ │ └── [...
|
|
378
|
+
│ │ └── [...all]/route.ts
|
|
379
|
+
│ ├── lib/
|
|
380
|
+
│ │ ├── auth.ts
|
|
381
|
+
│ │ ├── auth-client.ts
|
|
382
|
+
│ │ └── protected-routes.ts
|
|
373
383
|
│ └── components/
|
|
374
|
-
│ ├──
|
|
375
|
-
│
|
|
376
|
-
│ └── session-provider.tsx
|
|
384
|
+
│ ├── auth-wrapper.tsx
|
|
385
|
+
│ └── toaster.tsx
|
|
377
386
|
├── middleware.ts
|
|
378
387
|
├── .env.local
|
|
379
388
|
└── .stackpatch/
|