UNPKG

longcelot-sheet-db

Version:

Google Sheets-backed staging database adapter for Node.js with schema-first design

175 lines (171 loc) 7.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initCommand = initCommand; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); function printBanner() { const c = chalk_1.default.hex('#05b5fb').bold; const lines = [ '█ ██ █ █ ██ ███ ████ █ ██ ████ ███ █ █ ████ ████ ████ ███ ███ ', '█ █ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █', '█ █ █ █ ██ █ ██ █ ███ █ █ █ █ ██ ████ ███ ███ █ █ █ ███', '█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █', '████ ██ █ █ ███ ███ ████ ████ ██ █ ███ █ █ ████ ████ █ ███ ███', ]; console.log(); lines.forEach((line) => console.log(' ' + c(line))); console.log(); console.log(' ' + chalk_1.default.hex('#05b5fb')('Google Sheets-backed Staging Database Adapter')); console.log(); } async function initCommand(options) { printBanner(); if (options.integrate) { console.log(chalk_1.default.blue('Integrating into an existing project...\n')); } const defaultProjectName = path_1.default.basename(process.cwd()); const answers = await inquirer_1.default.prompt([ { type: 'input', name: 'projectName', message: 'Project name:', default: defaultProjectName, when: !options.integrate, }, { type: 'input', name: 'superAdminEmail', message: 'Super admin email:', validate: (input) => input.includes('@') || 'Please enter a valid email', }, { type: 'input', name: 'actors', message: 'Actors (comma-separated):', default: 'admin,user', filter: (input) => input.split(',').map((s) => s.trim()), }, ]); const projectName = options.integrate ? defaultProjectName : answers.projectName; const actorConfigs = answers.actors.map((role) => ({ name: role, sheetIdEnv: role === 'admin' ? 'ADMIN_SHEET_ID' : `DEV_${role.toUpperCase()}_SHEET_ID`, })); const configContent = `export default { projectName: "${projectName}", superAdminEmail: "${answers.superAdminEmail}", actors: ${JSON.stringify(actorConfigs, null, 2)}, // Schema mismatch behaviour: 'warn' | 'error' | 'auto-sync' onSchemaMismatch: 'warn', }; `; const nonAdminActors = answers.actors.filter((a) => a !== 'admin'); const devSheetVars = nonAdminActors .map((role) => `DEV_${role.toUpperCase()}_SHEET_ID=`) .join('\n'); const envContent = `# Google OAuth credentials # Get these at: https://console.cloud.google.com/apis/credentials GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= GOOGLE_REDIRECT_URI=http://localhost:3000/auth/callback # Your central admin Google Sheet ID # Create a blank Google Sheet and paste the ID from its URL here ADMIN_SHEET_ID= ${nonAdminActors.length > 0 ? `\n# Development actor sheet IDs (one per actor type)\n${devSheetVars}\n` : ''} # Super admin email (new user sheets will be shared with this account) SUPER_ADMIN_EMAIL=${answers.superAdminEmail} `; const hasExistingConfig = fs_1.default.existsSync('lsdb.config.ts') || fs_1.default.existsSync('sheet-db.config.ts'); if (!hasExistingConfig || !options.integrate) { fs_1.default.writeFileSync('lsdb.config.ts', configContent); } else { console.log(chalk_1.default.yellow('ℹ A config file already exists (lsdb.config.ts or sheet-db.config.ts), skipping creation.')); } if (!fs_1.default.existsSync('.env') || !options.integrate) { fs_1.default.writeFileSync('.env', envContent); } else { console.log(chalk_1.default.yellow('ℹ .env already exists, please merge Google OAuth vars manually.')); // Optionally append to .env const currentEnv = fs_1.default.readFileSync('.env', 'utf-8'); if (!currentEnv.includes('GOOGLE_CLIENT_ID')) { fs_1.default.appendFileSync('.env', '\n' + envContent); console.log(chalk_1.default.green('✅ Appended Google Sheet DB variables to .env')); } } if (!fs_1.default.existsSync('schemas')) { fs_1.default.mkdirSync('schemas'); } const adminSchemas = { users: `import { defineTable, string } from 'longcelot-sheet-db'; export default defineTable({ name: 'users', actor: 'admin', timestamps: true, columns: { user_id: string().required().unique(), role: string().required(), email: string().required().unique(), actor_sheet_id: string(), status: string().enum(['active', 'inactive']).default('active'), }, }); `, credentials: `import { defineTable, string } from 'longcelot-sheet-db'; export default defineTable({ name: 'credentials', actor: 'admin', columns: { user_id: string().required(), password_hash: string(), provider: string().enum(['oauth', 'local']).required(), }, }); `, schema_versions: `import { defineTable, string, number } from 'longcelot-sheet-db'; export default defineTable({ name: 'schema_versions', actor: 'admin', columns: { schema_version_id: string().primary(), actor_sheet_id: string().required(), table_name: string().required(), schema_hash: string().required(), synced_at: string().required(), column_count: number().required(), }, }); `, }; for (const role of answers.actors) { const actorDir = path_1.default.join('schemas', role); if (!fs_1.default.existsSync(actorDir)) { fs_1.default.mkdirSync(actorDir, { recursive: true }); } if (role === 'admin') { for (const [name, content] of Object.entries(adminSchemas)) { fs_1.default.writeFileSync(path_1.default.join(actorDir, `${name}.ts`), content); } } } console.log(chalk_1.default.green('\n✅ Project initialized!\n')); console.log(chalk_1.default.yellow('Created:')); console.log(' ' + chalk_1.default.white('lsdb.config.ts')); console.log(' ' + chalk_1.default.white('.env')); console.log(' ' + chalk_1.default.white('schemas/')); console.log(chalk_1.default.cyan('\nNext steps:')); console.log(' 1. ' + chalk_1.default.white('Fill in your .env file:')); console.log(' ' + chalk_1.default.gray('GOOGLE_CLIENT_ID=<your-client-id>')); console.log(' ' + chalk_1.default.gray('GOOGLE_CLIENT_SECRET=<your-client-secret>')); console.log(' ' + chalk_1.default.gray('ADMIN_SHEET_ID=<your-sheet-id>')); console.log(' ' + chalk_1.default.dim('→ https://console.cloud.google.com/apis/credentials')); console.log(' 2. ' + chalk_1.default.white('Generate tables: lsdb generate <table-name>')); console.log(' 3. ' + chalk_1.default.white('Sync to sheets: lsdb sync\n')); } //# sourceMappingURL=init.js.map