refactor: convert CLI entry points to ESM; migrate create-docusaurus to ESM (#6661)

* refactor: convert CLI entry points to ESM

* fix

* fix

* fix

* fix!

* create-docusaurus ESM

* fix lock

* final touchups

* fix lodash

* fix

* use lodash

* fix hasYarn
This commit is contained in:
Joshua Chen 2022-02-16 23:00:35 +08:00 committed by GitHub
parent eacc695542
commit 67918e35e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 85 additions and 54 deletions

View file

@ -8,12 +8,15 @@
// @ts-check // @ts-check
const logger = require('@docusaurus/logger').default; import logger from '@docusaurus/logger';
const semver = require('semver'); import semver from 'semver';
const path = require('path'); import path from 'path';
const {program} = require('commander'); import {program} from 'commander';
const {default: init} = require('../lib'); import {createRequire} from 'module';
const requiredVersion = require('../package.json').engines.node; import init from '../lib/index.js';
const packageJson = createRequire(import.meta.url)('../package.json');
const requiredVersion = packageJson.engines.node;
if (!semver.satisfies(process.version, requiredVersion)) { if (!semver.satisfies(process.version, requiredVersion)) {
logger.error('Minimum Node.js version not met :('); logger.error('Minimum Node.js version not met :(');
@ -29,7 +32,7 @@ function wrapCommand(fn) {
}); });
} }
program.version(require('../package.json').version); program.version(packageJson.version);
program program
.arguments('[siteName] [template] [rootDir]') .arguments('[siteName] [template] [rootDir]')

View file

@ -2,6 +2,7 @@
"name": "create-docusaurus", "name": "create-docusaurus",
"version": "2.0.0-beta.15", "version": "2.0.0-beta.15",
"description": "Create Docusaurus apps easily.", "description": "Create Docusaurus apps easily.",
"type": "module",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/facebook/docusaurus.git", "url": "https://github.com/facebook/docusaurus.git",
@ -24,11 +25,11 @@
"@docusaurus/logger": "2.0.0-beta.15", "@docusaurus/logger": "2.0.0-beta.15",
"commander": "^5.1.0", "commander": "^5.1.0",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"lodash": "^4.17.20", "lodash": "^4.17.21",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"semver": "^7.3.5", "semver": "^7.3.5",
"shelljs": "^0.8.5", "shelljs": "^0.8.5",
"supports-color": "^8.1.1", "supports-color": "^9.2.1",
"tslib": "^2.3.1" "tslib": "^2.3.1"
}, },
"engines": { "engines": {

View file

@ -7,20 +7,19 @@
import logger from '@docusaurus/logger'; import logger from '@docusaurus/logger';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {execSync} from 'child_process';
import prompts, {type Choice} from 'prompts'; import prompts, {type Choice} from 'prompts';
import path from 'path'; import path from 'path';
import shell from 'shelljs'; import shell from 'shelljs';
import {kebabCase, sortBy} from 'lodash'; import _ from 'lodash';
import supportsColor from 'supports-color'; import supportsColor from 'supports-color';
import {fileURLToPath} from 'url';
const RecommendedTemplate = 'classic'; const RecommendedTemplate = 'classic';
const TypeScriptTemplateSuffix = '-typescript'; const TypeScriptTemplateSuffix = '-typescript';
function hasYarn() { function hasYarn() {
try { try {
execSync('yarnpkg --version', {stdio: 'ignore'}); return shell.exec('yarnpkg --version', {silent: true}).code === 0;
return true;
} catch (e) { } catch (e) {
return false; return false;
} }
@ -50,7 +49,7 @@ function readTemplates(templatesDir: string) {
); );
// Classic should be first in list! // Classic should be first in list!
return sortBy(templates, (t) => t !== RecommendedTemplate); return _.sortBy(templates, (t) => t !== RecommendedTemplate);
} }
function createTemplateChoices(templates: string[]) { function createTemplateChoices(templates: string[]) {
@ -135,7 +134,7 @@ export default async function init(
}> = {}, }> = {},
): Promise<void> { ): Promise<void> {
const useYarn = cliOptions.useNpm ? false : hasYarn(); const useYarn = cliOptions.useNpm ? false : hasYarn();
const templatesDir = path.resolve(__dirname, '../templates'); const templatesDir = fileURLToPath(new URL('../templates', import.meta.url));
const templates = readTemplates(templatesDir); const templates = readTemplates(templatesDir);
const hasTS = (templateName: string) => const hasTS = (templateName: string) =>
fs.pathExistsSync( fs.pathExistsSync(
@ -296,7 +295,7 @@ export default async function init(
// Update package.json info. // Update package.json info.
try { try {
await updatePkg(path.join(dest, 'package.json'), { await updatePkg(path.join(dest, 'package.json'), {
name: kebabCase(name), name: _.kebabCase(name),
version: '0.0.0', version: '0.0.0',
private: true, private: true,
}); });

View file

@ -1,6 +1,7 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"module": "es2020",
"incremental": true, "incremental": true,
"tsBuildInfoFile": "./lib/.tsbuildinfo", "tsBuildInfoFile": "./lib/.tsbuildinfo",
"rootDir": "src", "rootDir": "src",

View file

@ -138,4 +138,9 @@ const logger = {
success, success,
}; };
// TODO remove when migrating to ESM
// logger can only be default-imported in ESM with this
module.exports = logger;
module.exports.default = logger;
export default logger; export default logger;

View file

@ -8,14 +8,15 @@
// @ts-check // @ts-check
const logger = require('@docusaurus/logger').default; import logger from '@docusaurus/logger';
const semver = require('semver'); import semver from 'semver';
const cli = require('commander'); import cli from 'commander';
const path = require('path'); import path from 'path';
import {createRequire} from 'module';
import {migrateDocusaurusProject, migrateMDToMDX} from '../lib/index.js';
const requiredVersion = require('../package.json').engines.node; const requiredVersion = createRequire(import.meta.url)('../package.json')
.engines.node;
const {migrateDocusaurusProject, migrateMDToMDX} = require('../lib');
function wrapCommand(fn) { function wrapCommand(fn) {
return (...args) => return (...args) =>
@ -50,6 +51,7 @@ cli
const newSitePath = path.resolve(newDir); const newSitePath = path.resolve(newDir);
wrapCommand(migrateMDToMDX)(sitePath, newSitePath); wrapCommand(migrateMDToMDX)(sitePath, newSitePath);
}); });
cli.parse(process.argv); cli.parse(process.argv);
if (!process.argv.slice(2).length) { if (!process.argv.slice(2).length) {

View file

@ -20,7 +20,7 @@
"access": "public" "access": "public"
}, },
"bin": { "bin": {
"docusaurus-migrate": "bin/index.js" "docusaurus-migrate": "bin/index.mjs"
}, },
"dependencies": { "dependencies": {
"@babel/preset-env": "^7.16.11", "@babel/preset-env": "^7.16.11",

View file

@ -7,21 +7,24 @@
// @ts-check // @ts-check
const logger = require('@docusaurus/logger').default; import logger from '@docusaurus/logger';
const fs = require('fs-extra'); import fs from 'fs-extra';
const semver = require('semver'); import semver from 'semver';
const path = require('path'); import path from 'path';
const updateNotifier = require('update-notifier'); import updateNotifier from 'update-notifier';
const boxen = require('boxen'); import boxen from 'boxen';
import {createRequire} from 'module';
const packageJson = createRequire(import.meta.url)('../package.json');
const sitePkg = createRequire(path.join(process.cwd(), 'package.json'))(
'./package.json',
);
const { const {
name, name,
version, version,
engines: {node: requiredVersion}, engines: {node: requiredVersion},
} = require('../package.json'); } = packageJson;
// eslint-disable-next-line import/no-dynamic-require
const sitePkg = require(path.resolve(process.cwd(), 'package.json'));
/** /**
* Notify user if `@docusaurus` packages are outdated * Notify user if `@docusaurus` packages are outdated
@ -130,4 +133,4 @@ function beforeCli() {
} }
} }
module.exports = beforeCli; export default beforeCli;

View file

@ -8,10 +8,11 @@
// @ts-check // @ts-check
const logger = require('@docusaurus/logger').default; import logger from '@docusaurus/logger';
const fs = require('fs'); import fs from 'fs';
const cli = require('commander'); import cli from 'commander';
const { import {createRequire} from 'module';
import {
build, build,
swizzle, swizzle,
deploy, deploy,
@ -21,15 +22,16 @@ const {
clear, clear,
writeTranslations, writeTranslations,
writeHeadingIds, writeHeadingIds,
} = require('../lib'); } from '../lib/index.js';
import beforeCli from './beforeCli.mjs';
const beforeCli = require('./beforeCli');
beforeCli(); beforeCli();
const resolveDir = (dir = '.') => fs.realpathSync(dir); const resolveDir = (dir = '.') => fs.realpathSync(dir);
cli.version(require('../package.json').version).usage('<command> [options]'); cli
.version(createRequire(import.meta.url)('../package.json').version)
.usage('<command> [options]');
cli cli
.command('build [siteDir]') .command('build [siteDir]')
@ -226,6 +228,9 @@ cli.arguments('<command>').action((cmd) => {
logger.error` Unknown command name=${cmd}.`; logger.error` Unknown command name=${cmd}.`;
}); });
/**
* @param {string} command
*/
function isInternalCommand(command) { function isInternalCommand(command) {
return [ return [
'start', 'start',

View file

@ -21,7 +21,7 @@
"directory": "packages/docusaurus" "directory": "packages/docusaurus"
}, },
"bin": { "bin": {
"docusaurus": "bin/docusaurus.js" "docusaurus": "bin/docusaurus.mjs"
}, },
"scripts": { "scripts": {
"build": "tsc && tsc -p tsconfig.client.json && node copyUntypedFiles.mjs", "build": "tsc && tsc -p tsconfig.client.json && node copyUntypedFiles.mjs",

View file

@ -5,12 +5,24 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
export {default as build} from './commands/build'; import build from './commands/build';
export {default as start} from './commands/start'; import clear from './commands/clear';
export {default as swizzle} from './commands/swizzle'; import deploy from './commands/deploy';
export {default as deploy} from './commands/deploy'; import externalCommand from './commands/external';
export {default as externalCommand} from './commands/external'; import serve from './commands/serve';
export {default as serve} from './commands/serve'; import start from './commands/start';
export {default as clear} from './commands/clear'; import swizzle from './commands/swizzle';
export {default as writeTranslations} from './commands/writeTranslations'; import writeHeadingIds from './commands/writeHeadingIds';
export {default as writeHeadingIds} from './commands/writeHeadingIds'; import writeTranslations from './commands/writeTranslations';
export {
build,
clear,
deploy,
externalCommand,
serve,
start,
swizzle,
writeHeadingIds,
writeTranslations,
};

View file

@ -17761,7 +17761,7 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies: dependencies:
has-flag "^4.0.0" has-flag "^4.0.0"
supports-color@^8.0.0, supports-color@^8.1.0, supports-color@^8.1.1: supports-color@^8.0.0, supports-color@^8.1.0:
version "8.1.1" version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==