create-solostack 1.3.5 → 1.3.7
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/package.json +1 -1
- package/src/generators/auth.js +80 -23
- package/src/index.js +10 -10
package/package.json
CHANGED
package/src/generators/auth.js
CHANGED
|
@@ -36,35 +36,29 @@ export function createClient() {
|
|
|
36
36
|
`;
|
|
37
37
|
await writeFile(path.join(projectPath, 'src/utils/supabase/client.ts'), clientUtil);
|
|
38
38
|
|
|
39
|
-
// 2. Server Utility
|
|
40
|
-
const serverUtil = `import { createServerClient
|
|
39
|
+
// 2. Server Utility (Next.js 15 compatible - async cookies)
|
|
40
|
+
const serverUtil = `import { createServerClient } from '@supabase/ssr'
|
|
41
41
|
import { cookies } from 'next/headers'
|
|
42
42
|
|
|
43
|
-
export function createClient(
|
|
43
|
+
export async function createClient() {
|
|
44
|
+
const cookieStore = await cookies()
|
|
45
|
+
|
|
44
46
|
return createServerClient(
|
|
45
47
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
46
48
|
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
47
49
|
{
|
|
48
50
|
cookies: {
|
|
49
|
-
|
|
50
|
-
return cookieStore.
|
|
51
|
+
getAll() {
|
|
52
|
+
return cookieStore.getAll()
|
|
51
53
|
},
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
cookieStore.set({ name, value, ...options })
|
|
55
|
-
} catch (error) {
|
|
56
|
-
// The \`set\` method was called from a Server Component.
|
|
57
|
-
// This can be ignored if you have middleware refreshing
|
|
58
|
-
// user sessions.
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
remove(name: string, options: CookieOptions) {
|
|
54
|
+
setAll(cookiesToSet) {
|
|
62
55
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//
|
|
56
|
+
cookiesToSet.forEach(({ name, value, options }) =>
|
|
57
|
+
cookieStore.set(name, value, options)
|
|
58
|
+
)
|
|
59
|
+
} catch {
|
|
60
|
+
// The \`setAll\` method was called from a Server Component.
|
|
61
|
+
// This can be ignored if you have middleware refreshing user sessions.
|
|
68
62
|
}
|
|
69
63
|
},
|
|
70
64
|
},
|
|
@@ -163,7 +157,6 @@ export const config = {
|
|
|
163
157
|
|
|
164
158
|
// 5. Auth Callback Route
|
|
165
159
|
const routeCallback = `import { NextResponse } from 'next/server'
|
|
166
|
-
import { cookies } from 'next/headers'
|
|
167
160
|
import { createClient } from '@/utils/supabase/server'
|
|
168
161
|
|
|
169
162
|
export async function GET(request: Request) {
|
|
@@ -172,8 +165,7 @@ export async function GET(request: Request) {
|
|
|
172
165
|
const next = searchParams.get('next') ?? '/'
|
|
173
166
|
|
|
174
167
|
if (code) {
|
|
175
|
-
const
|
|
176
|
-
const supabase = createClient(cookieStore)
|
|
168
|
+
const supabase = await createClient()
|
|
177
169
|
const { error } = await supabase.auth.exchangeCodeForSession(code)
|
|
178
170
|
if (!error) {
|
|
179
171
|
return NextResponse.redirect(new URL(next, request.url))
|
|
@@ -461,6 +453,71 @@ export default function SignupPage() {
|
|
|
461
453
|
`;
|
|
462
454
|
|
|
463
455
|
await writeFile(path.join(projectPath, 'src/app/signup/page.tsx'), signupPage);
|
|
456
|
+
|
|
457
|
+
// 8. Dashboard Layout (Supabase)
|
|
458
|
+
await ensureDir(path.join(projectPath, 'src/app/dashboard'));
|
|
459
|
+
|
|
460
|
+
const dashboardLayout = `import { redirect } from 'next/navigation';
|
|
461
|
+
import Link from 'next/link';
|
|
462
|
+
import { createClient } from '@/utils/supabase/server';
|
|
463
|
+
|
|
464
|
+
export default async function DashboardLayout({
|
|
465
|
+
children,
|
|
466
|
+
}: {
|
|
467
|
+
children: React.ReactNode;
|
|
468
|
+
}) {
|
|
469
|
+
const supabase = await createClient();
|
|
470
|
+
const { data: { user } } = await supabase.auth.getUser();
|
|
471
|
+
|
|
472
|
+
if (!user) {
|
|
473
|
+
redirect('/login');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return (
|
|
477
|
+
<div className="min-h-screen bg-gray-50">
|
|
478
|
+
<nav className="bg-white border-b">
|
|
479
|
+
<div className="container mx-auto px-4 py-4">
|
|
480
|
+
<div className="flex items-center justify-between">
|
|
481
|
+
<Link href="/dashboard" className="text-xl font-bold">
|
|
482
|
+
Dashboard
|
|
483
|
+
</Link>
|
|
484
|
+
<div className="flex items-center gap-6">
|
|
485
|
+
<Link href="/dashboard" className="text-sm hover:text-indigo-600">
|
|
486
|
+
Home
|
|
487
|
+
</Link>
|
|
488
|
+
<Link href="/dashboard/billing" className="text-sm hover:text-indigo-600">
|
|
489
|
+
Billing
|
|
490
|
+
</Link>
|
|
491
|
+
<Link href="/dashboard/settings" className="text-sm hover:text-indigo-600">
|
|
492
|
+
Settings
|
|
493
|
+
</Link>
|
|
494
|
+
<Link href="/api/auth/signout" className="text-sm text-red-600 hover:text-red-700">
|
|
495
|
+
Sign Out
|
|
496
|
+
</Link>
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
</div>
|
|
500
|
+
</nav>
|
|
501
|
+
<main>{children}</main>
|
|
502
|
+
</div>
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
`;
|
|
506
|
+
await writeFile(path.join(projectPath, 'src/app/dashboard/layout.tsx'), dashboardLayout);
|
|
507
|
+
|
|
508
|
+
// 9. Signout Route (Supabase)
|
|
509
|
+
await ensureDir(path.join(projectPath, 'src/app/api/auth/signout'));
|
|
510
|
+
|
|
511
|
+
const signoutRoute = `import { NextResponse } from 'next/server';
|
|
512
|
+
import { createClient } from '@/utils/supabase/server';
|
|
513
|
+
|
|
514
|
+
export async function GET() {
|
|
515
|
+
const supabase = await createClient();
|
|
516
|
+
await supabase.auth.signOut();
|
|
517
|
+
return NextResponse.redirect(new URL('/login', process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'));
|
|
518
|
+
}
|
|
519
|
+
`;
|
|
520
|
+
await writeFile(path.join(projectPath, 'src/app/api/auth/signout/route.ts'), signoutRoute);
|
|
464
521
|
}
|
|
465
522
|
|
|
466
523
|
async function generateNextAuth(projectPath) {
|
package/src/index.js
CHANGED
|
@@ -53,7 +53,7 @@ export async function main() {
|
|
|
53
53
|
╚════════════════════════════════════════════════════════════════╝
|
|
54
54
|
`));
|
|
55
55
|
|
|
56
|
-
console.log(chalk.gray(` Version ${orangeBright('1.3.
|
|
56
|
+
console.log(chalk.gray(` Version ${orangeBright('1.3.7')} • Built by ${orangeBright('Danish Akhtar')} • ${orangeBright('github.com/danish296')}\n`));
|
|
57
57
|
|
|
58
58
|
// Parse command line arguments
|
|
59
59
|
program
|
|
@@ -210,10 +210,17 @@ export async function main() {
|
|
|
210
210
|
await generateDatabase(projectPath, config);
|
|
211
211
|
spinner.succeed('Configured database (Prisma + PostgreSQL)');
|
|
212
212
|
|
|
213
|
-
// Generate
|
|
213
|
+
// Generate UI components (before auth so auth-specific layouts can override)
|
|
214
|
+
if (config.includeUI) {
|
|
215
|
+
spinner = ora('Adding UI components').start();
|
|
216
|
+
await generateUI(projectPath);
|
|
217
|
+
spinner.succeed('Added UI components (shadcn/ui)');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Generate authentication (after UI so auth-specific layouts take precedence)
|
|
214
221
|
spinner = ora('Configuring authentication').start();
|
|
215
222
|
await generateAuth(projectPath, config.auth);
|
|
216
|
-
spinner.succeed('Configured authentication
|
|
223
|
+
spinner.succeed('Configured authentication');
|
|
217
224
|
|
|
218
225
|
// Generate payments
|
|
219
226
|
spinner = ora('Configuring payments').start();
|
|
@@ -225,13 +232,6 @@ export async function main() {
|
|
|
225
232
|
await generateEmails(projectPath, config.email);
|
|
226
233
|
spinner.succeed('Configured emails (Resend)');
|
|
227
234
|
|
|
228
|
-
// Generate UI components
|
|
229
|
-
if (config.includeUI) {
|
|
230
|
-
spinner = ora('Adding UI components').start();
|
|
231
|
-
await generateUI(projectPath);
|
|
232
|
-
spinner.succeed('Added UI components (shadcn/ui)');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
235
|
// Generate setup & diagnostics
|
|
236
236
|
spinner = ora('Adding diagnostics page').start();
|
|
237
237
|
await generateSetup(projectPath, config);
|