forgestack-os-cli 0.2.0 → 0.3.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.
@@ -26,11 +26,62 @@ async function generateAuth(config, frontendDir, backendDir) {
26
26
  default:
27
27
  throw new Error(`Unsupported auth: ${config.auth}`);
28
28
  }
29
+ // Ensure frontend pages exist for all auth types
30
+ await generateFrontendAuthPages(config, frontendDir);
29
31
  }
30
- async function generateJWTAuth(config, frontendDir, backendDir) {
31
- // Backend: Auth routes
32
- const authRoutes = `import { Router } from 'express';
33
- import bcrypt from 'bcrypt';
32
+ async function generateJWTAuth(config, _frontendDir, backendDir) {
33
+ // Backend: Auth logic
34
+ if (config.backend === 'express') {
35
+ const routesDir = path_1.default.join(backendDir, 'src', 'routes');
36
+ await fs_extra_1.default.ensureDir(routesDir);
37
+ await fs_extra_1.default.writeFile(path_1.default.join(routesDir, 'auth.ts'), getExpressAuthRoutes(config));
38
+ }
39
+ else if (config.backend === 'fastify') {
40
+ const routesDir = path_1.default.join(backendDir, 'src', 'routes');
41
+ await fs_extra_1.default.ensureDir(routesDir);
42
+ await fs_extra_1.default.writeFile(path_1.default.join(routesDir, 'auth.ts'), getFastifyAuthRoutes(config));
43
+ }
44
+ else if (config.backend === 'nestjs') {
45
+ await generateNestJSAuth(config, backendDir);
46
+ }
47
+ // Isolation: Add .eslintrc.json to prevent parent config inheritance
48
+ const eslintConfig = {
49
+ root: true,
50
+ extends: ["eslint:recommended"],
51
+ env: { node: true, es2021: true }
52
+ };
53
+ await fs_extra_1.default.writeJSON(path_1.default.join(backendDir, '.eslintrc.json'), eslintConfig, { spaces: 2 });
54
+ }
55
+ async function generateFrontendAuthPages(config, frontendDir) {
56
+ const isNext = config.frontend === 'nextjs';
57
+ const frontendLibDir = path_1.default.join(frontendDir, isNext ? 'app/lib' : 'src/lib');
58
+ await fs_extra_1.default.ensureDir(frontendLibDir);
59
+ // Always generate auth context file for JWT-based auth
60
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendLibDir, 'auth.tsx'), getAuthContextCode());
61
+ if (isNext) {
62
+ const nextEslint = {
63
+ root: true,
64
+ extends: ["next/core-web-vitals"]
65
+ };
66
+ await fs_extra_1.default.writeJSON(path_1.default.join(frontendDir, '.eslintrc.json'), nextEslint, { spaces: 2 });
67
+ const authAppDir = path_1.default.join(frontendDir, 'app');
68
+ await fs_extra_1.default.ensureDir(path_1.default.join(authAppDir, 'login'));
69
+ await fs_extra_1.default.ensureDir(path_1.default.join(authAppDir, 'dashboard'));
70
+ await fs_extra_1.default.writeFile(path_1.default.join(authAppDir, 'login', 'page.tsx'), getLoginPageCode(config));
71
+ await fs_extra_1.default.writeFile(path_1.default.join(authAppDir, 'dashboard', 'page.tsx'), getDashboardPageCode(config));
72
+ await fs_extra_1.default.writeFile(path_1.default.join(authAppDir, 'page.tsx'), getHomePageCode(config));
73
+ }
74
+ else {
75
+ const pagesDir = path_1.default.join(frontendDir, 'src', 'pages');
76
+ await fs_extra_1.default.ensureDir(pagesDir);
77
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'LoginPage.tsx'), getLoginPageCode(config));
78
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'HomePage.tsx'), getHomePageCode(config));
79
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'DashboardPage.tsx'), getDashboardPageCode(config));
80
+ }
81
+ }
82
+ function getExpressAuthRoutes(config) {
83
+ return `import { Router } from 'express';
84
+ import bcrypt from 'bcryptjs';
34
85
  import jwt from 'jsonwebtoken';
35
86
  import { z } from 'zod';
36
87
  ${config.database === 'mongodb' ? "import User from '../models/User';" : "import prisma from '../lib/prisma';"}
@@ -41,128 +92,108 @@ const registerSchema = z.object({
41
92
  email: z.string().email(),
42
93
  password: z.string().min(8),
43
94
  name: z.string().optional(),
44
- ${config.multiTenant ? 'tenantId: z.string(),' : ''}
45
- });
46
-
47
- const loginSchema = z.object({
48
- email: z.string().email(),
49
- password: z.string(),
50
95
  });
51
96
 
52
97
  router.post('/register', async (req, res, next) => {
53
98
  try {
54
99
  const data = registerSchema.parse(req.body);
55
-
56
100
  const hashedPassword = await bcrypt.hash(data.password, 10);
57
-
58
- ${config.database === 'mongodb' ? `
59
- const user = await User.create({
60
- email: data.email,
61
- password: hashedPassword,
62
- name: data.name,
63
- ${config.multiTenant ? 'tenantId: data.tenantId,' : ''}
64
- });
65
- ` : `
66
- const user = await prisma.user.create({
67
- data: {
68
- email: data.email,
69
- password: hashedPassword,
70
- name: data.name,
71
- ${config.multiTenant ? 'tenantId: data.tenantId,' : ''}
72
- },
73
- });
74
- `}
75
-
76
- const token = jwt.sign(
77
- {
78
- userId: user.id,
79
- email: user.email,
80
- ${config.multiTenant ? 'tenantId: user.tenantId,' : ''}
81
- },
82
- process.env.JWT_SECRET!,
83
- { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
84
- );
85
-
101
+ const user = ${config.database === 'mongodb' ? `await User.create({ email: data.email, password: hashedPassword, name: data.name })` : `await prisma.user.create({ data: { email: data.email, password: hashedPassword, name: data.name } })`};
102
+ const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET || '${config.jwtSecret}', { expiresIn: '7d' });
86
103
  res.json({ token, user: { id: user.id, email: user.email, name: user.name } });
87
- } catch (error) {
88
- next(error);
89
- }
104
+ } catch (error) { next(error); }
90
105
  });
91
106
 
92
107
  router.post('/login', async (req, res, next) => {
93
108
  try {
94
- const data = loginSchema.parse(req.body);
95
-
96
- ${config.database === 'mongodb' ? `
97
- const user = await User.findOne({ email: data.email });
98
- ` : `
99
- const user = await prisma.user.findUnique({
100
- where: { email: data.email },
101
- });
102
- `}
103
-
104
- if (!user || !user.password) {
105
- return res.status(401).json({ error: 'Invalid credentials' });
106
- }
107
-
108
- const validPassword = await bcrypt.compare(data.password, user.password);
109
-
110
- if (!validPassword) {
111
- return res.status(401).json({ error: 'Invalid credentials' });
112
- }
113
-
114
- const token = jwt.sign(
115
- {
116
- userId: user.id,
117
- email: user.email,
118
- ${config.multiTenant ? 'tenantId: user.tenantId,' : ''}
119
- },
120
- process.env.JWT_SECRET!,
121
- { expiresIn: process.env.JWT_EXPIRES_IN || '7d' }
122
- );
123
-
109
+ const { email, password } = req.body;
110
+ const user = ${config.database === 'mongodb' ? `await User.findOne({ email })` : `await prisma.user.findUnique({ where: { email } })`};
111
+ if (!user || !(await bcrypt.compare(password, user.password))) return res.status(401).json({ error: 'Invalid credentials' });
112
+ const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET || '${config.jwtSecret}', { expiresIn: '7d' });
124
113
  res.json({ token, user: { id: user.id, email: user.email, name: user.name } });
125
- } catch (error) {
126
- next(error);
127
- }
114
+ } catch (error) { next(error); }
128
115
  });
129
116
 
130
117
  export default router;
131
118
  `;
132
- const routesDir = path_1.default.join(backendDir, 'src', 'routes');
133
- await fs_extra_1.default.writeFile(path_1.default.join(routesDir, 'auth.ts'), authRoutes);
134
- // Frontend: Auth context
135
- const authContext = `import React, { createContext, useContext, useState, useEffect } from 'react';
136
- import api from '../lib/api';
119
+ }
120
+ function getFastifyAuthRoutes(config) {
121
+ return `import { FastifyInstance } from 'fastify';
122
+ import bcrypt from 'bcrypt';
137
123
 
138
- interface User {
139
- id: string;
140
- email: string;
124
+ export default async function authRoutes(fastify: FastifyInstance) {
125
+ fastify.post('/register', async (request, reply) => {
126
+ reply.send({ success: true });
127
+ });
128
+ fastify.post('/login', async (request, reply) => {
129
+ reply.send({ token: '...' });
130
+ });
131
+ }
132
+ `;
133
+ }
134
+ async function generateNestJSAuth(config, backendDir) {
135
+ const authDir = path_1.default.join(backendDir, 'src', 'auth');
136
+ await fs_extra_1.default.ensureDir(authDir);
137
+ await fs_extra_1.default.ensureDir(path_1.default.join(authDir, 'dto'));
138
+ const controller = `import { Controller, Post, Body } from '@nestjs/common';
139
+ import { AuthService } from './auth.service';
140
+ import { RegisterDto, LoginDto } from './dto/auth.dto';
141
+
142
+ @Controller('auth')
143
+ export class AuthController {
144
+ constructor(private authService: AuthService) {}
145
+ @Post('register')
146
+ async register(@Body() dto: RegisterDto) { return this.authService.register(dto); }
147
+ @Post('login')
148
+ async login(@Body() dto: LoginDto) { return this.authService.login(dto); }
149
+ }
150
+ `;
151
+ await fs_extra_1.default.writeFile(path_1.default.join(authDir, 'auth.controller.ts'), controller);
152
+ const dto = `import { IsEmail, IsString, MinLength } from 'class-validator';
153
+ export class RegisterDto {
154
+ @IsEmail()
155
+ email!: string;
156
+ @IsString()
157
+ @MinLength(8)
158
+ password!: string;
159
+ @IsString()
141
160
  name?: string;
142
161
  }
143
-
144
- interface AuthContextType {
145
- user: User | null;
146
- login: (email: string, password: string) => Promise<void>;
147
- register: (email: string, password: string, name?: string) => Promise<void>;
148
- logout: () => void;
149
- isLoading: boolean;
162
+ export class LoginDto {
163
+ @IsEmail()
164
+ email!: string;
165
+ @IsString()
166
+ password!: string;
150
167
  }
168
+ `;
169
+ await fs_extra_1.default.writeFile(path_1.default.join(authDir, 'dto/auth.dto.ts'), dto);
170
+ const service = `import { Injectable } from '@nestjs/common';
171
+ import { JwtService } from '@nestjs/jwt';
172
+
173
+ @Injectable()
174
+ export class AuthService {
175
+ constructor(private jwtService: JwtService) {}
176
+ async register(dto: any) { return { success: true }; }
177
+ async login(user: any) { return { token: this.jwtService.sign({ id: '1' }) }; }
178
+ }
179
+ `;
180
+ await fs_extra_1.default.writeFile(path_1.default.join(authDir, 'auth.service.ts'), service);
181
+ }
182
+ function getAuthContextCode() {
183
+ return `'use client';
184
+ import React, { createContext, useContext, useState, useEffect } from 'react';
185
+ import api from '../lib/api';
151
186
 
152
- const AuthContext = createContext<AuthContextType | undefined>(undefined);
187
+ const AuthContext = createContext<any>(undefined);
153
188
 
154
189
  export function AuthProvider({ children }: { children: React.ReactNode }) {
155
- const [user, setUser] = useState<User | null>(null);
190
+ const [user, setUser] = useState(null);
156
191
  const [isLoading, setIsLoading] = useState(true);
157
192
 
158
193
  useEffect(() => {
159
194
  const token = localStorage.getItem('token');
160
195
  if (token) {
161
- // Verify token and get user
162
- api.get('/auth/me')
163
- .then(res => setUser(res.data.user))
164
- .catch(() => localStorage.removeItem('token'))
165
- .finally(() => setIsLoading(false));
196
+ api.get('/auth/me').then(res => setUser(res.data.user)).finally(() => setIsLoading(false));
166
197
  } else {
167
198
  setIsLoading(false);
168
199
  }
@@ -174,296 +205,86 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
174
205
  setUser(res.data.user);
175
206
  };
176
207
 
177
- const register = async (email: string, password: string, name?: string) => {
178
- const res = await api.post('/auth/register', { email, password, name });
179
- localStorage.setItem('token', res.data.token);
180
- setUser(res.data.user);
181
- };
182
-
183
208
  const logout = () => {
184
209
  localStorage.removeItem('token');
185
210
  setUser(null);
186
211
  };
187
212
 
188
- return (
189
- <AuthContext.Provider value={{ user, login, register, logout, isLoading }}>
190
- {children}
191
- </AuthContext.Provider>
192
- );
213
+ return <AuthContext.Provider value={{ user, login, logout, isLoading }}>{children}</AuthContext.Provider>;
193
214
  }
194
215
 
195
- export function useAuth() {
196
- const context = useContext(AuthContext);
197
- if (!context) {
198
- throw new Error('useAuth must be used within AuthProvider');
199
- }
200
- return context;
201
- }
216
+ export const useAuth = () => useContext(AuthContext);
202
217
  `;
203
- const frontendLibDir = path_1.default.join(frontendDir, config.frontend === 'nextjs' ? 'lib' : 'src/lib');
204
- // For Next.js, generateNextJS already handles auth pages and middleware.
205
- // We only need the backend routes and potentially the lib/auth.tsx if we
206
- // want a context, but Next.js template currently uses direct api calls.
207
- // To restore reliability, we skip frontend JWT auth files for Next.js for now.
208
- if (config.frontend === 'nextjs') {
209
- return;
210
- }
211
- await fs_extra_1.default.ensureDir(frontendLibDir);
212
- await fs_extra_1.default.writeFile(path_1.default.join(frontendLibDir, 'auth.tsx'), authContext);
213
- // Frontend: Login page
214
- const loginPage = `import { useState } from 'react';
215
- import { useNavigate } from 'react-router-dom';
216
- import { useAuth } from '../lib/auth';
218
+ }
219
+ function getLoginPageCode(config) {
220
+ const isNext = config.frontend === 'nextjs';
221
+ const authPath = isNext ? '../lib/auth' : '../lib/auth';
222
+ return `${isNext ? "'use client';" : ""}
223
+ import { useState } from 'react';
224
+ ${isNext ? "import { useRouter } from 'next/navigation';" : "import { useNavigate } from 'react-router-dom';"}
225
+ import { useAuth } from '${authPath}';
217
226
 
218
227
  export default function LoginPage() {
219
228
  const [email, setEmail] = useState('');
220
229
  const [password, setPassword] = useState('');
221
- const [error, setError] = useState('');
222
230
  const { login } = useAuth();
223
- const navigate = useNavigate();
231
+ ${isNext ? "const router = useRouter();" : "const navigate = useNavigate();"}
224
232
 
225
- const handleSubmit = async (e: React.FormEvent) => {
233
+ const handleSubmit = async (e: any) => {
226
234
  e.preventDefault();
227
- try {
228
- await login(email, password);
229
- navigate('/dashboard');
230
- } catch (err: any) {
231
- setError(err.response?.data?.error || 'Login failed');
232
- }
235
+ await login(email, password);
236
+ ${isNext ? "router.push('/dashboard');" : "navigate('/dashboard');"}
233
237
  };
234
238
 
235
239
  return (
236
240
  <div className="min-h-screen flex items-center justify-center bg-gray-900">
237
- <div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full max-w-md">
238
- <h1 className="text-3xl font-bold text-white mb-6">Login</h1>
239
- {error && <div className="bg-red-500 text-white p-3 rounded mb-4">{error}</div>}
240
- <form onSubmit={handleSubmit}>
241
- <div className="mb-4">
242
- <label className="block text-gray-300 mb-2">Email</label>
243
- <input
244
- type="email"
245
- value={email}
246
- onChange={(e) => setEmail(e.target.value)}
247
- className="w-full p-3 rounded bg-gray-700 text-white"
248
- required
249
- />
250
- </div>
251
- <div className="mb-6">
252
- <label className="block text-gray-300 mb-2">Password</label>
253
- <input
254
- type="password"
255
- value={password}
256
- onChange={(e) => setPassword(e.target.value)}
257
- className="w-full p-3 rounded bg-gray-700 text-white"
258
- required
259
- />
260
- </div>
261
- <button
262
- type="submit"
263
- className="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded"
264
- >
265
- Login
266
- </button>
267
- </form>
268
- </div>
241
+ <form onSubmit={handleSubmit} className="bg-gray-800 p-8 rounded shadow-lg">
242
+ <input type="email" value={email} onChange={e => setEmail(e.target.value)} className="block w-full mb-4 p-2 bg-gray-700 text-white" />
243
+ <input type="password" value={password} onChange={e => setPassword(e.target.value)} className="block w-full mb-4 p-2 bg-gray-700 text-white" />
244
+ <button type="submit" className="w-full bg-blue-600 p-2 text-white">Login</button>
245
+ </form>
269
246
  </div>
270
247
  );
271
248
  }
272
249
  `;
273
- const pagesDir = path_1.default.join(frontendDir, 'src', 'pages');
274
- await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'LoginPage.tsx'), loginPage);
275
- // Frontend: Home page
276
- const homePage = `export default function HomePage() {
250
+ }
251
+ function getHomePageCode(config) {
252
+ return `export default function HomePage() {
277
253
  return (
278
- <div className="min-h-screen bg-gray-900 text-white">
279
- <div className="container mx-auto px-4 py-16">
280
- <h1 className="text-5xl font-bold mb-4">${config.projectName}</h1>
281
- <p className="text-xl text-gray-400 mb-8">
282
- Generated by ForgeStack OS
283
- </p>
284
- <div className="space-x-4">
285
- <a
286
- href="/login"
287
- className="inline-block bg-blue-600 hover:bg-blue-700 px-6 py-3 rounded font-semibold"
288
- >
289
- Get Started
290
- </a>
291
- </div>
292
- </div>
254
+ <div className="min-h-screen bg-gray-900 text-white flex items-center justify-center">
255
+ <h1 className="text-4xl">${config.projectName}</h1>
293
256
  </div>
294
257
  );
295
258
  }
296
259
  `;
297
- await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'HomePage.tsx'), homePage);
298
- // Frontend: Dashboard page
299
- const dashboardPage = `import { useAuth } from '../lib/auth';
300
- import { useNavigate } from 'react-router-dom';
301
- import { useEffect } from 'react';
302
-
260
+ }
261
+ function getDashboardPageCode(config) {
262
+ const isNext = config.frontend === 'nextjs';
263
+ const authPath = isNext ? '../lib/auth' : '../lib/auth';
264
+ return `${isNext ? "'use client';" : ""}
265
+ import { useAuth } from '${authPath}';
303
266
  export default function DashboardPage() {
304
- const { user, logout, isLoading } = useAuth();
305
- const navigate = useNavigate();
306
-
307
- useEffect(() => {
308
- if (!isLoading && !user) {
309
- navigate('/login');
310
- }
311
- }, [user, isLoading, navigate]);
312
-
313
- if (isLoading) {
314
- return <div className="min-h-screen bg-gray-900 flex items-center justify-center">
315
- <div className="text-white">Loading...</div>
316
- </div>;
317
- }
318
-
267
+ const { user, logout } = useAuth();
319
268
  return (
320
- <div className="min-h-screen bg-gray-900 text-white">
321
- <nav className="bg-gray-800 p-4">
322
- <div className="container mx-auto flex justify-between items-center">
323
- <h1 className="text-2xl font-bold">${config.projectName}</h1>
324
- <button
325
- onClick={logout}
326
- className="bg-red-600 hover:bg-red-700 px-4 py-2 rounded"
327
- >
328
- Logout
329
- </button>
330
- </div>
331
- </nav>
332
- <div className="container mx-auto px-4 py-16">
333
- <h2 className="text-3xl font-bold mb-4">Welcome, {user?.name || user?.email}!</h2>
334
- <p className="text-gray-400">You're logged in to your dashboard.</p>
335
- </div>
269
+ <div className="min-h-screen bg-gray-900 text-white p-8">
270
+ <h1>Dashboard for ${config.projectName}</h1>
271
+ <p>Welcome, {user?.email}</p>
272
+ <button onClick={logout} className="bg-red-600 p-2 rounded">Logout</button>
336
273
  </div>
337
274
  );
338
275
  }
339
276
  `;
340
- await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'DashboardPage.tsx'), dashboardPage);
341
277
  }
342
278
  async function generateClerkAuth(config, frontendDir, _backendDir) {
343
- const isNextJS = config.frontend === 'nextjs';
344
- const clerkSetup = `# Clerk Authentication Setup
345
-
346
- 1. Create a Clerk account at https://clerk.com
347
- 2. Create a new application
348
- 3. Copy your API keys to .env
349
- 4. For ${isNextJS ? 'Next.js' : 'React'}, the components are already configured.
350
-
351
- Components used:
352
- - LoginPage: Uses Clerk's SignIn component
353
- - Dashboard: Uses Clerk's UserButton
354
- - Layout: ${isNextJS ? 'Configured with ClerkProvider' : 'Needs ClerkProvider in main.tsx'}
355
- `;
356
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'CLERK_SETUP.md'), clerkSetup);
357
- if (isNextJS) {
358
- // Next.js specific logic (mostly handled in generateNextJS)
359
- const middleware = `import { authMiddleware } from '@clerk/nextjs';
360
-
361
- export default authMiddleware({
362
- publicRoutes: ['/'],
363
- });
364
-
365
- export const config = {
366
- matcher: ['/((?!.+\\\\.[\\\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
367
- };
368
- `;
369
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'middleware.ts'), middleware);
370
- }
371
- else {
372
- // React+Vite specific logic
373
- const hook = `import { useAuth, useUser, SignInButton, SignOutButton } from "@clerk/clerk-react";
374
-
375
- export function AuthStatus() {
376
- const { isSignedIn, user } = useUser();
377
- if (isSignedIn) return <div>Hello {user.fullName} <SignOutButton /></div>;
378
- return <SignInButton />;
379
- }
380
- `;
381
- await fs_extra_1.default.ensureDir(path_1.default.join(frontendDir, 'src', 'components'));
382
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'src', 'components', 'AuthStatus.tsx'), hook);
383
- }
279
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'CLERK_SETUP.md'), '# Clerk Setup');
384
280
  }
385
281
  async function generateSupabaseAuth(config, frontendDir, _backendDir) {
386
- const isNextJS = config.frontend === 'nextjs';
387
- const supabaseSetup = `# Supabase Authentication Setup
388
-
389
- 1. Create a Supabase project at https://supabase.com
390
- 2. Copy your project URL and anon key to .env
391
- 3. Configure auth providers in Supabase dashboard
392
- 4. For ${isNextJS ? 'Next.js' : 'React'}, the clients are already configured in src/lib/supabase.ts.
393
- `;
394
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'SUPABASE_SETUP.md'), supabaseSetup);
395
- const supabaseClient = isNextJS
396
- ? `import { createBrowserClient } from '@supabase/ssr'
397
-
398
- export function createClient() {
399
- return createBrowserClient(
400
- process.env.NEXT_PUBLIC_SUPABASE_URL!,
401
- process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
402
- )
403
- }`
404
- : `import { createClient } from '@supabase/supabase-js'
405
-
406
- export const supabase = createClient(
407
- process.env.VITE_SUPABASE_URL!,
408
- process.env.VITE_SUPABASE_ANON_KEY!
409
- )`;
410
- const libDir = path_1.default.join(frontendDir, isNextJS ? 'lib' : 'src/lib');
411
- await fs_extra_1.default.ensureDir(libDir);
412
- await fs_extra_1.default.writeFile(path_1.default.join(libDir, 'supabase.ts'), supabaseClient);
282
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'SUPABASE_SETUP.md'), '# Supabase Setup');
413
283
  }
414
284
  async function generateAuthJS(config, frontendDir, _backendDir) {
415
- const isNextJS = config.frontend === 'nextjs';
416
- const authJSSetup = `# Auth.js (NextAuth) Setup
417
-
418
- 1. Configure providers in ${isNextJS ? 'app/api/auth/[...nextauth]/route.ts' : 'src/lib/auth.ts'}
419
- 2. Add provider credentials to .env
420
- 3. See https://authjs.dev for setup guides.
421
- `;
422
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'AUTHJS_SETUP.md'), authJSSetup);
423
- if (isNextJS) {
424
- const authRouteDir = path_1.default.join(frontendDir, 'app/api/auth/[...nextauth]');
425
- await fs_extra_1.default.ensureDir(authRouteDir);
426
- const authRoute = `import NextAuth from "next-auth"
427
- import GithubProvider from "next-auth/providers/github"
428
-
429
- export const authOptions = {
430
- providers: [
431
- GithubProvider({
432
- clientId: process.env.GITHUB_ID!,
433
- clientSecret: process.env.GITHUB_SECRET!,
434
- }),
435
- ],
436
- }
437
-
438
- const handler = NextAuth(authOptions)
439
- export { handler as GET, handler as POST }
440
- `;
441
- await fs_extra_1.default.writeFile(path_1.default.join(authRouteDir, 'route.ts'), authRoute);
442
- }
285
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'AUTHJS_SETUP.md'), '# Auth.js Setup');
443
286
  }
444
287
  async function generateFirebaseAuth(config, frontendDir, _backendDir) {
445
- const isNextJS = config.frontend === 'nextjs';
446
- const firebaseSetup = `# Firebase Auth Setup
447
-
448
- 1. Create a Firebase project at https://firebase.google.com
449
- 2. Enable authentication methods
450
- 3. Copy your project config to .env
451
- `;
452
- await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'FIREBASE_SETUP.md'), firebaseSetup);
453
- const firebaseConfig = `import { initializeApp } from "firebase/app";
454
- import { getAuth } from "firebase/auth";
455
-
456
- const firebaseConfig = {
457
- apiKey: process.env.${isNextJS ? 'NEXT_PUBLIC_' : 'VITE_'}FIREBASE_API_KEY,
458
- authDomain: process.env.${isNextJS ? 'NEXT_PUBLIC_' : 'VITE_'}FIREBASE_AUTH_DOMAIN,
459
- projectId: process.env.${isNextJS ? 'NEXT_PUBLIC_' : 'VITE_'}FIREBASE_PROJECT_ID,
460
- };
461
-
462
- const app = initializeApp(firebaseConfig);
463
- export const auth = getAuth(app);
464
- `;
465
- const libDir = path_1.default.join(frontendDir, isNextJS ? 'lib' : 'src/lib');
466
- await fs_extra_1.default.ensureDir(libDir);
467
- await fs_extra_1.default.writeFile(path_1.default.join(libDir, 'firebase.ts'), firebaseConfig);
288
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'FIREBASE_SETUP.md'), '# Firebase Setup');
468
289
  }
469
290
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/generators/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/generators/auth.ts"],"names":[],"mappings":"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"}