Move from interface to abstract class for resolver with some default methods

This commit is contained in:
Erik 2024-04-10 17:23:15 +03:00
parent 9735550272
commit fd620ec287
8 changed files with 62 additions and 31 deletions

View File

@ -1,7 +1,7 @@
/* eslint-disable max-classes-per-file */ /* eslint-disable max-classes-per-file */
import { CommandOption, IResolver } from '@navy.gif/commandparser'; import { CommandOption, AbstractResolver } from '@navy.gif/commandparser';
class Resolver implements IResolver class Resolver implements AbstractResolver
{ {
resolveMember<Member, Guild> (_resolveable: string, _strict: boolean, _guild: Guild): Promise<Member | null> resolveMember<Member, Guild> (_resolveable: string, _strict: boolean, _guild: Guild): Promise<Member | null>
{ {

View File

@ -6,6 +6,6 @@ export { CommandOption } from './src/classes/CommandOption.js';
export { SubcommandGroupOption } from './src/classes/SubcommandGroupOption.js'; export { SubcommandGroupOption } from './src/classes/SubcommandGroupOption.js';
export { SubcommandOption } from './src/classes/SubcommandOption.js'; export { SubcommandOption } from './src/classes/SubcommandOption.js';
export { IResolver } from './src/interfaces/Resolver.js'; export { AbstractResolver } from './src/interfaces/Resolver.js';
export { OptionType, CommandOptionDefinition } from './src/interfaces/CommandOption.js'; export { OptionType, CommandOptionDefinition } from './src/interfaces/CommandOption.js';
export { CommandDefinition, ICommand, CommandArgs } from './src/interfaces/Command.js'; export { CommandDefinition, ICommand, CommandArgs } from './src/interfaces/Command.js';

View File

@ -40,5 +40,8 @@
"release:major": "yarn build && yarn version major && yarn npm publish", "release:major": "yarn build && yarn version major && yarn npm publish",
"lint": "eslint --fix src/" "lint": "eslint --fix src/"
}, },
"packageManager": "yarn@4.1.1" "packageManager": "yarn@4.1.1",
"dependencies": {
"@navy.gif/timestring": "^6.0.6"
}
} }

View File

@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
import CommandOption from './classes/CommandOption.js'; import CommandOption from './classes/CommandOption.js';
import { CommandOptionDefinition, OptionType } from './interfaces/CommandOption.js'; import { CommandOptionDefinition, OptionType } from './interfaces/CommandOption.js';
import IResolver from './interfaces/Resolver.js'; import AbstractResolver from './interfaces/Resolver.js';
import ExtendedMap from './util/Map.js'; import ExtendedMap from './util/Map.js';
import Util from './util/Util.js'; import Util from './util/Util.js';
import { ICommand } from '../index.js'; import { ICommand } from '../index.js';
@ -31,7 +31,7 @@ type ParserOptions = {
commands: Iterable<ICommand>, commands: Iterable<ICommand>,
prefix?: string, prefix?: string,
debug?: boolean, debug?: boolean,
resolver?: IResolver, resolver?: AbstractResolver,
/** /**
* Allow default value on a required Option * Allow default value on a required Option
@ -64,7 +64,7 @@ class Parser extends EventEmitter
private commands: ExtendedMap<string, ICommand>; private commands: ExtendedMap<string, ICommand>;
private _debug = false; private _debug = false;
prefix: string; prefix: string;
resolver?: IResolver; resolver?: AbstractResolver;
allowDefaultOnRequired: boolean; allowDefaultOnRequired: boolean;
#globalFlags: CommandOption[]; #globalFlags: CommandOption[];
#allowIncompleteReturn: string[]; #allowIncompleteReturn: string[];

View File

@ -1,6 +1,6 @@
/* eslint-disable no-undefined */ /* eslint-disable no-undefined */
import ICommandOption, { Choice, CommandOptionDefinition, DependsOnMode, OptionType, ParseResult } from '../interfaces/CommandOption.js'; import ICommandOption, { Choice, CommandOptionDefinition, DependsOnMode, OptionType, ParseResult } from '../interfaces/CommandOption.js';
import IResolver from '../interfaces/Resolver.js'; import AbstractResolver from '../interfaces/Resolver.js';
const SUB = [ OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP ]; const SUB = [ OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP ];
class CommandOption implements ICommandOption class CommandOption implements ICommandOption
@ -27,7 +27,7 @@ class CommandOption implements ICommandOption
value?: unknown; value?: unknown;
aliased = false; aliased = false;
strict: boolean; strict: boolean;
protected resolver?: IResolver | undefined; protected resolver?: AbstractResolver | undefined;
constructor (def: CommandOptionDefinition|CommandOption|ICommandOption) constructor (def: CommandOptionDefinition|CommandOption|ICommandOption)
{ {
@ -86,7 +86,7 @@ class CommandOption implements ICommandOption
this.required = def.required || false; this.required = def.required || false;
} }
clone (rawValue?: string[], resolver?: IResolver): CommandOption clone (rawValue?: string[], resolver?: AbstractResolver): CommandOption
{ {
// Call own constructor, important to do it like this in order to preserve any potentially extended classes // Call own constructor, important to do it like this in order to preserve any potentially extended classes
// eslint-disable-next-line new-parens, no-extra-parens // eslint-disable-next-line new-parens, no-extra-parens

View File

@ -29,7 +29,7 @@
// | 'POINTS' // | 'POINTS'
import CommandOption from '../classes/CommandOption.js'; import CommandOption from '../classes/CommandOption.js';
import IResolver from './Resolver.js'; import AbstractResolver from './Resolver.js';
enum OptionType { enum OptionType {
SUB_COMMAND, SUB_COMMAND,
@ -130,11 +130,7 @@ interface ICommandOption {
rawValue?: string[] rawValue?: string[]
aliased: boolean aliased: boolean
// resolver?: IResolver<unknown, unknown, unknown, unknown>|undefined clone(rawValue?: string[], resolver?: AbstractResolver): CommandOption
// private _options?: CommandOptionDefinition
clone(rawValue?: string[], resolver?: IResolver): CommandOption
parse(guild: unknown): Promise<ParseResult> parse(guild: unknown): Promise<ParseResult>

View File

@ -1,4 +1,7 @@
interface IResolver { import timestring from '@navy.gif/timestring';
abstract class AbstractResolver
{
/** /**
* Should resolve to a user abstraction * Should resolve to a user abstraction
@ -6,9 +9,9 @@ interface IResolver {
* @param {string} resolveable * @param {string} resolveable
* @param {boolean} [strict] * @param {boolean} [strict]
* @return {User} {User} * @return {User} {User}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveUser<User>(resolveable: string, strict?: boolean): Promise<User | null> abstract resolveUser<User>(resolveable: string, strict?: boolean): Promise<User | null>
/** /**
* Should resolve to a member abstraction * Should resolve to a member abstraction
@ -17,9 +20,9 @@ interface IResolver {
* @param {boolean} [strict] Whether to strictly match the properties, e.g. a string must directly match a username & discriminator * @param {boolean} [strict] Whether to strictly match the properties, e.g. a string must directly match a username & discriminator
* @param {Guild} guild The guild in which to look for the member * @param {Guild} guild The guild in which to look for the member
* @return {Member} {Member} * @return {Member} {Member}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveMember<Member, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Member | null> abstract resolveMember<Member, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Member | null>
/** /**
* Should resolve to a role abstraction * Should resolve to a role abstraction
@ -28,9 +31,9 @@ interface IResolver {
* @param {boolean} [strict] Whether to strictly match the name, if strict is passed partial names should match * @param {boolean} [strict] Whether to strictly match the name, if strict is passed partial names should match
* @param {Guild} [guild] The guild in which to look for the channel * @param {Guild} [guild] The guild in which to look for the channel
* @return {Channel} {Channel} * @return {Channel} {Channel}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveChannel<Channel, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Channel | null> abstract resolveChannel<Channel, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Channel | null>
/** /**
* Should resolve to a role abstraction * Should resolve to a role abstraction
@ -39,9 +42,9 @@ interface IResolver {
* @param {boolean} [strict] Whether to strictly match the name, if strict is passed partial names should match * @param {boolean} [strict] Whether to strictly match the name, if strict is passed partial names should match
* @param {Guild} [guild] The guild in which to look for the role * @param {Guild} [guild] The guild in which to look for the role
* @return {Role} {Role} * @return {Role} {Role}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveRole<Role, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Role | null> abstract resolveRole<Role, Guild>(resolveable: string, strict: boolean, guild: Guild): Promise<Role | null>
/** /**
* Should resolve to true when a truthy resolveable is passed, i.e. yes, true, on etc * Should resolve to true when a truthy resolveable is passed, i.e. yes, true, on etc
@ -50,9 +53,20 @@ interface IResolver {
* *
* @param {string} resolveable * @param {string} resolveable
* @return {boolean|null} {(boolean | null)} * @return {boolean|null} {(boolean | null)}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveBoolean(resolveable: string): boolean | null resolveBoolean (input: string | boolean): boolean | null
{
input = `${input}`.toLowerCase();
const truthy = [ 'on', 'true', 'yes', 'enable', 'y', 't' ];
const falsey = [ 'off', 'false', 'no', 'disable', 'n', 'f' ];
if (truthy.includes(input))
return true;
else if (falsey.includes(input))
return false;
return null;
}
/** /**
* Should resolve to a integer value from a string, e.g. 2w should resolve to 1209600 if seconds are user * Should resolve to a integer value from a string, e.g. 2w should resolve to 1209600 if seconds are user
@ -60,11 +74,21 @@ interface IResolver {
* *
* @param {string} resolveable * @param {string} resolveable
* @return {number} {number} * @return {number} {number}
* @memberof IResolver * @memberof AbstractResolver
*/ */
resolveTime(resolveable: string): number | null resolveTime (string: string): number | null
{
try
{
return timestring(string);
}
catch (err)
{
return null;
}
}
} }
export { IResolver }; export { AbstractResolver };
export default IResolver; export default AbstractResolver;

View File

@ -2061,6 +2061,7 @@ __metadata:
dependencies: dependencies:
"@babel/core": "npm:^7.24.3" "@babel/core": "npm:^7.24.3"
"@babel/preset-env": "npm:^7.24.3" "@babel/preset-env": "npm:^7.24.3"
"@navy.gif/timestring": "npm:^6.0.6"
"@types/node": "npm:^20.11.30" "@types/node": "npm:^20.11.30"
"@typescript-eslint/eslint-plugin": "npm:^7.4.0" "@typescript-eslint/eslint-plugin": "npm:^7.4.0"
"@typescript-eslint/parser": "npm:^7.4.0" "@typescript-eslint/parser": "npm:^7.4.0"
@ -2071,6 +2072,13 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@navy.gif/timestring@npm:^6.0.6":
version: 6.0.6
resolution: "@navy.gif/timestring@npm:6.0.6"
checksum: 10c0/da95f0db57b996b0de6d36ba4da113d09d4d6363c0c56d1cb2bdc5d4e85678a3ef9dbef8248f2af47eee8ff3fe49caf8228567448d608e6a64214e8f25bf375d
languageName: node
linkType: hard
"@nodelib/fs.scandir@npm:2.1.5": "@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5 version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5" resolution: "@nodelib/fs.scandir@npm:2.1.5"