mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05:00
feat: --stream
Add new global option called `--stream`. When used, the output from child processes is streamed to the console immediately, prefixed with the originating package directory. This allows output from different packages to be interleaved. close #2147 close #1609 PR #2595
This commit is contained in:
5
.changeset/happy-baboons-stare.md
Normal file
5
.changeset/happy-baboons-stare.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/common-cli-options-help": minor
|
||||
---
|
||||
|
||||
Add `--stream` option description to the `UNIVERSAL_OPTIONS` array.
|
||||
5
.changeset/late-pets-rescue.md
Normal file
5
.changeset/late-pets-rescue.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/default-reporter": minor
|
||||
---
|
||||
|
||||
Add new reporting option: `streamLifecycleOutput`. When `true`, the output from child processes is printed immediately and is never collapsed.
|
||||
8
.changeset/lovely-zebras-heal.md
Normal file
8
.changeset/lovely-zebras-heal.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@pnpm/config": minor
|
||||
"@pnpm/plugin-commands-script-runners": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
Add new global option called `--stream`.
|
||||
When used, the output from child processes is streamed to the console immediately, prefixed with the originating package directory. This allows output from different packages to be interleaved.
|
||||
@@ -44,6 +44,10 @@ export const UNIVERSAL_OPTIONS = [
|
||||
description: 'What level of logs to report. Any logs at or higher than the given level will be shown. Levels (lowest to highest): debug, info, warn, error. Or use "--silent" to turn off all logging.',
|
||||
name: '--loglevel <level>',
|
||||
},
|
||||
{
|
||||
description: 'Stream output from child processes immediately, prefixed with the originating package directory. This allows output from different packages to be interleaved.',
|
||||
name: '--stream',
|
||||
},
|
||||
]
|
||||
export const FILTERING = {
|
||||
list: [
|
||||
|
||||
@@ -39,6 +39,7 @@ export interface Config {
|
||||
saveOptional?: boolean,
|
||||
savePeer?: boolean,
|
||||
saveWorkspaceProtocol?: boolean,
|
||||
stream?: boolean,
|
||||
production?: boolean,
|
||||
fetchRetries?: number,
|
||||
fetchRetryFactor?: number,
|
||||
|
||||
@@ -75,6 +75,7 @@ export const types = Object.assign({
|
||||
'sort': Boolean,
|
||||
'store': String, // TODO: deprecate
|
||||
'store-dir': String,
|
||||
'stream': Boolean,
|
||||
'strict-peer-dependencies': Boolean,
|
||||
'use-beta-cli': Boolean,
|
||||
'use-running-store-server': Boolean,
|
||||
|
||||
@@ -15,6 +15,7 @@ export default function (
|
||||
reportingOptions?: {
|
||||
appendOnly?: boolean,
|
||||
logLevel?: LogLevel,
|
||||
streamLifecycleOutput?: boolean,
|
||||
throttleProgress?: number,
|
||||
outputMaxWidth?: number,
|
||||
},
|
||||
@@ -66,6 +67,7 @@ export function toOutput$ (
|
||||
appendOnly?: boolean,
|
||||
logLevel?: LogLevel,
|
||||
outputMaxWidth?: number,
|
||||
streamLifecycleOutput?: boolean,
|
||||
throttleProgress?: number,
|
||||
},
|
||||
context: {
|
||||
@@ -174,6 +176,7 @@ export function toOutput$ (
|
||||
isRecursive: opts.context.config?.['recursive'] === true,
|
||||
logLevel: opts.reportingOptions?.logLevel,
|
||||
pnpmConfig: opts.context.config,
|
||||
streamLifecycleOutput: opts.reportingOptions?.streamLifecycleOutput,
|
||||
throttleProgress: opts.reportingOptions?.throttleProgress,
|
||||
width: opts.reportingOptions?.outputMaxWidth,
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export default function (
|
||||
isRecursive: boolean,
|
||||
logLevel?: LogLevel,
|
||||
pnpmConfig?: Config,
|
||||
streamLifecycleOutput?: boolean,
|
||||
throttleProgress?: number,
|
||||
width?: number,
|
||||
}
|
||||
@@ -52,7 +53,7 @@ export default function (
|
||||
throttleProgress: opts.throttleProgress,
|
||||
}),
|
||||
reportLifecycleScripts(log$, {
|
||||
appendOnly: opts.appendOnly,
|
||||
appendOnly: opts.appendOnly || opts.streamLifecycleOutput,
|
||||
cwd,
|
||||
width,
|
||||
}),
|
||||
|
||||
@@ -26,10 +26,8 @@ export default (
|
||||
// When the reporter is not append-only, the length of output is limited
|
||||
// in order to reduce flickering
|
||||
if (opts.appendOnly) {
|
||||
return most.of(
|
||||
log$.lifecycle
|
||||
.map((log: LifecycleLog) => ({ msg: formatLifecycleHideOverflowForAppendOnly(opts.cwd, log) }))
|
||||
)
|
||||
return log$.lifecycle
|
||||
.map((log: LifecycleLog) => most.of({ msg: formatLifecycleHideOverflowForAppendOnly(opts.cwd, log) }))
|
||||
}
|
||||
const lifecycleMessages: {
|
||||
[depPath: string]: {
|
||||
|
||||
@@ -259,6 +259,125 @@ test('groups lifecycle output when append-only is used', t => {
|
||||
})
|
||||
})
|
||||
|
||||
test('groups lifecycle output when streamLifecycleOutput is used', t => {
|
||||
const output$ = toOutput$({
|
||||
context: { argv: ['install'] },
|
||||
reportingOptions: {
|
||||
outputMaxWidth: 79,
|
||||
streamLifecycleOutput: true,
|
||||
},
|
||||
streamParser: createStreamParser(),
|
||||
})
|
||||
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
optional: false,
|
||||
script: 'node foo',
|
||||
stage: 'preinstall',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
line: 'foo 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30',
|
||||
stage: 'preinstall',
|
||||
stdio: 'stdout',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
exitCode: 1,
|
||||
optional: true,
|
||||
stage: 'preinstall',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
optional: false,
|
||||
script: 'node foo',
|
||||
stage: 'postinstall',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
line: 'foo I',
|
||||
stage: 'postinstall',
|
||||
stdio: 'stdout',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/bar',
|
||||
optional: false,
|
||||
script: 'node bar',
|
||||
stage: 'postinstall',
|
||||
wd: 'packages/bar',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/bar',
|
||||
line: 'bar I',
|
||||
stage: 'postinstall',
|
||||
stdio: 'stdout',
|
||||
wd: 'packages/bar',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
line: 'foo II',
|
||||
stage: 'postinstall',
|
||||
stdio: 'stdout',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
line: 'foo III',
|
||||
stage: 'postinstall',
|
||||
stdio: 'stdout',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/qar',
|
||||
optional: false,
|
||||
script: 'node qar',
|
||||
stage: 'install',
|
||||
wd: 'packages/qar',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/qar',
|
||||
exitCode: 0,
|
||||
optional: false,
|
||||
stage: 'install',
|
||||
wd: 'packages/qar',
|
||||
})
|
||||
lifecycleLogger.debug({
|
||||
depPath: 'packages/foo',
|
||||
exitCode: 0,
|
||||
optional: false,
|
||||
stage: 'postinstall',
|
||||
wd: 'packages/foo',
|
||||
})
|
||||
|
||||
t.plan(1)
|
||||
|
||||
output$.skip(11).take(1).map(normalizeNewline).subscribe({
|
||||
complete: () => t.end(),
|
||||
error: t.end,
|
||||
next: (output: string) => {
|
||||
t.equal(output, stripIndents`
|
||||
packages/foo ${PREINSTALL}$ node foo
|
||||
packages/foo ${PREINSTALL}: foo 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
||||
packages/foo ${PREINSTALL}: Failed
|
||||
packages/foo ${POSTINSTALL}$ node foo
|
||||
packages/foo ${POSTINSTALL}: foo I
|
||||
packages/bar ${POSTINSTALL}$ node bar
|
||||
packages/bar ${POSTINSTALL}: bar I
|
||||
packages/foo ${POSTINSTALL}: foo II
|
||||
packages/foo ${POSTINSTALL}: foo III
|
||||
packages/qar ${INSTALL}$ node qar
|
||||
packages/qar ${INSTALL}: Done
|
||||
packages/foo ${POSTINSTALL}: Done
|
||||
`)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('collapse lifecycle output when it has too many lines', t => {
|
||||
const output$ = toOutput$({
|
||||
context: { argv: ['install'] },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { docsUrl, readProjectManifestOnly } from '@pnpm/cli-utils'
|
||||
import { CompletionFunc } from '@pnpm/command'
|
||||
import { FILTERING } from '@pnpm/common-cli-options-help'
|
||||
import { FILTERING, UNIVERSAL_OPTIONS } from '@pnpm/common-cli-options-help'
|
||||
import { Config, types as allTypes } from '@pnpm/config'
|
||||
import PnpmError from '@pnpm/error'
|
||||
import runLifecycleHooks from '@pnpm/lifecycle'
|
||||
@@ -69,6 +69,7 @@ export function help () {
|
||||
shortAlias: '-r',
|
||||
},
|
||||
IF_PRESENT_OPTION_HELP,
|
||||
...UNIVERSAL_OPTIONS,
|
||||
],
|
||||
},
|
||||
FILTERING,
|
||||
|
||||
@@ -34,6 +34,7 @@ export const GLOBAL_OPTIONS = R.pick([
|
||||
'parseable',
|
||||
'prefix',
|
||||
'reporter',
|
||||
'stream',
|
||||
'workspace-packages',
|
||||
], allTypes)
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export default (
|
||||
reportingOptions: {
|
||||
appendOnly: false,
|
||||
logLevel: opts.config.loglevel as LogLevel,
|
||||
streamLifecycleOutput: opts.config.stream,
|
||||
throttleProgress: 200,
|
||||
},
|
||||
streamParser,
|
||||
|
||||
Reference in New Issue
Block a user