forgestack-os-cli 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.
Files changed (82) hide show
  1. package/dist/commands/create.d.ts +1 -0
  2. package/dist/commands/create.d.ts.map +1 -0
  3. package/dist/commands/create.js +78 -0
  4. package/dist/commands/create.js.map +1 -0
  5. package/dist/generators/api.d.ts +3 -0
  6. package/dist/generators/api.d.ts.map +1 -0
  7. package/dist/generators/api.js +346 -0
  8. package/dist/generators/api.js.map +1 -0
  9. package/dist/generators/auth.d.ts +2 -0
  10. package/dist/generators/auth.d.ts.map +1 -0
  11. package/dist/generators/auth.js +371 -0
  12. package/dist/generators/auth.js.map +1 -0
  13. package/dist/generators/backend.d.ts +2 -0
  14. package/dist/generators/backend.d.ts.map +1 -0
  15. package/dist/generators/backend.js +875 -0
  16. package/dist/generators/backend.js.map +1 -0
  17. package/dist/generators/common.d.ts +2 -0
  18. package/dist/generators/common.d.ts.map +1 -0
  19. package/dist/generators/common.js +354 -0
  20. package/dist/generators/common.js.map +1 -0
  21. package/dist/generators/database.d.ts +2 -0
  22. package/dist/generators/database.d.ts.map +1 -0
  23. package/dist/generators/database.js +157 -0
  24. package/dist/generators/database.js.map +1 -0
  25. package/dist/generators/docker.d.ts +2 -0
  26. package/dist/generators/docker.d.ts.map +1 -0
  27. package/dist/generators/docker.js +181 -0
  28. package/dist/generators/docker.js.map +1 -0
  29. package/dist/generators/frontend-helpers.d.ts +3 -0
  30. package/dist/generators/frontend-helpers.d.ts.map +1 -0
  31. package/dist/generators/frontend-helpers.js +23 -0
  32. package/dist/generators/frontend-helpers.js.map +1 -0
  33. package/dist/generators/frontend.d.ts +2 -0
  34. package/dist/generators/frontend.d.ts.map +1 -0
  35. package/dist/generators/frontend.js +735 -0
  36. package/dist/generators/frontend.js.map +1 -0
  37. package/dist/generators/index.d.ts +2 -0
  38. package/dist/generators/index.d.ts.map +1 -0
  39. package/dist/generators/index.js +59 -0
  40. package/dist/generators/index.js.map +1 -0
  41. package/dist/generators/nextjs-helpers.d.ts +6 -0
  42. package/dist/generators/nextjs-helpers.d.ts.map +1 -0
  43. package/dist/generators/nextjs-helpers.js +216 -0
  44. package/dist/generators/nextjs-helpers.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +24 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/types.d.ts +15 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +3 -0
  52. package/dist/types.js.map +1 -0
  53. package/dist/utils/logger.d.ts +9 -0
  54. package/dist/utils/logger.d.ts.map +1 -0
  55. package/dist/utils/logger.js +32 -0
  56. package/dist/utils/logger.js.map +1 -0
  57. package/dist/utils/prompts.d.ts +2 -0
  58. package/dist/utils/prompts.d.ts.map +1 -0
  59. package/dist/utils/prompts.js +107 -0
  60. package/dist/utils/prompts.js.map +1 -0
  61. package/dist/utils/validators.d.ts +2 -0
  62. package/dist/utils/validators.d.ts.map +1 -0
  63. package/dist/utils/validators.js +48 -0
  64. package/dist/utils/validators.js.map +1 -0
  65. package/package.json +49 -0
  66. package/src/commands/create.ts +82 -0
  67. package/src/generators/api.ts +353 -0
  68. package/src/generators/auth.ts +406 -0
  69. package/src/generators/backend.ts +927 -0
  70. package/src/generators/common.ts +377 -0
  71. package/src/generators/database.ts +165 -0
  72. package/src/generators/docker.ts +185 -0
  73. package/src/generators/frontend.ts +783 -0
  74. package/src/generators/index.ts +64 -0
  75. package/src/index.ts +27 -0
  76. package/src/types.ts +16 -0
  77. package/src/utils/logger.ts +31 -0
  78. package/src/utils/prompts.ts +105 -0
  79. package/src/utils/validators.ts +50 -0
  80. package/tests/validators.test.ts +69 -0
  81. package/tsc_output.txt +0 -0
  82. package/tsconfig.json +21 -0
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateAuth = generateAuth;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ async function generateAuth(config, frontendDir, backendDir) {
10
+ switch (config.auth) {
11
+ case 'jwt':
12
+ await generateJWTAuth(config, frontendDir, backendDir);
13
+ break;
14
+ case 'clerk':
15
+ await generateClerkAuth(config, frontendDir, backendDir);
16
+ break;
17
+ case 'supabase':
18
+ await generateSupabaseAuth(config, frontendDir, backendDir);
19
+ break;
20
+ case 'authjs':
21
+ await generateAuthJS(config, frontendDir, backendDir);
22
+ break;
23
+ case 'firebase':
24
+ await generateFirebaseAuth(config, frontendDir, backendDir);
25
+ break;
26
+ default:
27
+ throw new Error(`Unsupported auth: ${config.auth}`);
28
+ }
29
+ }
30
+ async function generateJWTAuth(config, frontendDir, backendDir) {
31
+ // Backend: Auth routes
32
+ const authRoutes = `import { Router } from 'express';
33
+ import bcrypt from 'bcrypt';
34
+ import jwt from 'jsonwebtoken';
35
+ import { z } from 'zod';
36
+ ${config.database === 'mongodb' ? "import User from '../models/User';" : "import prisma from '../lib/prisma';"}
37
+
38
+ const router = Router();
39
+
40
+ const registerSchema = z.object({
41
+ email: z.string().email(),
42
+ password: z.string().min(8),
43
+ 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
+ });
51
+
52
+ router.post('/register', async (req, res, next) => {
53
+ try {
54
+ const data = registerSchema.parse(req.body);
55
+
56
+ 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
+
86
+ res.json({ token, user: { id: user.id, email: user.email, name: user.name } });
87
+ } catch (error) {
88
+ next(error);
89
+ }
90
+ });
91
+
92
+ router.post('/login', async (req, res, next) => {
93
+ 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
+
124
+ res.json({ token, user: { id: user.id, email: user.email, name: user.name } });
125
+ } catch (error) {
126
+ next(error);
127
+ }
128
+ });
129
+
130
+ export default router;
131
+ `;
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';
137
+
138
+ interface User {
139
+ id: string;
140
+ email: string;
141
+ name?: string;
142
+ }
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;
150
+ }
151
+
152
+ const AuthContext = createContext<AuthContextType | undefined>(undefined);
153
+
154
+ export function AuthProvider({ children }: { children: React.ReactNode }) {
155
+ const [user, setUser] = useState<User | null>(null);
156
+ const [isLoading, setIsLoading] = useState(true);
157
+
158
+ useEffect(() => {
159
+ const token = localStorage.getItem('token');
160
+ 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));
166
+ } else {
167
+ setIsLoading(false);
168
+ }
169
+ }, []);
170
+
171
+ const login = async (email: string, password: string) => {
172
+ const res = await api.post('/auth/login', { email, password });
173
+ localStorage.setItem('token', res.data.token);
174
+ setUser(res.data.user);
175
+ };
176
+
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
+ const logout = () => {
184
+ localStorage.removeItem('token');
185
+ setUser(null);
186
+ };
187
+
188
+ return (
189
+ <AuthContext.Provider value={{ user, login, register, logout, isLoading }}>
190
+ {children}
191
+ </AuthContext.Provider>
192
+ );
193
+ }
194
+
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
+ }
202
+ `;
203
+ const frontendLibDir = path_1.default.join(frontendDir, 'src', 'lib');
204
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendLibDir, 'auth.tsx'), authContext);
205
+ // Frontend: Login page
206
+ const loginPage = `import { useState } from 'react';
207
+ import { useNavigate } from 'react-router-dom';
208
+ import { useAuth } from '../lib/auth';
209
+
210
+ export default function LoginPage() {
211
+ const [email, setEmail] = useState('');
212
+ const [password, setPassword] = useState('');
213
+ const [error, setError] = useState('');
214
+ const { login } = useAuth();
215
+ const navigate = useNavigate();
216
+
217
+ const handleSubmit = async (e: React.FormEvent) => {
218
+ e.preventDefault();
219
+ try {
220
+ await login(email, password);
221
+ navigate('/dashboard');
222
+ } catch (err: any) {
223
+ setError(err.response?.data?.error || 'Login failed');
224
+ }
225
+ };
226
+
227
+ return (
228
+ <div className="min-h-screen flex items-center justify-center bg-gray-900">
229
+ <div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full max-w-md">
230
+ <h1 className="text-3xl font-bold text-white mb-6">Login</h1>
231
+ {error && <div className="bg-red-500 text-white p-3 rounded mb-4">{error}</div>}
232
+ <form onSubmit={handleSubmit}>
233
+ <div className="mb-4">
234
+ <label className="block text-gray-300 mb-2">Email</label>
235
+ <input
236
+ type="email"
237
+ value={email}
238
+ onChange={(e) => setEmail(e.target.value)}
239
+ className="w-full p-3 rounded bg-gray-700 text-white"
240
+ required
241
+ />
242
+ </div>
243
+ <div className="mb-6">
244
+ <label className="block text-gray-300 mb-2">Password</label>
245
+ <input
246
+ type="password"
247
+ value={password}
248
+ onChange={(e) => setPassword(e.target.value)}
249
+ className="w-full p-3 rounded bg-gray-700 text-white"
250
+ required
251
+ />
252
+ </div>
253
+ <button
254
+ type="submit"
255
+ className="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded"
256
+ >
257
+ Login
258
+ </button>
259
+ </form>
260
+ </div>
261
+ </div>
262
+ );
263
+ }
264
+ `;
265
+ const pagesDir = path_1.default.join(frontendDir, 'src', 'pages');
266
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'LoginPage.tsx'), loginPage);
267
+ // Frontend: Home page
268
+ const homePage = `export default function HomePage() {
269
+ return (
270
+ <div className="min-h-screen bg-gray-900 text-white">
271
+ <div className="container mx-auto px-4 py-16">
272
+ <h1 className="text-5xl font-bold mb-4">${config.projectName}</h1>
273
+ <p className="text-xl text-gray-400 mb-8">
274
+ Generated by ForgeStack OS
275
+ </p>
276
+ <div className="space-x-4">
277
+ <a
278
+ href="/login"
279
+ className="inline-block bg-blue-600 hover:bg-blue-700 px-6 py-3 rounded font-semibold"
280
+ >
281
+ Get Started
282
+ </a>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ );
287
+ }
288
+ `;
289
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'HomePage.tsx'), homePage);
290
+ // Frontend: Dashboard page
291
+ const dashboardPage = `import { useAuth } from '../lib/auth';
292
+ import { useNavigate } from 'react-router-dom';
293
+ import { useEffect } from 'react';
294
+
295
+ export default function DashboardPage() {
296
+ const { user, logout, isLoading } = useAuth();
297
+ const navigate = useNavigate();
298
+
299
+ useEffect(() => {
300
+ if (!isLoading && !user) {
301
+ navigate('/login');
302
+ }
303
+ }, [user, isLoading, navigate]);
304
+
305
+ if (isLoading) {
306
+ return <div className="min-h-screen bg-gray-900 flex items-center justify-center">
307
+ <div className="text-white">Loading...</div>
308
+ </div>;
309
+ }
310
+
311
+ return (
312
+ <div className="min-h-screen bg-gray-900 text-white">
313
+ <nav className="bg-gray-800 p-4">
314
+ <div className="container mx-auto flex justify-between items-center">
315
+ <h1 className="text-2xl font-bold">${config.projectName}</h1>
316
+ <button
317
+ onClick={logout}
318
+ className="bg-red-600 hover:bg-red-700 px-4 py-2 rounded"
319
+ >
320
+ Logout
321
+ </button>
322
+ </div>
323
+ </nav>
324
+ <div className="container mx-auto px-4 py-16">
325
+ <h2 className="text-3xl font-bold mb-4">Welcome, {user?.name || user?.email}!</h2>
326
+ <p className="text-gray-400">You're logged in to your dashboard.</p>
327
+ </div>
328
+ </div>
329
+ );
330
+ }
331
+ `;
332
+ await fs_extra_1.default.writeFile(path_1.default.join(pagesDir, 'DashboardPage.tsx'), dashboardPage);
333
+ }
334
+ async function generateClerkAuth(config, frontendDir, backendDir) {
335
+ // Placeholder for Clerk integration
336
+ // Will be implemented in Phase 2
337
+ const readme = `# Clerk Authentication
338
+
339
+ To complete Clerk setup:
340
+
341
+ 1. Create a Clerk account at https://clerk.com
342
+ 2. Create a new application
343
+ 3. Copy your API keys to .env
344
+ 4. Install Clerk SDK: npm install @clerk/clerk-react
345
+ 5. Wrap your app with ClerkProvider
346
+
347
+ See Clerk documentation for details.
348
+ `;
349
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'CLERK_SETUP.md'), readme);
350
+ }
351
+ async function generateSupabaseAuth(config, frontendDir, backendDir) {
352
+ // Placeholder
353
+ const readme = `# Supabase Authentication
354
+
355
+ To complete Supabase Auth setup:
356
+
357
+ 1. Create a Supabase project at https://supabase.com
358
+ 2. Copy your project URL and anon key to .env
359
+ 3. Configure auth providers in Supabase dashboard
360
+
361
+ See Supabase documentation for details.
362
+ `;
363
+ await fs_extra_1.default.writeFile(path_1.default.join(frontendDir, 'SUPABASE_SETUP.md'), readme);
364
+ }
365
+ async function generateAuthJS(config, frontendDir, backendDir) {
366
+ throw new Error('Auth.js support coming in Phase 2');
367
+ }
368
+ async function generateFirebaseAuth(config, frontendDir, backendDir) {
369
+ throw new Error('Firebase Auth support coming in Phase 2');
370
+ }
371
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/generators/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { StackConfig } from '../types';
2
+ export declare function generateBackend(config: StackConfig, backendDir: string): Promise<void>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/generators/backend.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAoB5E"}