Skip to content

Commit

Permalink
chore: migrate BaseCommand and postinstall to esm (#5167)
Browse files Browse the repository at this point in the history
* chore: rename files

* chore: migrate BaseCommand and postinstall to esm
  • Loading branch information
danez committed Oct 14, 2022
1 parent e9155fa commit 9261bc3
Show file tree
Hide file tree
Showing 14 changed files with 137 additions and 140 deletions.
1 change: 1 addition & 0 deletions .eslintrc.cjs
Expand Up @@ -99,6 +99,7 @@ module.exports = {
},
},
rules: {
'import/extensions': [2, 'always'],
'no-restricted-imports': [
'error',
{
Expand Down
2 changes: 1 addition & 1 deletion bin/run.mjs
Expand Up @@ -5,7 +5,7 @@ import { fileURLToPath } from 'url'

import updateNotifier from 'update-notifier'

import { createMainCommand } from '../src/commands/index.cjs'
import { createMainCommand } from '../src/commands/index.mjs'

// 12 hours
const UPDATE_CHECK_INTERVAL = 432e5
Expand Down
6 changes: 4 additions & 2 deletions package.json
Expand Up @@ -162,8 +162,10 @@
"files": [
"/bin",
"/npm-shrinkwrap.json",
"/scripts/postinstall.cjs",
"/scripts/postinstall.mjs",
"/src/**/*.cjs",
"/src/**/*.js",
"/src/**/*.mjs",
"/src/**/*.sh",
"/src/**/*.ps1",
"/src/functions-templates/**",
Expand Down Expand Up @@ -215,7 +217,7 @@
"site:build": "run-s site:build:*",
"site:build:install": "cd site && npm ci --no-audit",
"site:build:assets": "cd site && npm run build",
"postinstall": "node ./scripts/postinstall.cjs",
"postinstall": "node ./scripts/postinstall.mjs",
"certs": "openssl req -x509 -out localhost.crt -keyout localhost.key -newkey rsa:2048 -nodes -sha256 -subj \"/CN=localhost\" -extensions EXT -config certconf"
},
"config": {
Expand Down
56 changes: 0 additions & 56 deletions scripts/postinstall.cjs

This file was deleted.

60 changes: 60 additions & 0 deletions scripts/postinstall.mjs
@@ -0,0 +1,60 @@
import process from 'process'

const id = (message) => message

/**
*
* @param {string} message
* @param {Array<chalk['Color'] | chalk['Modifiers']>} styles
* @returns
*/
const format = async (message, styles) => {
let func = id
try {
// this fails sometimes on outdated npm versions
const chalk = await import('chalk')
func = chalk.default
styles.forEach((style) => {
func = func[style]
})
} catch {}
return func(message)
}

const postInstall = async () => {
// yarn plug and play seems to have an issue with reading an esm file by building up the cache.
// as yarn pnp analyzes everything inside the postinstall
// yarn pnp executes it out of a .yarn folder .yarn/unplugged/netlify-cli-file-fb026a3a6d/node_modules/netlify-cli/scripts/postinstall.mjs
if (!process.argv[1].includes('.yarn')) {
const { createMainCommand } = await import('../src/commands/index.mjs')
// TODO: use destructuring again once the imported file is esm
const completion = await import('../src/lib/completion/index.cjs')

// create or update the autocompletion definition
const program = createMainCommand()
completion.createAutocompletion(program)
}

console.log('')
console.log(await format('Success! Netlify CLI has been installed!', ['greenBright', 'bold', 'underline']))
console.log('')
console.log('Your device is now configured to use Netlify CLI to deploy and manage your Netlify sites.')
console.log('')
console.log('Next steps:')
console.log('')
console.log(
` ${await format('netlify init', [
'cyanBright',
'bold',
])} Connect or create a Netlify site from current directory`,
)
console.log(
` ${await format('netlify deploy', ['cyanBright', 'bold'])} Deploy the latest changes to your Netlify site`,
)
console.log('')
console.log(`For more information on the CLI run ${await format('netlify help', ['cyanBright', 'bold'])}`)
console.log(`Or visit the docs at ${await format('https://cli.netlify.com', ['cyanBright', 'bold'])}`)
console.log('')
}

await postInstall()
4 changes: 2 additions & 2 deletions site/scripts/generate-command-data.mjs
@@ -1,8 +1,8 @@
// @ts-check
import main from '../../src/commands/index.cjs'
import { createMainCommand } from '../../src/commands/index.mjs'
import utils from '../../src/utils/index.cjs'

const program = main.createMainCommand()
const program = createMainCommand()

/** @type {Array<import('../../src/commands/base-command').BaseCommand>} */
// @ts-ignore typecast needed
Expand Down
27 changes: 12 additions & 15 deletions src/commands/base-command.cjs → src/commands/base-command.mjs
@@ -1,16 +1,17 @@
// @ts-check
const process = require('process')
const { format } = require('util')
import process from 'process'
import { format } from 'util'

const { Command, Option } = require('commander')
const debug = require('debug')
const merge = require('lodash/merge')
import { resolveConfig } from '@netlify/config'
import { Command, Option } from 'commander'
import debug from 'debug'
import merge from 'lodash/merge.js'
import { NetlifyAPI } from 'netlify'

// TODO: use static `import` after migrating this repository to pure ES modules
const jsClient = import('netlify')
const netlifyConfigPromise = import('@netlify/config')
import { getAgent } from '../lib/http-agent.cjs'
// TODO: use named imports again once the imported file is esm
import utils from '../utils/index.cjs'

const { getAgent } = require('../lib/http-agent.cjs')
const {
NETLIFY_CYAN,
StateConfig,
Expand All @@ -29,7 +30,7 @@ const {
sortOptions,
track,
warn,
} = require('../utils/index.cjs')
} = utils

// Netlify CLI client id. Lives in bot@netlify.com
// TODO: setup client for multiple environments
Expand Down Expand Up @@ -80,7 +81,7 @@ const getDuration = function (startTime) {
*/

/** Base command class that provides tracking and config initialization */
class BaseCommand extends Command {
export default class BaseCommand extends Command {
/** @type {NetlifyOptions} */
netlify

Expand Down Expand Up @@ -428,7 +429,6 @@ class BaseCommand extends Command {
})
const apiOpts = { ...apiUrlOpts, agent }
const globalConfig = await getGlobalConfig()
const { NetlifyAPI } = await jsClient

actionCommand.netlify = {
// api methods
Expand Down Expand Up @@ -468,7 +468,6 @@ class BaseCommand extends Command {
async getConfig(config) {
const options = this.opts()
const { cwd, host, offline = options.offline, pathPrefix, scheme, state, token } = config
const { resolveConfig } = await netlifyConfigPromise

try {
return await resolveConfig({
Expand Down Expand Up @@ -511,5 +510,3 @@ class BaseCommand extends Command {
}
}
}

module.exports = { BaseCommand }
5 changes: 3 additions & 2 deletions src/commands/dev/dev.cjs
Expand Up @@ -222,10 +222,11 @@ const startFrameworkServer = async function ({ settings }) {
}

stopSpinner({ error: false, spinner })
} catch {
} catch (error_) {
stopSpinner({ error: true, spinner })
log(NETLIFYDEVERR, `Netlify Dev could not connect to localhost:${settings.frameworkPort}.`)
log(NETLIFYDEVERR, `Netlify Dev could not start or connect to localhost:${settings.frameworkPort}.`)
log(NETLIFYDEVERR, `Please make sure your framework server is running on port ${settings.frameworkPort}`)
error(error_)
exit(1)
}

Expand Down
7 changes: 0 additions & 7 deletions src/commands/index.cjs

This file was deleted.

2 changes: 2 additions & 0 deletions src/commands/index.mjs
@@ -0,0 +1,2 @@
export { default as BaseCommand } from './base-command.mjs'
export { createMainCommand } from './main.mjs'
88 changes: 40 additions & 48 deletions src/commands/main.cjs → src/commands/main.mjs
@@ -1,54 +1,46 @@
// @ts-check
const process = require('process')

const { Option } = require('commander')
const inquirer = require('inquirer')
const { findBestMatch } = require('string-similarity')

const pkg = require('../../package.json')
const {
BANG,
NETLIFY_CYAN,
USER_AGENT,
chalk,
error,
execa,
exit,
getGlobalConfig,
log,
track,
warn,
} = require('../utils/index.cjs')

const { createAddonsCommand } = require('./addons/index.cjs')
const { createApiCommand } = require('./api/index.cjs')
const { BaseCommand } = require('./base-command.cjs')
const { createBuildCommand } = require('./build/index.cjs')
const { createCompletionCommand } = require('./completion/index.cjs')
const { createDeployCommand } = require('./deploy/index.cjs')
const { createDevCommand } = require('./dev/index.cjs')
const { createEnvCommand } = require('./env/index.cjs')
const { createFunctionsCommand } = require('./functions/index.cjs')
const { createGraphCommand } = require('./graph/index.cjs')
const { createInitCommand } = require('./init/index.cjs')
const { createLinkCommand } = require('./link/index.cjs')
const { createLmCommand } = require('./lm/index.cjs')
const { createLoginCommand } = require('./login/index.cjs')
const { createLogoutCommand } = require('./logout/index.cjs')
const { createOpenCommand } = require('./open/index.cjs')
const { createRecipesCommand, createRecipesListCommand } = require('./recipes/index.cjs')
const { createSitesCommand } = require('./sites/index.cjs')
const { createStatusCommand } = require('./status/index.cjs')
const { createSwitchCommand } = require('./switch/index.cjs')
const { createUnlinkCommand } = require('./unlink/index.cjs')
const { createWatchCommand } = require('./watch/index.cjs')
import { readFile } from 'fs/promises'
import process from 'process'
import { fileURLToPath } from 'url'

import { Option } from 'commander'
import inquirer from 'inquirer'
import { findBestMatch } from 'string-similarity'

// TODO: use named imports again once the imported file is esm
import utils from '../utils/index.cjs'

import { createAddonsCommand } from './addons/index.cjs'
import { createApiCommand } from './api/index.cjs'
import BaseCommand from './base-command.mjs'
import { createBuildCommand } from './build/index.cjs'
import { createCompletionCommand } from './completion/index.cjs'
import { createDeployCommand } from './deploy/index.cjs'
import { createDevCommand } from './dev/index.cjs'
import { createEnvCommand } from './env/index.cjs'
import { createFunctionsCommand } from './functions/index.cjs'
import { createGraphCommand } from './graph/index.cjs'
import { createInitCommand } from './init/index.cjs'
import { createLinkCommand } from './link/index.cjs'
import { createLmCommand } from './lm/index.cjs'
import { createLoginCommand } from './login/index.cjs'
import { createLogoutCommand } from './logout/index.cjs'
import { createOpenCommand } from './open/index.cjs'
import { createRecipesCommand, createRecipesListCommand } from './recipes/index.cjs'
import { createSitesCommand } from './sites/index.cjs'
import { createStatusCommand } from './status/index.cjs'
import { createSwitchCommand } from './switch/index.cjs'
import { createUnlinkCommand } from './unlink/index.cjs'
import { createWatchCommand } from './watch/index.cjs'

const { BANG, NETLIFY_CYAN, USER_AGENT, chalk, error, execa, exit, getGlobalConfig, log, track, warn } = utils

const SUGGESTION_TIMEOUT = 1e4

const getVersionPage = async () => {
// performance optimization - load envinfo on demand
// eslint-disable-next-line n/global-require
const envinfo = require('envinfo')

const envinfo = await import('envinfo')
const data = await envinfo.run({
System: ['OS', 'CPU'],
Binaries: ['Node', 'Yarn', 'npm'],
Expand Down Expand Up @@ -98,6 +90,8 @@ const mainCommand = async function (options, command) {

// if no command show the header and the help
if (command.args.length === 0) {
const pkg = JSON.parse(await readFile(fileURLToPath(new URL('../../package.json', import.meta.url))), 'utf-8')

const title = `${chalk.bgBlack.cyan('⬥ Netlify CLI')}`
const docsMsg = `${chalk.greenBright('Read the docs:')} https://docs.netlify.com/cli/get-started/`
const supportMsg = `${chalk.magentaBright('Support and bugs:')} ${pkg.bugs.url}`
Expand Down Expand Up @@ -161,7 +155,7 @@ const mainCommand = async function (options, command) {
* Promise is needed as the envinfo is a promise
* @returns {import('./base-command').BaseCommand}
*/
const createMainCommand = () => {
export const createMainCommand = () => {
const program = new BaseCommand('netlify')
// register all the commands
createAddonsCommand(program)
Expand Down Expand Up @@ -207,5 +201,3 @@ const createMainCommand = () => {

return program
}

module.exports = { createMainCommand }
4 changes: 2 additions & 2 deletions src/lib/completion/index.cjs
@@ -1,5 +1,5 @@
const generateAutocompletion = require('./generate-autocompletion.cjs')
const { createAutocompletion } = require('./generate-autocompletion.cjs')

module.exports = {
...generateAutocompletion,
createAutocompletion,
}

1 comment on commit 9261bc3

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

Package size: 233 MB

Please sign in to comment.