diff --git a/src/index.ts b/src/index.ts index 6a89557..c380da9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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'; diff --git a/src/types/core.ts b/src/types/core.ts new file mode 100644 index 0000000..4ae0862 --- /dev/null +++ b/src/types/core.ts @@ -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 = { message: T }; +export type Singleton = () => T; +export type Transient = () => () => T; + +export interface CoreDependencies { + '@sern/logger'?: Singleton; + '@sern/emitter': Singleton; + '@sern/store': Singleton; + '@sern/modules': Singleton; + '@sern/errors': Singleton; +} +/** + * 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; +} +export type AnyDependencies = + | ServerlessDependencies + | WebsocketDependencies; + +//prettier-ignore +export type MapDeps = T extends [ + infer First extends keyof Deps, + ...infer Rest extends readonly unknown[], +] + ? [ + UnpackFunction, + ...(MapDeps extends [never] ? [] : MapDeps), + ] + : [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 & { name: string; description: string }; +export type Deprecated = [never, Message]; +export interface DependencyConfiguration { + exclude?: Set; + build: (root: Container, {}>) => Container; +} + +export interface ImportPayload { + module: T; + absPath: string +}; + diff --git a/src/types/handler.ts b/src/types/handler.ts index d349a9b..2bc528b 100644 --- a/src/types/handler.ts +++ b/src/types/handler.ts @@ -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 = PromiseLike | T; @@ -20,69 +17,22 @@ export type Args = ParseType<{ text: string[]; slash: SlashOptions }>; export type SlashOptions = Omit; -/** - * 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; -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 = { message: T }; -export type Singleton = () => T; -export type Transient = () => () => T; - -export interface CoreDependencies { - '@sern/logger'?: Singleton; - '@sern/emitter': Singleton; - '@sern/store': Singleton; - '@sern/modules': Singleton; - '@sern/errors': Singleton; -} -/** - * 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; -} -export type AnyDependencies = - | ServerlessDependencies - | WebsocketDependencies; export type ReplyOptions = | string | Omit | MessageReplyOptions; -//prettier-ignore -export type MapDeps = T extends [ - infer First extends keyof Deps, - ...infer Rest extends readonly unknown[], -] - ? [ - UnpackFunction, - ...(MapDeps extends [never] ? [] : MapDeps), - ] - : [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 & { name: string; description: string }; -export type Deprecated = [never, Message]; -export interface DependencyConfiguration { - exclude?: Set; - build: (root: Container, {}>) => Container; -} -export type ImportPayload = { module: T; absPath: string }; + +export type AnyDefinedModule = Processed; +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]; +}; diff --git a/src/types/module.ts b/src/types/module.ts index e133d86..a85aa43 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -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; } - -export interface TextCommand extends Module { - type: CommandType.Text; - alias?: string[]; - execute: (ctx: Context, args: ['text', string[]]) => Awaitable; +export interface CommandTypeModule extends Module { + type: CommandType +} +export interface EventTypeModule extends Module { + type: EventType +} +export interface SernEventCommand + extends Module { + name?: T; + type: EventType.Sern; + execute(...args: SernEventsMapping[T]): Awaitable; +} +export interface ExternalEventCommand extends Module { + name?: string; + emitter: string; + type: EventType.External; + execute(...args: unknown[]): Awaitable; } -export interface SlashCommand extends Module { - type: CommandType.Slash; - description: string; - options?: SernOptionsData[]; - execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable; -} - -export interface BothCommand extends Module { - type: CommandType.Both; - alias?: string[]; - description: string; - options?: SernOptionsData[]; - execute: (ctx: Context, args: Args) => Awaitable; -} export interface ContextMenuUser extends Module { type: CommandType.CtxUser; @@ -105,32 +115,102 @@ export interface ModalSubmitCommand extends Module { } export interface AutocompleteCommand - extends Omit { + extends Omit { onEvent: ControlPlugin[]; execute: (ctx: AutocompleteInteraction) => Awaitable; } -export interface SernEventCommand - extends Module { - name?: T; - type: EventType.Sern; - execute(...args: SernEventsMapping[T]): Awaitable; -} - export interface DiscordEventCommand extends Module { name?: T; type: EventType.Discord; execute(...args: ClientEvents[T]): Awaitable; } - -export interface ExternalEventCommand extends Module { - name?: string; - emitter: string; - type: EventType.External; - execute(...args: unknown[]): Awaitable; +export interface TextCommand extends Module { + type: CommandType.Text; + alias?: string[]; + execute: (ctx: Context, args: ['text', string[]]) => Awaitable; } +export interface SlashCommand extends Module { + type: CommandType.Slash; + description: string; + options?: SernOptionsData[]; + execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable; +} + +export interface BothCommand extends Module { + type: CommandType.Both; + alias?: string[]; + description: string; + options?: SernOptionsData[]; + execute: (ctx: Context, args: Args) => Awaitable; +} +export interface CommandArgsMatrix { + [CommandType.Text]: { + [PluginType.Control]: [Context, ['text', string[]]]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.Slash]: { + [PluginType.Control]: [Context, ['slash', /* library coupled */ SlashOptions]]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.Both]: { + [PluginType.Control]: [Context, Args]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.CtxMsg]: { + [PluginType.Control]: [/* library coupled */ MessageContextMenuCommandInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.CtxUser]: { + [PluginType.Control]: [/* library coupled */ UserContextMenuCommandInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.Button]: { + [PluginType.Control]: [/* library coupled */ ButtonInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.StringSelect]: { + [PluginType.Control]: [/* library coupled */ StringSelectMenuInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.RoleSelect]: { + [PluginType.Control]: [/* library coupled */ RoleSelectMenuInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.ChannelSelect]: { + [PluginType.Control]: [/* library coupled */ ChannelSelectMenuInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.MentionableSelect]: { + [PluginType.Control]: [/* library coupled */ MentionableSelectMenuInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.UserSelect]: { + [PluginType.Control]: [/* library coupled */ UserSelectMenuInteraction]; + [PluginType.Init]: [InitArgs>]; + }; + [CommandType.Modal]: { + [PluginType.Control]: [/* library coupled */ ModalSubmitInteraction]; + [PluginType.Init]: [InitArgs>]; + }; +}; + +export interface EventArgsMatrix { + [EventType.Discord]: { + [PluginType.Control]: /* library coupled */ ClientEvents[keyof ClientEvents]; + [PluginType.Init]: [InitArgs>]; + }; + [EventType.Sern]: { + [PluginType.Control]: [Payload]; + [PluginType.Init]: [InitArgs>]; + }; + [EventType.External]: { + [PluginType.Control]: unknown[]; + [PluginType.Init]: [InitArgs>]; + }; +}; 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; + [T in CommandType]: Omit; }; export type EventModulesNoPlugins = { - [T in EventType]: Omit; + [T in EventType]: Omit; }; export type InputEvent = { diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 49822fb..7c1ab44 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -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; export type VoidResult = Result;