create-solostack 1.3.4 → 1.3.5
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 +154 -1
- package/src/index.js +1 -1
package/package.json
CHANGED
package/src/generators/auth.js
CHANGED
|
@@ -21,6 +21,7 @@ async function generateSupabaseAuth(projectPath) {
|
|
|
21
21
|
// Create auth directories
|
|
22
22
|
await ensureDir(path.join(projectPath, 'src/app/auth/callback'));
|
|
23
23
|
await ensureDir(path.join(projectPath, 'src/app/login'));
|
|
24
|
+
await ensureDir(path.join(projectPath, 'src/app/signup'));
|
|
24
25
|
await ensureDir(path.join(projectPath, 'src/app/private'));
|
|
25
26
|
|
|
26
27
|
// 1. Client Utility
|
|
@@ -73,7 +74,7 @@ export function createClient(cookieStore: ReturnType<typeof cookies>) {
|
|
|
73
74
|
`;
|
|
74
75
|
await writeFile(path.join(projectPath, 'src/utils/supabase/server.ts'), serverUtil);
|
|
75
76
|
|
|
76
|
-
// 3.
|
|
77
|
+
// 3. Middleware Utility
|
|
77
78
|
const middlewareUtil = `import { createServerClient, type CookieOptions } from '@supabase/ssr'
|
|
78
79
|
import { NextResponse, type NextRequest } from 'next/server'
|
|
79
80
|
|
|
@@ -191,6 +192,7 @@ import { createClient } from '@/utils/supabase/client';
|
|
|
191
192
|
import { useRouter } from 'next/navigation';
|
|
192
193
|
import { useState } from 'react';
|
|
193
194
|
import { Rocket } from 'lucide-react';
|
|
195
|
+
import Link from 'next/link';
|
|
194
196
|
|
|
195
197
|
export default function LoginPage() {
|
|
196
198
|
const router = useRouter();
|
|
@@ -301,6 +303,13 @@ export default function LoginPage() {
|
|
|
301
303
|
{loading ? 'Signing in...' : 'Sign In'}
|
|
302
304
|
</button>
|
|
303
305
|
</form>
|
|
306
|
+
|
|
307
|
+
<div className="text-center text-sm">
|
|
308
|
+
<span className="text-zinc-500">Don't have an account? </span>
|
|
309
|
+
<Link href="/signup" className="font-medium text-indigo-400 hover:text-indigo-300">
|
|
310
|
+
Sign up
|
|
311
|
+
</Link>
|
|
312
|
+
</div>
|
|
304
313
|
</div>
|
|
305
314
|
</div>
|
|
306
315
|
);
|
|
@@ -308,6 +317,150 @@ export default function LoginPage() {
|
|
|
308
317
|
`;
|
|
309
318
|
|
|
310
319
|
await writeFile(path.join(projectPath, 'src/app/login/page.tsx'), loginPage);
|
|
320
|
+
|
|
321
|
+
// 7. Signup Page (Supabase)
|
|
322
|
+
const signupPage = `'use client';
|
|
323
|
+
import { createClient } from '@/utils/supabase/client';
|
|
324
|
+
import { useRouter } from 'next/navigation';
|
|
325
|
+
import { useState } from 'react';
|
|
326
|
+
import { Rocket } from 'lucide-react';
|
|
327
|
+
import Link from 'next/link';
|
|
328
|
+
|
|
329
|
+
export default function SignupPage() {
|
|
330
|
+
const router = useRouter();
|
|
331
|
+
const [email, setEmail] = useState('');
|
|
332
|
+
const [password, setPassword] = useState('');
|
|
333
|
+
const [loading, setLoading] = useState(false);
|
|
334
|
+
const [message, setMessage] = useState('');
|
|
335
|
+
|
|
336
|
+
const supabase = createClient();
|
|
337
|
+
|
|
338
|
+
const handleEmailSignup = async (e: React.FormEvent) => {
|
|
339
|
+
e.preventDefault();
|
|
340
|
+
setLoading(true);
|
|
341
|
+
setMessage('');
|
|
342
|
+
|
|
343
|
+
const { error } = await supabase.auth.signUp({
|
|
344
|
+
email,
|
|
345
|
+
password,
|
|
346
|
+
options: {
|
|
347
|
+
emailRedirectTo: \`\${location.origin}/auth/callback\`,
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
if (error) {
|
|
352
|
+
setMessage(error.message);
|
|
353
|
+
} else {
|
|
354
|
+
setMessage('Check your email for the confirmation link!');
|
|
355
|
+
}
|
|
356
|
+
setLoading(false);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const handleGitHubLogin = async () => {
|
|
360
|
+
await supabase.auth.signInWithOAuth({
|
|
361
|
+
provider: 'github',
|
|
362
|
+
options: {
|
|
363
|
+
redirectTo: \`\${location.origin}/auth/callback\`,
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const handleGoogleLogin = async () => {
|
|
369
|
+
await supabase.auth.signInWithOAuth({
|
|
370
|
+
provider: 'google',
|
|
371
|
+
options: {
|
|
372
|
+
redirectTo: \`\${location.origin}/auth/callback\`,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
return (
|
|
378
|
+
<div className="flex min-h-screen flex-col items-center justify-center bg-zinc-950 p-4 text-white">
|
|
379
|
+
<div className="w-full max-w-sm space-y-8 rounded-xl border border-zinc-800 bg-zinc-900/50 p-8 shadow-xl backdrop-blur-xl">
|
|
380
|
+
<div className="text-center">
|
|
381
|
+
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-lg bg-indigo-600">
|
|
382
|
+
<Rocket className="h-6 w-6 text-white" />
|
|
383
|
+
</div>
|
|
384
|
+
<h2 className="text-2xl font-bold tracking-tight">Create account</h2>
|
|
385
|
+
<p className="mt-2 text-sm text-zinc-400">Sign up to get started</p>
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<div className="space-y-4">
|
|
389
|
+
<button
|
|
390
|
+
onClick={handleGitHubLogin}
|
|
391
|
+
className="w-full rounded-md border border-zinc-700 bg-zinc-800 py-2 text-sm font-medium hover:bg-zinc-700 transition-colors"
|
|
392
|
+
>
|
|
393
|
+
Continue with GitHub
|
|
394
|
+
</button>
|
|
395
|
+
<button
|
|
396
|
+
onClick={handleGoogleLogin}
|
|
397
|
+
className="w-full rounded-md border border-zinc-700 bg-zinc-800 py-2 text-sm font-medium hover:bg-zinc-700 transition-colors"
|
|
398
|
+
>
|
|
399
|
+
Continue with Google
|
|
400
|
+
</button>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
<div className="relative">
|
|
404
|
+
<div className="absolute inset-0 flex items-center">
|
|
405
|
+
<div className="w-full border-t border-zinc-800" />
|
|
406
|
+
</div>
|
|
407
|
+
<div className="relative flex justify-center text-xs uppercase">
|
|
408
|
+
<span className="bg-zinc-900 px-2 text-zinc-500">Or continue with</span>
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
|
|
412
|
+
<form onSubmit={handleEmailSignup} className="space-y-4">
|
|
413
|
+
<div>
|
|
414
|
+
<label className="mb-2 block text-sm font-medium text-zinc-400">Email</label>
|
|
415
|
+
<input
|
|
416
|
+
type="email"
|
|
417
|
+
value={email}
|
|
418
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
419
|
+
className="w-full rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm placeholder:text-zinc-600 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
|
|
420
|
+
required
|
|
421
|
+
/>
|
|
422
|
+
</div>
|
|
423
|
+
<div>
|
|
424
|
+
<label className="mb-2 block text-sm font-medium text-zinc-400">Password</label>
|
|
425
|
+
<input
|
|
426
|
+
type="password"
|
|
427
|
+
value={password}
|
|
428
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
429
|
+
className="w-full rounded-md border border-zinc-700 bg-zinc-900 px-3 py-2 text-sm placeholder:text-zinc-600 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
|
|
430
|
+
placeholder="Min 6 characters"
|
|
431
|
+
minLength={6}
|
|
432
|
+
required
|
|
433
|
+
/>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
{message && (
|
|
437
|
+
<p className={message.includes('Check') ? 'text-sm text-green-400' : 'text-sm text-red-400'}>
|
|
438
|
+
{message}
|
|
439
|
+
</p>
|
|
440
|
+
)}
|
|
441
|
+
|
|
442
|
+
<button
|
|
443
|
+
type="submit"
|
|
444
|
+
disabled={loading}
|
|
445
|
+
className="w-full rounded-md bg-indigo-600 py-2 text-sm font-medium text-white hover:bg-indigo-500 disabled:opacity-50"
|
|
446
|
+
>
|
|
447
|
+
{loading ? 'Creating account...' : 'Sign Up'}
|
|
448
|
+
</button>
|
|
449
|
+
</form>
|
|
450
|
+
|
|
451
|
+
<div className="text-center text-sm">
|
|
452
|
+
<span className="text-zinc-500">Already have an account? </span>
|
|
453
|
+
<Link href="/login" className="font-medium text-indigo-400 hover:text-indigo-300">
|
|
454
|
+
Sign in
|
|
455
|
+
</Link>
|
|
456
|
+
</div>
|
|
457
|
+
</div>
|
|
458
|
+
</div>
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
`;
|
|
462
|
+
|
|
463
|
+
await writeFile(path.join(projectPath, 'src/app/signup/page.tsx'), signupPage);
|
|
311
464
|
}
|
|
312
465
|
|
|
313
466
|
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.5')} • Built by ${orangeBright('Danish Akhtar')} • ${orangeBright('github.com/danish296')}\n`));
|
|
57
57
|
|
|
58
58
|
// Parse command line arguments
|
|
59
59
|
program
|