Skip to content

Commit

Permalink
chore: clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Apr 11, 2024
1 parent a5d1e6c commit 21f390d
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 94 deletions.
1 change: 0 additions & 1 deletion src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ export default class Plugins {
await yarn.install([], {
cwd: c.root,
logLevel: this.logLevel,
prod: false,
})
} else if (await fileExists(join(c.root, 'package-lock.json'))) {
this.debug('installing dependencies with npm')
Expand Down
97 changes: 4 additions & 93 deletions src/yarn.ts
Original file line number Diff line number Diff line change
@@ -1,103 +1,14 @@
import {Errors, Interfaces, ux} from '@oclif/core'
import {Interfaces, ux} from '@oclif/core'
import makeDebug from 'debug'
import {fork as cpFork} from 'node:child_process'
import {createRequire} from 'node:module'
import {fileURLToPath} from 'node:url'
import {npmRunPathEnv} from 'npm-run-path'

import {ExecOptions, Output, fork} from './fork.js'
import {LogLevel} from './log-level.js'

const require = createRequire(import.meta.url)
const debug = makeDebug('@oclif/plugin-plugins:yarn')

type ExecOptions = {
cwd: string
logLevel: LogLevel
}

type InstallOptions = ExecOptions & {
prod?: boolean
}

export type NpmOutput = {
stderr: string[]
stdout: string[]
}

async function fork(modulePath: string, args: string[] = [], {cwd, logLevel}: ExecOptions): Promise<NpmOutput> {
return new Promise((resolve, reject) => {
const forked = cpFork(modulePath, args, {
cwd,
env: {
...npmRunPathEnv(),
// Disable husky hooks because a plugin might be trying to install them, which will
// break the install since the install location isn't a .git directory.
HUSKY: '0',
},
execArgv: process.execArgv
.join(' ')
// Remove --loader ts-node/esm from execArgv so that the subprocess doesn't fail if it can't find ts-node.
// The ts-node/esm loader isn't need to execute npm commands anyways.
.replace('--loader ts-node/esm', '')
.replace('--loader=ts-node/esm', '')
.split(' ')
.filter(Boolean),
stdio: [0, null, null, 'ipc'],
})

const possibleLastLinesOfNpmInstall = ['up to date', 'added']
const stderr: string[] = []
const stdout: string[] = []
const loggedStderr: string[] = []
const loggedStdout: string[] = []

const shouldPrint = (str: string): boolean => {
// For ux cleanliness purposes, don't print the final line of npm install output if
// the log level is 'notice' and there's no other output.
const noOtherOutput = loggedStderr.length === 0 && loggedStdout.length === 0
const isLastLine = possibleLastLinesOfNpmInstall.some((line) => str.startsWith(line))
if (noOtherOutput && isLastLine && logLevel === 'notice') {
return false
}

return logLevel !== 'silent'
}

forked.stderr?.setEncoding('utf8')
forked.stderr?.on('data', (d: Buffer) => {
const output = d.toString().trim()
stderr.push(output)
if (shouldPrint(output)) {
loggedStderr.push(output)
ux.log(output)
} else debug(output)
})

forked.stdout?.setEncoding('utf8')
forked.stdout?.on('data', (d: Buffer) => {
const output = d.toString().trim()
stdout.push(output)
if (shouldPrint(output)) {
loggedStdout.push(output)
ux.log(output)
} else debug(output)
})

forked.on('error', reject)
forked.on('exit', (code: number) => {
if (code === 0) {
resolve({stderr, stdout})
} else {
reject(
new Errors.CLIError(`${modulePath} ${args.join(' ')} exited with code ${code}`, {
suggestions: ['Run with DEBUG=@oclif/plugin-plugins* to see debug output.'],
}),
)
}
})
})
}

export class Yarn {
private config: Interfaces.Config
private logLevel: LogLevel
Expand All @@ -107,7 +18,7 @@ export class Yarn {
this.logLevel = logLevel
}

async exec(args: string[] = [], options: ExecOptions): Promise<NpmOutput> {
async exec(args: string[] = [], options: ExecOptions): Promise<Output> {
const bin = await this.findYarn()
debug('yarn binary path', bin)

Expand All @@ -129,7 +40,7 @@ export class Yarn {
}
}

async install(args: string[], opts: InstallOptions): Promise<NpmOutput> {
async install(args: string[], opts: ExecOptions): Promise<Output> {
return this.exec(['install', ...args], opts)
}

Expand Down

0 comments on commit 21f390d

Please sign in to comment.