UNPKG

@curvenote/cli

Version:
188 lines (176 loc) โ€ข 7.84 kB
import chalk from 'chalk'; import fs from 'node:fs'; import inquirer from 'inquirer'; import { basename, join, resolve } from 'node:path'; import { config, findProjectsOnPath, loadProjectFromDisk, selectors, writeConfigs, startServer, } from 'myst-cli'; import { LogLevel, writeFileToFolder } from 'myst-cli-utils'; import { docLinks, LOGO } from '../docs.js'; import { MyUser } from '../models.js'; import { interactiveCloneQuestions } from './clone.js'; import { pullProjects } from './pull/project.js'; import questions from './questions.js'; import { getDefaultProjectConfig, getDefaultSiteConfig, INIT_LOGO_PATH } from './utils.js'; import { addOxaTransformersToOpts } from '../utils/utils.js'; const CURVENOTE_YML = 'curvenote.yml'; const WELCOME = async (session) => ` ${chalk.bold.green('Welcome to the Curvenote CLI!!')} ๐Ÿ‘‹ ${chalk.bold('curvenote init')} walks you through creating a ${chalk.bold(CURVENOTE_YML)} file. You can use this client library to: - ${chalk.bold('sync content')} to & from Curvenote - ${chalk.bold('build & export')} professional PDFs - create a ${chalk.bold('local website')} & deploy to ${chalk.blue(`https://${session.isAnon ? 'your' : (await new MyUser(session).get()).data.username}.curve.space`)} Find out more here: ${docLinks.overview} `; const FINISHED = async (session) => ` ${chalk.bold(chalk.green('Curvenote setup is complete!!'))} ๐Ÿš€ You can use this client library to: - ${chalk.bold('curvenote pull')}: Update your content to what is on https://curvenote.com - ${chalk.bold('curvenote start')}: Start a local web server now! - ${chalk.bold('curvenote deploy')}: Share content on ${chalk.blue(`https://${session.isAnon ? 'your' : (await new MyUser(session).get()).data.username}.curve.space`)} Find out more here: ${docLinks.overview} `; /** * Initialize local curvenote project from folder or remote project * * It creates a new curvenote.yml file in the current directory with * both site and project configuration. * * This fails if curvenote.yml already exists; use `start` or `add`. */ export async function init(session, opts) { var _a; if (!opts.yes) session.log.info(await WELCOME(session)); if (opts.domain) session.log.info(`Using custom domain ${opts.domain}`); let currentPath = resolve('.'); // Initialize config - error if it exists if (selectors.selectLocalSiteConfig(session.store.getState(), currentPath) && !opts.writeTOC) { throw Error(`Site config in ${CURVENOTE_YML} config already exists, did you mean to ${chalk.bold('curvenote clone')} or ${chalk.bold('curvenote start')}?`); } const folderName = basename(currentPath); const siteConfig = getDefaultSiteConfig(folderName); // Load the user now, and wait for it below! let me; if (!session.isAnon) me = new MyUser(session).get(); const folderIsEmpty = fs.readdirSync(currentPath).length === 0; if (folderIsEmpty && opts.yes) throw Error('Cannot initialize an empty folder'); let content; const projectConfigPaths = await findProjectsOnPath(session, currentPath); if ((!folderIsEmpty && opts.yes) || projectConfigPaths.length) { content = 'folder'; } else { const response = await inquirer.prompt([questions.content({ folderIsEmpty })]); content = response.content; } let projectConfig = selectors.selectCurrentProjectConfig(session.store.getState()); let pullComplete = false; let title = (projectConfig === null || projectConfig === void 0 ? void 0 : projectConfig.title) || siteConfig.title || undefined; if (content === 'folder') { if (projectConfigPaths.length > 0) { const pathListString = projectConfigPaths .map((p) => ` - ${join(p, CURVENOTE_YML)}`) .join('\n'); session.log.info(`๐Ÿ‘€ ${chalk.bold('Found existing project config files on your path:')}\n${pathListString}\n`); } if (projectConfig && opts.writeTOC && projectConfigPaths.length > 0) { if (projectConfig.toc) { session.log.warn('Not writing the table of contents, it already exists!'); return; } else { await loadProjectFromDisk(session, currentPath, opts); return; } } else { if (!opts.yes) { const promptTitle = await inquirer.prompt([questions.title({ title: title || '' })]); title = promptTitle.title; } if (!projectConfig) { try { await loadProjectFromDisk(session, currentPath, { ...opts, writeTOC: false }); session.log.info(`๐Ÿ““ Creating project config`); projectConfig = await getDefaultProjectConfig(title); projectConfigPaths.unshift(currentPath); } catch { if (!projectConfigPaths.length) { throw Error(`No markdown or notebook files found`); } session.log.info(`๐Ÿงน No additional markdown or notebook files found`); } } } pullComplete = true; } else if (content === 'curvenote') { const results = await interactiveCloneQuestions(session); const { siteProject } = results; projectConfig = results.projectConfig; title = projectConfig.title; currentPath = siteProject.path; } else { throw Error(`Invalid init content: ${content}`); } // If there is a new project config, save to the state and write to disk if (projectConfig) { await writeConfigs(session, currentPath, { projectConfig }); session.store.dispatch(config.actions.receiveCurrentProjectPath({ path: currentPath })); } // Personalize the config session.log.info(`๐Ÿ““ Creating site config`); me = await me; siteConfig.title = title; siteConfig.options = { logo_text: title }; if (me) { const { username, twitter } = me.data; siteConfig.domains = opts.domain ? [opts.domain.replace(/^http[s]*:\/\//, '')] : [`${username}.curve.space`]; if (twitter) siteConfig.options.twitter = twitter; } // Save site config to state and write to disk await writeConfigs(session, '.', { siteConfig }); session.store.dispatch(config.actions.receiveCurrentSitePath({ path: '.' })); const pullOpts = { level: LogLevel.debug }; let pullProcess; if (!pullComplete) { pullProcess = pullProjects(session, pullOpts).then(() => { pullComplete = true; }); } if (((_a = siteConfig.options) === null || _a === void 0 ? void 0 : _a.logo) === INIT_LOGO_PATH) { writeFileToFolder(INIT_LOGO_PATH, LOGO); } if (!opts.yes) session.log.info(await FINISHED(session)); let start = false; if (!opts.yes) { const promptStart = await inquirer.prompt([questions.start()]); start = promptStart.start; } if (!start && !opts.yes) { session.log.info(chalk.dim('\nYou can do this later with:'), chalk.bold('curvenote start')); } if (!pullComplete) { pullOpts.level = LogLevel.info; session.log.info(`${chalk.dim('\nFinishing')} ${chalk.bold('curvenote pull')}${chalk.dim('. This may take a minute โณ...')}`); } await pullProcess; if (opts.writeTOC) { await loadProjectFromDisk(session, currentPath, { ...opts, reloadProject: true }); } if (start) { session.log.info(chalk.dim('\nStarting local server with: '), chalk.bold('curvenote start')); await startServer(session, addOxaTransformersToOpts(session, opts)); } }