mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
chore: update typings
This commit is contained in:
@@ -1,10 +1,3 @@
|
||||
import { _const } from '../utilities/functions';
|
||||
/**
|
||||
* New signature
|
||||
* @since 2.0.0
|
||||
* @param cb
|
||||
*/
|
||||
export function single<T extends () => unknown>(cb: T): T;
|
||||
/**
|
||||
* @__PURE__
|
||||
* @since 2.0.0.
|
||||
@@ -13,8 +6,8 @@ export function single<T extends () => unknown>(cb: T): T;
|
||||
* For future versions, ensure that single is being passed as a **callback!!**
|
||||
* @param cb
|
||||
*/
|
||||
export function single<T>(cb: T) {
|
||||
return () => cb;
|
||||
export function single<T>(cb: () => T) {
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { Container } from 'iti';
|
||||
import type { Dependencies, DependencyConfiguration, MapDeps } from '../../types/handler';
|
||||
import type { AnyDependencies, Dependencies, DependencyConfiguration, MapDeps } from '../../types/handler';
|
||||
import SernEmitter from '../sernEmitter';
|
||||
import { DefaultErrorHandling, DefaultLogging, DefaultModuleManager } from '../contracts';
|
||||
import { Result } from 'ts-results-es';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { createContainer } from 'iti';
|
||||
import { type Wrapper, ModuleStore, SernError } from '../structures';
|
||||
import { AnyWrapper } from '../structures/wrapper';
|
||||
|
||||
export const containerSubject = new BehaviorSubject(defaultContainer());
|
||||
|
||||
@@ -15,7 +16,7 @@ export const containerSubject = new BehaviorSubject(defaultContainer());
|
||||
* Finally, update the containerSubject with the new container state
|
||||
* @param conf
|
||||
*/
|
||||
export function composeRoot<T extends Dependencies>(conf: DependencyConfiguration<T>) {
|
||||
export function composeRoot<T extends AnyDependencies>(conf: DependencyConfiguration<T>) {
|
||||
//Get the current container. This should have no client or possible logger yet.
|
||||
const currentContainer = containerSubject.getValue();
|
||||
const excludeLogger = conf.exclude?.has('@sern/logger');
|
||||
@@ -37,7 +38,7 @@ export function composeRoot<T extends Dependencies>(conf: DependencyConfiguratio
|
||||
containerSubject.next(container as any);
|
||||
}
|
||||
|
||||
export function useContainer<T extends Dependencies>() {
|
||||
export function useContainer<const T extends AnyDependencies>() {
|
||||
const container = containerSubject.getValue() as Container<T, {}>;
|
||||
return <V extends (keyof T)[]>(...keys: [...V]) =>
|
||||
keys.map(key => Result.wrap(() => container.get(key)).unwrapOr(undefined)) as MapDeps<T, V>;
|
||||
@@ -48,7 +49,7 @@ export function useContainer<T extends Dependencies>() {
|
||||
* Please be careful as this only gets the client's current state.
|
||||
* Exposes some methods from iti
|
||||
*/
|
||||
export function useContainerRaw<T extends Dependencies>() {
|
||||
export function useContainerRaw<T extends AnyDependencies>() {
|
||||
return containerSubject.getValue() as Container<T, {}>;
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ function defaultContainer() {
|
||||
};
|
||||
})
|
||||
.add({ '@sern/emitter': () => new SernEmitter() }) as Container<
|
||||
Omit<Dependencies, '@sern/client' | '@sern/logger'>,
|
||||
Omit<AnyDependencies, '@sern/client' | '@sern/logger'>,
|
||||
{}
|
||||
>;
|
||||
}
|
||||
@@ -74,16 +75,16 @@ function defaultContainer() {
|
||||
* A way for sern to grab only the necessary dependencies.
|
||||
* Returns a function which allows for the user to call for more dependencies.
|
||||
*/
|
||||
export function makeFetcher(wrapper: Wrapper) {
|
||||
export function makeFetcher<const Dep extends AnyDependencies>(wrapper: AnyWrapper) {
|
||||
const requiredDependencyKeys = [
|
||||
'@sern/emitter',
|
||||
'@sern/client',
|
||||
'@sern/errors',
|
||||
'@sern/logger',
|
||||
] as ['@sern/emitter', '@sern/client', '@sern/errors', '@sern/logger'];
|
||||
return <Keys extends (keyof Dependencies)[]>(otherKeys: [...Keys]) =>
|
||||
return <const Keys extends (keyof Dep)[]>(otherKeys: [...Keys]) =>
|
||||
wrapper.containerConfig.get(...requiredDependencyKeys, ...otherKeys) as MapDeps<
|
||||
Dependencies,
|
||||
AnyDependencies,
|
||||
[...typeof requiredDependencyKeys, ...Keys]
|
||||
>;
|
||||
}
|
||||
|
||||
1
src/core/platform/index.ts
Normal file
1
src/core/platform/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './strategy';
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
enum DispatchType {
|
||||
export const enum DispatchType {
|
||||
Websocket,
|
||||
Serverless
|
||||
}
|
||||
@@ -8,15 +8,15 @@ export type PlatformStrategy =
|
||||
| WebsocketStrategy
|
||||
| ServerlessStrategy;
|
||||
|
||||
interface WebsocketStrategy {
|
||||
export interface WebsocketStrategy {
|
||||
type: DispatchType.Websocket;
|
||||
interactionCreate: string;
|
||||
messageCreate: string;
|
||||
ready: string;
|
||||
defaultPrefix: string;
|
||||
defaultPrefix?: string;
|
||||
}
|
||||
|
||||
interface ServerlessStrategy {
|
||||
export interface ServerlessStrategy {
|
||||
type: DispatchType.Serverless;
|
||||
endpoint: string;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
import type { Dependencies } from '../../types/handler';
|
||||
import { PlatformStrategy } from '../platform/strategy';
|
||||
import type { ServerlessDependencies, WebsocketDependencies } from '../../types/handler';
|
||||
import { DispatchType, ServerlessStrategy, WebsocketStrategy } from '../platform/strategy';
|
||||
|
||||
/**
|
||||
* @since 1.0.0
|
||||
* An object to be passed into Sern#init() function.
|
||||
* @typedef {object} Wrapper
|
||||
*/
|
||||
interface Wrapper {
|
||||
readonly platform: PlatformStrategy;
|
||||
|
||||
export interface WebsocketWrapper {
|
||||
readonly platform: WebsocketStrategy;
|
||||
commands: string;
|
||||
/**
|
||||
* @deprecated
|
||||
* Add defaultPrefix to platform field instead
|
||||
*/
|
||||
readonly defaultPrefix?: string;
|
||||
readonly commands: string;
|
||||
readonly events?: string;
|
||||
readonly containerConfig: {
|
||||
get: (...keys: (keyof Dependencies)[]) => unknown[];
|
||||
};
|
||||
* @deprecated
|
||||
* Please specify this in platform specification
|
||||
*/
|
||||
defaultPrefix?: string;
|
||||
events?: string;
|
||||
containerConfig: {
|
||||
get: (...keys: (keyof WebsocketDependencies)[]) => unknown[];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
* Type alias for WebsocketWrapper
|
||||
*/
|
||||
export type Wrapper = WebsocketWrapper
|
||||
|
||||
export interface ServerlessWrapper {
|
||||
readonly platform: ServerlessStrategy
|
||||
containerConfig: {
|
||||
get: (...keys: (keyof ServerlessDependencies)[]) => unknown[];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type AnyWrapper =
|
||||
| WebsocketWrapper
|
||||
| ServerlessWrapper
|
||||
|
||||
|
||||
export function isServerless(wrapper: AnyWrapper): wrapper is ServerlessWrapper {
|
||||
return wrapper.platform.type === DispatchType.Serverless;
|
||||
}
|
||||
export default Wrapper;
|
||||
|
||||
@@ -2,8 +2,8 @@ import type { Awaitable, Message } from 'discord.js';
|
||||
import { concatMap, EMPTY, filter, from, Observable, of, tap, throwError } from 'rxjs';
|
||||
import { Result } from 'ts-results-es';
|
||||
import type { CommandModule, EventModule, Module } from '../../types/module';
|
||||
import SernEmitter from '../sernEmitter';
|
||||
import { callPlugin, everyPluginOk, filterMapTo } from './operators';
|
||||
import { SernEmitter } from '../../core';
|
||||
import { callPlugin, everyPluginOk, filterMapTo } from '../../core/operators';
|
||||
import type { ImportPayload, Processed } from '../../types/handler';
|
||||
import type { ControlPlugin, VoidResult } from '../../types/plugin';
|
||||
|
||||
@@ -12,6 +12,7 @@ function hasPrefix(prefix: string, content: string) {
|
||||
return prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ignores messages from any person / bot except itself
|
||||
* @param prefix
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { fromEvent, map, pipe, switchMap, take } from 'rxjs';
|
||||
import * as Files from '../module-loading/readFile';
|
||||
import * as Files from '../../core/module-loading/readFile';
|
||||
import { callInitPlugins } from './observableHandling';
|
||||
import { CommandType, type ModuleStore, SernError } from '../structures';
|
||||
import { CommandType, type ModuleStore, SernError } from '../../core/structures';
|
||||
import { Result } from 'ts-results-es';
|
||||
import { ApplicationCommandType, ComponentType } from 'discord.js';
|
||||
import type { CommandModule } from '../../types/module';
|
||||
import type { Processed } from '../../types/handler';
|
||||
import type { ErrorHandling, Logging, ModuleManager } from '../contracts';
|
||||
import { err, ok } from '../utilities/functions';
|
||||
import { errTap, fillDefaults } from './operators';
|
||||
import SernEmitter from '../sernEmitter';
|
||||
import type { ErrorHandling, Logging, ModuleManager } from '../../core/contracts';
|
||||
import { err, ok } from '../../core/utilities/functions';
|
||||
import { errTap, fillDefaults } from '../../core/operators';
|
||||
import SernEmitter from '../../core/sernEmitter';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
|
||||
function buildCommandModules(commandDir: string, sernEmitter: SernEmitter) {
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { catchError, finalize, map, mergeAll } from 'rxjs';
|
||||
import * as Files from '../module-loading/readFile';
|
||||
import type { Dependencies, Processed } from '../../types/handler';
|
||||
import * as Files from '../../core/module-loading/readFile';
|
||||
import type { Processed, WebsocketDependencies } from '../../types/handler';
|
||||
import { callInitPlugins } from './observableHandling';
|
||||
import type { CommandModule, EventModule } from '../../types/module';
|
||||
import type { EventEmitter } from 'events';
|
||||
import SernEmitter from '../sernEmitter';
|
||||
import type { ErrorHandling, Logging } from '../contracts';
|
||||
import { SernError, EventType, type Wrapper } from '../structures';
|
||||
import SernEmitter from '../../core/sernEmitter';
|
||||
import type { ErrorHandling, Logging } from '../../core/contracts';
|
||||
import { SernError, EventType, type Wrapper } from '../../core/structures';
|
||||
import { eventDispatcher } from './dispatchers';
|
||||
import { handleError } from '../contracts/errorHandling';
|
||||
import { errTap, fillDefaults } from './operators';
|
||||
import { useContainerRaw } from '../dependencies';
|
||||
import { handleError } from '../../core/contracts/errorHandling';
|
||||
import { errTap, fillDefaults } from '../../core/operators';
|
||||
import { useContainerRaw } from '../../core/dependencies';
|
||||
|
||||
export function makeEventsHandler(
|
||||
[s, client, err, log]: [SernEmitter, EventEmitter, ErrorHandling, Logging | undefined],
|
||||
eventsPath: string,
|
||||
containerGetter: Wrapper['containerConfig'],
|
||||
) {
|
||||
const lazy = (k: string) => containerGetter.get(k as keyof Dependencies)[0];
|
||||
const lazy = (k: string) => containerGetter.get(k as keyof WebsocketDependencies)[0];
|
||||
const eventStream$ = eventObservable(eventsPath, s);
|
||||
|
||||
const eventCreation$ = eventStream$.pipe(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Wrapper, CommandType, EventType, PluginType } from '../core/structures';
|
||||
import { DispatchType } from '../core/platform';
|
||||
import { makeEventsHandler } from './events/userDefinedEventsHandling';
|
||||
import { AnyEventPlugin, ControlPlugin, InitPlugin, type Plugin } from '../types/plugin';
|
||||
import { makeInteractionCreate } from './events/interactionHandler';
|
||||
@@ -12,12 +13,12 @@ import type {
|
||||
InputCommand,
|
||||
InputEvent,
|
||||
} from '../types/module';
|
||||
import type { Dependencies, DependencyConfiguration } from '../types/handler';
|
||||
import type { AnyDependencies, Dependencies, DependencyConfiguration } from '../types/handler';
|
||||
import { composeRoot, makeFetcher, useContainer } from '../core/dependencies/provider';
|
||||
import type { Logging } from '../core/contracts';
|
||||
import { err, ok, partition } from '../core/utilities/functions';
|
||||
import type { Awaitable, ClientEvents } from 'discord.js';
|
||||
|
||||
import { AnyWrapper, isServerless } from '../core/structures/wrapper';
|
||||
/**
|
||||
* @since 1.0.0
|
||||
* @param wrapper Options to pass into sern.
|
||||
@@ -34,20 +35,25 @@ import type { Awaitable, ClientEvents } from 'discord.js';
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export function init(wrapper: Wrapper) {
|
||||
export function init(wrapper: AnyWrapper) {
|
||||
const logger = wrapper.containerConfig.get('@sern/logger')[0] as Logging | undefined;
|
||||
const requiredDependenciesAnd = makeFetcher(wrapper);
|
||||
const startTime = performance.now();
|
||||
const { events } = wrapper;
|
||||
if (events !== undefined) {
|
||||
makeEventsHandler(requiredDependenciesAnd([]), events, wrapper.containerConfig);
|
||||
if(isServerless(wrapper)) {
|
||||
|
||||
|
||||
} else {
|
||||
const dependencies = requiredDependenciesAnd(['@sern/modules']);
|
||||
const { events } = wrapper;
|
||||
if (events !== undefined) {
|
||||
makeEventsHandler(requiredDependenciesAnd([]), events, wrapper.containerConfig);
|
||||
}
|
||||
makeReadyEvent(dependencies, wrapper.commands);
|
||||
makeMessageCreate(dependencies, wrapper?.defaultPrefix ?? wrapper.platform.defaultPrefix);
|
||||
makeInteractionCreate(dependencies);
|
||||
const endTime = performance.now();
|
||||
logger?.info({ message: `sern : ${(endTime - startTime).toFixed(2)} ms` });
|
||||
}
|
||||
const dependencies = requiredDependenciesAnd(['@sern/modules']);
|
||||
makeReadyEvent(dependencies, wrapper.commands);
|
||||
makeMessageCreate(dependencies, wrapper.defaultPrefix);
|
||||
makeInteractionCreate(dependencies);
|
||||
const endTime = performance.now();
|
||||
logger?.info({ message: `sern : ${(endTime - startTime).toFixed(2)} ms` });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,8 +66,7 @@ export const controller = {
|
||||
};
|
||||
|
||||
/**
|
||||
* @since 1.0.0
|
||||
* The wrapper function to define command modules for sern
|
||||
* @since 1.0.0 The wrapper function to define command modules for sern
|
||||
* @param mod
|
||||
*/
|
||||
export function commandModule(mod: InputCommand): CommandModule {
|
||||
@@ -109,7 +114,7 @@ export function discordEvent<T extends keyof ClientEvents>(mod: {
|
||||
* @since 2.0.0
|
||||
* @param conf a configuration for creating your project dependencies
|
||||
*/
|
||||
export function makeDependencies<T extends Dependencies>(conf: DependencyConfiguration<T>) {
|
||||
export function makeDependencies<const T extends AnyDependencies>(conf: DependencyConfiguration<T>) {
|
||||
//Until there are more optional dependencies, just check if the logger exists
|
||||
composeRoot(conf);
|
||||
return useContainer<T>();
|
||||
|
||||
@@ -39,21 +39,35 @@ export type LogPayload<T = unknown> = { message: T };
|
||||
export type Singleton<T> = () => T;
|
||||
export type Transient<T> = () => () => T;
|
||||
|
||||
export interface Dependencies {
|
||||
'@sern/client': Singleton<EventEmitter>;
|
||||
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 Dependencies, T extends readonly unknown[]> = T extends [
|
||||
export type MapDeps<Deps extends AnyDependencies, T extends readonly unknown[]> = T extends [
|
||||
infer First extends keyof Deps,
|
||||
...infer Rest extends readonly unknown[],
|
||||
]
|
||||
@@ -66,9 +80,9 @@ export type MapDeps<Deps extends Dependencies, T extends readonly unknown[]> = T
|
||||
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 Dependencies> {
|
||||
export interface DependencyConfiguration<T extends AnyDependencies> {
|
||||
exclude?: Set<OptionalDependencies>;
|
||||
build: (root: Container<Omit<Dependencies, '@sern/client'>, {}>) => Container<T, {}>;
|
||||
build: (root: Container<Omit<AnyDependencies, '@sern/client'>, {}>) => Container<T, {}>;
|
||||
}
|
||||
|
||||
export type ImportPayload<T> = { module: T; absPath: string };
|
||||
|
||||
Reference in New Issue
Block a user