@sapphire/framework
Version:
Discord bot framework built for advanced and amazing bots.
291 lines (289 loc) • 8.21 kB
JavaScript
"use strict";
const require_lib_errors_Identifiers = require('../errors/Identifiers.cjs');
const require_lib_errors_UserError = require('../errors/UserError.cjs');
const require_lib_errors_ArgumentError = require('../errors/ArgumentError.cjs');
let __sapphire_pieces = require("@sapphire/pieces");
let __sapphire_result = require("@sapphire/result");
let __sapphire_lexure = require("@sapphire/lexure");
//#region src/lib/parsers/Args.ts
/**
* The argument parser to be used in {@link Command}.
*/
var Args = class {
constructor(message, command, parser, context) {
this.states = [];
this.message = message;
this.command = command;
this.parser = parser;
this.commandContext = context;
}
/**
* Sets the parser to the first token.
*/
start() {
this.parser.reset();
return this;
}
async pickResult(type, options = {}) {
const argument = this.resolveArgument(type);
if (!argument) return this.unavailableArgument(type);
const result = await this.parser.singleParseAsync(async (arg) => argument.run(arg, {
args: this,
argument,
message: this.message,
command: this.command,
commandContext: this.commandContext,
...options
}));
if (result.isErrAnd((value) => value === null)) return this.missingArguments();
return result;
}
async pick(type, options) {
return (await this.pickResult(type, options)).unwrapRaw();
}
async restResult(type, options = {}) {
const argument = this.resolveArgument(type);
if (!argument) return this.unavailableArgument(type);
if (this.parser.finished) return this.missingArguments();
const state = this.parser.save();
const data = (0, __sapphire_lexure.join)(this.parser.many().unwrapOr([]));
return (await argument.run(data, {
args: this,
argument,
message: this.message,
command: this.command,
commandContext: this.commandContext,
...options
})).inspectErr(() => this.parser.restore(state));
}
async rest(type, options) {
return (await this.restResult(type, options)).unwrapRaw();
}
async repeatResult(type, options = {}) {
const argument = this.resolveArgument(type);
if (!argument) return this.unavailableArgument(type);
if (this.parser.finished) return this.missingArguments();
const output = [];
for (let i = 0, times = options.times ?? Infinity; i < times; i++) {
const result = await this.parser.singleParseAsync(async (arg) => argument.run(arg, {
args: this,
argument,
message: this.message,
command: this.command,
commandContext: this.commandContext,
...options
}));
if (result.isErr()) {
if (result.unwrapErr() === null) break;
if (output.length === 0) return result;
break;
}
output.push(result.unwrap());
}
return __sapphire_result.Result.ok(output);
}
async repeat(type, options) {
return (await this.repeatResult(type, options)).unwrapRaw();
}
async peekResult(type, options = {}) {
this.save();
const result = typeof type === "function" ? await type() : await this.pickResult(type, options);
this.restore();
return result;
}
async peek(type, options) {
return (await this.peekResult(type, options)).unwrapRaw();
}
nextMaybe(cb) {
return __sapphire_result.Option.from(typeof cb === "function" ? this.parser.singleMap(cb) : this.parser.single());
}
next(cb) {
return (cb ? this.nextMaybe(cb) : this.nextMaybe()).unwrapOr(null);
}
/**
* Checks if one or more flag were given.
* @param keys The name(s) of the flag.
* @example
* ```typescript
* // Suppose args are from '--f --g'.
* console.log(args.getFlags('f'));
* // >>> true
*
* console.log(args.getFlags('g', 'h'));
* // >>> true
*
* console.log(args.getFlags('h'));
* // >>> false
* ```
*/
getFlags(...keys) {
return this.parser.flag(...keys);
}
/**
* Gets the last value of one or more options as an {@link Option}.
* If you do not care about safely handling non-existing values
* you can use {@link Args.getOption} to get `string | null` as return type
* @param keys The name(s) of the option.
* @example
* ```typescript
* // Suppose args are from '--a=1 --b=2 --c=3'.
* console.log(args.getOptionResult('a'));
* // >>> Some { value: '1' }
*
* console.log(args.getOptionResult('b', 'c'));
* // >>> Some { value: '2' }
*
* console.log(args.getOptionResult('d'));
* // >>> None {}
* ```
*/
getOptionResult(...keys) {
return this.parser.option(...keys);
}
/**
* Gets the last value of one or more options.
* Similar to {@link Args.getOptionResult} but returns the value on success, or `null` if not.
* @param keys The name(s) of the option.
* @example
* ```typescript
* // Suppose args are from '--a=1 --b=2 --c=3'.
* console.log(args.getOption('a'));
* // >>> '1'
*
* console.log(args.getOption('b', 'c'));
* // >>> '2'
*
* console.log(args.getOption('d'));
* // >>> null
* ```
*/
getOption(...keys) {
return this.parser.option(...keys).unwrapOr(null);
}
/**
* Gets all the values of one or more option.
* @param keys The name(s) of the option.
* @example
* ```typescript
* // Suppose args are from '--a=1 --a=1 --b=2 --c=3'.
* console.log(args.getOptionsResult('a'));
* // >>> Some { value: [ '1' ] }
*
* console.log(args.getOptionsResult('a', 'd'));
* // >>> Some { value: [ '1' ] }
*
* console.log(args.getOptionsResult('b', 'c'));
* // >>> Some { value: [ '2', '3' ] }
*
* console.log(args.getOptionsResult('d'));
* // >>> None {}
* ```
*/
getOptionsResult(...keys) {
return this.parser.options(...keys);
}
/**
* Gets all the values of one or more option.
* Similar to {@link Args.getOptionsResult} but returns the value on success, or `null` if not.
* @param keys The name(s) of the option.
* @example
* ```typescript
* // Suppose args are from '--a=1 --a=1 --b=2 --c=3'.
* console.log(args.getOptions('a'));
* // >>> ['1', '1']
*
* console.log(args.getOptions('b', 'c'));
* // >>> ['2', '3']
*
* console.log(args.getOptions('d'));
* // >>> null
* ```
*/
getOptions(...keys) {
return this.parser.options(...keys).unwrapOr(null);
}
/**
* Saves the current state into the stack following a FILO strategy (first-in, last-out).
* @see Args#restore
*/
save() {
this.states.push(this.parser.save());
}
/**
* Restores the previously saved state from the stack.
* @see Args#save
*/
restore() {
if (this.states.length !== 0) this.parser.restore(this.states.pop());
}
/**
* Whether all arguments have been consumed.
*/
get finished() {
return this.parser.finished;
}
/**
* Defines the `JSON.stringify` override.
*/
toJSON() {
return {
message: this.message,
command: this.command,
commandContext: this.commandContext
};
}
unavailableArgument(type) {
const name = typeof type === "string" ? type : type.name;
return __sapphire_result.Result.err(new require_lib_errors_UserError.UserError({
identifier: require_lib_errors_Identifiers.Identifiers.ArgsUnavailable,
message: `The argument "${name}" was not found.`,
context: {
name,
...this.toJSON()
}
}));
}
missingArguments() {
return __sapphire_result.Result.err(new require_lib_errors_UserError.UserError({
identifier: require_lib_errors_Identifiers.Identifiers.ArgsMissing,
message: "There are no more arguments.",
context: this.toJSON()
}));
}
/**
* Resolves an argument.
* @param arg The argument name or {@link IArgument} instance.
*/
resolveArgument(arg) {
if (typeof arg === "object") return arg;
return __sapphire_pieces.container.stores.get("arguments").get(arg);
}
/**
* Converts a callback into a usable argument.
* @param cb The callback to convert into an {@link IArgument}.
* @param name The name of the argument.
*/
static make(cb, name = "") {
return {
run: cb,
name
};
}
/**
* Constructs an {@link Ok} result.
* @param value The value to pass.
*/
static ok(value) {
return __sapphire_result.Result.ok(value);
}
/**
* Constructs an {@link Err} result containing an {@link ArgumentError}.
* @param options The options for the argument error.
*/
static error(options) {
return __sapphire_result.Result.err(new require_lib_errors_ArgumentError.ArgumentError(options));
}
};
//#endregion
exports.Args = Args;
//# sourceMappingURL=Args.cjs.map