Repository: oclif/core
Pull request #776 (2023-09-01 09:58:53)

feat: revert exports changes


Patch:
diff --git a/README.md b/README.md
index c8b893e..2a7e60c 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ See the [v3 migration guide](./guides/V3_MIGRATION.md) for an overview of breaki
 CLI UX
 =====
 
-The [ux README](./src/ux/README.md) contains detailed usage examples of using the `ux` export.
+The [ux README](./src/cli-ux/README.md) contains detailed usage examples of using the `ux` export.
 
 Usage
 =====
diff --git a/flush.d.ts b/flush.d.ts
new file mode 100644
index 0000000..5ca9b09
--- /dev/null
+++ b/flush.d.ts
@@ -0,0 +1,3 @@
+declare const flush: () => Promise<void>
+
+export = flush
diff --git a/flush.js b/flush.js
new file mode 100644
index 0000000..0808110
--- /dev/null
+++ b/flush.js
@@ -0,0 +1,1 @@
+module.exports = require('./lib/cli-ux/flush').flush
diff --git a/guides/V3_MIGRATION.md b/guides/V3_MIGRATION.md
index c130a80..82811fa 100644
--- a/guides/V3_MIGRATION.md
+++ b/guides/V3_MIGRATION.md
@@ -12,7 +12,6 @@ Migrating to @oclif/core@V3
     - [`handle`](#handle)
     - [`noCacheDefault` flag property replaces `isWritingManifest`](#nocachedefault-flag-property-replaces-iswritingmanifest)
   - [Features 🎉](#features-)
-    - [Exports](#exports)
     - [Cache Flexible taxonomy Command Permutations](#cache-flexible-taxonomy-command-permutations)
 
 
@@ -112,31 +111,6 @@ export const mySensitiveFlag = Flags.string({
 
 ## Features 🎉
 
-### Exports
-The `exports` property in the package.json are now used for exporting a few individual pieces of functionality.
-
-The main export should continue to work as it did in v2:
-
-```typescript
-import {handle, flush} from '@oclif/core'
-```
-
-But you can now import individual modules if desired:
-
-```typescript
-import handle from '@oclif/core/handle'
-import flush from '@oclif/core/flush'
-```
-
-These are the exports that are available:
-`@oclif/core/execute`
-`@oclif/core/flush`
-`@oclif/core/handle`
-`@oclif/core/run`
-`@oclif/core/settings`
-
-**You will need to set moduleResolution to Node16 in your tsconfig.json to use this feature.**
-
 ### Cache Flexible taxonomy Command Permutations
 
 The command permutations for flexible taxonomy are now cached in the oclif.manifest.json allowing for quicker startup times.
diff --git a/handle.js b/handle.js
new file mode 100644
index 0000000..aff2c83
--- /dev/null
+++ b/handle.js
@@ -0,0 +1,1 @@
+module.exports = async error => require('./lib/errors/handle').handle(error)
diff --git a/package.json b/package.json
index e782e2e..9ce7fda 100644
--- a/package.json
+++ b/package.json
@@ -83,7 +83,10 @@
     "node": ">=16.0.0"
   },
   "files": [
-    "/lib"
+    "/lib",
+    "/flush.js",
+    "/flush.d.ts",
+    "/handle.js"
   ],
   "homepage": "https://github.com/oclif/core",
   "keywords": [
@@ -91,14 +94,6 @@
   ],
   "license": "MIT",
   "main": "./lib/index.js",
-  "exports": {
-    ".": "./lib/index.js",
-    "./execute": "./lib/execute.js",
-    "./flush": "./lib/ux/flush.js",
-    "./handle": "./lib/errors/handle.js",
-    "./run": "./lib/main.js",
-    "./settings": "./lib/settings.js"
-  },
   "repository": "oclif/core",
   "oclif": {
     "bin": "oclif",
diff --git a/src/ux/README.md b/src/cli-ux/README.md
similarity index 100%
rename from src/ux/README.md
rename to src/cli-ux/README.md
diff --git a/src/ux/action/base.ts b/src/cli-ux/action/base.ts
similarity index 100%
rename from src/ux/action/base.ts
rename to src/cli-ux/action/base.ts
diff --git a/src/ux/action/simple.ts b/src/cli-ux/action/simple.ts
similarity index 100%
rename from src/ux/action/simple.ts
rename to src/cli-ux/action/simple.ts
diff --git a/src/ux/action/spinner.ts b/src/cli-ux/action/spinner.ts
similarity index 100%
rename from src/ux/action/spinner.ts
rename to src/cli-ux/action/spinner.ts
diff --git a/src/ux/action/spinners.ts b/src/cli-ux/action/spinners.ts
similarity index 100%
rename from src/ux/action/spinners.ts
rename to src/cli-ux/action/spinners.ts
diff --git a/src/ux/config.ts b/src/cli-ux/config.ts
similarity index 100%
rename from src/ux/config.ts
rename to src/cli-ux/config.ts
diff --git a/src/ux/exit.ts b/src/cli-ux/exit.ts
similarity index 100%
rename from src/ux/exit.ts
rename to src/cli-ux/exit.ts
diff --git a/src/ux/flush.ts b/src/cli-ux/flush.ts
similarity index 89%
rename from src/ux/flush.ts
rename to src/cli-ux/flush.ts
index ceae1d8..148975e 100644
--- a/src/ux/flush.ts
+++ b/src/cli-ux/flush.ts
@@ -24,6 +24,6 @@ async function _flush() {
   return p
 }
 
-export default async function flush(ms = 10_000): Promise<void> {
+export async function flush(ms = 10_000): Promise<void> {
   await timeout(_flush(), ms)
 }
diff --git a/src/ux/global.d.ts b/src/cli-ux/global.d.ts
similarity index 100%
rename from src/ux/global.d.ts
rename to src/cli-ux/global.d.ts
diff --git a/src/ux/index.ts b/src/cli-ux/index.ts
similarity index 97%
rename from src/ux/index.ts
rename to src/cli-ux/index.ts
index b1df2bb..a882f92 100644
--- a/src/ux/index.ts
+++ b/src/cli-ux/index.ts
@@ -7,15 +7,14 @@ import {ExitError} from './exit'
 import {IPromptOptions} from './prompt'
 import * as styled from './styled'
 import {Table} from './styled'
-export * from './styled/table'
 import * as uxPrompt from './prompt'
 import uxWait from './wait'
 import {stdout} from './stream'
-import * as _flush from './flush'
+import {flush as _flush} from './flush'
 
 const hyperlinker = require('hyperlinker')
 
-export default class ux {
+export class ux {
   public static config: Config = config
 
   public static get prompt(): typeof uxPrompt.prompt {
@@ -110,7 +109,7 @@ export default class ux {
   }
 
   public static async flush(ms = 10_000): Promise<void> {
-    await _flush.default(ms)
+    await _flush(ms)
   }
 }
 
@@ -139,15 +138,20 @@ const warn = Errors.warn
 
 export {
   action,
+  ActionBase,
   annotation,
   anykey,
+  config,
+  Config,
   confirm,
   debug,
   done,
   error,
   exit,
+  ExitError,
   flush,
   info,
+  IPromptOptions,
   log,
   progress,
   prompt,
@@ -155,17 +159,12 @@ export {
   styledJSON,
   styledObject,
   table,
+  Table,
   trace,
   tree,
   url,
   wait,
   warn,
-  ActionBase,
-  config,
-  Config,
-  ExitError,
-  IPromptOptions,
-  Table,
 }
 
 const uxProcessExitHandler = async () => {
diff --git a/src/ux/list.ts b/src/cli-ux/list.ts
similarity index 100%
rename from src/ux/list.ts
rename to src/cli-ux/list.ts
diff --git a/src/ux/prompt.ts b/src/cli-ux/prompt.ts
similarity index 99%
rename from src/ux/prompt.ts
rename to src/cli-ux/prompt.ts
index 7f4d7a0..a3a8c0d 100644
--- a/src/ux/prompt.ts
+++ b/src/cli-ux/prompt.ts
@@ -93,6 +93,7 @@ async function _prompt(name: string, inputOptions: Partial<IPromptOptions> = {})
     ...inputOptions,
   }
   const passwordPrompt = require('password-prompt')
+
   switch (options.type) {
   case 'normal':
     return normal(options)
diff --git a/src/ux/stream.ts b/src/cli-ux/stream.ts
similarity index 100%
rename from src/ux/stream.ts
rename to src/cli-ux/stream.ts
diff --git a/src/ux/styled/index.ts b/src/cli-ux/styled/index.ts
similarity index 100%
rename from src/ux/styled/index.ts
rename to src/cli-ux/styled/index.ts
diff --git a/src/ux/styled/json.ts b/src/cli-ux/styled/json.ts
similarity index 92%
rename from src/ux/styled/json.ts
rename to src/cli-ux/styled/json.ts
index 363b492..55a0628 100644
--- a/src/ux/styled/json.ts
+++ b/src/cli-ux/styled/json.ts
@@ -1,6 +1,6 @@
 import * as chalk from 'chalk'
 
-import ux from '../index'
+import {ux} from '../index'
 
 export default function styledJSON(obj: unknown): void {
   const json = JSON.stringify(obj, null, 2)
diff --git a/src/ux/styled/object.ts b/src/cli-ux/styled/object.ts
similarity index 100%
rename from src/ux/styled/object.ts
rename to src/cli-ux/styled/object.ts
diff --git a/src/ux/styled/progress.ts b/src/cli-ux/styled/progress.ts
similarity index 100%
rename from src/ux/styled/progress.ts
rename to src/cli-ux/styled/progress.ts
diff --git a/src/ux/styled/table.ts b/src/cli-ux/styled/table.ts
similarity index 100%
rename from src/ux/styled/table.ts
rename to src/cli-ux/styled/table.ts
diff --git a/src/ux/styled/tree.ts b/src/cli-ux/styled/tree.ts
similarity index 100%
rename from src/ux/styled/tree.ts
rename to src/cli-ux/styled/tree.ts
diff --git a/src/ux/wait.ts b/src/cli-ux/wait.ts
similarity index 100%
rename from src/ux/wait.ts
rename to src/cli-ux/wait.ts
diff --git a/src/command.ts b/src/command.ts
index fba35e5..1bccd6e 100644
--- a/src/command.ts
+++ b/src/command.ts
@@ -1,7 +1,7 @@
 import {fileURLToPath} from 'url'
 import * as chalk from 'chalk'
 import {format, inspect} from 'util'
-import ux from './ux'
+import {ux} from './cli-ux'
 import {Config} from './config'
 import * as Errors from './errors'
 import {PrettyPrintableError} from './errors'
@@ -27,7 +27,7 @@ import {CommandError} from './interfaces/errors'
 import {boolean} from './flags'
 import {requireJson} from './util'
 import {PJSON} from './interfaces'
-import {stdout, stderr} from './ux/stream'
+import {stdout, stderr} from './cli-ux/stream'
 
 const pjson = requireJson<PJSON>(__dirname, '..', 'package.json')
 
diff --git a/src/config/config.ts b/src/config/config.ts
index f776048..3e038e0 100644
--- a/src/config/config.ts
+++ b/src/config/config.ts
@@ -14,9 +14,9 @@ import ModuleLoader from '../module-loader'
 import {getHelpFlagAdditions} from '../help'
 import {Command} from '../command'
 import {CompletableOptionFlag, Arg} from '../interfaces/parser'
-import {stdout} from '../ux/stream'
+import {stdout} from '../cli-ux/stream'
 import Performance from '../performance'
-import settings from '../settings'
+import {settings} from '../settings'
 import {userInfo as osUserInfo} from 'node:os'
 import {sep} from 'node:path'
 import PluginLoader from './plugin-loader'
diff --git a/src/config/ts-node.ts b/src/config/ts-node.ts
index d4fb96a..478f5e2 100644
--- a/src/config/ts-node.ts
+++ b/src/config/ts-node.ts
@@ -3,7 +3,7 @@ import * as path from 'path'
 import * as TSNode from 'ts-node'
 
 import {TSConfig, Plugin} from '../interfaces'
-import settings from '../settings'
+import {settings} from '../settings'
 import {isProd} from '../util'
 import {Debug} from './util'
 import {Config} from './config'
diff --git a/src/errors/config.ts b/src/errors/config.ts
index b0876ca..7a757f9 100644
--- a/src/errors/config.ts
+++ b/src/errors/config.ts
@@ -1,4 +1,4 @@
-import settings from '../settings'
+import {settings} from '../settings'
 import {Logger} from './logger'
 
 function displayWarnings() {
diff --git a/src/errors/handle.ts b/src/errors/handle.ts
index 81cb6ec..0c0af3d 100644
--- a/src/errors/handle.ts
+++ b/src/errors/handle.ts
@@ -7,7 +7,7 @@ import clean = require('clean-stack')
 import {CLIError} from './errors/cli'
 import {OclifError, PrettyPrintableError} from '../interfaces'
 
-export default async function handle(err: Error & Partial<PrettyPrintableError> & Partial<OclifError> & {skipOclifErrorHandling?: boolean}): Promise<void> {
+export async function handle(err: Error & Partial<PrettyPrintableError> & Partial<OclifError> & {skipOclifErrorHandling?: boolean}): Promise<void> {
   try {
     if (!err) err = new CLIError('no error?')
     if (err.message === 'SIGINT') process.exit(1)
diff --git a/src/errors/index.ts b/src/errors/index.ts
index a55c06b..4fbbbfe 100644
--- a/src/errors/index.ts
+++ b/src/errors/index.ts
@@ -1,4 +1,4 @@
-export {default as handle} from './handle'
+export {handle} from './handle'
 export {ExitError} from './errors/exit'
 export {ModuleLoadError} from './errors/module-load'
 export {CLIError} from './errors/cli'
diff --git a/src/execute.ts b/src/execute.ts
index a8761b9..f83b014 100644
--- a/src/execute.ts
+++ b/src/execute.ts
@@ -1,6 +1,6 @@
-import settings from './settings'
-import flush from './ux/flush'
-import handle from './errors/handle'
+import {settings} from './settings'
+import {flush} from './cli-ux/flush'
+import {handle} from './errors/handle'
 import run from './main'
 import * as Interfaces from './interfaces'
 
diff --git a/src/help/index.ts b/src/help/index.ts
index 37cf2bb..20cc062 100644
--- a/src/help/index.ts
+++ b/src/help/index.ts
@@ -9,7 +9,7 @@ import {formatCommandDeprecationWarning, getHelpFlagAdditions, standardizeIDFrom
 import {HelpFormatter} from './formatter'
 import {toCached} from '../config/config'
 import {Command} from '../command'
-import {stdout} from '../ux/stream'
+import {stdout} from '../cli-ux/stream'
 export {CommandHelp} from './command'
 export {standardizeIDFromArgv, loadHelpClass, getHelpFlagAdditions, normalizeArgv} from './util'
 
diff --git a/src/index.ts b/src/index.ts
index 40a4ae3..97621e0 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,7 +1,7 @@
 import {Command} from './command'
 import run from './main'
 import execute from './execute'
-import handle from './errors/handle'
+import {handle} from './errors/handle'
 import {Config, Plugin, tsPath, toCached} from './config'
 import * as Interfaces from './interfaces'
 import * as Errors from './errors'
@@ -11,12 +11,12 @@ import {CommandHelp, HelpBase, Help, loadHelpClass} from './help'
 import {toStandardizedId, toConfiguredId} from './help/util'
 import * as Parser from './parser'
 import {Hook} from './interfaces/hooks'
-import settings, {Settings} from './settings'
+import {settings, Settings} from './settings'
 import {HelpSection, HelpSectionRenderer, HelpSectionKeyValueTable} from './help/formatter'
-import * as ux from './ux'
-import {stderr, stdout} from './ux/stream'
+import * as ux from './cli-ux'
+import {stderr, stdout} from './cli-ux/stream'
 import Performance from './performance'
-import flush from './ux/flush'
+import {flush} from './cli-ux/flush'
 
 export {
   Args,
diff --git a/src/main.ts b/src/main.ts
index c0107d2..488679a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -6,7 +6,7 @@ import * as Interfaces from './interfaces'
 import {URL} from 'url'
 import {Config} from './config'
 import {getHelpFlagAdditions, loadHelpClass, normalizeArgv} from './help'
-import {stdout} from './ux/stream'
+import {stdout} from './cli-ux/stream'
 import Performance from './performance'
 
 const debug = require('debug')('oclif:main')
diff --git a/src/parser/errors.ts b/src/parser/errors.ts
index 63fd884..d6a8321 100644
--- a/src/parser/errors.ts
+++ b/src/parser/errors.ts
@@ -1,7 +1,7 @@
 import {CLIError} from '../errors'
 
 import {flagUsages} from './help'
-import {renderList} from '../ux/list'
+import {renderList} from '../cli-ux/list'
 import * as chalk from 'chalk'
 import {OptionFlag, Flag} from '../interfaces'
 import {uniq} from '../config/util'
diff --git a/src/performance.ts b/src/performance.ts
index d1e58f8..9705f88 100644
--- a/src/performance.ts
+++ b/src/performance.ts
@@ -1,5 +1,5 @@
 import {PerformanceObserver, performance} from 'perf_hooks'
-import settings from './settings'
+import {settings} from './settings'
 
 type Details = Record<string, string | boolean | number | string[]>
 type PerfResult = {
diff --git a/src/screen.ts b/src/screen.ts
index cc86f45..68b1e6f 100644
--- a/src/screen.ts
+++ b/src/screen.ts
@@ -1,5 +1,5 @@
-import {stdout, stderr} from './ux/stream'
-import settings from './settings'
+import {stdout, stderr} from './cli-ux/stream'
+import {settings} from './settings'
 
 function termwidth(stream: any): number {
   if (!stream.isTTY) {
diff --git a/src/settings.ts b/src/settings.ts
index dd94d6d..9f797f8 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -40,5 +40,4 @@ export type Settings = {
 // Set global.oclif to the new object if it wasn't set before
 if (!(global as any).oclif) (global as any).oclif = {}
 
-const settings: Settings = (global as any).oclif as Settings
-export default settings
+export const settings: Settings = (global as any).oclif as Settings


Test patch:
diff --git a/test/cli-ux/export.test.ts b/test/cli-ux/export.test.ts
index 5caa755..4a50da4 100644
--- a/test/cli-ux/export.test.ts
+++ b/test/cli-ux/export.test.ts
@@ -1,4 +1,4 @@
-import ux, {Table, IPromptOptions, Config, ActionBase, ExitError} from '../../src/ux'
+import {ux, Table, IPromptOptions, Config, ActionBase, ExitError} from '../../src/cli-ux'
 import {expect} from 'chai'
 
 type MyColumns = Record<string, unknown>
diff --git a/test/cli-ux/fancy.ts b/test/cli-ux/fancy.ts
index 9f7a60b..74d8c17 100644
--- a/test/cli-ux/fancy.ts
+++ b/test/cli-ux/fancy.ts
@@ -2,7 +2,7 @@ import {expect, fancy as base, FancyTypes} from 'fancy-test'
 import {rm} from 'node:fs/promises'
 import {join} from 'node:path'
 
-import ux from '../../src/ux'
+import {ux} from '../../src/cli-ux'
 
 export {
   expect,
diff --git a/test/cli-ux/index.test.ts b/test/cli-ux/index.test.ts
index 234c9d0..866449a 100644
--- a/test/cli-ux/index.test.ts
+++ b/test/cli-ux/index.test.ts
@@ -1,4 +1,4 @@
-import ux from '../../src/ux'
+import {ux} from '../../src/cli-ux'
 
 import {expect, fancy} from './fancy'
 const hyperlinker = require('hyperlinker')
diff --git a/test/cli-ux/prompt.test.ts b/test/cli-ux/prompt.test.ts
index 18676fb..fd8c681 100644
--- a/test/cli-ux/prompt.test.ts
+++ b/test/cli-ux/prompt.test.ts
@@ -2,7 +2,7 @@ import * as chai from 'chai'
 
 const expect = chai.expect
 
-import ux from '../../src/ux'
+import {ux} from '../../src/cli-ux'
 
 import {fancy} from './fancy'
 
diff --git a/test/cli-ux/styled/header.test.ts b/test/cli-ux/styled/header.test.ts
index 619d071..65fb714 100644
--- a/test/cli-ux/styled/header.test.ts
+++ b/test/cli-ux/styled/header.test.ts
@@ -2,7 +2,7 @@ import {expect} from 'chai'
 
 import {stdout} from '../../../src'
 import {stub, SinonStub} from 'sinon'
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 
 describe('styled/header', () => {
   let writeStub: SinonStub
diff --git a/test/cli-ux/styled/object.test.ts b/test/cli-ux/styled/object.test.ts
index f0e4d93..8c35056 100644
--- a/test/cli-ux/styled/object.test.ts
+++ b/test/cli-ux/styled/object.test.ts
@@ -1,6 +1,6 @@
 import {expect, fancy} from 'fancy-test'
 
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 
 describe('styled/object', () => {
   fancy
diff --git a/test/cli-ux/styled/progress.test.ts b/test/cli-ux/styled/progress.test.ts
index 098ec06..63ecd75 100644
--- a/test/cli-ux/styled/progress.test.ts
+++ b/test/cli-ux/styled/progress.test.ts
@@ -1,5 +1,5 @@
 import {expect, fancy} from 'fancy-test'
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 
 describe('progress', () => {
   // single bar
diff --git a/test/cli-ux/styled/table.e2e.ts b/test/cli-ux/styled/table.e2e.ts
index a5b162d..c590209 100644
--- a/test/cli-ux/styled/table.e2e.ts
+++ b/test/cli-ux/styled/table.e2e.ts
@@ -1,5 +1,5 @@
 import {expect, fancy} from 'fancy-test'
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 
 describe('styled/table', () => {
   describe('null/undefined handling', () => {
diff --git a/test/cli-ux/styled/table.test.ts b/test/cli-ux/styled/table.test.ts
index 90056da..6fa148a 100644
--- a/test/cli-ux/styled/table.test.ts
+++ b/test/cli-ux/styled/table.test.ts
@@ -1,6 +1,6 @@
 import {expect, fancy} from 'fancy-test'
 
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 import * as screen from '../../../src/screen'
 
 /* eslint-disable camelcase */
diff --git a/test/cli-ux/styled/tree.test.ts b/test/cli-ux/styled/tree.test.ts
index 5e4e470..0706d06 100644
--- a/test/cli-ux/styled/tree.test.ts
+++ b/test/cli-ux/styled/tree.test.ts
@@ -1,6 +1,6 @@
 import {expect, fancy} from 'fancy-test'
 
-import ux from '../../../src/ux'
+import {ux} from '../../../src/cli-ux'
 
 describe('styled/tree', () => {
   fancy
diff --git a/test/errors/handle.test.ts b/test/errors/handle.test.ts
index db08132..29536b8 100644
--- a/test/errors/handle.test.ts
+++ b/test/errors/handle.test.ts
@@ -4,7 +4,7 @@ import * as path from 'path'
 import * as process from 'process'
 
 import {CLIError, config, ExitError} from '../../src/errors'
-import handle from '../../src/errors/handle'
+import {handle} from '../../src/errors/handle'
 import {exit as exitErrorThrower} from '../../src/errors'
 
 const errlog = path.join(__dirname, '../tmp/mytest/error.log')
diff --git a/test/integration/sf.e2e.ts b/test/integration/sf.e2e.ts
index 3b2bc49..69ea754 100644
--- a/test/integration/sf.e2e.ts
+++ b/test/integration/sf.e2e.ts
@@ -15,7 +15,15 @@ describe('Salesforce CLI (sf)', () => {
   let executor: Executor
   before(async () => {
     process.env.SFDX_TELEMETRY_DISABLE_ACKNOWLEDGEMENT = 'true'
-    executor = await setup(__filename, {repo: 'https://github.com/salesforcecli/cli'})
+    executor = await setup(__filename, {
+      repo: 'https://github.com/salesforcecli/cli',
+      // Allowing failed install here because it let's attempt to run the tests
+      // even if there's a linting error caused by the code changes. This is only
+      // acceptable since we're crossing major versions at the moment. It should
+      // be removed as soon as sf uses v3.
+      allowFailedInstall: true,
+      compileCmd: 'yarn compile',
+    })
   })
 
   it('should show custom help', async () => {
diff --git a/test/integration/util.ts b/test/integration/util.ts
index 44e875e..98d4e58 100644
--- a/test/integration/util.ts
+++ b/test/integration/util.ts
@@ -23,6 +23,8 @@ export type SetupOptions = {
   repo: string;
   plugins?: string[];
   subDir?: string;
+  allowFailedInstall?: boolean;
+  compileCmd?: string;
 }
 
 export type ExecutorOptions = {
@@ -187,15 +189,16 @@ export async function setup(testFile: string, options: SetupOptions): Promise<Ex
   executor.debug(`${bin}_CACHE_DIR:`, process.env[`${bin}_CACHE_DIR`])
 
   const yarnInstallRes = await executor.executeInTestDir('yarn install --force')
-  if (yarnInstallRes.code !== 0) {
+  if (yarnInstallRes.code !== 0 && !options.allowFailedInstall) {
     console.error(yarnInstallRes?.error)
     throw new Error('Failed to run `yarn install`')
   }
 
-  const yarnBuildRes = await executor.executeInTestDir('yarn build')
-  if (yarnBuildRes.code !== 0) {
-    console.error(yarnBuildRes?.error)
-    throw new Error('Failed to run `yarn build`')
+  const compileCmd = options.compileCmd ?? 'yarn build'
+  const compileRes = await executor.executeInTestDir(compileCmd)
+  if (compileRes.code !== 0) {
+    console.error(compileRes?.error)
+    throw new Error(`Failed to run \`${compileCmd}\``)
   }
 
   return executor