UNPKG

niledatabase

Version:

Command line interface for Nile databases

248 lines (241 loc) 11.9 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.createAuthCommand = createAuthCommand; const commander_1 = require("commander"); const config_1 = require("../lib/config"); const api_1 = require("../lib/api"); const colors_1 = require("../lib/colors"); const globalOptions_1 = require("../lib/globalOptions"); const errorHandling_1 = require("../lib/errorHandling"); const child_process_1 = require("child_process"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const axios_1 = __importDefault(require("axios")); function createAuthCommand(getOptions) { const auth = new commander_1.Command('auth') .description('Manage authentication') .addHelpText('after', ` Examples: ${(0, colors_1.formatCommand)('nile auth quickstart --nextjs')} Set up authentication in a Next.js app ${(0, colors_1.formatCommand)('nile auth env')} Generate environment variables ${(0, colors_1.formatCommand)('nile auth env --output .env.local')} Save environment variables to file ${(0, globalOptions_1.getGlobalOptionsHelp)()}`); auth .command('quickstart') .description('Set up authentication in your application') .requiredOption('--nextjs', 'Set up authentication in a Next.js application') .action(async (cmdOptions) => { try { const options = getOptions(); const configManager = new config_1.ConfigManager(options); const workspaceSlug = configManager.getWorkspace(); if (!workspaceSlug) { throw new Error('No workspace specified. Use one of:\n' + '1. --workspace flag\n' + '2. nile config --workspace <name>\n' + '3. NILE_WORKSPACE environment variable'); } const api = new api_1.NileAPI({ token: configManager.getToken(), dbHost: configManager.getDbHost(), controlPlaneUrl: configManager.getGlobalHost(), debug: options.debug }); if (cmdOptions.nextjs) { console.log(colors_1.theme.primary('\nSetting up authentication in Next.js application...')); // Create Next.js app if it doesn't exist if (!fs.existsSync('package.json')) { console.log(colors_1.theme.dim('\nCreating new Next.js application...')); (0, child_process_1.execSync)('npx create-next-app@latest . --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"', { stdio: 'inherit' }); } // Install required dependencies console.log(colors_1.theme.dim('\nInstalling required dependencies...')); (0, child_process_1.execSync)('npm install @niledatabase/react @niledatabase/server', { stdio: 'inherit' }); // Get database credentials console.log(colors_1.theme.dim('\nFetching database credentials...')); const credentials = await api.createDatabaseCredentials(workspaceSlug, 'test'); const connection = await api.getDatabaseConnection(workspaceSlug, 'test'); // Create environment variables const envVars = { NILE_DATABASE_URL: `postgres://${connection.user}:${connection.password}@${connection.host}:${connection.port}/${connection.database}`, NILE_WORKSPACE: workspaceSlug, NILE_API_KEY: credentials.id, NILE_API_SECRET: credentials.password }; // Write to .env.local console.log(colors_1.theme.dim('\nWriting environment variables to .env.local...')); const envContent = Object.entries(envVars) .map(([key, value]) => `${key}=${value}`) .join('\n'); fs.writeFileSync('.env.local', envContent); // Create API routes console.log(colors_1.theme.dim('\nCreating API routes...')); const apiDir = path.join('src', 'app', 'api'); if (!fs.existsSync(apiDir)) { fs.mkdirSync(apiDir, { recursive: true }); } // Create auth route const authRoute = path.join(apiDir, 'auth', 'route.ts'); fs.mkdirSync(path.dirname(authRoute), { recursive: true }); fs.writeFileSync(authRoute, ` import { Nile } from '@niledatabase/server'; import { NextResponse } from 'next/server'; const nile = new Nile({ databaseUrl: process.env.NILE_DATABASE_URL, apiKey: process.env.NILE_API_KEY, apiSecret: process.env.NILE_API_SECRET, workspace: process.env.NILE_WORKSPACE }); export async function POST(request: Request) { try { const body = await request.json(); const { email, password } = body; const user = await nile.auth.signUp({ email, password }); return NextResponse.json(user); } catch (error) { return NextResponse.json({ error: 'Authentication failed' }, { status: 400 }); } } `); // Create auth provider component console.log(colors_1.theme.dim('\nCreating auth provider component...')); const componentsDir = path.join('src', 'components'); if (!fs.existsSync(componentsDir)) { fs.mkdirSync(componentsDir, { recursive: true }); } const authProvider = path.join(componentsDir, 'AuthProvider.tsx'); fs.writeFileSync(authProvider, ` import { NileProvider } from '@niledatabase/react'; export function AuthProvider({ children }: { children: React.ReactNode }) { return ( <NileProvider databaseUrl={process.env.NILE_DATABASE_URL} apiKey={process.env.NILE_API_KEY} apiSecret={process.env.NILE_API_SECRET} workspace={process.env.NILE_WORKSPACE} > {children} </NileProvider> ); } `); // Update root layout console.log(colors_1.theme.dim('\nUpdating root layout...')); const layoutFile = path.join('src', 'app', 'layout.tsx'); const layoutContent = fs.readFileSync(layoutFile, 'utf-8'); const updatedLayout = layoutContent.replace('export default function RootLayout', `import { AuthProvider } from '@/components/AuthProvider';\n\nexport default function RootLayout`).replace('<body>', '<body>\n <AuthProvider>').replace('</body>', ' </AuthProvider>\n </body>'); fs.writeFileSync(layoutFile, updatedLayout); console.log(colors_1.theme.success('\nAuthentication setup complete!')); console.log(colors_1.theme.secondary('\nNext steps:')); console.log('1. Start your Next.js app with "npm run dev"'); console.log('2. Visit http://localhost:3000 to see your app'); console.log('3. Use the Nile React components to add authentication UI'); } } catch (error) { if (axios_1.default.isAxiosError(error) && (error.response?.status === 401 || error.message === 'Token is required')) { await (0, errorHandling_1.handleApiError)(error, 'set up authentication', new config_1.ConfigManager(getOptions())); } else { throw error; } } }); auth .command('env') .description('Generate environment variables for authentication') .option('--output <file>', 'Output file for environment variables (e.g., .env.local)') .action(async (cmdOptions) => { try { const options = getOptions(); const configManager = new config_1.ConfigManager(options); const workspaceSlug = configManager.getWorkspace(); if (!workspaceSlug) { throw new Error('No workspace specified. Use one of:\n' + '1. --workspace flag\n' + '2. nile config --workspace <name>\n' + '3. NILE_WORKSPACE environment variable'); } const api = new api_1.NileAPI({ token: configManager.getToken(), dbHost: configManager.getDbHost(), controlPlaneUrl: configManager.getGlobalHost(), debug: options.debug }); // Get database credentials console.log(colors_1.theme.dim('\nFetching database credentials...')); const credentials = await api.createDatabaseCredentials(workspaceSlug, 'test'); const connection = await api.getDatabaseConnection(workspaceSlug, 'test'); // Generate environment variables const envVars = { NILE_DATABASE_URL: `postgres://${connection.user}:${connection.password}@${connection.host}:${connection.port}/${connection.database}`, NILE_WORKSPACE: workspaceSlug, NILE_API_KEY: credentials.id, NILE_API_SECRET: credentials.password }; // Format environment variables const envContent = Object.entries(envVars) .map(([key, value]) => `${key}=${value}`) .join('\n'); // Output to file if specified if (cmdOptions.output) { console.log(colors_1.theme.dim(`\nWriting environment variables to ${cmdOptions.output}...`)); fs.writeFileSync(cmdOptions.output, envContent); console.log(colors_1.theme.success(`\nEnvironment variables written to ${cmdOptions.output}`)); } else { // Display in terminal console.log(colors_1.theme.primary('\nEnvironment variables:')); console.log(colors_1.theme.secondary('\n' + envContent)); } } catch (error) { if (axios_1.default.isAxiosError(error) && (error.response?.status === 401 || error.message === 'Token is required')) { await (0, errorHandling_1.handleApiError)(error, 'generate environment variables', new config_1.ConfigManager(getOptions())); } else { throw error; } } }); return auth; }