UNPKG

google-oauth-cli-generator

Version:

CLI tool to quickly set up Google OAuth authentication for hackathons and projects

268 lines (242 loc) 8.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateExpressTemplate = generateExpressTemplate; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); async function generateExpressTemplate(data) { const { projectPath, config } = data; const backendPath = path_1.default.join(projectPath, 'backend'); // Create Express directory structure await fs_extra_1.default.ensureDir(path_1.default.join(backendPath, 'src', 'routes')); await fs_extra_1.default.ensureDir(path_1.default.join(backendPath, 'src', 'middleware')); await fs_extra_1.default.ensureDir(path_1.default.join(backendPath, 'src', 'config')); if (config.database !== 'none') { await fs_extra_1.default.ensureDir(path_1.default.join(backendPath, 'src', 'models')); } // Generate package.json const packageJson = { name: `${config.projectName}-backend`, version: '1.0.0', private: true, scripts: { dev: 'nodemon src/index.ts', build: 'tsc', start: 'node dist/index.js', 'build:start': 'npm run build && npm run start' }, dependencies: { express: '^4.18.2', 'passport': '^0.6.0', 'passport-google-oauth20': '^2.0.0', 'express-session': '^1.17.3', cors: '^2.8.5', dotenv: '^16.3.1', ...(config.database === 'mongodb' && { mongoose: '^7.5.0' }), ...(config.database === 'postgresql' && { pg: '^8.11.3', '@types/pg': '^8.10.2' }) }, devDependencies: { '@types/node': '^20.8.0', '@types/express': '^4.17.17', '@types/passport': '^1.0.12', '@types/passport-google-oauth20': '^2.0.11', '@types/express-session': '^1.17.7', '@types/cors': '^2.8.14', typescript: '^5.2.2', 'ts-node': '^10.9.1', nodemon: '^3.0.1' } }; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'package.json'), JSON.stringify(packageJson, null, 2)); // Generate tsconfig.json const tsConfig = { compilerOptions: { target: 'ES2020', module: 'commonjs', lib: ['ES2020'], outDir: './dist', rootDir: './src', strict: true, esModuleInterop: true, skipLibCheck: true, forceConsistentCasingInFileNames: true, resolveJsonModule: true }, include: ['src/**/*'], exclude: ['node_modules', 'dist'] }; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2)); // Generate main server file const indexTs = `import express from 'express'; import session from 'express-session'; import passport from 'passport'; import cors from 'cors'; import dotenv from 'dotenv'; import authRoutes from './routes/auth'; import { setupPassport } from './config/passport'; ${config.database === 'mongodb' ? "import { connectDatabase } from './config/database';" : ''} dotenv.config(); const app = express(); const PORT = process.env.PORT || 5000; // Middleware app.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:3000', credentials: true })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Session configuration app.use(session({ secret: process.env.SESSION_SECRET || 'your-session-secret', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', maxAge: 24 * 60 * 60 * 1000 // 24 hours } })); // Passport middleware app.use(passport.initialize()); app.use(passport.session()); // Setup passport strategies setupPassport(); // Routes app.use('/api/auth', authRoutes); // Health check app.get('/api/health', (req, res) => { res.json({ status: 'OK', message: 'Server is running' }); }); // Start server const startServer = async () => { try { ${config.database === 'mongodb' ? 'await connectDatabase();' : ''} app.listen(PORT, () => { console.log(\`🚀 Server running on port \${PORT}\`); console.log(\`📱 Frontend: \${process.env.FRONTEND_URL || 'http://localhost:3000'}\`); console.log(\`🔐 Google OAuth configured: \${process.env.GOOGLE_CLIENT_ID ? '✅' : '❌'}\`); }); } catch (error) { console.error('Failed to start server:', error); process.exit(1); } }; startServer();`; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'src', 'index.ts'), indexTs); // Generate passport configuration const passportTs = `import passport from 'passport'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; ${config.database !== 'none' ? "import { User } from '../models/User';" : ''} interface UserProfile { id: string; name: string; email: string; picture: string; } ${config.database === 'none' ? ` // In-memory user storage (for demo purposes only) const users: Map<string, UserProfile> = new Map(); ` : ''} export function setupPassport() { passport.use(new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, callbackURL: "/api/auth/google/callback" }, async (accessToken, refreshToken, profile, done) => { try { const userProfile: UserProfile = { id: profile.id, name: profile.displayName || 'Unknown', email: profile.emails?.[0]?.value || '', picture: profile.photos?.[0]?.value || '' }; ${config.database === 'none' ? ` // Store user in memory users.set(profile.id, userProfile); return done(null, userProfile); ` : ` // Check if user exists in database let user = await User.findByGoogleId(profile.id); if (!user) { // Create new user user = await User.create(userProfile); } else { // Update existing user user = await User.update(profile.id, userProfile); } return done(null, user); `} } catch (error) { return done(error as Error, undefined); } })); passport.serializeUser((user: any, done) => { done(null, user.id); }); passport.deserializeUser(async (id: string, done) => { try { ${config.database === 'none' ? ` const user = users.get(id); done(null, user || null); ` : ` const user = await User.findByGoogleId(id); done(null, user); `} } catch (error) { done(error, null); } }); }`; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'src', 'config', 'passport.ts'), passportTs); // Generate auth routes const authRoutesTs = `import express from 'express'; import passport from 'passport'; const router = express.Router(); // Google OAuth login router.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] }) ); // Google OAuth callback router.get('/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (req, res) => { // Successful authentication res.redirect(process.env.FRONTEND_URL || 'http://localhost:3000'); } ); // Get current user router.get('/user', (req, res) => { if (req.isAuthenticated()) { res.json(req.user); } else { res.status(401).json({ error: 'Not authenticated' }); } }); // Logout router.post('/logout', (req, res) => { req.logout((err) => { if (err) { return res.status(500).json({ error: 'Logout failed' }); } res.json({ message: 'Logged out successfully' }); }); }); export default router;`; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'src', 'routes', 'auth.ts'), authRoutesTs); // Generate nodemon config const nodemonJson = { watch: ['src'], ext: 'ts', ignore: ['src/**/*.test.ts'], exec: 'ts-node src/index.ts' }; await fs_extra_1.default.writeFile(path_1.default.join(backendPath, 'nodemon.json'), JSON.stringify(nodemonJson, null, 2)); } //# sourceMappingURL=express-template.js.map