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
JavaScript
"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