UNPKG

google-oauth-cli-generator

Version:

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

342 lines (303 loc) 9.39 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateVanillaTemplate = generateVanillaTemplate; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); async function generateVanillaTemplate(data) { const { projectPath } = data; const frontendPath = path_1.default.join(projectPath, 'frontend'); // Create vanilla JS directory structure await fs_extra_1.default.ensureDir(path_1.default.join(frontendPath, 'src')); await fs_extra_1.default.ensureDir(path_1.default.join(frontendPath, 'public')); // Generate package.json const packageJson = { name: `${data.config.projectName}-frontend`, version: '1.0.0', private: true, scripts: { dev: 'vite', build: 'vite build', preview: 'vite preview' }, devDependencies: { vite: '^4.4.9' } }; await fs_extra_1.default.writeFile(path_1.default.join(frontendPath, 'package.json'), JSON.stringify(packageJson, null, 2)); // Generate vite.config.js const viteConfig = `import { defineConfig } from 'vite' export default defineConfig({ server: { port: 3000, proxy: { '/api': { target: 'http://localhost:5000', changeOrigin: true } } } })`; await fs_extra_1.default.writeFile(path_1.default.join(frontendPath, 'vite.config.js'), viteConfig); // Generate index.html const indexHtml = `<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>${data.config.projectName}</title> <link rel="stylesheet" href="/src/style.css" /> </head> <body> <div id="app"> <header class="app-header"> <h1>🚀 ${data.config.projectName}</h1> <p>Google OAuth Authentication Demo</p> </header> <main class="app-main"> <div id="loading" class="loading">Loading...</div> <div id="login-container" class="login-container" style="display: none;"> <h2>Welcome! Please sign in</h2> <button id="login-btn" class="google-login-btn"> <svg class="google-icon" viewBox="0 0 24 24"> <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/> <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/> <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/> <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/> </svg> Sign in with Google </button> </div> <div id="profile-container" class="profile-container" style="display: none;"> <div class="profile-card"> <img id="profile-picture" class="profile-picture" alt="Profile" /> <h2 id="profile-name">Welcome!</h2> <p id="profile-email" class="profile-email"></p> <button id="logout-btn" class="logout-btn">Sign Out</button> </div> </div> </main> </div> <script type="module" src="/src/main.js"></script> </body> </html>`; await fs_extra_1.default.writeFile(path_1.default.join(frontendPath, 'index.html'), indexHtml); // Generate main.js const mainJs = `class AuthApp { constructor() { this.user = null; this.loadingEl = document.getElementById('loading'); this.loginContainer = document.getElementById('login-container'); this.profileContainer = document.getElementById('profile-container'); this.loginBtn = document.getElementById('login-btn'); this.logoutBtn = document.getElementById('logout-btn'); this.init(); } async init() { this.bindEvents(); await this.checkAuthStatus(); } bindEvents() { this.loginBtn.addEventListener('click', this.handleLogin.bind(this)); this.logoutBtn.addEventListener('click', this.handleLogout.bind(this)); } async checkAuthStatus() { try { const response = await fetch('/api/auth/user', { credentials: 'include' }); if (response.ok) { this.user = await response.json(); this.showProfile(); } else { this.showLogin(); } } catch (error) { console.error('Auth check failed:', error); this.showLogin(); } finally { this.hideLoading(); } } handleLogin() { window.location.href = '/api/auth/google'; } async handleLogout() { try { await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' }); this.user = null; this.showLogin(); } catch (error) { console.error('Logout failed:', error); } } hideLoading() { this.loadingEl.style.display = 'none'; } showLogin() { this.loginContainer.style.display = 'block'; this.profileContainer.style.display = 'none'; } showProfile() { if (!this.user) return; document.getElementById('profile-picture').src = this.user.picture; document.getElementById('profile-picture').alt = this.user.name; document.getElementById('profile-name').textContent = \`Welcome, \${this.user.name}!\`; document.getElementById('profile-email').textContent = this.user.email; this.profileContainer.style.display = 'block'; this.loginContainer.style.display = 'none'; } } // Initialize the app when the DOM is loaded document.addEventListener('DOMContentLoaded', () => { new AuthApp(); });`; await fs_extra_1.default.writeFile(path_1.default.join(frontendPath, 'src', 'main.js'), mainJs); // Generate style.css const styleCss = `* { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #app { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 2rem; } .app-header h1 { font-size: 3rem; margin-bottom: 0.5rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); text-align: center; } .app-header p { font-size: 1.2rem; opacity: 0.9; margin-bottom: 2rem; text-align: center; } .loading { font-size: 1.5rem; animation: pulse 1.5s ease-in-out infinite alternate; } @keyframes pulse { from { opacity: 0.6; } to { opacity: 1; } } .login-container { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 20px; padding: 3rem; box-shadow: 0 8px 32px rgba(0,0,0,0.1); border: 1px solid rgba(255, 255, 255, 0.2); text-align: center; } .login-container h2 { margin-bottom: 2rem; font-size: 1.8rem; } .google-login-btn { display: flex; align-items: center; justify-content: center; gap: 12px; background: white; color: #333; border: none; border-radius: 12px; padding: 16px 32px; font-size: 16px; font-weight: 500; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .google-login-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,0.2); } .google-icon { width: 20px; height: 20px; } .profile-container { display: flex; justify-content: center; align-items: center; } .profile-card { background: rgba(255, 255, 255, 0.1); backdrop-filter: blur(10px); border-radius: 20px; padding: 3rem; box-shadow: 0 8px 32px rgba(0,0,0,0.1); border: 1px solid rgba(255, 255, 255, 0.2); text-align: center; } .profile-picture { width: 120px; height: 120px; border-radius: 50%; margin-bottom: 1.5rem; border: 4px solid rgba(255, 255, 255, 0.3); box-shadow: 0 4px 12px rgba(0,0,0,0.2); } .profile-card h2 { margin-bottom: 0.5rem; font-size: 2rem; } .profile-email { opacity: 0.8; margin-bottom: 2rem; font-size: 1.1rem; } .logout-btn { background: rgba(255, 255, 255, 0.2); color: white; border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 12px; padding: 12px 24px; font-size: 16px; cursor: pointer; transition: all 0.3s ease; } .logout-btn:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); } @media (max-width: 768px) { .app-header h1 { font-size: 2rem; } .login-container, .profile-card { padding: 2rem; margin: 0 1rem; } .profile-picture { width: 100px; height: 100px; } }`; await fs_extra_1.default.writeFile(path_1.default.join(frontendPath, 'src', 'style.css'), styleCss); } //# sourceMappingURL=vanilla-template.js.map