mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
chore: modularize and split typings
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
export { default as SernEmitter } from './core/sernEmitter';
|
||||
export * as Sern from './handler/sern';
|
||||
export * from './types/handler';
|
||||
export * from './types/module';
|
||||
export * from './types/plugin';
|
||||
export * from './core'
|
||||
export * from './core';
|
||||
export { controller } from './handler/sern'
|
||||
export { commandModule, eventModule, discordEvent } from './commands'
|
||||
export { default as Context } from './classic/context'
|
||||
export { commandModule, eventModule } from './commands'
|
||||
export { Context } from './classic/context'
|
||||
export * from './classic/module';
|
||||
|
||||
62
src/types/core.ts
Normal file
62
src/types/core.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { type EventEmitter } from "node:events";
|
||||
import { ErrorHandling, Logging, ModuleManager, ModuleStore, SernEmitter } from "../core";
|
||||
import { Container, UnpackFunction } from "iti";
|
||||
|
||||
export type ServerlessDependencyList = [ SernEmitter,ErrorHandling, Logging | undefined, ModuleManager];
|
||||
export type WebsocketDependencyList = [SernEmitter,ErrorHandling, Logging | undefined, ModuleManager, EventEmitter];
|
||||
/**
|
||||
* After modules are transformed, name and description are given default values if none
|
||||
* are provided to Module. This type represents that transformation
|
||||
*/
|
||||
|
||||
export type LogPayload<T = unknown> = { message: T };
|
||||
export type Singleton<T> = () => T;
|
||||
export type Transient<T> = () => () => T;
|
||||
|
||||
export interface CoreDependencies {
|
||||
'@sern/logger'?: Singleton<Logging>;
|
||||
'@sern/emitter': Singleton<SernEmitter>;
|
||||
'@sern/store': Singleton<ModuleStore>;
|
||||
'@sern/modules': Singleton<ModuleManager>;
|
||||
'@sern/errors': Singleton<ErrorHandling>;
|
||||
}
|
||||
/**
|
||||
* To support older versions. Type alias for WebsocketDependencies
|
||||
* @deprecated
|
||||
*/
|
||||
export type Dependencies = WebsocketDependencies
|
||||
export interface ServerlessDependencies extends CoreDependencies {
|
||||
'@sern/client': never
|
||||
}
|
||||
|
||||
export interface WebsocketDependencies extends CoreDependencies {
|
||||
'@sern/client': Singleton<EventEmitter>;
|
||||
}
|
||||
export type AnyDependencies =
|
||||
| ServerlessDependencies
|
||||
| WebsocketDependencies;
|
||||
|
||||
//prettier-ignore
|
||||
export type MapDeps<Deps extends AnyDependencies, T extends readonly unknown[]> = T extends [
|
||||
infer First extends keyof Deps,
|
||||
...infer Rest extends readonly unknown[],
|
||||
]
|
||||
? [
|
||||
UnpackFunction<Deps[First]>,
|
||||
...(MapDeps<Deps, Rest> extends [never] ? [] : MapDeps<Deps, Rest>),
|
||||
]
|
||||
: [never];
|
||||
//Basically, '@sern/client' | '@sern/store' | '@sern/modules' | '@sern/error' | '@sern/emitter' will be provided defaults, and you can exclude the rest
|
||||
export type OptionalDependencies = '@sern/logger';
|
||||
export type Processed<T> = T & { name: string; description: string };
|
||||
export type Deprecated<Message extends string> = [never, Message];
|
||||
export interface DependencyConfiguration<T extends AnyDependencies> {
|
||||
exclude?: Set<OptionalDependencies>;
|
||||
build: (root: Container<Omit<AnyDependencies, '@sern/client'>, {}>) => Container<T, {}>;
|
||||
}
|
||||
|
||||
export interface ImportPayload<T> {
|
||||
module: T;
|
||||
absPath: string
|
||||
};
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { CommandInteractionOptionResolver } from 'discord.js';
|
||||
import type { PayloadType } from '../core/structures/enums';
|
||||
import type { InteractionReplyOptions, MessageReplyOptions } from 'discord.js';
|
||||
import type { EventEmitter } from 'events';
|
||||
import type { CommandModule, EventModule, AnyModule } from './module';
|
||||
import type { UnpackFunction } from 'iti';
|
||||
import type { InteractionReplyOptions, MessageReplyOptions, CommandInteractionOptionResolver } from 'discord.js';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
import type { ErrorHandling, Logging, ModuleManager } from '../core/contracts';
|
||||
import type { ModuleStore } from '../core/structures/moduleStore';
|
||||
import type SernEmitter from '../core/sernEmitter';
|
||||
import type { Container } from 'iti';
|
||||
import type { SernEmitter } from '../core/sernEmitter';
|
||||
import { Processed } from './core';
|
||||
import { AnyModule, CommandModule, EventModule } from './module';
|
||||
import { PayloadType } from '../core';
|
||||
|
||||
export type Awaitable<T> = PromiseLike<T> | T;
|
||||
|
||||
@@ -20,69 +17,22 @@ export type Args = ParseType<{ text: string[]; slash: SlashOptions }>;
|
||||
|
||||
export type SlashOptions = Omit<CommandInteractionOptionResolver, 'getMessage' | 'getFocused'>;
|
||||
|
||||
/**
|
||||
* After modules are transformed, name and description are given default values if none
|
||||
* are provided to Module. This type represents that transformation
|
||||
*/
|
||||
export type AnyDefinedModule = Processed<CommandModule | EventModule>;
|
||||
export type Payload =
|
||||
| { type: PayloadType.Success; module: AnyModule }
|
||||
| { type: PayloadType.Failure; module?: AnyModule; reason: string | Error }
|
||||
| { type: PayloadType.Warning; reason: string };
|
||||
export type SernEventsMapping = {
|
||||
'module.register': [Payload];
|
||||
'module.activate': [Payload];
|
||||
error: [Payload];
|
||||
warning: [Payload];
|
||||
};
|
||||
export type LogPayload<T = unknown> = { message: T };
|
||||
export type Singleton<T> = () => T;
|
||||
export type Transient<T> = () => () => T;
|
||||
|
||||
export interface CoreDependencies {
|
||||
'@sern/logger'?: Singleton<Logging>;
|
||||
'@sern/emitter': Singleton<SernEmitter>;
|
||||
'@sern/store': Singleton<ModuleStore>;
|
||||
'@sern/modules': Singleton<ModuleManager>;
|
||||
'@sern/errors': Singleton<ErrorHandling>;
|
||||
}
|
||||
/**
|
||||
* To support older versions. Type alias for WebsocketDependencies
|
||||
* @deprecated
|
||||
*/
|
||||
export type Dependencies = WebsocketDependencies
|
||||
export interface ServerlessDependencies extends CoreDependencies {
|
||||
'@sern/client': never
|
||||
}
|
||||
|
||||
export interface WebsocketDependencies extends CoreDependencies {
|
||||
'@sern/client': Singleton<EventEmitter>;
|
||||
}
|
||||
export type AnyDependencies =
|
||||
| ServerlessDependencies
|
||||
| WebsocketDependencies;
|
||||
|
||||
export type ReplyOptions =
|
||||
| string
|
||||
| Omit<InteractionReplyOptions, 'fetchReply'>
|
||||
| MessageReplyOptions;
|
||||
//prettier-ignore
|
||||
export type MapDeps<Deps extends AnyDependencies, T extends readonly unknown[]> = T extends [
|
||||
infer First extends keyof Deps,
|
||||
...infer Rest extends readonly unknown[],
|
||||
]
|
||||
? [
|
||||
UnpackFunction<Deps[First]>,
|
||||
...(MapDeps<Deps, Rest> extends [never] ? [] : MapDeps<Deps, Rest>),
|
||||
]
|
||||
: [never];
|
||||
//Basically, '@sern/client' | '@sern/store' | '@sern/modules' | '@sern/error' | '@sern/emitter' will be provided defaults, and you can exclude the rest
|
||||
export type OptionalDependencies = '@sern/logger';
|
||||
export type Processed<T> = T & { name: string; description: string };
|
||||
export type Deprecated<Message extends string> = [never, Message];
|
||||
export interface DependencyConfiguration<T extends AnyDependencies> {
|
||||
exclude?: Set<OptionalDependencies>;
|
||||
build: (root: Container<Omit<AnyDependencies, '@sern/client'>, {}>) => Container<T, {}>;
|
||||
}
|
||||
|
||||
export type ImportPayload<T> = { module: T; absPath: string };
|
||||
|
||||
export type AnyDefinedModule = Processed<CommandModule | EventModule>;
|
||||
export type Payload =
|
||||
| { type: PayloadType.Success; module: AnyModule }
|
||||
| { type: PayloadType.Failure; module?: AnyModule; reason: string | Error }
|
||||
| { type: PayloadType.Warning; reason: string };
|
||||
|
||||
export interface SernEventsMapping {
|
||||
'module.register': [Payload];
|
||||
'module.activate': [Payload];
|
||||
error: [Payload];
|
||||
warning: [Payload];
|
||||
};
|
||||
|
||||
@@ -8,26 +8,37 @@ import type {
|
||||
ApplicationCommandOptionType,
|
||||
ApplicationCommandSubCommandData,
|
||||
ApplicationCommandSubGroupData,
|
||||
AutocompleteInteraction,
|
||||
BaseApplicationCommandOptionsData,
|
||||
} from 'discord.js';
|
||||
import {
|
||||
AutocompleteInteraction,
|
||||
ButtonInteraction,
|
||||
ChannelSelectMenuInteraction,
|
||||
ClientEvents,
|
||||
MentionableSelectMenuInteraction,
|
||||
MessageContextMenuCommandInteraction,
|
||||
ModalSubmitInteraction,
|
||||
UserContextMenuCommandInteraction,
|
||||
ChannelSelectMenuInteraction,
|
||||
MentionableSelectMenuInteraction,
|
||||
RoleSelectMenuInteraction,
|
||||
StringSelectMenuInteraction,
|
||||
UserSelectMenuInteraction,
|
||||
} from 'discord.js';
|
||||
import { CommandType } from '../core/structures/enums';
|
||||
import type { Args, Awaitable, SlashOptions } from './handler';
|
||||
import type Context from '../handler/structures/context';
|
||||
UserContextMenuCommandInteraction,
|
||||
UserSelectMenuInteraction
|
||||
|
||||
} from "discord.js";
|
||||
import { InitArgs, } from "../core";
|
||||
import { Args, Payload, SlashOptions } from "../types/handler";
|
||||
import { Context } from "../classic/context";
|
||||
import { Processed } from "../types/core";
|
||||
import { CommandType, PluginType } from '../core/structures/enums';
|
||||
import type { Awaitable, SernEventsMapping } from './handler';
|
||||
import type { InitPlugin, ControlPlugin } from './plugin';
|
||||
import { EventType } from '../core/structures/enums';
|
||||
import type { AnyCommandPlugin, AnyEventPlugin } from './plugin';
|
||||
import type { SernEventsMapping } from './handler';
|
||||
import type { ClientEvents } from 'discord.js';
|
||||
import { sernMeta } from '../commands';
|
||||
|
||||
interface CommandMeta {
|
||||
fullPath: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Module {
|
||||
type: CommandType | EventType;
|
||||
@@ -35,29 +46,28 @@ export interface Module {
|
||||
onEvent: ControlPlugin[];
|
||||
plugins: InitPlugin[];
|
||||
description?: string;
|
||||
[sernMeta] : CommandMeta
|
||||
execute: (...args: any[]) => Awaitable<any>;
|
||||
}
|
||||
|
||||
export interface TextCommand extends Module {
|
||||
type: CommandType.Text;
|
||||
alias?: string[];
|
||||
execute: (ctx: Context, args: ['text', string[]]) => Awaitable<unknown>;
|
||||
export interface CommandTypeModule extends Module {
|
||||
type: CommandType
|
||||
}
|
||||
export interface EventTypeModule extends Module {
|
||||
type: EventType
|
||||
}
|
||||
export interface SernEventCommand<T extends keyof SernEventsMapping = keyof SernEventsMapping>
|
||||
extends Module {
|
||||
name?: T;
|
||||
type: EventType.Sern;
|
||||
execute(...args: SernEventsMapping[T]): Awaitable<unknown>;
|
||||
}
|
||||
export interface ExternalEventCommand extends Module {
|
||||
name?: string;
|
||||
emitter: string;
|
||||
type: EventType.External;
|
||||
execute(...args: unknown[]): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface SlashCommand extends Module {
|
||||
type: CommandType.Slash;
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface BothCommand extends Module {
|
||||
type: CommandType.Both;
|
||||
alias?: string[];
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: Args) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface ContextMenuUser extends Module {
|
||||
type: CommandType.CtxUser;
|
||||
@@ -105,32 +115,102 @@ export interface ModalSubmitCommand extends Module {
|
||||
}
|
||||
|
||||
export interface AutocompleteCommand
|
||||
extends Omit<Module, 'name' | 'type' | 'plugins' | 'description'> {
|
||||
extends Omit<Module, 'name' | 'type' | 'plugins' | 'description' | typeof sernMeta> {
|
||||
onEvent: ControlPlugin[];
|
||||
execute: (ctx: AutocompleteInteraction) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface SernEventCommand<T extends keyof SernEventsMapping = keyof SernEventsMapping>
|
||||
extends Module {
|
||||
name?: T;
|
||||
type: EventType.Sern;
|
||||
execute(...args: SernEventsMapping[T]): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface DiscordEventCommand<T extends keyof ClientEvents = keyof ClientEvents>
|
||||
extends Module {
|
||||
name?: T;
|
||||
type: EventType.Discord;
|
||||
execute(...args: ClientEvents[T]): Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface ExternalEventCommand extends Module {
|
||||
name?: string;
|
||||
emitter: string;
|
||||
type: EventType.External;
|
||||
execute(...args: unknown[]): Awaitable<unknown>;
|
||||
export interface TextCommand extends Module {
|
||||
type: CommandType.Text;
|
||||
alias?: string[];
|
||||
execute: (ctx: Context, args: ['text', string[]]) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface SlashCommand extends Module {
|
||||
type: CommandType.Slash;
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable<unknown>;
|
||||
}
|
||||
|
||||
export interface BothCommand extends Module {
|
||||
type: CommandType.Both;
|
||||
alias?: string[];
|
||||
description: string;
|
||||
options?: SernOptionsData[];
|
||||
execute: (ctx: Context, args: Args) => Awaitable<unknown>;
|
||||
}
|
||||
export interface CommandArgsMatrix {
|
||||
[CommandType.Text]: {
|
||||
[PluginType.Control]: [Context, ['text', string[]]];
|
||||
[PluginType.Init]: [InitArgs<Processed<TextCommand>>];
|
||||
};
|
||||
[CommandType.Slash]: {
|
||||
[PluginType.Control]: [Context, ['slash', /* library coupled */ SlashOptions]];
|
||||
[PluginType.Init]: [InitArgs<Processed<SlashCommand>>];
|
||||
};
|
||||
[CommandType.Both]: {
|
||||
[PluginType.Control]: [Context, Args];
|
||||
[PluginType.Init]: [InitArgs<Processed<BothCommand>>];
|
||||
};
|
||||
[CommandType.CtxMsg]: {
|
||||
[PluginType.Control]: [/* library coupled */ MessageContextMenuCommandInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ContextMenuMsg>>];
|
||||
};
|
||||
[CommandType.CtxUser]: {
|
||||
[PluginType.Control]: [/* library coupled */ UserContextMenuCommandInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ContextMenuUser>>];
|
||||
};
|
||||
[CommandType.Button]: {
|
||||
[PluginType.Control]: [/* library coupled */ ButtonInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ButtonCommand>>];
|
||||
};
|
||||
[CommandType.StringSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ StringSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<StringSelectCommand>>];
|
||||
};
|
||||
[CommandType.RoleSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ RoleSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<RoleSelectCommand>>];
|
||||
};
|
||||
[CommandType.ChannelSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ ChannelSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ChannelSelectCommand>>];
|
||||
};
|
||||
[CommandType.MentionableSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ MentionableSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<MentionableSelectCommand>>];
|
||||
};
|
||||
[CommandType.UserSelect]: {
|
||||
[PluginType.Control]: [/* library coupled */ UserSelectMenuInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<UserSelectCommand>>];
|
||||
};
|
||||
[CommandType.Modal]: {
|
||||
[PluginType.Control]: [/* library coupled */ ModalSubmitInteraction];
|
||||
[PluginType.Init]: [InitArgs<Processed<ModalSubmitCommand>>];
|
||||
};
|
||||
};
|
||||
|
||||
export interface EventArgsMatrix {
|
||||
[EventType.Discord]: {
|
||||
[PluginType.Control]: /* library coupled */ ClientEvents[keyof ClientEvents];
|
||||
[PluginType.Init]: [InitArgs<Processed<DiscordEventCommand>>];
|
||||
};
|
||||
[EventType.Sern]: {
|
||||
[PluginType.Control]: [Payload];
|
||||
[PluginType.Init]: [InitArgs<Processed<SernEventCommand>>];
|
||||
};
|
||||
[EventType.External]: {
|
||||
[PluginType.Control]: unknown[];
|
||||
[PluginType.Init]: [InitArgs<Processed<ExternalEventCommand>>];
|
||||
};
|
||||
};
|
||||
export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand;
|
||||
export type CommandModule =
|
||||
| TextCommand
|
||||
@@ -150,7 +230,7 @@ export type AnyModule = CommandModule | EventModule;
|
||||
|
||||
//https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union
|
||||
// Explicit Module Definitions for mapping
|
||||
export type CommandModuleDefs = {
|
||||
export interface CommandModuleDefs {
|
||||
[CommandType.Text]: TextCommand;
|
||||
[CommandType.Slash]: SlashCommand;
|
||||
[CommandType.Both]: BothCommand;
|
||||
@@ -165,7 +245,7 @@ export type CommandModuleDefs = {
|
||||
[CommandType.Modal]: ModalSubmitCommand;
|
||||
};
|
||||
|
||||
export type EventModuleDefs = {
|
||||
export interface EventModuleDefs {
|
||||
[EventType.Sern]: SernEventCommand;
|
||||
[EventType.Discord]: DiscordEventCommand;
|
||||
[EventType.External]: ExternalEventCommand;
|
||||
@@ -182,10 +262,10 @@ export interface SernAutocompleteData
|
||||
}
|
||||
|
||||
export type CommandModuleNoPlugins = {
|
||||
[T in CommandType]: Omit<CommandModuleDefs[T], 'plugins' | 'onEvent'>;
|
||||
[T in CommandType]: Omit<CommandModuleDefs[T], 'plugins' | 'onEvent' | typeof sernMeta>;
|
||||
};
|
||||
export type EventModulesNoPlugins = {
|
||||
[T in EventType]: Omit<EventModuleDefs[T], 'plugins' | 'onEvent'>;
|
||||
[T in EventType]: Omit<EventModuleDefs[T], 'plugins' | 'onEvent' | typeof sernMeta>;
|
||||
};
|
||||
|
||||
export type InputEvent = {
|
||||
|
||||
@@ -15,7 +15,8 @@ import type { Err, Ok, Result } from 'ts-results-es';
|
||||
import type { PluginType } from '../core/structures/enums';
|
||||
import type { CommandModule, EventModule } from './module';
|
||||
import type { InitArgs } from '../core/plugins';
|
||||
import type { Awaitable, Processed } from './handler';
|
||||
import type { Awaitable } from './handler';
|
||||
import { Processed } from './core';
|
||||
export type PluginResult = Awaitable<VoidResult>;
|
||||
export type VoidResult = Result<void, void>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user