1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Parser = void 0;
|
5 | const tslib_1 = require("tslib");
|
6 | const deps_1 = tslib_1.__importDefault(require("./deps"));
|
7 |
|
8 | const m = deps_1.default()
|
9 |
|
10 | .add('errors', () => require('./errors'))
|
11 |
|
12 | .add('util', () => require('./util'));
|
13 | let debug;
|
14 | try {
|
15 |
|
16 | if (process.env.CLI_FLAGS_DEBUG !== '1')
|
17 | debug = () => { };
|
18 | else
|
19 |
|
20 | debug = require('debug')('@oclif/parser');
|
21 | }
|
22 | catch (_a) {
|
23 | debug = () => { };
|
24 | }
|
25 | class Parser {
|
26 | constructor(input) {
|
27 | this.input = input;
|
28 | this.raw = [];
|
29 | const { pickBy } = m.util;
|
30 | this.context = input.context || {};
|
31 | this.argv = input.argv.slice(0);
|
32 | this._setNames();
|
33 | this.booleanFlags = pickBy(input.flags, f => f.type === 'boolean');
|
34 | this.metaData = {};
|
35 | }
|
36 | parse() {
|
37 | this._debugInput();
|
38 | const findLongFlag = (arg) => {
|
39 | const name = arg.slice(2);
|
40 | if (this.input.flags[name]) {
|
41 | return name;
|
42 | }
|
43 | if (arg.startsWith('--no-')) {
|
44 | const flag = this.booleanFlags[arg.slice(5)];
|
45 | if (flag && flag.allowNo)
|
46 | return flag.name;
|
47 | }
|
48 | };
|
49 | const findShortFlag = (arg) => {
|
50 | return Object.keys(this.input.flags).find(k => this.input.flags[k].char === arg[1]);
|
51 | };
|
52 | const parseFlag = (arg) => {
|
53 | const long = arg.startsWith('--');
|
54 | const name = long ? findLongFlag(arg) : findShortFlag(arg);
|
55 | if (!name) {
|
56 | const i = arg.indexOf('=');
|
57 | if (i !== -1) {
|
58 | const sliced = arg.slice(i + 1);
|
59 | this.argv.unshift(sliced);
|
60 | const equalsParsed = parseFlag(arg.slice(0, i));
|
61 | if (!equalsParsed) {
|
62 | this.argv.shift();
|
63 | }
|
64 | return equalsParsed;
|
65 | }
|
66 | return false;
|
67 | }
|
68 | const flag = this.input.flags[name];
|
69 | if (flag.type === 'option') {
|
70 | this.currentFlag = flag;
|
71 | let input;
|
72 | if (long || arg.length < 3) {
|
73 | input = this.argv.shift();
|
74 | }
|
75 | else {
|
76 | input = arg.slice(arg[2] === '=' ? 3 : 2);
|
77 | }
|
78 | if (typeof input !== 'string') {
|
79 | throw new m.errors.CLIError(`Flag --${name} expects a value`);
|
80 | }
|
81 | this.raw.push({ type: 'flag', flag: flag.name, input });
|
82 | }
|
83 | else {
|
84 | this.raw.push({ type: 'flag', flag: flag.name, input: arg });
|
85 |
|
86 | if (!long && arg.length > 2) {
|
87 | this.argv.unshift(`-${arg.slice(2)}`);
|
88 | }
|
89 | }
|
90 | return true;
|
91 | };
|
92 | let parsingFlags = true;
|
93 | while (this.argv.length) {
|
94 | const input = this.argv.shift();
|
95 | if (parsingFlags && input.startsWith('-') && input !== '-') {
|
96 |
|
97 | if (this.input['--'] !== false && input === '--') {
|
98 | parsingFlags = false;
|
99 | continue;
|
100 | }
|
101 | if (parseFlag(input)) {
|
102 | continue;
|
103 | }
|
104 |
|
105 | }
|
106 | if (parsingFlags && this.currentFlag && this.currentFlag.multiple) {
|
107 | this.raw.push({ type: 'flag', flag: this.currentFlag.name, input });
|
108 | continue;
|
109 | }
|
110 |
|
111 | const arg = this.input.args[this._argTokens.length];
|
112 | if (arg)
|
113 | arg.input = input;
|
114 | this.raw.push({ type: 'arg', input });
|
115 | }
|
116 | const argv = this._argv();
|
117 | const args = this._args(argv);
|
118 | const flags = this._flags();
|
119 | this._debugOutput(argv, args, flags);
|
120 | return {
|
121 | args,
|
122 | argv,
|
123 | flags,
|
124 | raw: this.raw,
|
125 | metadata: this.metaData,
|
126 | };
|
127 | }
|
128 | _args(argv) {
|
129 | const args = {};
|
130 | for (let i = 0; i < this.input.args.length; i++) {
|
131 | const arg = this.input.args[i];
|
132 | args[arg.name] = argv[i];
|
133 | }
|
134 | return args;
|
135 | }
|
136 | _flags() {
|
137 | const flags = {};
|
138 | this.metaData.flags = {};
|
139 | for (const token of this._flagTokens) {
|
140 | const flag = this.input.flags[token.flag];
|
141 | if (!flag)
|
142 | throw new m.errors.CLIError(`Unexpected flag ${token.flag}`);
|
143 | if (flag.type === 'boolean') {
|
144 | if (token.input === `--no-${flag.name}`) {
|
145 | flags[token.flag] = false;
|
146 | }
|
147 | else {
|
148 | flags[token.flag] = true;
|
149 | }
|
150 | flags[token.flag] = flag.parse(flags[token.flag], this.context);
|
151 | }
|
152 | else {
|
153 | const input = token.input;
|
154 | if (flag.options && !flag.options.includes(input)) {
|
155 | throw new m.errors.FlagInvalidOptionError(flag, input);
|
156 | }
|
157 | const value = flag.parse ? flag.parse(input, this.context) : input;
|
158 | if (flag.multiple) {
|
159 | flags[token.flag] = flags[token.flag] || [];
|
160 | flags[token.flag].push(value);
|
161 | }
|
162 | else {
|
163 | flags[token.flag] = value;
|
164 | }
|
165 | }
|
166 | }
|
167 | for (const k of Object.keys(this.input.flags)) {
|
168 | const flag = this.input.flags[k];
|
169 | if (flags[k])
|
170 | continue;
|
171 | if (flag.type === 'option' && flag.env) {
|
172 | const input = process.env[flag.env];
|
173 | if (input)
|
174 | flags[k] = flag.parse(input, this.context);
|
175 | }
|
176 | if (!(k in flags) && flag.default !== undefined) {
|
177 | this.metaData.flags[k] = { setFromDefault: true };
|
178 | if (typeof flag.default === 'function') {
|
179 | flags[k] = flag.default(Object.assign({ options: flag, flags }, this.context));
|
180 | }
|
181 | else {
|
182 | flags[k] = flag.default;
|
183 | }
|
184 | }
|
185 | }
|
186 | return flags;
|
187 | }
|
188 | _argv() {
|
189 | const args = [];
|
190 | const tokens = this._argTokens;
|
191 | for (let i = 0; i < Math.max(this.input.args.length, tokens.length); i++) {
|
192 | const token = tokens[i];
|
193 | const arg = this.input.args[i];
|
194 | if (token) {
|
195 | if (arg) {
|
196 | if (arg.options && !arg.options.includes(token.input)) {
|
197 | throw new m.errors.ArgInvalidOptionError(arg, token.input);
|
198 | }
|
199 | args[i] = arg.parse(token.input);
|
200 | }
|
201 | else {
|
202 | args[i] = token.input;
|
203 | }
|
204 | }
|
205 | else if ('default' in arg) {
|
206 | if (typeof arg.default === 'function') {
|
207 | args[i] = arg.default();
|
208 | }
|
209 | else {
|
210 | args[i] = arg.default;
|
211 | }
|
212 | }
|
213 | }
|
214 | return args;
|
215 | }
|
216 | _debugOutput(args, flags, argv) {
|
217 | if (argv.length > 0) {
|
218 | debug('argv: %o', argv);
|
219 | }
|
220 | if (Object.keys(args).length > 0) {
|
221 | debug('args: %o', args);
|
222 | }
|
223 | if (Object.keys(flags).length > 0) {
|
224 | debug('flags: %o', flags);
|
225 | }
|
226 | }
|
227 | _debugInput() {
|
228 | debug('input: %s', this.argv.join(' '));
|
229 | if (this.input.args.length > 0) {
|
230 | debug('available args: %s', this.input.args.map(a => a.name).join(' '));
|
231 | }
|
232 | if (Object.keys(this.input.flags).length === 0)
|
233 | return;
|
234 | debug('available flags: %s', Object.keys(this.input.flags)
|
235 | .map(f => `--${f}`)
|
236 | .join(' '));
|
237 | }
|
238 | get _argTokens() {
|
239 | return this.raw.filter(o => o.type === 'arg');
|
240 | }
|
241 | get _flagTokens() {
|
242 | return this.raw.filter(o => o.type === 'flag');
|
243 | }
|
244 | _setNames() {
|
245 | for (const k of Object.keys(this.input.flags)) {
|
246 | this.input.flags[k].name = k;
|
247 | }
|
248 | }
|
249 | }
|
250 | exports.Parser = Parser;
|