UNPKG

quallaa-cli

Version:

Sets up core infrastructure services for AI-assisted development

271 lines • 10.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.setupSupabase = setupSupabase; exports.createSupabaseTable = createSupabaseTable; const chalk_1 = __importDefault(require("chalk")); const inquirer_1 = __importDefault(require("inquirer")); const child_process_1 = require("child_process"); const util_1 = require("util"); const credentials_1 = require("../storage/credentials"); const execAsync = (0, util_1.promisify)(child_process_1.exec); async function setupSupabase() { try { console.log(chalk_1.default.gray('\nSupabase provides database, authentication, and storage.')); console.log(chalk_1.default.gray('You\'ll need a Supabase account (free tier available).\n')); const cliInstalled = await checkSupabaseCLI(); if (!cliInstalled) { await installSupabaseCLI(); } const existing = await (0, credentials_1.getCredentials)('supabase'); if (existing) { const { useExisting } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'useExisting', message: 'Existing Supabase credentials found. Use them?', default: true, }, ]); if (useExisting) { return { success: true, service: 'supabase', message: 'Using existing credentials' }; } } console.log(chalk_1.default.yellow('\nšŸ” Authenticating with Supabase...')); console.log(chalk_1.default.gray('This will open your browser for authentication.\n')); await loginSupabase(); const { projectChoice } = await inquirer_1.default.prompt([ { type: 'list', name: 'projectChoice', message: 'Would you like to:', choices: [ { name: 'Create a new Supabase project', value: 'new' }, { name: 'Use an existing project', value: 'existing' }, ], }, ]); let projectRef; let projectDetails; if (projectChoice === 'new') { projectDetails = await createSupabaseProject(); projectRef = projectDetails.ref; } else { projectRef = await selectExistingProject(); projectDetails = await getProjectDetails(projectRef); } await initLocalSupabase(); const credentials = { accessToken: projectDetails.access_token, projectRef, anonKey: projectDetails.anon_key, serviceRoleKey: projectDetails.service_role_key, dbUrl: projectDetails.db_url, }; await (0, credentials_1.saveCredentials)('supabase', credentials); await createEnvFile(credentials); return { success: true, service: 'supabase', credentials: { supabase: credentials }, }; } catch (error) { return { success: false, service: 'supabase', message: error instanceof Error ? error.message : 'Setup failed', error: error, }; } } async function checkSupabaseCLI() { try { await execAsync('supabase --version'); return true; } catch { return false; } } async function installSupabaseCLI() { console.log(chalk_1.default.yellow('šŸ“¦ Installing Supabase CLI...')); const platform = process.platform; if (platform === 'darwin') { try { await execAsync('brew --version'); await execAsync('brew install supabase/tap/supabase'); } catch { await execAsync('npm install -g supabase'); } } else if (platform === 'win32') { await execAsync('npm install -g supabase'); } else { await execAsync('npm install -g supabase'); } console.log(chalk_1.default.green('āœ“ Supabase CLI installed')); } async function loginSupabase() { return new Promise((resolve, reject) => { const login = (0, child_process_1.spawn)('supabase', ['login'], { stdio: 'inherit', shell: true, }); login.on('close', (code) => { if (code === 0) { resolve(); } else { reject(new Error('Supabase login failed')); } }); }); } async function createSupabaseProject() { const { projectName, orgId, region, planId } = await inquirer_1.default.prompt([ { type: 'input', name: 'projectName', message: 'Project name:', validate: (input) => input.length > 0 || 'Project name is required', }, { type: 'input', name: 'orgId', message: 'Organization ID (leave empty for personal):', }, { type: 'list', name: 'region', message: 'Region:', choices: [ { name: 'US East (N. Virginia)', value: 'us-east-1' }, { name: 'US West (Oregon)', value: 'us-west-1' }, { name: 'EU (Frankfurt)', value: 'eu-central-1' }, { name: 'Asia Pacific (Singapore)', value: 'ap-southeast-1' }, { name: 'Asia Pacific (Sydney)', value: 'ap-southeast-2' }, ], default: 'us-east-1', }, { type: 'list', name: 'planId', message: 'Plan:', choices: [ { name: 'Free tier', value: 'free' }, { name: 'Pro', value: 'pro' }, ], default: 'free', }, ]); const createCmd = [ 'supabase', 'projects', 'create', '--name', projectName, ]; if (orgId) { createCmd.push('--org-id', orgId); } if (region) { createCmd.push('--region', region); } if (planId) { createCmd.push('--plan', planId); } const { stdout } = await execAsync(createCmd.join(' ')); const projectRef = stdout.match(/Project ID: ([\w-]+)/)?.[1]; if (!projectRef) { throw new Error('Failed to create project'); } return await getProjectDetails(projectRef); } async function selectExistingProject() { const { stdout } = await execAsync('supabase projects list --json'); const projects = JSON.parse(stdout); if (projects.length === 0) { throw new Error('No existing projects found'); } const { selectedProject } = await inquirer_1.default.prompt([ { type: 'list', name: 'selectedProject', message: 'Select a project:', choices: projects.map((p) => ({ name: `${p.name} (${p.region})`, value: p.ref, })), }, ]); return selectedProject; } async function getProjectDetails(projectRef) { const { stdout } = await execAsync(`supabase projects get ${projectRef} --json`); return JSON.parse(stdout); } async function initLocalSupabase() { console.log(chalk_1.default.yellow('\nšŸ”§ Initializing local Supabase...')); await execAsync('supabase init'); console.log(chalk_1.default.green('āœ“ Local Supabase initialized')); } async function createEnvFile(credentials) { const envContent = `# Supabase NEXT_PUBLIC_SUPABASE_URL=${credentials.dbUrl} NEXT_PUBLIC_SUPABASE_ANON_KEY=${credentials.anonKey} SUPABASE_SERVICE_ROLE_KEY=${credentials.serviceRoleKey} `; const fs = await Promise.resolve().then(() => __importStar(require('fs/promises'))); await fs.writeFile('.env.local', envContent, { flag: 'a' }); console.log(chalk_1.default.green('āœ“ Environment variables added to .env.local')); } async function createSupabaseTable(tableName, schema) { const credentials = await (0, credentials_1.getCredentials)('supabase'); if (!credentials) { throw new Error('Supabase not configured. Run "quallaa setup supabase" first.'); } const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('-').slice(0, 4).join(''); const migrationName = `${timestamp}_create_${tableName}`; await execAsync(`supabase migration new ${migrationName}`); const fs = await Promise.resolve().then(() => __importStar(require('fs/promises'))); const migrationPath = `./supabase/migrations/${migrationName}.sql`; await fs.writeFile(migrationPath, schema); await execAsync('supabase db push'); } //# sourceMappingURL=supabase.js.map