1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | Object.defineProperty(exports, "__esModule", { value: true });
|
9 | exports.buildSfdxFlags = exports.optionalBuiltinFlags = exports.requiredBuiltinFlags = exports.flags = void 0;
|
10 | const url_1 = require("url");
|
11 | const core_1 = require("@oclif/core");
|
12 | const core_2 = require("@salesforce/core");
|
13 | const kit_1 = require("@salesforce/kit");
|
14 | const ts_types_1 = require("@salesforce/ts-types");
|
15 | core_2.Messages.importMessagesDirectory(__dirname);
|
16 | const messages = core_2.Messages.load('@salesforce/command', 'flags', [
|
17 | 'error.UnknownBuiltinFlagType',
|
18 | 'error.FormattingMessageArrayValue',
|
19 | 'error.FormattingMessageArrayOption',
|
20 | 'error.FormattingMessageDate',
|
21 | 'error.FormattingMessageId',
|
22 | 'error.FormattingMessageId',
|
23 | 'error.InvalidFlagType',
|
24 | 'flags.json.description.long',
|
25 | 'flags.json.description',
|
26 | 'error.InvalidLoggerLevel',
|
27 | 'error.InvalidApiVersion',
|
28 | 'flags.apiversion.description',
|
29 | 'flags.apiversion.description.long',
|
30 | 'flags.concise.description',
|
31 | 'flags.long.description.long',
|
32 | 'flags.loglevel.description',
|
33 | 'flags.loglevel.description.long',
|
34 | 'flags.quiet.description',
|
35 | 'flags.quiet.description.long',
|
36 | 'flags.targetdevhubusername.description',
|
37 | 'flags.targetdevhubusername.description.long',
|
38 | 'flags.targetusername.description',
|
39 | 'flags.targetusername.description.long',
|
40 | 'flags.verbose.description',
|
41 | 'flags.verbose.description.long',
|
42 | 'error.InvalidFlagName',
|
43 | 'error.InvalidFlagChar',
|
44 | 'error.MissingOrInvalidFlagDescription',
|
45 | 'error.InvalidLongDescriptionFormat',
|
46 | ]);
|
47 | function validateValue(isValid, value, kind, correct) {
|
48 | if (isValid)
|
49 | return value;
|
50 | throw messages.createError('error.InvalidFlagType', [value, kind, correct || '']);
|
51 | }
|
52 | function toValidatorFn(validator) {
|
53 | return (val) => {
|
54 | if ((0, ts_types_1.isString)(validator))
|
55 | return new RegExp(validator).test(val);
|
56 | if ((0, ts_types_1.isInstance)(validator, RegExp))
|
57 | return validator.test(val);
|
58 | if ((0, ts_types_1.isFunction)(validator))
|
59 | return !!validator(val);
|
60 | return true;
|
61 | };
|
62 | }
|
63 | function merge(kind, flag, describable) {
|
64 | if ((0, ts_types_1.has)(flag, 'validate') && (0, ts_types_1.hasFunction)(flag, 'parse')) {
|
65 | const parse = flag.parse.bind(flag);
|
66 | flag.parse = (val, ctx) => {
|
67 | validateValue(toValidatorFn(flag.validate)(val), val, kind);
|
68 | return parse(val, ctx);
|
69 | };
|
70 | }
|
71 | return {
|
72 | kind,
|
73 | ...flag,
|
74 | description: describable.description,
|
75 | longDescription: describable.longDescription,
|
76 | };
|
77 | }
|
78 | function option(kind, options, parse) {
|
79 | const flag = core_1.Flags.option({ ...options, parse });
|
80 | return merge(kind, flag, options);
|
81 | }
|
82 |
|
83 | function buildBoolean(options) {
|
84 | const flag = core_1.Flags.boolean(options);
|
85 | return merge('boolean', flag, options);
|
86 | }
|
87 | function buildEnum(options) {
|
88 | return {
|
89 | kind: 'enum',
|
90 | ...core_1.Flags.enum(options),
|
91 | options: options.options,
|
92 | description: options.description,
|
93 | longDescription: options.longDescription,
|
94 | };
|
95 | }
|
96 | function buildHelp(options) {
|
97 | const flag = core_1.Flags.help(options);
|
98 | return merge('help', core_1.Flags.help(options), {
|
99 | description: (0, ts_types_1.ensure)(flag.description),
|
100 | });
|
101 | }
|
102 | function buildFilepath(options) {
|
103 | return option('filepath', options, (val) => {
|
104 | return Promise.resolve(validateValue(core_2.sfdc.validatePathDoesNotContainInvalidChars(val), val, 'filepath'));
|
105 | });
|
106 | }
|
107 | function buildDirectory(options) {
|
108 | return option('directory', options, (val) => {
|
109 | return Promise.resolve(validateValue(core_2.sfdc.validatePathDoesNotContainInvalidChars(val), val, 'directory'));
|
110 | });
|
111 | }
|
112 | function validateBounds(kind, value, bounds, extract) {
|
113 | if (bounds.min != null && value < extract(bounds.min)) {
|
114 | throw new core_2.SfError(`Expected ${kind} greater than or equal to ${extract(bounds.min)} but received ${value}`, 'InvalidFlagNumericBoundsError');
|
115 | }
|
116 | if (bounds.max != null && value > extract(bounds.max)) {
|
117 | throw new core_2.SfError(`Expected ${kind} less than or equal to ${extract(bounds.max)} but received ${value}`, 'InvalidFlagNumericBoundsError');
|
118 | }
|
119 | return value;
|
120 | }
|
121 | function buildInteger(options) {
|
122 | const kind = 'integer';
|
123 | return option(kind, options, async (val) => {
|
124 | const parsed = (0, kit_1.toNumber)(val);
|
125 | validateValue(Number.isInteger(parsed), val, kind);
|
126 | return validateBounds(kind, parsed, options, (t) => t);
|
127 | });
|
128 | }
|
129 | function buildOption(options) {
|
130 | return merge('option', core_1.Flags.option(options), options);
|
131 | }
|
132 | function buildString(options) {
|
133 | return merge('string', core_1.Flags.string(options), options);
|
134 | }
|
135 | function buildVersion(options) {
|
136 | const flag = core_1.Flags.version(options);
|
137 | return merge('version', flag, {
|
138 | description: (0, ts_types_1.ensure)(flag.description),
|
139 | });
|
140 | }
|
141 |
|
142 | function validateArrayValues(kind, raw, vals, validator) {
|
143 | validateValue(vals.every(toValidatorFn(validator)), raw, kind, ` ${messages.getMessage('error.FormattingMessageArrayValue')}`);
|
144 | }
|
145 | function validateArrayOptions(kind, raw, vals, allowed) {
|
146 | validateValue(allowed.size === 0 || vals.every((t) => allowed.has(t)), raw, kind, ` ${messages.getMessage('error.FormattingMessageArrayOption', [Array.from(allowed).toString()])}`);
|
147 | }
|
148 | const convertArrayFlagToArray = (flagValue, delimiter = ',') => {
|
149 |
|
150 |
|
151 | const regex = new RegExp(`"(.*?)"|\'(.*?)\'|${delimiter}`);
|
152 | return flagValue
|
153 | .split(regex)
|
154 | .filter((i) => !!i)
|
155 | .map((i) => i.trim());
|
156 | };
|
157 | function buildMappedArray(kind, options) {
|
158 | const { options: values, ...rest } = options;
|
159 | const allowed = new Set(values);
|
160 | return option(kind, rest, (val) => {
|
161 | const vals = convertArrayFlagToArray(val, options.delimiter);
|
162 | validateArrayValues(kind, val, vals, options.validate);
|
163 | const mappedVals = vals.map(options.map);
|
164 | validateArrayOptions(kind, val, mappedVals, allowed);
|
165 | return Promise.resolve(mappedVals);
|
166 | });
|
167 | }
|
168 | function buildStringArray(kind, options) {
|
169 | const { options: values, ...rest } = options;
|
170 | const allowed = new Set(values);
|
171 | return option(kind, rest, (val) => {
|
172 | const vals = convertArrayFlagToArray(val, options.delimiter);
|
173 | validateArrayValues(kind, val, vals, options.validate);
|
174 | validateArrayOptions(kind, val, vals, allowed);
|
175 | return Promise.resolve(vals);
|
176 | });
|
177 | }
|
178 | function buildArray(options) {
|
179 | const kind = 'array';
|
180 | return 'map' in options ? buildMappedArray(kind, options) : buildStringArray(kind, options);
|
181 | }
|
182 | function buildDate(options) {
|
183 | const kind = 'date';
|
184 | return option(kind, options, (val) => {
|
185 | const parsed = Date.parse(val);
|
186 | validateValue(!isNaN(parsed), val, kind, ` ${messages.getMessage('error.FormattingMessageDate')}`);
|
187 | return Promise.resolve(new Date(parsed));
|
188 | });
|
189 | }
|
190 | function buildDatetime(options) {
|
191 | const kind = 'datetime';
|
192 | return option(kind, options, (val) => {
|
193 | const parsed = Date.parse(val);
|
194 | validateValue(!isNaN(parsed), val, kind, ` ${messages.getMessage('error.FormattingMessageDate')}`);
|
195 | return Promise.resolve(new Date(parsed));
|
196 | });
|
197 | }
|
198 | function buildEmail(options) {
|
199 | return option('email', options, (val) => {
|
200 | return Promise.resolve(validateValue(core_2.sfdc.validateEmail(val), val, 'email'));
|
201 | });
|
202 | }
|
203 | function buildId(options) {
|
204 | return option('id', options, (val) => {
|
205 | return Promise.resolve(validateValue(core_2.sfdc.validateSalesforceId(val), val, 'id', ` ${messages.getMessage('error.FormattingMessageId')}`));
|
206 | });
|
207 | }
|
208 | function buildMilliseconds(options) {
|
209 | const kind = 'milliseconds';
|
210 | return option(kind, options, async (val) => {
|
211 | const parsed = (0, kit_1.toNumber)(val);
|
212 | validateValue(Number.isInteger(parsed), val, kind);
|
213 | return Promise.resolve(kit_1.Duration.milliseconds(validateBounds(kind, parsed, options, (v) => ((0, ts_types_1.isNumber)(v) ? v : v[kind]))));
|
214 | });
|
215 | }
|
216 | function buildMinutes(options) {
|
217 | const kind = 'minutes';
|
218 | return option(kind, options, async (val) => {
|
219 | const parsed = (0, kit_1.toNumber)(val);
|
220 | validateValue(Number.isInteger(parsed), val, kind);
|
221 | return Promise.resolve(kit_1.Duration.minutes(validateBounds(kind, parsed, options, (v) => ((0, ts_types_1.isNumber)(v) ? v : v[kind]))));
|
222 | });
|
223 | }
|
224 | function buildNumber(options) {
|
225 | const kind = 'number';
|
226 | return option(kind, options, async (val) => {
|
227 | const parsed = (0, kit_1.toNumber)(val);
|
228 | validateValue(isFinite(parsed), val, kind);
|
229 | return validateBounds(kind, parsed, options, (t) => t);
|
230 | });
|
231 | }
|
232 | function buildSeconds(options) {
|
233 | const kind = 'seconds';
|
234 | return option(kind, options, async (val) => {
|
235 | const parsed = (0, kit_1.toNumber)(val);
|
236 | validateValue(Number.isInteger(parsed), val, kind);
|
237 | return Promise.resolve(kit_1.Duration.seconds(validateBounds(kind, parsed, options, (v) => ((0, ts_types_1.isNumber)(v) ? v : v[kind]))));
|
238 | });
|
239 | }
|
240 | function buildUrl(options) {
|
241 | return option('url', options, (val) => {
|
242 | try {
|
243 | return Promise.resolve(new url_1.URL(val));
|
244 | }
|
245 | catch (err) {
|
246 | const correct = ` ${messages.getMessage('error.FormattingMessageId')}`;
|
247 | throw messages.createError('error.InvalidFlagType', [val, 'url', correct || '']);
|
248 | }
|
249 | });
|
250 | }
|
251 | function buildBuiltin(options = {}) {
|
252 | return { ...options, type: 'builtin' };
|
253 | }
|
254 | exports.flags = {
|
255 |
|
256 | |
257 |
|
258 |
|
259 | boolean: buildBoolean,
|
260 | |
261 |
|
262 |
|
263 | enum: buildEnum,
|
264 | |
265 |
|
266 |
|
267 | help: buildHelp,
|
268 | |
269 |
|
270 |
|
271 |
|
272 | integer: buildInteger,
|
273 | |
274 |
|
275 |
|
276 |
|
277 | option: buildOption,
|
278 | |
279 |
|
280 |
|
281 | string: buildString,
|
282 | |
283 |
|
284 |
|
285 | version: buildVersion,
|
286 | |
287 |
|
288 |
|
289 |
|
290 |
|
291 | filepath: buildFilepath,
|
292 | |
293 |
|
294 |
|
295 |
|
296 |
|
297 | directory: buildDirectory,
|
298 |
|
299 | |
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 | array: buildArray,
|
306 | |
307 |
|
308 |
|
309 | date: buildDate,
|
310 | |
311 |
|
312 |
|
313 | datetime: buildDatetime,
|
314 | |
315 |
|
316 |
|
317 |
|
318 |
|
319 | email: buildEmail,
|
320 | |
321 |
|
322 |
|
323 |
|
324 |
|
325 | id: buildId,
|
326 | |
327 |
|
328 |
|
329 | milliseconds: buildMilliseconds,
|
330 | |
331 |
|
332 |
|
333 | minutes: buildMinutes,
|
334 | |
335 |
|
336 |
|
337 |
|
338 | number: buildNumber,
|
339 | |
340 |
|
341 |
|
342 | seconds: buildSeconds,
|
343 | |
344 |
|
345 |
|
346 | url: buildUrl,
|
347 |
|
348 | |
349 |
|
350 |
|
351 | builtin: buildBuiltin,
|
352 | };
|
353 | exports.requiredBuiltinFlags = {
|
354 | json() {
|
355 | return exports.flags.boolean({
|
356 | description: messages.getMessage('flags.json.description'),
|
357 | longDescription: messages.getMessage('flags.json.description.long'),
|
358 | });
|
359 | },
|
360 | loglevel() {
|
361 | return exports.flags.enum({
|
362 | options: core_2.Logger.LEVEL_NAMES.concat(core_2.Logger.LEVEL_NAMES.map((l) => l.toUpperCase())),
|
363 | default: core_2.LoggerLevel[core_2.Logger.DEFAULT_LEVEL].toLowerCase(),
|
364 | required: false,
|
365 | description: messages.getMessage('flags.loglevel.description'),
|
366 | longDescription: messages.getMessage('flags.loglevel.description.long'),
|
367 | parse: (val) => {
|
368 | val = val.toLowerCase();
|
369 | if (core_2.Logger.LEVEL_NAMES.includes(val))
|
370 | return Promise.resolve(val);
|
371 | throw messages.createError('error.InvalidLoggerLevel', [val]);
|
372 | },
|
373 | });
|
374 | },
|
375 | };
|
376 | function resolve(opts, key, def) {
|
377 | return (0, ts_types_1.hasString)(opts, key) ? opts[key] : def;
|
378 | }
|
379 | exports.optionalBuiltinFlags = {
|
380 | apiversion(opts) {
|
381 | return Object.assign(opts || {}, exports.flags.string({
|
382 | description: resolve(opts, 'description', messages.getMessage('flags.apiversion.description')),
|
383 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.apiversion.description.long')),
|
384 | parse: (val) => {
|
385 | if (core_2.sfdc.validateApiVersion(val))
|
386 | return Promise.resolve(val);
|
387 | throw messages.createError('error.InvalidApiVersion', [val]);
|
388 | },
|
389 | }));
|
390 | },
|
391 | concise(opts) {
|
392 | return Object.assign(opts || {}, exports.flags.boolean({
|
393 | description: resolve(opts, 'description', messages.getMessage('flags.concise.description')),
|
394 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.long.description.long')),
|
395 | }));
|
396 | },
|
397 | quiet(opts) {
|
398 | return Object.assign(opts || {}, exports.flags.boolean({
|
399 | description: resolve(opts, 'description', messages.getMessage('flags.quiet.description')),
|
400 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.quiet.description.long')),
|
401 | }));
|
402 | },
|
403 | targetdevhubusername(opts) {
|
404 | return Object.assign(opts || {}, exports.flags.string({
|
405 | char: 'v',
|
406 | description: resolve(opts, 'description', messages.getMessage('flags.targetdevhubusername.description')),
|
407 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.targetdevhubusername.description.long')),
|
408 | }));
|
409 | },
|
410 | targetusername(opts) {
|
411 | return Object.assign(opts || {}, exports.flags.string({
|
412 | char: 'u',
|
413 | description: resolve(opts, 'description', messages.getMessage('flags.targetusername.description')),
|
414 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.targetusername.description.long')),
|
415 | }));
|
416 | },
|
417 | verbose(opts) {
|
418 | return Object.assign(opts || {}, exports.flags.boolean({
|
419 | description: resolve(opts, 'description', messages.getMessage('flags.verbose.description')),
|
420 | longDescription: resolve(opts, 'longDescription', messages.getMessage('flags.verbose.description.long')),
|
421 | }));
|
422 | },
|
423 | };
|
424 |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 |
|
434 |
|
435 |
|
436 | function validateCustomFlag(key, flag) {
|
437 | if (!/^(?!(?:[-]|[0-9]*$))[a-z0-9-]+$/.test(key)) {
|
438 | throw messages.createError('error.InvalidFlagName', [key]);
|
439 | }
|
440 | if (flag.char && (flag.char.length !== 1 || !/[a-zA-Z]/.test(flag.char))) {
|
441 | throw messages.createError('error.InvalidFlagChar', [key]);
|
442 | }
|
443 | if (!flag.description || !(0, ts_types_1.isString)(flag.description)) {
|
444 | throw messages.createError('error.MissingOrInvalidFlagDescription', [key]);
|
445 | }
|
446 | if (flag.longDescription !== undefined && !(0, ts_types_1.isString)(flag.longDescription)) {
|
447 | throw messages.createError('error.InvalidLongDescriptionFormat', [key]);
|
448 | }
|
449 | return flag;
|
450 | }
|
451 |
|
452 | function isBuiltin(flag) {
|
453 | return (0, ts_types_1.hasString)(flag, 'type') && flag.type === 'builtin';
|
454 | }
|
455 |
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 |
|
466 | function buildSfdxFlags(flagsConfig, options
|
467 | // tslint:disable-next-line:no-any matches oclif
|
468 | ) {
|
469 | const output = {};
|
470 |
|
471 | output.json = exports.requiredBuiltinFlags.json();
|
472 | output.loglevel = exports.requiredBuiltinFlags.loglevel();
|
473 | if (options.targetdevhubusername)
|
474 | output.targetdevhubusername = exports.optionalBuiltinFlags.targetdevhubusername();
|
475 | if (options.targetusername)
|
476 | output.targetusername = exports.optionalBuiltinFlags.targetusername();
|
477 | if (options.targetdevhubusername || options.targetusername)
|
478 | output.apiversion = exports.optionalBuiltinFlags.apiversion();
|
479 |
|
480 | (0, ts_types_1.definiteEntriesOf)(flagsConfig).forEach(([key, flag]) => {
|
481 | if (isBuiltin(flag)) {
|
482 | if (!(0, ts_types_1.isKeyOf)(exports.optionalBuiltinFlags, key)) {
|
483 | throw messages.createError('error.UnknownBuiltinFlagType', [key]);
|
484 | }
|
485 | output[key] = exports.optionalBuiltinFlags[key](flag);
|
486 | }
|
487 | else {
|
488 | output[key] = validateCustomFlag(key, flag);
|
489 | }
|
490 | });
|
491 | return output;
|
492 | }
|
493 | exports.buildSfdxFlags = buildSfdxFlags;
|
494 |
|
\ | No newline at end of file |