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