UNPKG

boostr

Version:
117 lines 4.71 kB
import { execFileSync } from 'child_process'; import { readFileSync, writeFileSync } from 'fs'; import { join, basename, extname } from 'path'; import { temporaryDirectoryTask } from 'tempy'; import tar from 'tar'; import walkSync from 'walk-sync'; import kebabCase from 'lodash/kebabCase.js'; import { createApplicationServiceFromDirectory } from './services/index.js'; import { GLOBAL_OPTIONS_HELP_OBJECT } from './argument-parser.js'; import { formatHelp } from './help.js'; import { logMessage, throwError, resolveVariables, directoryExists, directoryIsEmpty } from './utilities.js'; const INITIALIZE_HELP = formatHelp({ 'Command': 'initialize', 'Alias': 'init', 'Description': 'Initializes your app within the current directory from the specified template.', 'Usage': 'boostr initialize <template> [options]', 'Options': { '--name': 'Specifies the name of your app (default: the name of the current directory).' }, 'Examples': [ 'boostr initialize @boostr/web-app-ts', 'boostr init @boostr/web-app-js --name=my-app' ], 'Global Options': GLOBAL_OPTIONS_HELP_OBJECT }); const POPULATABLE_TEMPLATE_FILE_EXTENSIONS = ['.js', '.mjs', '.jsx', '.ts', '.tsx', '.json', '.md']; export async function initialize(directory, templateName, { name: applicationName } = {}, { stage, showHelp = false }) { if (showHelp) { console.log(INITIALIZE_HELP); return; } if (!templateName) { throwError(`Please specify a template name (example: \`boostr initialize @boostr/web-app-ts\`)`); } if (!directoryIsEmpty(directory, { ignoreDirectoryNames: ['.git', '.DS_Store'] })) { throwError(`Sorry, the 'initialize' command can only be used within an empty directory`); } if (!applicationName) { applicationName = kebabCase(basename(directory)); } logMessage('Fetching template...'); await fetchTemplate(directory, templateName); await populateVariables(directory, { applicationName }); if (!(await hasGitDirectory(directory))) { logMessage('Initializing Git directory...'); await initializeGitDirectory(directory); } logMessage('Installing npm dependencies...'); const applicationService = await createApplicationServiceFromDirectory(directory, { stage }); await applicationService.install(); logMessage('Application successfully initialized'); logMessage('Run `boostr start` to start the development environment'); } async function fetchTemplate(directory, name) { await temporaryDirectoryTask(async (temporaryDirectory) => { try { const tarballFileName = execFileSync('npm', ['pack', name, '--silent'], { cwd: temporaryDirectory }) .toString() .trim(); const tarballFile = join(temporaryDirectory, tarballFileName); try { await tar.extract({ file: tarballFile, cwd: directory, strip: 2, keep: true }, [ 'package/template' ]); } catch (error) { throwError(`An error occurred while extracting the '${name}' npm package`); } } catch { throwError(`An error occurred while fetching the '${name}' npm package`); } }); } async function populateVariables(directory, { applicationName }) { const randomPort = Math.floor(Math.random() * 9990) + 10000; const variables = { applicationName, frontendPort: randomPort, backendPort: randomPort + 1, databasePort: randomPort + 2 }; const files = walkSync(directory, { directories: false, includeBasePath: true }); for (const file of files) { const extension = extname(file); if (!POPULATABLE_TEMPLATE_FILE_EXTENSIONS.includes(extension)) { continue; } const originalContent = readFileSync(file, 'utf-8'); const populatedContent = resolveVariables(originalContent, variables); if (populatedContent !== originalContent) { writeFileSync(file, populatedContent); } } } async function initializeGitDirectory(directory) { execFileSync('git', ['init', '--initial-branch=main'], { cwd: directory, stdio: 'inherit' }); } async function hasGitDirectory(directory) { while (true) { if (directoryExists(join(directory, '.git'))) { return true; } const parentDirectory = join(directory, '..'); if (parentDirectory === directory) { break; } directory = parentDirectory; } return false; } //# sourceMappingURL=initialize.js.map