@oclif/core 4.0.0-beta.2 → 4.0.0-beta.4

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/lib/command.js CHANGED
@@ -34,6 +34,7 @@ const cache_1 = __importDefault(require("./cache"));
34
34
  const config_1 = require("./config");
35
35
  const Errors = __importStar(require("./errors"));
36
36
  const util_1 = require("./help/util");
37
+ const logger_1 = require("./logger");
37
38
  const Parser = __importStar(require("./parser"));
38
39
  const aggregate_flags_1 = require("./util/aggregate-flags");
39
40
  const ids_1 = require("./util/ids");
@@ -123,7 +124,7 @@ class Command {
123
124
  this.config = config;
124
125
  this.id = this.ctor.id;
125
126
  try {
126
- this.debug = require('debug')(this.id ? `${this.config.bin}:${this.id}` : this.config.bin);
127
+ this.debug = (0, logger_1.makeDebug)(this.id ? `${this.config.bin}:${this.id}` : this.config.bin);
127
128
  }
128
129
  catch {
129
130
  this.debug = () => {
@@ -179,22 +180,9 @@ class Command {
179
180
  exit(code = 0) {
180
181
  Errors.exit(code);
181
182
  }
182
- async finally(_) {
183
- try {
184
- const { config } = Errors;
185
- if (config.errorLogger)
186
- await config.errorLogger.flush();
187
- }
188
- catch (error) {
189
- console.error(error);
190
- }
191
- }
183
+ async finally(_) { }
192
184
  async init() {
193
185
  this.debug('init version: %s argv: %o', this.ctor._base, this.argv);
194
- if (this.config.debug)
195
- Errors.config.debug = true;
196
- if (this.config.errlog)
197
- Errors.config.errlog = this.config.errlog;
198
186
  const g = global;
199
187
  g['http-call'] = g['http-call'] || {};
200
188
  g['http-call'].userAgent = this.config.userAgent;
@@ -13,9 +13,7 @@ export declare class Config implements IConfig {
13
13
  channel: string;
14
14
  configDir: string;
15
15
  dataDir: string;
16
- debug: number;
17
16
  dirname: string;
18
- errlog: string;
19
17
  flexibleTaxonomy: boolean;
20
18
  home: string;
21
19
  isSingleCommandCLI: boolean;
@@ -114,14 +112,9 @@ export declare class Config implements IConfig {
114
112
  */
115
113
  scopedEnvVarKeys(k: string): string[];
116
114
  scopedEnvVarTrue(k: string): boolean;
117
- protected warn(err: {
118
- detail: string;
119
- name: string;
120
- } | Error | string, scope?: string): void;
121
115
  protected windowsHome(): string | undefined;
122
116
  protected windowsHomedriveHome(): string | undefined;
123
117
  protected windowsUserprofileHome(): string | undefined;
124
- protected _debug(): number;
125
118
  protected _shell(): string;
126
119
  private buildS3Config;
127
120
  /**
@@ -159,4 +152,6 @@ export declare class Config implements IConfig {
159
152
  private isJitPluginCommand;
160
153
  private loadCommands;
161
154
  private loadTopics;
155
+ private maybeAdjustDebugSetting;
156
+ private warn;
162
157
  }
@@ -35,6 +35,7 @@ const node_url_1 = require("node:url");
35
35
  const cache_1 = __importDefault(require("../cache"));
36
36
  const errors_1 = require("../errors");
37
37
  const util_1 = require("../help/util");
38
+ const logger_1 = require("../logger");
38
39
  const module_loader_1 = require("../module-loader");
39
40
  const performance_1 = require("../performance");
40
41
  const settings_1 = require("../settings");
@@ -46,11 +47,19 @@ const theme_1 = require("../ux/theme");
46
47
  const plugin_loader_1 = __importDefault(require("./plugin-loader"));
47
48
  const ts_path_1 = require("./ts-path");
48
49
  const util_3 = require("./util");
49
- // eslint-disable-next-line new-cap
50
- const debug = (0, util_3.Debug)();
50
+ const debug = (0, util_3.makeDebug)();
51
51
  const _pjson = cache_1.default.getInstance().get('@oclif/core');
52
52
  const BASE = `${_pjson.name}@${_pjson.version}`;
53
53
  const ROOT_ONLY_HOOKS = new Set(['preparse']);
54
+ function displayWarnings() {
55
+ if (process.listenerCount('warning') > 1)
56
+ return;
57
+ process.on('warning', (warning) => {
58
+ console.error(warning.stack);
59
+ if (warning.detail)
60
+ console.error(warning.detail);
61
+ });
62
+ }
54
63
  function channelFromVersion(version) {
55
64
  const m = version.match(/[^-]+(?:-([^.]+))?/);
56
65
  return (m && m[1]) || 'stable';
@@ -94,9 +103,7 @@ class Config {
94
103
  channel;
95
104
  configDir;
96
105
  dataDir;
97
- debug = 0;
98
106
  dirname;
99
- errlog;
100
107
  flexibleTaxonomy;
101
108
  home;
102
109
  isSingleCommandCLI = false;
@@ -129,6 +136,7 @@ class Config {
129
136
  this.options = options;
130
137
  }
131
138
  static async load(opts = module.filename || __dirname) {
139
+ (0, logger_1.setLogger)(opts);
132
140
  // Handle the case when a file URL string is passed in such as 'import.meta.url'; covert to file path.
133
141
  if (typeof opts === 'string' && opts.startsWith('file://')) {
134
142
  opts = (0, node_url_1.fileURLToPath)(opts);
@@ -263,6 +271,9 @@ class Config {
263
271
  async load() {
264
272
  settings_1.settings.performanceEnabled =
265
273
  (settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
274
+ if (settings_1.settings.debug)
275
+ displayWarnings();
276
+ (0, logger_1.setLogger)(this.options);
266
277
  const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.load');
267
278
  this.pluginLoader = new plugin_loader_1.default({ plugins: this.options.plugins, root: this.options.root });
268
279
  this.rootPlugin = await this.pluginLoader.loadRoot({ pjson: this.options.pjson });
@@ -295,12 +306,10 @@ class Config {
295
306
  this.dirname = this.dirname.replace('/', '\\');
296
307
  this.userAgent = `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
297
308
  this.shell = this._shell();
298
- this.debug = this._debug();
299
309
  this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0, os_1.getHomeDir)() || (0, node_os_1.tmpdir)();
300
310
  this.cacheDir = this.scopedEnvVar('CACHE_DIR') || this.macosCacheDir() || this.dir('cache');
301
311
  this.configDir = this.scopedEnvVar('CONFIG_DIR') || this.dir('config');
302
312
  this.dataDir = this.scopedEnvVar('DATA_DIR') || this.dir('data');
303
- this.errlog = (0, node_path_1.join)(this.cacheDir, 'error.log');
304
313
  this.binPath = this.scopedEnvVar('BINPATH');
305
314
  this.npmRegistry = this.scopedEnvVar('NPM_REGISTRY') || this.pjson.oclif.npmRegistry;
306
315
  this.theme = await this.loadTheme();
@@ -313,6 +322,7 @@ class Config {
313
322
  (typeof this.pjson.oclif.commands !== 'string' &&
314
323
  this.pjson.oclif.commands?.strategy === 'single' &&
315
324
  this.pjson.oclif.commands?.target));
325
+ this.maybeAdjustDebugSetting();
316
326
  await this.loadPluginsAndCommands();
317
327
  debug('config done');
318
328
  marker?.addDetails({
@@ -447,7 +457,7 @@ class Config {
447
457
  };
448
458
  const plugins = ROOT_ONLY_HOOKS.has(event) ? [this.rootPlugin] : [...this.plugins.values()];
449
459
  const promises = plugins.map(async (p) => {
450
- const debug = require('debug')([this.bin, p.name, 'hooks', event].join(':'));
460
+ const debug = (0, logger_1.makeDebug)([p.name, 'hooks', event].join(':'));
451
461
  const context = {
452
462
  config: this,
453
463
  debug,
@@ -557,40 +567,6 @@ class Config {
557
567
  const v = this.scopedEnvVar(k);
558
568
  return v === '1' || v === 'true';
559
569
  }
560
- warn(err, scope) {
561
- if (this.warned)
562
- return;
563
- if (typeof err === 'string') {
564
- process.emitWarning(err);
565
- return;
566
- }
567
- if (err instanceof Error) {
568
- const modifiedErr = err;
569
- modifiedErr.name = `${err.name} Plugin: ${this.name}`;
570
- modifiedErr.detail = (0, util_2.compact)([
571
- err.detail,
572
- `module: ${this._base}`,
573
- scope && `task: ${scope}`,
574
- `plugin: ${this.name}`,
575
- `root: ${this.root}`,
576
- 'See more details with DEBUG=*',
577
- ]).join('\n');
578
- process.emitWarning(err);
579
- return;
580
- }
581
- // err is an object
582
- process.emitWarning('Config.warn expected either a string or Error, but instead received an object');
583
- err.name = `${err.name} Plugin: ${this.name}`;
584
- err.detail = (0, util_2.compact)([
585
- err.detail,
586
- `module: ${this._base}`,
587
- scope && `task: ${scope}`,
588
- `plugin: ${this.name}`,
589
- `root: ${this.root}`,
590
- 'See more details with DEBUG=*',
591
- ]).join('\n');
592
- process.emitWarning(JSON.stringify(err));
593
- }
594
570
  windowsHome() {
595
571
  return this.windowsHomedriveHome() || this.windowsUserprofileHome();
596
572
  }
@@ -600,17 +576,6 @@ class Config {
600
576
  windowsUserprofileHome() {
601
577
  return process.env.USERPROFILE;
602
578
  }
603
- _debug() {
604
- if (this.scopedEnvVarTrue('DEBUG'))
605
- return 1;
606
- try {
607
- const { enabled } = require('debug')(this.bin);
608
- if (enabled)
609
- return 1;
610
- }
611
- catch { }
612
- return 0;
613
- }
614
579
  _shell() {
615
580
  let shellPath;
616
581
  const { COMSPEC } = process.env;
@@ -828,5 +793,45 @@ class Config {
828
793
  }
829
794
  marker?.stop();
830
795
  }
796
+ maybeAdjustDebugSetting() {
797
+ if (this.scopedEnvVarTrue('DEBUG')) {
798
+ settings_1.settings.debug = true;
799
+ displayWarnings();
800
+ }
801
+ }
802
+ warn(err, scope) {
803
+ if (this.warned)
804
+ return;
805
+ if (typeof err === 'string') {
806
+ process.emitWarning(err);
807
+ return;
808
+ }
809
+ if (err instanceof Error) {
810
+ const modifiedErr = err;
811
+ modifiedErr.name = `${err.name} Plugin: ${this.name}`;
812
+ modifiedErr.detail = (0, util_2.compact)([
813
+ err.detail,
814
+ `module: ${this._base}`,
815
+ scope && `task: ${scope}`,
816
+ `plugin: ${this.name}`,
817
+ `root: ${this.root}`,
818
+ 'See more details with DEBUG=*',
819
+ ]).join('\n');
820
+ process.emitWarning(err);
821
+ return;
822
+ }
823
+ // err is an object
824
+ process.emitWarning('Config.warn expected either a string or Error, but instead received an object');
825
+ err.name = `${err.name} Plugin: ${this.name}`;
826
+ err.detail = (0, util_2.compact)([
827
+ err.detail,
828
+ `module: ${this._base}`,
829
+ scope && `task: ${scope}`,
830
+ `plugin: ${this.name}`,
831
+ `root: ${this.root}`,
832
+ 'See more details with DEBUG=*',
833
+ ]).join('\n');
834
+ process.emitWarning(JSON.stringify(err));
835
+ }
831
836
  }
832
837
  exports.Config = Config;
@@ -30,8 +30,7 @@ const fs_1 = require("../util/fs");
30
30
  const util_1 = require("../util/util");
31
31
  const Plugin = __importStar(require("./plugin"));
32
32
  const util_2 = require("./util");
33
- // eslint-disable-next-line new-cap
34
- const debug = (0, util_2.Debug)();
33
+ const debug = (0, util_2.makeDebug)();
35
34
  function findMatchingDependencies(dependencies, patterns) {
36
35
  return Object.keys(dependencies).filter((p) => patterns.some((w) => (0, minimatch_1.minimatch)(p, w)));
37
36
  }
@@ -104,8 +104,7 @@ class Plugin {
104
104
  valid = false;
105
105
  version;
106
106
  _base = `${_pjson.name}@${_pjson.version}`;
107
- // eslint-disable-next-line new-cap
108
- _debug = (0, util_2.Debug)();
107
+ _debug = (0, util_2.makeDebug)();
109
108
  commandCache;
110
109
  commandDiscoveryOpts;
111
110
  flexibleTaxonomy;
@@ -190,8 +189,7 @@ class Plugin {
190
189
  this.alias = this.options.name ?? this.pjson.name;
191
190
  if (!this.name)
192
191
  throw new errors_1.CLIError(`no name in package.json (${root})`);
193
- // eslint-disable-next-line new-cap
194
- this._debug = (0, util_2.Debug)(this.name);
192
+ this._debug = (0, util_2.makeDebug)(this.name);
195
193
  this.version = this.pjson.version;
196
194
  if (this.pjson.oclif) {
197
195
  this.valid = true;
@@ -13,8 +13,7 @@ const fs_1 = require("../util/fs");
13
13
  const read_tsconfig_1 = require("../util/read-tsconfig");
14
14
  const util_1 = require("../util/util");
15
15
  const util_2 = require("./util");
16
- // eslint-disable-next-line new-cap
17
- const debug = (0, util_2.Debug)('ts-path');
16
+ const debug = (0, util_2.makeDebug)('ts-path');
18
17
  exports.TS_CONFIGS = {};
19
18
  const REGISTERED = new Set();
20
19
  function determineRuntime() {
@@ -1,4 +1,4 @@
1
- export declare function Debug(...scope: string[]): (..._: any) => void;
1
+ export declare function makeDebug(...scope: string[]): (..._: any) => void;
2
2
  export declare function getPermutations(arr: string[]): Array<string[]>;
3
3
  export declare function getCommandIdPermutations(commandId: string): string[];
4
4
  /**
@@ -1,27 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.collectUsableIds = exports.getCommandIdPermutations = exports.getPermutations = exports.Debug = void 0;
4
- const debug = require('debug');
5
- function displayWarnings() {
6
- if (process.listenerCount('warning') > 1)
7
- return;
8
- process.on('warning', (warning) => {
9
- console.error(warning.stack);
10
- if (warning.detail)
11
- console.error(warning.detail);
12
- });
3
+ exports.collectUsableIds = exports.getCommandIdPermutations = exports.getPermutations = exports.makeDebug = void 0;
4
+ const logger_1 = require("../logger");
5
+ function makeDebug(...scope) {
6
+ return (formatter, ...args) => (0, logger_1.getLogger)(['config', ...scope].join(':')).debug(formatter, ...args);
13
7
  }
14
- function Debug(...scope) {
15
- if (!debug)
16
- return (..._) => {
17
- // noop
18
- };
19
- const d = debug(['config', ...scope].join(':'));
20
- if (d.enabled)
21
- displayWarnings();
22
- return (...args) => d(...args);
23
- }
24
- exports.Debug = Debug;
8
+ exports.makeDebug = makeDebug;
25
9
  // Adapted from https://github.com/angus-c/just/blob/master/packages/array-permutations/index.js
26
10
  function getPermutations(arr) {
27
11
  if (arr.length === 0)
@@ -24,8 +24,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.error = void 0;
27
+ const logger_1 = require("../logger");
27
28
  const write_1 = require("../ux/write");
28
- const config_1 = require("./config");
29
29
  const cli_1 = require("./errors/cli");
30
30
  const pretty_print_1 = __importStar(require("./errors/pretty-print"));
31
31
  function error(input, options = {}) {
@@ -44,8 +44,8 @@ function error(input, options = {}) {
44
44
  const message = (0, pretty_print_1.default)(err);
45
45
  if (message)
46
46
  (0, write_1.stderr)(message);
47
- if (config_1.config.errorLogger)
48
- config_1.config.errorLogger.log(err?.stack ?? '');
47
+ if (err?.stack)
48
+ (0, logger_1.getLogger)().error(err.stack);
49
49
  }
50
50
  else
51
51
  throw err;
@@ -10,7 +10,7 @@ const indent_string_1 = __importDefault(require("indent-string"));
10
10
  const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
11
11
  const cache_1 = __importDefault(require("../../cache"));
12
12
  const screen_1 = require("../../screen");
13
- const config_1 = require("../config");
13
+ const settings_1 = require("../../settings");
14
14
  /**
15
15
  * properties specific to internal oclif error handling
16
16
  */
@@ -48,7 +48,7 @@ class CLIError extends Error {
48
48
  * @return {string} returns a string representing the dispay of the error
49
49
  */
50
50
  render() {
51
- if (config_1.config.debug) {
51
+ if (settings_1.settings.debug) {
52
52
  return this.stack;
53
53
  }
54
54
  let output = `${this.name}: ${this.message}`;
@@ -7,7 +7,7 @@ exports.applyPrettyPrintOptions = void 0;
7
7
  const indent_string_1 = __importDefault(require("indent-string"));
8
8
  const wrap_ansi_1 = __importDefault(require("wrap-ansi"));
9
9
  const screen_1 = require("../../screen");
10
- const config_1 = require("../config");
10
+ const settings_1 = require("../../settings");
11
11
  function applyPrettyPrintOptions(error, options) {
12
12
  const prettyErrorKeys = ['message', 'code', 'ref', 'suggestions'];
13
13
  for (const key of prettyErrorKeys) {
@@ -30,7 +30,7 @@ const formatSuggestions = (suggestions) => {
30
30
  return `${label}\n${(0, indent_string_1.default)(multiple, 2)}`;
31
31
  };
32
32
  function prettyPrint(error) {
33
- if (config_1.config.debug) {
33
+ if (settings_1.settings.debug) {
34
34
  return error.stack;
35
35
  }
36
36
  const { bang, code, message, name: errorSuffix, ref, suggestions } = error;
@@ -7,7 +7,7 @@ exports.handle = exports.Exit = void 0;
7
7
  const clean_stack_1 = __importDefault(require("clean-stack"));
8
8
  const cache_1 = __importDefault(require("../cache"));
9
9
  const index_1 = require("../help/index");
10
- const config_1 = require("./config");
10
+ const logger_1 = require("../logger");
11
11
  const cli_1 = require("./errors/cli");
12
12
  const exit_1 = require("./errors/exit");
13
13
  const pretty_print_1 = __importDefault(require("./errors/pretty-print"));
@@ -46,17 +46,10 @@ async function handle(err) {
46
46
  }
47
47
  }
48
48
  const exitCode = err.oclif?.exit ?? 1;
49
- if (config_1.config.errorLogger && err.code !== 'EEXIT') {
50
- if (stack) {
51
- config_1.config.errorLogger.log(stack);
52
- }
53
- await config_1.config.errorLogger
54
- .flush()
55
- .then(() => exports.Exit.exit(exitCode))
56
- .catch(console.error);
49
+ if (err.code !== 'EEXIT' && stack) {
50
+ (0, logger_1.getLogger)().error(stack);
57
51
  }
58
- else
59
- exports.Exit.exit(exitCode);
52
+ exports.Exit.exit(exitCode);
60
53
  }
61
54
  catch (error) {
62
55
  console.error(err.stack);
@@ -1,10 +1,8 @@
1
1
  export { PrettyPrintableError } from '../interfaces';
2
- export { config } from './config';
3
2
  export { error } from './error';
4
3
  export { CLIError } from './errors/cli';
5
4
  export { ExitError } from './errors/exit';
6
5
  export { ModuleLoadError } from './errors/module-load';
7
6
  export { exit } from './exit';
8
7
  export { handle } from './handle';
9
- export { Logger } from './logger';
10
8
  export { warn } from './warn';
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.warn = exports.Logger = exports.handle = exports.exit = exports.ModuleLoadError = exports.ExitError = exports.CLIError = exports.error = exports.config = void 0;
4
- var config_1 = require("./config");
5
- Object.defineProperty(exports, "config", { enumerable: true, get: function () { return config_1.config; } });
3
+ exports.warn = exports.handle = exports.exit = exports.ModuleLoadError = exports.ExitError = exports.CLIError = exports.error = void 0;
6
4
  var error_1 = require("./error");
7
5
  Object.defineProperty(exports, "error", { enumerable: true, get: function () { return error_1.error; } });
8
6
  var cli_1 = require("./errors/cli");
@@ -15,7 +13,5 @@ var exit_2 = require("./exit");
15
13
  Object.defineProperty(exports, "exit", { enumerable: true, get: function () { return exit_2.exit; } });
16
14
  var handle_1 = require("./handle");
17
15
  Object.defineProperty(exports, "handle", { enumerable: true, get: function () { return handle_1.handle; } });
18
- var logger_1 = require("./logger");
19
- Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_1.Logger; } });
20
16
  var warn_1 = require("./warn");
21
17
  Object.defineProperty(exports, "warn", { enumerable: true, get: function () { return warn_1.warn; } });
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.warn = void 0;
7
+ const logger_1 = require("../logger");
7
8
  const write_1 = require("../ux/write");
8
- const config_1 = require("./config");
9
9
  const cli_1 = require("./errors/cli");
10
10
  const pretty_print_1 = __importDefault(require("./errors/pretty-print"));
11
11
  const WARNINGS = new Set();
@@ -33,8 +33,8 @@ function warn(input, options) {
33
33
  const message = (0, pretty_print_1.default)(err);
34
34
  if (message)
35
35
  (0, write_1.stderr)(message);
36
- if (config_1.config.errorLogger)
37
- config_1.config.errorLogger.log(err?.stack ?? '');
36
+ if (err?.stack)
37
+ (0, logger_1.getLogger)().error(err.stack);
38
38
  }
39
39
  exports.warn = warn;
40
40
  exports.default = warn;
package/lib/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export { CommandHelp, Help, HelpBase, loadHelpClass } from './help';
10
10
  export { HelpSection, HelpSectionKeyValueTable, HelpSectionRenderer } from './help/formatter';
11
11
  export * as Interfaces from './interfaces';
12
12
  export { Hook } from './interfaces/hooks';
13
+ export { getLogger } from './logger';
13
14
  export { run } from './main';
14
15
  export * as ModuleLoader from './module-loader';
15
16
  export * as Parser from './parser';
package/lib/index.js CHANGED
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.ux = exports.toStandardizedId = exports.toConfiguredId = exports.settings = exports.Performance = exports.Parser = exports.ModuleLoader = exports.run = exports.Interfaces = exports.loadHelpClass = exports.HelpBase = exports.Help = exports.CommandHelp = exports.flush = exports.Flags = exports.execute = exports.handle = exports.Errors = exports.Plugin = exports.Config = exports.Command = exports.Args = void 0;
26
+ exports.ux = exports.toStandardizedId = exports.toConfiguredId = exports.settings = exports.Performance = exports.Parser = exports.ModuleLoader = exports.run = exports.getLogger = exports.Interfaces = exports.loadHelpClass = exports.HelpBase = exports.Help = exports.CommandHelp = exports.flush = exports.Flags = exports.execute = exports.handle = exports.Errors = exports.Plugin = exports.Config = exports.Command = exports.Args = void 0;
27
27
  function checkCWD() {
28
28
  try {
29
29
  process.cwd();
@@ -55,6 +55,8 @@ Object.defineProperty(exports, "Help", { enumerable: true, get: function () { re
55
55
  Object.defineProperty(exports, "HelpBase", { enumerable: true, get: function () { return help_1.HelpBase; } });
56
56
  Object.defineProperty(exports, "loadHelpClass", { enumerable: true, get: function () { return help_1.loadHelpClass; } });
57
57
  exports.Interfaces = __importStar(require("./interfaces"));
58
+ var logger_1 = require("./logger");
59
+ Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return logger_1.getLogger; } });
58
60
  var main_1 = require("./main");
59
61
  Object.defineProperty(exports, "run", { enumerable: true, get: function () { return main_1.run; } });
60
62
  exports.ModuleLoader = __importStar(require("./module-loader"));
@@ -57,22 +57,10 @@ export interface Config {
57
57
  * example: ~/.local/share/mycli
58
58
  */
59
59
  readonly dataDir: string;
60
- /**
61
- * debugging level
62
- *
63
- * set by ${BIN}_DEBUG or DEBUG=$BIN
64
- */
65
- readonly debug: number;
66
60
  /**
67
61
  * base dirname to use in cacheDir/configDir/dataDir
68
62
  */
69
63
  readonly dirname: string;
70
- /**
71
- * points to a file that should be appended to for error logs
72
- *
73
- * example: ~/Library/Caches/mycli/error.log
74
- */
75
- readonly errlog: string;
76
64
  findCommand(id: string, opts: {
77
65
  must: true;
78
66
  }): Command.Loadable;
@@ -5,6 +5,7 @@ export type { CommandError, OclifError, PrettyPrintableError } from './errors';
5
5
  export type { InferredFlags } from './flags';
6
6
  export type { HelpOptions } from './help';
7
7
  export type { Hook, Hooks } from './hooks';
8
+ export type { Logger } from './logger';
8
9
  export type { Manifest } from './manifest';
9
10
  export type { Arg, BooleanFlag, CustomOptions, Deprecation, Flag, FlagDefinition, OptionFlag } from './parser';
10
11
  export type { PJSON } from './pjson';
@@ -0,0 +1,9 @@
1
+ export type Logger = {
2
+ debug: (formatter: unknown, ...args: unknown[]) => void;
3
+ error: (formatter: unknown, ...args: unknown[]) => void;
4
+ info: (formatter: unknown, ...args: unknown[]) => void;
5
+ trace: (formatter: unknown, ...args: unknown[]) => void;
6
+ warn: (formatter: unknown, ...args: unknown[]) => void;
7
+ child: (namespace: string) => Logger;
8
+ namespace: string;
9
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,4 +1,5 @@
1
1
  import { Command } from '../command';
2
+ import { Logger } from './logger';
2
3
  import { HookOptions, PJSON } from './pjson';
3
4
  import { Topic } from './topic';
4
5
  export interface PluginOptions {
@@ -21,6 +22,7 @@ export interface Options extends PluginOptions {
21
22
  devPlugins?: boolean;
22
23
  enablePerf?: boolean;
23
24
  jitPlugins?: boolean;
25
+ logger?: Logger;
24
26
  pjson?: PJSON.Plugin;
25
27
  pluginAdditions?: {
26
28
  core?: string[];
@@ -0,0 +1,14 @@
1
+ import { LoadOptions } from './interfaces/config';
2
+ import { Logger } from './interfaces/logger';
3
+ /**
4
+ * Returns a logger instance for the given namespace.
5
+ * If a namespace is provided, a child logger is returned.
6
+ * If no namespace is provided, the root logger is returned.
7
+ */
8
+ export declare function getLogger(namespace?: string): Logger;
9
+ /**
10
+ * Convenience function to create a debug function for a specific namespace
11
+ */
12
+ export declare function makeDebug(namespace: string): Logger['debug'];
13
+ export declare function setLogger(loadOptions: LoadOptions): void;
14
+ export declare function clearLoggers(): void;
package/lib/logger.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.clearLoggers = exports.setLogger = exports.makeDebug = exports.getLogger = void 0;
7
+ const debug_1 = __importDefault(require("debug"));
8
+ const OCLIF_NS = 'oclif';
9
+ function makeLogger(namespace = OCLIF_NS) {
10
+ const debug = (0, debug_1.default)(namespace);
11
+ return {
12
+ child: (ns, delimiter) => makeLogger(`${namespace}${delimiter ?? ':'}${ns}`),
13
+ debug,
14
+ error: (formatter, ...args) => makeLogger(`${namespace}:error`).debug(formatter, ...args),
15
+ info: debug,
16
+ namespace,
17
+ trace: debug,
18
+ warn: debug,
19
+ };
20
+ }
21
+ /**
22
+ * Cache of logger instances. This is used to prevent creating multiple logger instances for the same namespace.
23
+ *
24
+ * The root logger is stored under the 'root' key as well as it's namespace.
25
+ */
26
+ const cachedLoggers = new Map();
27
+ /**
28
+ * Returns a logger instance for the given namespace.
29
+ * If a namespace is provided, a child logger is returned.
30
+ * If no namespace is provided, the root logger is returned.
31
+ */
32
+ function getLogger(namespace) {
33
+ let rootLogger = cachedLoggers.get('root');
34
+ if (!rootLogger) {
35
+ set(makeLogger(OCLIF_NS));
36
+ }
37
+ rootLogger = cachedLoggers.get('root');
38
+ if (namespace) {
39
+ const cachedLogger = cachedLoggers.get(namespace);
40
+ if (cachedLogger)
41
+ return cachedLogger;
42
+ const logger = rootLogger.child(namespace);
43
+ cachedLoggers.set(namespace, logger);
44
+ return logger;
45
+ }
46
+ return rootLogger;
47
+ }
48
+ exports.getLogger = getLogger;
49
+ function ensureItMatchesInterface(newLogger) {
50
+ return (typeof newLogger.child === 'function' &&
51
+ typeof newLogger.debug === 'function' &&
52
+ typeof newLogger.error === 'function' &&
53
+ typeof newLogger.info === 'function' &&
54
+ typeof newLogger.trace === 'function' &&
55
+ typeof newLogger.warn === 'function' &&
56
+ typeof newLogger.namespace === 'string');
57
+ }
58
+ function set(newLogger) {
59
+ if (cachedLoggers.has(newLogger.namespace))
60
+ return;
61
+ if (cachedLoggers.has('root'))
62
+ return;
63
+ if (ensureItMatchesInterface(newLogger)) {
64
+ cachedLoggers.set(newLogger.namespace, newLogger);
65
+ cachedLoggers.set('root', newLogger);
66
+ }
67
+ else {
68
+ process.emitWarning('Logger does not match the Logger interface. Using default logger.');
69
+ }
70
+ }
71
+ /**
72
+ * Convenience function to create a debug function for a specific namespace
73
+ */
74
+ function makeDebug(namespace) {
75
+ return (formatter, ...args) => getLogger(namespace).debug(formatter, ...args);
76
+ }
77
+ exports.makeDebug = makeDebug;
78
+ function setLogger(loadOptions) {
79
+ if (loadOptions && typeof loadOptions !== 'string' && 'logger' in loadOptions && loadOptions.logger) {
80
+ set(loadOptions.logger);
81
+ }
82
+ else {
83
+ set(makeLogger(OCLIF_NS));
84
+ }
85
+ }
86
+ exports.setLogger = setLogger;
87
+ function clearLoggers() {
88
+ cachedLoggers.clear();
89
+ }
90
+ exports.clearLoggers = clearLoggers;
package/lib/main.js CHANGED
@@ -8,10 +8,10 @@ const node_url_1 = require("node:url");
8
8
  const cache_1 = __importDefault(require("./cache"));
9
9
  const config_1 = require("./config");
10
10
  const help_1 = require("./help");
11
+ const logger_1 = require("./logger");
11
12
  const performance_1 = require("./performance");
12
13
  const symbols_1 = require("./symbols");
13
14
  const ux_1 = __importDefault(require("./ux"));
14
- const debug = require('debug')('oclif:main');
15
15
  const helpAddition = (argv, config) => {
16
16
  if (argv.length === 0 && !config.isSingleCommandCLI)
17
17
  return true;
@@ -48,6 +48,8 @@ async function run(argv, options) {
48
48
  const help = new Help(config, config.pjson.oclif.helpOptions ?? config.pjson.helpOptions);
49
49
  await help.showHelp(argv);
50
50
  };
51
+ (0, logger_1.setLogger)(options);
52
+ const { debug } = (0, logger_1.getLogger)('main');
51
53
  debug(`process.execPath: ${process.execPath}`);
52
54
  debug(`process.execArgv: ${process.execArgv}`);
53
55
  debug('process.argv: %O', process.argv);
@@ -7,13 +7,14 @@ exports.Parser = exports.readStdin = void 0;
7
7
  /* eslint-disable no-await-in-loop */
8
8
  const node_readline_1 = require("node:readline");
9
9
  const cache_1 = __importDefault(require("../cache"));
10
+ const logger_1 = require("../logger");
10
11
  const util_1 = require("../util/util");
11
12
  const errors_1 = require("./errors");
12
13
  let debug;
13
14
  try {
14
15
  debug =
15
16
  process.env.CLI_FLAGS_DEBUG === '1'
16
- ? require('debug')('../parser')
17
+ ? (0, logger_1.makeDebug)('parser')
17
18
  : () => {
18
19
  // noop
19
20
  };
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Performance = exports.OCLIF_MARKER_OWNER = void 0;
4
4
  const node_perf_hooks_1 = require("node:perf_hooks");
5
+ const logger_1 = require("./logger");
5
6
  const settings_1 = require("./settings");
6
7
  exports.OCLIF_MARKER_OWNER = '@oclif/core';
7
8
  class Marker {
@@ -143,7 +144,7 @@ class Performance {
143
144
  static debug() {
144
145
  if (!Performance.enabled)
145
146
  return;
146
- const oclifDebug = require('debug')('oclif-perf');
147
+ const oclifDebug = (0, logger_1.makeDebug)('perf');
147
148
  const processUpTime = (process.uptime() * 1000).toFixed(4);
148
149
  oclifDebug('Process Uptime: %sms', processUpTime);
149
150
  oclifDebug('Oclif Time: %sms', Performance.oclifPerf['oclif.runMs'].toFixed(4));
@@ -176,7 +177,7 @@ class Performance {
176
177
  if (Performance.oclifPerf['oclif.configLoadMs'] > Performance.oclifPerf['oclif.runMs']) {
177
178
  oclifDebug('! Config load time is greater than total oclif time. This might mean that Config was instantiated before oclif was run.');
178
179
  }
179
- const nonCoreDebug = require('debug')('non-oclif-perf');
180
+ const nonCoreDebug = (0, logger_1.makeDebug)('non-oclif-perf');
180
181
  const nonCorePerf = Performance.results;
181
182
  if (nonCorePerf.size > 0) {
182
183
  nonCoreDebug('Non-Core Performance Measurements:');
package/lib/settings.d.ts CHANGED
@@ -13,12 +13,6 @@ export type Settings = {
13
13
  * oclif.settings.debug = true;
14
14
  */
15
15
  debug?: boolean;
16
- /**
17
- * The path to the error.log file.
18
- *
19
- * NOTE: This is read-only and setting it will have no effect.
20
- */
21
- errlog?: string;
22
16
  /**
23
17
  * Enable performance tracking. Resulting data is available in the `perf` property of the `Config` class.
24
18
  * This will be overridden by the `enablePerf` property passed into Config constructor.
@@ -1,3 +1,4 @@
1
+ export declare function debug(...scope: string[]): (..._: any) => void;
1
2
  /**
2
3
  * Returns the root directory of the plugin.
3
4
  *
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findRoot = void 0;
7
- const debug_1 = __importDefault(require("debug"));
3
+ exports.findRoot = exports.debug = void 0;
8
4
  const node_path_1 = require("node:path");
5
+ const logger_1 = require("../logger");
9
6
  const fs_1 = require("./fs");
10
- const debug = (0, debug_1.default)('find-root');
7
+ function debug(...scope) {
8
+ return (formatter, ...args) => (0, logger_1.getLogger)(['find-root', ...scope].join(':')).debug(formatter, ...args);
9
+ }
10
+ exports.debug = debug;
11
11
  // essentially just "cd .."
12
12
  function* up(from) {
13
13
  while ((0, node_path_1.dirname)(from) !== from) {
@@ -25,11 +25,11 @@ function* up(from) {
25
25
  async function findPluginRoot(root, name) {
26
26
  // If we know the plugin name then we just need to traverse the file
27
27
  // system until we find the directory that matches the plugin name.
28
- debug.extend(name ?? 'root-plugin')(`Finding root starting at ${root}`);
28
+ debug(name ?? 'root-plugin')(`Finding root starting at ${root}`);
29
29
  if (name) {
30
30
  for (const next of up(root)) {
31
31
  if (next.endsWith((0, node_path_1.basename)(name))) {
32
- debug.extend(name)('Found root based on plugin name!');
32
+ debug(name)('Found root based on plugin name!');
33
33
  return next;
34
34
  }
35
35
  }
@@ -44,9 +44,9 @@ async function findPluginRoot(root, name) {
44
44
  }
45
45
  try {
46
46
  const cur = (0, node_path_1.join)(next, 'package.json');
47
- debug.extend(name ?? 'root-plugin')(`Checking ${cur}`);
47
+ debug(name ?? 'root-plugin')(`Checking ${cur}`);
48
48
  if (await (0, fs_1.safeReadJson)(cur)) {
49
- debug.extend(name ?? 'root-plugin')('Found root by traversing up from starting point!');
49
+ debug(name ?? 'root-plugin')('Found root by traversing up from starting point!');
50
50
  return (0, node_path_1.dirname)(cur);
51
51
  }
52
52
  }
@@ -60,7 +60,7 @@ async function findPluginRoot(root, name) {
60
60
  * See https://github.com/oclif/config/pull/289#issuecomment-983904051
61
61
  */
62
62
  async function findRootLegacy(name, root) {
63
- debug.extend(name ?? 'root-plugin')('Finding root using legacy method');
63
+ debug(name ?? 'root-plugin')('Finding root using legacy method');
64
64
  for (const next of up(root)) {
65
65
  let cur;
66
66
  if (name) {
@@ -106,7 +106,7 @@ function findPnpRoot(name, root) {
106
106
  maybeRequirePnpApi(root);
107
107
  if (!pnp)
108
108
  return;
109
- debug.extend(name)('Finding root for using pnp method');
109
+ debug(name)('Finding root for using pnp method');
110
110
  const seen = new Set();
111
111
  const traverseDependencyTree = (locator, parentPkg) => {
112
112
  // Prevent infinite recursion when A depends on B which depends on A
@@ -158,29 +158,29 @@ function findPnpRoot(name, root) {
158
158
  */
159
159
  async function findRoot(name, root) {
160
160
  if (name) {
161
- debug.extend(name)(`Finding root using ${root}`);
161
+ debug(name)(`Finding root using ${root}`);
162
162
  let pkgPath;
163
163
  try {
164
164
  pkgPath = require.resolve(name, { paths: [root] });
165
- debug.extend(name)(`Found starting point with require.resolve`);
165
+ debug(name)(`Found starting point with require.resolve`);
166
166
  }
167
167
  catch {
168
- debug.extend(name)(`require.resolve could not find plugin starting point`);
168
+ debug(name)(`require.resolve could not find plugin starting point`);
169
169
  }
170
170
  if (pkgPath) {
171
171
  const found = await findPluginRoot((0, node_path_1.dirname)(pkgPath), name);
172
172
  if (found) {
173
- debug.extend(name)(`Found root at ${found}`);
173
+ debug(name)(`Found root at ${found}`);
174
174
  return found;
175
175
  }
176
176
  }
177
177
  const found = process.versions.pnp ? findPnpRoot(name, root) : await findRootLegacy(name, root);
178
- debug.extend(name)(found ? `Found root at ${found}` : 'No root found!');
178
+ debug(name)(found ? `Found root at ${found}` : 'No root found!');
179
179
  return found;
180
180
  }
181
- debug.extend('root-plugin')(`Finding root plugin using ${root}`);
181
+ debug('root-plugin')(`Finding root plugin using ${root}`);
182
182
  const found = await findPluginRoot(root);
183
- debug.extend('root-plugin')(found ? `Found root at ${found}` : 'No root found!');
183
+ debug('root-plugin')(found ? `Found root at ${found}` : 'No root found!');
184
184
  return found;
185
185
  }
186
186
  exports.findRoot = findRoot;
@@ -1,15 +1,12 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.readTSConfig = void 0;
7
- const debug_1 = __importDefault(require("debug"));
8
4
  const promises_1 = require("node:fs/promises");
9
5
  const node_path_1 = require("node:path");
10
6
  const warn_1 = require("../errors/warn");
7
+ const logger_1 = require("../logger");
11
8
  const util_1 = require("./util");
12
- const debug = (0, debug_1.default)('read-tsconfig');
9
+ const debug = (0, logger_1.makeDebug)('read-tsconfig');
13
10
  function resolve(root, name) {
14
11
  try {
15
12
  return require.resolve(name, { paths: [root] });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oclif/core",
3
3
  "description": "base library for oclif CLIs",
4
- "version": "4.0.0-beta.2",
4
+ "version": "4.0.0-beta.4",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -17,6 +17,7 @@
17
17
  "is-wsl": "^2.2.0",
18
18
  "minimatch": "^9.0.4",
19
19
  "string-width": "^4.2.3",
20
+ "supports-color": "^9.4.0",
20
21
  "widest-line": "^3.1.0",
21
22
  "wordwrap": "^1.0.0",
22
23
  "wrap-ansi": "^7.0.0"
@@ -1,6 +0,0 @@
1
- import { Logger } from './logger';
2
- export declare const config: {
3
- debug: boolean;
4
- errlog: string | undefined;
5
- errorLogger: Logger | undefined;
6
- };
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.config = void 0;
4
- const settings_1 = require("../settings");
5
- const logger_1 = require("./logger");
6
- function displayWarnings() {
7
- if (process.listenerCount('warning') > 1)
8
- return;
9
- process.on('warning', (warning) => {
10
- console.error(warning.stack);
11
- if (warning.detail)
12
- console.error(warning.detail);
13
- });
14
- }
15
- exports.config = {
16
- get debug() {
17
- return Boolean(settings_1.settings.debug);
18
- },
19
- set debug(enabled) {
20
- settings_1.settings.debug = enabled;
21
- if (enabled)
22
- displayWarnings();
23
- },
24
- get errlog() {
25
- return settings_1.settings.errlog;
26
- },
27
- set errlog(errlog) {
28
- if (errlog) {
29
- this.errorLogger = new logger_1.Logger(errlog);
30
- settings_1.settings.errlog = errlog;
31
- }
32
- else {
33
- delete this.errorLogger;
34
- delete settings_1.settings.errlog;
35
- }
36
- },
37
- errorLogger: undefined,
38
- };
@@ -1,8 +0,0 @@
1
- export declare class Logger {
2
- file: string;
3
- protected buffer: string[];
4
- protected flushing: Promise<void>;
5
- constructor(file: string);
6
- flush(waitForMs?: number): Promise<void>;
7
- log(msg: string): void;
8
- }
@@ -1,48 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Logger = void 0;
7
- const ansis_1 = __importDefault(require("ansis"));
8
- const promises_1 = require("node:fs/promises");
9
- const node_path_1 = require("node:path");
10
- const timestamp = () => new Date().toISOString();
11
- let timer;
12
- const wait = (ms) => new Promise((resolve) => {
13
- if (timer)
14
- timer.unref();
15
- timer = setTimeout(() => resolve(null), ms);
16
- });
17
- function chomp(s) {
18
- if (s.endsWith('\n'))
19
- return s.replace(/\n$/, '');
20
- return s;
21
- }
22
- class Logger {
23
- file;
24
- buffer = [];
25
- flushing = Promise.resolve();
26
- constructor(file) {
27
- this.file = file;
28
- }
29
- async flush(waitForMs = 0) {
30
- await wait(waitForMs);
31
- this.flushing = this.flushing.then(async () => {
32
- if (this.buffer.length === 0)
33
- return;
34
- const mylines = this.buffer;
35
- this.buffer = [];
36
- await (0, promises_1.mkdir)((0, node_path_1.dirname)(this.file), { recursive: true });
37
- await (0, promises_1.appendFile)(this.file, mylines.join('\n') + '\n');
38
- });
39
- await this.flushing;
40
- }
41
- log(msg) {
42
- msg = ansis_1.default.strip(chomp(msg));
43
- const lines = msg.split('\n').map((l) => `${timestamp()} ${l}`.trimEnd());
44
- this.buffer.push(...lines);
45
- this.flush(50).catch(console.error);
46
- }
47
- }
48
- exports.Logger = Logger;