@oclif/core 3.0.4 → 3.0.5-dev.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.
@@ -78,8 +78,92 @@ class Parser {
78
78
  this.booleanFlags = (0, util_1.pickBy)(input.flags, (f) => f.type === 'boolean');
79
79
  this.flagAliases = Object.fromEntries(Object.values(input.flags).flatMap((flag) => [...(flag.aliases ?? []), ...(flag.charAliases ?? [])].map((a) => [a, flag])));
80
80
  }
81
- get _argTokens() {
82
- return this.raw.filter((o) => o.type === 'arg');
81
+ async parse() {
82
+ this._debugInput();
83
+ const parseFlag = (arg) => {
84
+ const { isLong, name } = this.findFlag(arg);
85
+ if (!name) {
86
+ const i = arg.indexOf('=');
87
+ if (i !== -1) {
88
+ const sliced = arg.slice(i + 1);
89
+ this.argv.unshift(sliced);
90
+ const equalsParsed = parseFlag(arg.slice(0, i));
91
+ if (!equalsParsed) {
92
+ this.argv.shift();
93
+ }
94
+ return equalsParsed;
95
+ }
96
+ return false;
97
+ }
98
+ const flag = this.input.flags[name];
99
+ if (flag.type === 'option') {
100
+ if (!flag.multiple && this.raw.some((o) => o.type === 'flag' && o.flag === name)) {
101
+ throw new errors_1.CLIError(`Flag --${name} can only be specified once`);
102
+ }
103
+ this.currentFlag = flag;
104
+ const input = isLong || arg.length < 3 ? this.argv.shift() : arg.slice(arg[2] === '=' ? 3 : 2);
105
+ // if the value ends up being one of the command's flags, the user didn't provide an input
106
+ if (typeof input !== 'string' || this.findFlag(input).name) {
107
+ throw new errors_1.CLIError(`Flag --${name} expects a value`);
108
+ }
109
+ this.raw.push({ flag: flag.name, input, type: 'flag' });
110
+ }
111
+ else {
112
+ this.raw.push({ flag: flag.name, input: arg, type: 'flag' });
113
+ // push the rest of the short characters back on the stack
114
+ if (!isLong && arg.length > 2) {
115
+ this.argv.unshift(`-${arg.slice(2)}`);
116
+ }
117
+ }
118
+ return true;
119
+ };
120
+ let parsingFlags = true;
121
+ const nonExistentFlags = [];
122
+ let dashdash = false;
123
+ const originalArgv = [...this.argv];
124
+ while (this.argv.length > 0) {
125
+ const input = this.argv.shift();
126
+ if (parsingFlags && input.startsWith('-') && input !== '-') {
127
+ // attempt to parse as arg
128
+ if (this.input['--'] !== false && input === '--') {
129
+ parsingFlags = false;
130
+ continue;
131
+ }
132
+ if (parseFlag(input)) {
133
+ continue;
134
+ }
135
+ if (input === '--') {
136
+ dashdash = true;
137
+ continue;
138
+ }
139
+ if (this.input['--'] !== false && !isNegativeNumber(input)) {
140
+ // At this point we have a value that begins with '-' or '--'
141
+ // but doesn't match up to a flag definition. So we assume that
142
+ // this is a misspelled flag or a non-existent flag,
143
+ // e.g. --hekp instead of --help
144
+ nonExistentFlags.push(input);
145
+ continue;
146
+ }
147
+ }
148
+ if (parsingFlags && this.currentFlag && this.currentFlag.multiple) {
149
+ this.raw.push({ flag: this.currentFlag.name, input, type: 'flag' });
150
+ continue;
151
+ }
152
+ // not a flag, parse as arg
153
+ const arg = Object.keys(this.input.args)[this._argTokens.length];
154
+ this.raw.push({ arg, input, type: 'arg' });
155
+ }
156
+ const [{ args, argv }, { flags, metadata }] = await Promise.all([this._args(), this._flags()]);
157
+ this._debugOutput(argv, args, flags);
158
+ const unsortedArgv = (dashdash ? [...argv, ...nonExistentFlags, '--'] : [...argv, ...nonExistentFlags]);
159
+ return {
160
+ args: args,
161
+ argv: unsortedArgv.sort((a, b) => originalArgv.indexOf(a) - originalArgv.indexOf(b)),
162
+ flags,
163
+ metadata,
164
+ nonExistentFlags,
165
+ raw: this.raw,
166
+ };
83
167
  }
84
168
  async _args() {
85
169
  const argv = [];
@@ -127,6 +211,9 @@ class Parser {
127
211
  }
128
212
  return { args, argv };
129
213
  }
214
+ get _argTokens() {
215
+ return this.raw.filter((o) => o.type === 'arg');
216
+ }
130
217
  _debugInput() {
131
218
  debug('input: %s', this.argv.join(' '));
132
219
  const args = Object.keys(this.input.args);
@@ -360,92 +447,5 @@ class Parser {
360
447
  }
361
448
  return flagTokenMap;
362
449
  }
363
- async parse() {
364
- this._debugInput();
365
- const parseFlag = (arg) => {
366
- const { isLong, name } = this.findFlag(arg);
367
- if (!name) {
368
- const i = arg.indexOf('=');
369
- if (i !== -1) {
370
- const sliced = arg.slice(i + 1);
371
- this.argv.unshift(sliced);
372
- const equalsParsed = parseFlag(arg.slice(0, i));
373
- if (!equalsParsed) {
374
- this.argv.shift();
375
- }
376
- return equalsParsed;
377
- }
378
- return false;
379
- }
380
- const flag = this.input.flags[name];
381
- if (flag.type === 'option') {
382
- if (!flag.multiple && this.raw.some((o) => o.type === 'flag' && o.flag === name)) {
383
- throw new errors_1.CLIError(`Flag --${name} can only be specified once`);
384
- }
385
- this.currentFlag = flag;
386
- const input = isLong || arg.length < 3 ? this.argv.shift() : arg.slice(arg[2] === '=' ? 3 : 2);
387
- // if the value ends up being one of the command's flags, the user didn't provide an input
388
- if (typeof input !== 'string' || this.findFlag(input).name) {
389
- throw new errors_1.CLIError(`Flag --${name} expects a value`);
390
- }
391
- this.raw.push({ flag: flag.name, input, type: 'flag' });
392
- }
393
- else {
394
- this.raw.push({ flag: flag.name, input: arg, type: 'flag' });
395
- // push the rest of the short characters back on the stack
396
- if (!isLong && arg.length > 2) {
397
- this.argv.unshift(`-${arg.slice(2)}`);
398
- }
399
- }
400
- return true;
401
- };
402
- let parsingFlags = true;
403
- const nonExistentFlags = [];
404
- let dashdash = false;
405
- const originalArgv = [...this.argv];
406
- while (this.argv.length > 0) {
407
- const input = this.argv.shift();
408
- if (parsingFlags && input.startsWith('-') && input !== '-') {
409
- // attempt to parse as arg
410
- if (this.input['--'] !== false && input === '--') {
411
- parsingFlags = false;
412
- continue;
413
- }
414
- if (parseFlag(input)) {
415
- continue;
416
- }
417
- if (input === '--') {
418
- dashdash = true;
419
- continue;
420
- }
421
- if (this.input['--'] !== false && !isNegativeNumber(input)) {
422
- // At this point we have a value that begins with '-' or '--'
423
- // but doesn't match up to a flag definition. So we assume that
424
- // this is a misspelled flag or a non-existent flag,
425
- // e.g. --hekp instead of --help
426
- nonExistentFlags.push(input);
427
- continue;
428
- }
429
- }
430
- if (parsingFlags && this.currentFlag && this.currentFlag.multiple) {
431
- this.raw.push({ flag: this.currentFlag.name, input, type: 'flag' });
432
- continue;
433
- }
434
- // not a flag, parse as arg
435
- const arg = Object.keys(this.input.args)[this._argTokens.length];
436
- this.raw.push({ arg, input, type: 'arg' });
437
- }
438
- const [{ args, argv }, { flags, metadata }] = await Promise.all([this._args(), this._flags()]);
439
- this._debugOutput(argv, args, flags);
440
- const unsortedArgv = (dashdash ? [...argv, ...nonExistentFlags, '--'] : [...argv, ...nonExistentFlags]);
441
- return {
442
- args: args,
443
- argv: unsortedArgv.sort((a, b) => originalArgv.indexOf(a) - originalArgv.indexOf(b)),
444
- flags,
445
- metadata,
446
- nonExistentFlags,
447
- raw: this.raw,
448
- };
449
- }
450
450
  }
451
451
  exports.Parser = Parser;
@@ -30,12 +30,12 @@ declare class Marker {
30
30
  owner: string;
31
31
  name: string;
32
32
  details: Details;
33
- private startMarker;
34
- private stopMarker;
35
33
  method: string;
36
34
  module: string;
37
35
  scope: string;
38
36
  stopped: boolean;
37
+ private startMarker;
38
+ private stopMarker;
39
39
  constructor(owner: string, name: string, details?: Details);
40
40
  addDetails(details: Details): void;
41
41
  measure(): void;
@@ -8,12 +8,12 @@ class Marker {
8
8
  owner;
9
9
  name;
10
10
  details;
11
- startMarker;
12
- stopMarker;
13
11
  method;
14
12
  module;
15
13
  scope;
16
14
  stopped = false;
15
+ startMarker;
16
+ stopMarker;
17
17
  constructor(owner, name, details = {}) {
18
18
  this.owner = owner;
19
19
  this.name = name;
package/lib/util/fs.d.ts CHANGED
@@ -1,7 +1,19 @@
1
1
  export declare function requireJson<T>(...pathParts: string[]): T;
2
- export declare function exists(path: string): Promise<boolean>;
2
+ /**
3
+ * Parser for Args.directory and Flags.directory. Checks that the provided path
4
+ * exists and is a directory.
5
+ * @param input flag or arg input
6
+ * @returns Promise<string>
7
+ */
3
8
  export declare const dirExists: (input: string) => Promise<string>;
9
+ /**
10
+ * Parser for Args.file and Flags.file. Checks that the provided path
11
+ * exists and is a file.
12
+ * @param input flag or arg input
13
+ * @returns Promise<string>
14
+ */
4
15
  export declare const fileExists: (input: string) => Promise<string>;
5
16
  export declare function readJson<T = unknown>(path: string): Promise<T>;
6
17
  export declare function readJsonSync(path: string, parse: false): string;
7
18
  export declare function readJsonSync<T = unknown>(path: string, parse?: true): T;
19
+ export declare function safeReadJson<T>(path: string): Promise<T | undefined>;
package/lib/util/fs.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = exports.exists = exports.requireJson = void 0;
3
+ exports.safeReadJson = exports.readJsonSync = exports.readJson = exports.fileExists = exports.dirExists = exports.requireJson = void 0;
4
4
  const node_fs_1 = require("node:fs");
5
5
  const promises_1 = require("node:fs/promises");
6
6
  const node_path_1 = require("node:path");
@@ -9,32 +9,40 @@ function requireJson(...pathParts) {
9
9
  return JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(...pathParts), 'utf8'));
10
10
  }
11
11
  exports.requireJson = requireJson;
12
- async function exists(path) {
12
+ /**
13
+ * Parser for Args.directory and Flags.directory. Checks that the provided path
14
+ * exists and is a directory.
15
+ * @param input flag or arg input
16
+ * @returns Promise<string>
17
+ */
18
+ const dirExists = async (input) => {
19
+ let dirStat;
13
20
  try {
14
- await (0, promises_1.access)(path);
15
- return true;
21
+ dirStat = await (0, promises_1.stat)(input);
16
22
  }
17
23
  catch {
18
- return false;
19
- }
20
- }
21
- exports.exists = exists;
22
- const dirExists = async (input) => {
23
- if (!(await exists(input))) {
24
24
  throw new Error(`No directory found at ${input}`);
25
25
  }
26
- const fileStat = await (0, promises_1.stat)(input);
27
- if (!fileStat.isDirectory()) {
26
+ if (!dirStat.isDirectory()) {
28
27
  throw new Error(`${input} exists but is not a directory`);
29
28
  }
30
29
  return input;
31
30
  };
32
31
  exports.dirExists = dirExists;
32
+ /**
33
+ * Parser for Args.file and Flags.file. Checks that the provided path
34
+ * exists and is a file.
35
+ * @param input flag or arg input
36
+ * @returns Promise<string>
37
+ */
33
38
  const fileExists = async (input) => {
34
- if (!(await exists(input))) {
39
+ let fileStat;
40
+ try {
41
+ fileStat = await (0, promises_1.stat)(input);
42
+ }
43
+ catch {
35
44
  throw new Error(`No file found at ${input}`);
36
45
  }
37
- const fileStat = await (0, promises_1.stat)(input);
38
46
  if (!fileStat.isFile()) {
39
47
  throw new Error(`${input} exists but is not a file`);
40
48
  }
@@ -52,3 +60,10 @@ function readJsonSync(path, parse = true) {
52
60
  return parse ? JSON.parse(contents) : contents;
53
61
  }
54
62
  exports.readJsonSync = readJsonSync;
63
+ async function safeReadJson(path) {
64
+ try {
65
+ return await readJson(path);
66
+ }
67
+ catch { }
68
+ }
69
+ exports.safeReadJson = safeReadJson;
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": "3.0.4",
4
+ "version": "3.0.5-dev.0",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/core/issues",
7
7
  "dependencies": {
@@ -61,9 +61,8 @@
61
61
  "cross-env": "^7.0.3",
62
62
  "eslint": "^8.50.0",
63
63
  "eslint-config-oclif": "^5.0.0",
64
- "eslint-config-oclif-typescript": "^2.0.1",
64
+ "eslint-config-oclif-typescript": "^3.0.1",
65
65
  "eslint-config-prettier": "^9.0.0",
66
- "eslint-plugin-perfectionist": "^2.1.0",
67
66
  "fancy-test": "^3.0.1",
68
67
  "globby": "^11.1.0",
69
68
  "husky": "^8",