@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
102 lines (101 loc) • 4.21 kB
JavaScript
import chalk from 'chalk';
import { execa } from 'execa';
import inquirer from 'inquirer';
import Joi from 'joi';
import { randomUUID } from 'node:crypto';
import ora from 'ora';
import runMigrations from '../../../database/migrations/run.js';
import runSeed from '../../../database/seeds/run.js';
import { generateHash } from '../../../utils/generate-hash.js';
import createDBConnection from '../../utils/create-db-connection.js';
import createEnv from '../../utils/create-env/index.js';
import { defaultAdminPolicy, defaultAdminRole, defaultAdminUser } from '../../utils/defaults.js';
import { drivers, getDriverForClient } from '../../utils/drivers.js';
import { databaseQuestions } from './questions.js';
export default async function init() {
const rootPath = process.cwd();
const { client } = await inquirer.prompt([
{
type: 'list',
name: 'client',
message: 'Choose your database client',
choices: Object.values(drivers),
},
]);
const dbClient = getDriverForClient(client);
const spinnerDriver = ora('Installing Database Driver...').start();
await execa('npm', ['install', dbClient, '--production']);
spinnerDriver.stop();
let attemptsRemaining = 5;
const { credentials, db } = await trySeed();
async function trySeed() {
const credentials = await inquirer.prompt(databaseQuestions[dbClient].map((question) => question({ client: dbClient, filepath: rootPath })));
const db = createDBConnection(dbClient, credentials);
try {
await runSeed(db);
await runMigrations(db, 'latest', false);
}
catch (err) {
process.stdout.write('\nSomething went wrong while seeding the database:\n');
process.stdout.write(`\n${chalk.red(`[${err.code || 'Error'}]`)} ${err.message}\n`);
process.stdout.write('\nPlease try again\n\n');
attemptsRemaining--;
if (attemptsRemaining > 0) {
return await trySeed();
}
else {
process.stdout.write("Couldn't seed the database. Exiting.\n");
process.exit(1);
}
}
return { credentials, db };
}
await createEnv(dbClient, credentials, rootPath);
process.stdout.write('\nCreate your first admin user:\n\n');
const firstUser = await inquirer.prompt([
{
type: 'input',
name: 'email',
message: 'Email',
default: 'admin@example.com',
validate: (input) => {
const emailSchema = Joi.string().email().required();
const { error } = emailSchema.validate(input);
if (error)
throw new Error('The email entered is not a valid email address!');
return true;
},
},
{
type: 'password',
name: 'password',
message: 'Password',
mask: '*',
validate: (input) => {
if (input === null || input === '')
throw new Error('The password cannot be empty!');
return true;
},
},
]);
firstUser.password = await generateHash(firstUser.password);
const role = randomUUID();
const policy = randomUUID();
await db('directus_roles').insert({ ...defaultAdminRole, id: role });
await db('directus_policies').insert({ ...defaultAdminPolicy, id: policy });
await db('directus_access').insert({ id: randomUUID(), role, policy });
await db('directus_users').insert({
...defaultAdminUser,
id: randomUUID(),
email: firstUser.email,
password: firstUser.password,
role,
});
await db.destroy();
process.stdout.write(`\nYour project has been created at ${chalk.green(rootPath)}.\n`);
process.stdout.write(`\nThe configuration can be found in ${chalk.green(rootPath + '/.env')}\n`);
process.stdout.write(`\nStart Directus by running:\n`);
process.stdout.write(` ${chalk.blue('cd')} ${rootPath}\n`);
process.stdout.write(` ${chalk.blue('npx directus')} start\n`);
process.exit(0);
}