niledatabase
Version:
Command line interface for Nile databases
248 lines (241 loc) • 11.9 kB
JavaScript
;
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;
}