mirror of
https://github.com/sern-handler/handler
synced 2026-07-05 14:09:39 +00:00
feat: shrink package size, improve dev deps, esm and cjs support (#98)
* chore: fix tsc predicate type checking * build: add tsup as bundler * chore: revert text * chore: fix predicates.ts, update dependencies, bump version * docs: update example * build: update dependencies * fix: crash on collectors (#89) * fix: crash on collectors * feat: bump version for bug fix * fix: crash on collectors pt * docs: adding some documentation for docasaurus * docs: add errors.ts comments * docs: refactor comments * docs: adding examples * feat: refresh package-lock.json * refactor: destructure and clean namespaces * feat: add regen package.json script * feat: add tsup, remove tsc, add scripts * feat: update ts-results import style * feat: readd typescript because idk if i should * feat: breakup tsconfigs and add tsup config * feat: add esm json tsconfig to git * build: update dependencies and move to ts-result-es * feat: remove unused function * feat: update ts-results for esm/cjs interop! * revert: remove version.txt * build: goodbye tsc, hello tsup * build: moving discord.js as dev dependency * style: requested changes * feat: add tsc back ( i missed you ) * build: bump version -> 1.0.0 * feat: syncing to main * style: pretty * feat: fix tsconfig issues with tsup * revert: remove ExternallyUsed * feat: update scripts * build: update tsup and pkg-lock.json * feat: refresh package-lock.json * feat: test
This commit is contained in:
@@ -59,24 +59,24 @@ export default class InteractionHandler extends EventsHandler<{
|
||||
|
||||
override init() {
|
||||
this.discordEvent.subscribe({
|
||||
next: interaction => {
|
||||
if (isMessageComponent(interaction)) {
|
||||
const mod = Files.MessageCompCommands[interaction.componentType].get(
|
||||
interaction.customId,
|
||||
next: event => {
|
||||
if (isMessageComponent(event)) {
|
||||
const mod = Files.MessageCompCommands[event.componentType].get(
|
||||
event.customId,
|
||||
);
|
||||
this.setState({ event: interaction, mod });
|
||||
} else if (isApplicationCommand(interaction) || isAutocomplete(interaction)) {
|
||||
this.setState({ event, mod });
|
||||
} else if (isApplicationCommand(event) || isAutocomplete(event)) {
|
||||
const mod =
|
||||
Files.ApplicationCommands[interaction.commandType].get(
|
||||
interaction.commandName,
|
||||
) ?? Files.BothCommands.get(interaction.commandName);
|
||||
this.setState({ event: interaction, mod });
|
||||
} else if (isModalSubmit(interaction)) {
|
||||
Files.ApplicationCommands[event.commandType].get(
|
||||
event.commandName,
|
||||
) ?? Files.BothCommands.get(event.commandName);
|
||||
this.setState({ event, mod });
|
||||
} else if (isModalSubmit(event)) {
|
||||
/**
|
||||
* maybe move modal submits into message component object maps?
|
||||
*/
|
||||
const mod = Files.ModalSubmitCommands.get(interaction.customId);
|
||||
this.setState({ event: interaction, mod });
|
||||
const mod = Files.ModalSubmitCommands.get(event.customId);
|
||||
this.setState({ event, mod });
|
||||
} else {
|
||||
throw Error('This interaction is not supported yet');
|
||||
}
|
||||
@@ -96,31 +96,31 @@ export default class InteractionHandler extends EventsHandler<{
|
||||
}
|
||||
}
|
||||
|
||||
protected processModules(payload: { event: Interaction; mod: CommandModule }) {
|
||||
return match(payload.mod)
|
||||
protected processModules({ mod, event }: { event: Interaction; mod: CommandModule }) {
|
||||
return match(mod)
|
||||
.with(
|
||||
{ type: P.union(CommandType.Slash, CommandType.Both) },
|
||||
applicationCommandDispatcher(payload.event),
|
||||
applicationCommandDispatcher(event),
|
||||
)
|
||||
.with(
|
||||
{ type: CommandType.Modal },
|
||||
modalCommandDispatcher(payload.event as ModalSubmitInteraction),
|
||||
modalCommandDispatcher(event as ModalSubmitInteraction),
|
||||
)
|
||||
.with(
|
||||
{ type: CommandType.Button },
|
||||
buttonCommandDispatcher(payload.event as ButtonInteraction),
|
||||
buttonCommandDispatcher(event as ButtonInteraction),
|
||||
)
|
||||
.with(
|
||||
{ type: CommandType.MenuSelect },
|
||||
selectMenuCommandDispatcher(payload.event as SelectMenuInteraction),
|
||||
selectMenuCommandDispatcher(event as SelectMenuInteraction),
|
||||
)
|
||||
.with(
|
||||
{ type: CommandType.MenuUser },
|
||||
ctxMenuUserDispatcher(payload.event as UserContextMenuCommandInteraction),
|
||||
ctxMenuUserDispatcher(event as UserContextMenuCommandInteraction),
|
||||
)
|
||||
.with(
|
||||
{ type: CommandType.MenuMsg },
|
||||
ctxMenuMsgDispatcher(payload.event as MessageContextMenuCommandInteraction),
|
||||
ctxMenuMsgDispatcher(event as MessageContextMenuCommandInteraction),
|
||||
)
|
||||
.otherwise(() => {
|
||||
throw Error(SernError.MismatchModule);
|
||||
|
||||
@@ -2,31 +2,11 @@ import type { Message } from 'discord.js';
|
||||
import { from, Observable, of, tap, throwError } from 'rxjs';
|
||||
import { SernError } from '../structures/errors';
|
||||
import type { Module, CommandModuleDefs, CommandModule } from '../structures/module';
|
||||
import { correctModuleType } from '../utilities/predicates';
|
||||
import type { Result } from 'ts-results';
|
||||
import type { Result } from 'ts-results-es';
|
||||
import type { CommandType } from '../structures/enums';
|
||||
import type Wrapper from '../structures/wrapper';
|
||||
import { PayloadType } from '../structures/enums';
|
||||
|
||||
export function filterCorrectModule<T extends keyof CommandModuleDefs>(cmdType: T) {
|
||||
return (src: Observable<Module | undefined>) =>
|
||||
new Observable<CommandModuleDefs[T]>(subscriber => {
|
||||
return src.subscribe({
|
||||
next(mod) {
|
||||
if (mod === undefined) {
|
||||
return throwError(() => SernError.UndefinedModule);
|
||||
}
|
||||
if (correctModuleType(mod, cmdType)) {
|
||||
subscriber.next(mod!);
|
||||
} else {
|
||||
return throwError(() => SernError.MismatchModule);
|
||||
}
|
||||
},
|
||||
error: e => subscriber.error(e),
|
||||
complete: () => subscriber.complete(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function ignoreNonBot(prefix: string) {
|
||||
return (src: Observable<Message>) =>
|
||||
|
||||
@@ -11,7 +11,7 @@ import { processCommandPlugins } from './userDefinedEventsHandling';
|
||||
import type { Awaitable } from 'discord.js';
|
||||
import { SernError } from '../structures/errors';
|
||||
import { match } from 'ts-pattern';
|
||||
import { Err, Ok, type Result } from 'ts-results';
|
||||
import { type Result, Err, Ok } from 'ts-results-es';
|
||||
import { ApplicationCommandType, ComponentType } from 'discord.js';
|
||||
|
||||
export default class ReadyHandler extends EventsHandler<{
|
||||
@@ -46,7 +46,7 @@ export default class ReadyHandler extends EventsHandler<{
|
||||
if (allPluginsSuccessful) {
|
||||
const res = registerModule(payload.mod);
|
||||
if (res.err) {
|
||||
throw Error(SernError.NonValidModuleType);
|
||||
throw Error(SernError.InvalidModuleType);
|
||||
}
|
||||
wrapper.sernEmitter?.emit('module.register', {
|
||||
type: PayloadType.Success,
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
* The goal of plugins is to organize commands and
|
||||
* provide extensions to repetitive patterns
|
||||
* examples include refreshing modules,
|
||||
* categorizing commands, cooldowns, permissions, etc.
|
||||
* categorizing commands, cool-downs, permissions, etc.
|
||||
* Plugins are reminiscent of middleware in express.
|
||||
*/
|
||||
|
||||
import type { AutocompleteInteraction, Awaitable, Client, ClientEvents } from 'discord.js';
|
||||
import type { Err, Ok, Result } from 'ts-results';
|
||||
import type { CommandType, DefinitelyDefined, Override, SernEventsMapping } from '../..';
|
||||
import { EventType, PluginType } from '../..';
|
||||
import type { Result, Ok, Err } from 'ts-results-es';
|
||||
import type { CommandType, DefinitelyDefined, Override, SernEventsMapping } from '../../index';
|
||||
import { EventType, PluginType } from '../../index';
|
||||
import type { BaseModule, CommandModuleDefs, EventModuleDefs } from '../structures/module';
|
||||
import type { EventEmitter } from 'events';
|
||||
import type {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type Wrapper from './structures/wrapper';
|
||||
import { Err, Ok } from 'ts-results';
|
||||
import { Err, Ok } from 'ts-results-es';
|
||||
import { ExternalEventEmitters } from './utilities/readFile';
|
||||
import type { EventEmitter } from 'events';
|
||||
import { processEvents } from './events/userDefinedEventsHandling';
|
||||
@@ -20,8 +20,16 @@ import MessageHandler from './events/messageHandler';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param wrapper options to pass into sern.
|
||||
* Function to start the handler up.
|
||||
* @param wrapper Options to pass into sern.
|
||||
* Function to start the handler up
|
||||
* @example
|
||||
* ```ts title="src/index.ts"
|
||||
* Sern.init({
|
||||
* client,
|
||||
* defaultPrefix: '!',
|
||||
* commands: 'dist/commands',
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export function init(wrapper: Wrapper) {
|
||||
const { events } = wrapper;
|
||||
@@ -40,20 +48,21 @@ export function init(wrapper: Wrapper) {
|
||||
* As there are infinite possibilities to adding external event emitters,
|
||||
* Most types aren't provided and are as narrow as possibly can.
|
||||
* @example
|
||||
* ```ts title="src/index.ts"
|
||||
* //Add this before initiating Sern!
|
||||
* Sern.addExternal(new Level())
|
||||
* ```
|
||||
* Sern.addExternal(new Level())
|
||||
* @example
|
||||
* ```ts title="events/level.ts"
|
||||
* export default eventModule({
|
||||
* emitter: 'Level',
|
||||
* type : EventType.External,
|
||||
* name: 'error',
|
||||
* execute(args) {
|
||||
* console.log(args)
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
* ```
|
||||
* // events/level.ts
|
||||
* export default eventModule({
|
||||
* emitter: 'Level',
|
||||
* type : EventType.External,
|
||||
* name: 'error',
|
||||
* execute(args) {
|
||||
* console.log(args)
|
||||
* }
|
||||
* })
|
||||
*
|
||||
*/
|
||||
export function addExternal<T extends EventEmitter>(emitter: T) {
|
||||
if (ExternalEventEmitters.has(emitter.constructor.name)) {
|
||||
@@ -62,11 +71,18 @@ export function addExternal<T extends EventEmitter>(emitter: T) {
|
||||
ExternalEventEmitters.set(emitter.constructor.name, emitter);
|
||||
}
|
||||
|
||||
/**
|
||||
* The object passed into every plugin to control a command's behavior
|
||||
*/
|
||||
export const controller = {
|
||||
next: () => Ok.EMPTY,
|
||||
stop: () => Err.EMPTY,
|
||||
};
|
||||
|
||||
/**
|
||||
* The wrapper function to define command modules for sern
|
||||
* @param mod
|
||||
*/
|
||||
export function commandModule(mod: InputCommandModule): CommandModule {
|
||||
const onEvent: EventPlugin[] = [];
|
||||
const plugins: CommandPlugin[] = [];
|
||||
@@ -84,6 +100,10 @@ export function commandModule(mod: InputCommandModule): CommandModule {
|
||||
plugins,
|
||||
} as CommandModule;
|
||||
}
|
||||
/**
|
||||
* The wrapper function to define event modules for sern
|
||||
* @param mod
|
||||
*/
|
||||
export function eventModule(mod: InputEventModule): EventModule {
|
||||
const onEvent: EventModuleEventPluginDefs[EventType][] = [];
|
||||
const plugins: EventModuleCommandPluginDefs[EventType][] = [];
|
||||
|
||||
@@ -11,9 +11,8 @@ import type {
|
||||
TextBasedChannel,
|
||||
User,
|
||||
} from 'discord.js';
|
||||
import { None, Option, Some } from 'ts-results';
|
||||
import { type Option, None, Some } from 'ts-results-es';
|
||||
import type { Nullish } from '../../types/handler';
|
||||
import { ExternallyUsed } from '../utilities/externallyUsed';
|
||||
import { SernError } from './errors';
|
||||
|
||||
function firstSome<T>(...args: Option<T>[]): Nullish<T> {
|
||||
@@ -42,7 +41,6 @@ export default class Context {
|
||||
* CommandType.Slash or the event fired in a Both command was
|
||||
* ChatInputCommandInteraction
|
||||
*/
|
||||
@ExternallyUsed
|
||||
public get message() {
|
||||
return this.oMsg.expect(SernError.MismatchEvent);
|
||||
}
|
||||
@@ -51,12 +49,10 @@ export default class Context {
|
||||
* CommandType.Text or the event fired in a Both command was
|
||||
* Message
|
||||
*/
|
||||
@ExternallyUsed
|
||||
public get interaction() {
|
||||
return this.oInterac.expect(SernError.MismatchEvent);
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get id(): Snowflake {
|
||||
return firstSome(
|
||||
this.oInterac.map(i => i.id),
|
||||
@@ -64,7 +60,6 @@ export default class Context {
|
||||
)!;
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get channel(): Nullish<TextBasedChannel> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.channel),
|
||||
@@ -72,7 +67,6 @@ export default class Context {
|
||||
);
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get user(): User {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.author),
|
||||
@@ -80,7 +74,6 @@ export default class Context {
|
||||
)!;
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get createdTimestamp(): number {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.createdTimestamp),
|
||||
@@ -88,7 +81,6 @@ export default class Context {
|
||||
)!;
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get guild(): Guild {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guild),
|
||||
@@ -96,7 +88,6 @@ export default class Context {
|
||||
)!;
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get guildId(): Snowflake {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.guildId),
|
||||
@@ -107,7 +98,6 @@ export default class Context {
|
||||
/*
|
||||
* interactions can return APIGuildMember if the guild it is emitted from is not cached
|
||||
*/
|
||||
@ExternallyUsed
|
||||
public get member(): Nullish<GuildMember | APIGuildMember> {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.member),
|
||||
@@ -115,7 +105,6 @@ export default class Context {
|
||||
);
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get client(): Client {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.client),
|
||||
@@ -123,7 +112,6 @@ export default class Context {
|
||||
)!;
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public get inGuild(): boolean {
|
||||
return firstSome(
|
||||
this.oMsg.map(m => m.inGuild()),
|
||||
@@ -138,12 +126,10 @@ export default class Context {
|
||||
return new Context(Some(wrappable), None);
|
||||
}
|
||||
|
||||
@ExternallyUsed
|
||||
public isEmpty() {
|
||||
return this.oMsg.none && this.oInterac.none;
|
||||
}
|
||||
//Make queueable
|
||||
@ExternallyUsed
|
||||
public reply(
|
||||
content: string | Omit<InteractionReplyOptions, 'fetchReply'> | ReplyMessageOptions,
|
||||
) {
|
||||
|
||||
@@ -1,30 +1,119 @@
|
||||
/**
|
||||
* @enum { number };
|
||||
* @enum { number }
|
||||
* @example
|
||||
* ```ts
|
||||
* export default commandModule({
|
||||
* // highlight-next-line
|
||||
* type : CommandType.Text,
|
||||
* name : 'a text command'
|
||||
* execute(message) {
|
||||
* console.log(message.content)
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export enum CommandType {
|
||||
/**
|
||||
* The CommandType for text commands
|
||||
*/
|
||||
Text = 0b00000000001,
|
||||
/**
|
||||
* The CommandType for slash commands
|
||||
*/
|
||||
Slash = 0b00000000010,
|
||||
/**
|
||||
* The CommandType for hybrid commands, text and slash
|
||||
*/
|
||||
Both = 0b0000011,
|
||||
/**
|
||||
* The CommandType for UserContextMenuInteraction commands
|
||||
*/
|
||||
MenuUser = 0b00000000100,
|
||||
/**
|
||||
* The CommandType for MessageContextMenuInteraction commands
|
||||
*/
|
||||
MenuMsg = 0b0000001000,
|
||||
/**
|
||||
* The CommandType for ButtonInteraction commands
|
||||
*/
|
||||
Button = 0b00000010000,
|
||||
/**
|
||||
* The CommandType for SelectMenuInteraction commands
|
||||
*/
|
||||
MenuSelect = 0b00000100000,
|
||||
/**
|
||||
* The CommandType for ModalSubmitInteraction commands
|
||||
*/
|
||||
Modal = 0b00001000000,
|
||||
}
|
||||
|
||||
/**
|
||||
* @enum { number }
|
||||
* @example
|
||||
* ```ts
|
||||
* export default eventModule({
|
||||
* //highlight-next-line
|
||||
* type : EventType.Discord,
|
||||
* name : 'guildMemberAdd'
|
||||
* execute(member : GuildMember) {
|
||||
* console.log(member)
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export enum EventType {
|
||||
/**
|
||||
* The EventType for handling discord events
|
||||
*/
|
||||
Discord = 0b01,
|
||||
/**
|
||||
* The EventType for handling sern events
|
||||
*/
|
||||
Sern = 0b10,
|
||||
/**
|
||||
* The EventType for handling external events.
|
||||
* Could be for example, `process` events, database events
|
||||
*/
|
||||
External = 0b11,
|
||||
}
|
||||
|
||||
/**
|
||||
* @enum { number }
|
||||
* @example
|
||||
* ```ts
|
||||
* export default function myPlugin() : EventPlugin<CommandType.Text> {
|
||||
* //highlight-next-line
|
||||
* type : PluginType.Event,
|
||||
* execute([ctx, args], controller) {
|
||||
* return controller.next();
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export enum PluginType {
|
||||
/**
|
||||
* The PluginType for CommandPlugins
|
||||
*/
|
||||
Command = 0b01,
|
||||
/**
|
||||
* The PluginType for EventPlugins
|
||||
*/
|
||||
Event = 0b10,
|
||||
}
|
||||
|
||||
/**
|
||||
* @enum { string }
|
||||
*/
|
||||
export enum PayloadType {
|
||||
/**
|
||||
* The PayloadType for a SernEmitter success event
|
||||
*/
|
||||
Success = 'success',
|
||||
/**
|
||||
* The PayloadType for a SernEmitter failure event
|
||||
*/
|
||||
Failure = 'failure',
|
||||
/**
|
||||
* The PayloadType for a SernEmitter warning event
|
||||
*/
|
||||
Warning = 'warning',
|
||||
}
|
||||
|
||||
@@ -1,9 +1,34 @@
|
||||
/**
|
||||
* @enum { string }
|
||||
*/
|
||||
export enum SernError {
|
||||
NonValidModuleType = 'Detected an unknown module type',
|
||||
UndefinedModule = `A module could not be detected at`,
|
||||
/**
|
||||
* Throws when registering an invalid module.
|
||||
* This means it is undefined or an invalid command type was provided
|
||||
*/
|
||||
InvalidModuleType = 'Detected an unknown module type',
|
||||
/**
|
||||
* Attempted to lookup module in command module store. Nothing was found!
|
||||
*/
|
||||
UndefinedModule = `A module could not be detected`,
|
||||
/**
|
||||
* Attempted to lookup module in command module store. Nothing was found!
|
||||
*/
|
||||
MismatchModule = `A module type mismatched with event emitted!`,
|
||||
/**
|
||||
* Unsupported interaction at this moment.
|
||||
*/
|
||||
NotSupportedInteraction = `This interaction is not supported.`,
|
||||
/**
|
||||
* One plugin called `controller.stop()` (end command execution / loading)
|
||||
*/
|
||||
PluginFailure = `A plugin failed to call controller.next()`,
|
||||
/**
|
||||
* A crash that occurs when accessing an invalid property of Context
|
||||
*/
|
||||
MismatchEvent = `You cannot use message when an interaction fired or vice versa`,
|
||||
/**
|
||||
* Unsupported feature attempted to access at this time
|
||||
*/
|
||||
NotSupportedYet = `This feature is not supported yet`,
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import type {
|
||||
import type { Awaitable, ClientEvents } from 'discord.js';
|
||||
import type { EventType } from './enums';
|
||||
|
||||
/*
|
||||
* Mapped type to generate all sern event modules
|
||||
*/
|
||||
export type SernEventCommand<T extends keyof SernEventsMapping = keyof SernEventsMapping> =
|
||||
Override<
|
||||
BaseModule,
|
||||
@@ -22,6 +25,9 @@ export type SernEventCommand<T extends keyof SernEventsMapping = keyof SernEvent
|
||||
execute(...args: SernEventsMapping[T]): Awaitable<void | unknown>;
|
||||
}
|
||||
>;
|
||||
/*
|
||||
* Mapped type to generate all discord event modules
|
||||
*/
|
||||
export type DiscordEventCommand<T extends keyof ClientEvents = keyof ClientEvents> = Override<
|
||||
BaseModule,
|
||||
{
|
||||
@@ -32,7 +38,9 @@ export type DiscordEventCommand<T extends keyof ClientEvents = keyof ClientEvent
|
||||
execute(...args: ClientEvents[T]): Awaitable<void | unknown>;
|
||||
}
|
||||
>;
|
||||
|
||||
/*
|
||||
* Type for any event emitter that can be handled by sern
|
||||
*/
|
||||
export type ExternalEventCommand = Override<
|
||||
BaseModule,
|
||||
{
|
||||
|
||||
@@ -30,7 +30,6 @@ export interface BaseModule {
|
||||
execute: (ctx: Context, args: Args) => Awaitable<void | unknown>;
|
||||
}
|
||||
|
||||
//possible refactoring types into interfaces and not types
|
||||
export type TextCommand = Override<
|
||||
BaseModule,
|
||||
{
|
||||
@@ -118,7 +117,6 @@ export type ModalSubmitCommand = Override<
|
||||
// Autocomplete commands are a little different
|
||||
// They can't have command plugins as they are
|
||||
// in conjunction with chat input commands
|
||||
// TODO: possibly in future, allow Autocmp commands in separate files?
|
||||
export type AutocompleteCommand = Override<
|
||||
BaseModule,
|
||||
{
|
||||
@@ -178,7 +176,7 @@ export type SernAutocompleteData = Override<
|
||||
>;
|
||||
|
||||
/**
|
||||
* Type that just uses SernAutocompleteData and not regular autocomplete
|
||||
* Type that replaces autocomplete with {@link SernAutocompleteData}
|
||||
*/
|
||||
export type BaseOptions =
|
||||
| ApplicationCommandChoicesData
|
||||
|
||||
@@ -3,13 +3,8 @@ import type SernEmitter from '../sernEmitter';
|
||||
import type { EventModule } from './module';
|
||||
|
||||
/**
|
||||
* An object to be passed into Sern.Handler constructor.
|
||||
* An object to be passed into Sern#init() function.
|
||||
* @typedef {object} Wrapper
|
||||
* @property {readonly Client} client
|
||||
* @prop { readonly SernEmitter } sernEmitter
|
||||
* @property {readonly string} defaultPrefix
|
||||
* @property {readonly string} commands
|
||||
* @prop { readonly DiscordEvent[] } events
|
||||
*/
|
||||
interface Wrapper {
|
||||
readonly client: Client;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ApplicationCommandType, ComponentType } from 'discord.js';
|
||||
import { readdirSync, statSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { from, Observable } from 'rxjs';
|
||||
import { type Observable, from, concatAll } from 'rxjs';
|
||||
import type { CommandModule } from '../structures/module';
|
||||
import { SernError } from '../structures/errors';
|
||||
import { Err, Ok, type Result } from 'ts-results';
|
||||
import { type Result, Err, Ok } from 'ts-results-es';
|
||||
import type { EventEmitter } from 'events';
|
||||
|
||||
//Maybe move this? this probably doesnt belong in utlities/
|
||||
@@ -63,15 +63,19 @@ export function buildData<T>(commandDir: string): Observable<
|
||||
>
|
||||
> {
|
||||
const commands = getCommands(commandDir);
|
||||
return from(
|
||||
commands.map(absPath => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const mod = <T | undefined>require(absPath).default;
|
||||
return from(Promise.all(commands.map(async absPath => {
|
||||
let mod : T | undefined;
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
mod = require(absPath).default;
|
||||
} catch {
|
||||
mod = (await import(`file:///` +absPath)).default;
|
||||
}
|
||||
if (mod !== undefined) {
|
||||
return Ok({ mod, absPath });
|
||||
} else return Err(SernError.UndefinedModule);
|
||||
}),
|
||||
);
|
||||
})
|
||||
)).pipe(concatAll());
|
||||
}
|
||||
|
||||
export function getCommands(dir: string): string[] {
|
||||
|
||||
Reference in New Issue
Block a user