@sapphire/framework
Version:
Discord bot framework built for advanced and amazing bots.
300 lines (297 loc) • 8.9 kB
JavaScript
'use strict';
var lexure = require('@sapphire/lexure');
var pieces = require('@sapphire/pieces');
var result = require('@sapphire/result');
var ArgumentError_cjs = require('../errors/ArgumentError.cjs');
var Identifiers_cjs = require('../errors/Identifiers.cjs');
var UserError_cjs = require('../errors/UserError.cjs');
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var _Args = class _Args {
constructor(message, command, parser, context) {
/**
* The states stored in the args.
* @see Args#save
* @see Args#restore
*/
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) {
const result = await this.pickResult(type, options);
return result.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 = lexure.join(this.parser.many().unwrapOr([]));
const result = await argument.run(data, {
args: this,
argument,
message: this.message,
command: this.command,
commandContext: this.commandContext,
...options
});
return result.inspectErr(() => this.parser.restore(state));
}
async rest(type, options) {
const result = await this.restResult(type, options);
return result.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()) {
const error = result.unwrapErr();
if (error === null) break;
if (output.length === 0) {
return result;
}
break;
}
output.push(result.unwrap());
}
return result.Result.ok(output);
}
async repeat(type, options) {
const result = await this.repeatResult(type, options);
return result.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) {
const result = await this.peekResult(type, options);
return result.unwrapRaw();
}
nextMaybe(cb) {
return result.Option.from(typeof cb === "function" ? this.parser.singleMap(cb) : this.parser.single());
}
next(cb) {
const value = cb ? this.nextMaybe(cb) : this.nextMaybe();
return value.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 result.Result.err(
new UserError_cjs.UserError({
identifier: Identifiers_cjs.Identifiers.ArgsUnavailable,
message: `The argument "${name}" was not found.`,
context: { name, ...this.toJSON() }
})
);
}
missingArguments() {
return result.Result.err(new UserError_cjs.UserError({ identifier: Identifiers_cjs.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 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 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 result.Result.err(new ArgumentError_cjs.ArgumentError(options));
}
};
__name(_Args, "Args");
var Args = _Args;
exports.Args = Args;
//# sourceMappingURL=Args.cjs.map
//# sourceMappingURL=Args.cjs.map