@oclif/core 3.0.0-beta.9 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/flush.d.ts +3 -0
- package/flush.js +1 -0
- package/handle.js +1 -0
- package/lib/args.d.ts +2 -2
- package/lib/args.js +17 -18
- package/lib/{ux → cli-ux}/action/base.d.ts +19 -21
- package/lib/{ux → cli-ux}/action/base.js +126 -120
- package/lib/{ux → cli-ux}/action/simple.js +25 -30
- package/lib/{ux → cli-ux}/action/spinner.d.ts +9 -7
- package/lib/{ux → cli-ux}/action/spinner.js +45 -37
- package/lib/{ux → cli-ux}/action/spinners.js +187 -187
- package/lib/cli-ux/action/types.d.ts +5 -0
- package/lib/cli-ux/action/types.js +2 -0
- package/lib/{ux → cli-ux}/config.d.ts +5 -5
- package/lib/{ux → cli-ux}/config.js +17 -17
- package/lib/{ux → cli-ux}/exit.js +3 -0
- package/lib/cli-ux/flush.d.ts +1 -0
- package/lib/cli-ux/flush.js +28 -0
- package/lib/cli-ux/index.d.ts +39 -0
- package/lib/{ux → cli-ux}/index.js +74 -88
- package/lib/{ux → cli-ux}/list.js +3 -3
- package/lib/{ux → cli-ux}/prompt.d.ts +3 -3
- package/lib/{ux → cli-ux}/prompt.js +35 -25
- package/lib/{ux → cli-ux}/stream.d.ts +6 -6
- package/lib/{ux → cli-ux}/stream.js +11 -10
- package/lib/cli-ux/styled/index.d.ts +4 -0
- package/lib/cli-ux/styled/index.js +11 -0
- package/lib/{ux → cli-ux}/styled/object.js +7 -9
- package/lib/{ux → cli-ux}/styled/table.d.ts +10 -10
- package/lib/{ux → cli-ux}/styled/table.js +130 -133
- package/lib/{ux → cli-ux}/styled/tree.js +11 -13
- package/lib/cli-ux/wait.js +5 -0
- package/lib/command.d.ts +82 -88
- package/lib/command.js +196 -175
- package/lib/config/config.d.ts +89 -90
- package/lib/config/config.js +466 -566
- package/lib/config/index.d.ts +0 -1
- package/lib/config/index.js +1 -3
- package/lib/config/plugin-loader.d.ts +12 -12
- package/lib/config/plugin-loader.js +72 -56
- package/lib/config/plugin.d.ts +25 -24
- package/lib/config/plugin.js +188 -154
- package/lib/config/ts-node.d.ts +2 -1
- package/lib/config/ts-node.js +71 -58
- package/lib/config/util.d.ts +1 -11
- package/lib/config/util.js +6 -59
- package/lib/errors/config.d.ts +1 -1
- package/lib/errors/config.js +6 -6
- package/lib/errors/errors/cli.d.ts +7 -7
- package/lib/errors/errors/cli.js +20 -16
- package/lib/errors/errors/exit.d.ts +1 -4
- package/lib/errors/errors/exit.js +1 -1
- package/lib/errors/errors/module-load.d.ts +1 -4
- package/lib/errors/errors/module-load.js +1 -1
- package/lib/errors/errors/pretty-print.d.ts +1 -1
- package/lib/errors/errors/pretty-print.js +12 -10
- package/lib/errors/handle.d.ts +12 -2
- package/lib/errors/handle.js +26 -14
- package/lib/errors/index.d.ts +10 -10
- package/lib/errors/index.js +25 -24
- package/lib/errors/logger.d.ts +2 -2
- package/lib/errors/logger.js +14 -13
- package/lib/execute.d.ts +6 -6
- package/lib/execute.js +10 -9
- package/lib/flags.d.ts +103 -32
- package/lib/flags.js +79 -45
- package/lib/help/command.d.ts +16 -14
- package/lib/help/command.js +178 -163
- package/lib/help/docopts.d.ts +5 -5
- package/lib/help/docopts.js +50 -54
- package/lib/help/formatter.d.ts +37 -37
- package/lib/help/formatter.js +66 -55
- package/lib/help/index.d.ts +25 -21
- package/lib/help/index.js +169 -147
- package/lib/help/root.d.ts +1 -1
- package/lib/help/root.js +15 -17
- package/lib/help/util.d.ts +2 -8
- package/lib/help/util.js +8 -28
- package/lib/index.d.ts +19 -20
- package/lib/index.js +37 -43
- package/lib/interfaces/config.d.ts +67 -66
- package/lib/interfaces/errors.d.ts +5 -5
- package/lib/interfaces/help.d.ts +17 -17
- package/lib/interfaces/hooks.d.ts +49 -49
- package/lib/interfaces/index.d.ts +7 -7
- package/lib/interfaces/manifest.d.ts +1 -1
- package/lib/interfaces/parser.d.ts +175 -51
- package/lib/interfaces/pjson.d.ts +41 -41
- package/lib/interfaces/plugin.d.ts +47 -41
- package/lib/interfaces/s3-manifest.d.ts +7 -7
- package/lib/interfaces/topic.d.ts +1 -1
- package/lib/interfaces/ts-config.d.ts +7 -7
- package/lib/main.d.ts +2 -2
- package/lib/main.js +16 -16
- package/lib/module-loader.d.ts +67 -77
- package/lib/module-loader.js +183 -150
- package/lib/parser/errors.d.ts +7 -7
- package/lib/parser/errors.js +29 -22
- package/lib/parser/help.js +5 -5
- package/lib/parser/index.js +2 -2
- package/lib/parser/parse.d.ts +9 -6
- package/lib/parser/parse.js +253 -221
- package/lib/parser/validate.js +53 -33
- package/lib/performance.d.ts +43 -32
- package/lib/performance.js +133 -91
- package/lib/screen.js +2 -2
- package/lib/settings.d.ts +11 -12
- package/lib/settings.js +2 -2
- package/lib/util/aggregate-flags.d.ts +2 -0
- package/lib/util/aggregate-flags.js +13 -0
- package/lib/util/cache-command.d.ts +3 -0
- package/lib/util/cache-command.js +109 -0
- package/lib/util/cache-default-value.d.ts +2 -0
- package/lib/util/cache-default-value.js +28 -0
- package/lib/util/ensure-arg-object.d.ts +12 -0
- package/lib/util/ensure-arg-object.js +14 -0
- package/lib/util/fs.d.ts +7 -0
- package/lib/util/fs.js +54 -0
- package/lib/util/os.d.ts +19 -0
- package/lib/util/os.js +28 -0
- package/lib/{util.d.ts → util/util.d.ts} +7 -16
- package/lib/util/util.js +98 -0
- package/package.json +35 -37
- package/lib/util.js +0 -126
- package/lib/ux/flush.d.ts +0 -1
- package/lib/ux/flush.js +0 -27
- package/lib/ux/index.d.ts +0 -58
- package/lib/ux/styled/index.d.ts +0 -6
- package/lib/ux/styled/index.js +0 -13
- package/lib/ux/styled/json.d.ts +0 -1
- package/lib/ux/styled/json.js +0 -15
- package/lib/ux/wait.js +0 -7
- package/lib/{ux → cli-ux}/action/simple.d.ts +4 -4
- package/lib/{ux → cli-ux}/action/spinners.d.ts +117 -117
- package/lib/{ux → cli-ux}/exit.d.ts +2 -2
- package/lib/{ux → cli-ux}/list.d.ts +0 -0
- package/lib/{ux → cli-ux}/styled/object.d.ts +0 -0
- package/lib/{ux → cli-ux}/styled/progress.d.ts +0 -0
- package/lib/{ux → cli-ux}/styled/progress.js +0 -0
- package/lib/{ux → cli-ux}/styled/tree.d.ts +1 -1
- /package/lib/{ux → cli-ux}/wait.d.ts +0 -0
package/lib/parser/validate.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validate = void 0;
|
|
4
|
+
const util_1 = require("../util/util");
|
|
4
5
|
const errors_1 = require("./errors");
|
|
5
|
-
const util_1 = require("../config/util");
|
|
6
6
|
async function validate(parse) {
|
|
7
7
|
let cachedResolvedFlags;
|
|
8
8
|
function validateArgs() {
|
|
9
9
|
if (parse.output.nonExistentFlags?.length > 0) {
|
|
10
|
-
throw new errors_1.NonExistentFlagsError({
|
|
10
|
+
throw new errors_1.NonExistentFlagsError({ flags: parse.output.nonExistentFlags, parse });
|
|
11
11
|
}
|
|
12
12
|
const maxArgs = Object.keys(parse.input.args).length;
|
|
13
13
|
if (parse.input.strict && parse.output.argv.length > maxArgs) {
|
|
14
14
|
const extras = parse.output.argv.slice(maxArgs);
|
|
15
|
-
throw new errors_1.UnexpectedArgsError({
|
|
15
|
+
throw new errors_1.UnexpectedArgsError({ args: extras, parse });
|
|
16
16
|
}
|
|
17
17
|
const missingRequiredArgs = [];
|
|
18
18
|
let hasOptional = false;
|
|
@@ -23,7 +23,7 @@ async function validate(parse) {
|
|
|
23
23
|
else if (hasOptional) {
|
|
24
24
|
// (required arg) check whether an optional has occurred before
|
|
25
25
|
// optionals should follow required, not before
|
|
26
|
-
throw new errors_1.InvalidArgsSpecError({
|
|
26
|
+
throw new errors_1.InvalidArgsSpecError({ args: parse.input.args, parse });
|
|
27
27
|
}
|
|
28
28
|
if (arg.required && !parse.output.args[name] && parse.output.args[name] !== 0) {
|
|
29
29
|
missingRequiredArgs.push(arg);
|
|
@@ -33,31 +33,31 @@ async function validate(parse) {
|
|
|
33
33
|
const flagsWithMultiple = Object.entries(parse.input.flags)
|
|
34
34
|
.filter(([_, flagDef]) => flagDef.type === 'option' && Boolean(flagDef.multiple))
|
|
35
35
|
.map(([name]) => name);
|
|
36
|
-
throw new errors_1.RequiredArgsError({
|
|
36
|
+
throw new errors_1.RequiredArgsError({ args: missingRequiredArgs, flagsWithMultiple, parse });
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
async function validateFlags() {
|
|
40
40
|
const promises = Object.entries(parse.input.flags).flatMap(([name, flag]) => {
|
|
41
41
|
if (parse.output.flags[name] !== undefined) {
|
|
42
42
|
return [
|
|
43
|
-
...flag.relationships ? validateRelationships(name, flag) : [],
|
|
44
|
-
...flag.dependsOn ? [validateDependsOn(name, flag.dependsOn)] : [],
|
|
45
|
-
...flag.exclusive ? [validateExclusive(name, flag.exclusive)] : [],
|
|
46
|
-
...flag.exactlyOne ? [validateExactlyOne(name, flag.exactlyOne)] : [],
|
|
43
|
+
...(flag.relationships ? validateRelationships(name, flag) : []),
|
|
44
|
+
...(flag.dependsOn ? [validateDependsOn(name, flag.dependsOn)] : []),
|
|
45
|
+
...(flag.exclusive ? [validateExclusive(name, flag.exclusive)] : []),
|
|
46
|
+
...(flag.exactlyOne ? [validateExactlyOne(name, flag.exactlyOne)] : []),
|
|
47
47
|
];
|
|
48
48
|
}
|
|
49
49
|
if (flag.required) {
|
|
50
|
-
return [{
|
|
50
|
+
return [{ name, reason: `Missing required flag ${name}`, status: 'failed', validationFn: 'required' }];
|
|
51
51
|
}
|
|
52
52
|
if (flag.exactlyOne && flag.exactlyOne.length > 0) {
|
|
53
53
|
return [validateAcrossFlags(flag)];
|
|
54
54
|
}
|
|
55
55
|
return [];
|
|
56
56
|
});
|
|
57
|
-
const results =
|
|
58
|
-
const failed = results.filter(r => r.status === 'failed');
|
|
57
|
+
const results = await Promise.all(promises);
|
|
58
|
+
const failed = results.filter((r) => r.status === 'failed');
|
|
59
59
|
if (failed.length > 0)
|
|
60
|
-
throw new errors_1.FailedFlagValidationError({
|
|
60
|
+
throw new errors_1.FailedFlagValidationError({ failed, parse });
|
|
61
61
|
}
|
|
62
62
|
async function resolveFlags(flags) {
|
|
63
63
|
if (cachedResolvedFlags)
|
|
@@ -70,21 +70,21 @@ async function validate(parse) {
|
|
|
70
70
|
return result ? [flag.name, parse.output.flags[flag.name]] : null;
|
|
71
71
|
});
|
|
72
72
|
const resolved = await Promise.all(promises);
|
|
73
|
-
cachedResolvedFlags = Object.fromEntries(resolved.filter(r => r !== null));
|
|
73
|
+
cachedResolvedFlags = Object.fromEntries(resolved.filter((r) => r !== null));
|
|
74
74
|
return cachedResolvedFlags;
|
|
75
75
|
}
|
|
76
|
-
const getPresentFlags = (flags) => Object.keys(flags).filter(key => key !== undefined);
|
|
76
|
+
const getPresentFlags = (flags) => Object.keys(flags).filter((key) => key !== undefined);
|
|
77
77
|
function validateAcrossFlags(flag) {
|
|
78
78
|
const base = { name: flag.name, validationFn: 'validateAcrossFlags' };
|
|
79
79
|
const intersection = Object.entries(parse.input.flags)
|
|
80
|
-
.map(entry => entry[0]) // array of flag names
|
|
81
|
-
.filter(flagName => parse.output.flags[flagName] !== undefined) // with values
|
|
82
|
-
.filter(flagName => flag.exactlyOne && flag.exactlyOne.includes(flagName)); // and in the exactlyOne list
|
|
80
|
+
.map((entry) => entry[0]) // array of flag names
|
|
81
|
+
.filter((flagName) => parse.output.flags[flagName] !== undefined) // with values
|
|
82
|
+
.filter((flagName) => flag.exactlyOne && flag.exactlyOne.includes(flagName)); // and in the exactlyOne list
|
|
83
83
|
if (intersection.length === 0) {
|
|
84
84
|
// the command's exactlyOne may or may not include itself, so we'll use Set to add + de-dupe
|
|
85
|
-
const deduped = (0, util_1.uniq)(flag.exactlyOne?.map(flag => `--${flag}`) ?? []).join(', ');
|
|
85
|
+
const deduped = (0, util_1.uniq)(flag.exactlyOne?.map((flag) => `--${flag}`) ?? []).join(', ');
|
|
86
86
|
const reason = `Exactly one of the following must be provided: ${deduped}`;
|
|
87
|
-
return { ...base, status: 'failed'
|
|
87
|
+
return { ...base, reason, status: 'failed' };
|
|
88
88
|
}
|
|
89
89
|
return { ...base, status: 'success' };
|
|
90
90
|
}
|
|
@@ -100,7 +100,11 @@ async function validate(parse) {
|
|
|
100
100
|
continue;
|
|
101
101
|
if (parse.output.flags[flag] !== undefined) {
|
|
102
102
|
const flagValue = parse.output.metadata.flags?.[flag]?.defaultHelp ?? parse.output.flags[flag];
|
|
103
|
-
return {
|
|
103
|
+
return {
|
|
104
|
+
...base,
|
|
105
|
+
reason: `--${flag}=${flagValue} cannot also be provided when using --${name}`,
|
|
106
|
+
status: 'failed',
|
|
107
|
+
};
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
return { ...base, status: 'success' };
|
|
@@ -111,7 +115,7 @@ async function validate(parse) {
|
|
|
111
115
|
const keys = getPresentFlags(resolved);
|
|
112
116
|
for (const flag of keys) {
|
|
113
117
|
if (flag !== name && parse.output.flags[flag] !== undefined) {
|
|
114
|
-
return { ...base,
|
|
118
|
+
return { ...base, reason: `--${flag} cannot also be provided when using --${name}`, status: 'failed' };
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
return { ...base, status: 'success' };
|
|
@@ -119,10 +123,16 @@ async function validate(parse) {
|
|
|
119
123
|
async function validateDependsOn(name, flags) {
|
|
120
124
|
const base = { name, validationFn: 'validateDependsOn' };
|
|
121
125
|
const resolved = await resolveFlags(flags);
|
|
122
|
-
const foundAll = Object.values(resolved).every(val => val !== undefined);
|
|
126
|
+
const foundAll = Object.values(resolved).every((val) => val !== undefined);
|
|
123
127
|
if (!foundAll) {
|
|
124
|
-
const formattedFlags = Object.keys(resolved)
|
|
125
|
-
|
|
128
|
+
const formattedFlags = Object.keys(resolved)
|
|
129
|
+
.map((f) => `--${f}`)
|
|
130
|
+
.join(', ');
|
|
131
|
+
return {
|
|
132
|
+
...base,
|
|
133
|
+
reason: `All of the following must be provided when using --${name}: ${formattedFlags}`,
|
|
134
|
+
status: 'failed',
|
|
135
|
+
};
|
|
126
136
|
}
|
|
127
137
|
return { ...base, status: 'success' };
|
|
128
138
|
}
|
|
@@ -131,24 +141,34 @@ async function validate(parse) {
|
|
|
131
141
|
const resolved = await resolveFlags(flags);
|
|
132
142
|
const foundAtLeastOne = Object.values(resolved).some(Boolean);
|
|
133
143
|
if (!foundAtLeastOne) {
|
|
134
|
-
const formattedFlags = Object.keys(resolved)
|
|
135
|
-
|
|
144
|
+
const formattedFlags = Object.keys(resolved)
|
|
145
|
+
.map((f) => `--${f}`)
|
|
146
|
+
.join(', ');
|
|
147
|
+
return {
|
|
148
|
+
...base,
|
|
149
|
+
reason: `One of the following must be provided when using --${name}: ${formattedFlags}`,
|
|
150
|
+
status: 'failed',
|
|
151
|
+
};
|
|
136
152
|
}
|
|
137
153
|
return { ...base, status: 'success' };
|
|
138
154
|
}
|
|
139
155
|
function validateRelationships(name, flag) {
|
|
140
|
-
return (
|
|
156
|
+
return (flag.relationships ?? []).map((relationship) => {
|
|
141
157
|
switch (relationship.type) {
|
|
142
|
-
case 'all':
|
|
158
|
+
case 'all': {
|
|
143
159
|
return validateDependsOn(name, relationship.flags);
|
|
144
|
-
|
|
160
|
+
}
|
|
161
|
+
case 'some': {
|
|
145
162
|
return validateSome(name, relationship.flags);
|
|
146
|
-
|
|
163
|
+
}
|
|
164
|
+
case 'none': {
|
|
147
165
|
return validateExclusive(name, relationship.flags);
|
|
148
|
-
|
|
166
|
+
}
|
|
167
|
+
default: {
|
|
149
168
|
throw new Error(`Unknown relationship type: ${relationship.type}`);
|
|
169
|
+
}
|
|
150
170
|
}
|
|
151
|
-
})
|
|
171
|
+
});
|
|
152
172
|
}
|
|
153
173
|
validateArgs();
|
|
154
174
|
return validateFlags();
|
package/lib/performance.d.ts
CHANGED
|
@@ -1,53 +1,50 @@
|
|
|
1
|
-
type Details = Record<string,
|
|
1
|
+
type Details = Record<string, boolean | number | string | string[]>;
|
|
2
2
|
type PerfResult = {
|
|
3
|
-
name: string;
|
|
4
|
-
duration: number;
|
|
5
3
|
details: Details;
|
|
6
|
-
|
|
4
|
+
duration: number;
|
|
7
5
|
method: string | undefined;
|
|
6
|
+
module: string;
|
|
7
|
+
name: string;
|
|
8
8
|
scope: string | undefined;
|
|
9
9
|
};
|
|
10
10
|
type PerfHighlights = {
|
|
11
|
-
configLoadTime: number;
|
|
12
|
-
runTime: number;
|
|
13
|
-
initTime: number;
|
|
14
|
-
commandLoadTime: number;
|
|
15
|
-
pluginLoadTimes: Record<string, number>;
|
|
16
|
-
corePluginsLoadTime: number;
|
|
17
|
-
userPluginsLoadTime: number;
|
|
18
|
-
linkedPluginsLoadTime: number;
|
|
19
11
|
hookRunTimes: Record<string, Record<string, number>>;
|
|
12
|
+
'oclif.commandLoadMs': number;
|
|
13
|
+
'oclif.commandRunMs': number;
|
|
14
|
+
'oclif.configLoadMs': number;
|
|
15
|
+
'oclif.corePluginsLoadMs': number;
|
|
16
|
+
'oclif.initHookMs': number;
|
|
17
|
+
'oclif.initMs': number;
|
|
18
|
+
'oclif.linkedPluginsLoadMs': number;
|
|
19
|
+
'oclif.postrunHookMs': number;
|
|
20
|
+
'oclif.prerunHookMs': number;
|
|
21
|
+
'oclif.runMs': number;
|
|
22
|
+
'oclif.userPluginsLoadMs': number;
|
|
23
|
+
pluginLoadTimes: Record<string, {
|
|
24
|
+
details: Details;
|
|
25
|
+
duration: number;
|
|
26
|
+
}>;
|
|
20
27
|
};
|
|
28
|
+
export declare const OCLIF_MARKER_OWNER = "@oclif/core";
|
|
21
29
|
declare class Marker {
|
|
30
|
+
owner: string;
|
|
22
31
|
name: string;
|
|
23
32
|
details: Details;
|
|
24
|
-
|
|
33
|
+
private startMarker;
|
|
34
|
+
private stopMarker;
|
|
25
35
|
method: string;
|
|
36
|
+
module: string;
|
|
26
37
|
scope: string;
|
|
27
38
|
stopped: boolean;
|
|
28
|
-
|
|
29
|
-
private stopMarker;
|
|
30
|
-
constructor(name: string, details?: Details);
|
|
39
|
+
constructor(owner: string, name: string, details?: Details);
|
|
31
40
|
addDetails(details: Details): void;
|
|
32
|
-
stop(): void;
|
|
33
41
|
measure(): void;
|
|
42
|
+
stop(): void;
|
|
34
43
|
}
|
|
35
|
-
export
|
|
36
|
-
private static
|
|
44
|
+
export declare class Performance {
|
|
45
|
+
private static _oclifPerf;
|
|
37
46
|
private static _results;
|
|
38
|
-
private static
|
|
39
|
-
static get enabled(): boolean;
|
|
40
|
-
static get results(): PerfResult[];
|
|
41
|
-
static getResult(name: string): PerfResult | undefined;
|
|
42
|
-
static get highlights(): PerfHighlights;
|
|
43
|
-
/**
|
|
44
|
-
* Add a new performance marker
|
|
45
|
-
*
|
|
46
|
-
* @param name Name of the marker. Use `module.method#scope` format
|
|
47
|
-
* @param details Arbitrary details to attach to the marker
|
|
48
|
-
* @returns Marker instance
|
|
49
|
-
*/
|
|
50
|
-
static mark(name: string, details?: Details): Marker | undefined;
|
|
47
|
+
private static markers;
|
|
51
48
|
/**
|
|
52
49
|
* Collect performance results into static Performance.results
|
|
53
50
|
*
|
|
@@ -59,5 +56,19 @@ export default class Performance {
|
|
|
59
56
|
* @returns void
|
|
60
57
|
*/
|
|
61
58
|
static debug(): void;
|
|
59
|
+
static get enabled(): boolean;
|
|
60
|
+
static getResult(owner: string, name: string): PerfResult | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Add a new performance marker
|
|
63
|
+
*
|
|
64
|
+
* @param owner An npm package like `@oclif/core` or `@salesforce/source-tracking`
|
|
65
|
+
* @param name Name of the marker. Use `module.method#scope` format
|
|
66
|
+
* @param details Arbitrary details to attach to the marker
|
|
67
|
+
* @returns Marker instance
|
|
68
|
+
*/
|
|
69
|
+
static mark(owner: string, name: string, details?: Details): Marker | undefined;
|
|
70
|
+
static get oclifPerf(): PerfHighlights | Record<string, never>;
|
|
71
|
+
/** returns a map of owner, PerfResult[]. Excludes oclif PerfResult, which you can get from oclifPerf */
|
|
72
|
+
static get results(): Map<string, PerfResult[]>;
|
|
62
73
|
}
|
|
63
74
|
export {};
|
package/lib/performance.js
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
exports.Performance = exports.OCLIF_MARKER_OWNER = void 0;
|
|
4
|
+
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
4
5
|
const settings_1 = require("./settings");
|
|
6
|
+
exports.OCLIF_MARKER_OWNER = '@oclif/core';
|
|
5
7
|
class Marker {
|
|
6
|
-
|
|
8
|
+
owner;
|
|
9
|
+
name;
|
|
10
|
+
details;
|
|
11
|
+
startMarker;
|
|
12
|
+
stopMarker;
|
|
13
|
+
method;
|
|
14
|
+
module;
|
|
15
|
+
scope;
|
|
16
|
+
stopped = false;
|
|
17
|
+
constructor(owner, name, details = {}) {
|
|
18
|
+
this.owner = owner;
|
|
7
19
|
this.name = name;
|
|
8
20
|
this.details = details;
|
|
9
|
-
this.stopped = false;
|
|
10
21
|
this.startMarker = `${this.name}-start`;
|
|
11
22
|
this.stopMarker = `${this.name}-stop`;
|
|
12
23
|
const [caller, scope] = name.split('#');
|
|
@@ -14,54 +25,25 @@ class Marker {
|
|
|
14
25
|
this.module = module;
|
|
15
26
|
this.method = method;
|
|
16
27
|
this.scope = scope;
|
|
17
|
-
|
|
28
|
+
node_perf_hooks_1.performance.mark(this.startMarker);
|
|
18
29
|
}
|
|
19
30
|
addDetails(details) {
|
|
20
31
|
this.details = { ...this.details, ...details };
|
|
21
32
|
}
|
|
33
|
+
measure() {
|
|
34
|
+
node_perf_hooks_1.performance.measure(this.name, this.startMarker, this.stopMarker);
|
|
35
|
+
}
|
|
22
36
|
stop() {
|
|
23
37
|
this.stopped = true;
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
measure() {
|
|
27
|
-
perf_hooks_1.performance.measure(this.name, this.startMarker, this.stopMarker);
|
|
38
|
+
node_perf_hooks_1.performance.mark(this.stopMarker);
|
|
28
39
|
}
|
|
29
40
|
}
|
|
30
41
|
class Performance {
|
|
31
|
-
static
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return [];
|
|
37
|
-
if (Performance._results.length > 0)
|
|
38
|
-
return Performance._results;
|
|
39
|
-
throw new Error('Perf results not available. Did you forget to call await Performance.collect()?');
|
|
40
|
-
}
|
|
41
|
-
static getResult(name) {
|
|
42
|
-
return Performance.results.find(r => r.name === name);
|
|
43
|
-
}
|
|
44
|
-
static get highlights() {
|
|
45
|
-
if (!Performance.enabled)
|
|
46
|
-
return {};
|
|
47
|
-
if (Performance._highlights)
|
|
48
|
-
return Performance._highlights;
|
|
49
|
-
throw new Error('Perf results not available. Did you forget to call await Performance.collect()?');
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Add a new performance marker
|
|
53
|
-
*
|
|
54
|
-
* @param name Name of the marker. Use `module.method#scope` format
|
|
55
|
-
* @param details Arbitrary details to attach to the marker
|
|
56
|
-
* @returns Marker instance
|
|
57
|
-
*/
|
|
58
|
-
static mark(name, details = {}) {
|
|
59
|
-
if (!Performance.enabled)
|
|
60
|
-
return;
|
|
61
|
-
const marker = new Marker(name, details);
|
|
62
|
-
Performance.markers[marker.name] = marker;
|
|
63
|
-
return marker;
|
|
64
|
-
}
|
|
42
|
+
static _oclifPerf;
|
|
43
|
+
/* Key: marker.owner */
|
|
44
|
+
static _results = new Map();
|
|
45
|
+
/* Key: marker.name */
|
|
46
|
+
static markers = new Map();
|
|
65
47
|
/**
|
|
66
48
|
* Collect performance results into static Performance.results
|
|
67
49
|
*
|
|
@@ -70,36 +52,41 @@ class Performance {
|
|
|
70
52
|
static async collect() {
|
|
71
53
|
if (!Performance.enabled)
|
|
72
54
|
return;
|
|
73
|
-
if (Performance._results.
|
|
55
|
+
if (Performance._results.size > 0)
|
|
74
56
|
return;
|
|
75
|
-
const markers =
|
|
57
|
+
const markers = [...Performance.markers.values()];
|
|
76
58
|
if (markers.length === 0)
|
|
77
59
|
return;
|
|
78
|
-
for (const marker of markers.filter(m => !m.stopped)) {
|
|
60
|
+
for (const marker of markers.filter((m) => !m.stopped)) {
|
|
79
61
|
marker.stop();
|
|
80
62
|
}
|
|
81
|
-
return new Promise(resolve => {
|
|
82
|
-
const perfObserver = new
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
const perfObserver = new node_perf_hooks_1.PerformanceObserver((items) => {
|
|
83
65
|
for (const entry of items.getEntries()) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
66
|
+
const marker = Performance.markers.get(entry.name);
|
|
67
|
+
if (marker) {
|
|
68
|
+
const result = {
|
|
69
|
+
details: marker.details,
|
|
70
|
+
duration: entry.duration,
|
|
89
71
|
method: marker.method,
|
|
72
|
+
module: marker.module,
|
|
73
|
+
name: entry.name,
|
|
90
74
|
scope: marker.scope,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
75
|
+
};
|
|
76
|
+
const existing = Performance._results.get(marker.owner) ?? [];
|
|
77
|
+
Performance._results.set(marker.owner, [...existing, result]);
|
|
94
78
|
}
|
|
95
79
|
}
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
const
|
|
80
|
+
const oclifResults = Performance._results.get(exports.OCLIF_MARKER_OWNER) ?? [];
|
|
81
|
+
const command = oclifResults.find((r) => r.name.startsWith('config.runCommand'));
|
|
82
|
+
const commandLoadTime = command
|
|
83
|
+
? Performance.getResult(exports.OCLIF_MARKER_OWNER, `plugin.findCommand#${command.details.plugin}.${command.details.command}`)?.duration ?? 0
|
|
84
|
+
: 0;
|
|
85
|
+
const pluginLoadTimes = Object.fromEntries(oclifResults
|
|
99
86
|
.filter(({ name }) => name.startsWith('plugin.load#'))
|
|
100
87
|
.sort((a, b) => b.duration - a.duration)
|
|
101
|
-
.map(({
|
|
102
|
-
const hookRunTimes =
|
|
88
|
+
.map(({ details, duration, scope }) => [scope, { details, duration }]));
|
|
89
|
+
const hookRunTimes = oclifResults
|
|
103
90
|
.filter(({ name }) => name.startsWith('config.runHook#'))
|
|
104
91
|
.reduce((acc, perfResult) => {
|
|
105
92
|
const event = perfResult.details.event;
|
|
@@ -116,24 +103,28 @@ class Performance {
|
|
|
116
103
|
}
|
|
117
104
|
return acc;
|
|
118
105
|
}, {});
|
|
119
|
-
const pluginLoadTimeByType = Object.fromEntries(
|
|
106
|
+
const pluginLoadTimeByType = Object.fromEntries(oclifResults
|
|
120
107
|
.filter(({ name }) => name.startsWith('config.loadPlugins#'))
|
|
121
108
|
.sort((a, b) => b.duration - a.duration)
|
|
122
|
-
.map(({
|
|
123
|
-
Performance.
|
|
124
|
-
configLoadTime: Performance.getResult('config.load')?.duration ?? 0,
|
|
125
|
-
runTime: Performance.getResult('main.run')?.duration ?? 0,
|
|
126
|
-
initTime: Performance.getResult('main.run#init')?.duration ?? 0,
|
|
127
|
-
commandLoadTime,
|
|
128
|
-
pluginLoadTimes,
|
|
109
|
+
.map(({ duration, scope }) => [scope, duration]));
|
|
110
|
+
Performance._oclifPerf = {
|
|
129
111
|
hookRunTimes,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
112
|
+
'oclif.commandLoadMs': commandLoadTime,
|
|
113
|
+
'oclif.commandRunMs': oclifResults.find(({ name }) => name.startsWith('config.runCommand#'))?.duration ?? 0,
|
|
114
|
+
'oclif.configLoadMs': Performance.getResult(exports.OCLIF_MARKER_OWNER, 'config.load')?.duration ?? 0,
|
|
115
|
+
'oclif.corePluginsLoadMs': pluginLoadTimeByType.core ?? 0,
|
|
116
|
+
'oclif.initHookMs': hookRunTimes.init?.total ?? 0,
|
|
117
|
+
'oclif.initMs': Performance.getResult(exports.OCLIF_MARKER_OWNER, 'main.run#init')?.duration ?? 0,
|
|
118
|
+
'oclif.linkedPluginsLoadMs': pluginLoadTimeByType.link ?? 0,
|
|
119
|
+
'oclif.postrunHookMs': hookRunTimes.postrun?.total ?? 0,
|
|
120
|
+
'oclif.prerunHookMs': hookRunTimes.prerun?.total ?? 0,
|
|
121
|
+
'oclif.runMs': Performance.getResult(exports.OCLIF_MARKER_OWNER, 'main.run')?.duration ?? 0,
|
|
122
|
+
'oclif.userPluginsLoadMs': pluginLoadTimeByType.user ?? 0,
|
|
123
|
+
pluginLoadTimes,
|
|
133
124
|
};
|
|
134
125
|
resolve();
|
|
135
126
|
});
|
|
136
|
-
perfObserver.observe({ entryTypes: ['measure']
|
|
127
|
+
perfObserver.observe({ buffered: true, entryTypes: ['measure'] });
|
|
137
128
|
for (const marker of markers) {
|
|
138
129
|
try {
|
|
139
130
|
marker.measure();
|
|
@@ -142,7 +133,7 @@ class Performance {
|
|
|
142
133
|
// ignore
|
|
143
134
|
}
|
|
144
135
|
}
|
|
145
|
-
|
|
136
|
+
node_perf_hooks_1.performance.clearMarks();
|
|
146
137
|
});
|
|
147
138
|
}
|
|
148
139
|
/**
|
|
@@ -152,27 +143,78 @@ class Performance {
|
|
|
152
143
|
static debug() {
|
|
153
144
|
if (!Performance.enabled)
|
|
154
145
|
return;
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
146
|
+
const oclifDebug = require('debug')('oclif-perf');
|
|
147
|
+
oclifDebug('Total Time: %sms', Performance.oclifPerf['oclif.runMs'].toFixed(4));
|
|
148
|
+
oclifDebug('Init Time: %sms', Performance.oclifPerf['oclif.initMs'].toFixed(4));
|
|
149
|
+
oclifDebug('Config Load Time: %sms', Performance.oclifPerf['oclif.configLoadMs'].toFixed(4));
|
|
150
|
+
oclifDebug(' • Plugins Load Time: %sms', Performance.getResult(exports.OCLIF_MARKER_OWNER, 'config.loadAllPlugins')?.duration.toFixed(4) ?? 0);
|
|
151
|
+
oclifDebug(' • Commands Load Time: %sms', Performance.getResult(exports.OCLIF_MARKER_OWNER, 'config.loadAllCommands')?.duration.toFixed(4) ?? 0);
|
|
152
|
+
oclifDebug('Core Plugin Load Time: %sms', Performance.oclifPerf['oclif.corePluginsLoadMs'].toFixed(4));
|
|
153
|
+
oclifDebug('User Plugin Load Time: %sms', Performance.oclifPerf['oclif.userPluginsLoadMs'].toFixed(4));
|
|
154
|
+
oclifDebug('Linked Plugin Load Time: %sms', Performance.oclifPerf['oclif.linkedPluginsLoadMs'].toFixed(4));
|
|
155
|
+
oclifDebug('Plugin Load Times:');
|
|
156
|
+
for (const [plugin, result] of Object.entries(Performance.oclifPerf.pluginLoadTimes)) {
|
|
157
|
+
if (result.details.hasManifest) {
|
|
158
|
+
oclifDebug(` ${plugin}: ${result.duration.toFixed(4)}ms`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
oclifDebug(` ${plugin}: ${result.duration.toFixed(4)}ms (no manifest!)`);
|
|
162
|
+
}
|
|
166
163
|
}
|
|
167
|
-
|
|
168
|
-
for (const [event, runTimes] of Object.entries(Performance.
|
|
169
|
-
|
|
164
|
+
oclifDebug('Hook Run Times:');
|
|
165
|
+
for (const [event, runTimes] of Object.entries(Performance.oclifPerf.hookRunTimes)) {
|
|
166
|
+
oclifDebug(` ${event}:`);
|
|
170
167
|
for (const [plugin, duration] of Object.entries(runTimes)) {
|
|
171
|
-
|
|
168
|
+
oclifDebug(` ${plugin}: ${duration.toFixed(4)}ms`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
oclifDebug('Command Load Time: %sms', Performance.oclifPerf['oclif.commandLoadMs'].toFixed(4));
|
|
172
|
+
oclifDebug('Command Run Time: %sms', Performance.oclifPerf['oclif.commandRunMs'].toFixed(4));
|
|
173
|
+
const nonCoreDebug = require('debug')('non-oclif-perf');
|
|
174
|
+
const nonCorePerf = Performance.results;
|
|
175
|
+
if (nonCorePerf.size > 0) {
|
|
176
|
+
nonCoreDebug('Non-Core Performance Measurements:');
|
|
177
|
+
for (const [owner, results] of nonCorePerf) {
|
|
178
|
+
nonCoreDebug(` ${owner}:`);
|
|
179
|
+
for (const result of results) {
|
|
180
|
+
nonCoreDebug(` ${result.name}: ${result.duration.toFixed(4)}ms`);
|
|
181
|
+
}
|
|
172
182
|
}
|
|
173
183
|
}
|
|
174
184
|
}
|
|
185
|
+
static get enabled() {
|
|
186
|
+
return settings_1.settings.performanceEnabled ?? false;
|
|
187
|
+
}
|
|
188
|
+
static getResult(owner, name) {
|
|
189
|
+
return Performance._results.get(owner)?.find((r) => r.name === name);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Add a new performance marker
|
|
193
|
+
*
|
|
194
|
+
* @param owner An npm package like `@oclif/core` or `@salesforce/source-tracking`
|
|
195
|
+
* @param name Name of the marker. Use `module.method#scope` format
|
|
196
|
+
* @param details Arbitrary details to attach to the marker
|
|
197
|
+
* @returns Marker instance
|
|
198
|
+
*/
|
|
199
|
+
static mark(owner, name, details = {}) {
|
|
200
|
+
if (!Performance.enabled)
|
|
201
|
+
return;
|
|
202
|
+
const marker = new Marker(owner, name, details);
|
|
203
|
+
Performance.markers.set(marker.name, marker);
|
|
204
|
+
return marker;
|
|
205
|
+
}
|
|
206
|
+
static get oclifPerf() {
|
|
207
|
+
if (!Performance.enabled)
|
|
208
|
+
return {};
|
|
209
|
+
if (Performance._oclifPerf)
|
|
210
|
+
return Performance._oclifPerf;
|
|
211
|
+
throw new Error('Perf results not available. Did you forget to call await Performance.collect()?');
|
|
212
|
+
}
|
|
213
|
+
/** returns a map of owner, PerfResult[]. Excludes oclif PerfResult, which you can get from oclifPerf */
|
|
214
|
+
static get results() {
|
|
215
|
+
if (!Performance.enabled)
|
|
216
|
+
return new Map();
|
|
217
|
+
return new Map([...Performance._results.entries()].filter(([owner]) => owner !== exports.OCLIF_MARKER_OWNER));
|
|
218
|
+
}
|
|
175
219
|
}
|
|
176
|
-
exports.
|
|
177
|
-
Performance.markers = {};
|
|
178
|
-
Performance._results = [];
|
|
220
|
+
exports.Performance = Performance;
|
package/lib/screen.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.errtermwidth = exports.stdtermwidth = void 0;
|
|
4
|
-
const stream_1 = require("./ux/stream");
|
|
4
|
+
const stream_1 = require("./cli-ux/stream");
|
|
5
5
|
const settings_1 = require("./settings");
|
|
6
6
|
function termwidth(stream) {
|
|
7
7
|
if (!stream.isTTY) {
|
|
@@ -16,6 +16,6 @@ function termwidth(stream) {
|
|
|
16
16
|
}
|
|
17
17
|
return width;
|
|
18
18
|
}
|
|
19
|
-
const columns = Number.parseInt(process.env.OCLIF_COLUMNS, 10) || settings_1.
|
|
19
|
+
const columns = Number.parseInt(process.env.OCLIF_COLUMNS, 10) || settings_1.settings.columns;
|
|
20
20
|
exports.stdtermwidth = columns || termwidth(stream_1.stdout);
|
|
21
21
|
exports.errtermwidth = columns || termwidth(stream_1.stderr);
|
package/lib/settings.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export type Settings = {
|
|
2
|
+
/**
|
|
3
|
+
* Set the terminal width to a specified number of columns (characters)
|
|
4
|
+
*
|
|
5
|
+
* Environment Variable:
|
|
6
|
+
* OCLIF_COLUMNS=80
|
|
7
|
+
*/
|
|
8
|
+
columns?: number;
|
|
2
9
|
/**
|
|
3
10
|
* Show additional debug output without DEBUG. Mainly shows stackstraces.
|
|
4
11
|
*
|
|
@@ -13,12 +20,10 @@ export type Settings = {
|
|
|
13
20
|
*/
|
|
14
21
|
errlog?: string;
|
|
15
22
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* Environment Variable:
|
|
19
|
-
* OCLIF_COLUMNS=80
|
|
23
|
+
* Enable performance tracking. Resulting data is available in the `perf` property of the `Config` class.
|
|
24
|
+
* This will be overridden by the `enablePerf` property passed into Config constructor.
|
|
20
25
|
*/
|
|
21
|
-
|
|
26
|
+
performanceEnabled?: boolean;
|
|
22
27
|
/**
|
|
23
28
|
* Try to use ts-node to load typescript source files instead of
|
|
24
29
|
* javascript files.
|
|
@@ -30,11 +35,5 @@ export type Settings = {
|
|
|
30
35
|
* NODE_ENV=development
|
|
31
36
|
*/
|
|
32
37
|
tsnodeEnabled?: boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Enable performance tracking. Resulting data is available in the `perf` property of the `Config` class.
|
|
35
|
-
* This will be overridden by the `enablePerf` property passed into Config constructor.
|
|
36
|
-
*/
|
|
37
|
-
performanceEnabled?: boolean;
|
|
38
38
|
};
|
|
39
|
-
declare const settings: Settings;
|
|
40
|
-
export default settings;
|
|
39
|
+
export declare const settings: Settings;
|
package/lib/settings.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.settings = void 0;
|
|
3
4
|
// Set global.oclif to the new object if it wasn't set before
|
|
4
5
|
if (!global.oclif)
|
|
5
6
|
global.oclif = {};
|
|
6
|
-
|
|
7
|
-
exports.default = settings;
|
|
7
|
+
exports.settings = global.oclif;
|