From 30230d49c30dad4b12ebca6b32c9cebf1dec9c8d Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 28 Apr 2024 13:48:50 -0500 Subject: [PATCH 01/90] step 1 --- src/core/functions.ts | 9 +++------ src/core/module-loading.ts | 4 ++++ src/core/modules.ts | 20 +++++++++++++++----- src/core/presences.ts | 3 +-- test/core/module-loading.test.ts | 20 +++++++++----------- test/core/services.test.ts | 7 +++---- 6 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index 878151b5..a03cdf53 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -15,13 +15,10 @@ import { PayloadType, PluginType } from './structures'; import assert from 'assert'; import type { Payload } from '../types/utility'; -//function wrappers for empty ok / err -export const ok = /* @__PURE__*/ () => Ok.EMPTY; -export const err = /* @__PURE__*/ () => Err.EMPTY; +export const ok = () => Ok.EMPTY; +export const err = () => Err.EMPTY; -export function partitionPlugins( - arr: (AnyEventPlugin | AnyCommandPlugin)[] = [], -): [Plugin[], Plugin[]] { +export function partitionPlugins(arr: (AnyEventPlugin | AnyCommandPlugin)[] = []): [Plugin[], Plugin[]] { const controlPlugins = []; const initPlugins = []; diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 0833672b..2fa3a7f3 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -8,6 +8,10 @@ import type { Module } from '../types/core-modules'; import { existsSync } from 'fs'; import type { Logging } from './contracts/logging'; + +export const parseCallsite = (fpath: string) => { + return parse(fpath.replace(/file:\\?/, "")).name; +} export const shouldHandle = (path: string, fpath: string) => { const file_name = fpath+extname(path); let newPath = join(dirname(path), file_name) diff --git a/src/core/modules.ts b/src/core/modules.ts index 5b1e541c..7b0b9921 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -1,8 +1,6 @@ import { ClientEvents } from 'discord.js'; import { EventType } from '../core/structures'; -import type { - AnyEventPlugin, -} from '../types/core-plugin'; +import type { AnyEventPlugin, } from '../types/core-plugin'; import type { CommandModule, EventModule, @@ -11,18 +9,27 @@ import type { } from '../types/core-modules'; import { partitionPlugins } from './_internal'; import type { Awaitable } from '../types/utility'; - +import callsites from 'callsites'; +import * as Files from './module-loading' +import path, { basename } from 'path'; +import * as Id from './id' /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod */ export function commandModule(mod: InputCommand): CommandModule { const [onEvent, plugins] = partitionPlugins(mod.plugins); + const initCallsite = callsites()[1].getFileName()?.replace(/file:\\?/, ""); + if(!initCallsite) throw Error("initCallsite is null"); + const filename = Files.parseCallsite(initCallsite); + mod.name ??= filename; + const id = Id.create(mod.name, mod.type) return { ...mod, + __id: id, onEvent, plugins, - } as CommandModule; + } as unknown as CommandModule; } /** * @since 1.0.0 @@ -31,6 +38,9 @@ export function commandModule(mod: InputCommand): CommandModule { */ export function eventModule(mod: InputEvent): EventModule { const [onEvent, plugins] = partitionPlugins(mod.plugins); + const initCallsite = callsites()[1].getFileName(); + console.log(initCallsite?.replace(/file:\\?/, "")) + return { ...mod, plugins, diff --git a/src/core/presences.ts b/src/core/presences.ts index 594c836f..6e66431d 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -25,8 +25,7 @@ export type Config = * Create a Presence module which **MUST** be put in a file called presence.(language-extension) * adjacent to the file where **Sern.init** is CALLED. */ -export function module(conf: Config) -{ return conf; } +export const module = (conf: Config) => conf; /** diff --git a/test/core/module-loading.test.ts b/test/core/module-loading.test.ts index dc4e9a8f..b3906c1d 100644 --- a/test/core/module-loading.test.ts +++ b/test/core/module-loading.test.ts @@ -8,15 +8,13 @@ describe('module-loading', () => { const filename = Files.fmtFileName(name+'.'+extension); expect(filename).toBe(name) }) - -// todo: handle commands with multiple extensions -// it('should properly extract filename from file, nested multiple', () => { -// const extension = faker.system.fileExt() -// const extension2 = faker.system.fileExt() -// const name = faker.system.fileName({ extensionCount: 0 }) -// const filename = Files.fmtFileName(name+'.'+extension+'.'+extension2); -// console.log(filename, name) -// expect(filename).toBe(name) -// -// }) + it('should get the filename of the commandmodule (linux)', () => { + const fname = "///home/pooba/Projects/sern/halibu/dist/commands/ping.js" + expect(Files.parseCallsite(fname)).toBe("ping") + }) + it('should get the filename of the commandmodule (windows)', () => { + //const fname = "C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + //expect(Files.parseCallsite(fname)).toBe("ping") + }) + }) diff --git a/test/core/services.test.ts b/test/core/services.test.ts index 479adef1..4f532f39 100644 --- a/test/core/services.test.ts +++ b/test/core/services.test.ts @@ -2,10 +2,9 @@ import { SpyInstance, afterAll, beforeEach, describe, expect, it, vi } from 'vit import { CoreContainer } from '../../src/core/ioc/container'; import { DefaultLogging } from '../../src/core'; import { faker } from '@faker-js/faker'; -import { commandModule } from '../../src'; +import { commandModule, CommandType } from '../../src'; import * as Id from '../../src/core/id'; import { CommandMeta } from '../../src/types/core-modules'; - describe('services', () => { //@ts-ignore let container: CoreContainer; @@ -23,9 +22,9 @@ describe('services', () => { it('module-store.ts', async () => { function createRandomCommandModules() { return commandModule({ - type: faker.number.int({ min: 1 << 0, max: 1 << 10 }), + type: CommandType.Slash, description: faker.string.alpha(), - name: faker.string.alpha(), + name: faker.string.alpha({ length: { min: 5, max: 10 }}), execute: () => {}, }); } From 6228f532443b42de20d4fb0c2034918c038ad798 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 14:14:51 -0500 Subject: [PATCH 02/90] Refactorings --- src/core/create-plugins.ts | 4 ---- src/handlers/dispatchers.ts | 14 ++++++-------- src/handlers/event-utils.ts | 7 ++----- src/handlers/interaction-event.ts | 6 +++--- src/handlers/message-event.ts | 6 +++--- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 7f1b8bfe..b8d6192e 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -14,7 +14,6 @@ export function makePlugin( } /** * @since 2.5.0 - * @__PURE__ */ export function EventInitPlugin( execute: (...args: EventArgs) => PluginResult, @@ -23,7 +22,6 @@ export function EventInitPlugin( } /** * @since 2.5.0 - * @__PURE__ */ export function CommandInitPlugin( execute: (...args: CommandArgs) => PluginResult, @@ -32,7 +30,6 @@ export function CommandInitPlugin( } /** * @since 2.5.0 - * @__PURE__ */ export function CommandControlPlugin( execute: (...args: CommandArgs) => PluginResult, @@ -41,7 +38,6 @@ export function CommandControlPlugin( } /** * @since 2.5.0 - * @__PURE__ */ export function EventControlPlugin( execute: (...args: EventArgs) => PluginResult, diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index 8e4eb10c..b9b1b6a0 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -50,14 +50,12 @@ const createResult = createResultResolver< export function eventDispatcher(module: Processed, source: unknown) { assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); - const execute: OperatorFunction = concatMap(async args => - module.execute(...args), - ); - return fromEvent(source, module.name).pipe( - intoPayload(module), - concatMap(createResult), - execute, - ); + const execute: OperatorFunction = + concatMap(async args => module.execute(...args)); + return fromEvent(source, module.name) + .pipe(intoPayload(module), + concatMap(createResult), + execute); } export function createDispatcher(payload: { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index fc7a16c8..08e1e6b5 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -169,7 +169,6 @@ export function executeModule( } - /** * A higher order function that * - creates a stream of {@link VoidResult} { config.createStream } @@ -235,15 +234,13 @@ export function makeModuleExecutor< module, args }); - return concatMap( - createResultResolver({ + return createResultResolver({ onStop, createStream: ({ args, module }) => from(module.onEvent) .pipe(callPlugin(args)), onNext, - }), - ); + }) } export const handleCrash = (err: ErrorHandling,sernemitter: Emitter, log?: Logging) => diff --git a/src/handlers/interaction-event.ts b/src/handlers/interaction-event.ts index 06523417..e9ec3fe6 100644 --- a/src/handlers/interaction-event.ts +++ b/src/handlers/interaction-event.ts @@ -1,5 +1,5 @@ import { Interaction } from 'discord.js'; -import { mergeMap, merge } from 'rxjs'; +import { mergeMap, merge, concatMap } from 'rxjs'; import { PayloadType } from '../core'; import { isAutocomplete, @@ -27,7 +27,7 @@ export function interactionHandler([emitter, err, log, modules, client]: Depende return interactionHandler$ .pipe( filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - makeModuleExecutor(module => - emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure))), + concatMap(makeModuleExecutor(module => + emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index 86b14466..a1c1a690 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -1,4 +1,4 @@ -import { mergeMap, EMPTY } from 'rxjs'; +import { mergeMap, EMPTY, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; import { PayloadType } from '../core'; import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; @@ -39,9 +39,9 @@ export function messageHandler( return msgCommands$.pipe( filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - makeModuleExecutor(module => { + concatMap(makeModuleExecutor(module => { const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); emitter.emit('module.activate', result); - }), + })), mergeMap(payload => executeModule(emitter, log, err, payload))); } From 599a02c9df6638a6f37bc8fb35e99ec3a65b4918 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 15:50:29 -0500 Subject: [PATCH 03/90] command modules do not depend on anything but itself --- src/core/_internal.ts | 14 +++++++++++- src/core/functions.ts | 8 +++++++ src/core/module-loading.ts | 39 +++++++++++++++++++------------- src/core/modules.ts | 36 ++++++++++++++++++----------- src/types/core-plugin.ts | 2 +- test/core/module-loading.test.ts | 17 ++++++++++---- test/core/services.test.ts | 17 +++++++------- 7 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 1b2f35c9..1e8f2030 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,10 +1,22 @@ +import type { Result } from 'ts-results-es' + export * as Id from './id'; export * from './operators'; export * as Files from './module-loading'; export * from './functions'; -export type { VoidResult } from '../types/core-plugin'; export { SernError } from './structures/enums'; export { ModuleStore } from './structures/module-store'; export * as __Services from './structures/services'; export { useContainerRaw } from './ioc/base'; +export type _Module = { + meta: { + id: string, + absPath: string + } + name: string, + execute : Function + [key: PropertyKey]: unknown +} + +export type VoidResult = Result; diff --git a/src/core/functions.ts b/src/core/functions.ts index a03cdf53..39ff1590 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -118,3 +118,11 @@ export function resultPayload (type: T, module?: Module, reason?: unknown) { return { type, module, reason } as Payload & { type : T }; } + +export function pipe(arg: unknown, firstFn: Function, ...fns: Function[]): T { + let result = firstFn(arg); + for (let fn of fns) { + result = fn(result); + } + return result; +} diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 2fa3a7f3..51a6d30c 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,6 +1,6 @@ import { type Observable, from, mergeMap, ObservableInput } from 'rxjs'; import { readdir, stat } from 'fs/promises'; -import { basename, extname, join, resolve, parse, dirname } from 'path'; +import path from 'node:path'; import assert from 'assert'; import { createRequire } from 'node:module'; import type { ImportPayload, Wrapper } from '../types/core'; @@ -10,11 +10,18 @@ import type { Logging } from './contracts/logging'; export const parseCallsite = (fpath: string) => { - return parse(fpath.replace(/file:\\?/, "")).name; + const pathobj = + path.parse(fpath.replace(/file:\\?/, "") + .split(path.sep) + .join(path.posix.sep)) + return { + name: pathobj.name, + absPath : path.posix.format(pathobj) + } } -export const shouldHandle = (path: string, fpath: string) => { - const file_name = fpath+extname(path); - let newPath = join(dirname(path), file_name) +export const shouldHandle = (pth: string, fpath: string) => { + const file_name = fpath+path.extname(pth); + let newPath = path.join(path.dirname(pth), file_name) .replace(/file:\\?/, ""); return { exists: existsSync(newPath), path: 'file:///'+newPath }; @@ -41,7 +48,7 @@ export async function importModule(absPath: string) { let commandModule = fileModule.default; - assert(commandModule , `Found no export @ ${absPath}. Forgot to ignore with "!"? (!${basename(absPath)})?`); + assert(commandModule , `Found no export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); if ('default' in commandModule ) { commandModule = commandModule.default; } @@ -54,7 +61,7 @@ export async function defaultModuleLoader(absPath: string): Mo return { module, absPath }; } -export const fmtFileName = (fileName: string) => parse(fileName).name; +export const fmtFileName = (fileName: string) => path.parse(fileName).name; /** * a directory string is converted into a stream of modules. @@ -69,21 +76,21 @@ export function buildModuleStream( .pipe(mergeMap(defaultModuleLoader)); } -export const getFullPathTree = (dir: string) => readPaths(resolve(dir)); +export const getFullPathTree = (dir: string) => readPaths(path.resolve(dir)); -export const filename = (path: string) => fmtFileName(basename(path)); +export const filename = (p: string) => fmtFileName(path.basename(p)); +const validExtensions = ['.js', '.cjs', '.mts', '.mjs', '.cts', '.ts', '']; const isSkippable = (filename: string) => { //empty string is for non extension files (directories) - const validExtensions = ['.js', '.cjs', '.mts', '.mjs', '.cts', '.ts', '']; - return filename[0] === '!' || !validExtensions.includes(extname(filename)); + return filename[0] === '!' || !validExtensions.includes(path.extname(filename)); }; async function deriveFileInfo(dir: string, file: string) { - const fullPath = join(dir, file); + const fullPath = path.join(dir, file); return { fullPath, fileStats: await stat(fullPath), - base: basename(file) }; + base: path.basename(file) }; } async function* readPaths(dir: string): AsyncGenerator { @@ -114,12 +121,12 @@ export function loadConfig(wrapper: Wrapper | 'file', log: Logging | undefined): return wrapper; } log?.info({ message: 'Experimental loading of sern.config.json'}); - const config = requir(resolve('sern.config.json')); + const config = requir(path.resolve('sern.config.json')); const makePath = (dir: PropertyKey) => config.language === 'typescript' - ? join('dist', config.paths[dir]!) - : join(config.paths[dir]!); + ? path.join('dist', config.paths[dir]!) + : path.join(config.paths[dir]!); log?.info({ message: 'Loading config: ' + JSON.stringify(config, null, 4) }); const commandsPath = makePath('commands'); diff --git a/src/core/modules.ts b/src/core/modules.ts index 7b0b9921..0b3946e6 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -7,45 +7,55 @@ import type { InputCommand, InputEvent, } from '../types/core-modules'; -import { partitionPlugins } from './_internal'; +import { _Module, partitionPlugins } from './_internal'; import type { Awaitable } from '../types/utility'; import callsites from 'callsites'; import * as Files from './module-loading' -import path, { basename } from 'path'; import * as Id from './id' /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod */ -export function commandModule(mod: InputCommand): CommandModule { +export function commandModule(mod: InputCommand): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = callsites()[1].getFileName()?.replace(/file:\\?/, ""); + const initCallsite = callsites()[1].getFileName(); if(!initCallsite) throw Error("initCallsite is null"); - const filename = Files.parseCallsite(initCallsite); - mod.name ??= filename; - const id = Id.create(mod.name, mod.type) + + const { name, absPath } = Files.parseCallsite(initCallsite); + mod.name ??= name; + //@ts-ignore return { ...mod, - __id: id, + meta: { + id: Id.create(mod.name, mod.type), + absPath + }, onEvent, plugins, - } as unknown as CommandModule; + }; } /** * @since 1.0.0 * The wrapper function to define event modules for sern * @param mod */ -export function eventModule(mod: InputEvent): EventModule { +export function eventModule(mod: InputEvent): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); const initCallsite = callsites()[1].getFileName(); - console.log(initCallsite?.replace(/file:\\?/, "")) - + console.log(initCallsite); + if(!initCallsite) throw Error("initCallsite is null"); + const { name, absPath } = Files.parseCallsite(initCallsite); + mod.name ??= name; + //@ts-ignore return { ...mod, + meta: { + id: Id.create(mod.name, mod.type), + absPath + }, plugins, onEvent, - } as EventModule; + }; } /** Create event modules from discord.js client events, diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 8ece7c3c..ae92c688 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -47,9 +47,9 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; +import { VoidResult } from '../core/_internal'; export type PluginResult = Awaitable; -export type VoidResult = Result; export interface InitArgs> { module: T; diff --git a/test/core/module-loading.test.ts b/test/core/module-loading.test.ts index b3906c1d..59521d40 100644 --- a/test/core/module-loading.test.ts +++ b/test/core/module-loading.test.ts @@ -8,13 +8,20 @@ describe('module-loading', () => { const filename = Files.fmtFileName(name+'.'+extension); expect(filename).toBe(name) }) - it('should get the filename of the commandmodule (linux)', () => { + it('should get the filename of the commandmodule (linux, esm)', () => { const fname = "///home/pooba/Projects/sern/halibu/dist/commands/ping.js" - expect(Files.parseCallsite(fname)).toBe("ping") + const callsiteinfo = Files.parseCallsite(fname) + expect(callsiteinfo.name).toBe("ping") }) - it('should get the filename of the commandmodule (windows)', () => { - //const fname = "C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" - //expect(Files.parseCallsite(fname)).toBe("ping") + it('should get the filename of the commandmodule (windows, cjs)', () => { + const fname = "C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + const callsiteinfo = Files.parseCallsite(fname) + expect(callsiteinfo.name).toEqual("ping"); + }) + it('should get filename of commandmodule (windows, esm)', () => { + const fname = "file:///C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + const callsiteinfo = Files.parseCallsite(fname) + expect(callsiteinfo.name).toEqual("ping"); }) }) diff --git a/test/core/services.test.ts b/test/core/services.test.ts index 4f532f39..cfd963aa 100644 --- a/test/core/services.test.ts +++ b/test/core/services.test.ts @@ -5,6 +5,14 @@ import { faker } from '@faker-js/faker'; import { commandModule, CommandType } from '../../src'; import * as Id from '../../src/core/id'; import { CommandMeta } from '../../src/types/core-modules'; +function createRandomCommandModules() { + return commandModule({ + type: CommandType.Slash, + description: faker.string.alpha(), + name: faker.string.alpha({ length: { min: 5, max: 10 }}), + execute: vi.fn(), + }); +} describe('services', () => { //@ts-ignore let container: CoreContainer; @@ -20,15 +28,6 @@ describe('services', () => { consoleMock.mockReset(); }); it('module-store.ts', async () => { - function createRandomCommandModules() { - return commandModule({ - type: CommandType.Slash, - description: faker.string.alpha(), - name: faker.string.alpha({ length: { min: 5, max: 10 }}), - execute: () => {}, - }); - } - const modules = faker.helpers.multiple(createRandomCommandModules, { count: 40, }); From 3d10ee1c5903469b7925f04be62845aa5fde1795 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 18:44:58 -0500 Subject: [PATCH 04/90] tearing it up --- src/core/module-loading.ts | 22 +++++++++------------ src/core/operators.ts | 3 ++- src/handlers/dispatchers.ts | 3 +-- src/handlers/event-utils.ts | 22 +-------------------- src/handlers/ready-event.ts | 38 ++++++------------------------------- src/sern.ts | 8 +++++--- src/types/core-modules.ts | 2 -- 7 files changed, 24 insertions(+), 74 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 51a6d30c..98dd2cac 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -10,17 +10,14 @@ import type { Logging } from './contracts/logging'; export const parseCallsite = (fpath: string) => { - const pathobj = - path.parse(fpath.replace(/file:\\?/, "") - .split(path.sep) - .join(path.posix.sep)) - return { - name: pathobj.name, - absPath : path.posix.format(pathobj) - } + const pathobj = path.parse(fpath.replace(/file:\\?/, "") + .split(path.sep) + .join(path.posix.sep)) + return { name: pathobj.name, + absPath : path.posix.format(pathobj) } } -export const shouldHandle = (pth: string, fpath: string) => { - const file_name = fpath+path.extname(pth); +export const shouldHandle = (pth: string, filenam: string) => { + const file_name = filenam+path.extname(pth); let newPath = path.join(path.dirname(pth), file_name) .replace(/file:\\?/, ""); return { exists: existsSync(newPath), @@ -49,7 +46,7 @@ export async function importModule(absPath: string) { let commandModule = fileModule.default; assert(commandModule , `Found no export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); - if ('default' in commandModule ) { + if ('default' in commandModule) { commandModule = commandModule.default; } return { module: commandModule } as T; @@ -72,8 +69,7 @@ export const fmtFileName = (fileName: string) => path.parse(fileName).name; export function buildModuleStream( input: ObservableInput, ): Observable> { - return from(input) - .pipe(mergeMap(defaultModuleLoader)); + return from(input).pipe(mergeMap(defaultModuleLoader)); } export const getFullPathTree = (dir: string) => readPaths(path.resolve(dir)); diff --git a/src/core/operators.ts b/src/core/operators.ts index 4c5ff729..5350de4d 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -18,8 +18,9 @@ import { } from 'rxjs'; import { Emitter, ErrorHandling, Logging } from './contracts'; import util from 'node:util'; -import type { PluginResult, VoidResult } from '../types/core-plugin'; +import type { PluginResult } from '../types/core-plugin'; import type { Result } from 'ts-results-es' +import type { VoidResult } from './_internal'; /** * if {src} is true, mapTo V, else ignore * @param item diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index b9b1b6a0..e1218b62 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -30,8 +30,7 @@ export function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: function intoPayload(module: Processed, ) { return pipe( arrayifySource, - map(args => ({ module, args, })), - ); + map(args => ({ module, args, }))); } const createResult = createResultResolver< diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 08e1e6b5..bd2df77f 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -103,31 +103,11 @@ export function createMessageHandler( /** * This function assigns remaining, incomplete data to each imported module. */ -function assignDefaults() { - return map(({ module, absPath }) => { - const processed = { - name: module.name ?? Files.filename(absPath), - description: module.description ?? '...', - ...module - } - return { - module: processed, - absPath, - metadata: { - isClass: module.constructor.name === 'Function', - fullPath: absPath, - id: Id.create(processed.name, module.type), - } - } - }); -} export function buildModules( input: ObservableInput, ) { - return Files - .buildModuleStream>(input) - .pipe(assignDefaults()); + return Files.buildModuleStream>(input); } diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index e1ddb8eb..12500dcc 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -1,6 +1,5 @@ import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; -import { CommandType } from '../core/structures'; -import { SernError } from '../core/_internal'; +import { SernError, _Module } from '../core/_internal'; import { Result } from 'ts-results-es'; import { Logging, ModuleManager } from '../core/contracts'; import { buildModules, callInitPlugins } from './_internal'; @@ -16,39 +15,14 @@ export function readyHandler( //Todo: add module manager on on ready const ready$ = fromEvent(client!, 'ready').pipe(once(log)); - return concat(ready$, buildModules(allPaths)) - .pipe(callInitPlugins(sEmitter)) - .subscribe(({ module, metadata }) => { - register(moduleManager, module, metadata) - .expect(SernError.InvalidModuleType + ' ' + util.inspect(module)); - }); + concat(ready$) + //.pipe(callInitPlugins(sEmitter)) +// const validModuleType = module.type >= 0 && module.type <= 1 << 10; +// assert.ok(validModuleType, +// `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); } const once = (log: Logging | undefined) => pipe( tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), first(), ignoreElements()) - - -function register>( - manager: ModuleManager, - module: T, - metadata:CommandMeta -): Result { - manager.setMetadata(module, metadata)!; - - const validModuleType = module.type >= 0 && module.type <= 1 << 10; - assert.ok( - validModuleType, - //@ts-ignore - `Found ${module.name} at ${metadata.fullPath}, which does not have a valid type`, - ); - if (module.type === CommandType.Both) { - module.alias?.forEach(a => manager.set(`${a}_B`, module)); - } else { - if(module.type === CommandType.Text){ - module.alias?.forEach(a => manager.set(`${a}_T`, module)); - } - } - return Result.wrap(() => manager.set(metadata.id, module)); -} diff --git a/src/sern.ts b/src/sern.ts index fd458f4c..e7639423 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -9,7 +9,8 @@ import { readyHandler } from './handlers/ready-event'; import { messageHandler } from './handlers/message-event'; import { interactionHandler } from './handlers/interaction-event'; import { presenceHandler } from './handlers/presence'; -import { Client } from 'discord.js'; +import type { Client } from 'discord.js'; + /** * @since 1.0.0 @@ -31,8 +32,8 @@ export function init(maybeWrapper: Wrapper | 'file') { '@sern/modules', '@sern/client'); const logger = dependencies[2], - errorHandler = dependencies[1]; - + errorHandler = dependencies[1]; + const wrapper = Files.loadConfig(maybeWrapper, logger); if (wrapper.events !== undefined) { eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); @@ -40,6 +41,7 @@ export function init(maybeWrapper: Wrapper | 'file') { const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); + //Ready event: load all modules and when finished, time should be taken and logged readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) .add(() => { diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index d0f98349..1cad72fb 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -109,7 +109,6 @@ export interface DiscordEventCommand Awaitable; } @@ -122,7 +121,6 @@ export interface SlashCommand extends Module { export interface BothCommand extends Module { type: CommandType.Both; - alias?: string[]; description: string; options?: SernOptionsData[]; execute: (ctx: Context, args: Args) => Awaitable; From 76ee9c6edf469a090bf6394dfea97a2b77b39060 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:34:08 -0500 Subject: [PATCH 05/90] Remove module store, manager, and Intializable type --- src/core/_internal.ts | 1 - src/core/contracts/index.ts | 3 +- src/core/contracts/module-manager.ts | 34 ------------- src/core/contracts/module-store.ts | 9 ---- src/core/ioc/container.ts | 8 +-- src/core/structures/index.ts | 1 - src/core/structures/module-store.ts | 11 ---- src/core/structures/services/index.ts | 1 - .../structures/services/module-manager.ts | 51 ------------------- src/handlers/event-utils.ts | 7 ++- src/handlers/ready-event.ts | 11 ++-- src/sern.ts | 35 +++++++------ src/types/ioc.ts | 13 +---- 13 files changed, 27 insertions(+), 158 deletions(-) delete mode 100644 src/core/contracts/module-manager.ts delete mode 100644 src/core/contracts/module-store.ts delete mode 100644 src/core/structures/module-store.ts delete mode 100644 src/core/structures/services/module-manager.ts diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 1e8f2030..be7f2a57 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -5,7 +5,6 @@ export * from './operators'; export * as Files from './module-loading'; export * from './functions'; export { SernError } from './structures/enums'; -export { ModuleStore } from './structures/module-store'; export * as __Services from './structures/services'; export { useContainerRaw } from './ioc/base'; diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts index f0eb130a..fdd9bc63 100644 --- a/src/core/contracts/index.ts +++ b/src/core/contracts/index.ts @@ -1,6 +1,5 @@ export * from './error-handling'; export * from './logging'; -export * from './module-manager'; -export * from './module-store'; export * from './hooks'; export * from './emitter'; + diff --git a/src/core/contracts/module-manager.ts b/src/core/contracts/module-manager.ts deleted file mode 100644 index 5dbeaee4..00000000 --- a/src/core/contracts/module-manager.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { - CommandMeta, - CommandModule, - CommandModuleDefs, - Module, -} from '../../types/core-modules'; -import { CommandType } from '../structures'; - -interface MetadataAccess { - getMetadata(m: Module): CommandMeta | undefined; - setMetadata(m: Module, c: CommandMeta): void; -} - -/** - * @since 2.0.0 - * @internal - direct access to the module manager will be removed in version 4 - */ -export interface ModuleManager extends MetadataAccess { - get(id: string): Module | undefined; - - set(id: string, path: Module): void; - /** - * @deprecated - */ - getPublishableCommands(): CommandModule[]; - - /* - * @deprecated - */ - getByNameCommandType( - name: string, - commandType: T, - ): CommandModuleDefs[T] | undefined; -} diff --git a/src/core/contracts/module-store.ts b/src/core/contracts/module-store.ts deleted file mode 100644 index 90818f80..00000000 --- a/src/core/contracts/module-store.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { CommandMeta, Module } from '../../types/core-modules'; - -/** - * Represents a core module store that stores IDs mapped to file paths. - */ -export interface CoreModuleStore { - commands: Map; - metadata: WeakMap; -} diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index e8c49706..b063aca8 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -2,7 +2,7 @@ import { Container } from 'iti'; import { Disposable } from '../'; import * as assert from 'node:assert'; import { Subject } from 'rxjs'; -import { __Services, ModuleStore } from '../_internal'; +import { __Services } from '../_internal'; import * as Hooks from './hooks'; import { EventEmitter } from 'node:events'; @@ -24,11 +24,7 @@ export class CoreContainer> extends Container) .add({ '@sern/errors': () => new __Services.DefaultErrorHandling, - '@sern/emitter': () => new EventEmitter({ captureRejections: true }), - '@sern/store': () => new ModuleStore }) - .add(ctx => { - return { '@sern/modules': new __Services.DefaultModuleManager(ctx['@sern/store'])}; - }); + '@sern/emitter': () => new EventEmitter({ captureRejections: true }) }) } isReady() { diff --git a/src/core/structures/index.ts b/src/core/structures/index.ts index 8eeb6f92..64b87555 100644 --- a/src/core/structures/index.ts +++ b/src/core/structures/index.ts @@ -1,5 +1,4 @@ export { CommandType, PluginType, PayloadType, EventType } from './enums'; export * from './context'; export * from './services'; -export * from './module-store'; diff --git a/src/core/structures/module-store.ts b/src/core/structures/module-store.ts deleted file mode 100644 index 49b22c55..00000000 --- a/src/core/structures/module-store.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CommandMeta, Module } from '../../types/core-modules'; - -/* - * @deprecated - * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! - * For interacting with modules, use the ModuleManager instead. - */ -export class ModuleStore { - metadata = new WeakMap(); - commands = new Map(); -} diff --git a/src/core/structures/services/index.ts b/src/core/structures/services/index.ts index 3f1d4ab9..3074d8f5 100644 --- a/src/core/structures/services/index.ts +++ b/src/core/structures/services/index.ts @@ -1,3 +1,2 @@ export * from './error-handling'; export * from './logger'; -export * from './module-manager'; diff --git a/src/core/structures/services/module-manager.ts b/src/core/structures/services/module-manager.ts deleted file mode 100644 index dad28889..00000000 --- a/src/core/structures/services/module-manager.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as Id from '../../../core/id'; -import { CoreModuleStore, ModuleManager } from '../../contracts'; -import { CommandMeta, CommandModule, CommandModuleDefs, Module } from '../../../types/core-modules'; -import { CommandType } from '../enums'; -/** - * @internal - * @since 2.0.0 - * Version 4.0.0 will internalize this api. Please refrain from using DefaultModuleManager! - */ -export class DefaultModuleManager implements ModuleManager { - constructor(private moduleStore: CoreModuleStore) {} - - - getByNameCommandType(name: string, commandType: T) { - const module = this.get(Id.create(name, commandType)); - if (!module) { - return undefined; - } - return module as CommandModuleDefs[T]; - } - - setMetadata(m: Module, c: CommandMeta): void { - this.moduleStore.metadata.set(m, c); - } - - getMetadata(m: Module): CommandMeta { - const maybeModule = this.moduleStore.metadata.get(m); - if (!maybeModule) { - throw Error('Could not find metadata in store for ' + m); - } - return maybeModule; - } - - get(id: string) { - return this.moduleStore.commands.get(id); - } - set(id: string, path: CommandModule): void { - this.moduleStore.commands.set(id, path); - } - //not tested - getPublishableCommands(): CommandModule[] { - const entries = this.moduleStore.commands.entries(); - const publishable = 0b000000110; - return Array.from(entries) - .filter(([id]) => { - const last_entry = id.at(-1); - return last_entry == 'B' || !(publishable & Number.parseInt(last_entry!)); - }) - .map(([, path]) => path as CommandModule); - } -} diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index bd2df77f..6eff29f8 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -10,7 +10,6 @@ import { tap, catchError, finalize, - map, } from 'rxjs'; import { Files, @@ -23,7 +22,7 @@ import { VoidResult, resultPayload, } from '../core/_internal'; -import { Emitter, ErrorHandling, Logging, ModuleManager, PayloadType } from '../core'; +import { Emitter, ErrorHandling, Logging, PayloadType } from '../core'; import { contextArgs, createDispatcher } from './dispatchers'; import { ObservableInput, pipe } from 'rxjs'; import { Err, Ok, Result } from 'ts-results-es'; @@ -65,7 +64,7 @@ export function fmt(msg: string, prefix: string): string[] { */ export function createInteractionHandler( source: Observable, - mg: ModuleManager, + mg: any, //TODO ) { return createGenericHandler, void>>( source, @@ -86,7 +85,7 @@ export function createInteractionHandler( export function createMessageHandler( source: Observable, defaultPrefix: string, - mg: ModuleManager, + mg: any, //TODO ) { return createGenericHandler(source, async event => { const [prefix, ...rest] = fmt(event.content, defaultPrefix); diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 12500dcc..7be2e7a8 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -1,15 +1,10 @@ import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; -import { SernError, _Module } from '../core/_internal'; -import { Result } from 'ts-results-es'; -import { Logging, ModuleManager } from '../core/contracts'; -import { buildModules, callInitPlugins } from './_internal'; -import * as assert from 'node:assert'; -import * as util from 'node:util'; +import { _Module } from '../core/_internal'; +import { Logging, } from '../core/contracts'; import type { DependencyList } from '../types/ioc'; -import type { AnyModule, CommandMeta, Processed } from '../types/core-modules'; export function readyHandler( - [sEmitter, , log , moduleManager, client]: DependencyList, + [sEmitter, , log ,, client]: DependencyList, allPaths: ObservableInput, ) { //Todo: add module manager on on ready diff --git a/src/sern.ts b/src/sern.ts index e7639423..769c8d2d 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -29,36 +29,35 @@ export function init(maybeWrapper: Wrapper | 'file') { const dependencies = Services('@sern/emitter', '@sern/errors', '@sern/logger', - '@sern/modules', '@sern/client'); const logger = dependencies[2], errorHandler = dependencies[1]; const wrapper = Files.loadConfig(maybeWrapper, logger); if (wrapper.events !== undefined) { - eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); + //eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); } const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged - readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) - .add(() => { - logger?.info({ message: "Client signaled ready, registering modules" }); - const time = ((performance.now() - startTime) / 1000).toFixed(2); - dependencies[0].emit('modulesLoaded'); - logger?.info({ message: `sern: registered in ${time} s`, }); - if(presencePath.exists) { - const setPresence = async (p: any) => { - return (dependencies[4] as Client).user?.setPresence(p); - } - presenceHandler(presencePath.path, setPresence).subscribe(); - } - }); +// readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) +// .add(() => { +// logger?.info({ message: "Client signaled ready, registering modules" }); +// const time = ((performance.now() - startTime) / 1000).toFixed(2); +// dependencies[0].emit('modulesLoaded'); +// logger?.info({ message: `sern: registered in ${time} s`, }); +// if(presencePath.exists) { +// const setPresence = async (p: any) => { +// return (dependencies[4] as Client).user?.setPresence(p); +// } +// presenceHandler(presencePath.path, setPresence).subscribe(); +// } +// }); - const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); - const interactions$ = interactionHandler(dependencies); + //const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); + //const interactions$ = interactionHandler(dependencies); // listening to the message stream and interaction stream - merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); + //merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); } diff --git a/src/types/ioc.ts b/src/types/ioc.ts index be5278a9..290ce28a 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -10,29 +10,18 @@ export type Singleton = () => T; * Every time this is called, a new object is created */ export type Transient = () => () => T; -/** - * Type to annotate that something is initializable. - * If T has an init method, this will be called. - */ -export type Initializable = T export type DependencyList = [ Contracts.Emitter, Contracts.ErrorHandling, Contracts.Logging | undefined, - Contracts.ModuleManager, + null, Contracts.Emitter, ]; export interface CoreDependencies { '@sern/client': () => Contracts.Emitter; '@sern/emitter': () => Contracts.Emitter; - /** - * @deprecated - * Will be removed and turned internal - */ - '@sern/store': () => Contracts.CoreModuleStore; - '@sern/modules': () => Contracts.ModuleManager; '@sern/errors': () => Contracts.ErrorHandling; '@sern/logger'?: () => Contracts.Logging; } From f5136ba1ca3b97f34973e20270f5ffde5d8f0bdc Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:26:53 -0500 Subject: [PATCH 06/90] consolidate interfaces in single file --- src/core/contracts/emitter.ts | 9 ---- src/core/contracts/error-handling.ts | 16 ------ src/core/contracts/hooks.ts | 16 ------ src/core/contracts/index.ts | 5 -- src/core/contracts/logging.ts | 11 ---- src/core/id.ts | 11 ++-- src/core/index.ts | 2 +- src/core/interfaces.ts | 54 +++++++++++++++++++ src/core/ioc/base.ts | 2 +- src/core/module-loading.ts | 30 +++++------ src/core/modules.ts | 2 - src/core/operators.ts | 2 +- src/core/presences.ts | 2 +- .../structures/services/error-handling.ts | 2 +- src/core/structures/services/logger.ts | 2 +- src/handlers/dispatchers.ts | 6 +-- src/handlers/event-utils.ts | 2 +- src/handlers/ready-event.ts | 12 +++-- src/index.ts | 2 +- src/types/ioc.ts | 2 +- 20 files changed, 88 insertions(+), 102 deletions(-) delete mode 100644 src/core/contracts/emitter.ts delete mode 100644 src/core/contracts/error-handling.ts delete mode 100644 src/core/contracts/hooks.ts delete mode 100644 src/core/contracts/index.ts delete mode 100644 src/core/contracts/logging.ts create mode 100644 src/core/interfaces.ts diff --git a/src/core/contracts/emitter.ts b/src/core/contracts/emitter.ts deleted file mode 100644 index 11bbc286..00000000 --- a/src/core/contracts/emitter.ts +++ /dev/null @@ -1,9 +0,0 @@ -//i deleted it, hmm so how should we allow users to enable localization? -// a -import type { AnyFunction } from '../../types/utility'; - -export interface Emitter { - addListener(eventName: string | symbol, listener: AnyFunction): this; - removeListener(eventName: string | symbol, listener: AnyFunction): this; - emit(eventName: string | symbol, ...payload: any[]): boolean; -} diff --git a/src/core/contracts/error-handling.ts b/src/core/contracts/error-handling.ts deleted file mode 100644 index d5e94550..00000000 --- a/src/core/contracts/error-handling.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @since 2.0.0 - */ -export interface ErrorHandling { - /** - * @deprecated - * Version 4 will remove this method - */ - crash(err: Error): never; - /** - * A function that is called on every throw. - * @param error - */ - updateAlive(error: Error): void; - -} diff --git a/src/core/contracts/hooks.ts b/src/core/contracts/hooks.ts deleted file mode 100644 index ee329dde..00000000 --- a/src/core/contracts/hooks.ts +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * Represents an initialization contract. - * Let dependencies implement this to initiate some logic. - */ -export interface Init { - init(): unknown; -} - -/** - * Represents a Disposable contract. - * Let dependencies implement this to dispose and cleanup. - */ -export interface Disposable { - dispose(): unknown; -} diff --git a/src/core/contracts/index.ts b/src/core/contracts/index.ts deleted file mode 100644 index fdd9bc63..00000000 --- a/src/core/contracts/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './error-handling'; -export * from './logging'; -export * from './hooks'; -export * from './emitter'; - diff --git a/src/core/contracts/logging.ts b/src/core/contracts/logging.ts deleted file mode 100644 index 9ceb7616..00000000 --- a/src/core/contracts/logging.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @since 2.0.0 - */ -export interface Logging { - error(payload: LogPayload): void; - warning(payload: LogPayload): void; - info(payload: LogPayload): void; - debug(payload: LogPayload): void; -} - -export type LogPayload = { message: T }; diff --git a/src/core/id.ts b/src/core/id.ts index 50a781ed..91ab87b8 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -8,17 +8,12 @@ import { CommandType, EventType } from './structures'; */ export function reconstruct(event: T) { switch (event.type) { - case InteractionType.MessageComponent: { - return [`${event.customId}_C${event.componentType}`]; - } + case InteractionType.MessageComponent: return [`${event.customId}_C${event.componentType}`]; case InteractionType.ApplicationCommand: - case InteractionType.ApplicationCommandAutocomplete: { + case InteractionType.ApplicationCommandAutocomplete: return [`${event.commandName}_A${event.commandType}`, `${event.commandName}_B`]; - } //Modal interactions are classified as components for sern - case InteractionType.ModalSubmit: { - return [`${event.customId}_M`]; - } + case InteractionType.ModalSubmit: return [`${event.customId}_M`]; } } /** diff --git a/src/core/index.ts b/src/core/index.ts index ef0881d1..079589fc 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1,4 +1,4 @@ -export * from './contracts'; +export * from './interfaces'; export * from './create-plugins'; export * from './structures'; export * from './ioc'; diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts new file mode 100644 index 00000000..9c1ab4fa --- /dev/null +++ b/src/core/interfaces.ts @@ -0,0 +1,54 @@ +import type { AnyFunction } from '../types/utility'; + + +/** + * Represents an initialization contract. + * Let dependencies implement this to initiate some logic. + */ +export interface Init { + init(): unknown; +} + +/** + * Represents a Disposable contract. + * Let dependencies implement this to dispose and cleanup. + */ +export interface Disposable { + dispose(): unknown; +} + +export interface Emitter { + addListener(eventName: string | symbol, listener: AnyFunction): this; + removeListener(eventName: string | symbol, listener: AnyFunction): this; + emit(eventName: string | symbol, ...payload: any[]): boolean; +} + + +/** + * @since 2.0.0 + */ +export interface ErrorHandling { + /** + * @deprecated + * Version 4 will remove this method + */ + crash(err: Error): never; + /** + * A function that is called on every throw. + * @param error + */ + updateAlive(error: Error): void; + +} + +/** + * @since 2.0.0 + */ +export interface Logging { + error(payload: LogPayload): void; + warning(payload: LogPayload): void; + info(payload: LogPayload): void; + debug(payload: LogPayload): void; +} + +export type LogPayload = { message: T }; diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 59947835..6c65c75c 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -5,7 +5,7 @@ import { CoreContainer } from './container'; import { Result } from 'ts-results-es'; import { __Services } from '../_internal'; import { AnyFunction } from '../../types/utility'; -import type { Logging } from '../contracts/logging'; +import type { Logging } from '../interfaces'; import type { UnpackFunction } from 'iti'; //SIDE EFFECT: GLOBAL DI let containerSubject: CoreContainer>; diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 98dd2cac..3040d67b 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -6,7 +6,7 @@ import { createRequire } from 'node:module'; import type { ImportPayload, Wrapper } from '../types/core'; import type { Module } from '../types/core-modules'; import { existsSync } from 'fs'; -import type { Logging } from './contracts/logging'; +import type { Logging } from './interfaces'; export const parseCallsite = (fpath: string) => { @@ -76,7 +76,7 @@ export const getFullPathTree = (dir: string) => readPaths(path.resolve(dir)); export const filename = (p: string) => fmtFileName(path.basename(p)); -const validExtensions = ['.js', '.cjs', '.mts', '.mjs', '.cts', '.ts', '']; +const validExtensions = ['.js', '.ts', '']; const isSkippable = (filename: string) => { //empty string is for non extension files (directories) return filename[0] === '!' || !validExtensions.includes(path.extname(filename)); @@ -90,23 +90,19 @@ async function deriveFileInfo(dir: string, file: string) { } async function* readPaths(dir: string): AsyncGenerator { - try { - const files = await readdir(dir); - for (const file of files) { - const { fullPath, fileStats, base } = await deriveFileInfo(dir, file); - if (fileStats.isDirectory()) { - //Todo: refactor so that i dont repeat myself for files (line 71) - if (!isSkippable(base)) { - yield* readPaths(fullPath); - } - } else { - if (!isSkippable(base)) { - yield 'file:///' + fullPath; - } + const files = await readdir(dir); + for (const file of files) { + const { fullPath, fileStats, base } = await deriveFileInfo(dir, file); + if (fileStats.isDirectory()) { + //Todo: refactor so that i dont repeat myself for files (line 71) + if (!isSkippable(base)) { + yield* readPaths(fullPath); + } + } else { + if (!isSkippable(base)) { + yield 'file:///' + fullPath; } } - } catch (err) { - throw err; } } diff --git a/src/core/modules.ts b/src/core/modules.ts index 0b3946e6..96136aa7 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -2,8 +2,6 @@ import { ClientEvents } from 'discord.js'; import { EventType } from '../core/structures'; import type { AnyEventPlugin, } from '../types/core-plugin'; import type { - CommandModule, - EventModule, InputCommand, InputEvent, } from '../types/core-modules'; diff --git a/src/core/operators.ts b/src/core/operators.ts index 5350de4d..44fbf545 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -16,7 +16,7 @@ import { pipe, share, } from 'rxjs'; -import { Emitter, ErrorHandling, Logging } from './contracts'; +import { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; import type { PluginResult } from '../types/core-plugin'; import type { Result } from 'ts-results-es' diff --git a/src/core/presences.ts b/src/core/presences.ts index 6e66431d..33ad8cdc 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -1,6 +1,6 @@ import type { ActivitiesOptions } from "discord.js"; import type { IntoDependencies } from "../types/ioc"; -import type { Emitter } from "./contracts/emitter"; +import type { Emitter } from "./interfaces"; type Status = 'online' | 'idle' | 'invisible' | 'dnd' type PresenceReduce = (previous: Result) => Result; diff --git a/src/core/structures/services/error-handling.ts b/src/core/structures/services/error-handling.ts index 143639c2..7f53117c 100644 --- a/src/core/structures/services/error-handling.ts +++ b/src/core/structures/services/error-handling.ts @@ -1,4 +1,4 @@ -import { ErrorHandling } from '../../contracts'; +import { ErrorHandling } from '../../interfaces'; /** * @internal diff --git a/src/core/structures/services/logger.ts b/src/core/structures/services/logger.ts index 5de19c72..94597911 100644 --- a/src/core/structures/services/logger.ts +++ b/src/core/structures/services/logger.ts @@ -1,4 +1,4 @@ -import { LogPayload, Logging } from '../../contracts'; +import { LogPayload, Logging } from '../../interfaces'; /** * @internal diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index e1218b62..8bf6cffb 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -61,10 +61,8 @@ export function createDispatcher(payload: { module: Processed; event: BaseInteraction; }) { - assert.ok( - CommandType.Text !== payload.module.type, - SernError.MismatchEvent + 'Found text command in interaction stream', - ); + assert.ok(CommandType.Text !== payload.module.type, + SernError.MismatchEvent + 'Found text command in interaction stream'); switch (payload.module.type) { case CommandType.Slash: case CommandType.Both: { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 6eff29f8..f66f4e99 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -85,7 +85,7 @@ export function createInteractionHandler( export function createMessageHandler( source: Observable, defaultPrefix: string, - mg: any, //TODO + mg: any, ) { return createGenericHandler(source, async event => { const [prefix, ...rest] = fmt(event.content, defaultPrefix); diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 7be2e7a8..8b1a671f 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -1,8 +1,13 @@ import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; import { _Module } from '../core/_internal'; -import { Logging, } from '../core/contracts'; +import { Logging, } from '../core/interfaces'; import type { DependencyList } from '../types/ioc'; +const once = (log: Logging | undefined) => pipe( + tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), + first(), + ignoreElements()) + export function readyHandler( [sEmitter, , log ,, client]: DependencyList, allPaths: ObservableInput, @@ -17,7 +22,4 @@ export function readyHandler( // `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); } -const once = (log: Logging | undefined) => pipe( - tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), - first(), - ignoreElements()) + diff --git a/src/index.ts b/src/index.ts index 1f0af398..9bbe41e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -40,7 +40,7 @@ export type { Wrapper } from './types/core'; export type { Args, SlashOptions, Payload, SernEventsMapping } from './types/utility'; -export type { Singleton, Transient, CoreDependencies, Initializable } from './types/ioc'; +export type { Singleton, Transient, CoreDependencies } from './types/ioc'; export { commandModule, diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 290ce28a..303ed241 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -1,5 +1,5 @@ import { Container, UnpackFunction } from 'iti'; -import * as Contracts from '../core/contracts'; +import * as Contracts from '../core/interfaces'; /** * Type to annotate that something is a singleton. * T is created once and lazily. From 9faae7eca7a03ce4b2ae158e55e57c00b767b182 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:36:50 -0500 Subject: [PATCH 07/90] consolidate default services in single file --- src/core/_internal.ts | 2 +- .../logger.ts => default-services.ts} | 22 ++++++++++++++++++- src/core/structures/index.ts | 2 +- .../structures/services/error-handling.ts | 21 ------------------ src/core/structures/services/index.ts | 2 -- src/types/core-plugin.ts | 2 +- src/types/core.ts | 11 ---------- 7 files changed, 24 insertions(+), 38 deletions(-) rename src/core/structures/{services/logger.ts => default-services.ts} (60%) delete mode 100644 src/core/structures/services/error-handling.ts delete mode 100644 src/core/structures/services/index.ts diff --git a/src/core/_internal.ts b/src/core/_internal.ts index be7f2a57..35045973 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -5,7 +5,7 @@ export * from './operators'; export * as Files from './module-loading'; export * from './functions'; export { SernError } from './structures/enums'; -export * as __Services from './structures/services'; +export { __Services } from './structures'; export { useContainerRaw } from './ioc/base'; export type _Module = { diff --git a/src/core/structures/services/logger.ts b/src/core/structures/default-services.ts similarity index 60% rename from src/core/structures/services/logger.ts rename to src/core/structures/default-services.ts index 94597911..c4c11692 100644 --- a/src/core/structures/services/logger.ts +++ b/src/core/structures/default-services.ts @@ -1,4 +1,24 @@ -import { LogPayload, Logging } from '../../interfaces'; +import type { LogPayload, Logging, ErrorHandling } from '../interfaces'; +/** + * @internal + * @since 2.0.0 + * Version 4.0.0 will internalize this api. Please refrain from using the defaults! + */ +export class DefaultErrorHandling implements ErrorHandling { + crash(err: Error): never { + throw err; + } + + #keepAlive = 1; + + updateAlive(err: Error) { + this.#keepAlive--; + if (this.#keepAlive === 0) { + throw err; + } + } +} + /** * @internal diff --git a/src/core/structures/index.ts b/src/core/structures/index.ts index 64b87555..1a715ae4 100644 --- a/src/core/structures/index.ts +++ b/src/core/structures/index.ts @@ -1,4 +1,4 @@ export { CommandType, PluginType, PayloadType, EventType } from './enums'; export * from './context'; -export * from './services'; +export * as __Services from './default-services'; diff --git a/src/core/structures/services/error-handling.ts b/src/core/structures/services/error-handling.ts deleted file mode 100644 index 7f53117c..00000000 --- a/src/core/structures/services/error-handling.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ErrorHandling } from '../../interfaces'; - -/** - * @internal - * @since 2.0.0 - * Version 4.0.0 will internalize this api. Please refrain from using the defaults! - */ -export class DefaultErrorHandling implements ErrorHandling { - crash(err: Error): never { - throw err; - } - - #keepAlive = 1; - - updateAlive(err: Error) { - this.#keepAlive--; - if (this.#keepAlive === 0) { - throw err; - } - } -} diff --git a/src/core/structures/services/index.ts b/src/core/structures/services/index.ts deleted file mode 100644 index 3074d8f5..00000000 --- a/src/core/structures/services/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './error-handling'; -export * from './logger'; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index ae92c688..3d08899f 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -11,7 +11,7 @@ * Plugins are reminiscent of middleware in express. */ -import type { Err, Ok, Result } from 'ts-results-es'; +import type { Err, Ok } from 'ts-results-es'; import type { BothCommand, ButtonCommand, diff --git a/src/types/core.ts b/src/types/core.ts index 0985d60f..e388cf7a 100644 --- a/src/types/core.ts +++ b/src/types/core.ts @@ -9,15 +9,4 @@ export interface Wrapper { commands: string; defaultPrefix?: string; events?: string; - /** - * Overload to enable mode in case developer does not use a .env file. - * @deprecated - https://github.com/sern-handler/handler/pull/325 - */ - mode?: string - /* - * @deprecated - */ - containerConfig?: { - get: (...keys: (keyof Dependencies)[]) => unknown[]; - }; } From 6105f7b4ef24a0935b3e4d3893314f2838bb86c2 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:50:49 -0500 Subject: [PATCH 08/90] TEAR IT UP --- src/core/module-loading.ts | 52 ----------------------------- src/handlers/_internal.ts | 2 -- src/handlers/event-utils.ts | 8 ----- src/handlers/interaction-event.ts | 2 +- src/handlers/message-event.ts | 2 +- src/handlers/ready-event.ts | 2 +- src/handlers/user-defined-events.ts | 23 +++++++------ src/sern.ts | 2 +- 8 files changed, 16 insertions(+), 77 deletions(-) delete mode 100644 src/handlers/_internal.ts diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 3040d67b..978aa25e 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,10 +1,7 @@ -import { type Observable, from, mergeMap, ObservableInput } from 'rxjs'; -import { readdir, stat } from 'fs/promises'; import path from 'node:path'; import assert from 'assert'; import { createRequire } from 'node:module'; import type { ImportPayload, Wrapper } from '../types/core'; -import type { Module } from '../types/core-modules'; import { existsSync } from 'fs'; import type { Logging } from './interfaces'; @@ -52,60 +49,11 @@ export async function importModule(absPath: string) { return { module: commandModule } as T; } -export async function defaultModuleLoader(absPath: string): ModuleResult { - let { module } = await importModule<{ module: T }>(absPath); - assert(module, `Found an undefined module: ${absPath}`); - return { module, absPath }; -} export const fmtFileName = (fileName: string) => path.parse(fileName).name; -/** - * a directory string is converted into a stream of modules. - * starts the stream of modules that sern needs to process on init - * @returns {Observable<{ mod: Module; absPath: string; }[]>} data from command files - * @param commandDir - */ -export function buildModuleStream( - input: ObservableInput, -): Observable> { - return from(input).pipe(mergeMap(defaultModuleLoader)); -} - -export const getFullPathTree = (dir: string) => readPaths(path.resolve(dir)); - export const filename = (p: string) => fmtFileName(path.basename(p)); -const validExtensions = ['.js', '.ts', '']; -const isSkippable = (filename: string) => { - //empty string is for non extension files (directories) - return filename[0] === '!' || !validExtensions.includes(path.extname(filename)); -}; - -async function deriveFileInfo(dir: string, file: string) { - const fullPath = path.join(dir, file); - return { fullPath, - fileStats: await stat(fullPath), - base: path.basename(file) }; -} - -async function* readPaths(dir: string): AsyncGenerator { - const files = await readdir(dir); - for (const file of files) { - const { fullPath, fileStats, base } = await deriveFileInfo(dir, file); - if (fileStats.isDirectory()) { - //Todo: refactor so that i dont repeat myself for files (line 71) - if (!isSkippable(base)) { - yield* readPaths(fullPath); - } - } else { - if (!isSkippable(base)) { - yield 'file:///' + fullPath; - } - } - } -} - const requir = createRequire(import.meta.url); export function loadConfig(wrapper: Wrapper | 'file', log: Logging | undefined): Wrapper { diff --git a/src/handlers/_internal.ts b/src/handlers/_internal.ts deleted file mode 100644 index 4813218e..00000000 --- a/src/handlers/_internal.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './dispatchers'; -export * from './event-utils'; diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index f66f4e99..69020219 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -99,15 +99,7 @@ export function createMessageHandler( return Ok({ args: contextArgs(event, rest), module: fullPath as Processed }) }); } -/** - * This function assigns remaining, incomplete data to each imported module. - */ -export function buildModules( - input: ObservableInput, -) { - return Files.buildModuleStream>(input); -} interface ExecutePayload { diff --git a/src/handlers/interaction-event.ts b/src/handlers/interaction-event.ts index e9ec3fe6..62a125a4 100644 --- a/src/handlers/interaction-event.ts +++ b/src/handlers/interaction-event.ts @@ -11,7 +11,7 @@ import { filterTap, resultPayload, } from '../core/_internal'; -import { createInteractionHandler, executeModule, makeModuleExecutor } from './_internal'; +import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; import type { DependencyList } from '../types/ioc'; export function interactionHandler([emitter, err, log, modules, client]: DependencyList) { diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index a1c1a690..cc6fda19 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -2,7 +2,7 @@ import { mergeMap, EMPTY, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; import { PayloadType } from '../core'; import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; -import { createMessageHandler, executeModule, makeModuleExecutor } from './_internal'; +import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; import type { DependencyList } from '../types/ioc'; /** diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 8b1a671f..62746386 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -1,6 +1,6 @@ import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; import { _Module } from '../core/_internal'; -import { Logging, } from '../core/interfaces'; +import { Logging } from '../core/interfaces'; import type { DependencyList } from '../types/ioc'; const once = (log: Logging | undefined) => pipe( diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 66e7dfb7..6c794f6c 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,7 +1,8 @@ import { ObservableInput, map, mergeAll } from 'rxjs'; import { EventType } from '../core/structures'; import { SernError } from '../core/_internal'; -import { buildModules, callInitPlugins, handleCrash, eventDispatcher } from './_internal'; +import { callInitPlugins, handleCrash } from './event-utils'; +import { eventDispatcher } from './dispatchers' import { Service } from '../core/ioc'; import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; @@ -23,14 +24,14 @@ export function eventsHandler( throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; - buildModules(allPaths) - .pipe( - callInitPlugins(emitter), - map(intoDispatcher), - /** - * Where all events are turned on - */ - mergeAll(), - handleCrash(err, emitter, log)) - .subscribe(); +// buildModules(allPaths) +// .pipe( +// callInitPlugins(emitter), +// map(intoDispatcher), +// /** +// * Where all events are turned on +// */ +// mergeAll(), +// handleCrash(err, emitter, log)) +// .subscribe(); } diff --git a/src/sern.ts b/src/sern.ts index 769c8d2d..b64d79ab 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,4 +1,4 @@ -import { handleCrash } from './handlers/_internal'; +import { handleCrash } from './handlers/event-utils'; import callsites from 'callsites'; import { Files } from './core/_internal'; import { merge } from 'rxjs'; From 68c5f09b46c8eb0bb3d72a9422baa3ad90385c74 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:20:36 -0500 Subject: [PATCH 09/90] fix text compile --- src/core/module-loading.ts | 2 +- src/core/operators.ts | 15 ++++++--------- test/core/contracts.test.ts | 13 ++++--------- test/core/services.test.ts | 32 +++---------------------------- test/handlers/dispatchers.test.ts | 2 +- 5 files changed, 15 insertions(+), 49 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 978aa25e..3f6ff9ed 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -13,6 +13,7 @@ export const parseCallsite = (fpath: string) => { return { name: pathobj.name, absPath : path.posix.format(pathobj) } } + export const shouldHandle = (pth: string, filenam: string) => { const file_name = filenam+path.extname(pth); let newPath = path.join(path.dirname(pth), file_name) @@ -22,7 +23,6 @@ export const shouldHandle = (pth: string, filenam: string) => { } -export type ModuleResult = Promise>; /** * Import any module based on the absolute path. diff --git a/src/core/operators.ts b/src/core/operators.ts index 44fbf545..28f1c33d 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -51,14 +51,13 @@ export const arrayifySource = map(src => (Array.isArray(src) ? (src as unknown[] /** * Checks if the stream of results is all ok. */ -export const everyPluginOk: OperatorFunction = pipe( - every(result => result.isOk()), - defaultIfEmpty(true), -); +export const everyPluginOk: OperatorFunction = + pipe(every(result => result.isOk()), + defaultIfEmpty(true)); + +export const sharedEventStream = (e: Emitter, eventName: string) => + (fromEvent(e, eventName) as Observable).pipe(share()); -export const sharedEventStream = (e: Emitter, eventName: string) => { - return (fromEvent(e, eventName) as Observable).pipe(share()); -}; export function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { return (pload: unknown, caught: Observable) => { @@ -80,5 +79,3 @@ export const filterTap = (onErr: (e: R) => void): OperatorFunction { it('should satisfy contracts', () => { - assertType(new DefaultContracts.DefaultLogging()); - assertType(new DefaultContracts.DefaultErrorHandling()); - assertType( - new DefaultContracts.DefaultModuleManager(new ModuleStore()), - ); - assertType(new ModuleStore()); + assertType(new __Services.DefaultLogging()); + assertType(new __Services.DefaultErrorHandling()); }); }); diff --git a/test/core/services.test.ts b/test/core/services.test.ts index cfd963aa..148fdf65 100644 --- a/test/core/services.test.ts +++ b/test/core/services.test.ts @@ -1,10 +1,9 @@ import { SpyInstance, afterAll, beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; -import { DefaultLogging } from '../../src/core'; +import { __Services } from '../../src/core/structures/'; import { faker } from '@faker-js/faker'; import { commandModule, CommandType } from '../../src'; -import * as Id from '../../src/core/id'; -import { CommandMeta } from '../../src/types/core-modules'; + function createRandomCommandModules() { return commandModule({ type: CommandType.Slash, @@ -19,7 +18,7 @@ describe('services', () => { let consoleMock: SpyInstance; beforeEach(() => { container = new CoreContainer(); - container.add({ '@sern/logger': () => new DefaultLogging() }); + container.add({ '@sern/logger': () => new __Services.DefaultLogging() }); container.ready(); consoleMock = vi.spyOn(container.get('@sern/logger'), 'error').mockImplementation(() => {}); }); @@ -27,31 +26,6 @@ describe('services', () => { afterAll(() => { consoleMock.mockReset(); }); - it('module-store.ts', async () => { - const modules = faker.helpers.multiple(createRandomCommandModules, { - count: 40, - }); - - const paths = faker.helpers - .multiple(faker.system.directoryPath, { count: 40 }) - .map((path, i) => `${path}/${modules[i]}.js`); - - const metadata: CommandMeta[] = modules.map((cm, i) => ({ - id: Id.create(cm.name!, cm.type), - isClass: false, - fullPath: `${paths[i]}/${cm.name}.js`, - })); - const moduleManager = container.get('@sern/modules'); - let i = 0; - for (const m of modules) { - moduleManager.set(Id.create(m.name!, m.type), paths[i]); - moduleManager.setMetadata(m, metadata[i]); - i++; - } - for (const m of modules) { - expect(moduleManager.getMetadata(m), 'module references do not exist').toBeDefined(); - } - }); //todo add more it('error-handling', () => { diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index 0f100d25..a8c77215 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, vi, it } from 'vitest'; -import { createResultResolver, eventDispatcher } from '../../src/handlers/_internal'; +import { eventDispatcher } from '../../src/handlers/dispatchers'; import { faker } from '@faker-js/faker'; import { Module } from '../../src/core/types/modules'; import { Processed } from '../../src/handlers/types'; From 071d5eac490315065238ba2cf083617d0f32db2f Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 22:16:54 -0500 Subject: [PATCH 10/90] the end of sern init?? --- src/core/create-plugins.ts | 5 +---- src/core/ioc/base.ts | 5 +---- src/core/ioc/dependency-injection.ts | 7 ------- src/core/module-loading.ts | 6 +++--- src/index.ts | 8 +++++--- src/sern.ts | 17 +++++++++-------- src/types/core.ts | 12 ------------ test/core/ioc.test.ts | 9 +++------ 8 files changed, 22 insertions(+), 47 deletions(-) delete mode 100644 src/types/core.ts diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index b8d6192e..4db4ce60 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -7,10 +7,7 @@ export function makePlugin( type: PluginType, execute: (...args: any[]) => any, ): Plugin { - return { - type, - execute, - } as Plugin; + return { type, execute, } as Plugin; } /** * @since 2.5.0 diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 6c65c75c..2f3d90bc 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,5 +1,4 @@ import * as assert from 'assert'; -import { useContainer } from './dependency-injection'; import type { CoreDependencies, DependencyConfiguration } from '../../types/ioc'; import { CoreContainer } from './container'; import { Result } from 'ts-results-es'; @@ -141,7 +140,7 @@ function composeRoot( container.ready(); } -export async function makeDependencies +export async function makeDependencies (conf: ValidDependencyConfig) { containerSubject = new CoreContainer(); if(typeof conf === 'function') { @@ -160,7 +159,5 @@ export async function makeDependencies } else { composeRoot(containerSubject, conf); } - - return useContainer(); } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index f792b8ae..ac1b3692 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -48,10 +48,3 @@ export function Services(...keys: [...T] const container = useContainerRaw(); return keys.map(k => container.get(k)!) as IntoDependencies; } - - -export function useContainer() { - return (...keys: [...V]) => - keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as IntoDependencies; -} - diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 3f6ff9ed..48c68868 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import assert from 'assert'; import { createRequire } from 'node:module'; -import type { ImportPayload, Wrapper } from '../types/core'; +import type { Wrapper } from '../types/core'; import { existsSync } from 'fs'; import type { Logging } from './interfaces'; @@ -17,7 +17,7 @@ export const parseCallsite = (fpath: string) => { export const shouldHandle = (pth: string, filenam: string) => { const file_name = filenam+path.extname(pth); let newPath = path.join(path.dirname(pth), file_name) - .replace(/file:\\?/, ""); + .replace(/file:\\?/, ""); return { exists: existsSync(newPath), path: 'file:///'+newPath }; } @@ -42,7 +42,7 @@ export async function importModule(absPath: string) { let commandModule = fileModule.default; - assert(commandModule , `Found no export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); + assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); if ('default' in commandModule) { commandModule = commandModule.default; } diff --git a/src/index.ts b/src/index.ts index 9bbe41e3..dcb35dc3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,10 +36,12 @@ export type { AnyCommandPlugin, } from './types/core-plugin'; -export type { Wrapper } from './types/core'; - +export interface Wrapper { + commands: string; + defaultPrefix?: string; + events?: string; +} export type { Args, SlashOptions, Payload, SernEventsMapping } from './types/utility'; - export type { Singleton, Transient, CoreDependencies } from './types/ioc'; export { diff --git a/src/sern.ts b/src/sern.ts index b64d79ab..d716ee15 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,15 +1,16 @@ import { handleCrash } from './handlers/event-utils'; import callsites from 'callsites'; import { Files } from './core/_internal'; +import path from 'node:path' import { merge } from 'rxjs'; import { Services } from './core/ioc'; -import { Wrapper } from './types/core'; import { eventsHandler } from './handlers/user-defined-events'; import { readyHandler } from './handlers/ready-event'; import { messageHandler } from './handlers/message-event'; import { interactionHandler } from './handlers/interaction-event'; import { presenceHandler } from './handlers/presence'; import type { Client } from 'discord.js'; +import { type Wrapper } from './'; /** @@ -24,7 +25,7 @@ import type { Client } from 'discord.js'; * }) * ``` */ -export function init(maybeWrapper: Wrapper | 'file') { +export function init() { const startTime = performance.now(); const dependencies = Services('@sern/emitter', '@sern/errors', @@ -33,14 +34,15 @@ export function init(maybeWrapper: Wrapper | 'file') { const logger = dependencies[2], errorHandler = dependencies[1]; - const wrapper = Files.loadConfig(maybeWrapper, logger); - if (wrapper.events !== undefined) { + //const wrapper = Files.loadConfig(maybeWrapper, logger); + //if (wrapper.events !== undefined) { //eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); - } - + // } + //import(path.resolve("commands.js")) + //.then(({ commands }) => { }) + //.catch(message => logger?.error({ message })) const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); - //Ready event: load all modules and when finished, time should be taken and logged // readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) // .add(() => { @@ -55,7 +57,6 @@ export function init(maybeWrapper: Wrapper | 'file') { // presenceHandler(presencePath.path, setPresence).subscribe(); // } // }); - //const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); //const interactions$ = interactionHandler(dependencies); // listening to the message stream and interaction stream diff --git a/src/types/core.ts b/src/types/core.ts deleted file mode 100644 index e388cf7a..00000000 --- a/src/types/core.ts +++ /dev/null @@ -1,12 +0,0 @@ - -export interface ImportPayload { - module: T; - absPath: string; - [key: string]: unknown; -} - -export interface Wrapper { - commands: string; - defaultPrefix?: string; - events?: string; -} diff --git a/test/core/ioc.test.ts b/test/core/ioc.test.ts index e7903071..51f712b1 100644 --- a/test/core/ioc.test.ts +++ b/test/core/ioc.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; import { EventEmitter } from 'events'; -import { DefaultLogging, Disposable, Emitter, Init, Logging } from '../../src/core'; +import { Disposable, Emitter, Init, Logging, __Services } from '../../src/core'; import { CoreDependencies } from '../../src/types/ioc'; describe('ioc container', () => { @@ -43,13 +43,12 @@ describe('ioc container', () => { }); it('should container all core dependencies', async () => { const keys = [ - '@sern/modules', '@sern/emitter', '@sern/logger', '@sern/errors', ] satisfies (keyof CoreDependencies)[]; container.add({ - '@sern/logger': () => new DefaultLogging(), + '@sern/logger': () => new __Services.DefaultLogging(), '@sern/client': () => new EventEmitter(), }); for (const k of keys) { @@ -92,9 +91,7 @@ describe('ioc container', () => { it('should init dependency depending on something else', () => { container.add({ '@sern/client': dependency2 }); - container.upsert((cntr) => ({ - '@sern/logger': dependency - })); + container.upsert((cntr) => ({ '@sern/logger': dependency })); container.ready(); expect(dependency.init).toHaveBeenCalledTimes(1); }) From e6fba9d8b50278e006ea2bcb24433f3aa10b3196 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 28 Apr 2024 23:37:58 -0500 Subject: [PATCH 11/90] Presence namespaced types removed --- package.json | 10 ++- src/_internal.ts | 34 ++++++++ src/core/module-loading.ts | 32 -------- src/core/modules.ts | 5 +- src/core/presences.ts | 102 ++++++++++++------------ src/core/structures/default-services.ts | 8 +- src/handlers/presence.ts | 8 +- src/index.ts | 3 +- src/sern.ts | 11 --- tsconfig.json | 3 +- tsup.config.js | 11 +++ 11 files changed, 114 insertions(+), 113 deletions(-) create mode 100644 src/_internal.ts diff --git a/package.json b/package.json index 8da8116b..11612794 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,19 @@ "version": "3.3.4", "description": "A complete, customizable, typesafe, & reactive framework for discord bots.", "main": "./dist/index.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.js", "types": "./dist/index.d.ts" + }, + "./internal": { + "import": "./dist/_internal.js", + "require": "./dist/_internal.js", + "types": "./dist/_internal.d.ts" + } }, "scripts": { diff --git a/src/_internal.ts b/src/_internal.ts new file mode 100644 index 00000000..93382d9b --- /dev/null +++ b/src/_internal.ts @@ -0,0 +1,34 @@ +import type { Interaction } from 'discord.js'; +import { mergeMap, merge, concatMap } from 'rxjs'; +import { PayloadType } from './core'; +import { + isAutocomplete, + isCommand, + isMessageComponent, + isModal, + sharedEventStream, + SernError, + filterTap, + resultPayload, +} from './core/_internal'; +import { createInteractionHandler, executeModule, makeModuleExecutor } from './handlers/event-utils'; +import type { DependencyList } from './types/ioc'; + + +export function interactionHandler([emitter, err, log, modules, client]: DependencyList) { + const interactionStream$ = sharedEventStream(client, 'interactionCreate'); + const handle = createInteractionHandler(interactionStream$, modules); + + const interactionHandler$ = merge( + handle(isMessageComponent), + handle(isAutocomplete), + handle(isCommand), + handle(isModal), + ); + return interactionHandler$ + .pipe( + filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + concatMap(makeModuleExecutor(module => + emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), + mergeMap(payload => executeModule(emitter, log, err, payload))); +} diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 48c68868..b2be6ab1 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,9 +1,6 @@ import path from 'node:path'; import assert from 'assert'; -import { createRequire } from 'node:module'; -import type { Wrapper } from '../types/core'; import { existsSync } from 'fs'; -import type { Logging } from './interfaces'; export const parseCallsite = (fpath: string) => { @@ -54,32 +51,3 @@ export const fmtFileName = (fileName: string) => path.parse(fileName).name; export const filename = (p: string) => fmtFileName(path.basename(p)); -const requir = createRequire(import.meta.url); - -export function loadConfig(wrapper: Wrapper | 'file', log: Logging | undefined): Wrapper { - if (wrapper !== 'file') { - return wrapper; - } - log?.info({ message: 'Experimental loading of sern.config.json'}); - const config = requir(path.resolve('sern.config.json')); - - const makePath = (dir: PropertyKey) => - config.language === 'typescript' - ? path.join('dist', config.paths[dir]!) - : path.join(config.paths[dir]!); - - log?.info({ message: 'Loading config: ' + JSON.stringify(config, null, 4) }); - const commandsPath = makePath('commands'); - - log?.info({ message: `Commands path is set to ${commandsPath}` }); - let eventsPath: string | undefined; - if (config.paths.events) { - eventsPath = makePath('events'); - log?.info({ message: `Events path is set to ${eventsPath} `}); - } - - return { defaultPrefix: config.defaultPrefix, - commands: commandsPath, - events: eventsPath }; - -} diff --git a/src/core/modules.ts b/src/core/modules.ts index 96136aa7..ea361bb4 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -67,9 +67,6 @@ export function discordEvent(mod: { plugins?: AnyEventPlugin[]; execute: (...args: ClientEvents[T]) => Awaitable; }) { - return eventModule({ - type: EventType.Discord, - ...mod, - }); + return eventModule({ type: EventType.Discord, ...mod, }); } diff --git a/src/core/presences.ts b/src/core/presences.ts index 33ad8cdc..dbd5c6b1 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -3,65 +3,63 @@ import type { IntoDependencies } from "../types/ioc"; import type { Emitter } from "./interfaces"; type Status = 'online' | 'idle' | 'invisible' | 'dnd' -type PresenceReduce = (previous: Result) => Result; +type PresenceReduce = (previous: PresenceResult) => PresenceResult; -export interface Result { +export interface PresenceResult { status?: Status; afk?: boolean; activities?: ActivitiesOptions[]; shardId?: number[]; repeat?: number | [Emitter, string]; - onRepeat?: (previous: Result) => Result; + onRepeat?: (previous: PresenceResult) => PresenceResult; } -export type Config = -{ - inject?: [...T] - execute: (...v: IntoDependencies) => Result; -}; - -/** - * A small wrapper to provide type inference. - * Create a Presence module which **MUST** be put in a file called presence.(language-extension) - * adjacent to the file where **Sern.init** is CALLED. - */ -export const module = (conf: Config) => conf; - - -/** - * Create a Presence body which can be either: - * - once, the presence is activated only once. - * - repeated, per cycle or event, the presence can be changed. - */ -export function of(root: Omit) { - return { - /** - * @example - * Presence - * .of({ - * activities: [{ name: "deez nuts" }] - * }) //starts the presence with "deez nuts". - * .repeated(prev => { - * return { - * afk: true, - * activities: prev.activities?.map(s => ({ ...s, name: s.name+"s" })) - * }; - * }, 10000)) //every 10 s, the callback sets the presence to the returned one. - */ - repeated: (onRepeat: PresenceReduce, repeat: number | [Emitter, string]) => { - return { repeat, onRepeat, ...root } - }, - /** - * @example - * Presence - * .of({ - * activities: [ - * { name: "Chilling out" } - * ] - * }) - * .once() // Sets the presence once, with what's provided in '.of()' - */ - once: () => root - }; +export const Presence = { + /** + * A small wrapper to provide type inference. + * Create a Presence module which **MUST** be put in a file called presence.(language-extension) + * adjacent to the file where **Sern.init** is CALLED. + */ + module : (conf: PresenceConfig) => conf, + /** + * Create a Presence body which can be either: + * - once, the presence is activated only once. + * - repeated, per cycle or event, the presence can be changed. + */ + of : (root: Omit) => { + return { + /** + * @example + * Presence + * .of({ + * activities: [{ name: "deez nuts" }] + * }) //starts the presence with "deez nuts". + * .repeated(prev => { + * return { + * afk: true, + * activities: prev.activities?.map(s => ({ ...s, name: s.name+"s" })) + * }; + * }, 10000)) //every 10 s, the callback sets the presence to the returned one. + */ + repeated: (onRepeat: PresenceReduce, repeat: number | [Emitter, string]) => { + return { repeat, onRepeat, ...root } + }, + /** + * @example + * Presence + * .of({ + * activities: [ + * { name: "Chilling out" } + * ] + * }) + * .once() // Sets the presence once, with what's provided in '.of()' + */ + once: () => root + }; + } } +export type PresenceConfig = { + inject?: [...T] + execute: (...v: IntoDependencies) => PresenceResult; +}; diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index c4c11692..2bcd41d2 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -8,12 +8,10 @@ export class DefaultErrorHandling implements ErrorHandling { crash(err: Error): never { throw err; } - - #keepAlive = 1; - + keepAlive = 1; updateAlive(err: Error) { - this.#keepAlive--; - if (this.#keepAlive === 0) { + this.keepAlive--; + if (this.keepAlive === 0) { throw err; } } diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index 761fbb12..f5caa89f 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -1,12 +1,12 @@ import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" import { Files } from "../core/_internal"; -import * as Presence from "../core/presences"; +import { PresenceConfig, PresenceResult } from "../core/presences"; import { Services } from "../core/ioc"; import assert from "node:assert"; -type SetPresence = (conf: Presence.Result) => Promise +type SetPresence = (conf: PresenceResult) => Promise -const parseConfig = async (conf: Promise) => { +const parseConfig = async (conf: Promise) => { return conf.then(s => { if('repeat' in s) { const { onRepeat, repeat } = s; @@ -25,7 +25,7 @@ const parseConfig = async (conf: Promise) => { export const presenceHandler = (path: string, setPresence: SetPresence) => { interface PresenceModule { - module: Presence.Config<(keyof Dependencies)[]> + module: PresenceConfig<(keyof Dependencies)[]> } const presence = Files .importModule(path) diff --git a/src/index.ts b/src/index.ts index dcb35dc3..06a2ccda 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,5 @@ export { discordEvent, } from './core/modules'; -export * as Presence from './core/presences' - +export * from './core/presences' diff --git a/src/sern.ts b/src/sern.ts index d716ee15..68f2dbbf 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,17 +1,6 @@ -import { handleCrash } from './handlers/event-utils'; import callsites from 'callsites'; import { Files } from './core/_internal'; -import path from 'node:path' -import { merge } from 'rxjs'; import { Services } from './core/ioc'; -import { eventsHandler } from './handlers/user-defined-events'; -import { readyHandler } from './handlers/ready-event'; -import { messageHandler } from './handlers/message-event'; -import { interactionHandler } from './handlers/interaction-event'; -import { presenceHandler } from './handlers/presence'; -import type { Client } from 'discord.js'; -import { type Wrapper } from './'; - /** * @since 1.0.0 diff --git a/tsconfig.json b/tsconfig.json index bbb5bc28..abc01ec3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,8 @@ "allowSyntheticDefaultImports": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, - "module": "esnext", + "outDir": "dist", + "module": "commonjs", "target": "esnext" }, "exclude": ["node_modules", "dist"], diff --git a/tsup.config.js b/tsup.config.js index 812c2a60..ed9811b0 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -1,4 +1,5 @@ import { defineConfig } from 'tsup'; + const shared = { entry: ['src/index.ts'], external: ['discord.js', 'iti'], @@ -12,6 +13,16 @@ const shared = { }, }; export default defineConfig([ + { + ...shared, + format: ['esm', 'cjs'], + target: 'node18', + tsconfig: './tsconfig.json', + outDir: './dist', + minify: false, + dts: true, + entry: ['src/_internal.ts'], + }, { format: ['esm', 'cjs'], target: 'node18', From 821de65b86c7e6d6873b633ace1139694c2c5295 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:08:57 -0500 Subject: [PATCH 12/90] internal namespace --- package.json | 10 +++------- src/_internal.ts | 2 +- src/core/index.ts | 4 ---- src/core/ioc/container.ts | 2 +- src/handlers/dispatchers.ts | 2 +- src/handlers/event-utils.ts | 3 ++- src/handlers/interaction-event.ts | 2 +- src/handlers/message-event.ts | 2 +- src/index.ts | 6 ++++-- src/types/core-modules.ts | 2 +- src/types/core-plugin.ts | 3 ++- src/types/utility.ts | 2 +- 12 files changed, 18 insertions(+), 22 deletions(-) delete mode 100644 src/core/index.ts diff --git a/package.json b/package.json index 11612794..db2658ac 100644 --- a/package.json +++ b/package.json @@ -5,18 +5,14 @@ "description": "A complete, customizable, typesafe, & reactive framework for discord bots.", "main": "./dist/index.js", "module": "./dist/index.js", - "types": "./dist/index.d.ts", "exports": { ".": { "import": "./dist/index.js", - "require": "./dist/index.js", - "types": "./dist/index.d.ts" + "require": "./dist/index.js" }, "./internal": { "import": "./dist/_internal.js", - "require": "./dist/_internal.js", - "types": "./dist/_internal.d.ts" - + "require": "./dist/_internal.js" } }, "scripts": { @@ -25,7 +21,7 @@ "format": "eslint src/**/*.ts --fix", "build:dev": "tsup --metafile", "build:prod": "tsup ", - "prepare": "npm run build:prod", + "prepare": "tsc", "pretty": "prettier --write .", "tdd": "vitest", "test": "vitest --run", diff --git a/src/_internal.ts b/src/_internal.ts index 93382d9b..94cb21cf 100644 --- a/src/_internal.ts +++ b/src/_internal.ts @@ -1,6 +1,6 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap } from 'rxjs'; -import { PayloadType } from './core'; +import { PayloadType } from './core/structures/enums'; import { isAutocomplete, isCommand, diff --git a/src/core/index.ts b/src/core/index.ts deleted file mode 100644 index 079589fc..00000000 --- a/src/core/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './interfaces'; -export * from './create-plugins'; -export * from './structures'; -export * from './ioc'; diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index b063aca8..085f05b9 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,5 +1,5 @@ import { Container } from 'iti'; -import { Disposable } from '../'; +import type { Disposable } from '../interfaces'; import * as assert from 'node:assert'; import { Subject } from 'rxjs'; import { __Services } from '../_internal'; diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index 8bf6cffb..94718846 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -10,7 +10,7 @@ import { } from '../core/_internal'; import { createResultResolver } from './event-utils'; import { BaseInteraction, Message } from 'discord.js'; -import { CommandType, Context } from '../core'; +import { CommandType, Context } from '../core/structures'; import type { Args } from '../types/utility'; import { inspect } from 'node:util' import type { CommandModule, Module, Processed } from '../types/core-modules'; diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 69020219..9b7ffa1f 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -22,7 +22,8 @@ import { VoidResult, resultPayload, } from '../core/_internal'; -import { Emitter, ErrorHandling, Logging, PayloadType } from '../core'; +import { Emitter, ErrorHandling, Logging } from '../core/interfaces'; +import { PayloadType } from '../core/structures/enums' import { contextArgs, createDispatcher } from './dispatchers'; import { ObservableInput, pipe } from 'rxjs'; import { Err, Ok, Result } from 'ts-results-es'; diff --git a/src/handlers/interaction-event.ts b/src/handlers/interaction-event.ts index 62a125a4..a1def254 100644 --- a/src/handlers/interaction-event.ts +++ b/src/handlers/interaction-event.ts @@ -1,6 +1,6 @@ import { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap } from 'rxjs'; -import { PayloadType } from '../core'; +import { PayloadType } from '../core/structures/enums'; import { isAutocomplete, isCommand, diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index cc6fda19..6342bc4d 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -1,6 +1,6 @@ import { mergeMap, EMPTY, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { PayloadType } from '../core'; +import { PayloadType } from '../core/structures/enums'; import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; import type { DependencyList } from '../types/ioc'; diff --git a/src/index.ts b/src/index.ts index 06a2ccda..a391ac57 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ export * as Sern from './sern'; -export * from './core'; export type { CommandModule, EventModule, @@ -51,4 +50,7 @@ export { } from './core/modules'; export * from './core/presences' - +export * from './core/interfaces' +export * from './core/create-plugins'; +export * from './core/structures'; +export * from './core/ioc'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 1cad72fb..51510794 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -15,7 +15,7 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; -import { CommandType, Context, EventType } from '../../src/core'; +import type { CommandType, Context, EventType } from '../core/structures'; import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin'; import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility'; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 3d08899f..0576236e 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -34,7 +34,8 @@ import type { UserSelectCommand, } from './core-modules'; import type { Args, Awaitable, Payload, SlashOptions } from './utility'; -import type { CommandType, Context, EventType, PluginType } from '../core'; +import type { CommandType, EventType, PluginType } from '../core/structures/enums' +import type { Context } from '../core/structures/context' import type { ButtonInteraction, ChannelSelectMenuInteraction, diff --git a/src/types/utility.ts b/src/types/utility.ts index 90339e44..3b05e345 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -1,5 +1,5 @@ import type { CommandInteractionOptionResolver, InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; -import type { PayloadType } from '../core'; +import type { PayloadType } from '../core/structures/enums'; import type { AnyModule } from './core-modules'; export type Awaitable = PromiseLike | T; From 87c5631e57669c7e457574def443f331d0fed67c Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:13:16 -0500 Subject: [PATCH 13/90] clean up dependencies --- package.json | 8 +- tsup.config.js | 35 - yarn.lock | 2258 +----------------------------------------------- 3 files changed, 19 insertions(+), 2282 deletions(-) delete mode 100644 tsup.config.js diff --git a/package.json b/package.json index db2658ac..ff8be39d 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "build:prod": "tsup ", "prepare": "tsc", "pretty": "prettier --write .", - "tdd": "vitest", - "test": "vitest --run", + "tdd": "npx vitest", + "test": "npx vitest --run", "analyze-imports": "npx depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg" }, "keywords": [ @@ -52,9 +52,7 @@ "discord.js": "^14.11.0", "eslint": "8.39.0", "prettier": "2.8.8", - "tsup": "^6.7.0", - "typescript": "5.0.2", - "vitest": "latest" + "typescript": "5.0.2" }, "prettier": { "semi": true, diff --git a/tsup.config.js b/tsup.config.js deleted file mode 100644 index ed9811b0..00000000 --- a/tsup.config.js +++ /dev/null @@ -1,35 +0,0 @@ -import { defineConfig } from 'tsup'; - -const shared = { - entry: ['src/index.ts'], - external: ['discord.js', 'iti'], - platform: 'node', - clean: true, - sourcemap: true, - treeshake: { - moduleSideEffects: false, - correctVarValueBeforeDeclaration: true, //need this to treeshake esm discord.js empty import - annotations: true, - }, -}; -export default defineConfig([ - { - ...shared, - format: ['esm', 'cjs'], - target: 'node18', - tsconfig: './tsconfig.json', - outDir: './dist', - minify: false, - dts: true, - entry: ['src/_internal.ts'], - }, - { - format: ['esm', 'cjs'], - target: 'node18', - tsconfig: './tsconfig.json', - outDir: './dist', - minify: false, - dts: true, - ...shared, - }, - ]); diff --git a/yarn.lock b/yarn.lock index 1bd0fca6..d0c2ed06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -91,314 +91,6 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-arm64@npm:0.17.19" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-arm@npm:0.17.19" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-x64@npm:0.17.19" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/darwin-arm64@npm:0.17.19" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/darwin-x64@npm:0.17.19" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/freebsd-arm64@npm:0.17.19" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/freebsd-x64@npm:0.17.19" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-arm64@npm:0.17.19" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-arm@npm:0.17.19" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-ia32@npm:0.17.19" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-loong64@npm:0.17.19" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-mips64el@npm:0.17.19" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-ppc64@npm:0.17.19" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-riscv64@npm:0.17.19" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-s390x@npm:0.17.19" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-x64@npm:0.17.19" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/netbsd-x64@npm:0.17.19" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/openbsd-x64@npm:0.17.19" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/sunos-x64@npm:0.17.19" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-arm64@npm:0.17.19" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-ia32@npm:0.17.19" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-x64@npm:0.17.19" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -480,71 +172,6 @@ __metadata: languageName: node linkType: hard -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: ^5.1.2 - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: ^7.0.1 - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: ^8.1.0 - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb - languageName: node - linkType: hard - -"@jest/schemas@npm:^29.6.3": - version: 29.6.3 - resolution: "@jest/schemas@npm:29.6.3" - dependencies: - "@sinclair/typebox": ^0.27.8 - checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" - dependencies: - "@jridgewell/set-array": ^1.0.1 - "@jridgewell/sourcemap-codec": ^1.4.10 - "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.19 - resolution: "@jridgewell/trace-mapping@npm:0.3.19" - dependencies: - "@jridgewell/resolve-uri": ^3.1.0 - "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: 956a6f0f6fec060fb48c6bf1f5ec2064e13cd38c8be3873877d4b92b4a27ba58289a34071752671262a3e3c202abcc3fa2aac64d8447b4b0fa1ba3c9047f1c20 - languageName: node - linkType: hard - "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -572,22 +199,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/fs@npm:^3.1.0": - version: 3.1.0 - resolution: "@npmcli/fs@npm:3.1.0" - dependencies: - semver: ^7.3.5 - checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f - languageName: node - linkType: hard - "@sapphire/async-queue@npm:^1.5.0": version: 1.5.0 resolution: "@sapphire/async-queue@npm:1.5.0" @@ -634,42 +245,10 @@ __metadata: prettier: 2.8.8 rxjs: ^7.8.0 ts-results-es: ^4.1.0 - tsup: ^6.7.0 typescript: 5.0.2 - vitest: latest languageName: unknown linkType: soft -"@sinclair/typebox@npm:^0.27.8": - version: 0.27.8 - resolution: "@sinclair/typebox@npm:0.27.8" - checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 - languageName: node - linkType: hard - -"@tootallnate/once@npm:2": - version: 2.0.0 - resolution: "@tootallnate/once@npm:2.0.0" - checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 - languageName: node - linkType: hard - -"@types/chai-subset@npm:^1.3.3": - version: 1.3.3 - resolution: "@types/chai-subset@npm:1.3.3" - dependencies: - "@types/chai": "*" - checksum: 4481da7345022995f5a105e6683744f7203d2c3d19cfe88d8e17274d045722948abf55e0adfd97709e0f043dade37a4d4e98cd4c660e2e8a14f23e6ecf79418f - languageName: node - linkType: hard - -"@types/chai@npm:*, @types/chai@npm:^4.3.5": - version: 4.3.6 - resolution: "@types/chai@npm:4.3.6" - checksum: 32a6c18bf53fb3dbd89d1bfcadb1c6fd45cc0007c34e436393cc37a0a5a556f9e6a21d1e8dd71674c40cc36589d2f30bf4d9369d7787021e54d6e997b0d7300a - languageName: node - linkType: hard - "@types/json-schema@npm:^7.0.9": version: 7.0.12 resolution: "@types/json-schema@npm:7.0.12" @@ -882,59 +461,6 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/expect@npm:0.34.3" - dependencies: - "@vitest/spy": 0.34.3 - "@vitest/utils": 0.34.3 - chai: ^4.3.7 - checksum: 79afaa37d2efb7bb5503332caf389860b2261f198dbe61557e8061262b628d18658e59eb51d1808ecd35fc59f4bb4d04c0e0f97a27c7db02584ab5b424147b8d - languageName: node - linkType: hard - -"@vitest/runner@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/runner@npm:0.34.3" - dependencies: - "@vitest/utils": 0.34.3 - p-limit: ^4.0.0 - pathe: ^1.1.1 - checksum: 945580eaa58e8edbe29a64059bc2a524a9e85117b6d600fdb457cfe84cbfb81bf6d7e98e1227e7cb4e7399992c8fe8d83d0791d0385ff005dc1a4d9da125443b - languageName: node - linkType: hard - -"@vitest/snapshot@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/snapshot@npm:0.34.3" - dependencies: - magic-string: ^0.30.1 - pathe: ^1.1.1 - pretty-format: ^29.5.0 - checksum: 234893e91a1efd4bdbbde047a68de40975e02ead8407724ce8ca4a24edf0fb2d725f8a3efceb104965388407b598faf22407aadfbf4164cc74b3cf1e0e9f4543 - languageName: node - linkType: hard - -"@vitest/spy@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/spy@npm:0.34.3" - dependencies: - tinyspy: ^2.1.1 - checksum: a2b64b9c357a56ad2f2340ecd225ffe787e61afba4ffb24a6670aad3fc90ea2606ed48daa188ed62b3ef67d55c0259fda6b101143d6c91b58c9ac4298d8be4f9 - languageName: node - linkType: hard - -"@vitest/utils@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/utils@npm:0.34.3" - dependencies: - diff-sequences: ^29.4.3 - loupe: ^2.3.6 - pretty-format: ^29.5.0 - checksum: aeb8ef7fd98b32cb6c403796880d0aa8f5411bbdb249bb23b3301a70e1b7d1ee025ddb204aae8c1db5756f6ac428c49ebbb8e2ed23ce185c8a659b67413efa85 - languageName: node - linkType: hard - "@vladfrangu/async_event_emitter@npm:^2.2.2": version: 2.2.4 resolution: "@vladfrangu/async_event_emitter@npm:2.2.4" @@ -942,13 +468,6 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^1.0.0": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 - languageName: node - linkType: hard - "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -958,14 +477,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.2.0": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 - languageName: node - linkType: hard - -"acorn@npm:^8.10.0, acorn@npm:^8.9.0": +"acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" bin: @@ -974,34 +486,6 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:6, agent-base@npm:^6.0.2": - version: 6.0.2 - resolution: "agent-base@npm:6.0.2" - dependencies: - debug: 4 - checksum: f52b6872cc96fd5f622071b71ef200e01c7c4c454ee68bc9accca90c98cfb39f2810e3e9aa330435835eedc8c23f4f8a15267f67c6e245d2b33757575bdac49d - languageName: node - linkType: hard - -"agentkeepalive@npm:^4.2.1": - version: 4.5.0 - resolution: "agentkeepalive@npm:4.5.0" - dependencies: - humanize-ms: ^1.2.1 - checksum: 13278cd5b125e51eddd5079f04d6fe0914ac1b8b91c1f3db2c1822f99ac1a7457869068997784342fe455d59daaff22e14fb7b8c3da4e741896e7e31faf92481 - languageName: node - linkType: hard - -"aggregate-error@npm:^3.0.0": - version: 3.1.0 - resolution: "aggregate-error@npm:3.1.0" - dependencies: - clean-stack: ^2.0.0 - indent-string: ^4.0.0 - checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 - languageName: node - linkType: hard - "ajv@npm:^6.10.0, ajv@npm:^6.12.4": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -1021,14 +505,7 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": +"ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" dependencies: @@ -1037,54 +514,6 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^5.0.0": - version: 5.2.0 - resolution: "ansi-styles@npm:5.2.0" - checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 - languageName: node - linkType: hard - -"any-promise@npm:^1.0.0": - version: 1.3.0 - resolution: "any-promise@npm:1.3.0" - checksum: 0ee8a9bdbe882c90464d75d1f55cf027f5458650c4bd1f0467e65aec38ccccda07ca5844969ee77ed46d04e7dded3eaceb027e8d32f385688523fe305fa7e1de - languageName: node - linkType: hard - -"anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: ^3.0.0 - picomatch: ^2.0.4 - checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 - languageName: node - linkType: hard - -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: 5615cadcfb45289eea63f8afd064ab656006361020e1735112e346593856f87435e02d8dcc7ff0d11928bc7d425f27bc7c2a84f6c0b35ab0ff659c814c138a24 - languageName: node - linkType: hard - -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: ^1.0.0 - readable-stream: ^3.6.0 - checksum: 52590c24860fa7173bedeb69a4c05fb573473e860197f618b9a28432ee4379049336727ae3a1f9c4cb083114601c1140cee578376164d0e651217a9843f9fe83 - languageName: node - linkType: hard - "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -1099,13 +528,6 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^1.1.0": - version: 1.1.0 - resolution: "assertion-error@npm:1.1.0" - checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf - languageName: node - linkType: hard - "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -1113,13 +535,6 @@ __metadata: languageName: node linkType: hard -"binary-extensions@npm:^2.0.0": - version: 2.2.0 - resolution: "binary-extensions@npm:2.2.0" - checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -1130,16 +545,7 @@ __metadata: languageName: node linkType: hard -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: ^1.0.0 - checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 - languageName: node - linkType: hard - -"braces@npm:^3.0.2, braces@npm:~3.0.2": +"braces@npm:^3.0.2": version: 3.0.2 resolution: "braces@npm:3.0.2" dependencies: @@ -1148,44 +554,6 @@ __metadata: languageName: node linkType: hard -"bundle-require@npm:^4.0.0": - version: 4.0.1 - resolution: "bundle-require@npm:4.0.1" - dependencies: - load-tsconfig: ^0.2.3 - peerDependencies: - esbuild: ">=0.17" - checksum: 737217e37b72d7bee431b5d839b86ba604430f3ec346f073071de2ce65f0915189d4394ddd4685e0366b2930f38c95742b58c7101b8c53d9a8381d453f0b3b8a - languageName: node - linkType: hard - -"cac@npm:^6.7.12, cac@npm:^6.7.14": - version: 6.7.14 - resolution: "cac@npm:6.7.14" - checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a - languageName: node - linkType: hard - -"cacache@npm:^17.0.0": - version: 17.1.4 - resolution: "cacache@npm:17.1.4" - dependencies: - "@npmcli/fs": ^3.1.0 - fs-minipass: ^3.0.0 - glob: ^10.2.2 - lru-cache: ^7.7.1 - minipass: ^7.0.3 - minipass-collect: ^1.0.2 - minipass-flush: ^1.0.5 - minipass-pipeline: ^1.2.4 - p-map: ^4.0.0 - ssri: ^10.0.0 - tar: ^6.1.11 - unique-filename: ^3.0.0 - checksum: b7751df756656954a51201335addced8f63fc53266fa56392c9f5ae83c8d27debffb4458ac2d168a744a4517ec3f2163af05c20097f93d17bdc2dc8a385e14a6 - languageName: node - linkType: hard - "callsites@npm:^3.0.0, callsites@npm:^3.1.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -1193,21 +561,6 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.7": - version: 4.3.8 - resolution: "chai@npm:4.3.8" - dependencies: - assertion-error: ^1.1.0 - check-error: ^1.0.2 - deep-eql: ^4.1.2 - get-func-name: ^2.0.0 - loupe: ^2.3.1 - pathval: ^1.1.1 - type-detect: ^4.0.5 - checksum: 29e0984ed13308319cadc35437c8ef0a3e271544d226c991bf7e3b6d771bf89707321669e11d05e362bc0ad0bd26585079b989d1032f3c106e3bb95d7f079cce - languageName: node - linkType: hard - "chalk@npm:^4.0.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -1218,46 +571,6 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.2": - version: 1.0.2 - resolution: "check-error@npm:1.0.2" - checksum: d9d106504404b8addd1ee3f63f8c0eaa7cd962a1a28eb9c519b1c4a1dc7098be38007fc0060f045ee00f075fbb7a2a4f42abcf61d68323677e11ab98dc16042e - languageName: node - linkType: hard - -"chokidar@npm:^3.5.1": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" - dependencies: - anymatch: ~3.1.2 - braces: ~3.0.2 - fsevents: ~2.3.2 - glob-parent: ~5.1.2 - is-binary-path: ~2.1.0 - is-glob: ~4.0.1 - normalize-path: ~3.0.0 - readdirp: ~3.6.0 - dependenciesMeta: - fsevents: - optional: true - checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c - languageName: node - linkType: hard - -"chownr@npm:^2.0.0": - version: 2.0.0 - resolution: "chownr@npm:2.0.0" - checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f - languageName: node - linkType: hard - -"clean-stack@npm:^2.0.0": - version: 2.2.0 - resolution: "clean-stack@npm:2.2.0" - checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 - languageName: node - linkType: hard - "color-convert@npm:^2.0.1": version: 2.0.1 resolution: "color-convert@npm:2.0.1" @@ -1274,22 +587,6 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 9b7356817670b9a13a26ca5af1c21615463b500783b739b7634a0c2047c16cef4b2865d7576875c31c3cddf9dd621fa19285e628f20198b233a5cfdda6d0793b - languageName: node - linkType: hard - -"commander@npm:^4.0.0": - version: 4.1.1 - resolution: "commander@npm:4.1.1" - checksum: d7b9913ff92cae20cb577a4ac6fcc121bd6223319e54a40f51a14740a681ad5c574fd29a57da478a5f234a6fa6c52cbf0b7c641353e03c648b1ae85ba670b977 - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -1297,14 +594,7 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": +"cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -1315,7 +605,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -1327,15 +617,6 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.2": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" - dependencies: - type-detect: ^4.0.0 - checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -1343,20 +624,6 @@ __metadata: languageName: node linkType: hard -"delegates@npm:^1.0.0": - version: 1.0.0 - resolution: "delegates@npm:1.0.0" - checksum: a51744d9b53c164ba9c0492471a1a2ffa0b6727451bdc89e31627fdf4adda9d51277cfcbfb20f0a6f08ccb3c436f341df3e92631a3440226d93a8971724771fd - languageName: node - linkType: hard - -"diff-sequences@npm:^29.4.3": - version: 29.6.3 - resolution: "diff-sequences@npm:29.6.3" - checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -1404,204 +671,6 @@ __metadata: languageName: node linkType: hard -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: ^0.6.2 - checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 - languageName: node - linkType: hard - -"esbuild@npm:^0.17.6": - version: 0.17.19 - resolution: "esbuild@npm:0.17.19" - dependencies: - "@esbuild/android-arm": 0.17.19 - "@esbuild/android-arm64": 0.17.19 - "@esbuild/android-x64": 0.17.19 - "@esbuild/darwin-arm64": 0.17.19 - "@esbuild/darwin-x64": 0.17.19 - "@esbuild/freebsd-arm64": 0.17.19 - "@esbuild/freebsd-x64": 0.17.19 - "@esbuild/linux-arm": 0.17.19 - "@esbuild/linux-arm64": 0.17.19 - "@esbuild/linux-ia32": 0.17.19 - "@esbuild/linux-loong64": 0.17.19 - "@esbuild/linux-mips64el": 0.17.19 - "@esbuild/linux-ppc64": 0.17.19 - "@esbuild/linux-riscv64": 0.17.19 - "@esbuild/linux-s390x": 0.17.19 - "@esbuild/linux-x64": 0.17.19 - "@esbuild/netbsd-x64": 0.17.19 - "@esbuild/openbsd-x64": 0.17.19 - "@esbuild/sunos-x64": 0.17.19 - "@esbuild/win32-arm64": 0.17.19 - "@esbuild/win32-ia32": 0.17.19 - "@esbuild/win32-x64": 0.17.19 - dependenciesMeta: - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: ac11b1a5a6008e4e37ccffbd6c2c054746fc58d0ed4a2f9ee643bd030cfcea9a33a235087bc777def8420f2eaafb3486e76adb7bdb7241a9143b43a69a10afd8 - languageName: node - linkType: hard - -"esbuild@npm:^0.18.10": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": 0.18.20 - "@esbuild/android-arm64": 0.18.20 - "@esbuild/android-x64": 0.18.20 - "@esbuild/darwin-arm64": 0.18.20 - "@esbuild/darwin-x64": 0.18.20 - "@esbuild/freebsd-arm64": 0.18.20 - "@esbuild/freebsd-x64": 0.18.20 - "@esbuild/linux-arm": 0.18.20 - "@esbuild/linux-arm64": 0.18.20 - "@esbuild/linux-ia32": 0.18.20 - "@esbuild/linux-loong64": 0.18.20 - "@esbuild/linux-mips64el": 0.18.20 - "@esbuild/linux-ppc64": 0.18.20 - "@esbuild/linux-riscv64": 0.18.20 - "@esbuild/linux-s390x": 0.18.20 - "@esbuild/linux-x64": 0.18.20 - "@esbuild/netbsd-x64": 0.18.20 - "@esbuild/openbsd-x64": 0.18.20 - "@esbuild/sunos-x64": 0.18.20 - "@esbuild/win32-arm64": 0.18.20 - "@esbuild/win32-ia32": 0.18.20 - "@esbuild/win32-x64": 0.18.20 - dependenciesMeta: - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b - languageName: node - linkType: hard - "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -1736,30 +805,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.0 - human-signals: ^2.1.0 - is-stream: ^2.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^4.0.1 - onetime: ^5.1.2 - signal-exit: ^3.0.3 - strip-final-newline: ^2.0.0 - checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.1 - resolution: "exponential-backoff@npm:3.1.1" - checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 - languageName: node - linkType: hard - "fast-deep-equal@npm:3.1.3, fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -1849,34 +894,6 @@ __metadata: languageName: node linkType: hard -"foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" - dependencies: - cross-spawn: ^7.0.0 - signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 - languageName: node - linkType: hard - -"fs-minipass@npm:^2.0.0": - version: 2.1.0 - resolution: "fs-minipass@npm:2.1.0" - dependencies: - minipass: ^3.0.0 - checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: ^7.0.3 - checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 - languageName: node - linkType: hard - "fs.realpath@npm:^1.0.0": version: 1.0.0 resolution: "fs.realpath@npm:1.0.0" @@ -1884,56 +901,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:~2.3.2": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: latest - checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@~2.3.2#~builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: latest - conditions: os=darwin - languageName: node - linkType: hard - -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: ^1.0.3 || ^2.0.0 - color-support: ^1.1.3 - console-control-strings: ^1.1.0 - has-unicode: ^2.0.1 - signal-exit: ^3.0.7 - string-width: ^4.2.3 - strip-ansi: ^6.0.1 - wide-align: ^1.1.5 - checksum: 788b6bfe52f1dd8e263cda800c26ac0ca2ff6de0b6eee2fe0d9e3abf15e149b651bd27bf5226be10e6e3edb5c4e5d5985a5a1a98137e7a892f75eff76467ad2d - languageName: node - linkType: hard - -"get-func-name@npm:^2.0.0": - version: 2.0.0 - resolution: "get-func-name@npm:2.0.0" - checksum: 8d82e69f3e7fab9e27c547945dfe5cc0c57fc0adf08ce135dddb01081d75684a03e7a0487466f478872b341d52ac763ae49e660d01ab83741f74932085f693c3 - languageName: node - linkType: hard - -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": +"glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" dependencies: @@ -1951,36 +919,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.1.6": - version: 7.1.6 - resolution: "glob@npm:7.1.6" - dependencies: - fs.realpath: ^1.0.0 - inflight: ^1.0.4 - inherits: 2 - minimatch: ^3.0.4 - once: ^1.3.0 - path-is-absolute: ^1.0.0 - checksum: 351d549dd90553b87c2d3f90ce11aed9e1093c74130440e7ae0592e11bbcd2ce7f0ebb8ba6bfe63aaf9b62166a7f4c80cb84490ae5d78408bb2572bf7d4ee0a6 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.3.4 - resolution: "glob@npm:10.3.4" - dependencies: - foreground-child: ^3.1.0 - jackspeak: ^2.0.3 - minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 - bin: - glob: dist/cjs/src/bin.js - checksum: 176b97c124414401cb51329a93d2ba112cef8814adbed10348481916b9521b677773eee2691cb6b24d66632d8c8bb8913533f5ac4bfb2d0ef5454a1856082361 - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:^7.1.4": +"glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -2003,7 +942,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.0.3, globby@npm:^11.1.0": +"globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -2017,13 +956,6 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.2.6": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 - languageName: node - linkType: hard - "grapheme-splitter@npm:^1.0.4": version: 1.0.4 resolution: "grapheme-splitter@npm:1.0.4" @@ -2038,66 +970,6 @@ __metadata: languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 1eab07a7436512db0be40a710b29b5dc21fa04880b7f63c9980b706683127e3c1b57cb80ea96d47991bdae2dfe479604f6a1ba410106ee1046a41d1bd0814400 - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 - languageName: node - linkType: hard - -"http-proxy-agent@npm:^5.0.0": - version: 5.0.0 - resolution: "http-proxy-agent@npm:5.0.0" - dependencies: - "@tootallnate/once": 2 - agent-base: 6 - debug: 4 - checksum: e2ee1ff1656a131953839b2a19cd1f3a52d97c25ba87bd2559af6ae87114abf60971e498021f9b73f9fd78aea8876d1fb0d4656aac8a03c6caa9fc175f22b786 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^5.0.0": - version: 5.0.1 - resolution: "https-proxy-agent@npm:5.0.1" - dependencies: - agent-base: 6 - debug: 4 - checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 - languageName: node - linkType: hard - -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 - languageName: node - linkType: hard - -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" - dependencies: - ms: ^2.0.0 - checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 - languageName: node - linkType: hard - -"iconv-lite@npm:^0.6.2": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: ">= 2.1.2 < 3.0.0" - checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf - languageName: node - linkType: hard - "ignore@npm:^5.2.0": version: 5.2.4 resolution: "ignore@npm:5.2.4" @@ -2122,13 +994,6 @@ __metadata: languageName: node linkType: hard -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 - languageName: node - linkType: hard - "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -2139,29 +1004,13 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3": +"inherits@npm:2": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 - languageName: node - linkType: hard - -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: ^2.0.0 - checksum: 84192eb88cff70d320426f35ecd63c3d6d495da9d805b19bc65b518984b7c0760280e57dbf119b7e9be6b161784a5a673ab2c6abe83abb5198a432232ad5b35c - languageName: node - linkType: hard - "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -2169,14 +1018,7 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -2185,13 +1027,6 @@ __metadata: languageName: node linkType: hard -"is-lambda@npm:^1.0.1": - version: 1.0.1 - resolution: "is-lambda@npm:1.0.1" - checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 - languageName: node - linkType: hard - "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -2206,13 +1041,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -2229,26 +1057,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.3.3 - resolution: "jackspeak@npm:2.3.3" - dependencies: - "@isaacs/cliui": ^8.0.2 - "@pkgjs/parseargs": ^0.11.0 - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 4313a7c0cc44c7753c4cb9869935f0b06f4cf96827515f63f58ff46b3d2f6e29aba6b3b5151778397c3f5ae67ef8bfc48871967bd10343c27e90cff198ec7808 - languageName: node - linkType: hard - -"joycon@npm:^3.0.1": - version: 3.1.1 - resolution: "joycon@npm:3.1.1" - checksum: 8003c9c3fc79c5c7602b1c7e9f7a2df2e9916f046b0dbad862aa589be78c15734d11beb9fe846f5e06138df22cb2ad29961b6a986ba81c4920ce2b15a7f11067 - languageName: node - linkType: hard - "js-sdsl@npm:^4.1.4": version: 4.4.2 resolution: "js-sdsl@npm:4.4.2" @@ -2288,13 +1096,6 @@ __metadata: languageName: node linkType: hard -"jsonc-parser@npm:^3.2.0": - version: 3.2.0 - resolution: "jsonc-parser@npm:3.2.0" - checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 - languageName: node - linkType: hard - "keyv@npm:^4.5.3": version: 4.5.3 resolution: "keyv@npm:4.5.3" @@ -2314,34 +1115,6 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:^2.0.5": - version: 2.1.0 - resolution: "lilconfig@npm:2.1.0" - checksum: 8549bb352b8192375fed4a74694cd61ad293904eee33f9d4866c2192865c44c4eb35d10782966242634e0cbc1e91fe62b1247f148dc5514918e3a966da7ea117 - languageName: node - linkType: hard - -"lines-and-columns@npm:^1.1.6": - version: 1.2.4 - resolution: "lines-and-columns@npm:1.2.4" - checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 - languageName: node - linkType: hard - -"load-tsconfig@npm:^0.2.3": - version: 0.2.5 - resolution: "load-tsconfig@npm:0.2.5" - checksum: 631740833c4a7157bb7b6eeae6e1afb6a6fac7416b7ba91bd0944d5c5198270af2d68bf8347af3cc2ba821adc4d83ef98f66278bd263bc284c863a09ec441503 - languageName: node - linkType: hard - -"local-pkg@npm:^0.4.3": - version: 0.4.3 - resolution: "local-pkg@npm:0.4.3" - checksum: 7825aca531dd6afa3a3712a0208697aa4a5cd009065f32e3fb732aafcc42ed11f277b5ac67229222e96f4def55197171cdf3d5522d0381b489d2e5547b407d55 - languageName: node - linkType: hard - "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -2365,13 +1138,6 @@ __metadata: languageName: node linkType: hard -"lodash.sortby@npm:^4.7.0": - version: 4.7.0 - resolution: "lodash.sortby@npm:4.7.0" - checksum: db170c9396d29d11fe9a9f25668c4993e0c1331bcb941ddbd48fb76f492e732add7f2a47cfdf8e9d740fa59ac41bbfaf931d268bc72aab3ab49e9f89354d718c - languageName: node - linkType: hard - "lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -2379,15 +1145,6 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.1, loupe@npm:^2.3.6": - version: 2.3.6 - resolution: "loupe@npm:2.3.6" - dependencies: - get-func-name: ^2.0.0 - checksum: cc83f1b124a1df7384601d72d8d1f5fe95fd7a8185469fec48bb2e4027e45243949e7a013e8d91051a138451ff0552310c32aa9786e60b6a30d1e801bdc2163f - languageName: node - linkType: hard - "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -2397,20 +1154,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.7.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 - languageName: node - linkType: hard - -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.1 - resolution: "lru-cache@npm:10.0.1" - checksum: 06f8d0e1ceabd76bb6f644a26dbb0b4c471b79c7b514c13c6856113879b3bf369eb7b497dad4ff2b7e2636db202412394865b33c332100876d838ad1372f0181 - languageName: node - linkType: hard - "magic-bytes.js@npm:^1.5.0": version: 1.7.0 resolution: "magic-bytes.js@npm:1.7.0" @@ -2418,45 +1161,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.1": - version: 0.30.3 - resolution: "magic-string@npm:0.30.3" - dependencies: - "@jridgewell/sourcemap-codec": ^1.4.15 - checksum: a5a9ddf9bd3bf49a2de1048bf358464f1bda7b3cc1311550f4a0ba8f81a4070e25445d53a5ee28850161336f1bff3cf28aa3320c6b4aeff45ce3e689f300b2f3 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^11.0.3": - version: 11.1.1 - resolution: "make-fetch-happen@npm:11.1.1" - dependencies: - agentkeepalive: ^4.2.1 - cacache: ^17.0.0 - http-cache-semantics: ^4.1.1 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.0 - is-lambda: ^1.0.1 - lru-cache: ^7.7.1 - minipass: ^5.0.0 - minipass-fetch: ^3.0.0 - minipass-flush: ^1.0.5 - minipass-pipeline: ^1.2.4 - negotiator: ^0.6.3 - promise-retry: ^2.0.1 - socks-proxy-agent: ^7.0.0 - ssri: ^10.0.0 - checksum: 7268bf274a0f6dcf0343829489a4506603ff34bd0649c12058753900b0eb29191dce5dba12680719a5d0a983d3e57810f594a12f3c18494e93a1fbc6348a4540 - languageName: node - linkType: hard - -"merge-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "merge-stream@npm:2.0.0" - checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 - languageName: node - linkType: hard - "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -2474,14 +1178,7 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^2.1.0": - version: 2.1.0 - resolution: "mimic-fn@npm:2.1.0" - checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a - languageName: node - linkType: hard - -"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -2490,120 +1187,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" - dependencies: - brace-expansion: ^2.0.1 - checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 - languageName: node - linkType: hard - -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" - dependencies: - minipass: ^3.0.0 - checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 - languageName: node - linkType: hard - -"minipass-fetch@npm:^3.0.0": - version: 3.0.4 - resolution: "minipass-fetch@npm:3.0.4" - dependencies: - encoding: ^0.1.13 - minipass: ^7.0.3 - minipass-sized: ^1.0.3 - minizlib: ^2.1.2 - dependenciesMeta: - encoding: - optional: true - checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: ^3.0.0 - checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: ^3.0.0 - checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: ^3.0.0 - checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: ^4.0.0 - checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 - languageName: node - linkType: hard - -"minipass@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass@npm:5.0.0" - checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.3": - version: 7.0.3 - resolution: "minipass@npm:7.0.3" - checksum: 6f1614f5b5b55568a46bca5fec0e7c46dac027691db27d0e1923a8192866903144cd962ac772c0e9f89b608ea818b702709c042bce98e190d258847d85461531 - languageName: node - linkType: hard - -"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": - version: 2.1.2 - resolution: "minizlib@npm:2.1.2" - dependencies: - minipass: ^3.0.0 - yallist: ^4.0.0 - checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 - languageName: node - linkType: hard - -"mkdirp@npm:^1.0.3": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f - languageName: node - linkType: hard - -"mlly@npm:^1.2.0, mlly@npm:^1.4.0": - version: 1.4.2 - resolution: "mlly@npm:1.4.2" - dependencies: - acorn: ^8.10.0 - pathe: ^1.1.1 - pkg-types: ^1.0.3 - ufo: ^1.3.0 - checksum: ad0813eca133e59ac03b356b87deea57da96083dce7dda58a8eeb2dce92b7cc2315bedd9268f3ff8e98effe1867ddb1307486d4c5cd8be162daa8e0fa0a98ed4 - languageName: node - linkType: hard - "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -2611,33 +1194,6 @@ __metadata: languageName: node linkType: hard -"ms@npm:^2.0.0": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d - languageName: node - linkType: hard - -"mz@npm:^2.7.0": - version: 2.7.0 - resolution: "mz@npm:2.7.0" - dependencies: - any-promise: ^1.0.0 - object-assign: ^4.0.1 - thenify-all: ^1.0.0 - checksum: 8427de0ece99a07e9faed3c0c6778820d7543e3776f9a84d22cf0ec0a8eb65f6e9aee9c9d353ff9a105ff62d33a9463c6ca638974cc652ee8140cd1e35951c87 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" - bin: - nanoid: bin/nanoid.cjs - checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 - languageName: node - linkType: hard - "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -2652,80 +1208,6 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3": - version: 0.6.3 - resolution: "negotiator@npm:0.6.3" - checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 9.4.0 - resolution: "node-gyp@npm:9.4.0" - dependencies: - env-paths: ^2.2.0 - exponential-backoff: ^3.1.1 - glob: ^7.1.4 - graceful-fs: ^4.2.6 - make-fetch-happen: ^11.0.3 - nopt: ^6.0.0 - npmlog: ^6.0.0 - rimraf: ^3.0.2 - semver: ^7.3.5 - tar: ^6.1.2 - which: ^2.0.2 - bin: - node-gyp: bin/node-gyp.js - checksum: 78b404e2e0639d64e145845f7f5a3cb20c0520cdaf6dda2f6e025e9b644077202ea7de1232396ba5bde3fee84cdc79604feebe6ba3ec84d464c85d407bb5da99 - languageName: node - linkType: hard - -"nopt@npm:^6.0.0": - version: 6.0.0 - resolution: "nopt@npm:6.0.0" - dependencies: - abbrev: ^1.0.0 - bin: - nopt: bin/nopt.js - checksum: 82149371f8be0c4b9ec2f863cc6509a7fd0fa729929c009f3a58e4eb0c9e4cae9920e8f1f8eb46e7d032fec8fb01bede7f0f41a67eb3553b7b8e14fa53de1dac - languageName: node - linkType: hard - -"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 - languageName: node - linkType: hard - -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: ^3.0.0 - checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 - languageName: node - linkType: hard - -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: ^3.0.0 - console-control-strings: ^1.1.0 - gauge: ^4.0.3 - set-blocking: ^2.0.0 - checksum: ae238cd264a1c3f22091cdd9e2b106f684297d3c184f1146984ecbe18aaa86343953f26b9520dedd1b1372bc0316905b736c1932d778dbeb1fcf5a1001390e2a - languageName: node - linkType: hard - -"object-assign@npm:^4.0.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f - languageName: node - linkType: hard - "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -2735,15 +1217,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.2": - version: 5.1.2 - resolution: "onetime@npm:5.1.2" - dependencies: - mimic-fn: ^2.1.0 - checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 - languageName: node - linkType: hard - "optionator@npm:^0.9.1": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -2767,15 +1240,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^4.0.0": - version: 4.0.0 - resolution: "p-limit@npm:4.0.0" - dependencies: - yocto-queue: ^1.0.0 - checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b - languageName: node - linkType: hard - "p-locate@npm:^5.0.0": version: 5.0.0 resolution: "p-locate@npm:5.0.0" @@ -2785,15 +1249,6 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^4.0.0": - version: 4.0.0 - resolution: "p-map@npm:4.0.0" - dependencies: - aggregate-error: ^3.0.0 - checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c - languageName: node - linkType: hard - "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -2817,23 +1272,13 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": +"path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 languageName: node linkType: hard -"path-scurry@npm:^1.10.1": - version: 1.10.1 - resolution: "path-scurry@npm:1.10.1" - dependencies: - lru-cache: ^9.1.1 || ^10.0.0 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -2841,81 +1286,13 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.0, pathe@npm:^1.1.1": - version: 1.1.1 - resolution: "pathe@npm:1.1.1" - checksum: 34ab3da2e5aa832ebc6a330ffe3f73d7ba8aec6e899b53b8ec4f4018de08e40742802deb12cf5add9c73b7bf719b62c0778246bd376ca62b0fb23e0dde44b759 - languageName: node - linkType: hard - -"pathval@npm:^1.1.1": - version: 1.1.1 - resolution: "pathval@npm:1.1.1" - checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 - languageName: node - linkType: hard - -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": +"picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf languageName: node linkType: hard -"pirates@npm:^4.0.1": - version: 4.0.6 - resolution: "pirates@npm:4.0.6" - checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 - languageName: node - linkType: hard - -"pkg-types@npm:^1.0.3": - version: 1.0.3 - resolution: "pkg-types@npm:1.0.3" - dependencies: - jsonc-parser: ^3.2.0 - mlly: ^1.2.0 - pathe: ^1.1.0 - checksum: 4b305c834b912ddcc8a0fe77530c0b0321fe340396f84cbb87aecdbc126606f47f2178f23b8639e71a4870f9631c7217aef52ffed0ae17ea2dbbe7e43d116a6e - languageName: node - linkType: hard - -"postcss-load-config@npm:^3.0.1": - version: 3.1.4 - resolution: "postcss-load-config@npm:3.1.4" - dependencies: - lilconfig: ^2.0.5 - yaml: ^1.10.2 - peerDependencies: - postcss: ">=8.0.9" - ts-node: ">=9.0.0" - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - checksum: 1c589504c2d90b1568aecae8238ab993c17dba2c44f848a8f13619ba556d26a1c09644d5e6361b5784e721e94af37b604992f9f3dc0483e687a0cc1cc5029a34 - languageName: node - linkType: hard - -"postcss@npm:^8.4.27": - version: 8.4.29 - resolution: "postcss@npm:8.4.29" - dependencies: - nanoid: ^3.3.6 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: dd6daa25e781db9ae5b651d9b7bfde0ec6e60e86a37da69a18eb4773d5ddd51e28fc4ff054fbdc04636a31462e6bf09a1e50986f69ac52b10d46b7457cd36d12 - languageName: node - linkType: hard - "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -2932,27 +1309,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.5.0": - version: 29.6.3 - resolution: "pretty-format@npm:29.6.3" - dependencies: - "@jest/schemas": ^29.6.3 - ansi-styles: ^5.0.0 - react-is: ^18.0.0 - checksum: 4e1c0db48e65571c22e80ff92123925ff8b3a2a89b71c3a1683cfde711004d492de32fe60c6bc10eea8bf6c678e5cbe544ac6c56cb8096e1eb7caf856928b1c4 - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: ^2.0.2 - retry: ^0.12.0 - checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 - languageName: node - linkType: hard - "punycode@npm:^2.1.0": version: 2.3.0 resolution: "punycode@npm:2.3.0" @@ -2967,33 +1323,6 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0": - version: 18.2.0 - resolution: "react-is@npm:18.2.0" - checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e - languageName: node - linkType: hard - -"readable-stream@npm:^3.6.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: ^2.0.3 - string_decoder: ^1.1.1 - util-deprecate: ^1.0.1 - checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d - languageName: node - linkType: hard - -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: ^2.2.1 - checksum: 1ced032e6e45670b6d7352d71d21ce7edf7b9b928494dcaba6f11fba63180d9da6cd7061ebc34175ffda6ff529f481818c962952004d273178acd70f7059b320 - languageName: node - linkType: hard - "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -3001,20 +1330,6 @@ __metadata: languageName: node linkType: hard -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c - languageName: node - linkType: hard - "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -3033,20 +1348,6 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^3.2.5, rollup@npm:^3.27.1": - version: 3.28.1 - resolution: "rollup@npm:3.28.1" - dependencies: - fsevents: ~2.3.2 - dependenciesMeta: - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 1fcab0929c16130218447c76c19b56ccc0e677110552462297e3679188fc70185a6ec418cef8ce138ec9fb78fd5188537a3f5d28762788e8c88b12a7fb8ba0fb - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -3065,21 +1366,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 - languageName: node - linkType: hard - -"semver@npm:^7.3.5, semver@npm:^7.3.7": +"semver@npm:^7.3.7": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -3090,13 +1377,6 @@ __metadata: languageName: node linkType: hard -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 - languageName: node - linkType: hard - "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -3113,27 +1393,6 @@ __metadata: languageName: node linkType: hard -"siginfo@npm:^2.0.0": - version: 2.0.0 - resolution: "siginfo@npm:2.0.0" - checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 - languageName: node - linkType: hard - -"signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": - version: 3.0.7 - resolution: "signal-exit@npm:3.0.7" - checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 - languageName: node - linkType: hard - "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -3141,105 +1400,7 @@ __metadata: languageName: node linkType: hard -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "socks-proxy-agent@npm:7.0.0" - dependencies: - agent-base: ^6.0.2 - debug: ^4.3.3 - socks: ^2.6.2 - checksum: 720554370154cbc979e2e9ce6a6ec6ced205d02757d8f5d93fe95adae454fc187a5cbfc6b022afab850a5ce9b4c7d73e0f98e381879cf45f66317a4895953846 - languageName: node - linkType: hard - -"socks@npm:^2.6.2": - version: 2.7.1 - resolution: "socks@npm:2.7.1" - dependencies: - ip: ^2.0.0 - smart-buffer: ^4.2.0 - checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 - languageName: node - linkType: hard - -"source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c - languageName: node - linkType: hard - -"source-map@npm:0.8.0-beta.0": - version: 0.8.0-beta.0 - resolution: "source-map@npm:0.8.0-beta.0" - dependencies: - whatwg-url: ^7.0.0 - checksum: e94169be6461ab0ac0913313ad1719a14c60d402bd22b0ad96f4a6cffd79130d91ab5df0a5336a326b04d2df131c1409f563c9dc0d21a6ca6239a44b6c8dbd92 - languageName: node - linkType: hard - -"ssri@npm:^10.0.0": - version: 10.0.5 - resolution: "ssri@npm:10.0.5" - dependencies: - minipass: ^7.0.3 - checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 - languageName: node - linkType: hard - -"stackback@npm:0.0.2": - version: 0.0.2 - resolution: "stackback@npm:0.0.2" - checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 - languageName: node - linkType: hard - -"std-env@npm:^3.3.3": - version: 3.4.3 - resolution: "std-env@npm:3.4.3" - checksum: bef186fb2baddda31911234b1e58fa18f181eb6930616aaec3b54f6d5db65f2da5daaa5f3b326b98445a7d50ca81d6fe8809ab4ebab85ecbe4a802f1b40921bf - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: ^8.0.0 - is-fullwidth-code-point: ^3.0.0 - strip-ansi: ^6.0.1 - checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: ^0.2.0 - emoji-regex: ^9.2.2 - strip-ansi: ^7.0.1 - checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 - languageName: node - linkType: hard - -"string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: ~5.2.0 - checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": +"strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" dependencies: @@ -3248,22 +1409,6 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: ^6.0.1 - checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d - languageName: node - linkType: hard - -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 - languageName: node - linkType: hard - "strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -3271,33 +1416,6 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^1.0.1": - version: 1.3.0 - resolution: "strip-literal@npm:1.3.0" - dependencies: - acorn: ^8.10.0 - checksum: f5fa7e289df8ebe82e90091fd393974faf8871be087ca50114327506519323cf15f2f8fee6ebe68b5e58bfc795269cae8bdc7cb5a83e27b02b3fe953f37b0a89 - languageName: node - linkType: hard - -"sucrase@npm:^3.20.3": - version: 3.34.0 - resolution: "sucrase@npm:3.34.0" - dependencies: - "@jridgewell/gen-mapping": ^0.3.2 - commander: ^4.0.0 - glob: 7.1.6 - lines-and-columns: ^1.1.6 - mz: ^2.7.0 - pirates: ^4.0.1 - ts-interface-checker: ^0.1.9 - bin: - sucrase: bin/sucrase - sucrase-node: bin/sucrase-node - checksum: 61860063bdf6103413698e13247a3074d25843e91170825a9752e4af7668ffadd331b6e99e92fc32ee5b3c484ee134936f926fa9039d5711fafff29d017a2110 - languageName: node - linkType: hard - "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -3307,20 +1425,6 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2": - version: 6.1.15 - resolution: "tar@npm:6.1.15" - dependencies: - chownr: ^2.0.0 - fs-minipass: ^2.0.0 - minipass: ^5.0.0 - minizlib: ^2.1.1 - mkdirp: ^1.0.3 - yallist: ^4.0.0 - checksum: f23832fceeba7578bf31907aac744ae21e74a66f4a17a9e94507acf460e48f6db598c7023882db33bab75b80e027c21f276d405e4a0322d58f51c7088d428268 - languageName: node - linkType: hard - "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -3328,45 +1432,6 @@ __metadata: languageName: node linkType: hard -"thenify-all@npm:^1.0.0": - version: 1.6.0 - resolution: "thenify-all@npm:1.6.0" - dependencies: - thenify: ">= 3.1.0 < 4" - checksum: dba7cc8a23a154cdcb6acb7f51d61511c37a6b077ec5ab5da6e8b874272015937788402fd271fdfc5f187f8cb0948e38d0a42dcc89d554d731652ab458f5343e - languageName: node - linkType: hard - -"thenify@npm:>= 3.1.0 < 4": - version: 3.3.1 - resolution: "thenify@npm:3.3.1" - dependencies: - any-promise: ^1.0.0 - checksum: 84e1b804bfec49f3531215f17b4a6e50fd4397b5f7c1bccc427b9c656e1ecfb13ea79d899930184f78bc2f57285c54d9a50a590c8868f4f0cef5c1d9f898b05e - languageName: node - linkType: hard - -"tinybench@npm:^2.5.0": - version: 2.5.0 - resolution: "tinybench@npm:2.5.0" - checksum: 284bb9428f197ec8b869c543181315e65e41ccfdad3c4b6c916bb1fdae1b5c6785661b0d90cf135b48d833b03cb84dc5357b2d33ec65a1f5971fae0ab2023821 - languageName: node - linkType: hard - -"tinypool@npm:^0.7.0": - version: 0.7.0 - resolution: "tinypool@npm:0.7.0" - checksum: fdcccd5c750574fce51f8801a877f8284e145d12b79cd5f2d72bfbddfe20c895e915555bc848e122bb6aa968098e7ac4fe1e8e88104904d518dc01cccd18a510 - languageName: node - linkType: hard - -"tinyspy@npm:^2.1.1": - version: 2.1.1 - resolution: "tinyspy@npm:2.1.1" - checksum: cfe669803a7f11ca912742b84c18dcc4ceecaa7661c69bc5eb608a8a802d541c48aba220df8929f6c8cd09892ad37cb5ba5958ddbbb57940e91d04681d3cee73 - languageName: node - linkType: hard - "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -3376,31 +1441,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:^1.0.1": - version: 1.0.1 - resolution: "tr46@npm:1.0.1" - dependencies: - punycode: ^2.1.0 - checksum: 96d4ed46bc161db75dbf9247a236ea0bfcaf5758baae6749e92afab0bc5a09cb59af21788ede7e55080f2bf02dce3e4a8f2a484cc45164e29f4b5e68f7cbcc1a - languageName: node - linkType: hard - -"tree-kill@npm:^1.2.2": - version: 1.2.2 - resolution: "tree-kill@npm:1.2.2" - bin: - tree-kill: cli.js - checksum: 49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7 - languageName: node - linkType: hard - -"ts-interface-checker@npm:^0.1.9": - version: 0.1.13 - resolution: "ts-interface-checker@npm:0.1.13" - checksum: 20c29189c2dd6067a8775e07823ddf8d59a33e2ffc47a1bd59a5cb28bb0121a2969a816d5e77eda2ed85b18171aa5d1c4005a6b88ae8499ec7cc49f78571cb5e - languageName: node - linkType: hard - "ts-mixer@npm:^6.0.3": version: 6.0.3 resolution: "ts-mixer@npm:6.0.3" @@ -3429,42 +1469,6 @@ __metadata: languageName: node linkType: hard -"tsup@npm:^6.7.0": - version: 6.7.0 - resolution: "tsup@npm:6.7.0" - dependencies: - bundle-require: ^4.0.0 - cac: ^6.7.12 - chokidar: ^3.5.1 - debug: ^4.3.1 - esbuild: ^0.17.6 - execa: ^5.0.0 - globby: ^11.0.3 - joycon: ^3.0.1 - postcss-load-config: ^3.0.1 - resolve-from: ^5.0.0 - rollup: ^3.2.5 - source-map: 0.8.0-beta.0 - sucrase: ^3.20.3 - tree-kill: ^1.2.2 - peerDependencies: - "@swc/core": ^1 - postcss: ^8.4.12 - typescript: ">=4.1.0" - peerDependenciesMeta: - "@swc/core": - optional: true - postcss: - optional: true - typescript: - optional: true - bin: - tsup: dist/cli-default.js - tsup-node: dist/cli-node.js - checksum: 91ff179f0b9828a6880b6decaa8603fd7af0311f46a38d3a93647a2497298750d676810aeff533a335443a01a7b340dbba7c76523bcd7a87d7b05b7677742901 - languageName: node - linkType: hard - "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -3485,13 +1489,6 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": - version: 4.0.8 - resolution: "type-detect@npm:4.0.8" - checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 - languageName: node - linkType: hard - "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -3519,13 +1516,6 @@ __metadata: languageName: node linkType: hard -"ufo@npm:^1.3.0": - version: 1.3.0 - resolution: "ufo@npm:1.3.0" - checksum: 01f0be86cd5c205ad1b49ebea985e000a4542c503ee75398302b0f5e4b9a6d9cd8e77af2dc614ab7bea08805fdfd9a85191fb3b5ee3df383cb936cf65e9db30d - languageName: node - linkType: hard - "undici@npm:5.27.2": version: 5.27.2 resolution: "undici@npm:5.27.2" @@ -3535,24 +1525,6 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-filename@npm:3.0.0" - dependencies: - unique-slug: ^4.0.0 - checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df - languageName: node - linkType: hard - -"unique-slug@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-slug@npm:4.0.0" - dependencies: - imurmurhash: ^0.1.4 - checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 - languageName: node - linkType: hard - "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -3562,13 +1534,6 @@ __metadata: languageName: node linkType: hard -"util-deprecate@npm:^1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 - languageName: node - linkType: hard - "utility-types@npm:^3.10.0": version: 3.10.0 resolution: "utility-types@npm:3.10.0" @@ -3576,141 +1541,7 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:0.34.3": - version: 0.34.3 - resolution: "vite-node@npm:0.34.3" - dependencies: - cac: ^6.7.14 - debug: ^4.3.4 - mlly: ^1.4.0 - pathe: ^1.1.1 - picocolors: ^1.0.0 - vite: ^3.0.0 || ^4.0.0 - bin: - vite-node: vite-node.mjs - checksum: 366c4f3fb7c038e2180abc6b18cfbac3b8684cd878eaf7ebf1ffb07d95d2ea325713fc575a7949a13bb00cfe264acbc28c02e2836b8647e1f443fe631c17805a - languageName: node - linkType: hard - -"vite@npm:^3.0.0 || ^4.0.0": - version: 4.4.9 - resolution: "vite@npm:4.4.9" - dependencies: - esbuild: ^0.18.10 - fsevents: ~2.3.2 - postcss: ^8.4.27 - rollup: ^3.27.1 - peerDependencies: - "@types/node": ">= 14" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - stylus: "*" - sugarss: "*" - terser: ^5.4.0 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - bin: - vite: bin/vite.js - checksum: c511024ceae39c68c7dbf2ac4381ee655cd7bb62cf43867a14798bc835d3320b8fa7867a336143c30825c191c1fb4e9aa3348fce831ab617e96203080d3d2908 - languageName: node - linkType: hard - -"vitest@npm:latest": - version: 0.34.3 - resolution: "vitest@npm:0.34.3" - dependencies: - "@types/chai": ^4.3.5 - "@types/chai-subset": ^1.3.3 - "@types/node": "*" - "@vitest/expect": 0.34.3 - "@vitest/runner": 0.34.3 - "@vitest/snapshot": 0.34.3 - "@vitest/spy": 0.34.3 - "@vitest/utils": 0.34.3 - acorn: ^8.9.0 - acorn-walk: ^8.2.0 - cac: ^6.7.14 - chai: ^4.3.7 - debug: ^4.3.4 - local-pkg: ^0.4.3 - magic-string: ^0.30.1 - pathe: ^1.1.1 - picocolors: ^1.0.0 - std-env: ^3.3.3 - strip-literal: ^1.0.1 - tinybench: ^2.5.0 - tinypool: ^0.7.0 - vite: ^3.0.0 || ^4.0.0 - vite-node: 0.34.3 - why-is-node-running: ^2.2.2 - peerDependencies: - "@edge-runtime/vm": "*" - "@vitest/browser": "*" - "@vitest/ui": "*" - happy-dom: "*" - jsdom: "*" - playwright: "*" - safaridriver: "*" - webdriverio: "*" - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@vitest/browser": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true - bin: - vitest: vitest.mjs - checksum: 4535d080feede94db5015eb60c6ed5f7b0d8cd67f12072de5ae1faded133cc640043c0c2646ef51ab9b61c2f885589da57458a65e82cf91a25cf954470018a40 - languageName: node - linkType: hard - -"webidl-conversions@npm:^4.0.2": - version: 4.0.2 - resolution: "webidl-conversions@npm:4.0.2" - checksum: c93d8dfe908a0140a4ae9c0ebc87a33805b416a33ee638a605b551523eec94a9632165e54632f6d57a39c5f948c4bab10e0e066525e9a4b87a79f0d04fbca374 - languageName: node - linkType: hard - -"whatwg-url@npm:^7.0.0": - version: 7.1.0 - resolution: "whatwg-url@npm:7.1.0" - dependencies: - lodash.sortby: ^4.7.0 - tr46: ^1.0.1 - webidl-conversions: ^4.0.2 - checksum: fecb07c87290b47d2ec2fb6d6ca26daad3c9e211e0e531dd7566e7ff95b5b3525a57d4f32640ad4adf057717e0c215731db842ad761e61d947e81010e05cf5fd - languageName: node - linkType: hard - -"which@npm:^2.0.1, which@npm:^2.0.2": +"which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -3721,49 +1552,6 @@ __metadata: languageName: node linkType: hard -"why-is-node-running@npm:^2.2.2": - version: 2.2.2 - resolution: "why-is-node-running@npm:2.2.2" - dependencies: - siginfo: ^2.0.0 - stackback: 0.0.2 - bin: - why-is-node-running: cli.js - checksum: 50820428f6a82dfc3cbce661570bcae9b658723217359b6037b67e495255409b4c8bc7931745f5c175df71210450464517cab32b2f7458ac9c40b4925065200a - languageName: node - linkType: hard - -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" - dependencies: - string-width: ^1.0.2 || 2 || 3 || 4 - checksum: d5fc37cd561f9daee3c80e03b92ed3e84d80dde3365a8767263d03dacfc8fa06b065ffe1df00d8c2a09f731482fcacae745abfbb478d4af36d0a891fad4834d3 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: ^4.0.0 - string-width: ^4.1.0 - strip-ansi: ^6.0.0 - checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: ^6.1.0 - string-width: ^5.0.1 - strip-ansi: ^7.0.1 - checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 - languageName: node - linkType: hard - "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2" @@ -3808,23 +1596,9 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^1.10.2": - version: 1.10.2 - resolution: "yaml@npm:1.10.2" - checksum: ce4ada136e8a78a0b08dc10b4b900936912d15de59905b2bf415b4d33c63df1d555d23acb2a41b23cf9fb5da41c256441afca3d6509de7247daa062fd2c5ea5f - languageName: node - linkType: hard - "yocto-queue@npm:^0.1.0": version: 0.1.0 resolution: "yocto-queue@npm:0.1.0" checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 languageName: node linkType: hard - -"yocto-queue@npm:^1.0.0": - version: 1.0.0 - resolution: "yocto-queue@npm:1.0.0" - checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 - languageName: node - linkType: hard From 6c61ae7d6a19f5e84359ff0a60ed39324d6bda2d Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:17:58 -0500 Subject: [PATCH 14/90] fix test --- package.json | 4 ++-- test/core/id.test.ts | 2 +- test/core/ioc.test.ts | 3 ++- test/handlers/dispatchers.test.ts | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index ff8be39d..405396f8 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "build:prod": "tsup ", "prepare": "tsc", "pretty": "prettier --write .", - "tdd": "npx vitest", - "test": "npx vitest --run", + "tdd": "npx --yes vitest", + "test": "npx --yes vitest --run", "analyze-imports": "npx depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg" }, "keywords": [ diff --git a/test/core/id.test.ts b/test/core/id.test.ts index 9d130a01..db34ea71 100644 --- a/test/core/id.test.ts +++ b/test/core/id.test.ts @@ -1,4 +1,4 @@ -import { CommandType } from '../../src/core'; +import { CommandType } from '../../src/core/structures/enums'; import * as Id from '../../src/core/id' import { expect, test } from 'vitest' diff --git a/test/core/ioc.test.ts b/test/core/ioc.test.ts index 51f712b1..5c84dfba 100644 --- a/test/core/ioc.test.ts +++ b/test/core/ioc.test.ts @@ -1,7 +1,8 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; import { EventEmitter } from 'events'; -import { Disposable, Emitter, Init, Logging, __Services } from '../../src/core'; +import { Disposable, Emitter, Init, Logging } from '../../src/core/interfaces'; +import { __Services } from '../../src/core/structures' import { CoreDependencies } from '../../src/types/ioc'; describe('ioc container', () => { diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index a8c77215..bcb701d4 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -1,9 +1,9 @@ import { beforeEach, describe, expect, vi, it } from 'vitest'; import { eventDispatcher } from '../../src/handlers/dispatchers'; import { faker } from '@faker-js/faker'; -import { Module } from '../../src/core/types/modules'; +import { Module } from '../../src/types/core-modules'; import { Processed } from '../../src/handlers/types'; -import { CommandType } from '../../src/core'; +import { CommandType } from '../../src/core/structures/enums'; import { EventEmitter } from 'events'; function createRandomModule(): Processed { From 52d1b5a37a89f97f89378987cacf84e250a22f0e Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:48:37 -0500 Subject: [PATCH 15/90] fix circular dependency --- package.json | 2 +- src/handlers/dispatchers.ts | 83 ---------------------------- src/handlers/event-utils.ts | 86 ++++++++++++++++++++++++++--- src/handlers/interaction-event.ts | 33 ----------- src/handlers/user-defined-events.ts | 5 +- 5 files changed, 81 insertions(+), 128 deletions(-) delete mode 100644 src/handlers/interaction-event.ts diff --git a/package.json b/package.json index 405396f8..f127ac6f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "lint": "eslint src/**/*.ts", "format": "eslint src/**/*.ts --fix", "build:dev": "tsup --metafile", - "build:prod": "tsup ", + "build:prod": "tsc", "prepare": "tsc", "pretty": "prettier --write .", "tdd": "npx --yes vitest", diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts index 94718846..8b137891 100644 --- a/src/handlers/dispatchers.ts +++ b/src/handlers/dispatchers.ts @@ -1,84 +1 @@ -import { EventEmitter } from 'node:events'; -import * as assert from 'node:assert'; -import { concatMap, from, fromEvent, map, OperatorFunction, pipe } from 'rxjs'; -import { - arrayifySource, - callPlugin, - isAutocomplete, - treeSearch, - SernError, -} from '../core/_internal'; -import { createResultResolver } from './event-utils'; -import { BaseInteraction, Message } from 'discord.js'; -import { CommandType, Context } from '../core/structures'; -import type { Args } from '../types/utility'; -import { inspect } from 'node:util' -import type { CommandModule, Module, Processed } from '../types/core-modules'; -//TODO: refactor dispatchers so that it implements a strategy for each different type of payload? -export function dispatchMessage(module: Processed, args: [Context, Args]) { - return { module, args }; -} - -export function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { - const ctx = Context.wrap(wrappable); - const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options]; - return [ctx, args] as [Context, Args]; -} - - -function intoPayload(module: Processed, ) { - return pipe( - arrayifySource, - map(args => ({ module, args, }))); -} - -const createResult = createResultResolver< - Processed, - { module: Processed; args: unknown[] }, - unknown[] ->({ - createStream: ({ module, args }) => from(module.onEvent).pipe(callPlugin(args)), - onNext: ({ args }) => args, -}); -/** - * Creates an observable from { source } - * @param module - * @param source - */ -export function eventDispatcher(module: Processed, source: unknown) { - assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); - - const execute: OperatorFunction = - concatMap(async args => module.execute(...args)); - return fromEvent(source, module.name) - .pipe(intoPayload(module), - concatMap(createResult), - execute); -} - -export function createDispatcher(payload: { - module: Processed; - event: BaseInteraction; -}) { - assert.ok(CommandType.Text !== payload.module.type, - SernError.MismatchEvent + 'Found text command in interaction stream'); - switch (payload.module.type) { - case CommandType.Slash: - case CommandType.Both: { - if (isAutocomplete(payload.event)) { - const option = treeSearch(payload.event, payload.module.options); - assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(payload.module)); - const { command } = option; - - return { - ...payload, - module: command as Processed, //autocomplete is not a true "module" warning cast! - args: [payload.event], - }; - } - return { module: payload.module, args: contextArgs(payload.event) }; - } - default: return { module: payload.module, args: [payload.event] }; - } -} diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 9b7ffa1f..cc8e72bc 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -1,4 +1,4 @@ -import { Interaction, Message } from 'discord.js'; +import type { Interaction, Message, BaseInteraction } from 'discord.js'; import { EMPTY, Observable, @@ -8,30 +8,100 @@ import { of, throwError, tap, + fromEvent, map, OperatorFunction, catchError, finalize, + pipe } from 'rxjs'; import { - Files, Id, callPlugin, everyPluginOk, filterMapTo, handleError, SernError, - VoidResult, + type VoidResult, resultPayload, + arrayifySource, + isAutocomplete, + treeSearch, } from '../core/_internal'; -import { Emitter, ErrorHandling, Logging } from '../core/interfaces'; +import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { PayloadType } from '../core/structures/enums' -import { contextArgs, createDispatcher } from './dispatchers'; -import { ObservableInput, pipe } from 'rxjs'; import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { AnyModule, CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; +import { EventEmitter } from 'node:events'; +import * as assert from 'node:assert'; +import { CommandType, Context } from '../core/structures'; +import type { Args } from '../types/utility'; +import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; + +function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { + const ctx = Context.wrap(wrappable); + const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options]; + return [ctx, args] as [Context, Args]; +} + + +function intoPayload(module: Processed, ) { + return pipe( + arrayifySource, + map(args => ({ module, args, }))); +} + +const createResult = createResultResolver< + Processed, + { module: Processed; args: unknown[] }, + unknown[] +>({ + createStream: ({ module, args }) => from(module.onEvent).pipe(callPlugin(args)), + onNext: ({ args }) => args, +}); +/** + * Creates an observable from { source } + * @param module + * @param source + */ +export function eventDispatcher(module: Processed, source: unknown) { + assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); + + const execute: OperatorFunction = + concatMap(async args => module.execute(...args)); + return fromEvent(source, module.name) + .pipe(intoPayload(module), + concatMap(createResult), + execute); +} + +export function createDispatcher(payload: { + module: Processed; + event: BaseInteraction; +}) { + assert.ok(CommandType.Text !== payload.module.type, + SernError.MismatchEvent + 'Found text command in interaction stream'); + switch (payload.module.type) { + case CommandType.Slash: + case CommandType.Both: { + if (isAutocomplete(payload.event)) { + const option = treeSearch(payload.event, payload.module.options); + assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(payload.module)); + const { command } = option; + + return { + ...payload, + module: command as Processed, //autocomplete is not a true "module" warning cast! + args: [payload.event], + }; + } + return { module: payload.module, args: contextArgs(payload.event) }; + } + default: return { module: payload.module, args: [payload.event] }; + } +} function createGenericHandler( source: Observable, makeModule: (event: Narrowed) => Promise, @@ -138,7 +208,7 @@ export function executeModule( }), ); -} +}; /** @@ -169,7 +239,7 @@ export function createResultResolver< filterMapTo(() => config.onNext(args)), ); }; -} +}; /** * Calls a module's init plugins and checks for Err. If so, call { onStop } and diff --git a/src/handlers/interaction-event.ts b/src/handlers/interaction-event.ts deleted file mode 100644 index a1def254..00000000 --- a/src/handlers/interaction-event.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Interaction } from 'discord.js'; -import { mergeMap, merge, concatMap } from 'rxjs'; -import { PayloadType } from '../core/structures/enums'; -import { - isAutocomplete, - isCommand, - isMessageComponent, - isModal, - sharedEventStream, - SernError, - filterTap, - resultPayload, -} from '../core/_internal'; -import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; -import type { DependencyList } from '../types/ioc'; - -export function interactionHandler([emitter, err, log, modules, client]: DependencyList) { - const interactionStream$ = sharedEventStream(client, 'interactionCreate'); - const handle = createInteractionHandler(interactionStream$, modules); - - const interactionHandler$ = merge( - handle(isMessageComponent), - handle(isAutocomplete), - handle(isCommand), - handle(isModal), - ); - return interactionHandler$ - .pipe( - filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => - emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), - mergeMap(payload => executeModule(emitter, log, err, payload))); -} diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 6c794f6c..d195c6b7 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,8 +1,7 @@ -import { ObservableInput, map, mergeAll } from 'rxjs'; +import { ObservableInput } from 'rxjs'; import { EventType } from '../core/structures'; import { SernError } from '../core/_internal'; -import { callInitPlugins, handleCrash } from './event-utils'; -import { eventDispatcher } from './dispatchers' +import { eventDispatcher } from './event-utils' import { Service } from '../core/ioc'; import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; From 5b33a9d1bb83cce0aefe40d79e210e3d75c04a6c Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 30 Apr 2024 15:03:19 -0500 Subject: [PATCH 16/90] still broken but progress --- package.json | 4 ++-- src/_internal.ts | 23 ++++++++++------------- src/core/ioc/base.ts | 3 +-- src/handlers/dispatchers.ts | 1 - src/handlers/event-utils.ts | 11 +++++------ src/index.ts | 1 + 6 files changed, 19 insertions(+), 24 deletions(-) delete mode 100644 src/handlers/dispatchers.ts diff --git a/package.json b/package.json index f127ac6f..a999f1e1 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,10 @@ } }, "scripts": { - "watch": "tsup --watch", + "watch": "tsc --watch", "lint": "eslint src/**/*.ts", "format": "eslint src/**/*.ts --fix", - "build:dev": "tsup --metafile", + "build:dev": "tsc", "build:prod": "tsc", "prepare": "tsc", "pretty": "prettier --write .", diff --git a/src/_internal.ts b/src/_internal.ts index 94cb21cf..7749ac39 100644 --- a/src/_internal.ts +++ b/src/_internal.ts @@ -10,25 +10,22 @@ import { SernError, filterTap, resultPayload, + type _Module, } from './core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './handlers/event-utils'; -import type { DependencyList } from './types/ioc'; +import type { Emitter } from './core/interfaces' - -export function interactionHandler([emitter, err, log, modules, client]: DependencyList) { +export function interactionHandler(client: Emitter, emitter: Emitter, modules: Map) { const interactionStream$ = sharedEventStream(client, 'interactionCreate'); const handle = createInteractionHandler(interactionStream$, modules); - const interactionHandler$ = merge( - handle(isMessageComponent), - handle(isAutocomplete), - handle(isCommand), - handle(isModal), - ); + const interactionHandler$ = merge(handle(isMessageComponent), + handle(isAutocomplete), + handle(isCommand), + handle(isModal)); return interactionHandler$ - .pipe( - filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => + .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + concatMap(makeModuleExecutor(module => emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), - mergeMap(payload => executeModule(emitter, log, err, payload))); + mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 2f3d90bc..296f3f08 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -140,8 +140,7 @@ function composeRoot( container.ready(); } -export async function makeDependencies -(conf: ValidDependencyConfig) { +export async function makeDependencies (conf: ValidDependencyConfig) { containerSubject = new CoreContainer(); if(typeof conf === 'function') { const excluded: string[] = []; diff --git a/src/handlers/dispatchers.ts b/src/handlers/dispatchers.ts deleted file mode 100644 index 8b137891..00000000 --- a/src/handlers/dispatchers.ts +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index cc8e72bc..3fe3645f 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -25,6 +25,7 @@ import { arrayifySource, isAutocomplete, treeSearch, + _Module, } from '../core/_internal'; import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { PayloadType } from '../core/structures/enums' @@ -77,10 +78,7 @@ export function eventDispatcher(module: Processed, source: unknown) { execute); } -export function createDispatcher(payload: { - module: Processed; - event: BaseInteraction; -}) { +export function createDispatcher(payload: { module: Processed; event: BaseInteraction; }) { assert.ok(CommandType.Text !== payload.module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); switch (payload.module.type) { @@ -135,7 +133,7 @@ export function fmt(msg: string, prefix: string): string[] { */ export function createInteractionHandler( source: Observable, - mg: any, //TODO + mg: Map, //TODO ) { return createGenericHandler, void>>( source, @@ -143,12 +141,13 @@ export function createInteractionHandler( const possibleIds = Id.reconstruct(event); let fullPaths= possibleIds .map(id => mg.get(id)) - .filter((id): id is Module => id !== undefined); + .filter((id): id is _Module => id !== undefined); if(fullPaths.length == 0) { return Err.EMPTY; } const [ path ] = fullPaths; + //@ts-ignore TODO fixme return Ok(createDispatcher({ module: path as Processed, event })); }); } diff --git a/src/index.ts b/src/index.ts index a391ac57..d7d43fc5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export * as Sern from './sern'; + export type { CommandModule, EventModule, From d6eedb1b4d60e8de9015ec066f85b98fb3f7beea Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 30 Apr 2024 20:23:17 -0500 Subject: [PATCH 17/90] remove barrel for core/structs --- src/_internal.ts | 15 +++++++++++++-- src/core/_internal.ts | 1 - src/core/create-plugins.ts | 2 +- src/core/functions.ts | 2 +- src/core/id.ts | 2 +- src/core/ioc/base.ts | 2 +- src/core/ioc/container.ts | 2 +- src/core/modules.ts | 8 ++++---- src/core/operators.ts | 2 +- src/core/presences.ts | 3 +-- src/core/structures/index.ts | 4 ---- src/handlers/event-utils.ts | 3 ++- src/handlers/message-event.ts | 3 +-- src/handlers/user-defined-events.ts | 2 +- src/index.ts | 3 ++- src/types/core-modules.ts | 3 ++- 16 files changed, 32 insertions(+), 25 deletions(-) delete mode 100644 src/core/structures/index.ts diff --git a/src/_internal.ts b/src/_internal.ts index 7749ac39..690c56d1 100644 --- a/src/_internal.ts +++ b/src/_internal.ts @@ -13,9 +13,14 @@ import { type _Module, } from './core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './handlers/event-utils'; -import type { Emitter } from './core/interfaces' +import type { Emitter, ErrorHandling, Logging } from './core/interfaces' +import { Services } from './core/ioc/dependency-injection'; -export function interactionHandler(client: Emitter, emitter: Emitter, modules: Map) { +export function interactionHandler(client: Emitter, + emitter: Emitter, + log: Logging, + err: ErrorHandling, + modules: Map) { const interactionStream$ = sharedEventStream(client, 'interactionCreate'); const handle = createInteractionHandler(interactionStream$, modules); @@ -29,3 +34,9 @@ export function interactionHandler(client: Emitter, emitter: Emitter, modules: M emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), mergeMap(payload => executeModule(emitter, log, err, payload))); } + +export const __dependencies = () => + Services('@sern/emitter', + '@sern/errors', + '@sern/logger', + '@sern/client'); diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 35045973..a946f203 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -5,7 +5,6 @@ export * from './operators'; export * as Files from './module-loading'; export * from './functions'; export { SernError } from './structures/enums'; -export { __Services } from './structures'; export { useContainerRaw } from './ioc/base'; export type _Module = { diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 4db4ce60..1659e17b 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -1,4 +1,4 @@ -import { CommandType, EventType, PluginType } from './structures'; +import { CommandType, EventType, PluginType } from './structures/enums'; import type { Plugin, PluginResult, EventArgs, CommandArgs } from '../types/core-plugin'; import type { ClientEvents } from 'discord.js'; import { err, ok } from './functions'; diff --git a/src/core/functions.ts b/src/core/functions.ts index 39ff1590..b0d9ab65 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -11,7 +11,7 @@ import type { AutocompleteInteraction } from 'discord.js'; import { ApplicationCommandOptionType, InteractionType } from 'discord.js'; -import { PayloadType, PluginType } from './structures'; +import { PayloadType, PluginType } from './structures/enums'; import assert from 'assert'; import type { Payload } from '../types/utility'; diff --git a/src/core/id.ts b/src/core/id.ts index 91ab87b8..3ef46693 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -1,5 +1,5 @@ import { ApplicationCommandType, ComponentType, Interaction, InteractionType } from 'discord.js'; -import { CommandType, EventType } from './structures'; +import { CommandType, EventType } from './structures/enums'; /** * Construct unique ID for a given interaction object. diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 296f3f08..0e86deee 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -2,7 +2,7 @@ import * as assert from 'assert'; import type { CoreDependencies, DependencyConfiguration } from '../../types/ioc'; import { CoreContainer } from './container'; import { Result } from 'ts-results-es'; -import { __Services } from '../_internal'; +import * as __Services from '../structures/default-services'; import { AnyFunction } from '../../types/utility'; import type { Logging } from '../interfaces'; import type { UnpackFunction } from 'iti'; diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 085f05b9..d7afd0af 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -2,7 +2,7 @@ import { Container } from 'iti'; import type { Disposable } from '../interfaces'; import * as assert from 'node:assert'; import { Subject } from 'rxjs'; -import { __Services } from '../_internal'; +import * as __Services from '../structures/default-services'; import * as Hooks from './hooks'; import { EventEmitter } from 'node:events'; diff --git a/src/core/modules.ts b/src/core/modules.ts index ea361bb4..c6d48ae1 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -1,15 +1,16 @@ -import { ClientEvents } from 'discord.js'; -import { EventType } from '../core/structures'; +import type { ClientEvents } from 'discord.js'; +import { EventType } from '../core/structures/enums'; import type { AnyEventPlugin, } from '../types/core-plugin'; import type { InputCommand, InputEvent, } from '../types/core-modules'; -import { _Module, partitionPlugins } from './_internal'; +import { type _Module, partitionPlugins } from './_internal'; import type { Awaitable } from '../types/utility'; import callsites from 'callsites'; import * as Files from './module-loading' import * as Id from './id' + /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod @@ -40,7 +41,6 @@ export function commandModule(mod: InputCommand): _Module { export function eventModule(mod: InputEvent): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); const initCallsite = callsites()[1].getFileName(); - console.log(initCallsite); if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); mod.name ??= name; diff --git a/src/core/operators.ts b/src/core/operators.ts index 28f1c33d..a15c1856 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -26,7 +26,7 @@ import type { VoidResult } from './_internal'; * @param item */ export function filterMapTo(item: () => V): OperatorFunction { - return concatMap(shouldKeep => (shouldKeep ? of(item()) : EMPTY)); + return concatMap(keep => keep ? of(item()) : EMPTY); } interface PluginExecutable { diff --git a/src/core/presences.ts b/src/core/presences.ts index dbd5c6b1..0031c1f9 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -46,8 +46,7 @@ export const Presence = { }, /** * @example - * Presence - * .of({ + * Presence.of({ * activities: [ * { name: "Chilling out" } * ] diff --git a/src/core/structures/index.ts b/src/core/structures/index.ts deleted file mode 100644 index 1a715ae4..00000000 --- a/src/core/structures/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { CommandType, PluginType, PayloadType, EventType } from './enums'; -export * from './context'; -export * as __Services from './default-services'; - diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 3fe3645f..c72a64fe 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -35,7 +35,8 @@ import type { ControlPlugin } from '../types/core-plugin'; import type { AnyModule, CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; import { EventEmitter } from 'node:events'; import * as assert from 'node:assert'; -import { CommandType, Context } from '../core/structures'; +import { Context } from '../core/structures/context'; +import { CommandType } from '../core/structures/enums' import type { Args } from '../types/utility'; import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index 6342bc4d..f04d9715 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -15,8 +15,7 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); - return ( - prefixInContent.localeCompare(prefix, undefined, { + return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent', }) === 0 ); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index d195c6b7..90513749 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,5 +1,5 @@ import { ObservableInput } from 'rxjs'; -import { EventType } from '../core/structures'; +import { EventType } from '../core/structures/enums'; import { SernError } from '../core/_internal'; import { eventDispatcher } from './event-utils' import { Service } from '../core/ioc'; diff --git a/src/index.ts b/src/index.ts index d7d43fc5..787eea18 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,5 +53,6 @@ export { export * from './core/presences' export * from './core/interfaces' export * from './core/create-plugins'; -export * from './core/structures'; +export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; +export { Context } from './core/structures/context'; export * from './core/ioc'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 51510794..aa1b4b71 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -15,7 +15,8 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; -import type { CommandType, Context, EventType } from '../core/structures'; +import type { CommandType, EventType } from '../core/structures/enums'; +import { Context } from '../core/structures/context' import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin'; import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility'; From e8cfcc25254809452eb620f15968dd534a9946cf Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 30 Apr 2024 20:31:06 -0500 Subject: [PATCH 18/90] reffactor --- src/core/operators.ts | 2 +- src/handlers/event-utils.ts | 5 ++--- src/handlers/message-event.ts | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/core/operators.ts b/src/core/operators.ts index a15c1856..af87b138 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -16,7 +16,7 @@ import { pipe, share, } from 'rxjs'; -import { Emitter, ErrorHandling, Logging } from './interfaces'; +import type { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; import type { PluginResult } from '../types/core-plugin'; import type { Result } from 'ts-results-es' diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index c72a64fe..932164cc 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -50,9 +50,8 @@ function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[ function intoPayload(module: Processed, ) { - return pipe( - arrayifySource, - map(args => ({ module, args, }))); + return pipe(arrayifySource, + map(args => ({ module, args }))); } const createResult = createResultResolver< diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index f04d9715..b12412c8 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -16,9 +16,8 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); return (prefixInContent.localeCompare(prefix, undefined, { - sensitivity: 'accent', - }) === 0 - ); + sensitivity: 'accent', + }) === 0); } export function messageHandler( From 0488f45677ec4d9cc4b65ff643064e149170d9b9 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 1 May 2024 16:46:12 -0500 Subject: [PATCH 19/90] refactor allat --- src/core/id.ts | 29 ++++++++++++++-------------- src/core/ioc/dependency-injection.ts | 9 ++------- src/core/operators.ts | 3 +-- src/core/structures/context.ts | 3 +-- src/handlers/event-utils.ts | 6 +++--- src/handlers/message-event.ts | 24 +++++++++++------------ src/handlers/ready-event.ts | 2 +- src/handlers/user-defined-events.ts | 2 +- src/types/core-modules.ts | 1 - src/types/core-plugin.ts | 2 +- src/types/dependencies.d.ts | 4 ++++ src/types/ioc.ts | 1 - src/types/utility.ts | 8 ++++---- 13 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/core/id.ts b/src/core/id.ts index 3ef46693..173d25cd 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -20,22 +20,21 @@ export function reconstruct(event: T) { * * A magic number to represent any commandtype that is an ApplicationCommand. */ -const appBitField = 0b000000001111; +const PUBLISHABLE = 0b000000001111; -const TypeMap = new Map([ - [CommandType.Text, 0], - [CommandType.Both, 0], - [CommandType.Slash, ApplicationCommandType.ChatInput], - [CommandType.CtxUser, ApplicationCommandType.User], - [CommandType.CtxMsg, ApplicationCommandType.Message], - [CommandType.Button, ComponentType.Button], - [CommandType.Modal, InteractionType.ModalSubmit], - [CommandType.StringSelect, ComponentType.StringSelect], - [CommandType.UserSelect, ComponentType.UserSelect], - [CommandType.MentionableSelect, ComponentType.MentionableSelect], - [CommandType.RoleSelect, ComponentType.RoleSelect], - [CommandType.ChannelSelect, ComponentType.ChannelSelect]]); +const TypeMap = new Map([[CommandType.Text, 0], + [CommandType.Both, 0], + [CommandType.Slash, ApplicationCommandType.ChatInput], + [CommandType.CtxUser, ApplicationCommandType.User], + [CommandType.CtxMsg, ApplicationCommandType.Message], + [CommandType.Button, ComponentType.Button], + [CommandType.Modal, InteractionType.ModalSubmit], + [CommandType.StringSelect, ComponentType.StringSelect], + [CommandType.UserSelect, ComponentType.UserSelect], + [CommandType.MentionableSelect, ComponentType.MentionableSelect], + [CommandType.RoleSelect, ComponentType.RoleSelect], + [CommandType.ChannelSelect, ComponentType.ChannelSelect]]); /* * Generates an id based on name and CommandType. @@ -52,7 +51,7 @@ export function create(name: string, type: CommandType | EventType) { if(type == CommandType.Modal) { return `${name}_M`; } - const am = (appBitField & type) !== 0 ? 'A' : 'C'; + const am = (PUBLISHABLE & type) !== 0 ? 'A' : 'C'; return `${name}_${am}${TypeMap.get(type)!}` } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index ac1b3692..e5fa4ed7 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -3,14 +3,11 @@ import type { IntoDependencies } from '../../types/ioc'; import { useContainerRaw } from './base'; /** - * @__PURE__ * @since 2.0.0. * Creates a singleton object. * @param cb */ -export function single(cb: () => T) { - return cb; -} +export function single(cb: () => T) { return cb; } /** * @__PURE__ @@ -18,9 +15,7 @@ export function single(cb: () => T) { * Creates a transient object * @param cb */ -export function transient(cb: () => () => T) { - return cb; -} +export function transient(cb: () => () => T) { return cb; } /** * The new Service api, a cleaner alternative to useContainer * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. diff --git a/src/core/operators.ts b/src/core/operators.ts index af87b138..572a375d 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -9,7 +9,6 @@ import { EMPTY, every, fromEvent, - map, Observable, of, OperatorFunction, @@ -46,7 +45,7 @@ export function callPlugin(args: unknown): OperatorFunction (Array.isArray(src) ? (src as unknown[]) : [src])); +export const arrayifySource = (src: T) => (Array.isArray(src) ? (src as unknown[]) : [src]); /** * Checks if the stream of results is all ok. diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index fb37c05c..d4348005 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -105,8 +105,7 @@ export class Context extends CoreContext { this.ctx .map(m => m.reply(content as MessageReplyOptions)) .mapErr(i => - i.reply(content as InteractionReplyOptions).then(() => i.fetchReply()), - ), + i.reply(content as InteractionReplyOptions).then(() => i.fetchReply())), ); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 932164cc..2d0ca680 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -32,7 +32,7 @@ import { PayloadType } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; -import type { AnyModule, CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; +import type { CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; import { EventEmitter } from 'node:events'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; @@ -50,7 +50,7 @@ function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[ function intoPayload(module: Processed, ) { - return pipe(arrayifySource, + return pipe(map(arrayifySource), map(args => ({ module, args }))); } @@ -244,7 +244,7 @@ export function createResultResolver< * Calls a module's init plugins and checks for Err. If so, call { onStop } and * ignore the module */ -export function callInitPlugins>(sernEmitter: Emitter) { +export function callInitPlugins>(sernEmitter: Emitter) { return concatMap( createResultResolver({ createStream: args => from(args.module.plugins).pipe(callPlugin(args)), diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index b12412c8..1dbbddca 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -21,7 +21,7 @@ function hasPrefix(prefix: string, content: string) { } export function messageHandler( - [emitter, err, log, modules, client]: DependencyList, + [emitter, err, log, client]: DependencyList, defaultPrefix: string | undefined, ) { if (!defaultPrefix) { @@ -31,15 +31,15 @@ export function messageHandler( return EMPTY; } const messageStream$ = sharedEventStream(client, 'messageCreate'); - const handle = createMessageHandler(messageStream$, defaultPrefix, modules); - - const msgCommands$ = handle(isNonBot(defaultPrefix)); - - return msgCommands$.pipe( - filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => { - const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); - emitter.emit('module.activate', result); - })), - mergeMap(payload => executeModule(emitter, log, err, payload))); +// const handle = createMessageHandler(messageStream$, defaultPrefix, modules); +// +// const msgCommands$ = handle(isNonBot(defaultPrefix)); +// +// return msgCommands$.pipe( +// filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), +// concatMap(makeModuleExecutor(module => { +// const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); +// emitter.emit('module.activate', result); +// })), +// mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 62746386..2be7d27e 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -9,7 +9,7 @@ const once = (log: Logging | undefined) => pipe( ignoreElements()) export function readyHandler( - [sEmitter, , log ,, client]: DependencyList, + [sEmitter, , log, client]: DependencyList, allPaths: ObservableInput, ) { //Todo: add module manager on on ready diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 90513749..a62974a0 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -7,7 +7,7 @@ import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; export function eventsHandler( - [emitter, err, log, moduleManager, client]: DependencyList, + [emitter, err, log, client]: DependencyList, allPaths: ObservableInput, ) { //code smell diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index aa1b4b71..2533a873 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -142,7 +142,6 @@ export type CommandModule = | RoleSelectCommand | ModalSubmitCommand; -export type AnyModule = CommandModule | EventModule; //https://stackoverflow.com/questions/64092736/alternative-to-switch-statement-for-typescript-discriminated-union // Explicit Module Definitions for mapping export interface CommandModuleDefs { diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 0576236e..6f1621e1 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -48,7 +48,7 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; -import { VoidResult } from '../core/_internal'; +import type { VoidResult } from '../core/_internal'; export type PluginResult = Awaitable; diff --git a/src/types/dependencies.d.ts b/src/types/dependencies.d.ts index 2290f37d..123e37ba 100644 --- a/src/types/dependencies.d.ts +++ b/src/types/dependencies.d.ts @@ -10,3 +10,7 @@ declare global { interface Dependencies extends CoreDependencies {} } + +declare module './handler.js' { + declare const commands : Map +} diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 303ed241..45bce588 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -15,7 +15,6 @@ export type DependencyList = [ Contracts.Emitter, Contracts.ErrorHandling, Contracts.Logging | undefined, - null, Contracts.Emitter, ]; diff --git a/src/types/utility.ts b/src/types/utility.ts index 3b05e345..95d18fcd 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -1,6 +1,6 @@ import type { CommandInteractionOptionResolver, InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; import type { PayloadType } from '../core/structures/enums'; -import type { AnyModule } from './core-modules'; +import type { Module } from './core-modules'; export type Awaitable = PromiseLike | T; @@ -18,14 +18,14 @@ export type Args = ParseType<{ text: string[]; slash: SlashOptions }>; export interface SernEventsMapping { 'module.register': [Payload]; 'module.activate': [Payload]; - error: [{ type: PayloadType.Failure; module?: AnyModule; reason: string | Error }]; + error: [{ type: PayloadType.Failure; module?: Module; reason: string | Error }]; warning: [Payload]; modulesLoaded: [never?]; } export type Payload = - | { type: PayloadType.Success; module: AnyModule } - | { type: PayloadType.Failure; module?: AnyModule; reason: string | Error } + | { type: PayloadType.Success; module: Module } + | { type: PayloadType.Failure; module?: Module; reason: string | Error } | { type: PayloadType.Warning; module: undefined; reason: string }; From 219eda9bf775ca2cc5219aee4f54ce793259f24b Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 1 May 2024 18:24:56 -0500 Subject: [PATCH 20/90] more refactoring --- src/core/_internal.ts | 2 -- src/core/operators.ts | 3 ++- src/handlers/event-utils.ts | 2 +- src/handlers/message-event.ts | 4 +--- src/handlers/presence.ts | 2 +- src/sern.ts | 2 +- src/types/core-plugin.ts | 5 ++--- 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/core/_internal.ts b/src/core/_internal.ts index a946f203..fa9d4b58 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,8 +1,6 @@ import type { Result } from 'ts-results-es' -export * as Id from './id'; export * from './operators'; -export * as Files from './module-loading'; export * from './functions'; export { SernError } from './structures/enums'; export { useContainerRaw } from './ioc/base'; diff --git a/src/core/operators.ts b/src/core/operators.ts index 572a375d..ec4b1a8c 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -45,7 +45,8 @@ export function callPlugin(args: unknown): OperatorFunction(src: T) => (Array.isArray(src) ? (src as unknown[]) : [src]); +export const arrayifySource = (src: T) => + Array.isArray(src) ? src : [src]; /** * Checks if the stream of results is all ok. diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 2d0ca680..c0887c09 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -14,7 +14,6 @@ import { pipe } from 'rxjs'; import { - Id, callPlugin, everyPluginOk, filterMapTo, @@ -27,6 +26,7 @@ import { treeSearch, _Module, } from '../core/_internal'; +import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { PayloadType } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index 1dbbddca..1b45c59d 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -25,9 +25,7 @@ export function messageHandler( defaultPrefix: string | undefined, ) { if (!defaultPrefix) { - log?.debug({ - message: 'No prefix found. message handler shutting down', - }); + log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; } const messageStream$ = sharedEventStream(client, 'messageCreate'); diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index f5caa89f..4565da35 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -1,5 +1,5 @@ import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" -import { Files } from "../core/_internal"; +import * as Files from "../core/module-loading"; import { PresenceConfig, PresenceResult } from "../core/presences"; import { Services } from "../core/ioc"; import assert from "node:assert"; diff --git a/src/sern.ts b/src/sern.ts index 68f2dbbf..ee518d10 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,5 +1,5 @@ import callsites from 'callsites'; -import { Files } from './core/_internal'; +import * as Files from './core/module-loading'; import { Services } from './core/ioc'; /** diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 6f1621e1..5cff96f4 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -48,7 +48,7 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; -import type { VoidResult } from '../core/_internal'; +import { VoidResult } from '../core/_internal'; export type PluginResult = Awaitable; @@ -82,8 +82,7 @@ export type CommandArgs< J extends PluginType = PluginType, > = CommandArgsMatrix[I][J]; -export type EventArgs< - I extends EventType = EventType, +export type EventArgs< I extends EventType = EventType, J extends PluginType = PluginType, > = EventArgsMatrix[I][J]; From d3245c8a0c80f0acda395cab8470716256bf745e Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 2 May 2024 01:22:40 -0500 Subject: [PATCH 21/90] prototyping linking static handler --- src/_internal.ts | 12 +++++------ src/core/modules.ts | 2 ++ src/index.ts | 6 +----- src/sern.ts | 52 ++++++++++++++++----------------------------- 4 files changed, 26 insertions(+), 46 deletions(-) diff --git a/src/_internal.ts b/src/_internal.ts index 690c56d1..f0bf834d 100644 --- a/src/_internal.ts +++ b/src/_internal.ts @@ -1,6 +1,7 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap } from 'rxjs'; import { PayloadType } from './core/structures/enums'; +import { shouldHandle } from './core/module-loading' import { isAutocomplete, isCommand, @@ -14,9 +15,8 @@ import { } from './core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './handlers/event-utils'; import type { Emitter, ErrorHandling, Logging } from './core/interfaces' -import { Services } from './core/ioc/dependency-injection'; -export function interactionHandler(client: Emitter, +function interactionHandler(client: Emitter, emitter: Emitter, log: Logging, err: ErrorHandling, @@ -35,8 +35,6 @@ export function interactionHandler(client: Emitter, mergeMap(payload => executeModule(emitter, log, err, payload))); } -export const __dependencies = () => - Services('@sern/emitter', - '@sern/errors', - '@sern/logger', - '@sern/client'); +export const __start = (entryPoint: string, wrapper: { defaultPrefix?: string }) => { + +} diff --git a/src/core/modules.ts b/src/core/modules.ts index c6d48ae1..a37936f3 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -22,6 +22,7 @@ export function commandModule(mod: InputCommand): _Module { const { name, absPath } = Files.parseCallsite(initCallsite); mod.name ??= name; + mod.description ??= '...' //@ts-ignore return { ...mod, @@ -44,6 +45,7 @@ export function eventModule(mod: InputEvent): _Module { if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); mod.name ??= name; + mod.description ??= '...' //@ts-ignore return { ...mod, diff --git a/src/index.ts b/src/index.ts index 787eea18..6aac3e6b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,11 +36,7 @@ export type { AnyCommandPlugin, } from './types/core-plugin'; -export interface Wrapper { - commands: string; - defaultPrefix?: string; - events?: string; -} + export type { Args, SlashOptions, Payload, SernEventsMapping } from './types/utility'; export type { Singleton, Transient, CoreDependencies } from './types/ioc'; diff --git a/src/sern.ts b/src/sern.ts index ee518d10..e3a41c00 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -2,52 +2,36 @@ import callsites from 'callsites'; import * as Files from './core/module-loading'; import { Services } from './core/ioc'; + + +interface Wrapper { + commands?: string; + defaultPrefix?: string; + events?: string; +} + /** * @since 1.0.0 * @param wrapper Options to pass into sern. * Function to start the handler up * @example * ```ts title="src/index.ts" - * Sern.init({ - * commands: 'dist/commands', - * events: 'dist/events', - * }) + * Sern.init() * ``` */ -export function init() { +export function init(wrapper: Wrapper) { const startTime = performance.now(); const dependencies = Services('@sern/emitter', '@sern/errors', '@sern/logger', '@sern/client'); - const logger = dependencies[2], - errorHandler = dependencies[1]; - - //const wrapper = Files.loadConfig(maybeWrapper, logger); - //if (wrapper.events !== undefined) { - //eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); - // } - //import(path.resolve("commands.js")) - //.then(({ commands }) => { }) - //.catch(message => logger?.error({ message })) + const initCallsite = callsites()[1].getFileName(); - const presencePath = Files.shouldHandle(initCallsite!, "presence"); - //Ready event: load all modules and when finished, time should be taken and logged -// readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) -// .add(() => { -// logger?.info({ message: "Client signaled ready, registering modules" }); -// const time = ((performance.now() - startTime) / 1000).toFixed(2); -// dependencies[0].emit('modulesLoaded'); -// logger?.info({ message: `sern: registered in ${time} s`, }); -// if(presencePath.exists) { -// const setPresence = async (p: any) => { -// return (dependencies[4] as Client).user?.setPresence(p); -// } -// presenceHandler(presencePath.path, setPresence).subscribe(); -// } -// }); - //const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); - //const interactions$ = interactionHandler(dependencies); - // listening to the message stream and interaction stream - //merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); + const handlerModule = Files.shouldHandle(initCallsite!, "handler"); + if(!handlerModule.exists) { + throw Error("Cannot locate handler file. Did you run sern build?"); + } + import(handlerModule.path) + .then(({ start }) => start(initCallsite, wrapper)) + .catch(err => dependencies[2].error({ message: err })) } From d7ebdb2edc9f4d36a986a794d028938d6c8bc52e Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 2 May 2024 17:27:57 -0500 Subject: [PATCH 22/90] cleanup tests, codegen, and importing handler --- src/_internal.ts | 36 ----------------------- src/core/module-loading.ts | 10 +++---- src/sern.ts | 21 ++++++++++---- test/core/contracts.test.ts | 2 +- test/core/ioc.test.ts | 2 +- test/core/presence.test.ts | 2 +- test/core/services.test.ts | 2 +- test/handlers/dispatchers.test.ts | 4 +-- test/handlers/id.test.ts | 47 ------------------------------- tsconfig.json | 7 +++-- 10 files changed, 30 insertions(+), 103 deletions(-) delete mode 100644 test/handlers/id.test.ts diff --git a/src/_internal.ts b/src/_internal.ts index f0bf834d..fd40910d 100644 --- a/src/_internal.ts +++ b/src/_internal.ts @@ -1,40 +1,4 @@ -import type { Interaction } from 'discord.js'; -import { mergeMap, merge, concatMap } from 'rxjs'; -import { PayloadType } from './core/structures/enums'; -import { shouldHandle } from './core/module-loading' -import { - isAutocomplete, - isCommand, - isMessageComponent, - isModal, - sharedEventStream, - SernError, - filterTap, - resultPayload, - type _Module, -} from './core/_internal'; -import { createInteractionHandler, executeModule, makeModuleExecutor } from './handlers/event-utils'; -import type { Emitter, ErrorHandling, Logging } from './core/interfaces' -function interactionHandler(client: Emitter, - emitter: Emitter, - log: Logging, - err: ErrorHandling, - modules: Map) { - const interactionStream$ = sharedEventStream(client, 'interactionCreate'); - const handle = createInteractionHandler(interactionStream$, modules); - const interactionHandler$ = merge(handle(isMessageComponent), - handle(isAutocomplete), - handle(isCommand), - handle(isModal)); - return interactionHandler$ - .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => - emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), - mergeMap(payload => executeModule(emitter, log, err, payload))); -} -export const __start = (entryPoint: string, wrapper: { defaultPrefix?: string }) => { -} diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index b2be6ab1..14e620f1 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -3,10 +3,10 @@ import assert from 'assert'; import { existsSync } from 'fs'; -export const parseCallsite = (fpath: string) => { - const pathobj = path.parse(fpath.replace(/file:\\?/, "") - .split(path.sep) - .join(path.posix.sep)) +export const parseCallsite = (site: string) => { + const pathobj = path.parse(site.replace(/file:\\?/, "") + .split(path.sep) + .join(path.posix.sep)) return { name: pathobj.name, absPath : path.posix.format(pathobj) } } @@ -16,7 +16,7 @@ export const shouldHandle = (pth: string, filenam: string) => { let newPath = path.join(path.dirname(pth), file_name) .replace(/file:\\?/, ""); return { exists: existsSync(newPath), - path: 'file:///'+newPath }; + path: 'file://'+newPath }; } diff --git a/src/sern.ts b/src/sern.ts index e3a41c00..70fe15e3 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,8 +1,7 @@ import callsites from 'callsites'; import * as Files from './core/module-loading'; import { Services } from './core/ioc'; - - +import type { DependencyList } from './types/ioc'; interface Wrapper { commands?: string; @@ -10,6 +9,16 @@ interface Wrapper { events?: string; } +const __start = (entryPoint: string, + wrapper: { defaultPrefix?: string }, + dependencies: DependencyList) => { + console.log(entryPoint) + import(entryPoint) + .then(({ __commands, __events=new Map() }) => { + console.log(__commands, __events) + }) + .catch(err => dependencies[2]?.error({ message: err })); +} /** * @since 1.0.0 * @param wrapper Options to pass into sern. @@ -28,10 +37,10 @@ export function init(wrapper: Wrapper) { const initCallsite = callsites()[1].getFileName(); const handlerModule = Files.shouldHandle(initCallsite!, "handler"); + console.log(handlerModule) if(!handlerModule.exists) { - throw Error("Cannot locate handler file. Did you run sern build?"); + throw Error("Could not find handler module, did you run sern build?") } - import(handlerModule.path) - .then(({ start }) => start(initCallsite, wrapper)) - .catch(err => dependencies[2].error({ message: err })) + __start(handlerModule.path, wrapper, dependencies); } + diff --git a/test/core/contracts.test.ts b/test/core/contracts.test.ts index 6797c50d..1ecb4613 100644 --- a/test/core/contracts.test.ts +++ b/test/core/contracts.test.ts @@ -1,6 +1,6 @@ import { assertType, describe, it } from 'vitest'; -import { __Services } from '../../src/core/structures'; +import * as __Services from '../../src/core/structures/default-services'; import * as Contracts from '../../src/core/interfaces'; describe('default contracts', () => { diff --git a/test/core/ioc.test.ts b/test/core/ioc.test.ts index 5c84dfba..46cd0c0f 100644 --- a/test/core/ioc.test.ts +++ b/test/core/ioc.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; import { EventEmitter } from 'events'; import { Disposable, Emitter, Init, Logging } from '../../src/core/interfaces'; -import { __Services } from '../../src/core/structures' +import * as __Services from '../../src/core/structures/default-services' import { CoreDependencies } from '../../src/types/ioc'; describe('ioc container', () => { diff --git a/test/core/presence.test.ts b/test/core/presence.test.ts index 904b8637..f9a590b5 100644 --- a/test/core/presence.test.ts +++ b/test/core/presence.test.ts @@ -5,7 +5,7 @@ import { Presence } from '../../src'; // Example test suite for the module function describe('module function', () => { it('should return a valid configuration', () => { - const config: Presence.Config<['dependency1', 'dependency2']> = Presence.module({ + const config = Presence.module({ inject: ['dependency1', 'dependency2'], execute: vi.fn(), }); diff --git a/test/core/services.test.ts b/test/core/services.test.ts index 148fdf65..09cea944 100644 --- a/test/core/services.test.ts +++ b/test/core/services.test.ts @@ -1,6 +1,6 @@ import { SpyInstance, afterAll, beforeEach, describe, expect, it, vi } from 'vitest'; import { CoreContainer } from '../../src/core/ioc/container'; -import { __Services } from '../../src/core/structures/'; +import * as __Services from '../../src/core/structures/default-services'; import { faker } from '@faker-js/faker'; import { commandModule, CommandType } from '../../src'; diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index bcb701d4..a5ce406f 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, expect, vi, it } from 'vitest'; -import { eventDispatcher } from '../../src/handlers/dispatchers'; +import { eventDispatcher } from '../../src/handlers/event-utils'; import { faker } from '@faker-js/faker'; import { Module } from '../../src/types/core-modules'; -import { Processed } from '../../src/handlers/types'; +import { Processed } from '../../src/types/core-modules'; import { CommandType } from '../../src/core/structures/enums'; import { EventEmitter } from 'events'; diff --git a/test/handlers/id.test.ts b/test/handlers/id.test.ts deleted file mode 100644 index d8306900..00000000 --- a/test/handlers/id.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { describe, expect, it, vi } from 'vitest'; -import * as Id from '../../src/core/id'; -import { faker } from '@faker-js/faker'; -import { CommandModule, CommandType, commandModule } from '../../src'; - -function createRandomCommandModules() { - const randomCommandType = [ - CommandType.Text, - CommandType.Both, - CommandType.CtxMsg, - CommandType.CtxUser, - CommandType.Modal, - CommandType.ChannelSelect, - CommandType.RoleSelect, - CommandType.UserSelect, - CommandType.StringSelect, - CommandType.Button, - ]; - return commandModule({ - type: faker.helpers.uniqueArray(randomCommandType, 1)[0], - description: faker.string.alpha(), - name: faker.string.alpha(), - execute: () => {}, - }); -} -function createMetadata(c: CommandModule) { - return { - fullPath: faker.system.filePath(), - id: Id.create(c.name, c.type), - isClass: Boolean(Math.floor(Math.random())), - }; -} -const appBitField = 0b000000001111; - -describe('id resolution', () => { - it('should resolve application commands correctly', () => { - const modules = faker.helpers.multiple(createRandomCommandModules, { - count: 20, - }); - const metadata = modules.map(createMetadata); - metadata.forEach((meta, idx) => { - const associatedModule = modules[idx]; - const uid = Id.create(associatedModule.name!, associatedModule.type!); - expect(meta.id).toBe(uid); - }); - }); -}); diff --git a/tsconfig.json b/tsconfig.json index abc01ec3..61d09100 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "strict": true, "esModuleInterop": true, "strictNullChecks": true, - "moduleResolution": "node", + "moduleResolution": "node16", "skipLibCheck": true, "declaration": true, "preserveSymlinks": true, @@ -12,8 +12,9 @@ "forceConsistentCasingInFileNames": true, "isolatedModules": true, "outDir": "dist", - "module": "commonjs", - "target": "esnext" + "module": "node16", + "target": "esnext", + "sourceMap": true }, "exclude": ["node_modules", "dist"], "include": ["./src", "./src/**/*.d.ts"] From 545105e45bf58d7deac3244f8cd05ba2a53d8d5e Mon Sep 17 00:00:00 2001 From: jacob Date: Fri, 3 May 2024 16:14:55 -0500 Subject: [PATCH 23/90] some refactor --- src/handlers/event-utils.ts | 6 +----- src/handlers/message-event.ts | 10 +++------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index c0887c09..dd5ae4b3 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -189,11 +189,7 @@ export function executeModule( emitter: Emitter, logger: Logging|undefined, errHandler: ErrorHandling, - { - module, - task, - args - }: ExecutePayload, + { module, task, args }: ExecutePayload, ) { return of(module).pipe( //converting the task into a promise so rxjs can resolve the Awaitable properly diff --git a/src/handlers/message-event.ts b/src/handlers/message-event.ts index 1b45c59d..44486485 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message-event.ts @@ -1,8 +1,6 @@ -import { mergeMap, EMPTY, concatMap } from 'rxjs'; +import { EMPTY } from 'rxjs'; import type { Message } from 'discord.js'; -import { PayloadType } from '../core/structures/enums'; -import { sharedEventStream, SernError, filterTap, resultPayload } from '../core/_internal'; -import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; +import { sharedEventStream } from '../core/_internal'; import type { DependencyList } from '../types/ioc'; /** @@ -15,9 +13,7 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); - return (prefixInContent.localeCompare(prefix, undefined, { - sensitivity: 'accent', - }) === 0); + return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent', }) === 0); } export function messageHandler( From b0e9d15fa78692afee1b976d6e6069c7f6df5cd0 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 3 May 2024 17:35:25 -0500 Subject: [PATCH 24/90] generify partition --- src/core/functions.ts | 15 +++++---------- src/types/dependencies.d.ts | 3 --- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index b0d9ab65..b9f241df 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -1,6 +1,5 @@ import { Err, Ok } from 'ts-results-es'; import type { Module, SernAutocompleteData, SernOptionsData } from '../types/core-modules'; -import type { AnyCommandPlugin, AnyEventPlugin, Plugin } from '../types/core-plugin'; import type { AnySelectMenuInteraction, ButtonInteraction, @@ -18,21 +17,17 @@ import type { Payload } from '../types/utility'; export const ok = () => Ok.EMPTY; export const err = () => Err.EMPTY; -export function partitionPlugins(arr: (AnyEventPlugin | AnyCommandPlugin)[] = []): [Plugin[], Plugin[]] { +export function partitionPlugins +(arr: Array<{ type: PluginType }> = []): [T[], V[]] { const controlPlugins = []; const initPlugins = []; - for (const el of arr) { switch (el.type) { - case PluginType.Control: - controlPlugins.push(el); - break; - case PluginType.Init: - initPlugins.push(el); - break; + case PluginType.Control: controlPlugins.push(el); break; + case PluginType.Init: initPlugins.push(el); break; } } - return [controlPlugins, initPlugins]; + return [controlPlugins, initPlugins] as [T[], V[]]; } /** diff --git a/src/types/dependencies.d.ts b/src/types/dependencies.d.ts index 123e37ba..cf0fd9bf 100644 --- a/src/types/dependencies.d.ts +++ b/src/types/dependencies.d.ts @@ -11,6 +11,3 @@ declare global { } -declare module './handler.js' { - declare const commands : Map -} From cd92b548397da96374f1ae50b2469c9356169e10 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 3 May 2024 18:13:34 -0500 Subject: [PATCH 25/90] for now copy paste new ioc system --- src/core/_internal.ts | 1 - src/core/ioc/base.ts | 71 +++++--------------- src/core/ioc/container.ts | 98 +++++++++++++++++----------- src/core/ioc/dependency-injection.ts | 32 +-------- src/core/ioc/global.ts | 75 +++++++++++++++++++++ src/core/ioc/hooks.ts | 41 ------------ src/core/ioc/index.ts | 30 ++++++++- src/core/module-loading.ts | 22 +++---- src/handlers/presence.ts | 42 ++++++------ src/sern.ts | 1 - src/types/ioc.ts | 7 +- src/types/utility.ts | 3 +- 12 files changed, 220 insertions(+), 203 deletions(-) create mode 100644 src/core/ioc/global.ts delete mode 100644 src/core/ioc/hooks.ts diff --git a/src/core/_internal.ts b/src/core/_internal.ts index fa9d4b58..5066fa3f 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -3,7 +3,6 @@ import type { Result } from 'ts-results-es' export * from './operators'; export * from './functions'; export { SernError } from './structures/enums'; -export { useContainerRaw } from './ioc/base'; export type _Module = { meta: { diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 0e86deee..f8cc0d9c 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,53 +1,18 @@ -import * as assert from 'assert'; -import type { CoreDependencies, DependencyConfiguration } from '../../types/ioc'; -import { CoreContainer } from './container'; +import type { DependencyConfiguration } from '../../types/ioc'; +import { Container } from './container'; import { Result } from 'ts-results-es'; import * as __Services from '../structures/default-services'; -import { AnyFunction } from '../../types/utility'; +import { AnyFunction, UnpackFunction } from '../../types/utility'; import type { Logging } from '../interfaces'; -import type { UnpackFunction } from 'iti'; -//SIDE EFFECT: GLOBAL DI -let containerSubject: CoreContainer>; - -/** - * @internal - * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything - * then it will swap - */ -export async function __swap_container(c: CoreContainer>) { - if(containerSubject) { - await containerSubject.disposeAll() - } - containerSubject = c; -} - -/** - * @internal - * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything - * then it will swap - */ -export function __add_container(key: string,v : Insertable) { - containerSubject.add({ [key]: v }); -} - -/** - * Returns the underlying data structure holding all dependencies. - * Exposes methods from iti - * Use the Service API. The container should be readonly from the consumer side - */ -export function useContainerRaw() { - assert.ok( - containerSubject && containerSubject.isReady(), - "Could not find container or container wasn't ready. Did you call makeDependencies?", - ); - return containerSubject; -} +import { __add_container, __swap_container, useContainerRaw } from './global'; export function disposeAll(logger: Logging|undefined) { - containerSubject + useContainerRaw() ?.disposeAll() .then(() => logger?.info({ message: 'Cleaning container and crashing' })); } + + type UnpackedDependencies = { [K in keyof Dependencies]: UnpackFunction } @@ -121,8 +86,8 @@ type ValidDependencyConfig = * Finally, update the containerSubject with the new container state * @param conf */ -function composeRoot( - container: CoreContainer>, +async function composeRoot( + container: Container, conf: DependencyConfiguration, ) { //container should have no client or logger yet. @@ -131,32 +96,32 @@ function composeRoot( __add_container('@sern/logger', new __Services.DefaultLogging); } //Build the container based on the callback provided by the user - conf.build(container as CoreContainer>); + conf.build(container as Container); if (!hasLogger) { - container.get('@sern/logger')?.info({ message: 'All dependencies loaded successfully.' }); + container + .get('@sern/logger') + ?.info({ message: 'All dependencies loaded successfully.' }); } - container.ready(); } export async function makeDependencies (conf: ValidDependencyConfig) { - containerSubject = new CoreContainer(); + __swap_container(new Container({ autowire: false })); if(typeof conf === 'function') { const excluded: string[] = []; - conf(dependencyBuilder(containerSubject, excluded)); + conf(dependencyBuilder(useContainerRaw(), excluded)); //We only include logger if it does not exist const includeLogger = !excluded.includes('@sern/logger') - && !containerSubject.hasKey('@sern/logger'); + && !useContainerRaw().hasKey('@sern/logger'); if(includeLogger) { __add_container('@sern/logger', new __Services.DefaultLogging); } - - containerSubject.ready(); + await useContainerRaw().ready(); } else { - composeRoot(containerSubject, conf); + await composeRoot(useContainerRaw(), conf); } } diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index d7afd0af..528629db 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,54 +1,76 @@ -import { Container } from 'iti'; import type { Disposable } from '../interfaces'; -import * as assert from 'node:assert'; -import { Subject } from 'rxjs'; import * as __Services from '../structures/default-services'; -import * as Hooks from './hooks'; -import { EventEmitter } from 'node:events'; /** * A semi-generic container that provides error handling, emitter, and module store. * For the handler to operate correctly, The only user provided dependency needs to be @sern/client */ -export class CoreContainer> extends Container { - private ready$ = new Subject(); - constructor() { - super(); - assert.ok(!this.isReady(), 'Listening for dispose & init should occur prior to sern being ready.'); - - const { unsubscribe } = Hooks.createInitListener(this); - - this.ready$ - .subscribe({ complete: unsubscribe }); - - (this as Container<{}, {}>) - .add({ '@sern/errors': () => new __Services.DefaultErrorHandling, - '@sern/emitter': () => new EventEmitter({ captureRejections: true }) }) +export function hasCallableMethod(obj: object, name: PropertyKey) { + //@ts-ignore + return Object.hasOwn(obj, name) && typeof obj[name] == 'function'; +} +/** + * A Depedency injection container capable of adding singletons, firing hooks, and managing IOC within an application + */ +export class Container { + private __singletons = new Map(); + private hooks= new Map(); + private finished_init = false; + constructor(options: { autowire: boolean; path?: string }) { + if(options.autowire) { /* noop */ } + } + + addHook(name: string, callback: Function) { + if (!this.hooks.has(name)) { + this.hooks.set(name, []); + } + this.hooks.get(name)!.push(callback); + } + private registerHooks(hookname: string, insert: object) { + if(hasCallableMethod(insert, hookname)) { + console.log(hookname) + //@ts-ignore + this.addHook(hookname, async () => await insert[hookname]()) + } + } + addSingleton(key: string, insert: object) { + if(typeof insert !== 'object') { + throw Error("Inserted object must be an object"); + } + if(!this.__singletons.has(key)){ + this.registerHooks('init', insert) + this.registerHooks('dispose', insert) + this.__singletons.set(key, insert); + return true; + } + return false; } - isReady() { - return this.ready$.closed; + addWiredSingleton(key: string, fn: (c: Container) => object) { + const insert = fn(this); + return this.addSingleton(key, insert); } - - hasKey(key: string): boolean { - return Boolean((this as Container)._context[key]); + + async disposeAll() { + await this.executeHooks('dispose'); + this.hooks.delete('dispose'); } - override async disposeAll() { - const otherDisposables = Object - .entries(this._context) - .flatMap(([key, value]) => - 'dispose' in value ? [key] : []); - otherDisposables.forEach(key => { - //possible source of bug: dispose is a property. - this.addDisposer({ [key]: (dep: Disposable) => dep.dispose() } as never); - }) - await super.disposeAll(); + isReady() { return this.finished_init; } + hasKey(key: string) { return this.__singletons.has(key); } + get(key: PropertyKey) : T|undefined { return this.__singletons.get(key); } + + async ready() { + await this.executeHooks('init'); + this.hooks.delete('init'); + this.finished_init = true; } - - ready() { - this.ready$.complete(); - this.ready$.unsubscribe(); + + async executeHooks(name: string) { + const hookFunctions = this.hooks.get(name) || []; + for (const hookFunction of hookFunctions) { + await hookFunction(); + } } } diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts index e5fa4ed7..9b9373ce 100644 --- a/src/core/ioc/dependency-injection.ts +++ b/src/core/ioc/dependency-injection.ts @@ -1,7 +1,5 @@ -import assert from 'node:assert'; import type { IntoDependencies } from '../../types/ioc'; -import { useContainerRaw } from './base'; - +import { Service as __Service, Services as __Services } from './global' /** * @since 2.0.0. * Creates a singleton object. @@ -16,30 +14,4 @@ export function single(cb: () => T) { return cb; } * @param cb */ export function transient(cb: () => () => T) { return cb; } -/** - * The new Service api, a cleaner alternative to useContainer - * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. - * Usually our scaffolding tool takes care of this. - * Note: this method only works AFTER your container has been initiated - * @since 3.0.0 - * @example - * ```ts - * const client = Service('@sern/client'); - * ``` - * @param key a key that corresponds to a dependency registered. - * - */ -export function Service(key: T) { - const dep = useContainerRaw().get(key)!; - assert(dep, "Requested key " + key + " returned undefined"); - return dep; -} -/** - * @since 3.0.0 - * The plural version of {@link Service} - * @returns array of dependencies, in the same order of keys provided - */ -export function Services(...keys: [...T]) { - const container = useContainerRaw(); - return keys.map(k => container.get(k)!) as IntoDependencies; -} + diff --git a/src/core/ioc/global.ts b/src/core/ioc/global.ts new file mode 100644 index 00000000..1f3d6d12 --- /dev/null +++ b/src/core/ioc/global.ts @@ -0,0 +1,75 @@ +import { Container } from './container'; + +//SIDE EFFECT: GLOBAL DI +let containerSubject: Container; + +/** + * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything + * then it will swap + */ +export async function __swap_container(c: Container) { + if(containerSubject) { + await containerSubject.disposeAll() + } + containerSubject = c; +} + +/** + * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything + * then it will swap + */ +export function __add_container(key: string, v: object) { + containerSubject.addSingleton(key, v); +} + +/** + * Initiates the global api. + * Once this is finished, the Service api and the other global api is available + */ +export function __init_container(options: { + autowire: boolean; + path?: string | undefined; +}) { + containerSubject = new Container(options); +} + +/** + * Returns the underlying data structure holding all dependencies. + * Exposes methods from iti + * Use the Service API. The container should be readonly + */ +export function useContainerRaw() { + if (!(containerSubject && containerSubject.isReady())) { + throw new Error("Container wasn't ready or init'd. Please ensure container is ready()"); + } + + return containerSubject; +} + +/** + * The Service api, retrieve from the globally init'ed container + * Note: this method only works AFTER your container has been initiated + * @since 3.0.0 + * @example + * ```ts + * const client = Service('@sern/client'); + * ``` + * @param key a key that corresponds to a dependency registered. + * + */ +export function Service(key: PropertyKey) { + const dep = useContainerRaw().get(key)!; + if(!dep) { + throw Error("Requested key " + String(key) + " returned undefined"); + } + return dep; +} +/** + * @since 3.0.0 + * The plural version of {@link Service} + * @returns array of dependencies, in the same order of keys provided + */ +export function Services(...keys: [...T]) { + const container = useContainerRaw(); + return keys.map(k => container.get(k)!) as V; +} diff --git a/src/core/ioc/hooks.ts b/src/core/ioc/hooks.ts deleted file mode 100644 index 0a325572..00000000 --- a/src/core/ioc/hooks.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { CoreContainer } from "./container" - -interface HookEvent { - key : PropertyKey - newContainer: any -} -type HookName = 'init'; - -export const createInitListener = (coreContainer : CoreContainer) => { - const initCalled = new Set(); - const hasCallableMethod = createPredicate(initCalled); - const unsubscribe = coreContainer.on('containerUpserted', async event => { - - if(isNotHookable(event)) { - return; - } - - if(hasCallableMethod('init', event)) { - await event.newContainer?.init(); - initCalled.add(event.key); - } - - }); - - return { unsubscribe }; -} - -const isNotHookable = (hk: HookEvent) => { - return typeof hk.newContainer !== 'object' - || Array.isArray(hk.newContainer) - || hk.newContainer === null; -} - -const createPredicate = (called: Set) => { - return (hookName: HookName, event: T) => { - const hasMethod = Reflect.has(event.newContainer!, hookName); - const beenCalledOnce = !called.has(event.key) - - return hasMethod && beenCalledOnce - } -} diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index e89f8b6f..5d48b6ae 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,2 +1,30 @@ +import { IntoDependencies } from '../../types/ioc'; +import { Service as __Service, Services as __Services } from './global' export { makeDependencies } from './base'; -export { Service, Services, single, transient } from './dependency-injection'; +export { single, transient } from './dependency-injection'; + + +/** + * The new Service api, a cleaner alternative to useContainer + * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. + * Usually our scaffolding tool takes care of this. + * Note: this method only works AFTER your container has been initiated + * @since 3.0.0 + * @example + * ```ts + * const client = Service('@sern/client'); + * ``` + * @param key a key that corresponds to a dependency registered. + * + */ +export function Service(key: T) { + return __Service(key) as Dependencies[T] +} +/** + * @since 3.0.0 + * The plural version of {@link Service} + * @returns array of dependencies, in the same order of keys provided + */ +export function Services(...keys: [...T]) { + return __Services>(...keys) +} diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 14e620f1..6f7b0aac 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -34,17 +34,17 @@ export const shouldHandle = (pth: string, filenam: string) => { * esm javascript, typescript, and commonjs typescript * export default commandModule({}) */ -export async function importModule(absPath: string) { - let fileModule = await import(absPath); - - let commandModule = fileModule.default; - - assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); - if ('default' in commandModule) { - commandModule = commandModule.default; - } - return { module: commandModule } as T; -} +//async function importModule(absPath: string) { +// let fileModule = await import(absPath); +// +// let commandModule = fileModule.default; +// +// assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); +// if ('default' in commandModule) { +// commandModule = commandModule.default; +// } +// return { module: commandModule } as T; +//} export const fmtFileName = (fileName: string) => path.parse(fileName).name; diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index 4565da35..331f545a 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -1,7 +1,5 @@ -import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" -import * as Files from "../core/module-loading"; +import { interval, scan, startWith, fromEvent, take, of } from "rxjs" import { PresenceConfig, PresenceResult } from "../core/presences"; -import { Services } from "../core/ioc"; import assert from "node:assert"; type SetPresence = (conf: PresenceResult) => Promise @@ -22,24 +20,24 @@ const parseConfig = async (conf: Promise) => { return of(s).pipe(take(1)); }) }; - +interface PresenceModule { + module: PresenceConfig<(keyof Dependencies)[]> +} export const presenceHandler = (path: string, setPresence: SetPresence) => { - interface PresenceModule { - module: PresenceConfig<(keyof Dependencies)[]> - } - const presence = Files - .importModule(path) - .then(({ module }) => { - //fetch services with the order preserved, passing it to the execute fn - const fetchedServices = Services(...module.inject ?? []); - return async () => module.execute(...fetchedServices); - }) - const module$ = from(presence); - return module$.pipe( - //compose: - //call the execute function, passing that result into parseConfig. - //concatMap resolves the promise, and passes it to the next concatMap. - concatMap(fn => parseConfig(fn())), - // subscribe to the observable parseConfig yields, and set the presence. - concatMap(conf => conf.pipe(map(setPresence)))); + +// const presence = Files +// .importModule(path) +// .then(({ module }) => { +// //fetch services with the order preserved, passing it to the execute fn +// const fetchedServices = Services(...module.inject ?? []); +// return async () => module.execute(...fetchedServices); +// }) +// const module$ = from(presence); +// return module$.pipe( +// //compose: +// //call the execute function, passing that result into parseConfig. +// //concatMap resolves the promise, and passes it to the next concatMap. +// concatMap(fn => parseConfig(fn())), +// // subscribe to the observable parseConfig yields, and set the presence. +// concatMap(conf => conf.pipe(map(setPresence)))); } diff --git a/src/sern.ts b/src/sern.ts index 70fe15e3..9ff09bbb 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -37,7 +37,6 @@ export function init(wrapper: Wrapper) { const initCallsite = callsites()[1].getFileName(); const handlerModule = Files.shouldHandle(initCallsite!, "handler"); - console.log(handlerModule) if(!handlerModule.exists) { throw Error("Could not find handler module, did you run sern build?") } diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 45bce588..8ce0acaa 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -1,5 +1,6 @@ -import { Container, UnpackFunction } from 'iti'; +import type { Container } from '../core/ioc/container'; import * as Contracts from '../core/interfaces'; +import type { UnpackFunction } from './utility' /** * Type to annotate that something is a singleton. * T is created once and lazily. @@ -39,7 +40,5 @@ export interface DependencyConfiguration { * @deprecated. Loggers will be opt-in the future */ exclude?: Set<'@sern/logger'>; - build: ( - root: Container, {}>, - ) => Container; + build: (root: Container) => Container; } diff --git a/src/types/utility.ts b/src/types/utility.ts index 95d18fcd..4a705dd1 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -28,5 +28,6 @@ export type Payload = | { type: PayloadType.Failure; module?: Module; reason: string | Error } | { type: PayloadType.Warning; module: undefined; reason: string }; - +//https://github.com/molszanski/iti/blob/0a3a006113b4176316c308805314a135c0f47902/iti/src/_utils.ts#L29C1-L29C76 +export type UnpackFunction = T extends (...args: any) => infer U ? U : T export type ReplyOptions = string | Omit | MessageReplyOptions; From f76203350487f69bfc59c0be14c80eecdbbea2fc Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 3 May 2024 18:50:47 -0500 Subject: [PATCH 26/90] removeiti --- package.json | 1 - src/core/ioc/base.ts | 40 ++++++---------------------- src/core/ioc/container.ts | 7 +++-- src/core/ioc/dependency-injection.ts | 17 ------------ src/core/ioc/index.ts | 17 +++++++++++- yarn.lock | 17 ------------ 6 files changed, 27 insertions(+), 72 deletions(-) delete mode 100644 src/core/ioc/dependency-injection.ts diff --git a/package.json b/package.json index a999f1e1..da50b36b 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "license": "MIT", "dependencies": { "callsites": "^3.1.0", - "iti": "^0.6.0", "rxjs": "^7.8.0", "ts-results-es": "^4.1.0" }, diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index f8cc0d9c..69a6d6bf 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,8 +1,7 @@ import type { DependencyConfiguration } from '../../types/ioc'; import { Container } from './container'; -import { Result } from 'ts-results-es'; import * as __Services from '../structures/default-services'; -import { AnyFunction, UnpackFunction } from '../../types/utility'; +import { UnpackFunction } from '../../types/utility'; import type { Logging } from '../interfaces'; import { __add_container, __swap_container, useContainerRaw } from './global'; @@ -19,7 +18,7 @@ type UnpackedDependencies = { type Insertable = | ((container: UnpackedDependencies) => unknown) | object -const dependencyBuilder = (container: any, excluded: string[] ) => { +const dependencyBuilder = (container: Container, excluded: string[] ) => { return { /** * Insert a dependency into your container. @@ -27,12 +26,9 @@ const dependencyBuilder = (container: any, excluded: string[] ) => { */ add(key: keyof Dependencies, v: Insertable) { if(typeof v !== 'function') { - Result.wrap(() => container.add({ [key]: v})) - .expect("Failed to add " + key); + container.addSingleton(key, v) } else { - Result.wrap(() => - container.add((cntr: UnpackedDependencies) => ({ [key]: v(cntr)} ))) - .expect("Failed to add " + key); + container.addWiredSingleton(key, (cntr: UnpackedDependencies) => v(cntr)) } }, /** @@ -49,28 +45,9 @@ const dependencyBuilder = (container: any, excluded: string[] ) => { * Swap out a preexisting dependency. */ swap(key: keyof Dependencies, v: Insertable) { - if(typeof v !== 'function') { - Result.wrap(() => container.upsert({ [key]: v})) - .expect("Failed to update " + key); - } else { - Result.wrap(() => - container.upsert((cntr: UnpackedDependencies) => ({ [key]: v(cntr)}))) - .expect("Failed to update " + key); - } + //todo in container + this.add(key, v); }, - /** - * @param key the key of the dependency - * @param cleanup Provide cleanup for the dependency at key. First parameter is the dependency itself - * @example - * ```ts - * addDisposer('dbConnection', (dbConnection) => dbConnection.end()) - * ``` - * Swap out a preexisting dependency. - */ - addDisposer(key: keyof Dependencies, cleanup: AnyFunction) { - Result.wrap(() => container.addDisposer({ [key] : cleanup })) - .expect("Failed to addDisposer for" + key); - } }; }; @@ -99,9 +76,8 @@ async function composeRoot( conf.build(container as Container); if (!hasLogger) { - container - .get('@sern/logger') - ?.info({ message: 'All dependencies loaded successfully.' }); + container.get('@sern/logger') + ?.info({ message: 'All dependencies loaded successfully.' }); } container.ready(); } diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 528629db..91a66a04 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,7 +1,5 @@ -import type { Disposable } from '../interfaces'; import * as __Services from '../structures/default-services'; - /** * A semi-generic container that provides error handling, emitter, and module store. * For the handler to operate correctly, The only user provided dependency needs to be @sern/client @@ -19,6 +17,7 @@ export class Container { private finished_init = false; constructor(options: { autowire: boolean; path?: string }) { if(options.autowire) { /* noop */ } + } addHook(name: string, callback: Function) { @@ -31,14 +30,14 @@ export class Container { if(hasCallableMethod(insert, hookname)) { console.log(hookname) //@ts-ignore - this.addHook(hookname, async () => await insert[hookname]()) + this.addHook(hookname, () => insert[hookname]()) } } addSingleton(key: string, insert: object) { if(typeof insert !== 'object') { throw Error("Inserted object must be an object"); } - if(!this.__singletons.has(key)){ + if(!this.__singletons.has(key)) { this.registerHooks('init', insert) this.registerHooks('dispose', insert) this.__singletons.set(key, insert); diff --git a/src/core/ioc/dependency-injection.ts b/src/core/ioc/dependency-injection.ts deleted file mode 100644 index 9b9373ce..00000000 --- a/src/core/ioc/dependency-injection.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { IntoDependencies } from '../../types/ioc'; -import { Service as __Service, Services as __Services } from './global' -/** - * @since 2.0.0. - * Creates a singleton object. - * @param cb - */ -export function single(cb: () => T) { return cb; } - -/** - * @__PURE__ - * @since 2.0.0 - * Creates a transient object - * @param cb - */ -export function transient(cb: () => () => T) { return cb; } - diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index 5d48b6ae..1a03a8e4 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,7 +1,6 @@ import { IntoDependencies } from '../../types/ioc'; import { Service as __Service, Services as __Services } from './global' export { makeDependencies } from './base'; -export { single, transient } from './dependency-injection'; /** @@ -28,3 +27,19 @@ export function Service(key: T) { export function Services(...keys: [...T]) { return __Services>(...keys) } + +/** + * @since 2.0.0. + * Creates a singleton object. + * @param cb + */ +export function single(cb: () => T) { return cb; } + +/** + * @__PURE__ + * @since 2.0.0 + * Creates a transient object + * @param cb + */ +export function transient(cb: () => () => T) { return cb; } + diff --git a/yarn.lock b/yarn.lock index d0c2ed06..c380662e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -241,7 +241,6 @@ __metadata: callsites: ^3.1.0 discord.js: ^14.11.0 eslint: 8.39.0 - iti: ^0.6.0 prettier: 2.8.8 rxjs: ^7.8.0 ts-results-es: ^4.1.0 @@ -1048,15 +1047,6 @@ __metadata: languageName: node linkType: hard -"iti@npm:^0.6.0": - version: 0.6.0 - resolution: "iti@npm:0.6.0" - dependencies: - utility-types: ^3.10.0 - checksum: 19e484aa8b00bf57642c73c56b658d06d70d7b5acf5725a6aca9948c6b3c8d1fab18d71fb25f482a13d8c6acac137799fa80e7dbdc97cc24ed5afc94f03811e3 - languageName: node - linkType: hard - "js-sdsl@npm:^4.1.4": version: 4.4.2 resolution: "js-sdsl@npm:4.4.2" @@ -1534,13 +1524,6 @@ __metadata: languageName: node linkType: hard -"utility-types@npm:^3.10.0": - version: 3.10.0 - resolution: "utility-types@npm:3.10.0" - checksum: 8f274415c6196ab62883b8bd98c9d2f8829b58016e4269aaa1ebd84184ac5dda7dc2ca45800c0d5e0e0650966ba063bf9a412aaeaea6850ca4440a391283d5c8 - languageName: node - linkType: hard - "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" From 08ef80522f3b3088f1232bb10743ca049c55fc4f Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 4 May 2024 12:24:22 -0500 Subject: [PATCH 27/90] fdsfD --- src/core/module-loading.ts | 1 - src/core/operators.ts | 19 +++++++++---------- src/handlers/presence.ts | 8 ++------ src/sern.ts | 1 - 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 6f7b0aac..ccac73d6 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,5 +1,4 @@ import path from 'node:path'; -import assert from 'assert'; import { existsSync } from 'fs'; diff --git a/src/core/operators.ts b/src/core/operators.ts index ec4b1a8c..e2d01136 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -18,7 +18,6 @@ import { import type { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; import type { PluginResult } from '../types/core-plugin'; -import type { Result } from 'ts-results-es' import type { VoidResult } from './_internal'; /** * if {src} is true, mapTo V, else ignore @@ -70,12 +69,12 @@ export function handleError(crashHandler: ErrorHandling, emitter: Emitter, lo return caught; }; } -// Temporary until i get rxjs operators working on ts-results-es -export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => - pipe(concatMap(result => { - if(result.isOk()) { - return of(result.value) - } - onErr(result.error); - return EMPTY - })) +//// Temporary until i get rxjs operators working on ts-results-es +//const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => +// pipe(concatMap(result => { +// if(result.isOk()) { +// return of(result.value) +// } +// onErr(result.error); +// return EMPTY +// })) diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index 331f545a..821858e0 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -20,11 +20,7 @@ const parseConfig = async (conf: Promise) => { return of(s).pipe(take(1)); }) }; -interface PresenceModule { - module: PresenceConfig<(keyof Dependencies)[]> -} -export const presenceHandler = (path: string, setPresence: SetPresence) => { - + // const presence = Files // .importModule(path) // .then(({ module }) => { @@ -40,4 +36,4 @@ export const presenceHandler = (path: string, setPresence: SetPresence) => { // concatMap(fn => parseConfig(fn())), // // subscribe to the observable parseConfig yields, and set the presence. // concatMap(conf => conf.pipe(map(setPresence)))); -} + diff --git a/src/sern.ts b/src/sern.ts index 9ff09bbb..3719479f 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -2,7 +2,6 @@ import callsites from 'callsites'; import * as Files from './core/module-loading'; import { Services } from './core/ioc'; import type { DependencyList } from './types/ioc'; - interface Wrapper { commands?: string; defaultPrefix?: string; From ffb2872f8bc302c429243fe0612913d111f6150c Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 9 May 2024 20:42:09 -0500 Subject: [PATCH 28/90] ensure container is init'd --- src/core/ioc/base.ts | 6 ++++-- src/core/ioc/global.ts | 3 ++- src/core/ioc/index.ts | 8 ++++---- src/sern.ts | 1 - 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 69a6d6bf..75425002 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -3,7 +3,7 @@ import { Container } from './container'; import * as __Services from '../structures/default-services'; import { UnpackFunction } from '../../types/utility'; import type { Logging } from '../interfaces'; -import { __add_container, __swap_container, useContainerRaw } from './global'; +import { __add_container, __init_container, __swap_container, useContainerRaw } from './global'; export function disposeAll(logger: Logging|undefined) { useContainerRaw() @@ -28,6 +28,8 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { if(typeof v !== 'function') { container.addSingleton(key, v) } else { + //TODO fixme + //@ts-ignore container.addWiredSingleton(key, (cntr: UnpackedDependencies) => v(cntr)) } }, @@ -83,7 +85,7 @@ async function composeRoot( } export async function makeDependencies (conf: ValidDependencyConfig) { - __swap_container(new Container({ autowire: false })); + await __init_container({ autowire: false }); if(typeof conf === 'function') { const excluded: string[] = []; conf(dependencyBuilder(useContainerRaw(), excluded)); diff --git a/src/core/ioc/global.ts b/src/core/ioc/global.ts index 1f3d6d12..42ff98c9 100644 --- a/src/core/ioc/global.ts +++ b/src/core/ioc/global.ts @@ -26,11 +26,12 @@ export function __add_container(key: string, v: object) { * Initiates the global api. * Once this is finished, the Service api and the other global api is available */ -export function __init_container(options: { +export async function __init_container(options: { autowire: boolean; path?: string | undefined; }) { containerSubject = new Container(options); + await containerSubject.ready() } /** diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index 1a03a8e4..ab574760 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -29,17 +29,17 @@ export function Services(...keys: [...T] } /** - * @since 2.0.0. + * @deprecated * Creates a singleton object. * @param cb */ -export function single(cb: () => T) { return cb; } +export function single(cb: () => T) { return cb(); } /** - * @__PURE__ + * @deprecated * @since 2.0.0 * Creates a transient object * @param cb */ -export function transient(cb: () => () => T) { return cb; } +export function transient(cb: () => () => T) { return cb()(); } diff --git a/src/sern.ts b/src/sern.ts index 3719479f..3c620969 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -11,7 +11,6 @@ interface Wrapper { const __start = (entryPoint: string, wrapper: { defaultPrefix?: string }, dependencies: DependencyList) => { - console.log(entryPoint) import(entryPoint) .then(({ __commands, __events=new Map() }) => { console.log(__commands, __events) From 4d74e63dd36d6df0f978aea78af50b2190320dcc Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 10 May 2024 00:23:22 -0500 Subject: [PATCH 29/90] fix absPath gen --- src/core/modules.ts | 4 ++-- src/sern.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/modules.ts b/src/core/modules.ts index a37936f3..c374ac97 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -17,7 +17,7 @@ import * as Id from './id' */ export function commandModule(mod: InputCommand): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = callsites()[1].getFileName(); + const initCallsite = callsites().at(-2)?.getFileName(); if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); @@ -41,7 +41,7 @@ export function commandModule(mod: InputCommand): _Module { */ export function eventModule(mod: InputEvent): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = callsites()[1].getFileName(); + const initCallsite = callsites().at(-2)?.getFileName(); if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); mod.name ??= name; diff --git a/src/sern.ts b/src/sern.ts index 3c620969..4045caf0 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -11,9 +11,10 @@ interface Wrapper { const __start = (entryPoint: string, wrapper: { defaultPrefix?: string }, dependencies: DependencyList) => { + //@ts-ignore sern handler generates handler.js import(entryPoint) - .then(({ __commands, __events=new Map() }) => { - console.log(__commands, __events) + .then(({ commands=new Map(), events=new Map() }) => { + console.log(commands, events) }) .catch(err => dependencies[2]?.error({ message: err })); } From 8554eeaef410b4475a68ff9e05b714f7561e671e Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 10 May 2024 01:18:44 -0500 Subject: [PATCH 30/90] working on bun compat --- src/core/modules.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/modules.ts b/src/core/modules.ts index c374ac97..1015cde0 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -7,22 +7,23 @@ import type { } from '../types/core-modules'; import { type _Module, partitionPlugins } from './_internal'; import type { Awaitable } from '../types/utility'; -import callsites from 'callsites'; +import callsites, { type CallSite } from 'callsites'; import * as Files from './module-loading' import * as Id from './id' - +const get_callsite = (css: CallSite[]) => { + return css.map(cs => cs.getFileName()).filter(Boolean) +} /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod */ export function commandModule(mod: InputCommand): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = callsites().at(-2)?.getFileName(); + const initCallsite = get_callsite(callsites()).at(-2); if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); - mod.name ??= name; - mod.description ??= '...' + mod.name ??= name; mod.description ??= '...' //@ts-ignore return { ...mod, @@ -41,11 +42,10 @@ export function commandModule(mod: InputCommand): _Module { */ export function eventModule(mod: InputEvent): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = callsites().at(-2)?.getFileName(); + const initCallsite = get_callsite(callsites()).at(-2); if(!initCallsite) throw Error("initCallsite is null"); const { name, absPath } = Files.parseCallsite(initCallsite); - mod.name ??= name; - mod.description ??= '...' + mod.name ??= name; mod.description ??= '...' //@ts-ignore return { ...mod, From 6e2f4b616f8d8dc9aaa41268aa7c708864411c56 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 13 May 2024 15:27:12 -0500 Subject: [PATCH 31/90] refactor and clean up and reenter v3 module loading --- src/core/_internal.ts | 1 - src/core/functions.ts | 5 +- src/core/module-loading.ts | 23 +++---- src/core/modules.ts | 1 - src/core/operators.ts | 17 ++--- src/core/structures/core-context.ts | 2 +- src/handlers/event-utils.ts | 13 ++-- src/handlers/interaction.ts | 30 +++++++++ src/handlers/{message-event.ts => message.ts} | 30 +++++---- src/handlers/presence.ts | 41 ++++++------ src/handlers/ready-event.ts | 4 +- src/handlers/user-defined-events.ts | 23 ++++--- src/sern.ts | 63 ++++++++++++------- 13 files changed, 152 insertions(+), 101 deletions(-) create mode 100644 src/handlers/interaction.ts rename src/handlers/{message-event.ts => message.ts} (51%) diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 5066fa3f..b7ab4f35 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -2,7 +2,6 @@ import type { Result } from 'ts-results-es' export * from './operators'; export * from './functions'; -export { SernError } from './structures/enums'; export type _Module = { meta: { diff --git a/src/core/functions.ts b/src/core/functions.ts index b9f241df..dfbb2d83 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -61,10 +61,7 @@ export function treeSearch( { if ('autocomplete' in cur && cur.autocomplete) { const choice = iAutocomplete.options.getFocused(true); - assert( - 'command' in cur, - 'No `command` property found for autocomplete option', - ); + assert( 'command' in cur, 'No `command` property found for option ' + cur.name); if (subcommands.size > 0) { const parent = iAutocomplete.options.getSubcommand(); const parentAndOptionMatches = diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index ccac73d6..32bf7b57 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,5 +1,6 @@ import path from 'node:path'; import { existsSync } from 'fs'; +import assert from 'node:assert'; export const parseCallsite = (site: string) => { @@ -33,17 +34,17 @@ export const shouldHandle = (pth: string, filenam: string) => { * esm javascript, typescript, and commonjs typescript * export default commandModule({}) */ -//async function importModule(absPath: string) { -// let fileModule = await import(absPath); -// -// let commandModule = fileModule.default; -// -// assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); -// if ('default' in commandModule) { -// commandModule = commandModule.default; -// } -// return { module: commandModule } as T; -//} +export async function importModule(absPath: string) { + let fileModule = await import(absPath); + + let commandModule = fileModule.default; + + assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); + if ('default' in commandModule) { + commandModule = commandModule.default; + } + return { module: commandModule } as T; +} export const fmtFileName = (fileName: string) => path.parse(fileName).name; diff --git a/src/core/modules.ts b/src/core/modules.ts index 1015cde0..a8c87c53 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -21,7 +21,6 @@ export function commandModule(mod: InputCommand): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); const initCallsite = get_callsite(callsites()).at(-2); if(!initCallsite) throw Error("initCallsite is null"); - const { name, absPath } = Files.parseCallsite(initCallsite); mod.name ??= name; mod.description ??= '...' //@ts-ignore diff --git a/src/core/operators.ts b/src/core/operators.ts index e2d01136..4bb95c7d 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -19,6 +19,7 @@ import type { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; import type { PluginResult } from '../types/core-plugin'; import type { VoidResult } from './_internal'; +import { Result } from 'ts-results-es'; /** * if {src} is true, mapTo V, else ignore * @param item @@ -70,11 +71,11 @@ export function handleError(crashHandler: ErrorHandling, emitter: Emitter, lo }; } //// Temporary until i get rxjs operators working on ts-results-es -//const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => -// pipe(concatMap(result => { -// if(result.isOk()) { -// return of(result.value) -// } -// onErr(result.error); -// return EMPTY -// })) +export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => + concatMap(result => { + if(result.isOk()) { + return of(result.value) + } + onErr(result.error); + return EMPTY + }) diff --git a/src/core/structures/core-context.ts b/src/core/structures/core-context.ts index acff87b2..e5eed997 100644 --- a/src/core/structures/core-context.ts +++ b/src/core/structures/core-context.ts @@ -1,5 +1,5 @@ import { Result as Either } from 'ts-results-es'; -import { SernError } from '../_internal'; +import { SernError } from './enums'; import * as assert from 'node:assert'; /** diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index dd5ae4b3..c1991289 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -18,7 +18,6 @@ import { everyPluginOk, filterMapTo, handleError, - SernError, type VoidResult, resultPayload, arrayifySource, @@ -28,7 +27,7 @@ import { } from '../core/_internal'; import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; -import { PayloadType } from '../core/structures/enums' +import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; @@ -90,7 +89,6 @@ export function createDispatcher(payload: { module: Processed; ev const { command } = option; return { - ...payload, module: command as Processed, //autocomplete is not a true "module" warning cast! args: [payload.event], }; @@ -256,16 +254,13 @@ export function callInitPlugins>(sernEmitter: Emitte } /** - * Creates an executable task ( execute the command ) if all control plugins are successful + * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter */ export function makeModuleExecutor< M extends Processed, - Args extends { - module: M; - args: unknown[]; - }, ->(onStop: (m: M) => unknown) { + Args extends { module: M; args: unknown[]; }> +(onStop: (m: M) => unknown) { const onNext = ({ args, module }: Args) => ({ task: () => module.execute(...args), module, diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts new file mode 100644 index 00000000..d9b3c717 --- /dev/null +++ b/src/handlers/interaction.ts @@ -0,0 +1,30 @@ +import type { Interaction } from 'discord.js'; +import { mergeMap, merge, concatMap } from 'rxjs'; +import { PayloadType } from '../core/structures/enums'; +import { filterTap } from '../core/operators' +import { + isAutocomplete, + isCommand, + isMessageComponent, + isModal, + sharedEventStream, + resultPayload, +} from '../core/_internal'; +import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; +import type { DependencyList } from '../types/ioc'; +import { SernError } from '../core/structures/enums' +export function interactionHandler([emitter, err, log, client]: DependencyList) { + const interactionStream$ = sharedEventStream(client, 'interactionCreate'); + const modules = new Map(); + const handle = createInteractionHandler(interactionStream$, modules); + + const interactionHandler$ = merge(handle(isMessageComponent), + handle(isAutocomplete), + handle(isCommand), + handle(isModal)); + return interactionHandler$ + .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + concatMap(makeModuleExecutor(module => + emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), + mergeMap(payload => executeModule(emitter, log, err, payload))); +} diff --git a/src/handlers/message-event.ts b/src/handlers/message.ts similarity index 51% rename from src/handlers/message-event.ts rename to src/handlers/message.ts index 44486485..bcc6a669 100644 --- a/src/handlers/message-event.ts +++ b/src/handlers/message.ts @@ -1,8 +1,11 @@ -import { EMPTY } from 'rxjs'; +import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; import { sharedEventStream } from '../core/_internal'; import type { DependencyList } from '../types/ioc'; - +import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; +import { PayloadType, SernError } from '../core/structures/enums' +import { resultPayload } from '../core/functions' +import { filterTap } from '../core/operators' /** * Ignores messages from any person / bot except itself * @param prefix @@ -24,16 +27,17 @@ export function messageHandler( log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; } + const modules = new Map() const messageStream$ = sharedEventStream(client, 'messageCreate'); -// const handle = createMessageHandler(messageStream$, defaultPrefix, modules); -// -// const msgCommands$ = handle(isNonBot(defaultPrefix)); -// -// return msgCommands$.pipe( -// filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), -// concatMap(makeModuleExecutor(module => { -// const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); -// emitter.emit('module.activate', result); -// })), -// mergeMap(payload => executeModule(emitter, log, err, payload))); + const handle = createMessageHandler(messageStream$, defaultPrefix, modules); + + const msgCommands$ = handle(isNonBot(defaultPrefix)); + + return msgCommands$.pipe( + filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + concatMap(makeModuleExecutor(module => { + const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); + emitter.emit('module.activate', result); + })), + mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index 821858e0..b393e3d1 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -1,7 +1,8 @@ -import { interval, scan, startWith, fromEvent, take, of } from "rxjs" +import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" import { PresenceConfig, PresenceResult } from "../core/presences"; +import { Services } from "../core/ioc"; import assert from "node:assert"; - +import * as Files from "../core/module-loading"; type SetPresence = (conf: PresenceResult) => Promise const parseConfig = async (conf: Promise) => { @@ -21,19 +22,23 @@ const parseConfig = async (conf: Promise) => { }) }; -// const presence = Files -// .importModule(path) -// .then(({ module }) => { -// //fetch services with the order preserved, passing it to the execute fn -// const fetchedServices = Services(...module.inject ?? []); -// return async () => module.execute(...fetchedServices); -// }) -// const module$ = from(presence); -// return module$.pipe( -// //compose: -// //call the execute function, passing that result into parseConfig. -// //concatMap resolves the promise, and passes it to the next concatMap. -// concatMap(fn => parseConfig(fn())), -// // subscribe to the observable parseConfig yields, and set the presence. -// concatMap(conf => conf.pipe(map(setPresence)))); - +export const presenceHandler = (path: string, setPresence: SetPresence) => { + interface PresenceModule { + module: PresenceConfig<(keyof Dependencies)[]> + } + const presence = Files + .importModule(path) + .then(({ module }) => { + //fetch services with the order preserved, passing it to the execute fn + const fetchedServices = Services(...module.inject ?? []); + return async () => module.execute(...fetchedServices); + }) + const module$ = from(presence); + return module$.pipe( + //compose: + //call the execute function, passing that result into parseConfig. + //concatMap resolves the promise, and passes it to the next concatMap. + concatMap(fn => parseConfig(fn())), + // subscribe to the observable parseConfig yields, and set the presence. + concatMap(conf => conf.pipe(map(setPresence)))); +} diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 2be7d27e..b92aa9e3 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -2,6 +2,7 @@ import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } import { _Module } from '../core/_internal'; import { Logging } from '../core/interfaces'; import type { DependencyList } from '../types/ioc'; +import { callInitPlugins } from './event-utils'; const once = (log: Logging | undefined) => pipe( tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), @@ -15,8 +16,7 @@ export function readyHandler( //Todo: add module manager on on ready const ready$ = fromEvent(client!, 'ready').pipe(once(log)); - concat(ready$) - //.pipe(callInitPlugins(sEmitter)) + return concat(ready$).pipe(callInitPlugins(sEmitter)) // const validModuleType = module.type >= 0 && module.type <= 1 << 10; // assert.ok(validModuleType, // `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index a62974a0..7cefb6aa 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,6 +1,5 @@ import { ObservableInput } from 'rxjs'; -import { EventType } from '../core/structures/enums'; -import { SernError } from '../core/_internal'; +import { EventType, SernError } from '../core/structures/enums'; import { eventDispatcher } from './event-utils' import { Service } from '../core/ioc'; import type { DependencyList } from '../types/ioc'; @@ -23,14 +22,14 @@ export function eventsHandler( throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; -// buildModules(allPaths) -// .pipe( -// callInitPlugins(emitter), -// map(intoDispatcher), -// /** -// * Where all events are turned on -// */ -// mergeAll(), -// handleCrash(err, emitter, log)) -// .subscribe(); + buildModules(allPaths) + .pipe( + callInitPlugins(emitter), + map(intoDispatcher), + /** + * Where all events are turned on + */ + mergeAll(), + handleCrash(err, emitter, log)) + .subscribe(); } diff --git a/src/sern.ts b/src/sern.ts index 4045caf0..fbf8f39c 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,44 +1,65 @@ import callsites from 'callsites'; -import * as Files from './core/module-loading'; +import * as Files from './core/module-loading'; +import { merge } from 'rxjs'; import { Services } from './core/ioc'; -import type { DependencyList } from './types/ioc'; +import { eventsHandler } from './handlers/user-defined-events'; +import { readyHandler } from './handlers/ready-event'; +import { messageHandler } from './handlers/message'; +import { interactionHandler } from './handlers/interaction'; +import { presenceHandler } from './handlers/presence'; +import { Client } from 'discord.js'; +import { handleCrash } from './handlers/event-utils'; + interface Wrapper { commands?: string; defaultPrefix?: string; events?: string; } - -const __start = (entryPoint: string, - wrapper: { defaultPrefix?: string }, - dependencies: DependencyList) => { - //@ts-ignore sern handler generates handler.js - import(entryPoint) - .then(({ commands=new Map(), events=new Map() }) => { - console.log(commands, events) - }) - .catch(err => dependencies[2]?.error({ message: err })); -} /** * @since 1.0.0 * @param wrapper Options to pass into sern. * Function to start the handler up * @example * ```ts title="src/index.ts" - * Sern.init() + * Sern.init({ + * commands: 'dist/commands', + * events: 'dist/events', + * }) * ``` */ -export function init(wrapper: Wrapper) { +export function init(wrapper?: Wrapper) { + wrapper ??= { commands: "./dist/commands", events: "./dist/events" }; const startTime = performance.now(); const dependencies = Services('@sern/emitter', '@sern/errors', '@sern/logger', '@sern/client'); + const logger = dependencies[2], + errorHandler = dependencies[1]; - const initCallsite = callsites()[1].getFileName(); - const handlerModule = Files.shouldHandle(initCallsite!, "handler"); - if(!handlerModule.exists) { - throw Error("Could not find handler module, did you run sern build?") + if (wrapper.events !== undefined) { + eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); } - __start(handlerModule.path, wrapper, dependencies); -} + const initCallsite = callsites()[1].getFileName(); + const presencePath = Files.shouldHandle(initCallsite!, "presence"); + //Ready event: load all modules and when finished, time should be taken and logged + readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) + .add(() => { + logger?.info({ message: "Client signaled ready, registering modules" }); + const time = ((performance.now() - startTime) / 1000).toFixed(2); + dependencies[0].emit('modulesLoaded'); + logger?.info({ message: `sern: registered in ${time} s`, }); + if(presencePath.exists) { + const setPresence = async (p: any) => { + return (dependencies[4] as Client).user?.setPresence(p); + } + presenceHandler(presencePath.path, setPresence).subscribe(); + } + }); + + const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); + const interactions$ = interactionHandler(dependencies); + // listening to the message stream and interaction stream + merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); +} From 0a05cbba3f6e3a0c562785515da32f878925bc85 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 13 May 2024 16:06:02 -0500 Subject: [PATCH 32/90] dsfsd --- src/handlers/ready-event.ts | 3 +-- src/handlers/user-defined-events.ts | 26 +++++++++++++------------- src/sern.ts | 4 ++-- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index b92aa9e3..188875dc 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -11,12 +11,11 @@ const once = (log: Logging | undefined) => pipe( export function readyHandler( [sEmitter, , log, client]: DependencyList, - allPaths: ObservableInput, ) { //Todo: add module manager on on ready const ready$ = fromEvent(client!, 'ready').pipe(once(log)); - return concat(ready$).pipe(callInitPlugins(sEmitter)) + return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe() // const validModuleType = module.type >= 0 && module.type <= 1 << 10; // assert.ok(validModuleType, // `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 7cefb6aa..31bd390f 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,13 +1,13 @@ -import { ObservableInput } from 'rxjs'; +import { ObservableInput, map, mergeAll } from 'rxjs'; import { EventType, SernError } from '../core/structures/enums'; -import { eventDispatcher } from './event-utils' +import { callInitPlugins, eventDispatcher, handleCrash } from './event-utils' import { Service } from '../core/ioc'; import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; export function eventsHandler( [emitter, err, log, client]: DependencyList, - allPaths: ObservableInput, + //allPaths: ObservableInput, ) { //code smell const intoDispatcher = (e: { module: Processed }) => { @@ -22,14 +22,14 @@ export function eventsHandler( throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; - buildModules(allPaths) - .pipe( - callInitPlugins(emitter), - map(intoDispatcher), - /** - * Where all events are turned on - */ - mergeAll(), - handleCrash(err, emitter, log)) - .subscribe(); + //buildModules(allPaths) +// pipe( +// callInitPlugins(emitter), +// map(intoDispatcher), +// /** +// * Where all events are turned on +// */ +// mergeAll(), +// handleCrash(err, emitter, log)) +// .subscribe(); } diff --git a/src/sern.ts b/src/sern.ts index fbf8f39c..8d89de7c 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -38,13 +38,13 @@ export function init(wrapper?: Wrapper) { errorHandler = dependencies[1]; if (wrapper.events !== undefined) { - eventsHandler(dependencies, Files.getFullPathTree(wrapper.events)); + eventsHandler(dependencies); } const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged - readyHandler(dependencies, Files.getFullPathTree(wrapper.commands)) + readyHandler(dependencies) .add(() => { logger?.info({ message: "Client signaled ready, registering modules" }); const time = ((performance.now() - startTime) / 1000).toFixed(2); From 880311f08c506ed2ca688fcc6e6e233e49a1f592 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 14 May 2024 12:01:18 -0500 Subject: [PATCH 33/90] refactor, add cron types, reinstante module loader --- package.json | 13 +--- src/_internal.ts | 4 -- src/core/_internal.ts | 1 - src/core/ioc/base.ts | 4 +- src/core/module-loading.ts | 26 ++++++-- src/core/modules.ts | 24 +------- src/core/structures/enums.ts | 7 ++- src/handlers/event-utils.ts | 6 +- src/handlers/interaction.ts | 5 +- src/handlers/message.ts | 6 +- src/handlers/ready-event.ts | 13 ++-- src/sern.ts | 5 +- src/types/core-modules.ts | 2 + src/types/core-plugin.ts | 4 ++ test/core/ioc.test.ts | 111 ----------------------------------- test/core/services.test.ts | 52 ---------------- yarn.lock | 10 ++-- 17 files changed, 60 insertions(+), 233 deletions(-) delete mode 100644 src/_internal.ts delete mode 100644 test/core/ioc.test.ts delete mode 100644 test/core/services.test.ts diff --git a/package.json b/package.json index da50b36b..bf063ace 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,6 @@ ".": { "import": "./dist/index.js", "require": "./dist/index.js" - }, - "./internal": { - "import": "./dist/_internal.js", - "require": "./dist/_internal.js" } }, "scripts": { @@ -45,7 +41,7 @@ }, "devDependencies": { "@faker-js/faker": "^8.0.1", - "@types/node": "^18.15.11", + "@types/node": "~18.17.11", "@typescript-eslint/eslint-plugin": "5.58.0", "@typescript-eslint/parser": "5.59.1", "discord.js": "^14.11.0", @@ -80,10 +76,7 @@ "allowTemplateLiterals": true } ], - "semi": [ - "error", - "always" - ], + "semi": [ "error", "always" ], "@typescript-eslint/no-empty-interface": 0, "@typescript-eslint/ban-types": 0, "@typescript-eslint/no-explicit-any": "off" @@ -94,7 +87,7 @@ "url": "git+https://github.com/sern-handler/handler.git" }, "engines": { - "node": ">= 18.16.x" + "node": ">= 18.17.x" }, "homepage": "https://sern.dev" } diff --git a/src/_internal.ts b/src/_internal.ts deleted file mode 100644 index fd40910d..00000000 --- a/src/_internal.ts +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/core/_internal.ts b/src/core/_internal.ts index b7ab4f35..439c1705 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,6 +1,5 @@ import type { Result } from 'ts-results-es' -export * from './operators'; export * from './functions'; export type _Module = { diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 75425002..a33643b2 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -72,8 +72,9 @@ async function composeRoot( //container should have no client or logger yet. const hasLogger = conf.exclude?.has('@sern/logger'); if (!hasLogger) { - __add_container('@sern/logger', new __Services.DefaultLogging); + __add_container('@sern/logger', new __Services.DefaultLogging()); } + __add_container('@sern/errors', new __Services.DefaultErrorHandling()); //Build the container based on the callback provided by the user conf.build(container as Container); @@ -97,6 +98,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { if(includeLogger) { __add_container('@sern/logger', new __Services.DefaultLogging); } + __add_container('@sern/errors', new __Services.DefaultErrorHandling()); await useContainerRaw().ready(); } else { await composeRoot(useContainerRaw(), conf); diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 32bf7b57..cc7dc468 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,7 +1,9 @@ import path from 'node:path'; import { existsSync } from 'fs'; +import { readdir } from 'fs/promises'; import assert from 'node:assert'; - +import * as Id from './id' +import type { _Module } from './_internal'; export const parseCallsite = (site: string) => { const pathobj = path.parse(site.replace(/file:\\?/, "") @@ -27,7 +29,6 @@ export const shouldHandle = (pth: string, filenam: string) => { * commonjs, javascript : * ```js * exports = commandModule({ }) - * * //or * exports.default = commandModule({ }) * ``` @@ -37,16 +38,33 @@ export const shouldHandle = (pth: string, filenam: string) => { export async function importModule(absPath: string) { let fileModule = await import(absPath); - let commandModule = fileModule.default; + let commandModule: _Module = fileModule.default; assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); if ('default' in commandModule) { - commandModule = commandModule.default; + commandModule = commandModule.default as _Module; } + const p = path.parse(absPath) + commandModule.name ??= p.name; commandModule.description ??= "..."; + commandModule.meta = { + //@ts-ignore + id: Id.create(commandModule.name, commandModule.type), + absPath, + }; return { module: commandModule } as T; } +export async function* readRecursive(dir: string): AsyncGenerator { + const files = await readdir(dir, { withFileTypes: true, recursive: true }); + for (const file of files) { + const fullPath = path.join(file.path, file.name); + if(!file.name.startsWith('!') && !file.isDirectory()) { + yield fullPath; + } + } +} + export const fmtFileName = (fileName: string) => path.parse(fileName).name; export const filename = (p: string) => fmtFileName(path.basename(p)); diff --git a/src/core/modules.ts b/src/core/modules.ts index a8c87c53..e2be1f4a 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -7,29 +7,16 @@ import type { } from '../types/core-modules'; import { type _Module, partitionPlugins } from './_internal'; import type { Awaitable } from '../types/utility'; -import callsites, { type CallSite } from 'callsites'; -import * as Files from './module-loading' -import * as Id from './id' -const get_callsite = (css: CallSite[]) => { - return css.map(cs => cs.getFileName()).filter(Boolean) -} + /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod */ export function commandModule(mod: InputCommand): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = get_callsite(callsites()).at(-2); - if(!initCallsite) throw Error("initCallsite is null"); - const { name, absPath } = Files.parseCallsite(initCallsite); - mod.name ??= name; mod.description ??= '...' //@ts-ignore return { ...mod, - meta: { - id: Id.create(mod.name, mod.type), - absPath - }, onEvent, plugins, }; @@ -41,17 +28,10 @@ export function commandModule(mod: InputCommand): _Module { */ export function eventModule(mod: InputEvent): _Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - const initCallsite = get_callsite(callsites()).at(-2); - if(!initCallsite) throw Error("initCallsite is null"); - const { name, absPath } = Files.parseCallsite(initCallsite); - mod.name ??= name; mod.description ??= '...' + //@ts-ignore return { ...mod, - meta: { - id: Id.create(mod.name, mod.type), - absPath - }, plugins, onEvent, }; diff --git a/src/core/structures/enums.ts b/src/core/structures/enums.ts index 663785e3..ef398f10 100644 --- a/src/core/structures/enums.ts +++ b/src/core/structures/enums.ts @@ -48,16 +48,17 @@ export enum EventType { /** * The EventType for handling discord events */ - Discord = 1, + Discord, /** * The EventType for handling sern events */ - Sern = 2, + Sern, /** * The EventType for handling external events. * Could be for example, `process` events, database events */ - External = 3, + External, + Cron } /** diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index c1991289..d77302bc 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -14,13 +14,8 @@ import { pipe } from 'rxjs'; import { - callPlugin, - everyPluginOk, - filterMapTo, - handleError, type VoidResult, resultPayload, - arrayifySource, isAutocomplete, treeSearch, _Module, @@ -39,6 +34,7 @@ import { CommandType } from '../core/structures/enums' import type { Args } from '../types/utility'; import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; +import { arrayifySource, callPlugin, everyPluginOk, filterMapTo, handleError } from '../core/operators'; function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index d9b3c717..ffe9d2e0 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -1,13 +1,12 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap } from 'rxjs'; import { PayloadType } from '../core/structures/enums'; -import { filterTap } from '../core/operators' +import { filterTap, sharedEventStream } from '../core/operators' import { isAutocomplete, isCommand, isMessageComponent, isModal, - sharedEventStream, resultPayload, } from '../core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; @@ -19,7 +18,7 @@ export function interactionHandler([emitter, err, log, client]: DependencyList) const handle = createInteractionHandler(interactionStream$, modules); const interactionHandler$ = merge(handle(isMessageComponent), - handle(isAutocomplete), + handle(isAutocomplete), handle(isCommand), handle(isModal)); return interactionHandler$ diff --git a/src/handlers/message.ts b/src/handlers/message.ts index bcc6a669..8046ac12 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,11 +1,11 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { sharedEventStream } from '../core/_internal'; import type { DependencyList } from '../types/ioc'; import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' -import { filterTap } from '../core/operators' +import { filterTap, sharedEventStream } from '../core/operators' + /** * Ignores messages from any person / bot except itself * @param prefix @@ -16,7 +16,7 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); - return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent', }) === 0); + return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); } export function messageHandler( diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts index 188875dc..22ea02a9 100644 --- a/src/handlers/ready-event.ts +++ b/src/handlers/ready-event.ts @@ -1,13 +1,13 @@ -import { ObservableInput, concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; +import { concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; import { _Module } from '../core/_internal'; import { Logging } from '../core/interfaces'; import type { DependencyList } from '../types/ioc'; import { callInitPlugins } from './event-utils'; -const once = (log: Logging | undefined) => pipe( - tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), - first(), - ignoreElements()) +const once = (log: Logging | undefined) => + pipe(tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), + first(), + ignoreElements()) export function readyHandler( [sEmitter, , log, client]: DependencyList, @@ -15,7 +15,8 @@ export function readyHandler( //Todo: add module manager on on ready const ready$ = fromEvent(client!, 'ready').pipe(once(log)); - return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe() + return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe(); + // const validModuleType = module.type >= 0 && module.type <= 1 << 10; // assert.ok(validModuleType, // `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); diff --git a/src/sern.ts b/src/sern.ts index 8d89de7c..35875e95 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -27,8 +27,7 @@ interface Wrapper { * }) * ``` */ -export function init(wrapper?: Wrapper) { - wrapper ??= { commands: "./dist/commands", events: "./dist/events" }; +export function init(wrapper: Wrapper = { commands: "./dist/commands", events: "./dist/events" }) { const startTime = performance.now(); const dependencies = Services('@sern/emitter', '@sern/errors', @@ -52,7 +51,7 @@ export function init(wrapper?: Wrapper) { logger?.info({ message: `sern: registered in ${time} s`, }); if(presencePath.exists) { const setPresence = async (p: any) => { - return (dependencies[4] as Client).user?.setPresence(p); + return (dependencies[3] as Client).user?.setPresence(p); } presenceHandler(presencePath.path, setPresence).subscribe(); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 2533a873..c5940226 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -163,6 +163,8 @@ export interface EventModuleDefs { [EventType.Sern]: SernEventCommand; [EventType.Discord]: DiscordEventCommand; [EventType.External]: ExternalEventCommand; + //TODO + [EventType.Cron]: ExternalEventCommand; } export interface SernAutocompleteData diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 5cff96f4..331c9be2 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -150,4 +150,8 @@ interface EventArgsMatrix { [PluginType.Control]: unknown[]; [PluginType.Init]: [InitArgs>]; }; + [EventType.Cron]: { + [PluginType.Control]: unknown[]; + [PluginType.Init]: [InitArgs>]; + }; } diff --git a/test/core/ioc.test.ts b/test/core/ioc.test.ts deleted file mode 100644 index 46cd0c0f..00000000 --- a/test/core/ioc.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { CoreContainer } from '../../src/core/ioc/container'; -import { EventEmitter } from 'events'; -import { Disposable, Emitter, Init, Logging } from '../../src/core/interfaces'; -import * as __Services from '../../src/core/structures/default-services' -import { CoreDependencies } from '../../src/types/ioc'; - -describe('ioc container', () => { - let container: CoreContainer<{}> = new CoreContainer(); - let dependency: Logging & Init & Disposable; - let dependency2: Emitter - beforeEach(() => { - dependency = { - init: vi.fn(), - error(): void {}, - warning(): void {}, - info(): void {}, - debug(): void {}, - dispose: vi.fn() - }; - dependency2 = { - addListener: vi.fn(), - removeListener: vi.fn(), - emit: vi.fn() - }; - container = new CoreContainer(); - }); - const wait = (seconds: number) => new Promise((resolve) => setTimeout(resolve, seconds)); - class DB implements Init, Disposable { - public connected = false - constructor() {} - async init() { - this.connected = true - await wait(10) - } - async dispose() { - await wait(20) - this.connected = false - } - } - it('should be ready after calling container.ready()', () => { - container.ready(); - expect(container.isReady()).toBe(true); - }); - it('should container all core dependencies', async () => { - const keys = [ - '@sern/emitter', - '@sern/logger', - '@sern/errors', - ] satisfies (keyof CoreDependencies)[]; - container.add({ - '@sern/logger': () => new __Services.DefaultLogging(), - '@sern/client': () => new EventEmitter(), - }); - for (const k of keys) { - //@ts-expect-error typings for iti are strict - expect(() => container.get(k)).not.toThrow(); - } - }); - it('should init modules', () => { - container.upsert({ '@sern/logger': dependency }); - container.ready(); - expect(dependency.init).to.toHaveBeenCalledOnce(); - }); - it('should dispose modules', async () => { - - container.upsert({ '@sern/logger': dependency }) - - container.ready(); - // We need to access the dependency at least once to be able to dispose of it. - container.get('@sern/logger' as never); - await container.disposeAll(); - expect(dependency.dispose).toHaveBeenCalledOnce(); - }); - - it('should init and dispose', async () => { - container.add({ db: new DB() }) - container.ready() - const db = container.get('db' as never) as DB - expect(db.connected).toBeTruthy() - - await container.disposeAll(); - - expect(db.connected).toBeFalsy() - }) - - it('should not lazy module', () => { - container.upsert({ '@sern/logger': () => dependency }); - container.ready(); - expect(dependency.init).toHaveBeenCalledTimes(0); - }); - - it('should init dependency depending on something else', () => { - container.add({ '@sern/client': dependency2 }); - container.upsert((cntr) => ({ '@sern/logger': dependency })); - container.ready(); - expect(dependency.init).toHaveBeenCalledTimes(1); - }) - - it('should detect a key already exists', () => { - container.add({ '@sern/client': dependency2 }); - expect(container.hasKey('@sern/client')).toBeTruthy() - }) - - - it('should detect a key already exists', () => { - container.add({ '@sern/client': () => dependency2 }); - expect(container.hasKey('@sern/client')).toBeTruthy() - }) - -}); diff --git a/test/core/services.test.ts b/test/core/services.test.ts deleted file mode 100644 index 09cea944..00000000 --- a/test/core/services.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { SpyInstance, afterAll, beforeEach, describe, expect, it, vi } from 'vitest'; -import { CoreContainer } from '../../src/core/ioc/container'; -import * as __Services from '../../src/core/structures/default-services'; -import { faker } from '@faker-js/faker'; -import { commandModule, CommandType } from '../../src'; - -function createRandomCommandModules() { - return commandModule({ - type: CommandType.Slash, - description: faker.string.alpha(), - name: faker.string.alpha({ length: { min: 5, max: 10 }}), - execute: vi.fn(), - }); -} -describe('services', () => { - //@ts-ignore - let container: CoreContainer; - let consoleMock: SpyInstance; - beforeEach(() => { - container = new CoreContainer(); - container.add({ '@sern/logger': () => new __Services.DefaultLogging() }); - container.ready(); - consoleMock = vi.spyOn(container.get('@sern/logger'), 'error').mockImplementation(() => {}); - }); - - afterAll(() => { - consoleMock.mockReset(); - }); - - //todo add more - it('error-handling', () => { - const errorHandler = container.get('@sern/errors'); - const lifetime = errorHandler.keepAlive; - for (let i = 0; i < lifetime; i++) { - if (i == lifetime - 1) { - expect(() => errorHandler.updateAlive(new Error('poo'))).toThrowError(); - } else { - expect(() => errorHandler.updateAlive(new Error('poo'))).not.toThrowError(); - } - } - }); - //todo add more, spy on every instance? - it('logger', () => { - container.get('@sern/logger').error({ message: 'error' }); - - expect(consoleMock).toHaveBeenCalledOnce(); - expect(consoleMock).toHaveBeenLastCalledWith({ message: 'error' }); - }); - - - -}); diff --git a/yarn.lock b/yarn.lock index c380662e..43cc46b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -235,7 +235,7 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 - "@types/node": ^18.15.11 + "@types/node": ~18.17.11 "@typescript-eslint/eslint-plugin": 5.58.0 "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 @@ -262,10 +262,10 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^18.15.11": - version: 18.17.14 - resolution: "@types/node@npm:18.17.14" - checksum: f96ce1e588426a26cf82440193084f8bbab47bfb3c2e668cf174095f99ce808a20654b2137448c7e88cfd7b6c2b8521ffb6f714f521b3502ac595a0df0bff679 +"@types/node@npm:~18.17.11": + version: 18.17.19 + resolution: "@types/node@npm:18.17.19" + checksum: 6ab47127cd7534511aa199550659d56b44e5a6dbec9df054d0cde279926b4d43f0e6438f92c8392b039ab4e2a85aa0f698b95926430aff860e23bfc36c96576c languageName: node linkType: hard From a7aea4be1a7ee4f51c352a526dd89a0aa6db4cd6 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 14 May 2024 23:19:57 -0500 Subject: [PATCH 34/90] ready handler revamped so much cleaner --- package.json | 11 +++++-- src/core/_internal.ts | 14 ++------- src/core/interfaces.ts | 1 + src/core/ioc/base.ts | 3 ++ src/core/ioc/container.ts | 2 +- src/core/module-loading.ts | 15 ++++------ src/core/modules.ts | 14 ++++----- src/handlers/event-utils.ts | 38 ++++-------------------- src/handlers/interaction.ts | 11 ++----- src/handlers/message.ts | 5 ++-- src/handlers/presence.ts | 5 +--- src/handlers/ready-event.ts | 25 ---------------- src/handlers/ready.ts | 30 +++++++++++++++++++ src/handlers/user-defined-events.ts | 11 ++++--- src/index.ts | 2 +- src/sern.ts | 31 +++++++++---------- src/types/core-modules.ts | 16 ++++++++-- src/types/ioc.ts | 19 ++++-------- src/types/utility.ts | 2 +- yarn.lock | 46 +++++++++++++++++++++++++---- 20 files changed, 153 insertions(+), 148 deletions(-) delete mode 100644 src/handlers/ready-event.ts create mode 100644 src/handlers/ready.ts diff --git a/package.json b/package.json index bf063ace..e985a5a7 100644 --- a/package.json +++ b/package.json @@ -36,12 +36,14 @@ "license": "MIT", "dependencies": { "callsites": "^3.1.0", + "node-cron": "^3.0.3", "rxjs": "^7.8.0", "ts-results-es": "^4.1.0" }, "devDependencies": { "@faker-js/faker": "^8.0.1", - "@types/node": "~18.17.11", + "@types/node": "^20.0.0", + "@types/node-cron": "^3.0.11", "@typescript-eslint/eslint-plugin": "5.58.0", "@typescript-eslint/parser": "5.59.1", "discord.js": "^14.11.0", @@ -76,7 +78,10 @@ "allowTemplateLiterals": true } ], - "semi": [ "error", "always" ], + "semi": [ + "error", + "always" + ], "@typescript-eslint/no-empty-interface": 0, "@typescript-eslint/ban-types": 0, "@typescript-eslint/no-explicit-any": "off" @@ -87,7 +92,7 @@ "url": "git+https://github.com/sern-handler/handler.git" }, "engines": { - "node": ">= 18.17.x" + "node": ">= 20.0.x" }, "homepage": "https://sern.dev" } diff --git a/src/core/_internal.ts b/src/core/_internal.ts index 439c1705..a2347342 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,15 +1,7 @@ import type { Result } from 'ts-results-es' +import { CommandType, EventType, Plugin } from '..'; +import { AnyFunction } from '../types/utility'; +import { Module } from '../types/core-modules'; -export * from './functions'; - -export type _Module = { - meta: { - id: string, - absPath: string - } - name: string, - execute : Function - [key: PropertyKey]: unknown -} export type VoidResult = Result; diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts index 9c1ab4fa..70b9b8ac 100644 --- a/src/core/interfaces.ts +++ b/src/core/interfaces.ts @@ -21,6 +21,7 @@ export interface Emitter { addListener(eventName: string | symbol, listener: AnyFunction): this; removeListener(eventName: string | symbol, listener: AnyFunction): this; emit(eventName: string | symbol, ...payload: any[]): boolean; + on(eventName: string | symbol, listener: AnyFunction): this } diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index a33643b2..6ab34649 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -75,6 +75,8 @@ async function composeRoot( __add_container('@sern/logger', new __Services.DefaultLogging()); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); + __add_container('@sern/cron', {}) + __add_container('@sern/modules', new Map()) //Build the container based on the callback provided by the user conf.build(container as Container); @@ -99,6 +101,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { __add_container('@sern/logger', new __Services.DefaultLogging); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); + __add_container('@sern/cron', {}) await useContainerRaw().ready(); } else { await composeRoot(useContainerRaw(), conf); diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 91a66a04..1151db66 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -4,7 +4,7 @@ import * as __Services from '../structures/default-services'; * A semi-generic container that provides error handling, emitter, and module store. * For the handler to operate correctly, The only user provided dependency needs to be @sern/client */ -export function hasCallableMethod(obj: object, name: PropertyKey) { +function hasCallableMethod(obj: object, name: PropertyKey) { //@ts-ignore return Object.hasOwn(obj, name) && typeof obj[name] == 'function'; } diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index cc7dc468..9a3c438a 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -3,7 +3,7 @@ import { existsSync } from 'fs'; import { readdir } from 'fs/promises'; import assert from 'node:assert'; import * as Id from './id' -import type { _Module } from './_internal'; +import { Module } from '../types/core-modules'; export const parseCallsite = (site: string) => { const pathobj = path.parse(site.replace(/file:\\?/, "") @@ -38,11 +38,11 @@ export const shouldHandle = (pth: string, filenam: string) => { export async function importModule(absPath: string) { let fileModule = await import(absPath); - let commandModule: _Module = fileModule.default; + let commandModule: Module = fileModule.default; assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); if ('default' in commandModule) { - commandModule = commandModule.default as _Module; + commandModule = commandModule.default as Module; } const p = path.parse(absPath) commandModule.name ??= p.name; commandModule.description ??= "..."; @@ -51,21 +51,18 @@ export async function importModule(absPath: string) { id: Id.create(commandModule.name, commandModule.type), absPath, }; - return { module: commandModule } as T; + return { module: commandModule as T }; } export async function* readRecursive(dir: string): AsyncGenerator { - const files = await readdir(dir, { withFileTypes: true, recursive: true }); + const files = await readdir(dir, { recursive: true, withFileTypes: true }); for (const file of files) { - const fullPath = path.join(file.path, file.name); + const fullPath = path.join(file.parentPath, file.name); if(!file.name.startsWith('!') && !file.isDirectory()) { yield fullPath; } } } -export const fmtFileName = (fileName: string) => path.parse(fileName).name; - -export const filename = (p: string) => fmtFileName(path.basename(p)); diff --git a/src/core/modules.ts b/src/core/modules.ts index e2be1f4a..3e13c671 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -4,37 +4,35 @@ import type { AnyEventPlugin, } from '../types/core-plugin'; import type { InputCommand, InputEvent, + Module, } from '../types/core-modules'; -import { type _Module, partitionPlugins } from './_internal'; +import { partitionPlugins } from './functions' import type { Awaitable } from '../types/utility'; /** * @since 1.0.0 The wrapper function to define command modules for sern * @param mod */ -export function commandModule(mod: InputCommand): _Module { +export function commandModule(mod: InputCommand): Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - //@ts-ignore return { ...mod, onEvent, plugins, - }; + } as Module; } /** * @since 1.0.0 * The wrapper function to define event modules for sern * @param mod */ -export function eventModule(mod: InputEvent): _Module { +export function eventModule(mod: InputEvent): Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - - //@ts-ignore return { ...mod, plugins, onEvent, - }; + } as Module; } /** Create event modules from discord.js client events, diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index d77302bc..763bc8b6 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -15,10 +15,6 @@ import { } from 'rxjs'; import { type VoidResult, - resultPayload, - isAutocomplete, - treeSearch, - _Module, } from '../core/_internal'; import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; @@ -42,7 +38,7 @@ function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[ const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options]; return [ctx, args] as [Context, Args]; } - +import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' function intoPayload(module: Processed, ) { return pipe(map(arrayifySource), @@ -127,7 +123,7 @@ export function fmt(msg: string, prefix: string): string[] { */ export function createInteractionHandler( source: Observable, - mg: Map, //TODO + mg: Map, //TODO ) { return createGenericHandler, void>>( source, @@ -135,7 +131,7 @@ export function createInteractionHandler( const possibleIds = Id.reconstruct(event); let fullPaths= possibleIds .map(id => mg.get(id)) - .filter((id): id is _Module => id !== undefined); + .filter((id): id is Module => id !== undefined); if(fullPaths.length == 0) { return Err.EMPTY; @@ -230,25 +226,6 @@ export function createResultResolver< }; }; -/** - * Calls a module's init plugins and checks for Err. If so, call { onStop } and - * ignore the module - */ -export function callInitPlugins>(sernEmitter: Emitter) { - return concatMap( - createResultResolver({ - createStream: args => from(args.module.plugins).pipe(callPlugin(args)), - onStop: (module: T) => { - sernEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); - }, - onNext: (payload) => { - sernEmitter.emit('module.register', resultPayload(PayloadType.Success, payload.module)); - return payload as { module: T; metadata: CommandMeta }; - }, - }), - ); -} - /** * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter @@ -264,19 +241,16 @@ export function makeModuleExecutor< }); return createResultResolver({ onStop, - createStream: ({ args, module }) => - from(module.onEvent) - .pipe(callPlugin(args)), + createStream: ({ args, module }) => from(module.onEvent).pipe(callPlugin(args)), onNext, }) } export const handleCrash = (err: ErrorHandling,sernemitter: Emitter, log?: Logging) => - pipe( - catchError(handleError(err, sernemitter, log)), + pipe(catchError(handleError(err, sernemitter, log)), finalize(() => { log?.info({ message: 'A stream closed or reached end of lifetime', }); disposeAll(log); - })); + })) diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index ffe9d2e0..7c86da31 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -2,16 +2,11 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap } from 'rxjs'; import { PayloadType } from '../core/structures/enums'; import { filterTap, sharedEventStream } from '../core/operators' -import { - isAutocomplete, - isCommand, - isMessageComponent, - isModal, - resultPayload, -} from '../core/_internal'; import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; import type { DependencyList } from '../types/ioc'; import { SernError } from '../core/structures/enums' +import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, } from '../core/functions' + export function interactionHandler([emitter, err, log, client]: DependencyList) { const interactionStream$ = sharedEventStream(client, 'interactionCreate'); const modules = new Map(); @@ -25,5 +20,5 @@ export function interactionHandler([emitter, err, log, client]: DependencyList) .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), concatMap(makeModuleExecutor(module => emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), - mergeMap(payload => executeModule(emitter, log, err, payload))); + mergeMap(payload => executeModule(emitter, log, err, payload))); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 8046ac12..8c851e5a 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -20,16 +20,15 @@ function hasPrefix(prefix: string, content: string) { } export function messageHandler( - [emitter, err, log, client]: DependencyList, + [emitter, err, log, client, commands]: DependencyList, defaultPrefix: string | undefined, ) { if (!defaultPrefix) { log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; } - const modules = new Map() const messageStream$ = sharedEventStream(client, 'messageCreate'); - const handle = createMessageHandler(messageStream$, defaultPrefix, modules); + const handle = createMessageHandler(messageStream$, defaultPrefix, commands); const msgCommands$ = handle(isNonBot(defaultPrefix)); diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index b393e3d1..f492a696 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -23,11 +23,8 @@ const parseConfig = async (conf: Promise) => { }; export const presenceHandler = (path: string, setPresence: SetPresence) => { - interface PresenceModule { - module: PresenceConfig<(keyof Dependencies)[]> - } const presence = Files - .importModule(path) + .importModule>(path) .then(({ module }) => { //fetch services with the order preserved, passing it to the execute fn const fetchedServices = Services(...module.inject ?? []); diff --git a/src/handlers/ready-event.ts b/src/handlers/ready-event.ts deleted file mode 100644 index 22ea02a9..00000000 --- a/src/handlers/ready-event.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { concat, first, fromEvent, ignoreElements, pipe, tap } from 'rxjs'; -import { _Module } from '../core/_internal'; -import { Logging } from '../core/interfaces'; -import type { DependencyList } from '../types/ioc'; -import { callInitPlugins } from './event-utils'; - -const once = (log: Logging | undefined) => - pipe(tap(() => { log?.info({ message: "Waiting on discord client to be ready..." }) }), - first(), - ignoreElements()) - -export function readyHandler( - [sEmitter, , log, client]: DependencyList, -) { - //Todo: add module manager on on ready - const ready$ = fromEvent(client!, 'ready').pipe(once(log)); - - return concat(ready$).pipe(callInitPlugins(sEmitter)).subscribe(); - -// const validModuleType = module.type >= 0 && module.type <= 1 << 10; -// assert.ok(validModuleType, -// `Found ${module.name} at ${module.meta.fullPath}, which does not have a valid type`); -} - - diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts new file mode 100644 index 00000000..38ba3982 --- /dev/null +++ b/src/handlers/ready.ts @@ -0,0 +1,30 @@ +import type { DependencyList } from '../types/ioc'; +import * as Files from '../core/module-loading' +import { once } from 'events'; +import { resultPayload } from '../core/functions'; +import { PayloadType } from '..'; +import { SernError } from '../core/structures/enums'; +import { Module } from '../types/core-modules'; + +export default async function(dir: string, [sEmitter,, log, client, commands]: DependencyList) { + log?.info({ message: "Waiting on discord client to be ready..." }) + await once(client, "ready"); + log?.info({ message: "Client signaled ready, registering modules" }); + for await (const path of Files.readRecursive(dir)) { + const { module } = await Files.importModule(path); + const validModuleType = module.type >= 0 && module.type <= 1 << 10; + if(!validModuleType) { + throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``); + } + for(const plugin of module.plugins) { + const res = await plugin.execute({ module, absPath: module.meta.absPath }); + if(res.isErr()) { + sEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + throw Error("Plugin failed with controller.stop()"); + } + } + commands.set(module.meta.id, module); + sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); + } + sEmitter.emit('modulesLoaded'); +} diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 31bd390f..d1ff2fe1 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,14 +1,10 @@ -import { ObservableInput, map, mergeAll } from 'rxjs'; import { EventType, SernError } from '../core/structures/enums'; -import { callInitPlugins, eventDispatcher, handleCrash } from './event-utils' +import { eventDispatcher } from './event-utils' import { Service } from '../core/ioc'; import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; -export function eventsHandler( - [emitter, err, log, client]: DependencyList, - //allPaths: ObservableInput, -) { +export default function( [emitter, err, log, client]: DependencyList, eventDir: string) { //code smell const intoDispatcher = (e: { module: Processed }) => { switch (e.module.type) { @@ -18,6 +14,9 @@ export function eventsHandler( return eventDispatcher(e.module, client); case EventType.External: return eventDispatcher(e.module, Service(e.module.emitter)); + case EventType.Cron: + //@ts-ignore + return eventDispatcher(e.module, Service('@sern/cron')) default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } diff --git a/src/index.ts b/src/index.ts index 6aac3e6b..b752b228 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ export type { export type { Args, SlashOptions, Payload, SernEventsMapping } from './types/utility'; -export type { Singleton, Transient, CoreDependencies } from './types/ioc'; +export type { CoreDependencies } from './types/ioc'; export { commandModule, diff --git a/src/sern.ts b/src/sern.ts index 35875e95..8e865a68 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -2,8 +2,8 @@ import callsites from 'callsites'; import * as Files from './core/module-loading'; import { merge } from 'rxjs'; import { Services } from './core/ioc'; -import { eventsHandler } from './handlers/user-defined-events'; -import { readyHandler } from './handlers/ready-event'; +import eventsHandler from './handlers/user-defined-events'; +import ready from './handlers/ready'; import { messageHandler } from './handlers/message'; import { interactionHandler } from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; @@ -11,9 +11,9 @@ import { Client } from 'discord.js'; import { handleCrash } from './handlers/event-utils'; interface Wrapper { - commands?: string; + commands: string; defaultPrefix?: string; - events?: string; + events: string; } /** * @since 1.0.0 @@ -27,37 +27,38 @@ interface Wrapper { * }) * ``` */ -export function init(wrapper: Wrapper = { commands: "./dist/commands", events: "./dist/events" }) { +export function init(maybeWrapper: Wrapper = { commands: "./dist/commands", events: "./dist/events" }) { const startTime = performance.now(); const dependencies = Services('@sern/emitter', '@sern/errors', '@sern/logger', - '@sern/client'); + '@sern/client', + '@sern/modules'); const logger = dependencies[2], errorHandler = dependencies[1]; - - if (wrapper.events !== undefined) { - eventsHandler(dependencies); + + if (maybeWrapper.events !== undefined) { + eventsHandler(dependencies, maybeWrapper.events); } const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged - readyHandler(dependencies) - .add(() => { - logger?.info({ message: "Client signaled ready, registering modules" }); + ready(maybeWrapper.commands, dependencies) + .then(() => { const time = ((performance.now() - startTime) / 1000).toFixed(2); - dependencies[0].emit('modulesLoaded'); logger?.info({ message: `sern: registered in ${time} s`, }); if(presencePath.exists) { const setPresence = async (p: any) => { + //@ts-ignore return (dependencies[3] as Client).user?.setPresence(p); } presenceHandler(presencePath.path, setPresence).subscribe(); } - }); + }) + .catch(err => { throw err }); - const messages$ = messageHandler(dependencies, wrapper.defaultPrefix); + const messages$ = messageHandler(dependencies, maybeWrapper.defaultPrefix); const interactions$ = interactionHandler(dependencies); // listening to the message stream and interaction stream merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index c5940226..ed710861 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -35,6 +35,10 @@ export interface Module { onEvent: ControlPlugin[]; plugins: InitPlugin[]; description?: string; + meta: { + id: string; + absPath: string; + } execute(...args: any[]): Awaitable; } @@ -44,12 +48,18 @@ export interface SernEventCommand; } + export interface ExternalEventCommand extends Module { name?: string; emitter: keyof Dependencies; type: EventType.External; execute(...args: unknown[]): Awaitable; } +export interface CronEventCommand extends Module { + name?: string; + type: EventType.Cron; + execute(...args: unknown[]): Awaitable; +} export interface ContextMenuUser extends Module { type: CommandType.CtxUser; @@ -127,7 +137,7 @@ export interface BothCommand extends Module { execute: (ctx: Context, args: Args) => Awaitable; } -export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand; +export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand; export type CommandModule = | TextCommand | SlashCommand @@ -178,10 +188,10 @@ export interface SernAutocompleteData } type CommandModuleNoPlugins = { - [T in CommandType]: Omit; + [T in CommandType]: Omit; }; type EventModulesNoPlugins = { - [T in EventType]: Omit; + [T in EventType]: Omit; }; export type InputEvent = { diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 8ce0acaa..8fc92e31 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -1,29 +1,22 @@ import type { Container } from '../core/ioc/container'; import * as Contracts from '../core/interfaces'; import type { UnpackFunction } from './utility' -/** - * Type to annotate that something is a singleton. - * T is created once and lazily. - */ -export type Singleton = () => T; -/** - * Type to annotate that something is transient. - * Every time this is called, a new object is created - */ -export type Transient = () => () => T; - +import type { Client } from 'discord.js' +import { Module } from './core-modules'; export type DependencyList = [ Contracts.Emitter, Contracts.ErrorHandling, Contracts.Logging | undefined, - Contracts.Emitter, + Client, + Map ]; export interface CoreDependencies { - '@sern/client': () => Contracts.Emitter; + '@sern/client': () => Client; '@sern/emitter': () => Contracts.Emitter; '@sern/errors': () => Contracts.ErrorHandling; '@sern/logger'?: () => Contracts.Logging; + '@sern/modules': () => Map } export type DependencyFromKey = Dependencies[T]; diff --git a/src/types/utility.ts b/src/types/utility.ts index 4a705dd1..60fad87d 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -4,7 +4,7 @@ import type { Module } from './core-modules'; export type Awaitable = PromiseLike | T; -export type AnyFunction = (...args: unknown[]) => unknown; +export type AnyFunction = (...args: never[]) => unknown; // Thanks to @kelsny type ParseType = { diff --git a/yarn.lock b/yarn.lock index 43cc46b4..25b4e639 100644 --- a/yarn.lock +++ b/yarn.lock @@ -235,12 +235,14 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 - "@types/node": ~18.17.11 + "@types/node": ^20.0.0 + "@types/node-cron": ^3.0.11 "@typescript-eslint/eslint-plugin": 5.58.0 "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 discord.js: ^14.11.0 eslint: 8.39.0 + node-cron: ^3.0.3 prettier: 2.8.8 rxjs: ^7.8.0 ts-results-es: ^4.1.0 @@ -255,6 +257,13 @@ __metadata: languageName: node linkType: hard +"@types/node-cron@npm:^3.0.11": + version: 3.0.11 + resolution: "@types/node-cron@npm:3.0.11" + checksum: a73f69bcca52a5f3b1671cfb00a8e4a1d150d0aef36a611564a2f94e66b6981bade577e267ceeeca6fcee241768902d55eb8cf3a81f9ef4ed767a23112fdb16d + languageName: node + linkType: hard + "@types/node@npm:*": version: 20.5.9 resolution: "@types/node@npm:20.5.9" @@ -262,10 +271,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:~18.17.11": - version: 18.17.19 - resolution: "@types/node@npm:18.17.19" - checksum: 6ab47127cd7534511aa199550659d56b44e5a6dbec9df054d0cde279926b4d43f0e6438f92c8392b039ab4e2a85aa0f698b95926430aff860e23bfc36c96576c +"@types/node@npm:^20.0.0": + version: 20.12.12 + resolution: "@types/node@npm:20.12.12" + dependencies: + undici-types: ~5.26.4 + checksum: 5373983874b9af7c216e7ca5d26b32a8d9829c703a69f1e66f2113598b5be8582c0e009ca97369f1ec9a6282b3f92812208d06eb1e9fc3bd9b939b022303d042 languageName: node linkType: hard @@ -1198,6 +1209,15 @@ __metadata: languageName: node linkType: hard +"node-cron@npm:^3.0.3": + version: 3.0.3 + resolution: "node-cron@npm:3.0.3" + dependencies: + uuid: 8.3.2 + checksum: 351c37491ebf717d0ae69cc941465de118e5c2ef5d48bc3f87c98556241b060f100402c8a618c7b86f9f626b44756b20d8b5385b70e52f80716f21e55db0f1c5 + languageName: node + linkType: hard + "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -1506,6 +1526,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + "undici@npm:5.27.2": version: 5.27.2 resolution: "undici@npm:5.27.2" @@ -1524,6 +1551,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" From eb8ba6799b213cf1930fed33b324eae6b64eb2c8 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 14 May 2024 23:29:20 -0500 Subject: [PATCH 35/90] fdssdf --- src/core/_internal.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/core/_internal.ts b/src/core/_internal.ts index a2347342..da0a304f 100644 --- a/src/core/_internal.ts +++ b/src/core/_internal.ts @@ -1,7 +1,2 @@ import type { Result } from 'ts-results-es' -import { CommandType, EventType, Plugin } from '..'; -import { AnyFunction } from '../types/utility'; -import { Module } from '../types/core-modules'; - - export type VoidResult = Result; From ec45f80be6412b3b8ca6875bc4f42cdfa7e16d1c Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 15 May 2024 00:29:59 -0500 Subject: [PATCH 36/90] refactor deps list --- src/core/ioc/base.ts | 5 +---- src/core/ioc/container.ts | 4 ++++ src/handlers/event-utils.ts | 8 +++++--- src/handlers/interaction.ts | 11 ++++++++--- src/handlers/message.ts | 10 +++++----- src/handlers/ready.ts | 8 ++++++-- src/handlers/user-defined-events.ts | 17 +++++++++-------- src/sern.ts | 27 ++++++++++++--------------- src/types/ioc.ts | 8 +------- src/types/utility.ts | 3 +++ 10 files changed, 54 insertions(+), 47 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 6ab34649..6137a6f5 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,7 +1,7 @@ import type { DependencyConfiguration } from '../../types/ioc'; import { Container } from './container'; import * as __Services from '../structures/default-services'; -import { UnpackFunction } from '../../types/utility'; +import { UnpackedDependencies } from '../../types/utility'; import type { Logging } from '../interfaces'; import { __add_container, __init_container, __swap_container, useContainerRaw } from './global'; @@ -12,9 +12,6 @@ export function disposeAll(logger: Logging|undefined) { } -type UnpackedDependencies = { - [K in keyof Dependencies]: UnpackFunction -} type Insertable = | ((container: UnpackedDependencies) => unknown) | object diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 1151db66..7ba9828c 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -66,6 +66,10 @@ export class Container { this.finished_init = true; } + deps>(): T { + return Object.fromEntries(this.__singletons) as T + } + async executeHooks(name: string) { const hookFunctions = this.hooks.get(name) || []; for (const hookFunction of hookFunctions) { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 763bc8b6..40d88bc3 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -20,7 +20,7 @@ import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; -import type { Awaitable } from '../types/utility'; +import type { Awaitable, UnpackedDependencies } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; import { EventEmitter } from 'node:events'; @@ -246,8 +246,10 @@ export function makeModuleExecutor< }) } -export const handleCrash = (err: ErrorHandling,sernemitter: Emitter, log?: Logging) => - pipe(catchError(handleError(err, sernemitter, log)), +export const handleCrash = ({ "@sern/errors": err, + '@sern/emitter': sem, + '@sern/logger': log } : UnpackedDependencies) => + pipe(catchError(handleError(err, sem, log)), finalize(() => { log?.info({ message: 'A stream closed or reached end of lifetime', diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index 7c86da31..c0552601 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -3,13 +3,18 @@ import { mergeMap, merge, concatMap } from 'rxjs'; import { PayloadType } from '../core/structures/enums'; import { filterTap, sharedEventStream } from '../core/operators' import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; -import type { DependencyList } from '../types/ioc'; import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, } from '../core/functions' +import { UnpackedDependencies } from '../types/utility'; -export function interactionHandler([emitter, err, log, client]: DependencyList) { +export function interactionHandler(deps: UnpackedDependencies) { + //i wish javascript had clojure destructuring + const { '@sern/modules': modules, + '@sern/client': client, + '@sern/logger': log, + '@sern/errors': err, + '@sern/emitter': emitter } = deps const interactionStream$ = sharedEventStream(client, 'interactionCreate'); - const modules = new Map(); const handle = createInteractionHandler(interactionStream$, modules); const interactionHandler$ = merge(handle(isMessageComponent), diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 8c851e5a..a1a05569 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,10 +1,10 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import type { DependencyList } from '../types/ioc'; import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { filterTap, sharedEventStream } from '../core/operators' +import { UnpackedDependencies } from '../types/utility'; /** * Ignores messages from any person / bot except itself @@ -19,10 +19,10 @@ function hasPrefix(prefix: string, content: string) { return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); } -export function messageHandler( - [emitter, err, log, client, commands]: DependencyList, - defaultPrefix: string | undefined, -) { +export function messageHandler({"@sern/emitter": emitter, '@sern/errors':err, + '@sern/logger': log, '@sern/client': client, + '@sern/modules': commands}: UnpackedDependencies, + defaultPrefix: string | undefined) { if (!defaultPrefix) { log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 38ba3982..74474c64 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -1,12 +1,16 @@ -import type { DependencyList } from '../types/ioc'; import * as Files from '../core/module-loading' import { once } from 'events'; import { resultPayload } from '../core/functions'; import { PayloadType } from '..'; import { SernError } from '../core/structures/enums'; import { Module } from '../types/core-modules'; +import { UnpackedDependencies } from '../types/utility'; -export default async function(dir: string, [sEmitter,, log, client, commands]: DependencyList) { +export default async function(dir: string, deps : UnpackedDependencies) { + const { "@sern/client": client, + '@sern/logger': log, + '@sern/emitter': sEmitter, + '@sern/modules': commands} = deps; log?.info({ message: "Waiting on discord client to be ready..." }) await once(client, "ready"); log?.info({ message: "Client signaled ready, registering modules" }); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index d1ff2fe1..40d1977a 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,26 +1,27 @@ import { EventType, SernError } from '../core/structures/enums'; import { eventDispatcher } from './event-utils' -import { Service } from '../core/ioc'; -import type { DependencyList } from '../types/ioc'; import type { EventModule, Processed } from '../types/core-modules'; +import * as Files from '../core/module-loading' +import type { UnpackedDependencies } from '../types/utility'; -export default function( [emitter, err, log, client]: DependencyList, eventDir: string) { +export default function(deps: UnpackedDependencies, eventDir: string) { //code smell const intoDispatcher = (e: { module: Processed }) => { switch (e.module.type) { case EventType.Sern: - return eventDispatcher(e.module, emitter); + return eventDispatcher(e.module, deps['@sern/emitter']); case EventType.Discord: - return eventDispatcher(e.module, client); + return eventDispatcher(e.module, deps['@sern/client']); case EventType.External: - return eventDispatcher(e.module, Service(e.module.emitter)); + return eventDispatcher(e.module, deps[e.module.emitter]); case EventType.Cron: - //@ts-ignore - return eventDispatcher(e.module, Service('@sern/cron')) + //@ts-ignore TODO + return eventDispatcher(e.module, deps['@sern/cron']) default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; + Files.readRecursive(eventDir) //buildModules(allPaths) // pipe( // callInitPlugins(emitter), diff --git a/src/sern.ts b/src/sern.ts index 8e865a68..49aeb6fb 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -9,11 +9,13 @@ import { interactionHandler } from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; import { Client } from 'discord.js'; import { handleCrash } from './handlers/event-utils'; +import { useContainerRaw } from './core/ioc/global'; +import { UnpackedDependencies } from './types/utility'; interface Wrapper { commands: string; defaultPrefix?: string; - events: string; + events?: string; } /** * @since 1.0.0 @@ -27,27 +29,22 @@ interface Wrapper { * }) * ``` */ -export function init(maybeWrapper: Wrapper = { commands: "./dist/commands", events: "./dist/events" }) { + +export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { const startTime = performance.now(); - const dependencies = Services('@sern/emitter', - '@sern/errors', - '@sern/logger', - '@sern/client', - '@sern/modules'); - const logger = dependencies[2], - errorHandler = dependencies[1]; + const deps = useContainerRaw().deps(); if (maybeWrapper.events !== undefined) { - eventsHandler(dependencies, maybeWrapper.events); + eventsHandler(deps, maybeWrapper.events); } const initCallsite = callsites()[1].getFileName(); const presencePath = Files.shouldHandle(initCallsite!, "presence"); //Ready event: load all modules and when finished, time should be taken and logged - ready(maybeWrapper.commands, dependencies) + ready(maybeWrapper.commands, deps) .then(() => { const time = ((performance.now() - startTime) / 1000).toFixed(2); - logger?.info({ message: `sern: registered in ${time} s`, }); + deps['@sern/logger']?.info({ message: `sern: registered in ${time} s` }); if(presencePath.exists) { const setPresence = async (p: any) => { //@ts-ignore @@ -58,8 +55,8 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands", even }) .catch(err => { throw err }); - const messages$ = messageHandler(dependencies, maybeWrapper.defaultPrefix); - const interactions$ = interactionHandler(dependencies); + const messages$ = messageHandler(deps, maybeWrapper.defaultPrefix); + const interactions$ = interactionHandler(deps); // listening to the message stream and interaction stream - merge(messages$, interactions$).pipe(handleCrash(errorHandler, dependencies[0], logger)).subscribe(); + merge(messages$, interactions$).pipe(handleCrash(deps)).subscribe(); } diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 8fc92e31..cac4d3f2 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -3,13 +3,7 @@ import * as Contracts from '../core/interfaces'; import type { UnpackFunction } from './utility' import type { Client } from 'discord.js' import { Module } from './core-modules'; -export type DependencyList = [ - Contracts.Emitter, - Contracts.ErrorHandling, - Contracts.Logging | undefined, - Client, - Map -]; + export interface CoreDependencies { '@sern/client': () => Client; diff --git a/src/types/utility.ts b/src/types/utility.ts index 60fad87d..d215ea16 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -30,4 +30,7 @@ export type Payload = //https://github.com/molszanski/iti/blob/0a3a006113b4176316c308805314a135c0f47902/iti/src/_utils.ts#L29C1-L29C76 export type UnpackFunction = T extends (...args: any) => infer U ? U : T +export type UnpackedDependencies = { + [K in keyof Dependencies]: UnpackFunction +} export type ReplyOptions = string | Omit | MessageReplyOptions; From 16a84e85d1a885e7c0f042dcc043501fe8d51ab4 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 15 May 2024 01:44:23 -0500 Subject: [PATCH 37/90] add more tests, polish up ioc --- src/core/interfaces.ts | 1 + src/core/ioc/base.ts | 6 ++--- src/core/ioc/container.ts | 6 ++--- src/core/module-loading.ts | 13 +++++++---- src/handlers/event-utils.ts | 4 ++-- src/handlers/ready.ts | 4 ++-- src/types/core-modules.ts | 6 ----- test/core/module-loading.test.ts | 39 ++++++++++++++++++++++++------- test/mockules/!ignd.ts | 0 test/mockules/!ignored/ignored.ts | 0 test/mockules/failed.ts | 0 test/mockules/module.ts | 6 +++++ test/mockules/ug/pass.ts | 6 +++++ 13 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 test/mockules/!ignd.ts create mode 100644 test/mockules/!ignored/ignored.ts create mode 100644 test/mockules/failed.ts create mode 100644 test/mockules/module.ts create mode 100644 test/mockules/ug/pass.ts diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts index 70b9b8ac..6e02d301 100644 --- a/src/core/interfaces.ts +++ b/src/core/interfaces.ts @@ -17,6 +17,7 @@ export interface Disposable { dispose(): unknown; } + export interface Emitter { addListener(eventName: string | symbol, listener: AnyFunction): this; removeListener(eventName: string | symbol, listener: AnyFunction): this; diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 6137a6f5..cea55776 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -13,7 +13,7 @@ export function disposeAll(logger: Logging|undefined) { type Insertable = - | ((container: UnpackedDependencies) => unknown) + | ((container: UnpackedDependencies) => object) | object const dependencyBuilder = (container: Container, excluded: string[] ) => { return { @@ -25,9 +25,7 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { if(typeof v !== 'function') { container.addSingleton(key, v) } else { - //TODO fixme - //@ts-ignore - container.addWiredSingleton(key, (cntr: UnpackedDependencies) => v(cntr)) + container.addWiredSingleton(key, (cntr) => v(cntr as UnpackedDependencies)) } }, /** diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 7ba9828c..92aa4f53 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,4 +1,4 @@ -import * as __Services from '../structures/default-services'; +import type { UnpackedDependencies } from '../../types/utility'; /** * A semi-generic container that provides error handling, emitter, and module store. @@ -46,8 +46,8 @@ export class Container { return false; } - addWiredSingleton(key: string, fn: (c: Container) => object) { - const insert = fn(this); + addWiredSingleton(key: string, fn: (c: Record) => object) { + const insert = fn(this.deps()); return this.addSingleton(key, insert); } diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 9a3c438a..d4c6074d 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -40,7 +40,7 @@ export async function importModule(absPath: string) { let commandModule: Module = fileModule.default; - assert(commandModule , `No export @ ${absPath}. Forgot to ignore with "!"? (!${path.basename(absPath)})?`); + assert(commandModule , `No default export @ ${absPath}`); if ('default' in commandModule) { commandModule = commandModule.default as Module; } @@ -56,10 +56,15 @@ export async function importModule(absPath: string) { export async function* readRecursive(dir: string): AsyncGenerator { - const files = await readdir(dir, { recursive: true, withFileTypes: true }); + const files = await readdir(dir, { withFileTypes: true }); + for (const file of files) { - const fullPath = path.join(file.parentPath, file.name); - if(!file.name.startsWith('!') && !file.isDirectory()) { + const fullPath = path.join(dir, file.name); + if (file.isDirectory()) { + if (!file.name.startsWith('!')) { + yield* readRecursive(fullPath); + } + } else if (!file.name.startsWith('!')) { yield fullPath; } } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 40d88bc3..5d9cb51f 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -22,7 +22,7 @@ import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable, UnpackedDependencies } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; -import type { CommandMeta, CommandModule, Module, Processed } from '../types/core-modules'; +import type { CommandModule, Module, Processed } from '../types/core-modules'; import { EventEmitter } from 'node:events'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; @@ -32,13 +32,13 @@ import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; import { arrayifySource, callPlugin, everyPluginOk, filterMapTo, handleError } from '../core/operators'; +import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { const ctx = Context.wrap(wrappable); const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options]; return [ctx, args] as [Context, Args]; } -import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' function intoPayload(module: Processed, ) { return pipe(map(arrayifySource), diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 74474c64..620197c0 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -16,8 +16,8 @@ export default async function(dir: string, deps : UnpackedDependencies) { log?.info({ message: "Client signaled ready, registering modules" }); for await (const path of Files.readRecursive(dir)) { const { module } = await Files.importModule(path); - const validModuleType = module.type >= 0 && module.type <= 1 << 10; - if(!validModuleType) { + const validType = module.type >= 0 && module.type <= 1 << 10; + if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``); } for(const plugin of module.plugins) { diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index ed710861..98905736 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -21,12 +21,6 @@ import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './c import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility'; -export interface CommandMeta { - fullPath: string; - id: string; - isClass: boolean; -} - export type Processed = T & { name: string; description: string }; export interface Module { diff --git a/test/core/module-loading.test.ts b/test/core/module-loading.test.ts index 59521d40..d4adb292 100644 --- a/test/core/module-loading.test.ts +++ b/test/core/module-loading.test.ts @@ -1,13 +1,9 @@ import { describe, it, expect } from 'vitest' -import { faker } from '@faker-js/faker' +import path from 'node:path' import * as Files from '../../src/core/module-loading' +import { Module } from '../../src/types/core-modules' +import { AssertionError } from 'node:assert' describe('module-loading', () => { - it('should properly extract filename from file, nested once', () => { - const extension = faker.system.fileExt() - const name = faker.system.fileName({ extensionCount: 0 }) - const filename = Files.fmtFileName(name+'.'+extension); - expect(filename).toBe(name) - }) it('should get the filename of the commandmodule (linux, esm)', () => { const fname = "///home/pooba/Projects/sern/halibu/dist/commands/ping.js" const callsiteinfo = Files.parseCallsite(fname) @@ -23,5 +19,32 @@ describe('module-loading', () => { const callsiteinfo = Files.parseCallsite(fname) expect(callsiteinfo.name).toEqual("ping"); }) - + + it('should import a commandModule properly', async () => { + const { module } = await Files.importModule(path.resolve("test", 'mockules', "module.ts")); + expect(module.name).toBe('module') + }) + it('should throw when failed commandModule import', async () => { + try { + await Files.importModule(path.resolve('test', 'mockules', 'failed.ts')) + } catch(e) { + expect(e instanceof AssertionError) + } + }) + it('should throw when failed commandModule import', async () => { + try { + await Files.importModule(path.resolve('test', 'mockules', 'failed.ts')) + } catch(e) { + expect(e instanceof AssertionError) + } + }) + + it('reads all modules in mockules', async () => { + const ps = [] as string[] + for await (const fpath of Files.readRecursive(path.resolve('test', 'mockules'))) { + ps.push(fpath) + } + expect(ps.length === 4) + }) + }) diff --git a/test/mockules/!ignd.ts b/test/mockules/!ignd.ts new file mode 100644 index 00000000..e69de29b diff --git a/test/mockules/!ignored/ignored.ts b/test/mockules/!ignored/ignored.ts new file mode 100644 index 00000000..e69de29b diff --git a/test/mockules/failed.ts b/test/mockules/failed.ts new file mode 100644 index 00000000..e69de29b diff --git a/test/mockules/module.ts b/test/mockules/module.ts new file mode 100644 index 00000000..7a422b51 --- /dev/null +++ b/test/mockules/module.ts @@ -0,0 +1,6 @@ +import { CommandType, commandModule } from '../../src/' +export default commandModule({ + type: CommandType.Both, + description: "", + execute: (Ctx, args) => {} +}) diff --git a/test/mockules/ug/pass.ts b/test/mockules/ug/pass.ts new file mode 100644 index 00000000..9cdadf0b --- /dev/null +++ b/test/mockules/ug/pass.ts @@ -0,0 +1,6 @@ +import { CommandType, commandModule } from '../../../src/' +export default commandModule({ + type: CommandType.Both, + description: "", + execute: (Ctx, args) => {} +}) From 0d82658fc5b09d3fe1d9fe2649786830a85c8e71 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 15 May 2024 14:59:24 -0500 Subject: [PATCH 38/90] up to speed with event modules --- src/core/ioc/base.ts | 4 ++ src/core/module-loading.ts | 2 +- src/core/operators.ts | 10 ++--- src/handlers/event-utils.ts | 12 +++--- src/handlers/interaction.ts | 5 ++- src/handlers/message.ts | 5 ++- src/handlers/ready.ts | 9 +++-- src/handlers/user-defined-events.ts | 58 +++++++++++++++++------------ src/sern.ts | 16 ++++---- 9 files changed, 71 insertions(+), 50 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index cea55776..36ab71f0 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -4,6 +4,7 @@ import * as __Services from '../structures/default-services'; import { UnpackedDependencies } from '../../types/utility'; import type { Logging } from '../interfaces'; import { __add_container, __init_container, __swap_container, useContainerRaw } from './global'; +import { EventEmitter } from 'node:events'; export function disposeAll(logger: Logging|undefined) { useContainerRaw() @@ -72,6 +73,7 @@ async function composeRoot( __add_container('@sern/errors', new __Services.DefaultErrorHandling()); __add_container('@sern/cron', {}) __add_container('@sern/modules', new Map()) + __add_container('@sern/emitter', new EventEmitter()) //Build the container based on the callback provided by the user conf.build(container as Container); @@ -97,6 +99,8 @@ export async function makeDependencies (conf: ValidDependencyConfig) { } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); __add_container('@sern/cron', {}) + __add_container('@sern/modules', new Map()) + __add_container('@sern/emitter', new EventEmitter()) await useContainerRaw().ready(); } else { await composeRoot(useContainerRaw(), conf); diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index d4c6074d..35bd9aa4 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -59,7 +59,7 @@ export async function* readRecursive(dir: string): AsyncGenerator { const files = await readdir(dir, { withFileTypes: true }); for (const file of files) { - const fullPath = path.join(dir, file.name); + const fullPath = path.posix.resolve(dir, file.name); if (file.isDirectory()) { if (!file.name.startsWith('!')) { yield* readRecursive(fullPath); diff --git a/src/core/operators.ts b/src/core/operators.ts index 4bb95c7d..a02fb249 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -73,9 +73,9 @@ export function handleError(crashHandler: ErrorHandling, emitter: Emitter, lo //// Temporary until i get rxjs operators working on ts-results-es export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => concatMap(result => { - if(result.isOk()) { - return of(result.value) - } - onErr(result.error); - return EMPTY + if(result.isOk()) { + return of(result.value) + } + onErr(result.error); + return EMPTY; }) diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 5d9cb51f..ba50a581 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -40,7 +40,7 @@ function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[ return [ctx, args] as [Context, Args]; } -function intoPayload(module: Processed, ) { +function intoPayload(module: Module) { return pipe(map(arrayifySource), map(args => ({ module, args }))); } @@ -58,12 +58,13 @@ const createResult = createResultResolver< * @param module * @param source */ -export function eventDispatcher(module: Processed, source: unknown) { +export function eventDispatcher(module: Module, source: unknown) { assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); const execute: OperatorFunction = concatMap(async args => module.execute(...args)); - return fromEvent(source, module.name) + return fromEvent(source, module.name!) + //@ts-ignore .pipe(intoPayload(module), concatMap(createResult), execute); @@ -190,12 +191,10 @@ export function executeModule( return EMPTY; } return throwError(() => resultPayload(PayloadType.Failure, module, result.error)); - }), ); }; - /** * A higher order function that * - creates a stream of {@link VoidResult} { config.createStream } @@ -221,8 +220,7 @@ export function createResultResolver< result.isErr() && config.onStop?.(args.module); }), everyPluginOk, - filterMapTo(() => config.onNext(args)), - ); + filterMapTo(() => config.onNext(args))); }; }; diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index c0552601..9adf3fb5 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -6,15 +6,16 @@ import { createInteractionHandler, executeModule, makeModuleExecutor } from './e import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; +import { Emitter } from '../core/interfaces'; -export function interactionHandler(deps: UnpackedDependencies) { +export default function interactionHandler(deps: UnpackedDependencies) { //i wish javascript had clojure destructuring const { '@sern/modules': modules, '@sern/client': client, '@sern/logger': log, '@sern/errors': err, '@sern/emitter': emitter } = deps - const interactionStream$ = sharedEventStream(client, 'interactionCreate'); + const interactionStream$ = sharedEventStream(client as unknown as Emitter, 'interactionCreate'); const handle = createInteractionHandler(interactionStream$, modules); const interactionHandler$ = merge(handle(isMessageComponent), diff --git a/src/handlers/message.ts b/src/handlers/message.ts index a1a05569..05a0b1c4 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -5,6 +5,7 @@ import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { filterTap, sharedEventStream } from '../core/operators' import { UnpackedDependencies } from '../types/utility'; +import { Emitter } from '..'; /** * Ignores messages from any person / bot except itself @@ -19,7 +20,7 @@ function hasPrefix(prefix: string, content: string) { return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); } -export function messageHandler({"@sern/emitter": emitter, '@sern/errors':err, +export default function message({"@sern/emitter": emitter, '@sern/errors':err, '@sern/logger': log, '@sern/client': client, '@sern/modules': commands}: UnpackedDependencies, defaultPrefix: string | undefined) { @@ -27,7 +28,7 @@ export function messageHandler({"@sern/emitter": emitter, '@sern/errors':err, log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; } - const messageStream$ = sharedEventStream(client, 'messageCreate'); + const messageStream$ = sharedEventStream(client as unknown as Emitter, 'messageCreate'); const handle = createMessageHandler(messageStream$, defaultPrefix, commands); const msgCommands$ = handle(isNonBot(defaultPrefix)); diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 620197c0..4d1d8597 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -2,7 +2,7 @@ import * as Files from '../core/module-loading' import { once } from 'events'; import { resultPayload } from '../core/functions'; import { PayloadType } from '..'; -import { SernError } from '../core/structures/enums'; +import { CommandType, SernError } from '../core/structures/enums'; import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; @@ -14,15 +14,18 @@ export default async function(dir: string, deps : UnpackedDependencies) { log?.info({ message: "Waiting on discord client to be ready..." }) await once(client, "ready"); log?.info({ message: "Client signaled ready, registering modules" }); + + // https://observablehq.com/@ehouais/multiple-promises-as-an-async-generator + // possibly optimize to concurrently import modules for await (const path of Files.readRecursive(dir)) { const { module } = await Files.importModule(path); - const validType = module.type >= 0 && module.type <= 1 << 10; + const validType = module.type >= CommandType.Text && module.type <= CommandType.ChannelSelect; if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``); } for(const plugin of module.plugins) { const res = await plugin.execute({ module, absPath: module.meta.absPath }); - if(res.isErr()) { + if(res.isErr()) { sEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); throw Error("Plugin failed with controller.stop()"); } diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 40d1977a..627c2ab9 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,35 +1,47 @@ -import { EventType, SernError } from '../core/structures/enums'; -import { eventDispatcher } from './event-utils' -import type { EventModule, Processed } from '../types/core-modules'; +import { EventType, PayloadType, SernError } from '../core/structures/enums'; +import { eventDispatcher, handleCrash } from './event-utils' +import { EventModule, Module, Processed } from '../types/core-modules'; import * as Files from '../core/module-loading' import type { UnpackedDependencies } from '../types/utility'; +import { resultPayload } from '../core/functions'; +import { from, map, mergeAll } from 'rxjs'; -export default function(deps: UnpackedDependencies, eventDir: string) { - //code smell - const intoDispatcher = (e: { module: Processed }) => { - switch (e.module.type) { +const intoDispatcher = (deps: UnpackedDependencies) => + (module : EventModule) => { + switch (module.type) { case EventType.Sern: - return eventDispatcher(e.module, deps['@sern/emitter']); + return eventDispatcher(module, deps['@sern/emitter']); case EventType.Discord: - return eventDispatcher(e.module, deps['@sern/client']); + return eventDispatcher(module, deps['@sern/client']); case EventType.External: - return eventDispatcher(e.module, deps[e.module.emitter]); + return eventDispatcher(module, deps[module.emitter]); case EventType.Cron: //@ts-ignore TODO - return eventDispatcher(e.module, deps['@sern/cron']) + return eventDispatcher(module, deps['@sern/cron']) default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } - }; - Files.readRecursive(eventDir) - //buildModules(allPaths) -// pipe( -// callInitPlugins(emitter), -// map(intoDispatcher), -// /** -// * Where all events are turned on -// */ -// mergeAll(), -// handleCrash(err, emitter, log)) -// .subscribe(); +}; + +export default async function(deps: UnpackedDependencies, eventDir: string) { + const eventModules: EventModule[] = []; + for await (const path of Files.readRecursive(eventDir)) { + const { module } = await Files.importModule(path); + for(const plugin of module.plugins) { + const res = await plugin.execute({ module, absPath: module.meta.absPath }); + if(res.isErr()) { + deps['@sern/emitter'].emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + throw Error("Plugin failed with controller.stop()"); + } + } + eventModules.push(module as EventModule); + } + from(eventModules) + .pipe(map(intoDispatcher(deps)), + /** + * Where all events are turned on + */ + mergeAll(), + handleCrash(deps)) + .subscribe(); } diff --git a/src/sern.ts b/src/sern.ts index 49aeb6fb..b48da0b6 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,13 +1,11 @@ import callsites from 'callsites'; import * as Files from './core/module-loading'; import { merge } from 'rxjs'; -import { Services } from './core/ioc'; import eventsHandler from './handlers/user-defined-events'; import ready from './handlers/ready'; -import { messageHandler } from './handlers/message'; -import { interactionHandler } from './handlers/interaction'; +import messageHandler from './handlers/message'; +import interactionHandler from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; -import { Client } from 'discord.js'; import { handleCrash } from './handlers/event-utils'; import { useContainerRaw } from './core/ioc/global'; import { UnpackedDependencies } from './types/utility'; @@ -35,7 +33,12 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { const deps = useContainerRaw().deps(); if (maybeWrapper.events !== undefined) { - eventsHandler(deps, maybeWrapper.events); + eventsHandler(deps, maybeWrapper.events) + .then(() => { + deps['@sern/logger']?.info({ message: "Events registered" }); + }); + } else { + deps['@sern/logger']?.info({ message: "No events registered" }); } const initCallsite = callsites()[1].getFileName(); @@ -47,8 +50,7 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { deps['@sern/logger']?.info({ message: `sern: registered in ${time} s` }); if(presencePath.exists) { const setPresence = async (p: any) => { - //@ts-ignore - return (dependencies[3] as Client).user?.setPresence(p); + return deps['@sern/client'].user?.setPresence(p); } presenceHandler(presencePath.path, setPresence).subscribe(); } From d905f08993beb96a439d498d1d8f181b381086ce Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 15 May 2024 16:42:21 -0500 Subject: [PATCH 39/90] i think cron works --- src/core/_internal.ts | 2 -- src/core/interfaces.ts | 1 - src/core/ioc/container.ts | 2 -- src/core/operators.ts | 2 +- src/core/structures/default-services.ts | 41 +++++++++++++++++++++++++ src/handlers/event-utils.ts | 5 +-- src/handlers/user-defined-events.ts | 2 +- src/types/core-modules.ts | 1 + src/types/core-plugin.ts | 3 +- src/types/utility.ts | 4 ++- 10 files changed, 49 insertions(+), 14 deletions(-) delete mode 100644 src/core/_internal.ts diff --git a/src/core/_internal.ts b/src/core/_internal.ts deleted file mode 100644 index da0a304f..00000000 --- a/src/core/_internal.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { Result } from 'ts-results-es' -export type VoidResult = Result; diff --git a/src/core/interfaces.ts b/src/core/interfaces.ts index 6e02d301..cf682da4 100644 --- a/src/core/interfaces.ts +++ b/src/core/interfaces.ts @@ -22,7 +22,6 @@ export interface Emitter { addListener(eventName: string | symbol, listener: AnyFunction): this; removeListener(eventName: string | symbol, listener: AnyFunction): this; emit(eventName: string | symbol, ...payload: any[]): boolean; - on(eventName: string | symbol, listener: AnyFunction): this } diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 92aa4f53..8a41e705 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -1,5 +1,3 @@ -import type { UnpackedDependencies } from '../../types/utility'; - /** * A semi-generic container that provides error handling, emitter, and module store. * For the handler to operate correctly, The only user provided dependency needs to be @sern/client diff --git a/src/core/operators.ts b/src/core/operators.ts index a02fb249..6fdbaf93 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -18,8 +18,8 @@ import { import type { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; import type { PluginResult } from '../types/core-plugin'; -import type { VoidResult } from './_internal'; import { Result } from 'ts-results-es'; +import { VoidResult } from '../types/utility'; /** * if {src} is true, mapTo V, else ignore * @param item diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 2bcd41d2..75001ee2 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,4 +1,9 @@ import type { LogPayload, Logging, ErrorHandling } from '../interfaces'; +import { AnyFunction } from '../../types/utility'; +import cron from 'node-cron' +import { EventEmitter } from 'events'; +import type { CronEventCommand, Module } from '../../types/core-modules' +import { EventType } from './enums'; /** * @internal * @since 2.0.0 @@ -41,3 +46,39 @@ export class DefaultLogging implements Logging { console.warn(`WARN: ${this.date().toISOString()} -> ${payload.message}`); } } + +export class Cron extends EventEmitter { + tasks: string[] = []; + modules: Map = new Map(); + private sanityCheck(eventName: string | symbol) : asserts eventName is string { + if(typeof eventName === 'symbol') throw Error("Cron cannot add symbol based listener") + if(!cron.validate(eventName)) { + throw Error("Invalid cron expression while adding") + } + } + addCronModule(module: Module) { + if(module.type !== EventType.Cron) { + throw Error("Can only add cron modules"); + } + this.modules.set(module.name!, module as CronEventCommand); + } + addListener(eventName: string | symbol, listener: AnyFunction): this { + this.sanityCheck(eventName); + const retrievedModule = this.modules.get(eventName); + if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); + cron.schedule(retrievedModule.pattern, listener, { + name: retrievedModule?.name! + }); + return this; + } + removeListener(eventName: string | symbol, listener: AnyFunction) { + this.sanityCheck(eventName); + const retrievedModule = this.modules.get(eventName); + if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); + const task= cron.getTasks().get(retrievedModule.name!) + if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found"); + task.stop(); + super.removeListener(eventName, listener); + return this; + } +} diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index ba50a581..dc52eb90 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -13,14 +13,11 @@ import { finalize, pipe } from 'rxjs'; -import { - type VoidResult, -} from '../core/_internal'; import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; -import type { Awaitable, UnpackedDependencies } from '../types/utility'; +import type { Awaitable, UnpackedDependencies, VoidResult } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { CommandModule, Module, Processed } from '../types/core-modules'; import { EventEmitter } from 'node:events'; diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 627c2ab9..572b0d17 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,6 +1,6 @@ import { EventType, PayloadType, SernError } from '../core/structures/enums'; import { eventDispatcher, handleCrash } from './event-utils' -import { EventModule, Module, Processed } from '../types/core-modules'; +import { EventModule, Module } from '../types/core-modules'; import * as Files from '../core/module-loading' import type { UnpackedDependencies } from '../types/utility'; import { resultPayload } from '../core/functions'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 98905736..bbb82e1e 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -51,6 +51,7 @@ export interface ExternalEventCommand extends Module { } export interface CronEventCommand extends Module { name?: string; + pattern: string; type: EventType.Cron; execute(...args: unknown[]): Awaitable; } diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 331c9be2..abf36515 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -33,7 +33,7 @@ import type { TextCommand, UserSelectCommand, } from './core-modules'; -import type { Args, Awaitable, Payload, SlashOptions } from './utility'; +import type { Args, Awaitable, Payload, SlashOptions, VoidResult } from './utility'; import type { CommandType, EventType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { @@ -48,7 +48,6 @@ import type { UserContextMenuCommandInteraction, UserSelectMenuInteraction, } from 'discord.js'; -import { VoidResult } from '../core/_internal'; export type PluginResult = Awaitable; diff --git a/src/types/utility.ts b/src/types/utility.ts index d215ea16..ac959db7 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -1,10 +1,12 @@ import type { CommandInteractionOptionResolver, InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; import type { PayloadType } from '../core/structures/enums'; import type { Module } from './core-modules'; +import type { Result } from 'ts-results-es'; export type Awaitable = PromiseLike | T; -export type AnyFunction = (...args: never[]) => unknown; +export type VoidResult = Result; +export type AnyFunction = (...args: any[]) => unknown; // Thanks to @kelsny type ParseType = { From 203e8c8ecfbcd358fc94710a486793d4378e6ddf Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 15 May 2024 16:52:33 -0500 Subject: [PATCH 40/90] cron works now, poc --- src/core/ioc/base.ts | 4 ++-- src/core/structures/default-services.ts | 9 ++++++--- src/handlers/event-utils.ts | 2 +- src/handlers/user-defined-events.ts | 9 ++++++--- src/types/core-modules.ts | 5 ++--- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 36ab71f0..459f61fe 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -71,7 +71,7 @@ async function composeRoot( __add_container('@sern/logger', new __Services.DefaultLogging()); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/cron', {}) + __add_container('@sern/cron', new __Services.Cron()) __add_container('@sern/modules', new Map()) __add_container('@sern/emitter', new EventEmitter()) //Build the container based on the callback provided by the user @@ -98,7 +98,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { __add_container('@sern/logger', new __Services.DefaultLogging); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/cron', {}) + __add_container('@sern/cron', new __Services.Cron()) __add_container('@sern/modules', new Map()) __add_container('@sern/emitter', new EventEmitter()) await useContainerRaw().ready(); diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 75001ee2..be2d3df1 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -52,14 +52,17 @@ export class Cron extends EventEmitter { modules: Map = new Map(); private sanityCheck(eventName: string | symbol) : asserts eventName is string { if(typeof eventName === 'symbol') throw Error("Cron cannot add symbol based listener") - if(!cron.validate(eventName)) { - throw Error("Invalid cron expression while adding") - } + } addCronModule(module: Module) { if(module.type !== EventType.Cron) { throw Error("Can only add cron modules"); } + + //@ts-ignore + if(!cron.validate(module.pattern)) { + throw Error("Invalid cron expression while adding") + } this.modules.set(module.name!, module as CronEventCommand); } addListener(eventName: string | symbol, listener: AnyFunction): this { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index dc52eb90..103a62a3 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -55,7 +55,7 @@ const createResult = createResultResolver< * @param module * @param source */ -export function eventDispatcher(module: Module, source: unknown) { +export function eventDispatcher(module: Module, source: unknown) { assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); const execute: OperatorFunction = diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 572b0d17..35b382cc 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -15,9 +15,12 @@ const intoDispatcher = (deps: UnpackedDependencies) => return eventDispatcher(module, deps['@sern/client']); case EventType.External: return eventDispatcher(module, deps[module.emitter]); - case EventType.Cron: - //@ts-ignore TODO - return eventDispatcher(module, deps['@sern/cron']) + case EventType.Cron: { + //@ts-ignore + const cron = deps['@sern/cron']; + cron.addCronModule(module); + return eventDispatcher(module, cron) + } default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index bbb82e1e..58684ac1 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -50,9 +50,9 @@ export interface ExternalEventCommand extends Module { execute(...args: unknown[]): Awaitable; } export interface CronEventCommand extends Module { + type: EventType.Cron; name?: string; pattern: string; - type: EventType.Cron; execute(...args: unknown[]): Awaitable; } @@ -168,8 +168,7 @@ export interface EventModuleDefs { [EventType.Sern]: SernEventCommand; [EventType.Discord]: DiscordEventCommand; [EventType.External]: ExternalEventCommand; - //TODO - [EventType.Cron]: ExternalEventCommand; + [EventType.Cron]: CronEventCommand; } export interface SernAutocompleteData From 44c072f4018423ea25c6834a94ceb87a23ebcb95 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 16 May 2024 00:21:29 -0500 Subject: [PATCH 41/90] ksdjkldsfld --- src/core/ioc/base.ts | 12 ++-- src/core/operators.ts | 14 ++-- src/core/structures/default-services.ts | 2 +- src/handlers/event-utils.ts | 85 +++++++++++++------------ src/handlers/message.ts | 3 +- src/handlers/presence.ts | 5 +- src/handlers/ready.ts | 4 +- src/handlers/user-defined-events.ts | 2 +- src/types/ioc.ts | 10 +-- test/handlers/dispatchers.test.ts | 1 + 10 files changed, 70 insertions(+), 68 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 459f61fe..3b1c1ab5 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,7 +1,6 @@ import type { DependencyConfiguration } from '../../types/ioc'; import { Container } from './container'; import * as __Services from '../structures/default-services'; -import { UnpackedDependencies } from '../../types/utility'; import type { Logging } from '../interfaces'; import { __add_container, __init_container, __swap_container, useContainerRaw } from './global'; import { EventEmitter } from 'node:events'; @@ -14,7 +13,7 @@ export function disposeAll(logger: Logging|undefined) { type Insertable = - | ((container: UnpackedDependencies) => object) + | ((container: Dependencies) => object) | object const dependencyBuilder = (container: Container, excluded: string[] ) => { return { @@ -26,7 +25,8 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { if(typeof v !== 'function') { container.addSingleton(key, v) } else { - container.addWiredSingleton(key, (cntr) => v(cntr as UnpackedDependencies)) + //@ts-ignore + container.addWiredSingleton(key, (cntr) => v(cntr)) } }, /** @@ -53,7 +53,6 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { type ValidDependencyConfig = | ((c: ReturnType) => any) | DependencyConfiguration; - /** * Given the user's conf, check for any excluded/included dependency keys. @@ -79,13 +78,14 @@ async function composeRoot( if (!hasLogger) { container.get('@sern/logger') - ?.info({ message: 'All dependencies loaded successfully.' }); + ?.info({ message: 'All dependencies loaded successfully.' }); } - container.ready(); + await container.ready(); } export async function makeDependencies (conf: ValidDependencyConfig) { await __init_container({ autowire: false }); + if(typeof conf === 'function') { const excluded: string[] = []; conf(dependencyBuilder(useContainerRaw(), excluded)); diff --git a/src/core/operators.ts b/src/core/operators.ts index 6fdbaf93..31780a99 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -35,14 +35,12 @@ interface PluginExecutable { * Calls any plugin with {args}. * @param args if an array, its spread and plugin called. */ -export function callPlugin(args: unknown): OperatorFunction +export function callPlugin(plugin: PluginExecutable, args: unknown) { - return concatMap(async plugin => { - if (Array.isArray(args)) { - return plugin.execute(...args); - } - return plugin.execute(args); - }); + if (Array.isArray(args)) { + return plugin.execute(...args); + } + return plugin.execute(args); } export const arrayifySource = (src: T) => @@ -52,7 +50,7 @@ export const arrayifySource = (src: T) => * Checks if the stream of results is all ok. */ export const everyPluginOk: OperatorFunction = - pipe(every(result => result.isOk()), + pipe(every(result => result.isOk()), //this shortcircuits defaultIfEmpty(true)); export const sharedEventStream = (e: Emitter, eventName: string) => diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index be2d3df1..933579e7 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -61,7 +61,7 @@ export class Cron extends EventEmitter { //@ts-ignore if(!cron.validate(module.pattern)) { - throw Error("Invalid cron expression while adding") + throw Error("Invalid cron expression while adding " + module.name) } this.modules.set(module.name!, module as CronEventCommand); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 103a62a3..2ea4b193 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -20,7 +20,6 @@ import { Err, Ok, Result } from 'ts-results-es'; import type { Awaitable, UnpackedDependencies, VoidResult } from '../types/utility'; import type { ControlPlugin } from '../types/core-plugin'; import type { CommandModule, Module, Processed } from '../types/core-modules'; -import { EventEmitter } from 'node:events'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; import { CommandType } from '../core/structures/enums' @@ -28,7 +27,6 @@ import type { Args } from '../types/utility'; import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; import { arrayifySource, callPlugin, everyPluginOk, filterMapTo, handleError } from '../core/operators'; - import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { @@ -41,13 +39,17 @@ function intoPayload(module: Module) { return pipe(map(arrayifySource), map(args => ({ module, args }))); } - const createResult = createResultResolver< Processed, { module: Processed; args: unknown[] }, unknown[] >({ - createStream: ({ module, args }) => from(module.onEvent).pipe(callPlugin(args)), + createStream: async function* ({ module, args }) { + for(const plugin of module.onEvent) { + + } + //from(module.onEvent).pipe(callPlugin(args)) + }, onNext: ({ args }) => args, }); /** @@ -56,10 +58,10 @@ const createResult = createResultResolver< * @param source */ export function eventDispatcher(module: Module, source: unknown) { - assert.ok(source instanceof EventEmitter, `${source} is not an EventEmitter`); - + assert.ok(source && typeof source === 'object', `${source} cannot be constructed into an event listener`); const execute: OperatorFunction = concatMap(async args => module.execute(...args)); + //@ts-ignore return fromEvent(source, module.name!) //@ts-ignore .pipe(intoPayload(module), @@ -67,25 +69,24 @@ export function eventDispatcher(module: Module, source: unknown) { execute); } -export function createDispatcher(payload: { module: Processed; event: BaseInteraction; }) { - assert.ok(CommandType.Text !== payload.module.type, +export function createDispatcher({ module, event }: { module: Processed; event: BaseInteraction; }) { + assert.ok(CommandType.Text !== module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); - switch (payload.module.type) { + if(isAutocomplete(event)) { + assert.ok(module.type === CommandType.Slash + || module.type === CommandType.Both); + const option = treeSearch(event, module.options); + assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(module)); + const { command } = option; + return { module: command as Processed, //autocomplete is not a true "module" warning cast! + args: [event] }; + } + switch (module.type) { case CommandType.Slash: case CommandType.Both: { - if (isAutocomplete(payload.event)) { - const option = treeSearch(payload.event, payload.module.options); - assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(payload.module)); - const { command } = option; - - return { - module: command as Processed, //autocomplete is not a true "module" warning cast! - args: [payload.event], - }; - } - return { module: payload.module, args: contextArgs(payload.event) }; + return { module, args: contextArgs(event) }; } - default: return { module: payload.module, args: [payload.event] }; + default: return { module, args: [event] }; } } function createGenericHandler( @@ -94,8 +95,8 @@ function createGenericHandler( ) { return (pred: (i: Source) => i is Narrowed) => source.pipe( - filter(pred), - concatMap(makeModule)); + filter(pred), // only handle this stream if it passes pred + concatMap(makeModule)); // create a payload, preparing to execute } /** @@ -121,7 +122,7 @@ export function fmt(msg: string, prefix: string): string[] { */ export function createInteractionHandler( source: Observable, - mg: Map, //TODO + mg: Map, ) { return createGenericHandler, void>>( source, @@ -135,7 +136,6 @@ export function createInteractionHandler( return Err.EMPTY; } const [ path ] = fullPaths; - //@ts-ignore TODO fixme return Ok(createDispatcher({ module: path as Processed, event })); }); } @@ -147,12 +147,9 @@ export function createMessageHandler( ) { return createGenericHandler(source, async event => { const [prefix, ...rest] = fmt(event.content, defaultPrefix); - let fullPath = mg.get(`${prefix}_T`); + let fullPath = mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`); if(!fullPath) { - fullPath = mg.get(`${prefix}_B`); - if(!fullPath) { - return Err('Possibly undefined behavior: could not find a static id to resolve'); - } + return Err('Possibly undefined behavior: could not find a static id to resolve'); } return Ok({ args: contextArgs(event, rest), module: fullPath as Processed }) }); @@ -173,12 +170,13 @@ interface ExecutePayload { * @param module the module that will be executed with task * @param task the deferred execution which will be called */ -export function executeModule( +export async function executeModule( emitter: Emitter, logger: Logging|undefined, errHandler: ErrorHandling, { module, task, args }: ExecutePayload, ) { + const wrappedTask = await Result.wrapAsync(async () => task()); return of(module).pipe( //converting the task into a promise so rxjs can resolve the Awaitable properly concatMap(() => Result.wrapAsync(async () => task())), @@ -208,11 +206,11 @@ export function createResultResolver< >(config: { onStop?: (module: T) => unknown; onNext: (args: Args) => Output; - createStream: (args: Args) => Observable; + createStream: (args: Args) => AsyncGenerator; }) { return (args: Args) => { - const task$ = config.createStream(args); - return task$.pipe( + const task = config.createStream(args); + return from(task).pipe( tap(result => { result.isErr() && config.onStop?.(args.module); }), @@ -225,9 +223,7 @@ export function createResultResolver< * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter */ -export function makeModuleExecutor< - M extends Processed, - Args extends { module: M; args: unknown[]; }> +export function makeModuleExecutor< M extends Processed, Args extends { module: M; args: unknown[]; }> (onStop: (m: M) => unknown) { const onNext = ({ args, module }: Args) => ({ task: () => module.execute(...args), @@ -235,10 +231,17 @@ export function makeModuleExecutor< args }); return createResultResolver({ - onStop, - createStream: ({ args, module }) => from(module.onEvent).pipe(callPlugin(args)), - onNext, - }) + onStop, + createStream: async function* ({ args, module }) { + for(const plugin of module.onEvent) { + const result = await callPlugin(plugin, args); + if(result.isErr()) { + return result.error + } + } + }, + onNext, + }) } export const handleCrash = ({ "@sern/errors": err, diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 05a0b1c4..26023474 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -20,7 +20,8 @@ function hasPrefix(prefix: string, content: string) { return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); } -export default function message({"@sern/emitter": emitter, '@sern/errors':err, +export default function message( + {"@sern/emitter": emitter, '@sern/errors':err, '@sern/logger': log, '@sern/client': client, '@sern/modules': commands}: UnpackedDependencies, defaultPrefix: string | undefined) { diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index f492a696..f2528b6f 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -14,9 +14,8 @@ const parseConfig = async (conf: Promise) => { const src$ = typeof repeat === 'number' ? interval(repeat) : fromEvent(...repeat); - return src$ - .pipe(scan(onRepeat, s), - startWith(s)); + return src$.pipe(scan(onRepeat, s), + startWith(s)); } return of(s).pipe(take(1)); }) diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 4d1d8597..b641ab92 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -7,10 +7,10 @@ import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; export default async function(dir: string, deps : UnpackedDependencies) { - const { "@sern/client": client, + const { '@sern/client': client, '@sern/logger': log, '@sern/emitter': sEmitter, - '@sern/modules': commands} = deps; + '@sern/modules': commands } = deps; log?.info({ message: "Waiting on discord client to be ready..." }) await once(client, "ready"); log?.info({ message: "Client signaled ready, registering modules" }); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 35b382cc..20982ae8 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -19,7 +19,7 @@ const intoDispatcher = (deps: UnpackedDependencies) => //@ts-ignore const cron = deps['@sern/cron']; cron.addCronModule(module); - return eventDispatcher(module, cron) + return eventDispatcher(module, cron); } default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); diff --git a/src/types/ioc.ts b/src/types/ioc.ts index cac4d3f2..d3aa6711 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -6,11 +6,11 @@ import { Module } from './core-modules'; export interface CoreDependencies { - '@sern/client': () => Client; - '@sern/emitter': () => Contracts.Emitter; - '@sern/errors': () => Contracts.ErrorHandling; - '@sern/logger'?: () => Contracts.Logging; - '@sern/modules': () => Map + '@sern/client': Client; + '@sern/emitter': Contracts.Emitter; + '@sern/errors': Contracts.ErrorHandling; + '@sern/logger'?: Contracts.Logging; + '@sern/modules': Map; } export type DependencyFromKey = Dependencies[T]; diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index a5ce406f..dd62d52e 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -12,6 +12,7 @@ function createRandomModule(): Processed { min: CommandType.Text, max: CommandType.ChannelSelect, }), + meta: { id:"", absPath: faker.system.directoryPath() }, description: faker.string.alpha(), name: faker.string.alpha(), onEvent: [], From d3227e5ec11e305665474cf05238388a1296f540 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 16 May 2024 17:03:04 -0500 Subject: [PATCH 42/90] updating ioc api, experimenting with cron --- src/core/functions.ts | 4 +-- src/core/ioc/base.ts | 17 ++++++------ src/core/ioc/global.ts | 10 +++++++ src/core/structures/default-services.ts | 36 ++++++++++++++----------- src/types/core-modules.ts | 2 ++ 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index dfbb2d83..46e204c6 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -14,8 +14,8 @@ import { PayloadType, PluginType } from './structures/enums'; import assert from 'assert'; import type { Payload } from '../types/utility'; -export const ok = () => Ok.EMPTY; -export const err = () => Err.EMPTY; +export const ok = (val: unknown) => Ok(val); +export const err = (val: string) => Err(val); export function partitionPlugins (arr: Array<{ type: PluginType }> = []): [T[], V[]] { diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 3b1c1ab5..3ac05c3e 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -2,7 +2,7 @@ import type { DependencyConfiguration } from '../../types/ioc'; import { Container } from './container'; import * as __Services from '../structures/default-services'; import type { Logging } from '../interfaces'; -import { __add_container, __init_container, __swap_container, useContainerRaw } from './global'; +import { __add_container, __add_wiredcontainer, __init_container, __swap_container, useContainerRaw } from './global'; import { EventEmitter } from 'node:events'; export function disposeAll(logger: Logging|undefined) { @@ -70,9 +70,9 @@ async function composeRoot( __add_container('@sern/logger', new __Services.DefaultLogging()); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/cron', new __Services.Cron()) __add_container('@sern/modules', new Map()) __add_container('@sern/emitter', new EventEmitter()) + __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) //Build the container based on the callback provided by the user conf.build(container as Container); @@ -84,26 +84,25 @@ async function composeRoot( } export async function makeDependencies (conf: ValidDependencyConfig) { - await __init_container({ autowire: false }); - + const container = await __init_container({ autowire: false }); if(typeof conf === 'function') { const excluded: string[] = []; - conf(dependencyBuilder(useContainerRaw(), excluded)); + conf(dependencyBuilder(container, excluded)); //We only include logger if it does not exist const includeLogger = !excluded.includes('@sern/logger') - && !useContainerRaw().hasKey('@sern/logger'); + && !container.hasKey('@sern/logger'); if(includeLogger) { __add_container('@sern/logger', new __Services.DefaultLogging); } __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/cron', new __Services.Cron()) __add_container('@sern/modules', new Map()) __add_container('@sern/emitter', new EventEmitter()) - await useContainerRaw().ready(); + __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) + await container.ready(); } else { - await composeRoot(useContainerRaw(), conf); + await composeRoot(container, conf); } } diff --git a/src/core/ioc/global.ts b/src/core/ioc/global.ts index 42ff98c9..766b8c5e 100644 --- a/src/core/ioc/global.ts +++ b/src/core/ioc/global.ts @@ -1,3 +1,4 @@ +import { UnpackedDependencies } from '../../types/utility'; import { Container } from './container'; //SIDE EFFECT: GLOBAL DI @@ -22,6 +23,14 @@ export function __add_container(key: string, v: object) { containerSubject.addSingleton(key, v); } +/** + * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything + * then it will swap + */ +export function __add_wiredcontainer(key: string, depfn : (deps: UnpackedDependencies) => object) { + //@ts-ignore + containerSubject.addWiredSingleton(key, depfn); +} /** * Initiates the global api. * Once this is finished, the Service api and the other global api is available @@ -32,6 +41,7 @@ export async function __init_container(options: { }) { containerSubject = new Container(options); await containerSubject.ready() + return containerSubject } /** diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 933579e7..95e2b47c 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,5 +1,5 @@ -import type { LogPayload, Logging, ErrorHandling } from '../interfaces'; -import { AnyFunction } from '../../types/utility'; +import type { LogPayload, Logging, ErrorHandling, Emitter } from '../interfaces'; +import { AnyFunction, UnpackedDependencies } from '../../types/utility'; import cron from 'node-cron' import { EventEmitter } from 'events'; import type { CronEventCommand, Module } from '../../types/core-modules' @@ -13,12 +13,8 @@ export class DefaultErrorHandling implements ErrorHandling { crash(err: Error): never { throw err; } - keepAlive = 1; updateAlive(err: Error) { - this.keepAlive--; - if (this.keepAlive === 0) { - throw err; - } + throw err; } } @@ -47,41 +43,51 @@ export class DefaultLogging implements Logging { } } -export class Cron extends EventEmitter { +export class Cron implements Emitter { tasks: string[] = []; modules: Map = new Map(); + constructor(private deps: UnpackedDependencies) {} private sanityCheck(eventName: string | symbol) : asserts eventName is string { if(typeof eventName === 'symbol') throw Error("Cron cannot add symbol based listener") - } addCronModule(module: Module) { if(module.type !== EventType.Cron) { throw Error("Can only add cron modules"); } - //@ts-ignore if(!cron.validate(module.pattern)) { throw Error("Invalid cron expression while adding " + module.name) } + (module as CronEventCommand) this.modules.set(module.name!, module as CronEventCommand); } addListener(eventName: string | symbol, listener: AnyFunction): this { this.sanityCheck(eventName); const retrievedModule = this.modules.get(eventName); if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); - cron.schedule(retrievedModule.pattern, listener, { - name: retrievedModule?.name! - }); + + cron.schedule(retrievedModule.pattern, + (date) => listener({ date, deps: this.deps }), + { name: retrievedModule?.name!, + runOnInit: retrievedModule.runOnInit, + timezone: retrievedModule.timezone, + }); return this; } removeListener(eventName: string | symbol, listener: AnyFunction) { this.sanityCheck(eventName); const retrievedModule = this.modules.get(eventName); if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); - const task= cron.getTasks().get(retrievedModule.name!) + const task = cron.getTasks().get(retrievedModule.name!) if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found"); task.stop(); - super.removeListener(eventName, listener); return this; } + emit(eventName: string | symbol, ...payload: any[]): boolean { + this.sanityCheck(eventName); + const retrievedModule = this.modules.get(eventName); + if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); + const task= cron.getTasks().get(retrievedModule.name!) + return task?.emit(eventName, payload) ?? false; + } } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 58684ac1..c0f35565 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -53,6 +53,8 @@ export interface CronEventCommand extends Module { type: EventType.Cron; name?: string; pattern: string; + runOnInit?: boolean + timezone?: string; execute(...args: unknown[]): Awaitable; } From ca9b84ba21d590e62fe594b13be4a621b54176d0 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 16 May 2024 23:41:44 -0500 Subject: [PATCH 43/90] save b4 thunder and lightning --- src/core/module-loading.ts | 2 +- src/core/operators.ts | 19 +------- src/core/structures/default-services.ts | 12 ++--- src/handlers/event-utils.ts | 64 ++++++++++++------------- src/handlers/interaction.ts | 8 +++- src/handlers/message.ts | 8 +++- test/handlers/dispatchers.test.ts | 5 +- 7 files changed, 52 insertions(+), 66 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 35bd9aa4..4fd2d831 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -59,7 +59,7 @@ export async function* readRecursive(dir: string): AsyncGenerator { const files = await readdir(dir, { withFileTypes: true }); for (const file of files) { - const fullPath = path.posix.resolve(dir, file.name); + const fullPath = path.posix.join(dir, file.name); if (file.isDirectory()) { if (!file.name.startsWith('!')) { yield* readRecursive(fullPath); diff --git a/src/core/operators.ts b/src/core/operators.ts index 31780a99..2e08b2c9 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -31,28 +31,11 @@ export function filterMapTo(item: () => V): OperatorFunction { interface PluginExecutable { execute: (...args: unknown[]) => PluginResult; }; -/** - * Calls any plugin with {args}. - * @param args if an array, its spread and plugin called. - */ -export function callPlugin(plugin: PluginExecutable, args: unknown) -{ - if (Array.isArray(args)) { - return plugin.execute(...args); - } - return plugin.execute(args); -} + export const arrayifySource = (src: T) => Array.isArray(src) ? src : [src]; -/** - * Checks if the stream of results is all ok. - */ -export const everyPluginOk: OperatorFunction = - pipe(every(result => result.isOk()), //this shortcircuits - defaultIfEmpty(true)); - export const sharedEventStream = (e: Emitter, eventName: string) => (fromEvent(e, eventName) as Observable).pipe(share()); diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 95e2b47c..e30a6f5b 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -65,13 +65,11 @@ export class Cron implements Emitter { this.sanityCheck(eventName); const retrievedModule = this.modules.get(eventName); if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); - - cron.schedule(retrievedModule.pattern, - (date) => listener({ date, deps: this.deps }), - { name: retrievedModule?.name!, - runOnInit: retrievedModule.runOnInit, - timezone: retrievedModule.timezone, - }); + const { pattern, name, runOnInit, timezone } = retrievedModule; + const task = cron.schedule(pattern, + (date) => listener({ date, deps: this.deps }), + { name, runOnInit, timezone, scheduled: true }); + task.on('task-failed', console.error) return this; } removeListener(eventName: string | symbol, listener: AnyFunction) { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 2ea4b193..1c79e17a 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -4,10 +4,8 @@ import { Observable, concatMap, filter, - from, of, throwError, - tap, fromEvent, map, OperatorFunction, catchError, finalize, @@ -26,7 +24,7 @@ import { CommandType } from '../core/structures/enums' import type { Args } from '../types/utility'; import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; -import { arrayifySource, callPlugin, everyPluginOk, filterMapTo, handleError } from '../core/operators'; +import { arrayifySource, handleError } from '../core/operators'; import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { @@ -44,12 +42,8 @@ const createResult = createResultResolver< { module: Processed; args: unknown[] }, unknown[] >({ - createStream: async function* ({ module, args }) { - for(const plugin of module.onEvent) { - - } - //from(module.onEvent).pipe(callPlugin(args)) - }, + //@ts-ignore fix later + callPlugins, onNext: ({ args }) => args, }); /** @@ -63,6 +57,7 @@ export function eventDispatcher(module: Module, source: unknown) { concatMap(async args => module.execute(...args)); //@ts-ignore return fromEvent(source, module.name!) + //@ts-ignore .pipe(intoPayload(module), concatMap(createResult), @@ -166,17 +161,17 @@ interface ExecutePayload { * Wraps the task in a Result as a try / catch. * if the task is ok, an event is emitted and the stream becomes empty * if the task is an error, throw an error down the stream which will be handled by catchError + * thank u kingomes * @param emitter reference to SernEmitter that will emit a successful execution of module * @param module the module that will be executed with task * @param task the deferred execution which will be called */ -export async function executeModule( +export function executeModule( emitter: Emitter, logger: Logging|undefined, errHandler: ErrorHandling, { module, task, args }: ExecutePayload, ) { - const wrappedTask = await Result.wrapAsync(async () => task()); return of(module).pipe( //converting the task into a promise so rxjs can resolve the Awaitable properly concatMap(() => Result.wrapAsync(async () => task())), @@ -186,8 +181,7 @@ export async function executeModule( return EMPTY; } return throwError(() => resultPayload(PayloadType.Failure, module, result.error)); - }), - ); + })); }; /** @@ -206,19 +200,32 @@ export function createResultResolver< >(config: { onStop?: (module: T) => unknown; onNext: (args: Args) => Output; - createStream: (args: Args) => AsyncGenerator; }) { - return (args: Args) => { - const task = config.createStream(args); - return from(task).pipe( - tap(result => { - result.isErr() && config.onStop?.(args.module); - }), - everyPluginOk, - filterMapTo(() => config.onNext(args))); + return async (args: Args) => { + //@ts-ignore fix later + const task = await callPlugins(args); + if(task.isOk()) { + return config.onNext(args) as ExecutePayload; + } else { + config.onStop?.(args.module); + } }; }; +async function callPlugins({ args, module }: { args: unknown[], module: Module }) { + let state = {}; + for(const plugin of module.onEvent) { + const result = await plugin.execute.apply(null, !Array.isArray(args) ? args : args); + if(result.isErr()) { + return result + } + if(typeof result.value === 'object') { + //@ts-ignore TODO + state = { ...result.value, ...state }; + } + } + return Ok(state); +} /** * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter @@ -230,18 +237,7 @@ export function makeModuleExecutor< M extends Processed, Args extends { module, args }); - return createResultResolver({ - onStop, - createStream: async function* ({ args, module }) { - for(const plugin of module.onEvent) { - const result = await callPlugin(plugin, args); - if(result.isErr()) { - return result.error - } - } - }, - onNext, - }) + return createResultResolver({ onStop, onNext }) } export const handleCrash = ({ "@sern/errors": err, diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index 9adf3fb5..db1f4354 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -1,5 +1,5 @@ import type { Interaction } from 'discord.js'; -import { mergeMap, merge, concatMap } from 'rxjs'; +import { mergeMap, merge, concatMap, EMPTY } from 'rxjs'; import { PayloadType } from '../core/structures/enums'; import { filterTap, sharedEventStream } from '../core/operators' import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; @@ -26,5 +26,9 @@ export default function interactionHandler(deps: UnpackedDependencies) { .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), concatMap(makeModuleExecutor(module => emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), - mergeMap(payload => executeModule(emitter, log, err, payload))); + mergeMap(payload => { + if(payload) + return executeModule(emitter, log, err, payload) + return EMPTY; + })); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 26023474..f0563f06 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -5,7 +5,7 @@ import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { filterTap, sharedEventStream } from '../core/operators' import { UnpackedDependencies } from '../types/utility'; -import { Emitter } from '..'; +import type { Emitter } from '../core/interfaces'; /** * Ignores messages from any person / bot except itself @@ -40,5 +40,9 @@ export default function message( const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); emitter.emit('module.activate', result); })), - mergeMap(payload => executeModule(emitter, log, err, payload))); + mergeMap(payload => { + if(payload) + executeModule(emitter, log, err, payload) + return EMPTY; + })); } diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index dd62d52e..c8bb8ad8 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -5,12 +5,13 @@ import { Module } from '../../src/types/core-modules'; import { Processed } from '../../src/types/core-modules'; import { CommandType } from '../../src/core/structures/enums'; import { EventEmitter } from 'events'; +import { EventType } from '../../dist/core/structures/enums'; function createRandomModule(): Processed { return { type: faker.number.int({ - min: CommandType.Text, - max: CommandType.ChannelSelect, + min: EventType.Discord, + max: EventType.Cron, }), meta: { id:"", absPath: faker.system.directoryPath() }, description: faker.string.alpha(), From 671767272260de4e1294d3971c08f0cd97302cba Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 17 May 2024 15:07:32 -0500 Subject: [PATCH 44/90] plugin data reduction & args changes --- src/core/module-loading.ts | 3 +- src/core/operators.ts | 12 ++----- src/core/structures/context.ts | 29 +++++++++++++---- src/core/structures/default-services.ts | 1 - src/handlers/event-utils.ts | 43 +++++++++++++------------ src/handlers/interaction.ts | 4 +-- src/handlers/message.ts | 5 +-- src/sern.ts | 2 +- test/handlers/dispatchers.test.ts | 36 ++++++++++++--------- 9 files changed, 74 insertions(+), 61 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 4fd2d831..2d2b4046 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -57,7 +57,6 @@ export async function importModule(absPath: string) { export async function* readRecursive(dir: string): AsyncGenerator { const files = await readdir(dir, { withFileTypes: true }); - for (const file of files) { const fullPath = path.posix.join(dir, file.name); if (file.isDirectory()) { @@ -65,7 +64,7 @@ export async function* readRecursive(dir: string): AsyncGenerator { yield* readRecursive(fullPath); } } else if (!file.name.startsWith('!')) { - yield fullPath; + yield "file:///"+path.resolve(fullPath); } } } diff --git a/src/core/operators.ts b/src/core/operators.ts index 2e08b2c9..09986318 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -5,21 +5,17 @@ */ import { concatMap, - defaultIfEmpty, EMPTY, - every, fromEvent, Observable, of, OperatorFunction, - pipe, share, } from 'rxjs'; import type { Emitter, ErrorHandling, Logging } from './interfaces'; import util from 'node:util'; -import type { PluginResult } from '../types/core-plugin'; -import { Result } from 'ts-results-es'; -import { VoidResult } from '../types/utility'; +import type { Result } from 'ts-results-es'; + /** * if {src} is true, mapTo V, else ignore * @param item @@ -28,10 +24,6 @@ export function filterMapTo(item: () => V): OperatorFunction { return concatMap(keep => keep ? of(item()) : EMPTY); } -interface PluginExecutable { - execute: (...args: unknown[]) => PluginResult; -}; - export const arrayifySource = (src: T) => Array.isArray(src) ? src : [src]; diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index d4348005..2b22dee0 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -13,6 +13,10 @@ import { Result, Ok, Err } from 'ts-results-es'; import * as assert from 'assert'; import { ReplyOptions } from '../../types/utility'; +function fmt(msg: string, prefix?: string): string[] { + if(!prefix) throw Error("Unable to parse message without prefix"); + return msg.slice(prefix.length).trim().split(/\s+/g); +} /** * @since 1.0.0 @@ -20,14 +24,25 @@ import { ReplyOptions } from '../../types/utility'; * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { - /* - * @Experimental - */ + prefix: string|undefined; + get options() { return this.interaction.options; } - protected constructor(protected ctx: Result) { + + args() { + return { + message: () => { + const [, ...rest] = fmt(this.message.content, this.prefix); + return rest as T; + }, + interaction: () => this.interaction.options + } + } + + protected constructor(protected ctx: Result, prefix?: string) { super(ctx); + this.prefix = prefix } public get id(): Snowflake { @@ -109,12 +124,12 @@ export class Context extends CoreContext { ); } - static override wrap(wrappable: BaseInteraction | Message): Context { + static override wrap(wrappable: BaseInteraction | Message, prefix?: string): Context { if ('interaction' in wrappable) { - return new Context(Ok(wrappable)); + return new Context(Ok(wrappable), prefix); } assert.ok(wrappable.isChatInputCommand(), "Context created with bad interaction."); - return new Context(Err(wrappable)); + return new Context(Err(wrappable), prefix); } } diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index e30a6f5b..0981b9cb 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,7 +1,6 @@ import type { LogPayload, Logging, ErrorHandling, Emitter } from '../interfaces'; import { AnyFunction, UnpackedDependencies } from '../../types/utility'; import cron from 'node-cron' -import { EventEmitter } from 'events'; import type { CronEventCommand, Module } from '../../types/core-modules' import { EventType } from './enums'; /** diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 1c79e17a..42814584 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -9,7 +9,7 @@ import { fromEvent, map, OperatorFunction, catchError, finalize, - pipe + pipe, } from 'rxjs'; import * as Id from '../core/id' import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; @@ -21,16 +21,14 @@ import type { CommandModule, Module, Processed } from '../types/core-modules'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; import { CommandType } from '../core/structures/enums' -import type { Args } from '../types/utility'; import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; import { arrayifySource, handleError } from '../core/operators'; import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' -function contextArgs(wrappable: Message | BaseInteraction, messageArgs?: string[]) { - const ctx = Context.wrap(wrappable); - const args = ctx.isMessage() ? ['text', messageArgs!] : ['slash', ctx.options]; - return [ctx, args] as [Context, Args]; +function contextArgs(wrappable: Message | BaseInteraction, prefix?: string) { + const ctx = Context.wrap(wrappable, prefix); + return [ctx] as [Context]; } function intoPayload(module: Module) { @@ -44,7 +42,7 @@ const createResult = createResultResolver< >({ //@ts-ignore fix later callPlugins, - onNext: ({ args }) => args, + onNext: (p) => p.args, }); /** * Creates an observable from { source } @@ -52,19 +50,21 @@ const createResult = createResultResolver< * @param source */ export function eventDispatcher(module: Module, source: unknown) { - assert.ok(source && typeof source === 'object', `${source} cannot be constructed into an event listener`); + assert.ok(source && typeof source === 'object', + `${source} cannot be constructed into an event listener`); const execute: OperatorFunction = concatMap(async args => module.execute(...args)); //@ts-ignore return fromEvent(source, module.name!) - //@ts-ignore .pipe(intoPayload(module), concatMap(createResult), execute); } -export function createDispatcher({ module, event }: { module: Processed; event: BaseInteraction; }) { +export function createDispatcher( + { module, event }: { module: Processed; event: BaseInteraction; } +) { assert.ok(CommandType.Text !== module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); if(isAutocomplete(event)) { @@ -118,6 +118,7 @@ export function fmt(msg: string, prefix: string): string[] { export function createInteractionHandler( source: Observable, mg: Map, + defaultPrefix?: string ) { return createGenericHandler, void>>( source, @@ -141,12 +142,13 @@ export function createMessageHandler( mg: any, ) { return createGenericHandler(source, async event => { - const [prefix, ...rest] = fmt(event.content, defaultPrefix); - let fullPath = mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`); - if(!fullPath) { + const [prefix] = fmt(event.content, defaultPrefix); + console.log(prefix) + let module= mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`) as Module; + if(!module) { return Err('Possibly undefined behavior: could not find a static id to resolve'); } - return Ok({ args: contextArgs(event, rest), module: fullPath as Processed }) + return Ok({ args: [Context.wrap(event, defaultPrefix)], module }) }); } @@ -215,9 +217,9 @@ export function createResultResolver< async function callPlugins({ args, module }: { args: unknown[], module: Module }) { let state = {}; for(const plugin of module.onEvent) { - const result = await plugin.execute.apply(null, !Array.isArray(args) ? args : args); + const result = await plugin.execute.apply(null, arrayifySource(args)); if(result.isErr()) { - return result + return result; } if(typeof result.value === 'object') { //@ts-ignore TODO @@ -240,13 +242,12 @@ export function makeModuleExecutor< M extends Processed, Args extends { return createResultResolver({ onStop, onNext }) } -export const handleCrash = ({ "@sern/errors": err, - '@sern/emitter': sem, - '@sern/logger': log } : UnpackedDependencies) => +export const handleCrash = + ({ "@sern/errors": err, '@sern/emitter': sem, '@sern/logger': log } : UnpackedDependencies) => pipe(catchError(handleError(err, sem, log)), - finalize(() => { + finalize(() => { log?.info({ message: 'A stream closed or reached end of lifetime', }); disposeAll(log); - })) + })) diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index db1f4354..5e4c54ea 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -8,7 +8,7 @@ import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, import { UnpackedDependencies } from '../types/utility'; import { Emitter } from '../core/interfaces'; -export default function interactionHandler(deps: UnpackedDependencies) { +export default function interactionHandler(deps: UnpackedDependencies, defaultPrefix?: string) { //i wish javascript had clojure destructuring const { '@sern/modules': modules, '@sern/client': client, @@ -16,7 +16,7 @@ export default function interactionHandler(deps: UnpackedDependencies) { '@sern/errors': err, '@sern/emitter': emitter } = deps const interactionStream$ = sharedEventStream(client as unknown as Emitter, 'interactionCreate'); - const handle = createInteractionHandler(interactionStream$, modules); + const handle = createInteractionHandler(interactionStream$, modules, defaultPrefix); const interactionHandler$ = merge(handle(isMessageComponent), handle(isAutocomplete), diff --git a/src/handlers/message.ts b/src/handlers/message.ts index f0563f06..5005ec21 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -24,7 +24,8 @@ export default function message( {"@sern/emitter": emitter, '@sern/errors':err, '@sern/logger': log, '@sern/client': client, '@sern/modules': commands}: UnpackedDependencies, - defaultPrefix: string | undefined) { + defaultPrefix: string | undefined +) { if (!defaultPrefix) { log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; @@ -42,7 +43,7 @@ export default function message( })), mergeMap(payload => { if(payload) - executeModule(emitter, log, err, payload) + return executeModule(emitter, log, err, payload) return EMPTY; })); } diff --git a/src/sern.ts b/src/sern.ts index b48da0b6..41443aae 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -58,7 +58,7 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { .catch(err => { throw err }); const messages$ = messageHandler(deps, maybeWrapper.defaultPrefix); - const interactions$ = interactionHandler(deps); + const interactions$ = interactionHandler(deps, maybeWrapper.defaultPrefix); // listening to the message stream and interaction stream merge(messages$, interactions$).pipe(handleCrash(deps)).subscribe(); } diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index c8bb8ad8..e9a1544d 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -1,27 +1,31 @@ import { beforeEach, describe, expect, vi, it } from 'vitest'; import { eventDispatcher } from '../../src/handlers/event-utils'; import { faker } from '@faker-js/faker'; +import { TestScheduler } from 'rxjs/testing'; import { Module } from '../../src/types/core-modules'; import { Processed } from '../../src/types/core-modules'; -import { CommandType } from '../../src/core/structures/enums'; import { EventEmitter } from 'events'; import { EventType } from '../../dist/core/structures/enums'; function createRandomModule(): Processed { return { - type: faker.number.int({ - min: EventType.Discord, - max: EventType.Cron, - }), - meta: { id:"", absPath: faker.system.directoryPath() }, + type: EventType.Discord, + meta: { id:"", absPath: "" }, description: faker.string.alpha(), - name: faker.string.alpha(), + name: "abc", onEvent: [], plugins: [], execute: vi.fn(), }; } +const testScheduler = new TestScheduler((actual, expected) => { + // asserting the two objects are equal - required + // for TestScheduler assertions to work via your test framework + // e.g. using chai. + expect(actual).deep.equal(expected); +}); + describe('eventDispatcher standard', () => { let m: Processed; let ee: EventEmitter; @@ -33,15 +37,17 @@ describe('eventDispatcher standard', () => { it('should throw', () => { expect(() => eventDispatcher(m, 'not event emitter')).toThrowError(); }); + it("Shouldn't throw", () => { expect(() => eventDispatcher(m, ee)).not.toThrowError(); }); - - it('Should be called once', () => { - const s = eventDispatcher(m, ee); - s.subscribe(); - ee.emit(m.name, faker.string.alpha()); - - expect(m.execute).toHaveBeenCalledOnce(); - }); + //TODO +// it('Should be called once', () => { +// const s = eventDispatcher(m, ee); +// console.log(m) +// s.subscribe(); +// ee.emit(m.name); +// console.log(m.execute) +// expect(m.execute).toHaveBeenCalledOnce(); +// }); }); From 960f90c544cf9340e427ba7caad1e8195dbf6658 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 17 May 2024 20:16:16 -0500 Subject: [PATCH 45/90] freeze module after plugins, updateModule, and more --- src/core/functions.ts | 4 ++-- src/handlers/event-utils.ts | 1 - src/handlers/ready.ts | 12 ++++++++++-- src/types/core-modules.ts | 8 ++++---- src/types/core-plugin.ts | 35 ++++++++++++++++++----------------- 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index 46e204c6..02ef466a 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -14,8 +14,8 @@ import { PayloadType, PluginType } from './structures/enums'; import assert from 'assert'; import type { Payload } from '../types/utility'; -export const ok = (val: unknown) => Ok(val); -export const err = (val: string) => Err(val); +export const ok = (val: unknown=undefined) => Ok(val); +export const err = (val?: string) => Err(val); export function partitionPlugins (arr: Array<{ type: PluginType }> = []): [T[], V[]] { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 42814584..d0babb41 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -143,7 +143,6 @@ export function createMessageHandler( ) { return createGenericHandler(source, async event => { const [prefix] = fmt(event.content, defaultPrefix); - console.log(prefix) let module= mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`) as Module; if(!module) { return Err('Possibly undefined behavior: could not find a static id to resolve'); diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index b641ab92..e5aa8f62 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -18,18 +18,26 @@ export default async function(dir: string, deps : UnpackedDependencies) { // https://observablehq.com/@ehouais/multiple-promises-as-an-async-generator // possibly optimize to concurrently import modules for await (const path of Files.readRecursive(dir)) { - const { module } = await Files.importModule(path); + let { module } = await Files.importModule(path); const validType = module.type >= CommandType.Text && module.type <= CommandType.ChannelSelect; if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``); } for(const plugin of module.plugins) { - const res = await plugin.execute({ module, absPath: module.meta.absPath }); + const res = await plugin.execute({ + module, + absPath: module.meta.absPath , + updateModule: (partial: Partial) => { + module = { ...module, ...partial }; + return module; + } + }); if(res.isErr()) { sEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); throw Error("Plugin failed with controller.stop()"); } } + Object.freeze(module); // no more writing!! commands.set(module.meta.id, module); sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index c0f35565..cba35599 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -104,7 +104,7 @@ export interface ModalSubmitCommand extends Module { } export interface AutocompleteCommand - extends Omit { + extends Omit { onEvent: ControlPlugin[]; execute: (ctx: AutocompleteInteraction) => Awaitable; } @@ -117,21 +117,21 @@ export interface DiscordEventCommand Awaitable; + execute: (ctx: Context) => Awaitable; } export interface SlashCommand extends Module { type: CommandType.Slash; description: string; options?: SernOptionsData[]; - execute: (ctx: Context, args: ['slash', SlashOptions]) => Awaitable; + execute: (ctx: Context) => Awaitable; } export interface BothCommand extends Module { type: CommandType.Both; description: string; options?: SernOptionsData[]; - execute: (ctx: Context, args: Args) => Awaitable; + execute: (ctx: Context) => Awaitable; } export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index abf36515..398decb2 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -11,7 +11,7 @@ * Plugins are reminiscent of middleware in express. */ -import type { Err, Ok } from 'ts-results-es'; +import type { Err, Ok, Result } from 'ts-results-es'; import type { BothCommand, ButtonCommand, @@ -33,7 +33,7 @@ import type { TextCommand, UserSelectCommand, } from './core-modules'; -import type { Args, Awaitable, Payload, SlashOptions, VoidResult } from './utility'; +import type { Args, Awaitable, Payload, SlashOptions } from './utility'; import type { CommandType, EventType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { @@ -49,11 +49,12 @@ import type { UserSelectMenuInteraction, } from 'discord.js'; -export type PluginResult = Awaitable; +export type PluginResult = Awaitable>; export interface InitArgs> { module: T; absPath: string; + updateModule: (module: Partial) => T } export interface Controller { next: () => Ok; @@ -73,8 +74,8 @@ export interface ControlPlugin { execute: (...args: Args) => PluginResult; } -export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; -export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; +export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; +export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; export type CommandArgs< I extends CommandType = CommandType, @@ -88,51 +89,51 @@ export type EventArgs< I extends EventType = EventType, interface CommandArgsMatrix { [CommandType.Text]: { [PluginType.Control]: [Context, ['text', string[]]]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.Slash]: { [PluginType.Control]: [Context, ['slash', /* library coupled */ SlashOptions]]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.Both]: { [PluginType.Control]: [Context, Args]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.CtxMsg]: { [PluginType.Control]: [/* library coupled */ MessageContextMenuCommandInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.CtxUser]: { [PluginType.Control]: [/* library coupled */ UserContextMenuCommandInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.Button]: { [PluginType.Control]: [/* library coupled */ ButtonInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.StringSelect]: { [PluginType.Control]: [/* library coupled */ StringSelectMenuInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.RoleSelect]: { [PluginType.Control]: [/* library coupled */ RoleSelectMenuInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.ChannelSelect]: { [PluginType.Control]: [/* library coupled */ ChannelSelectMenuInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.MentionableSelect]: { [PluginType.Control]: [/* library coupled */ MentionableSelectMenuInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.UserSelect]: { [PluginType.Control]: [/* library coupled */ UserSelectMenuInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; [CommandType.Modal]: { [PluginType.Control]: [/* library coupled */ ModalSubmitInteraction]; - [PluginType.Init]: [InitArgs>]; + [PluginType.Init]: [InitArgs>]; }; } From 699adf276c36938281a8a09b314a5dd8a82ad149 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 17 May 2024 23:13:12 -0500 Subject: [PATCH 46/90] simplify plugin args and prepare for reduction among plugins --- src/core/create-plugins.ts | 12 ++- src/core/module-loading.ts | 2 - src/handlers/event-utils.ts | 56 +++++++------- src/handlers/ready.ts | 6 +- src/handlers/user-defined-events.ts | 11 ++- src/index.ts | 2 +- src/types/core-modules.ts | 25 +++--- src/types/core-plugin.ts | 115 ++++++---------------------- src/types/utility.ts | 11 +-- 9 files changed, 81 insertions(+), 159 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 1659e17b..4bcf269f 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -1,5 +1,5 @@ import { CommandType, EventType, PluginType } from './structures/enums'; -import type { Plugin, PluginResult, EventArgs, CommandArgs } from '../types/core-plugin'; +import type { Plugin, PluginResult, EventArgs, CommandArgs, InitArgs } from '../types/core-plugin'; import type { ClientEvents } from 'discord.js'; import { err, ok } from './functions'; @@ -12,16 +12,14 @@ export function makePlugin( /** * @since 2.5.0 */ -export function EventInitPlugin( - execute: (...args: EventArgs) => PluginResult, -) { +export function EventInitPlugin(execute: (args: InitArgs) => PluginResult) { return makePlugin(PluginType.Init, execute); } /** * @since 2.5.0 */ export function CommandInitPlugin( - execute: (...args: CommandArgs) => PluginResult, + execute: (args: InitArgs) => PluginResult ) { return makePlugin(PluginType.Init, execute); } @@ -29,7 +27,7 @@ export function CommandInitPlugin( * @since 2.5.0 */ export function CommandControlPlugin( - execute: (...args: CommandArgs) => PluginResult, + execute: (...args: CommandArgs) => PluginResult, ) { return makePlugin(PluginType.Control, execute); } @@ -37,7 +35,7 @@ export function CommandControlPlugin( * @since 2.5.0 */ export function EventControlPlugin( - execute: (...args: EventArgs) => PluginResult, + execute: (...args: EventArgs) => PluginResult, ) { return makePlugin(PluginType.Control, execute); } diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 2d2b4046..88cabd7e 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -22,7 +22,6 @@ export const shouldHandle = (pth: string, filenam: string) => { } - /** * Import any module based on the absolute path. * This can accept four types of exported modules @@ -47,7 +46,6 @@ export async function importModule(absPath: string) { const p = path.parse(absPath) commandModule.name ??= p.name; commandModule.description ??= "..."; commandModule.meta = { - //@ts-ignore id: Id.create(commandModule.name, commandModule.type), absPath, }; diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index d0babb41..1a529536 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -26,11 +26,6 @@ import { disposeAll } from '../core/ioc/base'; import { arrayifySource, handleError } from '../core/operators'; import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' -function contextArgs(wrappable: Message | BaseInteraction, prefix?: string) { - const ctx = Context.wrap(wrappable, prefix); - return [ctx] as [Context]; -} - function intoPayload(module: Module) { return pipe(map(arrayifySource), map(args => ({ module, args }))); @@ -39,11 +34,7 @@ const createResult = createResultResolver< Processed, { module: Processed; args: unknown[] }, unknown[] ->({ - //@ts-ignore fix later - callPlugins, - onNext: (p) => p.args, -}); +>({ onNext: (p) => p.args, }); /** * Creates an observable from { source } * @param module @@ -62,9 +53,12 @@ export function eventDispatcher(module: Module, source: unknown) { execute); } -export function createDispatcher( - { module, event }: { module: Processed; event: BaseInteraction; } -) { +interface DispatchPayload { + module: Processed; + event: BaseInteraction; + defaultPrefix?: string +}; +export function createDispatcher({ module, event, defaultPrefix }: DispatchPayload) { assert.ok(CommandType.Text !== module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); if(isAutocomplete(event)) { @@ -79,7 +73,10 @@ export function createDispatcher( switch (module.type) { case CommandType.Slash: case CommandType.Both: { - return { module, args: contextArgs(event) }; + return { + module, + args: [Context.wrap(event, defaultPrefix)] + }; } default: return { module, args: [event] }; } @@ -132,14 +129,18 @@ export function createInteractionHandler( return Err.EMPTY; } const [ path ] = fullPaths; - return Ok(createDispatcher({ module: path as Processed, event })); + return Ok(createDispatcher({ + module: path as Processed, + event, + defaultPrefix + })); }); } export function createMessageHandler( source: Observable, defaultPrefix: string, - mg: any, + mg: Map, ) { return createGenericHandler(source, async event => { const [prefix] = fmt(event.content, defaultPrefix); @@ -156,7 +157,6 @@ export function createMessageHandler( interface ExecutePayload { module: Processed; task: () => Awaitable; - args: unknown[] } /** * Wraps the task in a Result as a try / catch. @@ -171,7 +171,7 @@ export function executeModule( emitter: Emitter, logger: Logging|undefined, errHandler: ErrorHandling, - { module, task, args }: ExecutePayload, + { module, task }: ExecutePayload, ) { return of(module).pipe( //converting the task into a promise so rxjs can resolve the Awaitable properly @@ -200,15 +200,15 @@ export function createResultResolver< Output, >(config: { onStop?: (module: T) => unknown; - onNext: (args: Args) => Output; + onNext: (args: Args, map: Record) => Output; }) { - return async (args: Args) => { + return async (payload: Args) => { //@ts-ignore fix later - const task = await callPlugins(args); + const task = await callPlugins(payload); if(task.isOk()) { - return config.onNext(args) as ExecutePayload; + return config.onNext(payload, task.value) as ExecutePayload; } else { - config.onStop?.(args.module); + config.onStop?.(payload.module); } }; }; @@ -220,8 +220,7 @@ async function callPlugins({ args, module }: { args: unknown[], module: Module } if(result.isErr()) { return result; } - if(typeof result.value === 'object') { - //@ts-ignore TODO + if(typeof result.value === 'object' && result.value !== null) { state = { ...result.value, ...state }; } } @@ -231,12 +230,11 @@ async function callPlugins({ args, module }: { args: unknown[], module: Module } * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter */ -export function makeModuleExecutor< M extends Processed, Args extends { module: M; args: unknown[]; }> +export function makeModuleExecutor (onStop: (m: M) => unknown) { - const onNext = ({ args, module }: Args) => ({ - task: () => module.execute(...args), + const onNext = ({ args, module }: Args, state: Record) => ({ + task: () => module.execute(...args, state), module, - args }); return createResultResolver({ onStop, onNext }) } diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index e5aa8f62..503301c0 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -21,7 +21,7 @@ export default async function(dir: string, deps : UnpackedDependencies) { let { module } = await Files.importModule(path); const validType = module.type >= CommandType.Text && module.type <= CommandType.ChannelSelect; if(!validType) { - throw Error(`Found ${module.name} at ${module.meta.absPath}, which has an incorrect \`type\``); + throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } for(const plugin of module.plugins) { const res = await plugin.execute({ @@ -37,8 +37,8 @@ export default async function(dir: string, deps : UnpackedDependencies) { throw Error("Plugin failed with controller.stop()"); } } - Object.freeze(module); // no more writing!! - commands.set(module.meta.id, module); + // FREEZE! no more writing!! + commands.set(module.meta.id, Object.freeze(module)); sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); } sEmitter.emit('modulesLoaded'); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index 20982ae8..c58cff42 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -29,9 +29,16 @@ const intoDispatcher = (deps: UnpackedDependencies) => export default async function(deps: UnpackedDependencies, eventDir: string) { const eventModules: EventModule[] = []; for await (const path of Files.readRecursive(eventDir)) { - const { module } = await Files.importModule(path); + let { module } = await Files.importModule(path); for(const plugin of module.plugins) { - const res = await plugin.execute({ module, absPath: module.meta.absPath }); + const res = await plugin.execute({ + module, + absPath: module.meta.absPath , + updateModule: (partial: Partial) => { + module = { ...module, ...partial }; + return module; + } + }); if(res.isErr()) { deps['@sern/emitter'].emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); throw Error("Plugin failed with controller.stop()"); diff --git a/src/index.ts b/src/index.ts index b752b228..624de273 100644 --- a/src/index.ts +++ b/src/index.ts @@ -37,7 +37,7 @@ export type { } from './types/core-plugin'; -export type { Args, SlashOptions, Payload, SernEventsMapping } from './types/utility'; +export type { Payload, SernEventsMapping } from './types/utility'; export type { CoreDependencies } from './types/ioc'; export { diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index cba35599..e1fbebbe 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -18,9 +18,11 @@ import type { import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin'; -import { Awaitable, Args, SlashOptions, SernEventsMapping } from './utility'; - +import { Awaitable, SernEventsMapping } from './utility'; +type ToBeDecided = { + result: Record; +} export type Processed = T & { name: string; description: string }; export interface Module { @@ -70,42 +72,41 @@ export interface ContextMenuMsg extends Module { export interface ButtonCommand extends Module { type: CommandType.Button; - execute: (ctx: ButtonInteraction) => Awaitable; + execute: (ctx: ButtonInteraction, tbd: ToBeDecided) => Awaitable; } export interface StringSelectCommand extends Module { type: CommandType.StringSelect; - execute: (ctx: StringSelectMenuInteraction) => Awaitable; + execute: (ctx: StringSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; } export interface ChannelSelectCommand extends Module { type: CommandType.ChannelSelect; - execute: (ctx: ChannelSelectMenuInteraction) => Awaitable; + execute: (ctx: ChannelSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; } export interface RoleSelectCommand extends Module { type: CommandType.RoleSelect; - execute: (ctx: RoleSelectMenuInteraction) => Awaitable; + execute: (ctx: RoleSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; } export interface MentionableSelectCommand extends Module { type: CommandType.MentionableSelect; - execute: (ctx: MentionableSelectMenuInteraction) => Awaitable; + execute: (ctx: MentionableSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; } export interface UserSelectCommand extends Module { type: CommandType.UserSelect; - execute: (ctx: UserSelectMenuInteraction) => Awaitable; + execute: (ctx: UserSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; } export interface ModalSubmitCommand extends Module { type: CommandType.Modal; - execute: (ctx: ModalSubmitInteraction) => Awaitable; + execute: (ctx: ModalSubmitInteraction, tbd: ToBeDecided) => Awaitable; } -export interface AutocompleteCommand - extends Omit { - onEvent: ControlPlugin[]; +export interface AutocompleteCommand { + onEvent?: ControlPlugin[]; execute: (ctx: AutocompleteInteraction) => Awaitable; } diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 398decb2..108d2435 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -13,27 +13,10 @@ import type { Err, Ok, Result } from 'ts-results-es'; import type { - BothCommand, - ButtonCommand, - ChannelSelectCommand, - CommandModule, - ContextMenuMsg, - ContextMenuUser, - DiscordEventCommand, - EventModule, - ExternalEventCommand, - MentionableSelectCommand, - ModalSubmitCommand, Module, Processed, - RoleSelectCommand, - SernEventCommand, - SlashCommand, - StringSelectCommand, - TextCommand, - UserSelectCommand, } from './core-modules'; -import type { Args, Awaitable, Payload, SlashOptions } from './utility'; +import type { Awaitable, Payload } from './utility'; import type { CommandType, EventType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { @@ -51,14 +34,14 @@ import type { export type PluginResult = Awaitable>; -export interface InitArgs> { +export interface InitArgs = Processed> { module: T; absPath: string; updateModule: (module: Partial) => T } export interface Controller { - next: () => Ok; - stop: () => Err; + next: () => Ok; + stop: () => Err; } export interface Plugin { type: PluginType; @@ -77,81 +60,27 @@ export interface ControlPlugin { export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; -export type CommandArgs< - I extends CommandType = CommandType, - J extends PluginType = PluginType, -> = CommandArgsMatrix[I][J]; - -export type EventArgs< I extends EventType = EventType, - J extends PluginType = PluginType, -> = EventArgsMatrix[I][J]; +export type CommandArgs = CommandArgsMatrix[I] +export type EventArgs = EventArgsMatrix[I] 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>]; - }; + [CommandType.Text]: [Context]; + [CommandType.Slash]: [Context]; + [CommandType.Both]: [Context]; + [CommandType.CtxMsg]: [MessageContextMenuCommandInteraction]; + [CommandType.CtxUser]: [UserContextMenuCommandInteraction]; + [CommandType.Button]: [ButtonInteraction]; + [CommandType.StringSelect]: [StringSelectMenuInteraction]; + [CommandType.RoleSelect]: [RoleSelectMenuInteraction]; + [CommandType.ChannelSelect]: [ChannelSelectMenuInteraction]; + [CommandType.MentionableSelect]: [MentionableSelectMenuInteraction]; + [CommandType.UserSelect]: [UserSelectMenuInteraction]; + [CommandType.Modal]: [ModalSubmitInteraction]; } 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>]; - }; - [EventType.Cron]: { - [PluginType.Control]: unknown[]; - [PluginType.Init]: [InitArgs>]; - }; + [EventType.Discord]: ClientEvents[keyof ClientEvents]; + [EventType.Sern]: [Payload]; + [EventType.External]: unknown[]; + [EventType.Cron]: unknown[]; } diff --git a/src/types/utility.ts b/src/types/utility.ts index ac959db7..3b4c38ea 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -1,4 +1,4 @@ -import type { CommandInteractionOptionResolver, InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; +import type { InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; import type { PayloadType } from '../core/structures/enums'; import type { Module } from './core-modules'; import type { Result } from 'ts-results-es'; @@ -8,15 +8,6 @@ export type Awaitable = PromiseLike | T; export type VoidResult = Result; export type AnyFunction = (...args: any[]) => unknown; -// Thanks to @kelsny -type ParseType = { - [K in keyof T]: T[K] extends unknown ? [k: K, args: T[K]] : never; -}[keyof T]; - -export type SlashOptions = Omit; - -export type Args = ParseType<{ text: string[]; slash: SlashOptions }>; - export interface SernEventsMapping { 'module.register': [Payload]; 'module.activate': [Payload]; From 0beeb4c0646bea6ef93ccb8777c3ff1155141599 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 19 May 2024 22:33:57 -0500 Subject: [PATCH 47/90] add deps to plugin calls and execute --- src/core/operators.ts | 1 - src/core/structures/context.ts | 2 +- src/core/structures/core-context.ts | 6 -- src/core/structures/default-services.ts | 7 +- src/handlers/event-utils.ts | 137 ++++++++++++------------ src/handlers/interaction.ts | 16 ++- src/handlers/message.ts | 16 +-- src/handlers/user-defined-events.ts | 13 ++- src/sern.ts | 3 +- 9 files changed, 99 insertions(+), 102 deletions(-) diff --git a/src/core/operators.ts b/src/core/operators.ts index 09986318..77fa2579 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -24,7 +24,6 @@ export function filterMapTo(item: () => V): OperatorFunction { return concatMap(keep => keep ? of(item()) : EMPTY); } - export const arrayifySource = (src: T) => Array.isArray(src) ? src : [src]; diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 2b22dee0..f3aa1591 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -124,7 +124,7 @@ export class Context extends CoreContext { ); } - static override wrap(wrappable: BaseInteraction | Message, prefix?: string): Context { + static wrap(wrappable: BaseInteraction | Message, prefix?: string): Context { if ('interaction' in wrappable) { return new Context(Ok(wrappable), prefix); } diff --git a/src/core/structures/core-context.ts b/src/core/structures/core-context.ts index e5eed997..8ffd6a08 100644 --- a/src/core/structures/core-context.ts +++ b/src/core/structures/core-context.ts @@ -23,10 +23,4 @@ export abstract class CoreContext { public isSlash(): this is CoreContext { return !this.isMessage(); } - //todo: add agnostic options resolver for Context - abstract get options(): unknown; - - static wrap(_: unknown): unknown { - throw Error('You need to override this method; cannot wrap an abstract class'); - } } diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 0981b9cb..06b403df 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -65,10 +65,9 @@ export class Cron implements Emitter { const retrievedModule = this.modules.get(eventName); if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); const { pattern, name, runOnInit, timezone } = retrievedModule; - const task = cron.schedule(pattern, - (date) => listener({ date, deps: this.deps }), - { name, runOnInit, timezone, scheduled: true }); - task.on('task-failed', console.error) + cron.schedule(pattern, + (date) => listener({ date, deps: this.deps }), + { name, runOnInit, timezone, scheduled: true }); return this; } removeListener(eventName: string | symbol, listener: AnyFunction) { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 1a529536..474b6486 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -4,19 +4,20 @@ import { Observable, concatMap, filter, - of, throwError, - fromEvent, map, OperatorFunction, + fromEvent, + map, + type OperatorFunction, catchError, finalize, pipe, + from, } from 'rxjs'; import * as Id from '../core/id' -import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; +import type { Emitter } from '../core/interfaces'; import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; -import type { Awaitable, UnpackedDependencies, VoidResult } from '../types/utility'; -import type { ControlPlugin } from '../types/core-plugin'; +import type { UnpackedDependencies, VoidResult } from '../types/utility'; import type { CommandModule, Module, Processed } from '../types/core-modules'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; @@ -26,59 +27,75 @@ import { disposeAll } from '../core/ioc/base'; import { arrayifySource, handleError } from '../core/operators'; import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' -function intoPayload(module: Module) { +interface ExecutePayload { + module: Module; + args: unknown[]; + deps: Dependencies + [key: string]: unknown +} + +function intoPayload(module: Module, deps: Dependencies) { return pipe(map(arrayifySource), - map(args => ({ module, args }))); + map(args => ({ module, args, deps }))); } -const createResult = createResultResolver< - Processed, - { module: Processed; args: unknown[] }, - unknown[] ->({ onNext: (p) => p.args, }); +const createResult = (deps: Dependencies) => + createResultResolver({ + onNext: (p) => p.args, + onStop: (module) => { + //maybe do something when plugins fail? + } + }); /** * Creates an observable from { source } * @param module * @param source */ -export function eventDispatcher(module: Module, source: unknown) { +export function eventDispatcher(deps: Dependencies, module: Module, source: unknown) { assert.ok(source && typeof source === 'object', `${source} cannot be constructed into an event listener`); - const execute: OperatorFunction = - concatMap(async args => module.execute(...args)); + const execute: OperatorFunction = + concatMap(async args => { + if(args) + return module.execute.apply(null, args); + }); //@ts-ignore return fromEvent(source, module.name!) - //@ts-ignore - .pipe(intoPayload(module), - concatMap(createResult), + .pipe(intoPayload(module, deps), + concatMap(createResult(deps)), execute); } interface DispatchPayload { module: Processed; event: BaseInteraction; - defaultPrefix?: string + defaultPrefix?: string; + deps: Dependencies }; -export function createDispatcher({ module, event, defaultPrefix }: DispatchPayload) { +export function createDispatcher({ module, event, defaultPrefix, deps }: DispatchPayload): ExecutePayload { assert.ok(CommandType.Text !== module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); + if(isAutocomplete(event)) { assert.ok(module.type === CommandType.Slash - || module.type === CommandType.Both); + || module.type === CommandType.Both, "Autocomplete option on non command interaction"); const option = treeSearch(event, module.options); assert.ok(option, SernError.NotSupportedInteraction + ` There is no autocomplete tag for ` + inspect(module)); const { command } = option; return { module: command as Processed, //autocomplete is not a true "module" warning cast! - args: [event] }; + args: [event], + deps }; } + switch (module.type) { case CommandType.Slash: case CommandType.Both: { return { module, - args: [Context.wrap(event, defaultPrefix)] + args: [Context.wrap(event, defaultPrefix)], + deps }; } - default: return { module, args: [event] }; + default: return { module, args: [event], deps }; } } function createGenericHandler( @@ -114,25 +131,27 @@ export function fmt(msg: string, prefix: string): string[] { */ export function createInteractionHandler( source: Observable, - mg: Map, + deps: Dependencies, defaultPrefix?: string ) { + const mg = deps['@sern/modules'] return createGenericHandler, void>>( source, async event => { const possibleIds = Id.reconstruct(event); - let fullPaths= possibleIds + let modules = possibleIds .map(id => mg.get(id)) .filter((id): id is Module => id !== undefined); - if(fullPaths.length == 0) { + if(modules.length == 0) { return Err.EMPTY; } - const [ path ] = fullPaths; + const [ module ] = modules; return Ok(createDispatcher({ - module: path as Processed, + module: module as Processed, event, - defaultPrefix + defaultPrefix, + deps })); }); } @@ -140,24 +159,20 @@ export function createInteractionHandler( export function createMessageHandler( source: Observable, defaultPrefix: string, - mg: Map, + deps: Dependencies ) { + const mg = deps['@sern/modules']; return createGenericHandler(source, async event => { const [prefix] = fmt(event.content, defaultPrefix); let module= mg.get(`${prefix}_T`) ?? mg.get(`${prefix}_B`) as Module; if(!module) { return Err('Possibly undefined behavior: could not find a static id to resolve'); } - return Ok({ args: [Context.wrap(event, defaultPrefix)], module }) + return Ok({ args: [Context.wrap(event, defaultPrefix)], module, deps }) }); } - -interface ExecutePayload { - module: Processed; - task: () => Awaitable; -} /** * Wraps the task in a Result as a try / catch. * if the task is ok, an event is emitted and the stream becomes empty @@ -169,20 +184,16 @@ interface ExecutePayload { */ export function executeModule( emitter: Emitter, - logger: Logging|undefined, - errHandler: ErrorHandling, - { module, task }: ExecutePayload, + { module, args }: ExecutePayload, ) { - return of(module).pipe( - //converting the task into a promise so rxjs can resolve the Awaitable properly - concatMap(() => Result.wrapAsync(async () => task())), - concatMap(result => { + return from(Result.wrapAsync(async () => module.execute(...args))) + .pipe(concatMap(result => { if (result.isOk()) { emitter.emit('module.activate', resultPayload(PayloadType.Success, module)); return EMPTY; - } + } return throwError(() => resultPayload(PayloadType.Failure, module, result.error)); - })); + })) }; /** @@ -194,29 +205,25 @@ export function executeModule( * @param config * @returns receiver function for flattening a stream of data */ -export function createResultResolver< - T extends { execute: (...args: any[]) => any; onEvent: ControlPlugin[] }, - Args extends { module: T; [key: string]: unknown }, - Output, ->(config: { - onStop?: (module: T) => unknown; - onNext: (args: Args, map: Record) => Output; +export function createResultResolver(config: { + onStop?: (module: Module) => unknown; + onNext: (args: ExecutePayload, map: Record) => Output; }) { - return async (payload: Args) => { - //@ts-ignore fix later + const { onStop, onNext } = config; + return async (payload: ExecutePayload) => { const task = await callPlugins(payload); if(task.isOk()) { - return config.onNext(payload, task.value) as ExecutePayload; + return onNext(payload, task.value) as Output; } else { - config.onStop?.(payload.module); + onStop?.(payload.module); } }; }; -async function callPlugins({ args, module }: { args: unknown[], module: Module }) { +async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent) { - const result = await plugin.execute.apply(null, arrayifySource(args)); + const result = await plugin.execute(...args, { state, deps }); if(result.isErr()) { return result; } @@ -230,11 +237,11 @@ async function callPlugins({ args, module }: { args: unknown[], module: Module } * Creates an executable task ( execute the command ) if all control plugins are successful * @param onStop emits a failure response to the SernEmitter */ -export function makeModuleExecutor -(onStop: (m: M) => unknown) { - const onNext = ({ args, module }: Args, state: Record) => ({ - task: () => module.execute(...args, state), +export function intoTask(onStop: (m: Module) => unknown) { + const onNext = ({ args, module, deps }: ExecutePayload, state: Record) => ({ module, + args: [...args, { state }], + deps }); return createResultResolver({ onStop, onNext }) } @@ -243,8 +250,6 @@ export const handleCrash = ({ "@sern/errors": err, '@sern/emitter': sem, '@sern/logger': log } : UnpackedDependencies) => pipe(catchError(handleError(err, sem, log)), finalize(() => { - log?.info({ - message: 'A stream closed or reached end of lifetime', - }); + log?.info({ message: 'A stream closed or reached end of lifetime' }); disposeAll(log); })) diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index 5e4c54ea..b56debde 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -2,7 +2,7 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap, EMPTY } from 'rxjs'; import { PayloadType } from '../core/structures/enums'; import { filterTap, sharedEventStream } from '../core/operators' -import { createInteractionHandler, executeModule, makeModuleExecutor } from './event-utils'; +import { createInteractionHandler, executeModule, intoTask, } from './event-utils'; import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; @@ -10,13 +10,10 @@ import { Emitter } from '../core/interfaces'; export default function interactionHandler(deps: UnpackedDependencies, defaultPrefix?: string) { //i wish javascript had clojure destructuring - const { '@sern/modules': modules, - '@sern/client': client, - '@sern/logger': log, - '@sern/errors': err, + const { '@sern/client': client, '@sern/emitter': emitter } = deps const interactionStream$ = sharedEventStream(client as unknown as Emitter, 'interactionCreate'); - const handle = createInteractionHandler(interactionStream$, modules, defaultPrefix); + const handle = createInteractionHandler(interactionStream$, deps, defaultPrefix); const interactionHandler$ = merge(handle(isMessageComponent), handle(isAutocomplete), @@ -24,11 +21,12 @@ export default function interactionHandler(deps: UnpackedDependencies, defaultPr handle(isModal)); return interactionHandler$ .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => - emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)))), + concatMap(intoTask(module => { + emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)) + })), mergeMap(payload => { if(payload) - return executeModule(emitter, log, err, payload) + return executeModule(emitter, payload) return EMPTY; })); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 5005ec21..dc22fd53 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,6 +1,6 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { createMessageHandler, executeModule, makeModuleExecutor } from './event-utils'; +import { createMessageHandler, executeModule, intoTask } from './event-utils'; import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { filterTap, sharedEventStream } from '../core/operators' @@ -21,29 +21,31 @@ function hasPrefix(prefix: string, content: string) { } export default function message( - {"@sern/emitter": emitter, '@sern/errors':err, - '@sern/logger': log, '@sern/client': client, - '@sern/modules': commands}: UnpackedDependencies, + deps: UnpackedDependencies, defaultPrefix: string | undefined ) { + const {"@sern/emitter": emitter, + '@sern/logger': log, + '@sern/client': client } = deps + if (!defaultPrefix) { log?.debug({ message: 'No prefix found. message handler shutting down' }); return EMPTY; } const messageStream$ = sharedEventStream(client as unknown as Emitter, 'messageCreate'); - const handle = createMessageHandler(messageStream$, defaultPrefix, commands); + const handle = createMessageHandler(messageStream$, defaultPrefix, deps); const msgCommands$ = handle(isNonBot(defaultPrefix)); return msgCommands$.pipe( filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), - concatMap(makeModuleExecutor(module => { + concatMap(intoTask(module => { const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); emitter.emit('module.activate', result); })), mergeMap(payload => { if(payload) - return executeModule(emitter, log, err, payload) + return executeModule(emitter, payload) return EMPTY; })); } diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index c58cff42..f6276da4 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -10,19 +10,18 @@ const intoDispatcher = (deps: UnpackedDependencies) => (module : EventModule) => { switch (module.type) { case EventType.Sern: - return eventDispatcher(module, deps['@sern/emitter']); + return eventDispatcher(deps, module, deps['@sern/emitter']); case EventType.Discord: - return eventDispatcher(module, deps['@sern/client']); + return eventDispatcher(deps, module, deps['@sern/client']); case EventType.External: - return eventDispatcher(module, deps[module.emitter]); + return eventDispatcher(deps, module, deps[module.emitter]); case EventType.Cron: { //@ts-ignore const cron = deps['@sern/cron']; cron.addCronModule(module); - return eventDispatcher(module, cron); + return eventDispatcher(deps, module, cron); } - default: - throw Error(SernError.InvalidModuleType + ' while creating event handler'); + default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; @@ -33,7 +32,7 @@ export default async function(deps: UnpackedDependencies, eventDir: string) { for(const plugin of module.plugins) { const res = await plugin.execute({ module, - absPath: module.meta.absPath , + absPath: module.meta.absPath, updateModule: (partial: Partial) => { module = { ...module, ...partial }; return module; diff --git a/src/sern.ts b/src/sern.ts index 41443aae..3cd067de 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -9,6 +9,7 @@ import { presenceHandler } from './handlers/presence'; import { handleCrash } from './handlers/event-utils'; import { useContainerRaw } from './core/ioc/global'; import { UnpackedDependencies } from './types/utility'; +import type { PresenceResult } from './core/presences'; interface Wrapper { commands: string; @@ -49,7 +50,7 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { const time = ((performance.now() - startTime) / 1000).toFixed(2); deps['@sern/logger']?.info({ message: `sern: registered in ${time} s` }); if(presencePath.exists) { - const setPresence = async (p: any) => { + const setPresence = async (p: PresenceResult) => { return deps['@sern/client'].user?.setPresence(p); } presenceHandler(presencePath.path, setPresence).subscribe(); From 735a9e3816f816e68ce74b2a19f3f1200238e5f4 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 19 May 2024 22:50:21 -0500 Subject: [PATCH 48/90] plugin system loking better, tbd type --- src/core/structures/default-services.ts | 2 +- src/handlers/event-utils.ts | 5 ++--- src/handlers/message.ts | 6 +++--- src/types/core-modules.ts | 13 +++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 06b403df..474a6e49 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -24,7 +24,7 @@ export class DefaultErrorHandling implements ErrorHandling { * Version 4.0.0 will internalize this api. Please refrain from using ModuleStore! */ export class DefaultLogging implements Logging { - private date = () => new Date(); + private date() { return new Date() } debug(payload: LogPayload): void { console.debug(`DEBUG: ${this.date().toISOString()} -> ${payload.message}`); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 474b6486..e8e36213 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -55,8 +55,7 @@ export function eventDispatcher(deps: Dependencies, module: Module, source: unkn `${source} cannot be constructed into an event listener`); const execute: OperatorFunction = concatMap(async args => { - if(args) - return module.execute.apply(null, args); + if(args) return module.execute.apply(null, args); }); //@ts-ignore return fromEvent(source, module.name!) @@ -240,7 +239,7 @@ async function callPlugins({ args, module, deps }: ExecutePayload) { export function intoTask(onStop: (m: Module) => unknown) { const onNext = ({ args, module, deps }: ExecutePayload, state: Record) => ({ module, - args: [...args, { state }], + args: [...args, { state, deps }], deps }); return createResultResolver({ onStop, onNext }) diff --git a/src/handlers/message.ts b/src/handlers/message.ts index dc22fd53..6863f744 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -20,13 +20,13 @@ function hasPrefix(prefix: string, content: string) { return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); } -export default function message( +export default function ( deps: UnpackedDependencies, - defaultPrefix: string | undefined + defaultPrefix?: string ) { const {"@sern/emitter": emitter, '@sern/logger': log, - '@sern/client': client } = deps + '@sern/client': client} = deps if (!defaultPrefix) { log?.debug({ message: 'No prefix found. message handler shutting down' }); diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index e1fbebbe..c09f89ff 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -21,7 +21,8 @@ import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './c import { Awaitable, SernEventsMapping } from './utility'; type ToBeDecided = { - result: Record; + state: Record; + deps: Dependencies } export type Processed = T & { name: string; description: string }; @@ -62,12 +63,12 @@ export interface CronEventCommand extends Module { export interface ContextMenuUser extends Module { type: CommandType.CtxUser; - execute: (ctx: UserContextMenuCommandInteraction) => Awaitable; + execute: (ctx: UserContextMenuCommandInteraction, tbd: ToBeDecided) => Awaitable; } export interface ContextMenuMsg extends Module { type: CommandType.CtxMsg; - execute: (ctx: MessageContextMenuCommandInteraction) => Awaitable; + execute: (ctx: MessageContextMenuCommandInteraction, tbd: ToBeDecided) => Awaitable; } export interface ButtonCommand extends Module { @@ -118,21 +119,21 @@ export interface DiscordEventCommand Awaitable; + execute: (ctx: Context, tbd: ToBeDecided) => Awaitable; } export interface SlashCommand extends Module { type: CommandType.Slash; description: string; options?: SernOptionsData[]; - execute: (ctx: Context) => Awaitable; + execute: (ctx: Context, tbd: ToBeDecided) => Awaitable; } export interface BothCommand extends Module { type: CommandType.Both; description: string; options?: SernOptionsData[]; - execute: (ctx: Context) => Awaitable; + execute: (ctx: Context, tbd: ToBeDecided) => Awaitable; } export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand; From 15511a4868841aa5205ed5efb45dacb4949d0d99 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 20 May 2024 00:49:51 -0500 Subject: [PATCH 49/90] porg --- src/core/operators.ts | 1 - src/handlers/event-utils.ts | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/operators.ts b/src/core/operators.ts index 77fa2579..2d06a905 100644 --- a/src/core/operators.ts +++ b/src/core/operators.ts @@ -30,7 +30,6 @@ export const arrayifySource = (src: T) => export const sharedEventStream = (e: Emitter, eventName: string) => (fromEvent(e, eventName) as Observable).pipe(share()); - export function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { return (pload: unknown, caught: Observable) => { // This is done to fit the ErrorHandling contract diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index e8e36213..34264d56 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -197,10 +197,10 @@ export function executeModule( /** * A higher order function that - * - creates a stream of {@link VoidResult} { config.createStream } - * - any failures results to { config.onFailure } being called + * - calls all control plugins. + * - any failures results to { config.onStop } being called * - if all results are ok, the stream is converted to { config.onNext } - * emit config.onSuccess Observable + * config.onNext will be returned if everything is okay. * @param config * @returns receiver function for flattening a stream of data */ From e0f6a4cd16ab5cf6fea0dbe5b9f6a88871c3cf4a Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 20 May 2024 12:21:18 -0500 Subject: [PATCH 50/90] initplugins inject deps, inconspicuos --- src/core/create-plugins.ts | 25 ++-------------- src/core/functions.ts | 44 +++++++++++++---------------- src/core/modules.ts | 10 ++----- src/core/structures/context.ts | 23 ++++++++------- src/handlers/event-utils.ts | 31 ++++++++++++-------- src/handlers/message.ts | 2 +- src/handlers/ready.ts | 16 ++--------- src/handlers/user-defined-events.ts | 20 ++----------- src/index.ts | 3 +- src/types/core-modules.ts | 6 ++-- src/types/core-plugin.ts | 17 +++-------- 11 files changed, 68 insertions(+), 129 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 4bcf269f..3f9d7598 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -1,6 +1,5 @@ -import { CommandType, EventType, PluginType } from './structures/enums'; -import type { Plugin, PluginResult, EventArgs, CommandArgs, InitArgs } from '../types/core-plugin'; -import type { ClientEvents } from 'discord.js'; +import { CommandType, PluginType } from './structures/enums'; +import type { Plugin, PluginResult, CommandArgs, InitArgs } from '../types/core-plugin'; import { err, ok } from './functions'; export function makePlugin( @@ -31,27 +30,7 @@ export function CommandControlPlugin( ) { return makePlugin(PluginType.Control, execute); } -/** - * @since 2.5.0 - */ -export function EventControlPlugin( - execute: (...args: EventArgs) => PluginResult, -) { - return makePlugin(PluginType.Control, execute); -} -/** - * @since 2.5.0 - * @Experimental - * A specialized function for creating control plugins with discord.js ClientEvents. - * Will probably be moved one day! - */ -export function DiscordEventControlPlugin( - name: T, - execute: (...args: ClientEvents[T]) => PluginResult, -) { - return makePlugin(PluginType.Control, execute); -} /** * @since 1.0.0 diff --git a/src/core/functions.ts b/src/core/functions.ts index 02ef466a..20ccb430 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -46,37 +46,31 @@ export function treeSearch( while (_options.length > 0) { const cur = _options.pop()!; switch (cur.type) { - case ApplicationCommandOptionType.Subcommand: - { + case ApplicationCommandOptionType.Subcommand: { subcommands.add(cur.name); for (const option of cur.options ?? []) _options.push(option); - } - break; - case ApplicationCommandOptionType.SubcommandGroup: - { + } break; + case ApplicationCommandOptionType.SubcommandGroup: { for (const command of cur.options ?? []) _options.push(command); - } - break; - default: - { - if ('autocomplete' in cur && cur.autocomplete) { - const choice = iAutocomplete.options.getFocused(true); - assert( 'command' in cur, 'No `command` property found for option ' + cur.name); - if (subcommands.size > 0) { - const parent = iAutocomplete.options.getSubcommand(); - const parentAndOptionMatches = - subcommands.has(parent) && cur.name === choice.name; - if (parentAndOptionMatches) { - return { ...cur, parent }; - } - } else { - if (cur.name === choice.name) { - return { ...cur, parent: undefined }; - } + } break; + default: { + if ('autocomplete' in cur && cur.autocomplete) { + const choice = iAutocomplete.options.getFocused(true); + assert( 'command' in cur, 'No `command` property found for option ' + cur.name); + if (subcommands.size > 0) { + const parent = iAutocomplete.options.getSubcommand(); + const parentAndOptionMatches = + subcommands.has(parent) && cur.name === choice.name; + if (parentAndOptionMatches) { + return { ...cur, parent }; + } + } else { + if (cur.name === choice.name) { + return { ...cur, parent: undefined }; } } } - break; + } break; } } } diff --git a/src/core/modules.ts b/src/core/modules.ts index 3e13c671..06d1bf13 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -1,6 +1,5 @@ import type { ClientEvents } from 'discord.js'; import { EventType } from '../core/structures/enums'; -import type { AnyEventPlugin, } from '../types/core-plugin'; import type { InputCommand, InputEvent, @@ -21,18 +20,14 @@ export function commandModule(mod: InputCommand): Module { plugins, } as Module; } + /** * @since 1.0.0 * The wrapper function to define event modules for sern * @param mod */ export function eventModule(mod: InputEvent): Module { - const [onEvent, plugins] = partitionPlugins(mod.plugins); - return { - ...mod, - plugins, - onEvent, - } as Module; + return mod as Module; } /** Create event modules from discord.js client events, @@ -43,7 +38,6 @@ export function eventModule(mod: InputEvent): Module { */ export function discordEvent(mod: { name: T; - plugins?: AnyEventPlugin[]; execute: (...args: ClientEvents[T]) => Awaitable; }) { return eventModule({ type: EventType.Discord, ...mod, }); diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index f3aa1591..40292df6 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -24,25 +24,26 @@ function fmt(msg: string, prefix?: string): string[] { * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { - prefix: string|undefined; get options() { return this.interaction.options; } - args() { - return { - message: () => { + args(type: 'message'|'interaction', parser?: Function) { + switch(type) { + case 'message': { const [, ...rest] = fmt(this.message.content, this.prefix); - return rest as T; - }, - interaction: () => this.interaction.options + return rest; + }; + case 'interaction': { + return this.interaction.options; + }; } } - protected constructor(protected ctx: Result, prefix?: string) { + protected constructor(protected ctx: Result, + public prefix?: string) { super(ctx); - this.prefix = prefix } public get id(): Snowflake { @@ -52,9 +53,7 @@ export class Context extends CoreContext { } public get channel() { - return safeUnwrap(this.ctx - .map(m => m.channel) - .mapErr(i => i.channel)); + return safeUnwrap(this.ctx.map(m => m.channel).mapErr(i => i.channel)); } public get channelId(): Snowflake { diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 34264d56..edfa9a53 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -17,7 +17,7 @@ import * as Id from '../core/id' import type { Emitter } from '../core/interfaces'; import { PayloadType, SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; -import type { UnpackedDependencies, VoidResult } from '../types/utility'; +import type { UnpackedDependencies } from '../types/utility'; import type { CommandModule, Module, Processed } from '../types/core-modules'; import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; @@ -36,15 +36,9 @@ interface ExecutePayload { function intoPayload(module: Module, deps: Dependencies) { return pipe(map(arrayifySource), - map(args => ({ module, args, deps }))); + map(args => ({ module, args, deps })), + map(p => p.args)); } -const createResult = (deps: Dependencies) => - createResultResolver({ - onNext: (p) => p.args, - onStop: (module) => { - //maybe do something when plugins fail? - } - }); /** * Creates an observable from { source } * @param module @@ -60,7 +54,6 @@ export function eventDispatcher(deps: Dependencies, module: Module, source: unkn //@ts-ignore return fromEvent(source, module.name!) .pipe(intoPayload(module, deps), - concatMap(createResult(deps)), execute); } @@ -218,7 +211,23 @@ export function createResultResolver(config: { } }; }; - +export async function callInitPlugins(module: Module, deps: Dependencies, sEmitter?: Emitter) { + for(const plugin of module.plugins) { + const res = await plugin.execute({ + module, + absPath: module.meta.absPath , + updateModule: (partial: Partial) => { + module = { ...module, ...partial }; + return module; + }, + deps + }); + if(res.isErr()) { + sEmitter?.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + throw Error("Plugin failed with controller.stop()"); + } + } +} async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent) { diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 6863f744..2739e9d9 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -17,7 +17,7 @@ function isNonBot(prefix: string) { function hasPrefix(prefix: string, content: string) { const prefixInContent = content.slice(0, prefix.length); - return (prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0); + return prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0; } export default function ( diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 503301c0..e7cf0106 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -5,6 +5,7 @@ import { PayloadType } from '..'; import { CommandType, SernError } from '../core/structures/enums'; import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; +import { callInitPlugins } from './event-utils'; export default async function(dir: string, deps : UnpackedDependencies) { const { '@sern/client': client, @@ -23,20 +24,7 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - for(const plugin of module.plugins) { - const res = await plugin.execute({ - module, - absPath: module.meta.absPath , - updateModule: (partial: Partial) => { - module = { ...module, ...partial }; - return module; - } - }); - if(res.isErr()) { - sEmitter.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); - throw Error("Plugin failed with controller.stop()"); - } - } + await callInitPlugins(module, deps, sEmitter); // FREEZE! no more writing!! commands.set(module.meta.id, Object.freeze(module)); sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index f6276da4..fecee051 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -1,9 +1,8 @@ -import { EventType, PayloadType, SernError } from '../core/structures/enums'; -import { eventDispatcher, handleCrash } from './event-utils' +import { EventType, SernError } from '../core/structures/enums'; +import { callInitPlugins, eventDispatcher, handleCrash } from './event-utils' import { EventModule, Module } from '../types/core-modules'; import * as Files from '../core/module-loading' import type { UnpackedDependencies } from '../types/utility'; -import { resultPayload } from '../core/functions'; import { from, map, mergeAll } from 'rxjs'; const intoDispatcher = (deps: UnpackedDependencies) => @@ -29,20 +28,7 @@ export default async function(deps: UnpackedDependencies, eventDir: string) { const eventModules: EventModule[] = []; for await (const path of Files.readRecursive(eventDir)) { let { module } = await Files.importModule(path); - for(const plugin of module.plugins) { - const res = await plugin.execute({ - module, - absPath: module.meta.absPath, - updateModule: (partial: Partial) => { - module = { ...module, ...partial }; - return module; - } - }); - if(res.isErr()) { - deps['@sern/emitter'].emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); - throw Error("Plugin failed with controller.stop()"); - } - } + await callInitPlugins(module, deps) eventModules.push(module as EventModule); } from(eventModules) diff --git a/src/index.ts b/src/index.ts index 624de273..96db42d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,8 +32,7 @@ export type { InitPlugin, ControlPlugin, Plugin, - AnyEventPlugin, - AnyCommandPlugin, + AnyPlugin, } from './types/core-plugin'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index c09f89ff..ca618caa 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -17,7 +17,7 @@ import type { } from 'discord.js'; import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' -import { AnyCommandPlugin, AnyEventPlugin, ControlPlugin, InitPlugin } from './core-plugin'; +import { AnyPlugin, ControlPlugin, InitPlugin } from './core-plugin'; import { Awaitable, SernEventsMapping } from './utility'; type ToBeDecided = { @@ -193,12 +193,12 @@ type EventModulesNoPlugins = { }; export type InputEvent = { - [T in EventType]: EventModulesNoPlugins[T] & { plugins?: AnyEventPlugin[] }; + [T in EventType]: EventModulesNoPlugins[T]; }[EventType]; export type InputCommand = { [T in CommandType]: CommandModuleNoPlugins[T] & { - plugins?: AnyCommandPlugin[]; + plugins?: AnyPlugin[]; }; }[CommandType]; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 108d2435..d0bc067c 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -16,13 +16,12 @@ import type { Module, Processed, } from './core-modules'; -import type { Awaitable, Payload } from './utility'; -import type { CommandType, EventType, PluginType } from '../core/structures/enums' +import type { Awaitable } from './utility'; +import type { CommandType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { ButtonInteraction, ChannelSelectMenuInteraction, - ClientEvents, MentionableSelectMenuInteraction, MessageContextMenuCommandInteraction, ModalSubmitInteraction, @@ -37,6 +36,7 @@ export type PluginResult = Awaitable>; export interface InitArgs = Processed> { module: T; absPath: string; + deps: Dependencies updateModule: (module: Partial) => T } export interface Controller { @@ -57,11 +57,9 @@ export interface ControlPlugin { execute: (...args: Args) => PluginResult; } -export type AnyCommandPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; -export type AnyEventPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; +export type AnyPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; export type CommandArgs = CommandArgsMatrix[I] -export type EventArgs = EventArgsMatrix[I] interface CommandArgsMatrix { [CommandType.Text]: [Context]; @@ -77,10 +75,3 @@ interface CommandArgsMatrix { [CommandType.UserSelect]: [UserSelectMenuInteraction]; [CommandType.Modal]: [ModalSubmitInteraction]; } - -interface EventArgsMatrix { - [EventType.Discord]: ClientEvents[keyof ClientEvents]; - [EventType.Sern]: [Payload]; - [EventType.External]: unknown[]; - [EventType.Cron]: unknown[]; -} From e700297bfc7949f10df00919459413f2d1da37ef Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 20 May 2024 19:36:36 -0500 Subject: [PATCH 51/90] fix faiklling test --- package.json | 11 +- src/handlers/event-utils.ts | 33 ++-- src/handlers/message.ts | 8 +- src/handlers/ready.ts | 2 +- src/types/core-modules.ts | 33 ++-- src/types/core-plugin.ts | 25 +-- src/types/dependencies.d.ts | 1 - test/core/create-plugin.test.ts | 5 - test/handlers/dispatchers.test.ts | 27 ++-- yarn.lock | 253 ++++++++++++------------------ 10 files changed, 152 insertions(+), 246 deletions(-) diff --git a/package.json b/package.json index e985a5a7..fd9c29dd 100644 --- a/package.json +++ b/package.json @@ -46,19 +46,10 @@ "@types/node-cron": "^3.0.11", "@typescript-eslint/eslint-plugin": "5.58.0", "@typescript-eslint/parser": "5.59.1", - "discord.js": "^14.11.0", + "discord.js": "^14.x.x", "eslint": "8.39.0", - "prettier": "2.8.8", "typescript": "5.0.2" }, - "prettier": { - "semi": true, - "trailingComma": "all", - "singleQuote": true, - "printWidth": 100, - "tabWidth": 4, - "arrowParens": "avoid" - }, "eslintConfig": { "parser": "@typescript-eslint/parser", "extends": [ diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index edfa9a53..66b47ae7 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -1,17 +1,8 @@ import type { Interaction, Message, BaseInteraction } from 'discord.js'; import { - EMPTY, - Observable, - concatMap, - filter, - throwError, - fromEvent, - map, - type OperatorFunction, - catchError, - finalize, - pipe, - from, + EMPTY, type Observable, concatMap, filter, + throwError, fromEvent, map, type OperatorFunction, + catchError, finalize, pipe, from, } from 'rxjs'; import * as Id from '../core/id' import type { Emitter } from '../core/interfaces'; @@ -49,7 +40,7 @@ export function eventDispatcher(deps: Dependencies, module: Module, source: unkn `${source} cannot be constructed into an event listener`); const execute: OperatorFunction = concatMap(async args => { - if(args) return module.execute.apply(null, args); + if(args) return Reflect.apply(module.execute, null, args); }); //@ts-ignore return fromEvent(source, module.name!) @@ -81,11 +72,7 @@ export function createDispatcher({ module, event, defaultPrefix, deps }: Dispatc switch (module.type) { case CommandType.Slash: case CommandType.Both: { - return { - module, - args: [Context.wrap(event, defaultPrefix)], - deps - }; + return { module, args: [Context.wrap(event, defaultPrefix)], deps }; } default: return { module, args: [event], deps }; } @@ -198,7 +185,7 @@ export function executeModule( * @returns receiver function for flattening a stream of data */ export function createResultResolver(config: { - onStop?: (module: Module) => unknown; + onStop?: (module: Module, err?: string) => unknown; onNext: (args: ExecutePayload, map: Record) => Output; }) { const { onStop, onNext } = config; @@ -207,7 +194,7 @@ export function createResultResolver(config: { if(task.isOk()) { return onNext(payload, task.value) as Output; } else { - onStop?.(payload.module); + onStop?.(payload.module, String(task.error)); } }; }; @@ -231,7 +218,7 @@ export async function callInitPlugins(module: Module, deps: Dependencies, sEmitt async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent) { - const result = await plugin.execute(...args, { state, deps }); + const result = await plugin.execute(...args, { state, deps, type: module.type === CommandType.Text?'text':'slash' }); if(result.isErr()) { return result; } @@ -248,10 +235,10 @@ async function callPlugins({ args, module, deps }: ExecutePayload) { export function intoTask(onStop: (m: Module) => unknown) { const onNext = ({ args, module, deps }: ExecutePayload, state: Record) => ({ module, - args: [...args, { state, deps }], + args: [...args, { state, deps, type: module.type === CommandType.Text?'text':'slash' }], deps }); - return createResultResolver({ onStop, onNext }) + return createResultResolver({ onStop, onNext }); } export const handleCrash = diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 2739e9d9..193a5304 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -20,10 +20,8 @@ function hasPrefix(prefix: string, content: string) { return prefixInContent.localeCompare(prefix, undefined, { sensitivity: 'accent' }) === 0; } -export default function ( - deps: UnpackedDependencies, - defaultPrefix?: string -) { +export default +function (deps: UnpackedDependencies, defaultPrefix?: string) { const {"@sern/emitter": emitter, '@sern/logger': log, '@sern/client': client} = deps @@ -38,7 +36,7 @@ export default function ( const msgCommands$ = handle(isNonBot(defaultPrefix)); return msgCommands$.pipe( - filterTap((e) => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), concatMap(intoTask(module => { const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); emitter.emit('module.activate', result); diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index e7cf0106..41c7af3a 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -2,7 +2,7 @@ import * as Files from '../core/module-loading' import { once } from 'events'; import { resultPayload } from '../core/functions'; import { PayloadType } from '..'; -import { CommandType, SernError } from '../core/structures/enums'; +import { CommandType } from '../core/structures/enums'; import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; import { callInitPlugins } from './event-utils'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index ca618caa..87327456 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -20,10 +20,13 @@ import { Context } from '../core/structures/context' import { AnyPlugin, ControlPlugin, InitPlugin } from './core-plugin'; import { Awaitable, SernEventsMapping } from './utility'; -type ToBeDecided = { +//state, deps, type (very original) +export type SDT = { state: Record; - deps: Dependencies -} + deps: Dependencies; + type: 'slash' | 'text' +}; + export type Processed = T & { name: string; description: string }; export interface Module { @@ -63,47 +66,47 @@ export interface CronEventCommand extends Module { export interface ContextMenuUser extends Module { type: CommandType.CtxUser; - execute: (ctx: UserContextMenuCommandInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: UserContextMenuCommandInteraction, tbd: SDT) => Awaitable; } export interface ContextMenuMsg extends Module { type: CommandType.CtxMsg; - execute: (ctx: MessageContextMenuCommandInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: MessageContextMenuCommandInteraction, tbd: SDT) => Awaitable; } export interface ButtonCommand extends Module { type: CommandType.Button; - execute: (ctx: ButtonInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: ButtonInteraction, tbd: SDT) => Awaitable; } export interface StringSelectCommand extends Module { type: CommandType.StringSelect; - execute: (ctx: StringSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: StringSelectMenuInteraction, tbd: SDT) => Awaitable; } export interface ChannelSelectCommand extends Module { type: CommandType.ChannelSelect; - execute: (ctx: ChannelSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: ChannelSelectMenuInteraction, tbd: SDT) => Awaitable; } export interface RoleSelectCommand extends Module { type: CommandType.RoleSelect; - execute: (ctx: RoleSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: RoleSelectMenuInteraction, tbd: SDT) => Awaitable; } export interface MentionableSelectCommand extends Module { type: CommandType.MentionableSelect; - execute: (ctx: MentionableSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: MentionableSelectMenuInteraction, tbd: SDT) => Awaitable; } export interface UserSelectCommand extends Module { type: CommandType.UserSelect; - execute: (ctx: UserSelectMenuInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: UserSelectMenuInteraction, tbd: SDT) => Awaitable; } export interface ModalSubmitCommand extends Module { type: CommandType.Modal; - execute: (ctx: ModalSubmitInteraction, tbd: ToBeDecided) => Awaitable; + execute: (ctx: ModalSubmitInteraction, tbd: SDT) => Awaitable; } export interface AutocompleteCommand { @@ -119,21 +122,21 @@ export interface DiscordEventCommand Awaitable; + execute: (ctx: Context, tbd: SDT) => Awaitable; } export interface SlashCommand extends Module { type: CommandType.Slash; description: string; options?: SernOptionsData[]; - execute: (ctx: Context, tbd: ToBeDecided) => Awaitable; + execute: (ctx: Context, tbd: SDT) => Awaitable; } export interface BothCommand extends Module { type: CommandType.Both; description: string; options?: SernOptionsData[]; - execute: (ctx: Context, tbd: ToBeDecided) => Awaitable; + execute: (ctx: Context, tbd: SDT) => Awaitable; } export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index d0bc067c..60c0b03d 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -15,6 +15,7 @@ import type { Err, Ok, Result } from 'ts-results-es'; import type { Module, Processed, + SDT, } from './core-modules'; import type { Awaitable } from './utility'; import type { CommandType, PluginType } from '../core/structures/enums' @@ -62,16 +63,16 @@ export type AnyPlugin = ControlPlugin | InitPlugin<[InitArgs>] export type CommandArgs = CommandArgsMatrix[I] interface CommandArgsMatrix { - [CommandType.Text]: [Context]; - [CommandType.Slash]: [Context]; - [CommandType.Both]: [Context]; - [CommandType.CtxMsg]: [MessageContextMenuCommandInteraction]; - [CommandType.CtxUser]: [UserContextMenuCommandInteraction]; - [CommandType.Button]: [ButtonInteraction]; - [CommandType.StringSelect]: [StringSelectMenuInteraction]; - [CommandType.RoleSelect]: [RoleSelectMenuInteraction]; - [CommandType.ChannelSelect]: [ChannelSelectMenuInteraction]; - [CommandType.MentionableSelect]: [MentionableSelectMenuInteraction]; - [CommandType.UserSelect]: [UserSelectMenuInteraction]; - [CommandType.Modal]: [ModalSubmitInteraction]; + [CommandType.Text]: [Context, SDT]; + [CommandType.Slash]: [Context, SDT]; + [CommandType.Both]: [Context, SDT]; + [CommandType.CtxMsg]: [MessageContextMenuCommandInteraction, SDT]; + [CommandType.CtxUser]: [UserContextMenuCommandInteraction, SDT]; + [CommandType.Button]: [ButtonInteraction, SDT]; + [CommandType.StringSelect]: [StringSelectMenuInteraction, SDT]; + [CommandType.RoleSelect]: [RoleSelectMenuInteraction, SDT]; + [CommandType.ChannelSelect]: [ChannelSelectMenuInteraction, SDT]; + [CommandType.MentionableSelect]: [MentionableSelectMenuInteraction, SDT]; + [CommandType.UserSelect]: [UserSelectMenuInteraction, SDT]; + [CommandType.Modal]: [ModalSubmitInteraction, SDT]; } diff --git a/src/types/dependencies.d.ts b/src/types/dependencies.d.ts index cf0fd9bf..ecc76d5d 100644 --- a/src/types/dependencies.d.ts +++ b/src/types/dependencies.d.ts @@ -8,6 +8,5 @@ import { CoreDependencies } from './ioc'; declare global { interface Dependencies extends CoreDependencies {} - } diff --git a/test/core/create-plugin.test.ts b/test/core/create-plugin.test.ts index 37199e81..5236a61b 100644 --- a/test/core/create-plugin.test.ts +++ b/test/core/create-plugin.test.ts @@ -2,17 +2,12 @@ import { describe, it, expect } from 'vitest'; import { CommandControlPlugin, CommandInitPlugin, - EventControlPlugin, EventInitPlugin, } from '../../src/core/create-plugins'; import { PluginType, controller } from '../../src'; describe('create-plugins', () => { it('should make proper control plugins', () => { - const pl = EventControlPlugin(() => controller.next()); - expect(pl).to.have.all.keys(['type', 'execute']); - expect(pl.type).toBe(PluginType.Control); - expect(pl.execute).an('function'); const pl2 = CommandControlPlugin(() => controller.next()); expect(pl2).to.have.all.keys(['type', 'execute']); expect(pl2.type).toBe(PluginType.Control); diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index e9a1544d..325eff38 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -1,7 +1,6 @@ import { beforeEach, describe, expect, vi, it } from 'vitest'; import { eventDispatcher } from '../../src/handlers/event-utils'; import { faker } from '@faker-js/faker'; -import { TestScheduler } from 'rxjs/testing'; import { Module } from '../../src/types/core-modules'; import { Processed } from '../../src/types/core-modules'; import { EventEmitter } from 'events'; @@ -19,12 +18,13 @@ function createRandomModule(): Processed { }; } -const testScheduler = new TestScheduler((actual, expected) => { - // asserting the two objects are equal - required - // for TestScheduler assertions to work via your test framework - // e.g. using chai. - expect(actual).deep.equal(expected); -}); +function mockDeps() { + return { + '@sern/client': {} + } +} + + describe('eventDispatcher standard', () => { let m: Processed; @@ -35,19 +35,10 @@ describe('eventDispatcher standard', () => { }); it('should throw', () => { - expect(() => eventDispatcher(m, 'not event emitter')).toThrowError(); + expect(() => eventDispatcher(mockDeps(), m, 'not event emitter')).toThrowError(); }); it("Shouldn't throw", () => { - expect(() => eventDispatcher(m, ee)).not.toThrowError(); + expect(() => eventDispatcher(mockDeps(), m, ee)).not.toThrowError(); }); - //TODO -// it('Should be called once', () => { -// const s = eventDispatcher(m, ee); -// console.log(m) -// s.subscribe(); -// ee.emit(m.name); -// console.log(m.execute) -// expect(m.execute).toHaveBeenCalledOnce(); -// }); }); diff --git a/yarn.lock b/yarn.lock index 25b4e639..13daa980 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,18 +12,18 @@ __metadata: languageName: node linkType: hard -"@discordjs/builders@npm:^1.7.0": - version: 1.7.0 - resolution: "@discordjs/builders@npm:1.7.0" - dependencies: - "@discordjs/formatters": ^0.3.3 - "@discordjs/util": ^1.0.2 - "@sapphire/shapeshift": ^3.9.3 - discord-api-types: 0.37.61 +"@discordjs/builders@npm:^1.8.1": + version: 1.8.1 + resolution: "@discordjs/builders@npm:1.8.1" + dependencies: + "@discordjs/formatters": ^0.4.0 + "@discordjs/util": ^1.1.0 + "@sapphire/shapeshift": ^3.9.7 + discord-api-types: 0.37.83 fast-deep-equal: ^3.1.3 - ts-mixer: ^6.0.3 + ts-mixer: ^6.0.4 tslib: ^2.6.2 - checksum: 837e7643fc8396e4914bbbfbbfa1232ab7109c931884e8df45cd7356944633590f710a18513d30a10de1b6686ed5166df702bde0c4511fb0cbcac897edd9e56a + checksum: 21e826004ddddf6f9717cbdacafe4ff748d03103634d82883c66f605b068a5ae12a952aaa2558a2c21f3ec717427a12bb9b57f0f8670f8a4ab6a0757bb3b229d languageName: node linkType: hard @@ -34,60 +34,60 @@ __metadata: languageName: node linkType: hard -"@discordjs/collection@npm:^2.0.0": - version: 2.0.0 - resolution: "@discordjs/collection@npm:2.0.0" - checksum: c2d05fa2b9a27bb64e93e2836bbe44c835d21f85e28cd934f6e2a81fef423ab0415968cca9d066b83347539edc8ea9afa8075d80bd62594e39f09eb881052c49 +"@discordjs/collection@npm:^2.1.0": + version: 2.1.0 + resolution: "@discordjs/collection@npm:2.1.0" + checksum: ebe1a32769296f14a38b2c718c7e0d00830e37e68e59a3683aa0f7c25adf9487ebaca3ac3f78fd60e2c89cf314b7891312cac36e3b0885cceb4d2a677ae7d19b languageName: node linkType: hard -"@discordjs/formatters@npm:^0.3.3": - version: 0.3.3 - resolution: "@discordjs/formatters@npm:0.3.3" +"@discordjs/formatters@npm:^0.4.0": + version: 0.4.0 + resolution: "@discordjs/formatters@npm:0.4.0" dependencies: - discord-api-types: 0.37.61 - checksum: a844628094a6effa8ac4e4a4ea9082d5c89e6cae6bbd18e60abd410769e5ea18f64aa2db8623aa3c8c572084368f6c2e27cc2d72af640aff5e4ee7fc42132c60 + discord-api-types: 0.37.83 + checksum: 130ab7ba104635d7d0f92f4c3de67dbc60cdab004e9db605e0f2c7f410a9808df8776e4d5d45632597dc7257713dc77bb616ee25bb0827117247b6bebfe35921 languageName: node linkType: hard -"@discordjs/rest@npm:^2.1.0": - version: 2.2.0 - resolution: "@discordjs/rest@npm:2.2.0" - dependencies: - "@discordjs/collection": ^2.0.0 - "@discordjs/util": ^1.0.2 - "@sapphire/async-queue": ^1.5.0 - "@sapphire/snowflake": ^3.5.1 - "@vladfrangu/async_event_emitter": ^2.2.2 - discord-api-types: 0.37.61 - magic-bytes.js: ^1.5.0 +"@discordjs/rest@npm:^2.3.0": + version: 2.3.0 + resolution: "@discordjs/rest@npm:2.3.0" + dependencies: + "@discordjs/collection": ^2.1.0 + "@discordjs/util": ^1.1.0 + "@sapphire/async-queue": ^1.5.2 + "@sapphire/snowflake": ^3.5.3 + "@vladfrangu/async_event_emitter": ^2.2.4 + discord-api-types: 0.37.83 + magic-bytes.js: ^1.10.0 tslib: ^2.6.2 - undici: 5.27.2 - checksum: 29a14ecf3282ae3306883f1f6c870693d0ecacd080c5b66a72e31487a8070655807a80a8bf09bebea4f73e631439abc5121dfa38016ca0ccbe3f68c0f7ffc80e + undici: 6.13.0 + checksum: 01564bf108c359f5650318ccadc51bf762c99df56de865192b25adef4331c0729886e84b4ebd10dfc57818b97ff891f1857873811e7a2326d24fd0bf892a0201 languageName: node linkType: hard -"@discordjs/util@npm:^1.0.2": - version: 1.0.2 - resolution: "@discordjs/util@npm:1.0.2" - checksum: 320d7e125981001160d413ae56e76e60447dce102010b80e3b1b16d885be765df5ae2551aa79fdc4d435a82361ed72246b44251f0c1f7a8fef7056a4481d5609 +"@discordjs/util@npm:^1.1.0": + version: 1.1.0 + resolution: "@discordjs/util@npm:1.1.0" + checksum: b4db3fc6017986cd0e7fd6aa50e890e1259e79c6e0ff9c07685a86b2c22409a42f146f282d907885444f37ca596220c166d8be11851fab7f9e2c1ee932fd524e languageName: node linkType: hard -"@discordjs/ws@npm:^1.0.2": - version: 1.0.2 - resolution: "@discordjs/ws@npm:1.0.2" - dependencies: - "@discordjs/collection": ^2.0.0 - "@discordjs/rest": ^2.1.0 - "@discordjs/util": ^1.0.2 - "@sapphire/async-queue": ^1.5.0 - "@types/ws": ^8.5.9 - "@vladfrangu/async_event_emitter": ^2.2.2 - discord-api-types: 0.37.61 +"@discordjs/ws@npm:^1.1.0": + version: 1.1.0 + resolution: "@discordjs/ws@npm:1.1.0" + dependencies: + "@discordjs/collection": ^2.1.0 + "@discordjs/rest": ^2.3.0 + "@discordjs/util": ^1.1.0 + "@sapphire/async-queue": ^1.5.2 + "@types/ws": ^8.5.10 + "@vladfrangu/async_event_emitter": ^2.2.4 + discord-api-types: 0.37.83 tslib: ^2.6.2 - ws: ^8.14.2 - checksum: 2564d3ff00d04d7638955c8c9a9f6234c50168fbe8243140bc458dc9ffa39ad5063e7d5762cdce71bb8bcf70b6353c28b8531e40f54568706898e92bc8748590 + ws: ^8.16.0 + checksum: a187977572f028d0d92bed16e25ad0b4cb86025372a5f632a15a00d3d0c8ad27a264530c364fee2ca6e5f3637ccf970b8af3e6009ec5ad193d2f3211ab70a133 languageName: node linkType: hard @@ -140,13 +140,6 @@ __metadata: languageName: node linkType: hard -"@fastify/busboy@npm:^2.0.0": - version: 2.1.0 - resolution: "@fastify/busboy@npm:2.1.0" - checksum: 3233abd10f73e50668cb4bb278a79b7b3fadd30215ac6458299b0e5a09a29c3586ec07597aae6bd93f5cbedfcef43a8aeea51829cd28fc13850cdbcd324c28d5 - languageName: node - linkType: hard - "@humanwhocodes/config-array@npm:^0.11.8": version: 0.11.11 resolution: "@humanwhocodes/config-array@npm:0.11.11" @@ -199,34 +192,27 @@ __metadata: languageName: node linkType: hard -"@sapphire/async-queue@npm:^1.5.0": - version: 1.5.0 - resolution: "@sapphire/async-queue@npm:1.5.0" - checksum: 983dbd1fd1b1798496e5edb6a0db7e4d90015160e1028f20475eab0a92625513f1e8d938bc0305811a9cec461c94e01b1e4191615ff03ba49356f568f3255250 +"@sapphire/async-queue@npm:^1.5.2": + version: 1.5.2 + resolution: "@sapphire/async-queue@npm:1.5.2" + checksum: 6252e72254f33c91da4887e324f17b59708b12c603216cc45f001460fd33265844301de47ab67c8caf8383ee280b39c8427ede242bd3b50b6ccdf13a386a5f1b languageName: node linkType: hard -"@sapphire/shapeshift@npm:^3.9.3": - version: 3.9.4 - resolution: "@sapphire/shapeshift@npm:3.9.4" +"@sapphire/shapeshift@npm:^3.9.7": + version: 3.9.7 + resolution: "@sapphire/shapeshift@npm:3.9.7" dependencies: fast-deep-equal: ^3.1.3 lodash: ^4.17.21 - checksum: 680a06823f899753c230d676a0c4c4b45e5575329d3598fb243dd5777c491955a62dcba94aac35770327a5a1103ddee6ceb8fa99c6b88de3cdd313fe3bafb2d3 - languageName: node - linkType: hard - -"@sapphire/snowflake@npm:3.5.1": - version: 3.5.1 - resolution: "@sapphire/snowflake@npm:3.5.1" - checksum: 8fc025020adab1a7a1a5d2cf07704d598cc1977b50e5fcd3a5dd239f00934dc936d3a4d5ae336e71d8bf1d88ec27aa814b34de79e38ff097b7b9ba5a7977a683 + checksum: a36032ff8fc54056ea21e0cdbbea84c3d80c0c0fb19b2685e14e29111ab9c1172c9273e1e54d49e2a62ba5a393f18b3dab9330d34b97d3519d572e32dd64913d languageName: node linkType: hard -"@sapphire/snowflake@npm:^3.5.1": - version: 3.5.2 - resolution: "@sapphire/snowflake@npm:3.5.2" - checksum: f88ee6b167abd83868092b71d68ad36599e922948d1b77ba694c1e13afafc46d4b07914d86ad5af6841cb4b95ceaffd940affe56576362a1c7a5d28a4344f3e4 +"@sapphire/snowflake@npm:3.5.3, @sapphire/snowflake@npm:^3.5.3": + version: 3.5.3 + resolution: "@sapphire/snowflake@npm:3.5.3" + checksum: 821add76877e2786ddb1b5cd3ee5de130610b82014972d91a99b4b7ce5475839b9a26f94de322f48a66f9ba2e2c578ffe46a60d06cbb9a36fd8fb96ef78be248 languageName: node linkType: hard @@ -240,10 +226,9 @@ __metadata: "@typescript-eslint/eslint-plugin": 5.58.0 "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 - discord.js: ^14.11.0 + discord.js: ^14.x.x eslint: 8.39.0 node-cron: ^3.0.3 - prettier: 2.8.8 rxjs: ^7.8.0 ts-results-es: ^4.1.0 typescript: 5.0.2 @@ -264,14 +249,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 20.5.9 - resolution: "@types/node@npm:20.5.9" - checksum: 717490e94131722144878b4ca1a963ede1673bb8f2ef78c2f5b50b918df6dc9b35e7f8283e5c2a7a9f137730f7c08dc6228e53d4494a94c9ee16881e6ce6caed - languageName: node - linkType: hard - -"@types/node@npm:^20.0.0": +"@types/node@npm:*, @types/node@npm:^20.0.0": version: 20.12.12 resolution: "@types/node@npm:20.12.12" dependencies: @@ -287,16 +265,7 @@ __metadata: languageName: node linkType: hard -"@types/ws@npm:8.5.9": - version: 8.5.9 - resolution: "@types/ws@npm:8.5.9" - dependencies: - "@types/node": "*" - checksum: 83f436b731d2cdc49a45ced31a0a65cdd2e39c24d7b882776c26efa190dad6553e266d624c7a7089f36ad3ed471e02e729f3219282c80689b435f665df4a2b0b - languageName: node - linkType: hard - -"@types/ws@npm:^8.5.9": +"@types/ws@npm:^8.5.10": version: 8.5.10 resolution: "@types/ws@npm:8.5.10" dependencies: @@ -471,7 +440,7 @@ __metadata: languageName: node linkType: hard -"@vladfrangu/async_event_emitter@npm:^2.2.2": +"@vladfrangu/async_event_emitter@npm:^2.2.4": version: 2.2.4 resolution: "@vladfrangu/async_event_emitter@npm:2.2.4" checksum: ff65ebc4d89639adecd249e24e4f6f97b7696404f2a4461160efdff628d91de543e982727c18de62a4edada3f66381b5a3cd1d4f4f33098075d839c1b4f46979 @@ -643,32 +612,30 @@ __metadata: languageName: node linkType: hard -"discord-api-types@npm:0.37.61": - version: 0.37.61 - resolution: "discord-api-types@npm:0.37.61" - checksum: fe33d528e31a6de0bab2afb43d0e058957a6da6cfc4d797943fac83aeb8d07543dc0f85cad3c4e6789cbbac0c7ca49dae5ac465224b129c7acb716097fa0b081 +"discord-api-types@npm:0.37.83": + version: 0.37.83 + resolution: "discord-api-types@npm:0.37.83" + checksum: ab2a31188352d9c742f09a114a95322e7f7de90199cb9f5571f7f5ac25765e7abc9b83c15c14d513ffc5e1d63d9e3ea5ff088fa8a1c5d9c1e1f395b27027cef0 languageName: node linkType: hard -"discord.js@npm:^14.11.0": - version: 14.14.1 - resolution: "discord.js@npm:14.14.1" +"discord.js@npm:^14.x.x": + version: 14.15.2 + resolution: "discord.js@npm:14.15.2" dependencies: - "@discordjs/builders": ^1.7.0 + "@discordjs/builders": ^1.8.1 "@discordjs/collection": 1.5.3 - "@discordjs/formatters": ^0.3.3 - "@discordjs/rest": ^2.1.0 - "@discordjs/util": ^1.0.2 - "@discordjs/ws": ^1.0.2 - "@sapphire/snowflake": 3.5.1 - "@types/ws": 8.5.9 - discord-api-types: 0.37.61 + "@discordjs/formatters": ^0.4.0 + "@discordjs/rest": ^2.3.0 + "@discordjs/util": ^1.1.0 + "@discordjs/ws": ^1.1.0 + "@sapphire/snowflake": 3.5.3 + discord-api-types: 0.37.83 fast-deep-equal: 3.1.3 lodash.snakecase: 4.1.1 tslib: 2.6.2 - undici: 5.27.2 - ws: 8.14.2 - checksum: 651e61861ae33e6ec3903e72a8bf229caae5dab73f8d409c3673430cafd9c438a0dd59983242bdcff47bab50da39f7a04da5b586c35b396c102e8e87637076e5 + undici: 6.13.0 + checksum: a6ff7f014996fbea36f7fc7a8ce03f31ded8f3f434ba6c96173721d1d0e18963fcf59c4f00298fd2f01f523bf578582843f80bd99328bade5c4e2b31f82ae368 languageName: node linkType: hard @@ -1155,10 +1122,10 @@ __metadata: languageName: node linkType: hard -"magic-bytes.js@npm:^1.5.0": - version: 1.7.0 - resolution: "magic-bytes.js@npm:1.7.0" - checksum: c36cc3fa828ff27fc752998593dde7be8083b3608e0acec3b5091221fdea2d43b16c13ed368d5c406a120eb3812bcfe060d0aec5919e711ea780088c5b379050 +"magic-bytes.js@npm:^1.10.0": + version: 1.10.0 + resolution: "magic-bytes.js@npm:1.10.0" + checksum: c10e7fc3fe584e4b0767554fb6a12dfc4a9db0782d5005cbdd46bc9b36a8bb420f5266a4b02e089ea4db587937fde289ea467a7a379ad969fb906bf4a0ec3f38 languageName: node linkType: hard @@ -1310,15 +1277,6 @@ __metadata: languageName: node linkType: hard -"prettier@npm:2.8.8": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" - bin: - prettier: bin-prettier.js - checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 - languageName: node - linkType: hard - "punycode@npm:^2.1.0": version: 2.3.0 resolution: "punycode@npm:2.3.0" @@ -1451,10 +1409,10 @@ __metadata: languageName: node linkType: hard -"ts-mixer@npm:^6.0.3": - version: 6.0.3 - resolution: "ts-mixer@npm:6.0.3" - checksum: 7fbaba0a413bf817835a6a23d46bccf4192dd4d7345b6bae9d594c88acffac35bf4995ef3cce753090c8abcdf2afd16dba8899365584a1f960ccc2a15bf2e2d6 +"ts-mixer@npm:^6.0.4": + version: 6.0.4 + resolution: "ts-mixer@npm:6.0.4" + checksum: 36b1af526befd74345e736e9aa16f5c28876ebcea07784da14d929149fd7e6028cfd2fe9304c8efe8cb91b588443a9cc9e991df58e4c6e602326edbaae2af3ab languageName: node linkType: hard @@ -1533,12 +1491,10 @@ __metadata: languageName: node linkType: hard -"undici@npm:5.27.2": - version: 5.27.2 - resolution: "undici@npm:5.27.2" - dependencies: - "@fastify/busboy": ^2.0.0 - checksum: 22bbdd763798700979986546d70072b67223189353d2a811efa9c6e44476161a0d1781ffe24115221f69a1b344b95d5926bd39a6eb760a2cd8804781cec0c5eb +"undici@npm:6.13.0": + version: 6.13.0 + resolution: "undici@npm:6.13.0" + checksum: 47495e93aceeab18664678b6fb0ea2395b7c13a33d2ed4f7f36eb9be9ec5cd6f8e3a4ddaec18127da5e2012e5d7666ca824c7dc70af606dcfe6fdb8441ee3a7a languageName: node linkType: hard @@ -1578,24 +1534,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.14.2": - version: 8.14.2 - resolution: "ws@npm:8.14.2" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b - languageName: node - linkType: hard - -"ws@npm:^8.14.2": - version: 8.15.1 - resolution: "ws@npm:8.15.1" +"ws@npm:^8.16.0": + version: 8.17.0 + resolution: "ws@npm:8.17.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -1604,7 +1545,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 8c67365f6e6134278ad635d558bfce466d7ef7543a043baea333aaa430429f0af8a130c0c36e7dd78f918d68167a659ba9b5067330b77c4b279e91533395952b + checksum: 147ef9eab0251364e1d2c55338ad0efb15e6913923ccbfdf20f7a8a6cb8f88432bcd7f4d8f66977135bfad35575644f9983201c1a361019594a4e53977bf6d4e languageName: node linkType: hard From 88598b0948943770620cdff32c44e55ba5c93829 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 21 May 2024 00:35:19 -0500 Subject: [PATCH 52/90] fix initPlugins not reassigning --- src/core/ioc/container.ts | 1 - src/handlers/event-utils.ts | 10 ++++++---- src/handlers/ready.ts | 7 ++++--- test/handlers/dispatchers.test.ts | 1 - 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 8a41e705..2a959fed 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -26,7 +26,6 @@ export class Container { } private registerHooks(hookname: string, insert: object) { if(hasCallableMethod(insert, hookname)) { - console.log(hookname) //@ts-ignore this.addHook(hookname, () => insert[hookname]()) } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 66b47ae7..26cc93ac 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -199,13 +199,14 @@ export function createResultResolver(config: { }; }; export async function callInitPlugins(module: Module, deps: Dependencies, sEmitter?: Emitter) { - for(const plugin of module.plugins) { + let _module = module; + for(const plugin of _module.plugins ?? []) { const res = await plugin.execute({ module, - absPath: module.meta.absPath , + absPath: _module.meta.absPath , updateModule: (partial: Partial) => { - module = { ...module, ...partial }; - return module; + _module = { ..._module, ...partial }; + return _module; }, deps }); @@ -214,6 +215,7 @@ export async function callInitPlugins(module: Module, deps: Dependencies, sEmitt throw Error("Plugin failed with controller.stop()"); } } + return _module } async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 41c7af3a..c8fa11bc 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -24,10 +24,11 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - await callInitPlugins(module, deps, sEmitter); + const resultModule = await callInitPlugins(module, deps, sEmitter); + console.log(resultModule) // FREEZE! no more writing!! - commands.set(module.meta.id, Object.freeze(module)); - sEmitter.emit('module.register', resultPayload(PayloadType.Success, module)); + commands.set(resultModule.meta.id, Object.freeze(resultModule)); + sEmitter.emit('module.register', resultPayload(PayloadType.Success, resultModule)); } sEmitter.emit('modulesLoaded'); } diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts index 325eff38..9337d7e8 100644 --- a/test/handlers/dispatchers.test.ts +++ b/test/handlers/dispatchers.test.ts @@ -24,7 +24,6 @@ function mockDeps() { } } - describe('eventDispatcher standard', () => { let m: Processed; From 7f4004e04376c9c6ee40128006cdcd8776d8fe41 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 21 May 2024 01:18:20 -0500 Subject: [PATCH 53/90] parsingParams kinda --- src/core/id.ts | 23 ++++++++++++++++++++--- src/handlers/event-utils.ts | 11 ++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/core/id.ts b/src/core/id.ts index 173d25cd..41cec965 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -1,6 +1,15 @@ import { ApplicationCommandType, ComponentType, Interaction, InteractionType } from 'discord.js'; import { CommandType, EventType } from './structures/enums'; +const parseParams = (event: { customId: string }, id: string) => { + const hasSlash = event.customId.indexOf('/') + if(hasSlash === -1) { + return { id }; + } + const baseid = event.customId.substring(0, hasSlash); + const params = event.customId.substring(hasSlash+1); + return { id: baseid, params } +} /** * Construct unique ID for a given interaction object. * @param event The interaction object for which to create an ID. @@ -8,12 +17,20 @@ import { CommandType, EventType } from './structures/enums'; */ export function reconstruct(event: T) { switch (event.type) { - case InteractionType.MessageComponent: return [`${event.customId}_C${event.componentType}`]; + case InteractionType.MessageComponent: { + let id = `${event.customId}_C${event.componentType}`; + const data = parseParams(event, id) + return [data]; + } case InteractionType.ApplicationCommand: case InteractionType.ApplicationCommandAutocomplete: - return [`${event.commandName}_A${event.commandType}`, `${event.commandName}_B`]; + return [{ id: `${event.commandName}_A${event.commandType}` }, { id: `${event.commandName}_B` }]; //Modal interactions are classified as components for sern - case InteractionType.ModalSubmit: return [`${event.customId}_M`]; + case InteractionType.ModalSubmit: { + let id = `${event.customId}_M`; + const data = parseParams(event, id); + return [data]; + } } } /** diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 26cc93ac..6d51fe3e 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -119,9 +119,9 @@ export function createInteractionHandler( async event => { const possibleIds = Id.reconstruct(event); let modules = possibleIds - .map(id => mg.get(id)) + .map(({ id }) => mg.get(id)) .filter((id): id is Module => id !== undefined); - + if(modules.length == 0) { return Err.EMPTY; } @@ -198,12 +198,12 @@ export function createResultResolver(config: { } }; }; + export async function callInitPlugins(module: Module, deps: Dependencies, sEmitter?: Emitter) { let _module = module; for(const plugin of _module.plugins ?? []) { const res = await plugin.execute({ - module, - absPath: _module.meta.absPath , + module, absPath: _module.meta.absPath , updateModule: (partial: Partial) => { _module = { ..._module, ...partial }; return _module; @@ -217,9 +217,10 @@ export async function callInitPlugins(module: Module, deps: Dependencies, sEmitt } return _module } + async function callPlugins({ args, module, deps }: ExecutePayload) { let state = {}; - for(const plugin of module.onEvent) { + for(const plugin of module.onEvent??[]) { const result = await plugin.execute(...args, { state, deps, type: module.type === CommandType.Text?'text':'slash' }); if(result.isErr()) { return result; From 814fc4f01dcb910acd480b302e19a9df9e3adb3f Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 21 May 2024 01:41:34 -0500 Subject: [PATCH 54/90] proper mapping --- src/core/id.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/id.ts b/src/core/id.ts index 41cec965..17cf579d 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -1,14 +1,14 @@ import { ApplicationCommandType, ComponentType, Interaction, InteractionType } from 'discord.js'; import { CommandType, EventType } from './structures/enums'; -const parseParams = (event: { customId: string }, id: string) => { +const parseParams = (event: { customId: string }, id: string, append: string) => { const hasSlash = event.customId.indexOf('/') if(hasSlash === -1) { return { id }; } const baseid = event.customId.substring(0, hasSlash); const params = event.customId.substring(hasSlash+1); - return { id: baseid, params } + return { id: baseid+append, params } } /** * Construct unique ID for a given interaction object. @@ -18,8 +18,9 @@ const parseParams = (event: { customId: string }, id: string) => { export function reconstruct(event: T) { switch (event.type) { case InteractionType.MessageComponent: { - let id = `${event.customId}_C${event.componentType}`; - const data = parseParams(event, id) + let id = event.customId; + const data = parseParams(event, id, `_C${event.componentType}`) + console.log(data) return [data]; } case InteractionType.ApplicationCommand: @@ -27,8 +28,8 @@ export function reconstruct(event: T) { return [{ id: `${event.commandName}_A${event.commandType}` }, { id: `${event.commandName}_B` }]; //Modal interactions are classified as components for sern case InteractionType.ModalSubmit: { - let id = `${event.customId}_M`; - const data = parseParams(event, id); + let id = `${event.customId}`; + const data = parseParams(event, id, '_M'); return [data]; } } From 327e56fc1ca3ba01838c4c2160c7a5ce81d4c673 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 22 May 2024 00:44:59 -0500 Subject: [PATCH 55/90] dynamic customIds --- src/core/id.ts | 1 - src/core/ioc/base.ts | 2 +- src/handlers/event-utils.ts | 31 +++++++++++++++---------------- src/handlers/ready.ts | 3 +-- src/types/core-modules.ts | 3 ++- src/types/core-plugin.ts | 3 ++- src/types/ioc.ts | 10 ++++++---- 7 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/core/id.ts b/src/core/id.ts index 17cf579d..9591b3e0 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -20,7 +20,6 @@ export function reconstruct(event: T) { case InteractionType.MessageComponent: { let id = event.customId; const data = parseParams(event, id, `_C${event.componentType}`) - console.log(data) return [data]; } case InteractionType.ApplicationCommand: diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 3ac05c3e..7c0c4809 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -65,7 +65,7 @@ async function composeRoot( conf: DependencyConfiguration, ) { //container should have no client or logger yet. - const hasLogger = conf.exclude?.has('@sern/logger'); + const hasLogger = container.hasKey('@sern/logger'); if (!hasLogger) { __add_container('@sern/logger', new __Services.DefaultLogging()); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 6d51fe3e..1a876a15 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -21,7 +21,8 @@ import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' interface ExecutePayload { module: Module; args: unknown[]; - deps: Dependencies + deps: Dependencies; + params?: string; [key: string]: unknown } @@ -52,9 +53,10 @@ interface DispatchPayload { module: Processed; event: BaseInteraction; defaultPrefix?: string; - deps: Dependencies + deps: Dependencies; + params?: string }; -export function createDispatcher({ module, event, defaultPrefix, deps }: DispatchPayload): ExecutePayload { +export function createDispatcher({ module, event, defaultPrefix, deps, params }: DispatchPayload): ExecutePayload { assert.ok(CommandType.Text !== module.type, SernError.MismatchEvent + 'Found text command in interaction stream'); @@ -68,13 +70,12 @@ export function createDispatcher({ module, event, defaultPrefix, deps }: Dispatc args: [event], deps }; } - switch (module.type) { case CommandType.Slash: case CommandType.Both: { return { module, args: [Context.wrap(event, defaultPrefix)], deps }; } - default: return { module, args: [event], deps }; + default: return { module, args: [event], deps, params }; } } function createGenericHandler( @@ -113,24 +114,22 @@ export function createInteractionHandler( deps: Dependencies, defaultPrefix?: string ) { - const mg = deps['@sern/modules'] + const mg = deps['@sern/modules']; return createGenericHandler, void>>( source, async event => { const possibleIds = Id.reconstruct(event); let modules = possibleIds - .map(({ id }) => mg.get(id)) - .filter((id): id is Module => id !== undefined); + .map(({ id, params }) => ({ module: mg.get(id), params })) + .filter((id) => id !== undefined); if(modules.length == 0) { return Err.EMPTY; } - const [ module ] = modules; + const [{module, params}] = modules; return Ok(createDispatcher({ module: module as Processed, - event, - defaultPrefix, - deps + event, defaultPrefix, deps, params })); }); } @@ -218,10 +217,10 @@ export async function callInitPlugins(module: Module, deps: Dependencies, sEmitt return _module } -async function callPlugins({ args, module, deps }: ExecutePayload) { +async function callPlugins({ args, module, deps, params }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent??[]) { - const result = await plugin.execute(...args, { state, deps, type: module.type === CommandType.Text?'text':'slash' }); + const result = await plugin.execute(...args, { state, deps, params, type: module.type }); if(result.isErr()) { return result; } @@ -236,9 +235,9 @@ async function callPlugins({ args, module, deps }: ExecutePayload) { * @param onStop emits a failure response to the SernEmitter */ export function intoTask(onStop: (m: Module) => unknown) { - const onNext = ({ args, module, deps }: ExecutePayload, state: Record) => ({ + const onNext = ({ args, module, deps, params }: ExecutePayload, state: Record) => ({ module, - args: [...args, { state, deps, type: module.type === CommandType.Text?'text':'slash' }], + args: [...args, { state, deps, params, type: module.type }], deps }); return createResultResolver({ onStop, onNext }); diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index c8fa11bc..4dbbdee2 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -1,5 +1,5 @@ import * as Files from '../core/module-loading' -import { once } from 'events'; +import { once } from 'node:events'; import { resultPayload } from '../core/functions'; import { PayloadType } from '..'; import { CommandType } from '../core/structures/enums'; @@ -25,7 +25,6 @@ export default async function(dir: string, deps : UnpackedDependencies) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } const resultModule = await callInitPlugins(module, deps, sEmitter); - console.log(resultModule) // FREEZE! no more writing!! commands.set(resultModule.meta.id, Object.freeze(resultModule)); sEmitter.emit('module.register', resultPayload(PayloadType.Success, resultModule)); diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 87327456..911e5828 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -24,7 +24,8 @@ import { Awaitable, SernEventsMapping } from './utility'; export type SDT = { state: Record; deps: Dependencies; - type: 'slash' | 'text' + type: 'slash' | 'text', + params?: string }; export type Processed = T & { name: string; description: string }; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 60c0b03d..ce3ac059 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -13,12 +13,13 @@ import type { Err, Ok, Result } from 'ts-results-es'; import type { + CommandModuleDefs, Module, Processed, SDT, } from './core-modules'; import type { Awaitable } from './utility'; -import type { CommandType, PluginType } from '../core/structures/enums' +import type { CommandType, EventType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { ButtonInteraction, diff --git a/src/types/ioc.ts b/src/types/ioc.ts index d3aa6711..3803a644 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -21,11 +21,13 @@ export type IntoDependencies = { /** * @deprecated This old signature will be incompatible with future versions of sern. + * ```ts + * To switch your old code: + await makeDependencies(({ add }) => { + add('@sern/client', new Client()) + }) + * ``` */ export interface DependencyConfiguration { - /* - * @deprecated. Loggers will be opt-in the future - */ - exclude?: Set<'@sern/logger'>; build: (root: Container) => Container; } From 1de21b8b37a995f30ba514612c6feb0713509720 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 22 May 2024 23:33:37 -0500 Subject: [PATCH 56/90] handling customId params working --- src/core/id.ts | 4 +- src/core/ioc/base.ts | 75 ++++----------- src/core/structures/context.ts | 8 +- src/handlers/event-utils.ts | 11 ++- src/handlers/ready.ts | 2 +- src/handlers/user-defined-events.ts | 5 +- test/core/functions.test.ts | 40 ++------ test/core/id.test.ts | 78 +++++++++++++++- test/handlers/dispatchers.test.ts | 43 --------- test/handlers/index.test.ts | 136 ++++++++++++++++++++++++++++ 10 files changed, 255 insertions(+), 147 deletions(-) delete mode 100644 test/handlers/dispatchers.test.ts create mode 100644 test/handlers/index.test.ts diff --git a/src/core/id.ts b/src/core/id.ts index 9591b3e0..8a269a0c 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -1,10 +1,10 @@ -import { ApplicationCommandType, ComponentType, Interaction, InteractionType } from 'discord.js'; +import { ApplicationCommandType, ComponentType, type Interaction, InteractionType } from 'discord.js'; import { CommandType, EventType } from './structures/enums'; const parseParams = (event: { customId: string }, id: string, append: string) => { const hasSlash = event.customId.indexOf('/') if(hasSlash === -1) { - return { id }; + return { id:id+append }; } const baseid = event.customId.substring(0, hasSlash); const params = event.customId.substring(hasSlash+1); diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 7c0c4809..2fe45ff8 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,4 +1,3 @@ -import type { DependencyConfiguration } from '../../types/ioc'; import { Container } from './container'; import * as __Services from '../structures/default-services'; import type { Logging } from '../interfaces'; @@ -11,11 +10,11 @@ export function disposeAll(logger: Logging|undefined) { .then(() => logger?.info({ message: 'Cleaning container and crashing' })); } - type Insertable = | ((container: Dependencies) => object) | object -const dependencyBuilder = (container: Container, excluded: string[] ) => { + +const dependencyBuilder = (container: Container) => { return { /** * Insert a dependency into your container. @@ -29,14 +28,6 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { container.addWiredSingleton(key, (cntr) => v(cntr)) } }, - /** - * Exclude any dependencies from being added. - * Warning: this could lead to bad errors if not used correctly - */ - exclude(...keys: (keyof Dependencies)[]) { - keys.forEach(key => excluded.push(key)); - }, - /** * @param key the key of the dependency * @param v The dependency to swap out. @@ -49,60 +40,28 @@ const dependencyBuilder = (container: Container, excluded: string[] ) => { }; }; - +/** + * + * + * + */ type ValidDependencyConfig = | ((c: ReturnType) => any) - | DependencyConfiguration; -/** - * Given the user's conf, check for any excluded/included dependency keys. - * Then, call conf.build to get the rest of the users' dependencies. - * Finally, update the containerSubject with the new container state - * @param conf - */ -async function composeRoot( - container: Container, - conf: DependencyConfiguration, -) { - //container should have no client or logger yet. - const hasLogger = container.hasKey('@sern/logger'); - if (!hasLogger) { - __add_container('@sern/logger', new __Services.DefaultLogging()); - } - __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/modules', new Map()) - __add_container('@sern/emitter', new EventEmitter()) - __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) - //Build the container based on the callback provided by the user - conf.build(container as Container); - - if (!hasLogger) { - container.get('@sern/logger') - ?.info({ message: 'All dependencies loaded successfully.' }); - } - await container.ready(); -} export async function makeDependencies (conf: ValidDependencyConfig) { const container = await __init_container({ autowire: false }); - if(typeof conf === 'function') { - const excluded: string[] = []; - conf(dependencyBuilder(container, excluded)); - //We only include logger if it does not exist - const includeLogger = - !excluded.includes('@sern/logger') - && !container.hasKey('@sern/logger'); + conf(dependencyBuilder(container)); + //We only include logger if it does not exist + const includeLogger = !container.hasKey('@sern/logger'); - if(includeLogger) { - __add_container('@sern/logger', new __Services.DefaultLogging); - } - __add_container('@sern/errors', new __Services.DefaultErrorHandling()); - __add_container('@sern/modules', new Map()) - __add_container('@sern/emitter', new EventEmitter()) - __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) - await container.ready(); - } else { - await composeRoot(container, conf); + if(includeLogger) { + __add_container('@sern/logger', new __Services.DefaultLogging); } + __add_container('@sern/errors', new __Services.DefaultErrorHandling); + __add_container('@sern/modules', new Map) + __add_container('@sern/emitter', new EventEmitter) + __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) + await container.ready(); } diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 40292df6..e19055d0 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -28,7 +28,7 @@ export class Context extends CoreContext { get options() { return this.interaction.options; } - + //TODO args(type: 'message'|'interaction', parser?: Function) { switch(type) { case 'message': { @@ -42,10 +42,12 @@ export class Context extends CoreContext { } protected constructor(protected ctx: Result, - public prefix?: string) { + private __prefix?: string) { super(ctx); } - + public get prefix() { + return this.__prefix; + } public get id(): Snowflake { return safeUnwrap(this.ctx .map(m => m.id) diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 1a876a15..d5a7245c 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -181,7 +181,7 @@ export function executeModule( * - if all results are ok, the stream is converted to { config.onNext } * config.onNext will be returned if everything is okay. * @param config - * @returns receiver function for flattening a stream of data + * @returns function which calls all plugins and returns onNext or fail */ export function createResultResolver(config: { onStop?: (module: Module, err?: string) => unknown; @@ -198,11 +198,11 @@ export function createResultResolver(config: { }; }; -export async function callInitPlugins(module: Module, deps: Dependencies, sEmitter?: Emitter) { +export async function callInitPlugins(module: Module, deps: Dependencies, emit?: boolean ) { let _module = module; for(const plugin of _module.plugins ?? []) { const res = await plugin.execute({ - module, absPath: _module.meta.absPath , + module, absPath: _module.meta.absPath, updateModule: (partial: Partial) => { _module = { ..._module, ...partial }; return _module; @@ -210,7 +210,10 @@ export async function callInitPlugins(module: Module, deps: Dependencies, sEmitt deps }); if(res.isErr()) { - sEmitter?.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + if(emit) { + deps['@sern/emitter'] + ?.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + } throw Error("Plugin failed with controller.stop()"); } } diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 4dbbdee2..6651a3ee 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -24,7 +24,7 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - const resultModule = await callInitPlugins(module, deps, sEmitter); + const resultModule = await callInitPlugins(module, deps, true); // FREEZE! no more writing!! commands.set(resultModule.meta.id, Object.freeze(resultModule)); sEmitter.emit('module.register', resultPayload(PayloadType.Success, resultModule)); diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index fecee051..ebbe4b9b 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -33,10 +33,7 @@ export default async function(deps: UnpackedDependencies, eventDir: string) { } from(eventModules) .pipe(map(intoDispatcher(deps)), - /** - * Where all events are turned on - */ - mergeAll(), + mergeAll(), // all eventListeners are turned on handleCrash(deps)) .subscribe(); } diff --git a/test/core/functions.test.ts b/test/core/functions.test.ts index 512d34a7..8a54ec7d 100644 --- a/test/core/functions.test.ts +++ b/test/core/functions.test.ts @@ -1,11 +1,13 @@ +//@ts-nocheck + import { afterEach, describe, expect, it, vi } from 'vitest'; import { PluginType, SernOptionsData, controller } from '../../src/index'; import { partitionPlugins, treeSearch } from '../../src/core/functions'; import { faker } from '@faker-js/faker'; import { ApplicationCommandOptionType, AutocompleteInteraction } from 'discord.js'; -vi.mock('discord.js', () => { - const Collection = Map; +vi.mock('discord.js', async (importOriginal) => { + const mod = await importOriginal() const ModalSubmitInteraction = class { customId; type = 5; @@ -36,35 +38,11 @@ vi.mock('discord.js', () => { }; return { - Collection, - ComponentType: { - Button: 2, - }, - InteractionType: { - Ping: 1, - ApplicationCommand: 2, - MessageComponent: 3, - ApplicationCommandAutocomplete: 4, - ModalSubmit: 5, - }, - ApplicationCommandOptionType: { - Subcommand: 1, - SubcommandGroup: 2, - String: 3, - Integer: 4, - Boolean: 5, - User: 6, - Channel: 7, - Role: 8, - Mentionable: 9, - Number: 10, - Attachment: 11, - }, - ApplicationCommandType: { - ChatInput: 1, - User: 2, - Message: 3, - }, + Collection: mod.Collection, + ComponentType: mod.ComponentType, + InteractionType: mod.InteractionType, + ApplicationCommandOptionType: mod.ApplicationCommandOptionType, + ApplicationCommandType: mod.ApplicationCommandType, ModalSubmitInteraction, ButtonInteraction, AutocompleteInteraction, diff --git a/test/core/id.test.ts b/test/core/id.test.ts index db34ea71..84433c1b 100644 --- a/test/core/id.test.ts +++ b/test/core/id.test.ts @@ -1,7 +1,51 @@ +//@ts-nocheck +import { expect, test, vi } from 'vitest' import { CommandType } from '../../src/core/structures/enums'; + import * as Id from '../../src/core/id' -import { expect, test } from 'vitest' +import { ButtonInteraction, ModalSubmitInteraction } from 'discord.js'; +vi.mock('discord.js', async (importOriginal) => { + const mod = await importOriginal() + const ModalSubmitInteraction = class { + customId; + type = 5; + isModalSubmit = vi.fn(); + constructor(customId) { + this.customId = customId; + } + }; + const ButtonInteraction = class { + customId; + type = 3; + componentType = 2; + isButton = vi.fn(); + constructor(customId) { + this.customId = customId; + } + }; + const AutocompleteInteraction = class { + type = 4; + option: string; + constructor(s: string) { + this.option = s; + } + options = { + getFocused: vi.fn(), + getSubcommand: vi.fn(), + }; + }; + return { + Collection: mod.Collection, + ComponentType: mod.ComponentType, + InteractionType: mod.InteractionType, + ApplicationCommandOptionType: mod.ApplicationCommandOptionType, + ApplicationCommandType: mod.ApplicationCommandType, + ModalSubmitInteraction, + ButtonInteraction, + AutocompleteInteraction, + }; +}); test('id -> Text', () => { const bothCmdId = Id.create("ping", CommandType.Text) expect(bothCmdId).toBe("ping_T") @@ -60,5 +104,37 @@ test('id -> ChannelSelect', () => { expect(modal).toBe("mychannelselect_C8"); }) +test('id reconstruct button', () => { + const idload = Id.reconstruct(new ButtonInteraction("btn")) + expect(idload[0].id).toBe("btn_C2") +}) + +test('id reconstruct button with params', () => { + const idload = Id.reconstruct(new ButtonInteraction("btn/asdf")) + expect(idload[0].id).toBe("btn_C2") + expect(idload[0].params).toBe("asdf") +}) +test('id reconstruct modal with params', () => { + const idload = Id.reconstruct(new ModalSubmitInteraction("btn/asdf")) + expect(idload[0].id).toBe("btn_M") + expect(idload[0].params).toBe("asdf") +}) +test('id reconstruct modal', () => { + const idload = Id.reconstruct(new ModalSubmitInteraction("btn")) + expect(idload[0].id).toBe("btn_M") + expect(idload[0].params).toBe(undefined) +}) +test('id reconstruct button with empty params', () => { + const idload = Id.reconstruct(new ButtonInteraction("btn/")) + expect(idload[0].id).toBe("btn_C2") + expect(idload[0].params).toBe("") +}) + +test('id reconstruct button', () => { + const idload = Id.reconstruct(new ButtonInteraction("btn")) + expect(idload[0].id).toBe("btn_C2") + expect(idload[0].params).toBe(undefined) +}) + diff --git a/test/handlers/dispatchers.test.ts b/test/handlers/dispatchers.test.ts deleted file mode 100644 index 9337d7e8..00000000 --- a/test/handlers/dispatchers.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { beforeEach, describe, expect, vi, it } from 'vitest'; -import { eventDispatcher } from '../../src/handlers/event-utils'; -import { faker } from '@faker-js/faker'; -import { Module } from '../../src/types/core-modules'; -import { Processed } from '../../src/types/core-modules'; -import { EventEmitter } from 'events'; -import { EventType } from '../../dist/core/structures/enums'; - -function createRandomModule(): Processed { - return { - type: EventType.Discord, - meta: { id:"", absPath: "" }, - description: faker.string.alpha(), - name: "abc", - onEvent: [], - plugins: [], - execute: vi.fn(), - }; -} - -function mockDeps() { - return { - '@sern/client': {} - } -} - - -describe('eventDispatcher standard', () => { - let m: Processed; - let ee: EventEmitter; - beforeEach(() => { - ee = new EventEmitter(); - m = createRandomModule(); - }); - - it('should throw', () => { - expect(() => eventDispatcher(mockDeps(), m, 'not event emitter')).toThrowError(); - }); - - it("Shouldn't throw", () => { - expect(() => eventDispatcher(mockDeps(), m, ee)).not.toThrowError(); - }); -}); diff --git a/test/handlers/index.test.ts b/test/handlers/index.test.ts new file mode 100644 index 00000000..5c6a6de7 --- /dev/null +++ b/test/handlers/index.test.ts @@ -0,0 +1,136 @@ +//@ts-nocheck +import { beforeEach, describe, expect, vi, it } from 'vitest'; +import { callInitPlugins, eventDispatcher } from '../../src/handlers/event-utils'; + +import { Client } from 'discord.js' +import { faker } from '@faker-js/faker'; +import { Module } from '../../src/types/core-modules'; +import { Processed } from '../../src/types/core-modules'; +import { EventEmitter } from 'events'; +import { EventType } from '../../dist/core/structures/enums'; +import { CommandInitPlugin, controller } from '../../src'; + +vi.mock('discord.js', () => { + const Client = vi.fn() + Client.prototype.login= vi.fn() + const Collection = Map; + const ModalSubmitInteraction = class { + customId; + type = 5; + isModalSubmit = vi.fn(); + constructor(customId) { + this.customId = customId; + } + }; + const ButtonInteraction = class { + customId; + type = 3; + componentType = 2; + isButton = vi.fn(); + constructor(customId) { + this.customId = customId; + } + }; + const AutocompleteInteraction = class { + type = 4; + option: string; + constructor(s: string) { + this.option = s; + } + options = { + getFocused: vi.fn(), + getSubcommand: vi.fn(), + }; + }; + + return { + Client, + Collection, + ComponentType: { + Button: 2, + }, + InteractionType: { + Ping: 1, + ApplicationCommand: 2, + MessageComponent: 3, + ApplicationCommandAutocomplete: 4, + ModalSubmit: 5, + }, + ApplicationCommandOptionType: { + Subcommand: 1, + SubcommandGroup: 2, + String: 3, + Integer: 4, + Boolean: 5, + User: 6, + Channel: 7, + Role: 8, + Mentionable: 9, + Number: 10, + Attachment: 11, + }, + ApplicationCommandType: { + ChatInput: 1, + User: 2, + Message: 3, + }, + ModalSubmitInteraction, + ButtonInteraction, + AutocompleteInteraction, + }; +}) +function createRandomPlugin (s: 'go', mut?: Partial) { + return CommandInitPlugin(({ module, updateModule }) => { + if(mut) { + updateModule(mut) + } + return s == 'go' + ? controller.next() + : controller.stop() + }) +} +function createRandomModule(plugins: any[]): Processed { + return { + type: EventType.Discord, + meta: { id:"", absPath: "" }, + description: faker.string.alpha(), + plugins, + name: "cheese", + onEvent: [], + execute: vi.fn(), + }; +} + +function mockDeps() { + return { + '@sern/client': new Client(), + '@sern/emitter': new EventEmitter() + } +} + +describe('eventDispatcher standard', () => { + let m: Processed; + let ee: EventEmitter; + beforeEach(() => { + ee = new EventEmitter(); + m = createRandomModule(); + }); + + it('should throw', () => { + expect(() => eventDispatcher(mockDeps(), m, 'not event emitter')).toThrowError(); + }); + + it("Shouldn't throw", () => { + expect(() => eventDispatcher(mockDeps(), m, ee)).not.toThrowError(); + }); + it('mutate with init plugins', async () => { + const deps = mockDeps() + const plugins = createRandomPlugin('go', { name: "abc" }) + const mod = createRandomModule([plugins]) + const s = await callInitPlugins(mod, deps, false) + expect(s.name).not.equal(mod.name) + }) + +}); + + From 86dd0cd842a98e8dde3c6df3afff8bb4244e4668 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 23 May 2024 01:02:02 -0500 Subject: [PATCH 57/90] testing n shi --- src/core/create-plugins.ts | 2 +- src/core/functions.ts | 2 +- src/core/id.ts | 6 +- src/core/module-loading.ts | 2 +- src/core/structures/enums.ts | 10 +--- src/handlers/event-utils.ts | 9 ++- src/handlers/interaction.ts | 9 ++- src/handlers/message.ts | 2 +- src/handlers/ready.ts | 2 +- src/types/core-plugin.ts | 1 - src/types/utility.ts | 2 +- test/core/id.test.ts | 39 ++++++------- test/core/module-loading.test.ts | 1 + test/handlers/index.test.ts | 97 +++++++++++++++++--------------- 14 files changed, 86 insertions(+), 98 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 3f9d7598..e65b097d 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -6,7 +6,7 @@ export function makePlugin( type: PluginType, execute: (...args: any[]) => any, ): Plugin { - return { type, execute, } as Plugin; + return { type, execute } as Plugin; } /** * @since 2.5.0 diff --git a/src/core/functions.ts b/src/core/functions.ts index 20ccb430..520e0010 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -100,7 +100,7 @@ export function isModal(i: InteractionTypable): i is ModalSubmitInteraction { return i.type === InteractionType.ModalSubmit; } -export function resultPayload +export function resultPayload (type: T, module?: Module, reason?: unknown) { return { type, module, reason } as Payload & { type : T }; } diff --git a/src/core/id.ts b/src/core/id.ts index 8a269a0c..3b919c6d 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -18,8 +18,7 @@ const parseParams = (event: { customId: string }, id: string, append: string) => export function reconstruct(event: T) { switch (event.type) { case InteractionType.MessageComponent: { - let id = event.customId; - const data = parseParams(event, id, `_C${event.componentType}`) + const data = parseParams(event, event.customId, `_C${event.componentType}`) return [data]; } case InteractionType.ApplicationCommand: @@ -27,8 +26,7 @@ export function reconstruct(event: T) { return [{ id: `${event.commandName}_A${event.commandType}` }, { id: `${event.commandName}_B` }]; //Modal interactions are classified as components for sern case InteractionType.ModalSubmit: { - let id = `${event.customId}`; - const data = parseParams(event, id, '_M'); + const data = parseParams(event, event.customId, '_M'); return [data]; } } diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index 88cabd7e..dd4ef4f3 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -1,5 +1,5 @@ import path from 'node:path'; -import { existsSync } from 'fs'; +import { existsSync } from 'node:fs'; import { readdir } from 'fs/promises'; import assert from 'node:assert'; import * as Id from './id' diff --git a/src/core/structures/enums.ts b/src/core/structures/enums.ts index ef398f10..2990c2e7 100644 --- a/src/core/structures/enums.ts +++ b/src/core/structures/enums.ts @@ -86,20 +86,12 @@ export enum PluginType { Control = 2, } /** + * @deprecated - Use strings 'success' | 'failure' | 'warning' * @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', } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index d5a7245c..0d872a9c 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -6,7 +6,7 @@ import { } from 'rxjs'; import * as Id from '../core/id' import type { Emitter } from '../core/interfaces'; -import { PayloadType, SernError } from '../core/structures/enums' +import { SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; import type { UnpackedDependencies } from '../types/utility'; import type { CommandModule, Module, Processed } from '../types/core-modules'; @@ -167,10 +167,10 @@ export function executeModule( return from(Result.wrapAsync(async () => module.execute(...args))) .pipe(concatMap(result => { if (result.isOk()) { - emitter.emit('module.activate', resultPayload(PayloadType.Success, module)); + emitter.emit('module.activate', resultPayload('success', module)); return EMPTY; } - return throwError(() => resultPayload(PayloadType.Failure, module, result.error)); + return throwError(() => resultPayload('failure', module, result.error)); })) }; @@ -211,8 +211,7 @@ export async function callInitPlugins(module: Module, deps: Dependencies, emit?: }); if(res.isErr()) { if(emit) { - deps['@sern/emitter'] - ?.emit('module.register', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)); + deps['@sern/emitter']?.emit('module.register', resultPayload('failure', module, SernError.PluginFailure)); } throw Error("Plugin failed with controller.stop()"); } diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index b56debde..11696c4a 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -1,10 +1,9 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap, EMPTY } from 'rxjs'; -import { PayloadType } from '../core/structures/enums'; import { filterTap, sharedEventStream } from '../core/operators' -import { createInteractionHandler, executeModule, intoTask, } from './event-utils'; +import { createInteractionHandler, executeModule, intoTask } from './event-utils'; import { SernError } from '../core/structures/enums' -import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload, } from '../core/functions' +import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; import { Emitter } from '../core/interfaces'; @@ -20,9 +19,9 @@ export default function interactionHandler(deps: UnpackedDependencies, defaultPr handle(isCommand), handle(isModal)); return interactionHandler$ - .pipe(filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + .pipe(filterTap(e => emitter.emit('warning', resultPayload('warning', undefined, e))), concatMap(intoTask(module => { - emitter.emit('module.activate', resultPayload(PayloadType.Failure, module, SernError.PluginFailure)) + emitter.emit('module.activate', resultPayload('failure', module, SernError.PluginFailure)) })), mergeMap(payload => { if(payload) diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 193a5304..8eb8abf6 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,6 +1,6 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { createMessageHandler, executeModule, intoTask } from './event-utils'; +import { createMessageHandler, executeModule, intoTask } from './event-utils'; import { PayloadType, SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { filterTap, sharedEventStream } from '../core/operators' diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 6651a3ee..9ac10066 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -27,7 +27,7 @@ export default async function(dir: string, deps : UnpackedDependencies) { const resultModule = await callInitPlugins(module, deps, true); // FREEZE! no more writing!! commands.set(resultModule.meta.id, Object.freeze(resultModule)); - sEmitter.emit('module.register', resultPayload(PayloadType.Success, resultModule)); + sEmitter.emit('module.register', resultPayload('success', resultModule)); } sEmitter.emit('modulesLoaded'); } diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index ce3ac059..d082baef 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -13,7 +13,6 @@ import type { Err, Ok, Result } from 'ts-results-es'; import type { - CommandModuleDefs, Module, Processed, SDT, diff --git a/src/types/utility.ts b/src/types/utility.ts index 3b4c38ea..64c95da3 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -11,7 +11,7 @@ export type AnyFunction = (...args: any[]) => unknown; export interface SernEventsMapping { 'module.register': [Payload]; 'module.activate': [Payload]; - error: [{ type: PayloadType.Failure; module?: Module; reason: string | Error }]; + error: [{ type: 'failure'; module?: Module; reason: string | Error }]; warning: [Payload]; modulesLoaded: [never?]; } diff --git a/test/core/id.test.ts b/test/core/id.test.ts index 84433c1b..25925c43 100644 --- a/test/core/id.test.ts +++ b/test/core/id.test.ts @@ -47,56 +47,45 @@ vi.mock('discord.js', async (importOriginal) => { }; }); test('id -> Text', () => { - const bothCmdId = Id.create("ping", CommandType.Text) - expect(bothCmdId).toBe("ping_T") + expect(Id.create("ping", CommandType.Text)).toBe("ping_T") }) test('id -> Both', () => { - const bothCmdId = Id.create("ping", CommandType.Both) - expect(bothCmdId).toBe("ping_B") + expect(Id.create("ping", CommandType.Both)).toBe("ping_B") }) test('id -> CtxMsg', () => { - const bothCmdId = Id.create("ping", CommandType.CtxMsg) - expect(bothCmdId).toBe("ping_A3") + expect(Id.create("ping", CommandType.CtxMsg)).toBe("ping_A3") }) test('id -> CtxUsr', () => { - const bothCmdId = Id.create("ping", CommandType.CtxUser) - expect(bothCmdId).toBe("ping_A2") + expect(Id.create("ping", CommandType.CtxUser)).toBe("ping_A2") }) test('id -> Modal', () => { - const modal = Id.create("my-modal", CommandType.Modal) - expect(modal).toBe("my-modal_M"); + expect(Id.create("my-modal", CommandType.Modal)).toBe("my-modal_M"); }) test('id -> Button', () => { - const modal = Id.create("my-button", CommandType.Button) - expect(modal).toBe("my-button_C2"); + expect(Id.create("my-button", CommandType.Button)).toBe("my-button_C2"); }) test('id -> Slash', () => { - const modal = Id.create("myslash", CommandType.Slash) - expect(modal).toBe("myslash_A1"); + expect(Id.create("myslash", CommandType.Slash)).toBe("myslash_A1"); }) test('id -> StringSelect', () => { - const modal = Id.create("mystringselect", CommandType.StringSelect) - expect(modal).toBe("mystringselect_C3"); + expect(Id.create("mystringselect", CommandType.StringSelect)).toBe("mystringselect_C3"); }) test('id -> UserSelect', () => { - const modal = Id.create("myuserselect", CommandType.UserSelect) - expect(modal).toBe("myuserselect_C5"); + expect(Id.create("myuserselect", CommandType.UserSelect)).toBe("myuserselect_C5"); }) test('id -> RoleSelect', () => { - const modal = Id.create("myroleselect", CommandType.RoleSelect) - expect(modal).toBe("myroleselect_C6"); + expect(Id.create("myroleselect", CommandType.RoleSelect)).toBe("myroleselect_C6"); }) test('id -> MentionSelect', () => { - const modal = Id.create("mymentionselect", CommandType.MentionableSelect) - expect(modal).toBe("mymentionselect_C7"); + expect(Id.create("mymentionselect", CommandType.MentionableSelect)).toBe("mymentionselect_C7"); }) test('id -> ChannelSelect', () => { @@ -129,6 +118,12 @@ test('id reconstruct button with empty params', () => { expect(idload[0].id).toBe("btn_C2") expect(idload[0].params).toBe("") }) +test('id reconstruct with multiple slashes', () => { + const idload = Id.reconstruct(new ButtonInteraction("btn//")) + expect(idload[0].id).toBe("btn_C2") + expect(idload[0].params).toBe("/") +}) + test('id reconstruct button', () => { const idload = Id.reconstruct(new ButtonInteraction("btn")) diff --git a/test/core/module-loading.test.ts b/test/core/module-loading.test.ts index d4adb292..0f5d790b 100644 --- a/test/core/module-loading.test.ts +++ b/test/core/module-loading.test.ts @@ -3,6 +3,7 @@ import path from 'node:path' import * as Files from '../../src/core/module-loading' import { Module } from '../../src/types/core-modules' import { AssertionError } from 'node:assert' +//TODO: mock fs? describe('module-loading', () => { it('should get the filename of the commandmodule (linux, esm)', () => { const fname = "///home/pooba/Projects/sern/halibu/dist/commands/ping.js" diff --git a/test/handlers/index.test.ts b/test/handlers/index.test.ts index 5c6a6de7..315eb4ca 100644 --- a/test/handlers/index.test.ts +++ b/test/handlers/index.test.ts @@ -1,19 +1,17 @@ //@ts-nocheck -import { beforeEach, describe, expect, vi, it } from 'vitest'; +import { beforeEach, describe, expect, vi, it, test } from 'vitest'; import { callInitPlugins, eventDispatcher } from '../../src/handlers/event-utils'; -import { Client } from 'discord.js' +import { Client, ChatInputCommandInteraction } from 'discord.js' import { faker } from '@faker-js/faker'; import { Module } from '../../src/types/core-modules'; import { Processed } from '../../src/types/core-modules'; import { EventEmitter } from 'events'; import { EventType } from '../../dist/core/structures/enums'; -import { CommandInitPlugin, controller } from '../../src'; +import { CommandControlPlugin, CommandInitPlugin, CommandType, controller } from '../../src'; -vi.mock('discord.js', () => { - const Client = vi.fn() - Client.prototype.login= vi.fn() - const Collection = Map; +vi.mock('discord.js', async (importOriginal) => { + const mod = await importOriginal() const ModalSubmitInteraction = class { customId; type = 5; @@ -44,41 +42,19 @@ vi.mock('discord.js', () => { }; return { - Client, - Collection, - ComponentType: { - Button: 2, - }, - InteractionType: { - Ping: 1, - ApplicationCommand: 2, - MessageComponent: 3, - ApplicationCommandAutocomplete: 4, - ModalSubmit: 5, - }, - ApplicationCommandOptionType: { - Subcommand: 1, - SubcommandGroup: 2, - String: 3, - Integer: 4, - Boolean: 5, - User: 6, - Channel: 7, - Role: 8, - Mentionable: 9, - Number: 10, - Attachment: 11, - }, - ApplicationCommandType: { - ChatInput: 1, - User: 2, - Message: 3, - }, + Client : vi.fn(), + Collection: mod.Collection, + ComponentType: mod.ComponentType, + InteractionType: mod.InteractionType, + ApplicationCommandOptionType: mod.ApplicationCommandOptionType, + ApplicationCommandType: mod.ApplicationCommandType, ModalSubmitInteraction, ButtonInteraction, AutocompleteInteraction, + ChatInputCommandInteraction: vi.fn() }; -}) +}); + function createRandomPlugin (s: 'go', mut?: Partial) { return CommandInitPlugin(({ module, updateModule }) => { if(mut) { @@ -123,14 +99,43 @@ describe('eventDispatcher standard', () => { it("Shouldn't throw", () => { expect(() => eventDispatcher(mockDeps(), m, ee)).not.toThrowError(); }); - it('mutate with init plugins', async () => { - const deps = mockDeps() - const plugins = createRandomPlugin('go', { name: "abc" }) - const mod = createRandomModule([plugins]) - const s = await callInitPlugins(mod, deps, false) - expect(s.name).not.equal(mod.name) - }) - }); +test ('mutate with init plugins', async () => { + const deps = mockDeps() + const plugins = createRandomPlugin('go', { name: "abc" }) + const mod = createRandomModule([plugins]) + const s = await callInitPlugins(mod, deps, false) + expect(s.name).not.equal(mod.name) +}) + + +test('call control plugin ', async () => { + const plugin = CommandControlPlugin((ctx,sdt) => { + return controller.next(); + }); + const res = await plugin.execute(new ChatInputCommandInteraction(), {}) + expect(res.isOk()).toBe(true) +}) + +test('form sdt', async () => { + + const expectedObject = { + "plugin/abc": faker.person.jobArea(), + "plugin2/abc": faker.git.branch(), + "plugin3/cheese": faker.person.jobArea() + } + +// const plugin = CommandControlPlugin((ctx,sdt) => { +// return controller.next({ "plugin/abc": expectedObject['plugin/abc'] }); +// }); +// const plugin2 = CommandControlPlugin((ctx,sdt) => { +// return controller.next({ "plugin2/abc": expectedObject['plugin2/abc'] }); +// }); +// const plugin3 = CommandControlPlugin((ctx,sdt) => { +// return controller.next({ "plugin3/cheese": expectedObject['plugin3/cheese'] }); +// }); + +}) + From 76d9db7b98701d7d7398aaf8cc0b6d1594a64456 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 23 May 2024 19:36:08 -0500 Subject: [PATCH 58/90] inlineinignsd --- src/core/create-plugins.ts | 6 +++--- src/core/functions.ts | 5 ++--- src/core/module-loading.ts | 2 +- src/core/structures/context.ts | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index e65b097d..089d5aa1 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -1,6 +1,6 @@ import { CommandType, PluginType } from './structures/enums'; import type { Plugin, PluginResult, CommandArgs, InitArgs } from '../types/core-plugin'; -import { err, ok } from './functions'; +import { Err, Ok } from 'ts-results-es'; export function makePlugin( type: PluginType, @@ -37,6 +37,6 @@ export function CommandControlPlugin( * The object passed into every plugin to control a command's behavior */ export const controller = { - next: ok, - stop: err, + next: (val: unknown=undefined) => Ok(val), + stop: (val?: string) => Err(val), }; diff --git a/src/core/functions.ts b/src/core/functions.ts index 520e0010..85cfd8bb 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -10,12 +10,11 @@ import type { AutocompleteInteraction } from 'discord.js'; import { ApplicationCommandOptionType, InteractionType } from 'discord.js'; -import { PayloadType, PluginType } from './structures/enums'; +import { PluginType } from './structures/enums'; import assert from 'assert'; import type { Payload } from '../types/utility'; -export const ok = (val: unknown=undefined) => Ok(val); -export const err = (val?: string) => Err(val); + export function partitionPlugins (arr: Array<{ type: PluginType }> = []): [T[], V[]] { diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index dd4ef4f3..e4875c5c 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -6,7 +6,7 @@ import * as Id from './id' import { Module } from '../types/core-modules'; export const parseCallsite = (site: string) => { - const pathobj = path.parse(site.replace(/file:\\?/, "") + const pathobj = path.posix.parse(site.replace(/file:\\?/, "") .split(path.sep) .join(path.posix.sep)) return { name: pathobj.name, diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index e19055d0..53069ea7 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -11,7 +11,7 @@ import type { import { CoreContext } from '../structures/core-context'; import { Result, Ok, Err } from 'ts-results-es'; import * as assert from 'assert'; -import { ReplyOptions } from '../../types/utility'; +import type { ReplyOptions } from '../../types/utility'; function fmt(msg: string, prefix?: string): string[] { if(!prefix) throw Error("Unable to parse message without prefix"); @@ -29,7 +29,7 @@ export class Context extends CoreContext { return this.interaction.options; } //TODO - args(type: 'message'|'interaction', parser?: Function) { + args(type: 'message'|'interaction') { switch(type) { case 'message': { const [, ...rest] = fmt(this.message.content, this.prefix); From af0f909c444abf7d6495fa9b8443da0bb0979e0f Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 23 May 2024 22:00:12 -0500 Subject: [PATCH 59/90] consolidate fmt --- src/core/functions.ts | 15 ++++++++++++++- src/core/structures/context.ts | 6 +----- src/handlers/event-utils.ts | 17 ++--------------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index 85cfd8bb..18154c73 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -1,4 +1,3 @@ -import { Err, Ok } from 'ts-results-es'; import type { Module, SernAutocompleteData, SernOptionsData } from '../types/core-modules'; import type { AnySelectMenuInteraction, @@ -14,6 +13,20 @@ import { PluginType } from './structures/enums'; import assert from 'assert'; import type { Payload } from '../types/utility'; +/** + * Removes the first character(s) _[depending on prefix length]_ of the message + * @param msg + * @param prefix The prefix to remove + * @returns The message without the prefix + * @example + * message.content = '!ping'; + * console.log(fmt(message, '!')); + * // [ 'ping' ] + */ +export function fmt(msg: string, prefix?: string): string[] { + if(!prefix) throw Error("Unable to parse message without prefix"); + return msg.slice(prefix.length).trim().split(/\s+/g); +} export function partitionPlugins diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 53069ea7..ef3b4591 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -12,11 +12,7 @@ import { CoreContext } from '../structures/core-context'; import { Result, Ok, Err } from 'ts-results-es'; import * as assert from 'assert'; import type { ReplyOptions } from '../../types/utility'; - -function fmt(msg: string, prefix?: string): string[] { - if(!prefix) throw Error("Unable to parse message without prefix"); - return msg.slice(prefix.length).trim().split(/\s+/g); -} +import { fmt } from '../functions' /** * @since 1.0.0 diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 0d872a9c..21c3f0ae 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -16,7 +16,7 @@ import { CommandType } from '../core/structures/enums' import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; import { arrayifySource, handleError } from '../core/operators'; -import { resultPayload, isAutocomplete, treeSearch } from '../core/functions' +import { resultPayload, isAutocomplete, treeSearch, fmt } from '../core/functions' interface ExecutePayload { module: Module; @@ -88,19 +88,6 @@ function createGenericHandler( concatMap(makeModule)); // create a payload, preparing to execute } -/** - * Removes the first character(s) _[depending on prefix length]_ of the message - * @param msg - * @param prefix The prefix to remove - * @returns The message without the prefix - * @example - * message.content = '!ping'; - * console.log(fmt(message, '!')); - * // [ 'ping' ] - */ -export function fmt(msg: string, prefix: string): string[] { - return msg.slice(prefix.length).trim().split(/\s+/g); -} /** * @@ -137,7 +124,7 @@ export function createInteractionHandler( export function createMessageHandler( source: Observable, defaultPrefix: string, - deps: Dependencies + deps: Dependencies, ) { const mg = deps['@sern/modules']; return createGenericHandler(source, async event => { From 12a8f0c5d7e4cf76d607d500fdcadd49a701e3d9 Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 25 May 2024 12:39:24 -0500 Subject: [PATCH 60/90] once on eventModules --- src/core/module-loading.ts | 2 +- src/handlers/event-utils.ts | 16 ++++++++++------ src/handlers/message.ts | 2 +- src/handlers/ready.ts | 1 - src/types/core-modules.ts | 2 +- src/types/core-plugin.ts | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index e4875c5c..dd4ef4f3 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -6,7 +6,7 @@ import * as Id from './id' import { Module } from '../types/core-modules'; export const parseCallsite = (site: string) => { - const pathobj = path.posix.parse(site.replace(/file:\\?/, "") + const pathobj = path.parse(site.replace(/file:\\?/, "") .split(path.sep) .join(path.posix.sep)) return { name: pathobj.name, diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 21c3f0ae..6b47c3d7 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -2,7 +2,7 @@ import type { Interaction, Message, BaseInteraction } from 'discord.js'; import { EMPTY, type Observable, concatMap, filter, throwError, fromEvent, map, type OperatorFunction, - catchError, finalize, pipe, from, + catchError, finalize, pipe, from, take, } from 'rxjs'; import * as Id from '../core/id' import type { Emitter } from '../core/interfaces'; @@ -43,10 +43,15 @@ export function eventDispatcher(deps: Dependencies, module: Module, source: unkn concatMap(async args => { if(args) return Reflect.apply(module.execute, null, args); }); + + //@ts-ignore + let ev = fromEvent(source ,module.name!); //@ts-ignore - return fromEvent(source, module.name!) - .pipe(intoPayload(module, deps), - execute); + if(module['once']) { + ev = ev.pipe(take(1)) + } + return ev.pipe(intoPayload(module, deps), + execute); } interface DispatchPayload { @@ -108,8 +113,7 @@ export function createInteractionHandler( const possibleIds = Id.reconstruct(event); let modules = possibleIds .map(({ id, params }) => ({ module: mg.get(id), params })) - .filter((id) => id !== undefined); - + .filter(({ module }) => module !== undefined); if(modules.length == 0) { return Err.EMPTY; } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 8eb8abf6..125889f2 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -38,7 +38,7 @@ function (deps: UnpackedDependencies, defaultPrefix?: string) { return msgCommands$.pipe( filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), concatMap(intoTask(module => { - const result = resultPayload(PayloadType.Failure, module, SernError.PluginFailure); + const result = resultPayload('failure', module, SernError.PluginFailure); emitter.emit('module.activate', result); })), mergeMap(payload => { diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 9ac10066..662b1bd0 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -1,7 +1,6 @@ import * as Files from '../core/module-loading' import { once } from 'node:events'; import { resultPayload } from '../core/functions'; -import { PayloadType } from '..'; import { CommandType } from '../core/structures/enums'; import { Module } from '../types/core-modules'; import { UnpackedDependencies } from '../types/utility'; diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 911e5828..aeb102dd 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -193,7 +193,7 @@ type CommandModuleNoPlugins = { [T in CommandType]: Omit; }; type EventModulesNoPlugins = { - [T in EventType]: Omit; + [T in EventType]: Omit & { once?: boolean }; }; export type InputEvent = { diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index d082baef..60c0b03d 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -18,7 +18,7 @@ import type { SDT, } from './core-modules'; import type { Awaitable } from './utility'; -import type { CommandType, EventType, PluginType } from '../core/structures/enums' +import type { CommandType, PluginType } from '../core/structures/enums' import type { Context } from '../core/structures/context' import type { ButtonInteraction, From fb418c06758b6f3318bf4b5f58a58540139be8d4 Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 25 May 2024 16:22:25 -0500 Subject: [PATCH 61/90] refact,simplf --- src/core/create-plugins.ts | 2 +- src/core/id.ts | 2 +- src/core/module-loading.ts | 2 +- src/types/core-modules.ts | 4 ++-- test/core/module-loading.test.ts | 25 +++++++++++++++++++------ 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/core/create-plugins.ts b/src/core/create-plugins.ts index 089d5aa1..9006b099 100644 --- a/src/core/create-plugins.ts +++ b/src/core/create-plugins.ts @@ -37,6 +37,6 @@ export function CommandControlPlugin( * The object passed into every plugin to control a command's behavior */ export const controller = { - next: (val: unknown=undefined) => Ok(val), + next: (val?: Record) => Ok(val), stop: (val?: string) => Err(val), }; diff --git a/src/core/id.ts b/src/core/id.ts index 3b919c6d..3f91f92d 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -4,7 +4,7 @@ import { CommandType, EventType } from './structures/enums'; const parseParams = (event: { customId: string }, id: string, append: string) => { const hasSlash = event.customId.indexOf('/') if(hasSlash === -1) { - return { id:id+append }; + return { id:event.customId+append }; } const baseid = event.customId.substring(0, hasSlash); const params = event.customId.substring(hasSlash+1); diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts index dd4ef4f3..e4875c5c 100644 --- a/src/core/module-loading.ts +++ b/src/core/module-loading.ts @@ -6,7 +6,7 @@ import * as Id from './id' import { Module } from '../types/core-modules'; export const parseCallsite = (site: string) => { - const pathobj = path.parse(site.replace(/file:\\?/, "") + const pathobj = path.posix.parse(site.replace(/file:\\?/, "") .split(path.sep) .join(path.posix.sep)) return { name: pathobj.name, diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index aeb102dd..acf47084 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -193,11 +193,11 @@ type CommandModuleNoPlugins = { [T in CommandType]: Omit; }; type EventModulesNoPlugins = { - [T in EventType]: Omit & { once?: boolean }; + [T in EventType]: Omit ; }; export type InputEvent = { - [T in EventType]: EventModulesNoPlugins[T]; + [T in EventType]: EventModulesNoPlugins[T] & { once?: boolean }; }[EventType]; export type InputCommand = { diff --git a/test/core/module-loading.test.ts b/test/core/module-loading.test.ts index 0f5d790b..2ec5633c 100644 --- a/test/core/module-loading.test.ts +++ b/test/core/module-loading.test.ts @@ -10,15 +10,28 @@ describe('module-loading', () => { const callsiteinfo = Files.parseCallsite(fname) expect(callsiteinfo.name).toBe("ping") }) - it('should get the filename of the commandmodule (windows, cjs)', () => { - const fname = "C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + it('should get filename of commandmodule (linux, cjs)', () => { + const fname = "file:///home/pooba/Projects/sern/halibu/dist/commands/ping.js" const callsiteinfo = Files.parseCallsite(fname) - expect(callsiteinfo.name).toEqual("ping"); + expect(callsiteinfo.name).toBe("ping") + + }) + it('should get the filename of the commandmodule (windows, cjs)', () => { + //this test case is impossible on linux. + if(process.platform == 'win32') { + const fname = "C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + const callsiteinfo = Files.parseCallsite(fname) + expect(callsiteinfo.name).toEqual("ping"); + } }) it('should get filename of commandmodule (windows, esm)', () => { - const fname = "file:///C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" - const callsiteinfo = Files.parseCallsite(fname) - expect(callsiteinfo.name).toEqual("ping"); + //this test case is impossible on linux. + if(process.platform == 'win32') { + const fname = "file:///C:\\pooba\\Projects\\sern\\halibu\\dist\\commands\\ping.js" + const callsiteinfo = Files.parseCallsite(fname) + expect(callsiteinfo.name).toEqual("ping"); + } + }) it('should import a commandModule properly', async () => { From 792015a64e1ac30998977267c7e6c05bfc6f8195 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 27 May 2024 17:01:22 -0500 Subject: [PATCH 62/90] readd vitest and Asset fn --- package.json | 7 +- src/handlers/event-utils.ts | 8 +- src/index.ts | 18 +- src/types/core-plugin.ts | 8 +- yarn.lock | 1839 +++++++++++++++++++++++++++++++++-- 5 files changed, 1811 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index fd9c29dd..b177954f 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "build:prod": "tsc", "prepare": "tsc", "pretty": "prettier --write .", - "tdd": "npx --yes vitest", - "test": "npx --yes vitest --run", + "tdd": "vitest", + "test": "vitest --run", "analyze-imports": "npx depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg" }, "keywords": [ @@ -48,7 +48,8 @@ "@typescript-eslint/parser": "5.59.1", "discord.js": "^14.x.x", "eslint": "8.39.0", - "typescript": "5.0.2" + "typescript": "5.0.2", + "vitest": "^1.6.0" }, "eslintConfig": { "parser": "@typescript-eslint/parser", diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 6b47c3d7..1919a253 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -191,6 +191,7 @@ export function createResultResolver(config: { export async function callInitPlugins(module: Module, deps: Dependencies, emit?: boolean ) { let _module = module; + const emitter = deps['@sern/emitter']; for(const plugin of _module.plugins ?? []) { const res = await plugin.execute({ module, absPath: _module.meta.absPath, @@ -202,9 +203,10 @@ export async function callInitPlugins(module: Module, deps: Dependencies, emit?: }); if(res.isErr()) { if(emit) { - deps['@sern/emitter']?.emit('module.register', resultPayload('failure', module, SernError.PluginFailure)); + emitter?.emit('module.register', + resultPayload('failure', module, res.error ?? SernError.PluginFailure)); } - throw Error("Plugin failed with controller.stop()"); + throw Error(res.error ?? SernError.PluginFailure); } } return _module @@ -218,7 +220,7 @@ async function callPlugins({ args, module, deps, params }: ExecutePayload) { return result; } if(typeof result.value === 'object' && result.value !== null) { - state = { ...result.value, ...state }; + state = { ...state, ...result.value, }; } } return Ok(state); diff --git a/src/index.ts b/src/index.ts index 96db42d2..c82e48f3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +import fs from 'node:fs/promises' +import path from 'node:path' export * as Sern from './sern'; export type { @@ -24,10 +26,10 @@ export type { SernOptionsData, SernSubCommandData, SernSubCommandGroupData, + SDT } from './types/core-modules'; export type { - Controller, PluginResult, InitPlugin, ControlPlugin, @@ -47,7 +49,21 @@ export { export * from './core/presences' export * from './core/interfaces' +import type { controller } from './core/create-plugins'; +export type Controller = typeof controller export * from './core/create-plugins'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; export * from './core/ioc'; + + +export async function Asset(p: string) { + const assetsDir = path.resolve('assets'); + if (path.isAbsolute(p)) { + const relativePath = path.relative(assetsDir, "assets"+p); + return fs.readFile(path.join(assetsDir, relativePath), 'utf8'); + } + return fs.readFile(path.join(assetsDir, p), 'utf8'); +} + + diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 60c0b03d..bd01f59a 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -11,7 +11,7 @@ * Plugins are reminiscent of middleware in express. */ -import type { Err, Ok, Result } from 'ts-results-es'; +import type { Result } from 'ts-results-es'; import type { Module, Processed, @@ -32,7 +32,7 @@ import type { UserSelectMenuInteraction, } from 'discord.js'; -export type PluginResult = Awaitable>; +export type PluginResult = Awaitable|undefined, string|undefined>>; export interface InitArgs = Processed> { module: T; @@ -40,10 +40,6 @@ export interface InitArgs = Processed> { deps: Dependencies updateModule: (module: Partial) => T } -export interface Controller { - next: () => Ok; - stop: () => Err; -} export interface Plugin { type: PluginType; execute: (...args: Args) => PluginResult; diff --git a/yarn.lock b/yarn.lock index 13daa980..ef8561e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -91,6 +91,167 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/aix-ppc64@npm:0.20.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/android-arm64@npm:0.20.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/android-arm@npm:0.20.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/android-x64@npm:0.20.2" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/darwin-arm64@npm:0.20.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/darwin-x64@npm:0.20.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/freebsd-arm64@npm:0.20.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/freebsd-x64@npm:0.20.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-arm64@npm:0.20.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-arm@npm:0.20.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-ia32@npm:0.20.2" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-loong64@npm:0.20.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-mips64el@npm:0.20.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-ppc64@npm:0.20.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-riscv64@npm:0.20.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-s390x@npm:0.20.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/linux-x64@npm:0.20.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/netbsd-x64@npm:0.20.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/openbsd-x64@npm:0.20.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/sunos-x64@npm:0.20.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/win32-arm64@npm:0.20.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/win32-ia32@npm:0.20.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.20.2": + version: 0.20.2 + resolution: "@esbuild/win32-x64@npm:0.20.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -165,6 +326,36 @@ __metadata: languageName: node linkType: hard +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.15": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -192,6 +383,147 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.2 + resolution: "@npmcli/agent@npm:2.2.2" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.3 + checksum: 67de7b88cc627a79743c88bab35e023e23daf13831a8aa4e15f998b92f5507b644d8ffc3788afc8e64423c612e0785a6a92b74782ce368f49a6746084b50d874 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: ^7.3.5 + checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@rollup/rollup-android-arm-eabi@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.18.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-android-arm64@npm:4.18.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.18.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.18.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.18.0" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.18.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.18.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.18.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.18.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.18.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.18.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.18.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.18.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.18.0": + version: 4.18.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.18.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@sapphire/async-queue@npm:^1.5.2": version: 1.5.2 resolution: "@sapphire/async-queue@npm:1.5.2" @@ -232,9 +564,24 @@ __metadata: rxjs: ^7.8.0 ts-results-es: ^4.1.0 typescript: 5.0.2 + vitest: ^1.6.0 languageName: unknown linkType: soft +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 + languageName: node + linkType: hard + +"@types/estree@npm:1.0.5, @types/estree@npm:^1.0.0": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.9": version: 7.0.12 resolution: "@types/json-schema@npm:7.0.12" @@ -440,6 +787,60 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/expect@npm:1.6.0" + dependencies: + "@vitest/spy": 1.6.0 + "@vitest/utils": 1.6.0 + chai: ^4.3.10 + checksum: f3a9959ea387622297efed9e3689fd405044a813df5d5923302eaaea831e250d8d6a0ccd44fb387a95c19963242695ed803afc7c46ae06c48a8e06f194951984 + languageName: node + linkType: hard + +"@vitest/runner@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/runner@npm:1.6.0" + dependencies: + "@vitest/utils": 1.6.0 + p-limit: ^5.0.0 + pathe: ^1.1.1 + checksum: 2dcd953477d5effc051376e35a7f2c2b28abbe07c54e61157c9a6d6f01c880e079592c959397b3a55471423256ab91709c150881a33632558b81b1e251a0bf9c + languageName: node + linkType: hard + +"@vitest/snapshot@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/snapshot@npm:1.6.0" + dependencies: + magic-string: ^0.30.5 + pathe: ^1.1.1 + pretty-format: ^29.7.0 + checksum: c4249fbf3ce310de86a19529a0a5c10b1bde4d8d8a678029c632335969b86cbdbf51cedc20d5e9c9328afee834d13cec1b8de5d0fd58139bf8e2dd8dcd0797f4 + languageName: node + linkType: hard + +"@vitest/spy@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/spy@npm:1.6.0" + dependencies: + tinyspy: ^2.2.0 + checksum: 0201975232255e1197f70fc6b23a1ff5e606138a5b96598fff06077d5b747705391013ee98f951affcfd8f54322e4ae1416200393248bb6a9c794f4ef663a066 + languageName: node + linkType: hard + +"@vitest/utils@npm:1.6.0": + version: 1.6.0 + resolution: "@vitest/utils@npm:1.6.0" + dependencies: + diff-sequences: ^29.6.3 + estree-walker: ^3.0.3 + loupe: ^2.3.7 + pretty-format: ^29.7.0 + checksum: a4749533a48e7e4bbc8eafee0fee0e9a0d4eaa4910fbdb490d34e16f8ebcce59a2b38529b9e6b4578e3b4510ea67b29384c93165712b0a19f2e71946922d2c56 + languageName: node + linkType: hard + "@vladfrangu/async_event_emitter@npm:^2.2.4": version: 2.2.4 resolution: "@vladfrangu/async_event_emitter@npm:2.2.4" @@ -447,6 +848,13 @@ __metadata: languageName: node linkType: hard +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -456,6 +864,22 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.3.2": + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + languageName: node + linkType: hard + +"acorn@npm:^8.11.3": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" + bin: + acorn: bin/acorn + checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + languageName: node + linkType: hard + "acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" @@ -465,6 +889,25 @@ __metadata: languageName: node linkType: hard +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": + version: 7.1.1 + resolution: "agent-base@npm:7.1.1" + dependencies: + debug: ^4.3.4 + checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + "ajv@npm:^6.10.0, ajv@npm:^6.12.4": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -484,7 +927,14 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^4.1.0": +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": version: 4.3.0 resolution: "ansi-styles@npm:4.3.0" dependencies: @@ -493,6 +943,20 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -507,6 +971,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -524,6 +995,15 @@ __metadata: languageName: node linkType: hard +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + "braces@npm:^3.0.2": version: 3.0.2 resolution: "braces@npm:3.0.2" @@ -533,6 +1013,33 @@ __metadata: languageName: node linkType: hard +"cac@npm:^6.7.14": + version: 6.7.14 + resolution: "cac@npm:6.7.14" + checksum: 45a2496a9443abbe7f52a49b22fbe51b1905eff46e03fd5e6c98e3f85077be3f8949685a1849b1a9cd2bc3e5567dfebcf64f01ce01847baf918f1b37c839791a + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.3 + resolution: "cacache@npm:18.0.3" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^10.0.1 + minipass: ^7.0.3 + minipass-collect: ^2.0.1 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: b717fd9b36e9c3279bfde4545c3a8f6d5a539b084ee26a9504d48f83694beb724057d26e090b97540f9cc62bea18b9f6cf671c50e18fb7dac60eda9db691714f + languageName: node + linkType: hard + "callsites@npm:^3.0.0, callsites@npm:^3.1.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -540,6 +1047,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.10": + version: 4.4.1 + resolution: "chai@npm:4.4.1" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.0.8 + checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e + languageName: node + linkType: hard + "chalk@npm:^4.0.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -550,6 +1072,29 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + "color-convert@npm:^2.0.1": version: 2.0.1 resolution: "color-convert@npm:2.0.1" @@ -573,7 +1118,14 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.2": +"confbox@npm:^0.1.7": + version: 0.1.7 + resolution: "confbox@npm:0.1.7" + checksum: bde836c26f5154a348b0c0a757f8a0138929e5737e0553be3c4f07a056abca618b861aa63ac3b22d344789b56be99a1382928933e08cd500df00213bf4d8fb43 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -584,7 +1136,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -596,6 +1148,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: ^4.0.0 + checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -603,6 +1164,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa + languageName: node + linkType: hard + "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -648,6 +1216,130 @@ __metadata: languageName: node linkType: hard +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"esbuild@npm:^0.20.1": + version: 0.20.2 + resolution: "esbuild@npm:0.20.2" + dependencies: + "@esbuild/aix-ppc64": 0.20.2 + "@esbuild/android-arm": 0.20.2 + "@esbuild/android-arm64": 0.20.2 + "@esbuild/android-x64": 0.20.2 + "@esbuild/darwin-arm64": 0.20.2 + "@esbuild/darwin-x64": 0.20.2 + "@esbuild/freebsd-arm64": 0.20.2 + "@esbuild/freebsd-x64": 0.20.2 + "@esbuild/linux-arm": 0.20.2 + "@esbuild/linux-arm64": 0.20.2 + "@esbuild/linux-ia32": 0.20.2 + "@esbuild/linux-loong64": 0.20.2 + "@esbuild/linux-mips64el": 0.20.2 + "@esbuild/linux-ppc64": 0.20.2 + "@esbuild/linux-riscv64": 0.20.2 + "@esbuild/linux-s390x": 0.20.2 + "@esbuild/linux-x64": 0.20.2 + "@esbuild/netbsd-x64": 0.20.2 + "@esbuild/openbsd-x64": 0.20.2 + "@esbuild/sunos-x64": 0.20.2 + "@esbuild/win32-arm64": 0.20.2 + "@esbuild/win32-ia32": 0.20.2 + "@esbuild/win32-x64": 0.20.2 + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: bc88050fc1ca5c1bd03648f9979e514bdefb956a63aa3974373bb7b9cbac0b3aac9b9da1b5bdca0b3490e39d6b451c72815dbd6b7d7f978c91fbe9c9e9aa4e4c + languageName: node + linkType: hard + "escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -775,6 +1467,15 @@ __metadata: languageName: node linkType: hard +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -782,6 +1483,30 @@ __metadata: languageName: node linkType: hard +"execa@npm:^8.0.1": + version: 8.0.1 + resolution: "execa@npm:8.0.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^8.0.1 + human-signals: ^5.0.0 + is-stream: ^3.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^5.1.0 + onetime: ^6.0.0 + signal-exit: ^4.1.0 + strip-final-newline: ^3.0.0 + checksum: cac1bf86589d1d9b73bdc5dda65c52012d1a9619c44c526891956745f7b366ca2603d29fe3f7460bacc2b48c6eab5d6a4f7afe0534b31473d3708d1265545e1f + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + "fast-deep-equal@npm:3.1.3, fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -871,6 +1596,34 @@ __metadata: languageName: node linkType: hard +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: ^7.0.3 + checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 + languageName: node + linkType: hard + "fs.realpath@npm:^1.0.0": version: 1.0.0 resolution: "fs.realpath@npm:1.0.0" @@ -878,6 +1631,39 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + +"get-stream@npm:^8.0.1": + version: 8.0.1 + resolution: "get-stream@npm:8.0.1" + checksum: 01e3d3cf29e1393f05f44d2f00445c5f9ec3d1c49e8179b31795484b9c117f4c695e5e07b88b50785d5c8248a788c85d9913a79266fc77e3ef11f78f10f1b974 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -896,6 +1682,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.4.1 + resolution: "glob@npm:10.4.1" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^3.1.2 + minimatch: ^9.0.4 + minipass: ^7.1.2 + path-scurry: ^1.11.1 + bin: + glob: dist/esm/bin.mjs + checksum: 5d33c686c80bf6877f4284adf99a8c3cbb2a6eccbc92342943fe5d4b42c01d78c1881f2223d950c92a938d0f857e12e37b86a8e5483ab2141822e053b67d0dde + languageName: node + linkType: hard + "glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -933,6 +1734,13 @@ __metadata: languageName: node linkType: hard +"graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 + languageName: node + linkType: hard + "grapheme-splitter@npm:^1.0.4": version: 1.0.4 resolution: "grapheme-splitter@npm:1.0.4" @@ -947,6 +1755,49 @@ __metadata: languageName: node linkType: hard +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 + languageName: node + linkType: hard + +"human-signals@npm:^5.0.0": + version: 5.0.0 + resolution: "human-signals@npm:5.0.0" + checksum: 6504560d5ed91444f16bea3bd9dfc66110a339442084e56c3e7fa7bbdf3f406426d6563d662bdce67064b165eac31eeabfc0857ed170aaa612cf14ec9f9a464c + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + "ignore@npm:^5.2.0": version: 5.2.4 resolution: "ignore@npm:5.2.4" @@ -971,6 +1822,13 @@ __metadata: languageName: node linkType: hard +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -988,6 +1846,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: 1.1.0 + sprintf-js: ^1.1.3 + checksum: aa15f12cfd0ef5e38349744e3654bae649a34c3b10c77a674a167e99925d1549486c5b14730eebce9fea26f6db9d5e42097b00aa4f9f612e68c79121c71652dc + languageName: node + linkType: hard + "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -995,6 +1863,13 @@ __metadata: languageName: node linkType: hard +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -1004,6 +1879,13 @@ __metadata: languageName: node linkType: hard +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -1018,6 +1900,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^3.0.0": + version: 3.0.0 + resolution: "is-stream@npm:3.0.0" + checksum: 172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -1025,6 +1914,26 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + +"jackspeak@npm:^3.1.2": + version: 3.1.2 + resolution: "jackspeak@npm:3.1.2" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 134276d5f785c518930701a0dcba1f3b0e9ce3e5b1c3e300898e2ae0bbd9b5195088b77252bf2110768de072c426e9e39f47e13912b0b002da4a3f4ff6e16eac + languageName: node + linkType: hard + "js-sdsl@npm:^4.1.4": version: 4.4.2 resolution: "js-sdsl@npm:4.4.2" @@ -1032,6 +1941,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^9.0.0": + version: 9.0.0 + resolution: "js-tokens@npm:9.0.0" + checksum: 427d0db681caab0c906cfc78a0235bbe7b41712cee83f3f14785c1de079a1b1a85693cc8f99a3f71685d0d76acaa5b9c8920850b67f93d3eeb7ef186987d186c + languageName: node + linkType: hard + "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -1043,6 +1959,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 944f924f2bd67ad533b3850eee47603eed0f6ae425fd1ee8c760f477e8c34a05f144c1bd4f5a5dd1963141dc79a2c55f89ccc5ab77d039e7077f3ad196b64965 + languageName: node + linkType: hard + "json-buffer@npm:3.0.1": version: 3.0.1 resolution: "json-buffer@npm:3.0.1" @@ -1083,6 +2006,16 @@ __metadata: languageName: node linkType: hard +"local-pkg@npm:^0.5.0": + version: 0.5.0 + resolution: "local-pkg@npm:0.5.0" + dependencies: + mlly: ^1.4.2 + pkg-types: ^1.0.3 + checksum: b0a6931e588ad4f7bf4ab49faacf49e07fc4d05030f895aa055d46727a15b99300d39491cf2c3e3f05284aec65565fb760debb74c32e64109f4a101f9300d81a + languageName: node + linkType: hard + "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -1113,6 +2046,22 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6, loupe@npm:^2.3.7": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": + version: 10.2.2 + resolution: "lru-cache@npm:10.2.2" + checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e + languageName: node + linkType: hard + "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -1129,6 +2078,42 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.5": + version: 0.30.10 + resolution: "magic-string@npm:0.30.10" + dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 + checksum: 456fd47c39b296c47dff967e1965121ace35417eab7f45a99e681e725b8661b48e1573c366ee67a27715025b3740773c46b088f115421c7365ea4ea6fa10d399 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.1 + resolution: "make-fetch-happen@npm:13.0.1" + dependencies: + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 + http-cache-semantics: ^4.1.1 + is-lambda: ^1.0.1 + minipass: ^7.0.2 + minipass-fetch: ^3.0.0 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + proc-log: ^4.2.0 + promise-retry: ^2.0.1 + ssri: ^10.0.0 + checksum: 5c9fad695579b79488fa100da05777213dd9365222f85e4757630f8dd2a21a79ddd3206c78cfd6f9b37346819681782b67900ac847a57cf04190f52dda5343fd + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -1146,6 +2131,13 @@ __metadata: languageName: node linkType: hard +"mimic-fn@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-fn@npm:4.0.0" + checksum: 995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 + languageName: node + linkType: hard + "minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -1155,90 +2147,287 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.2": - version: 2.1.2 - resolution: "ms@npm:2.1.2" - checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f +"minimatch@npm:^9.0.4": + version: 9.0.4 + resolution: "minimatch@npm:9.0.4" + dependencies: + brace-expansion: ^2.0.1 + checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 languageName: node linkType: hard -"natural-compare-lite@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare-lite@npm:1.4.0" - checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 languageName: node linkType: hard -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d +"minipass-fetch@npm:^3.0.0": + version: 3.0.5 + resolution: "minipass-fetch@npm:3.0.5" + dependencies: + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: 8047d273236157aab27ab7cd8eab7ea79e6ecd63e8f80c3366ec076cb9a0fed550a6935bab51764369027c414647fd8256c2a20c5445fb250c483de43350de83 languageName: node linkType: hard -"node-cron@npm:^3.0.3": - version: 3.0.3 - resolution: "node-cron@npm:3.0.3" +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" dependencies: - uuid: 8.3.2 - checksum: 351c37491ebf717d0ae69cc941465de118e5c2ef5d48bc3f87c98556241b060f100402c8a618c7b86f9f626b44756b20d8b5385b70e52f80716f21e55db0f1c5 + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf languageName: node linkType: hard -"once@npm:^1.3.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" dependencies: - wrappy: 1 - checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b languageName: node linkType: hard -"optionator@npm:^0.9.1": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 - deep-is: ^0.1.3 - fast-levenshtein: ^2.0.6 - levn: ^0.4.1 - prelude-ls: ^1.2.1 - type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 languageName: node linkType: hard -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" dependencies: - yocto-queue: ^0.1.0 - checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 languageName: node linkType: hard -"p-locate@npm:^5.0.0": +"minipass@npm:^5.0.0": version: 5.0.0 - resolution: "p-locate@npm:5.0.0" - dependencies: - p-limit: ^3.0.2 - checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea languageName: node linkType: hard -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: ^3.0.0 - checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": + version: 7.1.2 + resolution: "minipass@npm:7.1.2" + checksum: 2bfd325b95c555f2b4d2814d49325691c7bee937d753814861b0b49d5edcda55cbbf22b6b6a60bb91eddac8668771f03c5ff647dcd9d0f798e9548b9cdc46ee3 languageName: node linkType: hard -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"mlly@npm:^1.4.2, mlly@npm:^1.7.0": + version: 1.7.0 + resolution: "mlly@npm:1.7.0" + dependencies: + acorn: ^8.11.3 + pathe: ^1.1.2 + pkg-types: ^1.1.0 + ufo: ^1.5.3 + checksum: c1548f4dd0e31ce15d293ebb7c61778bd28c405573dc43dcf799eaeb8f6b776d7dadd95e957d6631b9cc4bb963cd01079d58b7e2290ed540aa460e061bdbd1fa + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + languageName: node + linkType: hard + +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"node-cron@npm:^3.0.3": + version: 3.0.3 + resolution: "node-cron@npm:3.0.3" + dependencies: + uuid: 8.3.2 + checksum: 351c37491ebf717d0ae69cc941465de118e5c2ef5d48bc3f87c98556241b060f100402c8a618c7b86f9f626b44756b20d8b5385b70e52f80716f21e55db0f1c5 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.1.0 + resolution: "node-gyp@npm:10.1.0" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.1 + resolution: "nopt@npm:7.2.1" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: 6fa729cc77ce4162cfad8abbc9ba31d4a0ff6850c3af61d59b505653bef4781ec059f8890ecfe93ee8aa0c511093369cca88bfc998101616a2904e715bbbb7c9 + languageName: node + linkType: hard + +"npm-run-path@npm:^5.1.0": + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" + dependencies: + path-key: ^4.0.0 + checksum: ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"onetime@npm:^6.0.0": + version: 6.0.0 + resolution: "onetime@npm:6.0.0" + dependencies: + mimic-fn: ^4.0.0 + checksum: 0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 + languageName: node + linkType: hard + +"optionator@npm:^0.9.1": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-limit@npm:^5.0.0": + version: 5.0.0 + resolution: "p-limit@npm:5.0.0" + dependencies: + yocto-queue: ^1.0.0 + checksum: 87bf5837dee6942f0dbeff318436179931d9a97848d1b07dbd86140a477a5d2e6b90d9701b210b4e21fe7beaea2979dfde366e4f576fa644a59bd4d6a6371da7 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: ^3.0.0 + checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 languageName: node linkType: hard @@ -1256,6 +2445,23 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^4.0.0": + version: 4.0.0 + resolution: "path-key@npm:4.0.0" + checksum: 8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 + languageName: node + linkType: hard + +"path-scurry@npm:^1.11.1": + version: 1.11.1 + resolution: "path-scurry@npm:1.11.1" + dependencies: + lru-cache: ^10.2.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: 890d5abcd593a7912dcce7cf7c6bf7a0b5648e3dee6caf0712c126ca0a65c7f3d7b9d769072a4d1baf370f61ce493ab5b038d59988688e0c5f3f646ee3c69023 + languageName: node + linkType: hard + "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -1263,6 +2469,27 @@ __metadata: languageName: node linkType: hard +"pathe@npm:^1.1.1, pathe@npm:^1.1.2": + version: 1.1.2 + resolution: "pathe@npm:1.1.2" + checksum: ec5f778d9790e7b9ffc3e4c1df39a5bb1ce94657a4e3ad830c1276491ca9d79f189f47609884671db173400256b005f4955f7952f52a2aeb5834ad5fb4faf134 + languageName: node + linkType: hard + +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 + languageName: node + linkType: hard + "picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -1270,6 +2497,28 @@ __metadata: languageName: node linkType: hard +"pkg-types@npm:^1.0.3, pkg-types@npm:^1.1.0": + version: 1.1.1 + resolution: "pkg-types@npm:1.1.1" + dependencies: + confbox: ^0.1.7 + mlly: ^1.7.0 + pathe: ^1.1.2 + checksum: 78ee49eea8c03802ffbdc79dfb6a741f905a4053453280cd2f1149850523fdaf46d39ecb88c2c2f757cceb9883f234bb0e56371084b5895632bdb00ef0f7298f + languageName: node + linkType: hard + +"postcss@npm:^8.4.38": + version: 8.4.38 + resolution: "postcss@npm:8.4.38" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.0.0 + source-map-js: ^1.2.0 + checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -1277,6 +2526,41 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": ^29.6.3 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + +"proc-log@npm:^4.2.0": + version: 4.2.0 + resolution: "proc-log@npm:4.2.0" + checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + "punycode@npm:^2.1.0": version: 2.3.0 resolution: "punycode@npm:2.3.0" @@ -1291,6 +2575,13 @@ __metadata: languageName: node linkType: hard +"react-is@npm:^18.0.0": + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 + languageName: node + linkType: hard + "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -1298,6 +2589,13 @@ __metadata: languageName: node linkType: hard +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -1316,6 +2614,69 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.13.0": + version: 4.18.0 + resolution: "rollup@npm:4.18.0" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.18.0 + "@rollup/rollup-android-arm64": 4.18.0 + "@rollup/rollup-darwin-arm64": 4.18.0 + "@rollup/rollup-darwin-x64": 4.18.0 + "@rollup/rollup-linux-arm-gnueabihf": 4.18.0 + "@rollup/rollup-linux-arm-musleabihf": 4.18.0 + "@rollup/rollup-linux-arm64-gnu": 4.18.0 + "@rollup/rollup-linux-arm64-musl": 4.18.0 + "@rollup/rollup-linux-powerpc64le-gnu": 4.18.0 + "@rollup/rollup-linux-riscv64-gnu": 4.18.0 + "@rollup/rollup-linux-s390x-gnu": 4.18.0 + "@rollup/rollup-linux-x64-gnu": 4.18.0 + "@rollup/rollup-linux-x64-musl": 4.18.0 + "@rollup/rollup-win32-arm64-msvc": 4.18.0 + "@rollup/rollup-win32-ia32-msvc": 4.18.0 + "@rollup/rollup-win32-x64-msvc": 4.18.0 + "@types/estree": 1.0.5 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 54cde921e763017ce952ba76ec77d58dd9c01e3536c3be628d4af8c59d9b2f0e1e6a11b30fda44845c7b74098646cd972feb3bcd2f4a35d3293366f2eeb0a39e + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -1334,6 +2695,22 @@ __metadata: languageName: node linkType: hard +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"semver@npm:^7.3.5": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d + languageName: node + linkType: hard + "semver@npm:^7.3.7": version: 7.5.4 resolution: "semver@npm:7.5.4" @@ -1361,6 +2738,20 @@ __metadata: languageName: node linkType: hard +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 8aa5a98640ca09fe00d74416eca97551b3e42991614a3d1b824b115fc1401543650914f651ab1311518177e4d297e80b953f4cd4cd7ea1eabe824e8f2091de01 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -1368,7 +2759,94 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^6.0.1": +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.3 + resolution: "socks-proxy-agent@npm:8.0.3" + dependencies: + agent-base: ^7.1.1 + debug: ^4.3.4 + socks: ^2.7.1 + checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.8.3 + resolution: "socks@npm:2.8.3" + dependencies: + ip-address: ^9.0.5 + smart-buffer: ^4.2.0 + checksum: 7a6b7f6eedf7482b9e4597d9a20e09505824208006ea8f2c49b71657427f3c137ca2ae662089baa73e1971c62322d535d9d0cf1c9235cf6f55e315c18203eadd + languageName: node + linkType: hard + +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: a3fdac7b49643875b70864a9d9b469d87a40dfeaf5d34d9d0c5b1cda5fd7d065531fcb43c76357d62254c57184a7b151954156563a4d6a747015cfb41021cad0 + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.6 + resolution: "ssri@npm:10.0.6" + dependencies: + minipass: ^7.0.3 + checksum: 4603d53a05bcd44188747d38f1cc43833b9951b5a1ee43ba50535bdfc5fe4a0897472dbe69837570a5417c3c073377ef4f8c1a272683b401857f72738ee57299 + languageName: node + linkType: hard + +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 2d4dc4e64e2db796de4a3c856d5943daccdfa3dd092e452a1ce059c81e9a9c29e0b9badba91b43ef0d5ff5c04ee62feb3bcc559a804e16faf447bac2d883aa99 + languageName: node + linkType: hard + +"std-env@npm:^3.5.0": + version: 3.7.0 + resolution: "std-env@npm:3.7.0" + checksum: 4f489d13ff2ab838c9acd4ed6b786b51aa52ecacdfeaefe9275fcb220ff2ac80c6e95674723508fd29850a694569563a8caaaea738eb82ca16429b3a0b50e510 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" dependencies: @@ -1377,6 +2855,22 @@ __metadata: languageName: node linkType: hard +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-final-newline@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-final-newline@npm:3.0.0" + checksum: 23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -1384,6 +2878,15 @@ __metadata: languageName: node linkType: hard +"strip-literal@npm:^2.0.0": + version: 2.1.0 + resolution: "strip-literal@npm:2.1.0" + dependencies: + js-tokens: ^9.0.0 + checksum: 37c2072634d2de11a3644fe1bcf4abd566d85e89f0d8e8b10d35d04e7bef962e7c112fbe5b805ce63e59dfacedc240356eeef57976351502966b7c64b742c6ac + languageName: node + linkType: hard + "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -1393,6 +2896,20 @@ __metadata: languageName: node linkType: hard +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -1400,6 +2917,27 @@ __metadata: languageName: node linkType: hard +"tinybench@npm:^2.5.1": + version: 2.8.0 + resolution: "tinybench@npm:2.8.0" + checksum: 024a307c6a71f6e2903e110952457ee3dfa606093b45d7f49efcfd01d452650e099474080677ff650b0fd76b49074425ac68ff2a70561699a78515a278bf0862 + languageName: node + linkType: hard + +"tinypool@npm:^0.8.3": + version: 0.8.4 + resolution: "tinypool@npm:0.8.4" + checksum: d40c40e062d5eeae85dadc39294dde6bc7b9a7a7cf0c972acbbe5a2b42491dfd4c48381c1e48bbe02aff4890e63de73d115b2e7de2ce4c81356aa5e654a43caf + languageName: node + linkType: hard + +"tinyspy@npm:^2.2.0": + version: 2.2.1 + resolution: "tinyspy@npm:2.2.1" + checksum: 170d6232e87f9044f537b50b406a38fbfd6f79a261cd12b92879947bd340939a833a678632ce4f5c4a6feab4477e9c21cd43faac3b90b68b77dd0536c4149736 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -1457,6 +2995,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -1484,6 +3029,13 @@ __metadata: languageName: node linkType: hard +"ufo@npm:^1.5.3": + version: 1.5.3 + resolution: "ufo@npm:1.5.3" + checksum: 2f54fa543b2e689cc4ab341fe2194937afe37c5ee43cd782e6ecc184e36859e84d4197a43ae4cd6e9a56f793ca7c5b950dfff3f16fadaeef9b6b88b05c88c8ef + languageName: node + linkType: hard + "undici-types@npm:~5.26.4": version: 5.26.5 resolution: "undici-types@npm:5.26.5" @@ -1498,6 +3050,24 @@ __metadata: languageName: node linkType: hard +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -1516,6 +3086,111 @@ __metadata: languageName: node linkType: hard +"vite-node@npm:1.6.0": + version: 1.6.0 + resolution: "vite-node@npm:1.6.0" + dependencies: + cac: ^6.7.14 + debug: ^4.3.4 + pathe: ^1.1.1 + picocolors: ^1.0.0 + vite: ^5.0.0 + bin: + vite-node: vite-node.mjs + checksum: ce111c5c7a4cf65b722baa15cbc065b7bfdbf1b65576dd6372995f6a72b2b93773ec5df59f6c5f08cfe1284806597b44b832efcea50d5971102428159ff4379f + languageName: node + linkType: hard + +"vite@npm:^5.0.0": + version: 5.2.11 + resolution: "vite@npm:5.2.11" + dependencies: + esbuild: ^0.20.1 + fsevents: ~2.3.3 + postcss: ^8.4.38 + rollup: ^4.13.0 + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 3f9f976cc6ada93aca56abcc683a140e807725b351abc241a1ec0763ec561a4bf5760e1ad94de4e59505904ddaa88727de66af02f61ecf540c7720045de55d0a + languageName: node + linkType: hard + +"vitest@npm:^1.6.0": + version: 1.6.0 + resolution: "vitest@npm:1.6.0" + dependencies: + "@vitest/expect": 1.6.0 + "@vitest/runner": 1.6.0 + "@vitest/snapshot": 1.6.0 + "@vitest/spy": 1.6.0 + "@vitest/utils": 1.6.0 + acorn-walk: ^8.3.2 + chai: ^4.3.10 + debug: ^4.3.4 + execa: ^8.0.1 + local-pkg: ^0.5.0 + magic-string: ^0.30.5 + pathe: ^1.1.1 + picocolors: ^1.0.0 + std-env: ^3.5.0 + strip-literal: ^2.0.0 + tinybench: ^2.5.1 + tinypool: ^0.8.3 + vite: ^5.0.0 + vite-node: 1.6.0 + why-is-node-running: ^2.2.2 + peerDependencies: + "@edge-runtime/vm": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": 1.6.0 + "@vitest/ui": 1.6.0 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@types/node": + optional: true + "@vitest/browser": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: a9b9b97e5685d630e5d8d221e6d6cd2e1e9b5b2dd61e82042839ef11549c8d2d780cf696307de406dce804bf41c1219398cb20b4df570b3b47ad1e53af6bfe51 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -1527,6 +3202,51 @@ __metadata: languageName: node linkType: hard +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + +"why-is-node-running@npm:^2.2.2": + version: 2.2.2 + resolution: "why-is-node-running@npm:2.2.2" + dependencies: + siginfo: ^2.0.0 + stackback: 0.0.2 + bin: + why-is-node-running: cli.js + checksum: 50820428f6a82dfc3cbce661570bcae9b658723217359b6037b67e495255409b4c8bc7931745f5c175df71210450464517cab32b2f7458ac9c40b4925065200a + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2" @@ -1562,3 +3282,10 @@ __metadata: checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 languageName: node linkType: hard + +"yocto-queue@npm:^1.0.0": + version: 1.0.0 + resolution: "yocto-queue@npm:1.0.0" + checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 + languageName: node + linkType: hard From c8230334f2085757a31c716b2e4e7027f32c4309 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 28 May 2024 13:43:56 -0500 Subject: [PATCH 63/90] fix typings --- src/core/structures/context.ts | 5 ++++- src/types/core-modules.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index ef3b4591..2313f6b1 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -14,16 +14,19 @@ import * as assert from 'assert'; import type { ReplyOptions } from '../../types/utility'; import { fmt } from '../functions' +type ShitType = ChatInputCommandInteraction['options'] + /** * @since 1.0.0 * Provides values shared between * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { - get options() { return this.interaction.options; } + args(type: 'message') : string[] + args(type: 'interaction') : ShitType //TODO args(type: 'message'|'interaction') { switch(type) { diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index acf47084..c887b780 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -24,7 +24,7 @@ import { Awaitable, SernEventsMapping } from './utility'; export type SDT = { state: Record; deps: Dependencies; - type: 'slash' | 'text', + type: CommandType, params?: string }; From 898fdf52a3aae810b12b6e724495286af00ffdc2 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 31 May 2024 00:48:51 -0500 Subject: [PATCH 64/90] assets fn complete --- src/index.ts | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index c82e48f3..9ee4c0b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,20 +50,37 @@ export { export * from './core/presences' export * from './core/interfaces' import type { controller } from './core/create-plugins'; +import { AttachmentBuilder } from 'discord.js'; export type Controller = typeof controller export * from './core/create-plugins'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; export * from './core/ioc'; +export type AssetEncoding = "attachment"|"base64"|"binary"|"utf8" -export async function Asset(p: string) { - const assetsDir = path.resolve('assets'); +const ASSETS_DIR = path.resolve('assets'); +/** + * Reads an asset file from the 'assets' directory. + */ +export async function Asset(p: string, opts: { name?: string, encoding?: AssetEncoding }) { + const encoding = opts.encoding || 'utf8'; + + let relativePath: string; if (path.isAbsolute(p)) { - const relativePath = path.relative(assetsDir, "assets"+p); - return fs.readFile(path.join(assetsDir, relativePath), 'utf8'); + relativePath = path.relative(ASSETS_DIR, "assets" + p); + } else { + relativePath = p; + } + + const filePath = path.join(ASSETS_DIR, relativePath); + + if (encoding === 'attachment') { + const attachmentName = opts.name || path.basename(filePath); + return new AttachmentBuilder(filePath, { name: attachmentName }); + } else { + return fs.readFile(filePath, encoding); } - return fs.readFile(path.join(assetsDir, p), 'utf8'); } From 2120b18c4e53e298bc3568422781c1bda05a7177 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:43:55 -0500 Subject: [PATCH 65/90] more intuitive context.options and Asset typings --- src/core/structures/context.ts | 21 ++++++--------------- src/index.ts | 15 ++++++++++----- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 2313f6b1..59dcbb0c 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -14,7 +14,6 @@ import * as assert from 'assert'; import type { ReplyOptions } from '../../types/utility'; import { fmt } from '../functions' -type ShitType = ChatInputCommandInteraction['options'] /** * @since 1.0.0 @@ -22,21 +21,13 @@ type ShitType = ChatInputCommandInteraction['options'] * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { + get options() { - return this.interaction.options; - } - args(type: 'message') : string[] - args(type: 'interaction') : ShitType - //TODO - args(type: 'message'|'interaction') { - switch(type) { - case 'message': { - const [, ...rest] = fmt(this.message.content, this.prefix); - return rest; - }; - case 'interaction': { - return this.interaction.options; - }; + if(this.isMessage()) { + const [, ...rest] = fmt(this.message.content, this.prefix); + return rest; + } else { + return this.interaction.options; } } diff --git a/src/index.ts b/src/index.ts index 9ee4c0b1..a9a9f1f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,11 +60,18 @@ export * from './core/ioc'; export type AssetEncoding = "attachment"|"base64"|"binary"|"utf8" const ASSETS_DIR = path.resolve('assets'); + + + /** * Reads an asset file from the 'assets' directory. + * If encoding is 'attachment', a discord.js AttachmentBuilder is provided, else + * fs.promises.readFile is called. The default is utf8. */ -export async function Asset(p: string, opts: { name?: string, encoding?: AssetEncoding }) { - const encoding = opts.encoding || 'utf8'; +export async function Asset(p: string, opts?: { name?: string, encoding: Exclude }): Promise; +export async function Asset(p: string, opts?: { name?: string, encoding: 'attachment' }): Promise; +export async function Asset(p: string, opts?: { name?: string, encoding: AssetEncoding }): Promise { + const encoding = opts?.encoding || 'utf8'; let relativePath: string; if (path.isAbsolute(p)) { @@ -76,11 +83,9 @@ export async function Asset(p: string, opts: { name?: string, encoding?: AssetEn const filePath = path.join(ASSETS_DIR, relativePath); if (encoding === 'attachment') { - const attachmentName = opts.name || path.basename(filePath); + const attachmentName = opts?.name || path.basename(filePath); return new AttachmentBuilder(filePath, { name: attachmentName }); } else { return fs.readFile(filePath, encoding); } } - - From 45665292ae99b70b419575eef2271e29523a30e0 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 4 Jun 2024 00:48:30 -0500 Subject: [PATCH 66/90] add init hooks not firing --- src/core/ioc/container.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts index 2a959fed..5f2e02a5 100644 --- a/src/core/ioc/container.ts +++ b/src/core/ioc/container.ts @@ -4,7 +4,7 @@ */ function hasCallableMethod(obj: object, name: PropertyKey) { //@ts-ignore - return Object.hasOwn(obj, name) && typeof obj[name] == 'function'; + return typeof obj[name] == 'function'; } /** * A Depedency injection container capable of adding singletons, firing hooks, and managing IOC within an application @@ -15,7 +15,6 @@ export class Container { private finished_init = false; constructor(options: { autowire: boolean; path?: string }) { if(options.autowire) { /* noop */ } - } addHook(name: string, callback: Function) { @@ -25,11 +24,13 @@ export class Container { this.hooks.get(name)!.push(callback); } private registerHooks(hookname: string, insert: object) { + if(hasCallableMethod(insert, hookname)) { //@ts-ignore this.addHook(hookname, () => insert[hookname]()) } } + addSingleton(key: string, insert: object) { if(typeof insert !== 'object') { throw Error("Inserted object must be an object"); From bf071b7af4aca1107129b05c5f50a29d73ca9834 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 8 Jun 2024 00:20:24 -0500 Subject: [PATCH 67/90] -file,-updateModule,publish? --- src/core/id.ts | 2 +- src/core/operators.ts | 52 ----------------------------- src/core/presences.ts | 1 + src/core/structures/context.ts | 13 +++++++- src/core/structures/core-context.ts | 8 ----- src/handlers/event-utils.ts | 50 +++++++++++++++++++-------- src/handlers/interaction.ts | 3 +- src/handlers/message.ts | 7 ++-- src/sern.ts | 14 ++++++++ src/types/core-modules.ts | 5 +-- test/handlers/index.test.ts | 10 ++++-- 11 files changed, 78 insertions(+), 87 deletions(-) delete mode 100644 src/core/operators.ts diff --git a/src/core/id.ts b/src/core/id.ts index 3f91f92d..b795945c 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -44,8 +44,8 @@ const TypeMap = new Map([[CommandType.Text, 0], [CommandType.CtxUser, ApplicationCommandType.User], [CommandType.CtxMsg, ApplicationCommandType.Message], [CommandType.Button, ComponentType.Button], - [CommandType.Modal, InteractionType.ModalSubmit], [CommandType.StringSelect, ComponentType.StringSelect], + [CommandType.Modal, InteractionType.ModalSubmit], [CommandType.UserSelect, ComponentType.UserSelect], [CommandType.MentionableSelect, ComponentType.MentionableSelect], [CommandType.RoleSelect, ComponentType.RoleSelect], diff --git a/src/core/operators.ts b/src/core/operators.ts deleted file mode 100644 index 2d06a905..00000000 --- a/src/core/operators.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * This file holds sern's rxjs operators used for processing data. - * Each function should be modular and testable, not bound to discord / sern - * and independent of each other. - */ -import { - concatMap, - EMPTY, - fromEvent, - Observable, - of, - OperatorFunction, - share, -} from 'rxjs'; -import type { Emitter, ErrorHandling, Logging } from './interfaces'; -import util from 'node:util'; -import type { Result } from 'ts-results-es'; - -/** - * if {src} is true, mapTo V, else ignore - * @param item - */ -export function filterMapTo(item: () => V): OperatorFunction { - return concatMap(keep => keep ? of(item()) : EMPTY); -} - -export const arrayifySource = (src: T) => - Array.isArray(src) ? src : [src]; - -export const sharedEventStream = (e: Emitter, eventName: string) => - (fromEvent(e, eventName) as Observable).pipe(share()); - -export function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { - return (pload: unknown, caught: Observable) => { - // This is done to fit the ErrorHandling contract - if(!emitter.emit('error', pload)) { - const err = pload instanceof Error ? pload : Error(util.inspect(pload, { colors: true })); - logging?.error({ message: util.inspect(pload) }); - crashHandler.updateAlive(err); - } - return caught; - }; -} -//// Temporary until i get rxjs operators working on ts-results-es -export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => - concatMap(result => { - if(result.isOk()) { - return of(result.value) - } - onErr(result.error); - return EMPTY; - }) diff --git a/src/core/presences.ts b/src/core/presences.ts index 0031c1f9..d006c44a 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -61,4 +61,5 @@ export const Presence = { export type PresenceConfig = { inject?: [...T] execute: (...v: IntoDependencies) => PresenceResult; + }; diff --git a/src/core/structures/context.ts b/src/core/structures/context.ts index 59dcbb0c..69b460cb 100644 --- a/src/core/structures/context.ts +++ b/src/core/structures/context.ts @@ -13,6 +13,7 @@ import { Result, Ok, Err } from 'ts-results-es'; import * as assert from 'assert'; import type { ReplyOptions } from '../../types/utility'; import { fmt } from '../functions' +import { SernError } from './enums'; /** @@ -21,7 +22,7 @@ import { fmt } from '../functions' * Message and ChatInputCommandInteraction */ export class Context extends CoreContext { - + get options() { if(this.isMessage()) { const [, ...rest] = fmt(this.message.content, this.prefix); @@ -30,6 +31,7 @@ export class Context extends CoreContext { return this.interaction.options; } } + protected constructor(protected ctx: Result, private __prefix?: string) { @@ -94,6 +96,15 @@ export class Context extends CoreContext { .mapErr(i => i.member)); } + get message(): Message { + return this.ctx.expect(SernError.MismatchEvent); + } + + get interaction(): ChatInputCommandInteraction { + return this.ctx.expectErr(SernError.MismatchEvent); + } + + public get client(): Client { return safeUnwrap(this.ctx .map(m => m.client) diff --git a/src/core/structures/core-context.ts b/src/core/structures/core-context.ts index 8ffd6a08..73a92d58 100644 --- a/src/core/structures/core-context.ts +++ b/src/core/structures/core-context.ts @@ -1,5 +1,4 @@ import { Result as Either } from 'ts-results-es'; -import { SernError } from './enums'; import * as assert from 'node:assert'; /** @@ -9,13 +8,6 @@ export abstract class CoreContext { protected constructor(protected ctx: Either) { assert.ok(typeof ctx === 'object' && ctx != null, "Context was nonobject or null"); } - get message(): M { - return this.ctx.expect(SernError.MismatchEvent); - } - get interaction(): I { - return this.ctx.expectErr(SernError.MismatchEvent); - } - public isMessage(): this is CoreContext { return this.ctx.isOk(); } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 1919a253..129d456a 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -1,11 +1,12 @@ import type { Interaction, Message, BaseInteraction } from 'discord.js'; +import util from 'node:util'; import { EMPTY, type Observable, concatMap, filter, throwError, fromEvent, map, type OperatorFunction, - catchError, finalize, pipe, from, take, + catchError, finalize, pipe, from, take, share, of, } from 'rxjs'; import * as Id from '../core/id' -import type { Emitter } from '../core/interfaces'; +import type { Emitter, ErrorHandling, Logging } from '../core/interfaces'; import { SernError } from '../core/structures/enums' import { Err, Ok, Result } from 'ts-results-es'; import type { UnpackedDependencies } from '../types/utility'; @@ -15,9 +16,22 @@ import { Context } from '../core/structures/context'; import { CommandType } from '../core/structures/enums' import { inspect } from 'node:util' import { disposeAll } from '../core/ioc/base'; -import { arrayifySource, handleError } from '../core/operators'; import { resultPayload, isAutocomplete, treeSearch, fmt } from '../core/functions' +function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { + return (pload: unknown, caught: Observable) => { + // This is done to fit the ErrorHandling contract + if(!emitter.emit('error', pload)) { + const err = pload instanceof Error ? pload : Error(util.inspect(pload, { colors: true })); + logging?.error({ message: util.inspect(pload) }); + crashHandler.updateAlive(err); + } + return caught; + }; +} +const arrayify= (src: T) => + Array.isArray(src) ? src : [src]; + interface ExecutePayload { module: Module; args: unknown[]; @@ -26,8 +40,20 @@ interface ExecutePayload { [key: string]: unknown } +export const filterTap = (onErr: (e: R) => void): OperatorFunction, K> => + concatMap(result => { + if(result.isOk()) { + return of(result.value) + } + onErr(result.error); + return EMPTY; + }) + +export const sharedEventStream = (e: Emitter, eventName: string) => + (fromEvent(e, eventName) as Observable).pipe(share()); + function intoPayload(module: Module, deps: Dependencies) { - return pipe(map(arrayifySource), + return pipe(map(arrayify), map(args => ({ module, args, deps })), map(p => p.args)); } @@ -151,10 +177,7 @@ export function createMessageHandler( * @param module the module that will be executed with task * @param task the deferred execution which will be called */ -export function executeModule( - emitter: Emitter, - { module, args }: ExecutePayload, -) { +export function executeModule(emitter: Emitter, { module, args }: ExecutePayload) { return from(Result.wrapAsync(async () => module.execute(...args))) .pipe(concatMap(result => { if (result.isOk()) { @@ -181,6 +204,7 @@ export function createResultResolver(config: { const { onStop, onNext } = config; return async (payload: ExecutePayload) => { const task = await callPlugins(payload); + if (!task) throw Error("Plugin did not return anything."); if(task.isOk()) { return onNext(payload, task.value) as Output; } else { @@ -189,18 +213,16 @@ export function createResultResolver(config: { }; }; -export async function callInitPlugins(module: Module, deps: Dependencies, emit?: boolean ) { +export async function callInitPlugins(module: Module, deps: Dependencies, emit?: boolean) { let _module = module; const emitter = deps['@sern/emitter']; for(const plugin of _module.plugins ?? []) { const res = await plugin.execute({ - module, absPath: _module.meta.absPath, - updateModule: (partial: Partial) => { - _module = { ..._module, ...partial }; - return _module; - }, + module: _module, + absPath: _module.meta.absPath, deps }); + if (!res) throw Error("Plugin did not return anything."); if(res.isErr()) { if(emit) { emitter?.emit('module.register', diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index 11696c4a..0c95e1d3 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -1,7 +1,6 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap, EMPTY } from 'rxjs'; -import { filterTap, sharedEventStream } from '../core/operators' -import { createInteractionHandler, executeModule, intoTask } from './event-utils'; +import { createInteractionHandler, executeModule, intoTask, sharedEventStream, filterTap } from './event-utils'; import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 125889f2..60b3b8de 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,9 +1,8 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { createMessageHandler, executeModule, intoTask } from './event-utils'; -import { PayloadType, SernError } from '../core/structures/enums' +import { createMessageHandler, executeModule, intoTask, sharedEventStream, filterTap} from './event-utils'; +import { SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' -import { filterTap, sharedEventStream } from '../core/operators' import { UnpackedDependencies } from '../types/utility'; import type { Emitter } from '../core/interfaces'; @@ -36,7 +35,7 @@ function (deps: UnpackedDependencies, defaultPrefix?: string) { const msgCommands$ = handle(isNonBot(defaultPrefix)); return msgCommands$.pipe( - filterTap(e => emitter.emit('warning', resultPayload(PayloadType.Warning, undefined, e))), + filterTap(e => emitter.emit('warning', resultPayload('warning', undefined, e))), concatMap(intoTask(module => { const result = resultPayload('failure', module, SernError.PluginFailure); emitter.emit('module.activate', result); diff --git a/src/sern.ts b/src/sern.ts index 3cd067de..5ea5b1ea 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -10,6 +10,7 @@ import { handleCrash } from './handlers/event-utils'; import { useContainerRaw } from './core/ioc/global'; import { UnpackedDependencies } from './types/utility'; import type { PresenceResult } from './core/presences'; +import fs from 'fs/promises' interface Wrapper { commands: string; @@ -63,3 +64,16 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { // listening to the message stream and interaction stream merge(messages$, interactions$).pipe(handleCrash(deps)).subscribe(); } + + +export async function publisher() { + const directoryToWatch = "./src/commands"; + const watcher = fs.watch(directoryToWatch, { recursive: true }, ); + for await (const { eventType, filename } of watcher) { + switch(eventType) { + case 'change': { + console.log('change', filename) + } break; + } + } +} diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index c887b780..2e8ebb35 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -14,6 +14,7 @@ import type { StringSelectMenuInteraction, UserContextMenuCommandInteraction, UserSelectMenuInteraction, + ChatInputCommandInteraction, } from 'discord.js'; import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' @@ -123,14 +124,14 @@ export interface DiscordEventCommand Awaitable; + execute: (ctx: Context & { get options(): string[] }, tbd: SDT) => Awaitable; } export interface SlashCommand extends Module { type: CommandType.Slash; description: string; options?: SernOptionsData[]; - execute: (ctx: Context, tbd: SDT) => Awaitable; + execute: (ctx: Context & { get options(): ChatInputCommandInteraction['options']}, tbd: SDT) => Awaitable; } export interface BothCommand extends Module { diff --git a/test/handlers/index.test.ts b/test/handlers/index.test.ts index 315eb4ca..77a13589 100644 --- a/test/handlers/index.test.ts +++ b/test/handlers/index.test.ts @@ -56,9 +56,11 @@ vi.mock('discord.js', async (importOriginal) => { }); function createRandomPlugin (s: 'go', mut?: Partial) { - return CommandInitPlugin(({ module, updateModule }) => { + return CommandInitPlugin(({ module }) => { if(mut) { - updateModule(mut) + for(const [k,v] of Object.entries(mut)) { + module[k] = v + } } return s == 'go' ? controller.next() @@ -105,8 +107,10 @@ test ('mutate with init plugins', async () => { const deps = mockDeps() const plugins = createRandomPlugin('go', { name: "abc" }) const mod = createRandomModule([plugins]) + console.log(mod) const s = await callInitPlugins(mod, deps, false) - expect(s.name).not.equal(mod.name) + console.log(s) + expect("abc").equal(s.name) }) From 67bb4d4b9fa126f24874a3de1d4378e9fe9aca07 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:22:10 -0500 Subject: [PATCH 68/90] fix: ioc deps not created correctly --- src/core/ioc/base.ts | 2 +- src/index.ts | 1 + src/sern.ts | 14 -------------- src/types/core-plugin.ts | 7 ++----- src/types/utility.ts | 8 +++----- 5 files changed, 7 insertions(+), 25 deletions(-) diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index 2fe45ff8..b632ba6d 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -51,7 +51,6 @@ type ValidDependencyConfig = export async function makeDependencies (conf: ValidDependencyConfig) { const container = await __init_container({ autowire: false }); - conf(dependencyBuilder(container)); //We only include logger if it does not exist const includeLogger = !container.hasKey('@sern/logger'); @@ -62,6 +61,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { __add_container('@sern/modules', new Map) __add_container('@sern/emitter', new EventEmitter) __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) + conf(dependencyBuilder(container)); await container.ready(); } diff --git a/src/index.ts b/src/index.ts index a9a9f1f4..6baefdaf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -89,3 +89,4 @@ export async function Asset(p: string, opts?: { name?: string, encoding: AssetEn return fs.readFile(filePath, encoding); } } + diff --git a/src/sern.ts b/src/sern.ts index 5ea5b1ea..3cd067de 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -10,7 +10,6 @@ import { handleCrash } from './handlers/event-utils'; import { useContainerRaw } from './core/ioc/global'; import { UnpackedDependencies } from './types/utility'; import type { PresenceResult } from './core/presences'; -import fs from 'fs/promises' interface Wrapper { commands: string; @@ -64,16 +63,3 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { // listening to the message stream and interaction stream merge(messages$, interactions$).pipe(handleCrash(deps)).subscribe(); } - - -export async function publisher() { - const directoryToWatch = "./src/commands"; - const watcher = fs.watch(directoryToWatch, { recursive: true }, ); - for await (const { eventType, filename } of watcher) { - switch(eventType) { - case 'change': { - console.log('change', filename) - } break; - } - } -} diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index bd01f59a..89f8a12a 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -38,20 +38,17 @@ export interface InitArgs = Processed> { module: T; absPath: string; deps: Dependencies - updateModule: (module: Partial) => T } export interface Plugin { type: PluginType; execute: (...args: Args) => PluginResult; } -export interface InitPlugin { +export interface InitPlugin extends Plugin { type: PluginType.Init; - execute: (...args: Args) => PluginResult; } -export interface ControlPlugin { +export interface ControlPlugin extends Plugin { type: PluginType.Control; - execute: (...args: Args) => PluginResult; } export type AnyPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; diff --git a/src/types/utility.ts b/src/types/utility.ts index 64c95da3..dcbe3b22 100644 --- a/src/types/utility.ts +++ b/src/types/utility.ts @@ -1,5 +1,4 @@ import type { InteractionReplyOptions, MessageReplyOptions } from 'discord.js'; -import type { PayloadType } from '../core/structures/enums'; import type { Module } from './core-modules'; import type { Result } from 'ts-results-es'; @@ -17,11 +16,10 @@ export interface SernEventsMapping { } export type Payload = - | { type: PayloadType.Success; module: Module } - | { type: PayloadType.Failure; module?: Module; reason: string | Error } - | { type: PayloadType.Warning; module: undefined; reason: string }; + | { type: 'success'; module: Module } + | { type: 'failure'; module?: Module; reason: string | Error } + | { type: 'warning'; module: undefined; reason: string }; -//https://github.com/molszanski/iti/blob/0a3a006113b4176316c308805314a135c0f47902/iti/src/_utils.ts#L29C1-L29C76 export type UnpackFunction = T extends (...args: any) => infer U ? U : T export type UnpackedDependencies = { [K in keyof Dependencies]: UnpackFunction From 222ecd9b61ad0b94830a2a9444118f01e1b7d6cd Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Tue, 11 Jun 2024 00:27:36 -0500 Subject: [PATCH 69/90] documentation, add json for Asset --- src/core/id.ts | 6 ++-- src/core/ioc/base.ts | 11 ++++++- src/core/ioc/index.ts | 10 +++++-- src/core/modules.ts | 4 ++- src/core/presences.ts | 11 ++++--- src/index.ts | 15 ++++++---- src/types/core-modules.ts | 5 +++- src/types/core-plugin.ts | 2 +- .../index.test.ts => handlers.test.ts} | 30 +++++++++---------- 9 files changed, 58 insertions(+), 36 deletions(-) rename test/{handlers/index.test.ts => handlers.test.ts} (81%) diff --git a/src/core/id.ts b/src/core/id.ts index b795945c..f759ef4a 100644 --- a/src/core/id.ts +++ b/src/core/id.ts @@ -1,7 +1,7 @@ import { ApplicationCommandType, ComponentType, type Interaction, InteractionType } from 'discord.js'; import { CommandType, EventType } from './structures/enums'; -const parseParams = (event: { customId: string }, id: string, append: string) => { +const parseParams = (event: { customId: string }, append: string) => { const hasSlash = event.customId.indexOf('/') if(hasSlash === -1) { return { id:event.customId+append }; @@ -18,7 +18,7 @@ const parseParams = (event: { customId: string }, id: string, append: string) => export function reconstruct(event: T) { switch (event.type) { case InteractionType.MessageComponent: { - const data = parseParams(event, event.customId, `_C${event.componentType}`) + const data = parseParams(event, `_C${event.componentType}`) return [data]; } case InteractionType.ApplicationCommand: @@ -26,7 +26,7 @@ export function reconstruct(event: T) { return [{ id: `${event.commandName}_A${event.commandType}` }, { id: `${event.commandName}_B` }]; //Modal interactions are classified as components for sern case InteractionType.ModalSubmit: { - const data = parseParams(event, event.customId, '_M'); + const data = parseParams(event, '_M'); return [data]; } } diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index b632ba6d..fcf878da 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -48,7 +48,16 @@ const dependencyBuilder = (container: Container) => { type ValidDependencyConfig = | ((c: ReturnType) => any) - +/** + * makeDependencies constructs a dependency injection container for sern handler to use. + * This is required to start the handler, and is to be called before Sern.init. + * @example + * ```ts + * await makeDependencies(({ add }) => { + * add('@sern/client', new Client({ intents, partials }) + * }) + * ``` + */ export async function makeDependencies (conf: ValidDependencyConfig) { const container = await __init_container({ autowire: false }); //We only include logger if it does not exist diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index ab574760..e06055eb 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -33,7 +33,10 @@ export function Services(...keys: [...T] * Creates a singleton object. * @param cb */ -export function single(cb: () => T) { return cb(); } +export function single(cb: () => T) { + console.log('The `single` function is deprecated and has no effect') + return cb(); +} /** * @deprecated @@ -41,5 +44,8 @@ export function single(cb: () => T) { return cb(); } * Creates a transient object * @param cb */ -export function transient(cb: () => () => T) { return cb()(); } +export function transient(cb: () => () => T) { + console.log('The `transient` function is deprecated and has no effect') + return cb()(); +} diff --git a/src/core/modules.ts b/src/core/modules.ts index 06d1bf13..84d389e9 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -27,7 +27,9 @@ export function commandModule(mod: InputCommand): Module { * @param mod */ export function eventModule(mod: InputEvent): Module { - return mod as Module; + const [onEvent, plugins] = partitionPlugins(mod.plugins); + if(onEvent.length !== 0) throw Error("Event modules cannot have ControlPlugins"); + return { ...mod, plugins } as Module; } /** Create event modules from discord.js client events, diff --git a/src/core/presences.ts b/src/core/presences.ts index d006c44a..78b1024d 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -31,27 +31,26 @@ export const Presence = { /** * @example * Presence - * .of({ - * activities: [{ name: "deez nuts" }] - * }) //starts the presence with "deez nuts". + * .of({ activities: [{ name: "deez nuts" }] }) //starts presence with "deez nuts". * .repeated(prev => { * return { * afk: true, * activities: prev.activities?.map(s => ({ ...s, name: s.name+"s" })) * }; - * }, 10000)) //every 10 s, the callback sets the presence to the returned one. + * }, 10000)) //every 10 s, the callback sets the presence to the value returned. */ repeated: (onRepeat: PresenceReduce, repeat: number | [Emitter, string]) => { return { repeat, onRepeat, ...root } }, /** * @example + * ```ts * Presence.of({ * activities: [ * { name: "Chilling out" } * ] - * }) - * .once() // Sets the presence once, with what's provided in '.of()' + * }).once() // Sets the presence once, with what's provided in '.of()' + * ``` */ once: () => root }; diff --git a/src/index.ts b/src/index.ts index 6baefdaf..54c042eb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ import path from 'node:path' export * as Sern from './sern'; export type { + Module, CommandModule, EventModule, BothCommand, @@ -57,18 +58,17 @@ export { CommandType, PluginType, PayloadType, EventType } from './core/structur export { Context } from './core/structures/context'; export * from './core/ioc'; -export type AssetEncoding = "attachment"|"base64"|"binary"|"utf8" - +export type AssetEncoding = "attachment"|"base64"|"binary"|"utf8"|"json" +type PartialAssetEncoding = Exclude const ASSETS_DIR = path.resolve('assets'); - - /** * Reads an asset file from the 'assets' directory. * If encoding is 'attachment', a discord.js AttachmentBuilder is provided, else - * fs.promises.readFile is called. The default is utf8. + * fs.promises.readFile is called. The default encoding is utf8. */ -export async function Asset(p: string, opts?: { name?: string, encoding: Exclude }): Promise; +export async function Asset(p: string, opts?: { name?: never, encoding: PartialAssetEncoding }): Promise; +export async function Asset(p: string, opts?: { name?: never, encoding: 'json' }): Promise; export async function Asset(p: string, opts?: { name?: string, encoding: 'attachment' }): Promise; export async function Asset(p: string, opts?: { name?: string, encoding: AssetEncoding }): Promise { const encoding = opts?.encoding || 'utf8'; @@ -85,6 +85,9 @@ export async function Asset(p: string, opts?: { name?: string, encoding: AssetEn if (encoding === 'attachment') { const attachmentName = opts?.name || path.basename(filePath); return new AttachmentBuilder(filePath, { name: attachmentName }); + } else if(encoding === 'json') { + return fs.readFile(filePath, 'utf8') + .then(JSON.parse) } else { return fs.readFile(filePath, encoding); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 2e8ebb35..1b302d6b 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -198,7 +198,10 @@ type EventModulesNoPlugins = { }; export type InputEvent = { - [T in EventType]: EventModulesNoPlugins[T] & { once?: boolean }; + [T in EventType]: EventModulesNoPlugins[T] & { + once?: boolean; + plugins?: InitPlugin[] + }; }[EventType]; export type InputCommand = { diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 89f8a12a..7b0c9489 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -53,7 +53,7 @@ export interface ControlPlugin extends Plugin export type AnyPlugin = ControlPlugin | InitPlugin<[InitArgs>]>; -export type CommandArgs = CommandArgsMatrix[I] +export type CommandArgs = CommandArgsMatrix[I] interface CommandArgsMatrix { [CommandType.Text]: [Context, SDT]; diff --git a/test/handlers/index.test.ts b/test/handlers.test.ts similarity index 81% rename from test/handlers/index.test.ts rename to test/handlers.test.ts index 77a13589..35e6c02f 100644 --- a/test/handlers/index.test.ts +++ b/test/handlers.test.ts @@ -1,14 +1,14 @@ //@ts-nocheck import { beforeEach, describe, expect, vi, it, test } from 'vitest'; -import { callInitPlugins, eventDispatcher } from '../../src/handlers/event-utils'; +import { callInitPlugins, eventDispatcher } from '../src/handlers/event-utils'; import { Client, ChatInputCommandInteraction } from 'discord.js' import { faker } from '@faker-js/faker'; -import { Module } from '../../src/types/core-modules'; -import { Processed } from '../../src/types/core-modules'; +import { Module } from '../src/types/core-modules'; +import { Processed } from '../src/types/core-modules'; import { EventEmitter } from 'events'; -import { EventType } from '../../dist/core/structures/enums'; -import { CommandControlPlugin, CommandInitPlugin, CommandType, controller } from '../../src'; +import { EventType } from '../dist/core/structures/enums'; +import { CommandControlPlugin, CommandInitPlugin, CommandType, controller } from '../src'; vi.mock('discord.js', async (importOriginal) => { const mod = await importOriginal() @@ -129,16 +129,16 @@ test('form sdt', async () => { "plugin2/abc": faker.git.branch(), "plugin3/cheese": faker.person.jobArea() } - -// const plugin = CommandControlPlugin((ctx,sdt) => { -// return controller.next({ "plugin/abc": expectedObject['plugin/abc'] }); -// }); -// const plugin2 = CommandControlPlugin((ctx,sdt) => { -// return controller.next({ "plugin2/abc": expectedObject['plugin2/abc'] }); -// }); -// const plugin3 = CommandControlPlugin((ctx,sdt) => { -// return controller.next({ "plugin3/cheese": expectedObject['plugin3/cheese'] }); -// }); + + const plugin = CommandControlPlugin((ctx,sdt) => { + return controller.next({ "plugin/abc": expectedObject['plugin/abc'] }); + }); + const plugin2 = CommandControlPlugin((ctx,sdt) => { + return controller.next({ "plugin2/abc": expectedObject['plugin2/abc'] }); + }); + const plugin3 = CommandControlPlugin((ctx,sdt) => { + return controller.next({ "plugin3/cheese": expectedObject['plugin3/cheese'] }); + }); }) From 30feb790b1d6e2c43c2e4581659511d69fc1ca07 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 12 Jun 2024 23:09:13 -0500 Subject: [PATCH 70/90] remove asset --- src/handlers/event-utils.ts | 2 +- src/handlers/interaction.ts | 3 +-- src/index.ts | 37 +------------------------------------ 3 files changed, 3 insertions(+), 39 deletions(-) diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 129d456a..813f6ed4 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -222,7 +222,7 @@ export async function callInitPlugins(module: Module, deps: Dependencies, emit?: absPath: _module.meta.absPath, deps }); - if (!res) throw Error("Plugin did not return anything."); + if (!res) throw Error("Plugin did not return anything. " + inspect(plugin, false, Infinity, true)); if(res.isErr()) { if(emit) { emitter?.emit('module.register', diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index 0c95e1d3..e09eeef5 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -4,13 +4,12 @@ import { createInteractionHandler, executeModule, intoTask, sharedEventStream, f import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; -import { Emitter } from '../core/interfaces'; export default function interactionHandler(deps: UnpackedDependencies, defaultPrefix?: string) { //i wish javascript had clojure destructuring const { '@sern/client': client, '@sern/emitter': emitter } = deps - const interactionStream$ = sharedEventStream(client as unknown as Emitter, 'interactionCreate'); + const interactionStream$ = sharedEventStream(client, 'interactionCreate'); const handle = createInteractionHandler(interactionStream$, deps, defaultPrefix); const interactionHandler$ = merge(handle(isMessageComponent), diff --git a/src/index.ts b/src/index.ts index 54c042eb..81af075e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,3 @@ -import fs from 'node:fs/promises' -import path from 'node:path' export * as Sern from './sern'; export type { @@ -51,45 +49,12 @@ export { export * from './core/presences' export * from './core/interfaces' import type { controller } from './core/create-plugins'; -import { AttachmentBuilder } from 'discord.js'; export type Controller = typeof controller export * from './core/create-plugins'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; +export { Asset } from './core/structures/asset'; export * from './core/ioc'; -export type AssetEncoding = "attachment"|"base64"|"binary"|"utf8"|"json" -type PartialAssetEncoding = Exclude -const ASSETS_DIR = path.resolve('assets'); -/** - * Reads an asset file from the 'assets' directory. - * If encoding is 'attachment', a discord.js AttachmentBuilder is provided, else - * fs.promises.readFile is called. The default encoding is utf8. - */ -export async function Asset(p: string, opts?: { name?: never, encoding: PartialAssetEncoding }): Promise; -export async function Asset(p: string, opts?: { name?: never, encoding: 'json' }): Promise; -export async function Asset(p: string, opts?: { name?: string, encoding: 'attachment' }): Promise; -export async function Asset(p: string, opts?: { name?: string, encoding: AssetEncoding }): Promise { - const encoding = opts?.encoding || 'utf8'; - - let relativePath: string; - if (path.isAbsolute(p)) { - relativePath = path.relative(ASSETS_DIR, "assets" + p); - } else { - relativePath = p; - } - - const filePath = path.join(ASSETS_DIR, relativePath); - - if (encoding === 'attachment') { - const attachmentName = opts?.name || path.basename(filePath); - return new AttachmentBuilder(filePath, { name: attachmentName }); - } else if(encoding === 'json') { - return fs.readFile(filePath, 'utf8') - .then(JSON.parse) - } else { - return fs.readFile(filePath, encoding); - } -} From 19abb7cb229168179fb0ba79919bb19d231d26d3 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 12 Jun 2024 23:09:28 -0500 Subject: [PATCH 71/90] ss --- src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 81af075e..8c9088bc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,7 +53,6 @@ export type Controller = typeof controller export * from './core/create-plugins'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; -export { Asset } from './core/structures/asset'; export * from './core/ioc'; From c764de12ac38da320e8c8177994395961927ca1d Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:26:37 -0500 Subject: [PATCH 72/90] finish ioc transition --- package.json | 1 + src/core/ioc/base.ts | 5 +-- src/core/ioc/container.ts | 77 --------------------------------------- src/core/ioc/global.ts | 2 +- src/core/ioc/index.ts | 2 +- yarn.lock | 8 ++++ 6 files changed, 13 insertions(+), 82 deletions(-) delete mode 100644 src/core/ioc/container.ts diff --git a/package.json b/package.json index b177954f..88b081c2 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "author": "SernDevs", "license": "MIT", "dependencies": { + "@sern/ioc": "^1.0.2", "callsites": "^3.1.0", "node-cron": "^3.0.3", "rxjs": "^7.8.0", diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts index fcf878da..78db4b0d 100644 --- a/src/core/ioc/base.ts +++ b/src/core/ioc/base.ts @@ -1,4 +1,4 @@ -import { Container } from './container'; +import { Container } from '@sern/ioc'; import * as __Services from '../structures/default-services'; import type { Logging } from '../interfaces'; import { __add_container, __add_wiredcontainer, __init_container, __swap_container, useContainerRaw } from './global'; @@ -34,8 +34,7 @@ const dependencyBuilder = (container: Container) => { * Swap out a preexisting dependency. */ swap(key: keyof Dependencies, v: Insertable) { - //todo in container - this.add(key, v); + this.swap(key, v); }, }; }; diff --git a/src/core/ioc/container.ts b/src/core/ioc/container.ts deleted file mode 100644 index 5f2e02a5..00000000 --- a/src/core/ioc/container.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * A semi-generic container that provides error handling, emitter, and module store. - * For the handler to operate correctly, The only user provided dependency needs to be @sern/client - */ -function hasCallableMethod(obj: object, name: PropertyKey) { - //@ts-ignore - return typeof obj[name] == 'function'; -} -/** - * A Depedency injection container capable of adding singletons, firing hooks, and managing IOC within an application - */ -export class Container { - private __singletons = new Map(); - private hooks= new Map(); - private finished_init = false; - constructor(options: { autowire: boolean; path?: string }) { - if(options.autowire) { /* noop */ } - } - - addHook(name: string, callback: Function) { - if (!this.hooks.has(name)) { - this.hooks.set(name, []); - } - this.hooks.get(name)!.push(callback); - } - private registerHooks(hookname: string, insert: object) { - - if(hasCallableMethod(insert, hookname)) { - //@ts-ignore - this.addHook(hookname, () => insert[hookname]()) - } - } - - addSingleton(key: string, insert: object) { - if(typeof insert !== 'object') { - throw Error("Inserted object must be an object"); - } - if(!this.__singletons.has(key)) { - this.registerHooks('init', insert) - this.registerHooks('dispose', insert) - this.__singletons.set(key, insert); - return true; - } - return false; - } - - addWiredSingleton(key: string, fn: (c: Record) => object) { - const insert = fn(this.deps()); - return this.addSingleton(key, insert); - } - - async disposeAll() { - await this.executeHooks('dispose'); - this.hooks.delete('dispose'); - } - - isReady() { return this.finished_init; } - hasKey(key: string) { return this.__singletons.has(key); } - get(key: PropertyKey) : T|undefined { return this.__singletons.get(key); } - - async ready() { - await this.executeHooks('init'); - this.hooks.delete('init'); - this.finished_init = true; - } - - deps>(): T { - return Object.fromEntries(this.__singletons) as T - } - - async executeHooks(name: string) { - const hookFunctions = this.hooks.get(name) || []; - for (const hookFunction of hookFunctions) { - await hookFunction(); - } - } -} diff --git a/src/core/ioc/global.ts b/src/core/ioc/global.ts index 766b8c5e..2322293c 100644 --- a/src/core/ioc/global.ts +++ b/src/core/ioc/global.ts @@ -1,5 +1,5 @@ +import { Container } from '@sern/ioc'; import { UnpackedDependencies } from '../../types/utility'; -import { Container } from './container'; //SIDE EFFECT: GLOBAL DI let containerSubject: Container; diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts index e06055eb..09cddadb 100644 --- a/src/core/ioc/index.ts +++ b/src/core/ioc/index.ts @@ -1,4 +1,4 @@ -import { IntoDependencies } from '../../types/ioc'; +import type { IntoDependencies } from '../../types/ioc'; import { Service as __Service, Services as __Services } from './global' export { makeDependencies } from './base'; diff --git a/yarn.lock b/yarn.lock index ef8561e6..af7dc4cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -553,6 +553,7 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 + "@sern/ioc": ^1.0.2 "@types/node": ^20.0.0 "@types/node-cron": ^3.0.11 "@typescript-eslint/eslint-plugin": 5.58.0 @@ -568,6 +569,13 @@ __metadata: languageName: unknown linkType: soft +"@sern/ioc@npm:^1.0.2": + version: 1.0.2 + resolution: "@sern/ioc@npm:1.0.2" + checksum: 7e127e07c3f7eb2eefa77eb5f7c48ba37a259f089cbadfd91e1f6d448a5083cd7f38d4d3c5a2c6efada1b62120d310a3854ba2ba6444fb6a7279a11e2a0b4705 + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.27.8": version: 0.27.8 resolution: "@sinclair/typebox@npm:0.27.8" From 9c358e19281fc7dd12ad7c3d518e54c9cb3d6fad Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:28:03 -0500 Subject: [PATCH 73/90] nvm, now i did --- package.json | 2 +- src/core/ioc/base.ts | 75 -------------------------------- src/core/ioc/global.ts | 86 ------------------------------------- src/core/ioc/index.ts | 51 ---------------------- src/handlers/event-utils.ts | 2 +- src/index.ts | 2 +- src/sern.ts | 4 +- src/types/ioc.ts | 2 +- yarn.lock | 10 ++--- 9 files changed, 12 insertions(+), 222 deletions(-) delete mode 100644 src/core/ioc/base.ts delete mode 100644 src/core/ioc/global.ts delete mode 100644 src/core/ioc/index.ts diff --git a/package.json b/package.json index 88b081c2..1ed40164 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "author": "SernDevs", "license": "MIT", "dependencies": { - "@sern/ioc": "^1.0.2", + "@sern/ioc": "^1.0.3", "callsites": "^3.1.0", "node-cron": "^3.0.3", "rxjs": "^7.8.0", diff --git a/src/core/ioc/base.ts b/src/core/ioc/base.ts deleted file mode 100644 index 78db4b0d..00000000 --- a/src/core/ioc/base.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Container } from '@sern/ioc'; -import * as __Services from '../structures/default-services'; -import type { Logging } from '../interfaces'; -import { __add_container, __add_wiredcontainer, __init_container, __swap_container, useContainerRaw } from './global'; -import { EventEmitter } from 'node:events'; - -export function disposeAll(logger: Logging|undefined) { - useContainerRaw() - ?.disposeAll() - .then(() => logger?.info({ message: 'Cleaning container and crashing' })); -} - -type Insertable = - | ((container: Dependencies) => object) - | object - -const dependencyBuilder = (container: Container) => { - return { - /** - * Insert a dependency into your container. - * Supply the correct key and dependency - */ - add(key: keyof Dependencies, v: Insertable) { - if(typeof v !== 'function') { - container.addSingleton(key, v) - } else { - //@ts-ignore - container.addWiredSingleton(key, (cntr) => v(cntr)) - } - }, - /** - * @param key the key of the dependency - * @param v The dependency to swap out. - * Swap out a preexisting dependency. - */ - swap(key: keyof Dependencies, v: Insertable) { - this.swap(key, v); - }, - }; -}; - -/** - * - * - * - */ -type ValidDependencyConfig = - | ((c: ReturnType) => any) - -/** - * makeDependencies constructs a dependency injection container for sern handler to use. - * This is required to start the handler, and is to be called before Sern.init. - * @example - * ```ts - * await makeDependencies(({ add }) => { - * add('@sern/client', new Client({ intents, partials }) - * }) - * ``` - */ -export async function makeDependencies (conf: ValidDependencyConfig) { - const container = await __init_container({ autowire: false }); - //We only include logger if it does not exist - const includeLogger = !container.hasKey('@sern/logger'); - - if(includeLogger) { - __add_container('@sern/logger', new __Services.DefaultLogging); - } - __add_container('@sern/errors', new __Services.DefaultErrorHandling); - __add_container('@sern/modules', new Map) - __add_container('@sern/emitter', new EventEmitter) - __add_wiredcontainer('@sern/cron', deps => new __Services.Cron(deps)) - conf(dependencyBuilder(container)); - await container.ready(); -} - diff --git a/src/core/ioc/global.ts b/src/core/ioc/global.ts deleted file mode 100644 index 2322293c..00000000 --- a/src/core/ioc/global.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Container } from '@sern/ioc'; -import { UnpackedDependencies } from '../../types/utility'; - -//SIDE EFFECT: GLOBAL DI -let containerSubject: Container; - -/** - * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything - * then it will swap - */ -export async function __swap_container(c: Container) { - if(containerSubject) { - await containerSubject.disposeAll() - } - containerSubject = c; -} - -/** - * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything - * then it will swap - */ -export function __add_container(key: string, v: object) { - containerSubject.addSingleton(key, v); -} - -/** - * Don't use this unless you know what you're doing. Destroys old containerSubject if it exists and disposes everything - * then it will swap - */ -export function __add_wiredcontainer(key: string, depfn : (deps: UnpackedDependencies) => object) { - //@ts-ignore - containerSubject.addWiredSingleton(key, depfn); -} -/** - * Initiates the global api. - * Once this is finished, the Service api and the other global api is available - */ -export async function __init_container(options: { - autowire: boolean; - path?: string | undefined; -}) { - containerSubject = new Container(options); - await containerSubject.ready() - return containerSubject -} - -/** - * Returns the underlying data structure holding all dependencies. - * Exposes methods from iti - * Use the Service API. The container should be readonly - */ -export function useContainerRaw() { - if (!(containerSubject && containerSubject.isReady())) { - throw new Error("Container wasn't ready or init'd. Please ensure container is ready()"); - } - - return containerSubject; -} - -/** - * The Service api, retrieve from the globally init'ed container - * Note: this method only works AFTER your container has been initiated - * @since 3.0.0 - * @example - * ```ts - * const client = Service('@sern/client'); - * ``` - * @param key a key that corresponds to a dependency registered. - * - */ -export function Service(key: PropertyKey) { - const dep = useContainerRaw().get(key)!; - if(!dep) { - throw Error("Requested key " + String(key) + " returned undefined"); - } - return dep; -} -/** - * @since 3.0.0 - * The plural version of {@link Service} - * @returns array of dependencies, in the same order of keys provided - */ -export function Services(...keys: [...T]) { - const container = useContainerRaw(); - return keys.map(k => container.get(k)!) as V; -} diff --git a/src/core/ioc/index.ts b/src/core/ioc/index.ts deleted file mode 100644 index 09cddadb..00000000 --- a/src/core/ioc/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { IntoDependencies } from '../../types/ioc'; -import { Service as __Service, Services as __Services } from './global' -export { makeDependencies } from './base'; - - -/** - * The new Service api, a cleaner alternative to useContainer - * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. - * Usually our scaffolding tool takes care of this. - * Note: this method only works AFTER your container has been initiated - * @since 3.0.0 - * @example - * ```ts - * const client = Service('@sern/client'); - * ``` - * @param key a key that corresponds to a dependency registered. - * - */ -export function Service(key: T) { - return __Service(key) as Dependencies[T] -} -/** - * @since 3.0.0 - * The plural version of {@link Service} - * @returns array of dependencies, in the same order of keys provided - */ -export function Services(...keys: [...T]) { - return __Services>(...keys) -} - -/** - * @deprecated - * Creates a singleton object. - * @param cb - */ -export function single(cb: () => T) { - console.log('The `single` function is deprecated and has no effect') - return cb(); -} - -/** - * @deprecated - * @since 2.0.0 - * Creates a transient object - * @param cb - */ -export function transient(cb: () => () => T) { - console.log('The `transient` function is deprecated and has no effect') - return cb()(); -} - diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 813f6ed4..f8352815 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -15,7 +15,7 @@ import * as assert from 'node:assert'; import { Context } from '../core/structures/context'; import { CommandType } from '../core/structures/enums' import { inspect } from 'node:util' -import { disposeAll } from '../core/ioc/base'; +import { disposeAll } from '../core/ioc'; import { resultPayload, isAutocomplete, treeSearch, fmt } from '../core/functions' function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { diff --git a/src/index.ts b/src/index.ts index 8c9088bc..76396926 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,7 +53,7 @@ export type Controller = typeof controller export * from './core/create-plugins'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; -export * from './core/ioc'; +export { makeDependencies, single, transient, Service, Services } from './core/ioc'; diff --git a/src/sern.ts b/src/sern.ts index 3cd067de..2fabe7a6 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -1,3 +1,6 @@ +//side effect: global container +import { useContainerRaw } from '@sern/ioc/global'; + import callsites from 'callsites'; import * as Files from './core/module-loading'; import { merge } from 'rxjs'; @@ -7,7 +10,6 @@ import messageHandler from './handlers/message'; import interactionHandler from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; import { handleCrash } from './handlers/event-utils'; -import { useContainerRaw } from './core/ioc/global'; import { UnpackedDependencies } from './types/utility'; import type { PresenceResult } from './core/presences'; diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 3803a644..6e543ac7 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -1,4 +1,4 @@ -import type { Container } from '../core/ioc/container'; +import type { Container } from '@sern/ioc'; import * as Contracts from '../core/interfaces'; import type { UnpackFunction } from './utility' import type { Client } from 'discord.js' diff --git a/yarn.lock b/yarn.lock index af7dc4cd..6ffc01f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -553,7 +553,7 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 - "@sern/ioc": ^1.0.2 + "@sern/ioc": ^1.0.3 "@types/node": ^20.0.0 "@types/node-cron": ^3.0.11 "@typescript-eslint/eslint-plugin": 5.58.0 @@ -569,10 +569,10 @@ __metadata: languageName: unknown linkType: soft -"@sern/ioc@npm:^1.0.2": - version: 1.0.2 - resolution: "@sern/ioc@npm:1.0.2" - checksum: 7e127e07c3f7eb2eefa77eb5f7c48ba37a259f089cbadfd91e1f6d448a5083cd7f38d4d3c5a2c6efada1b62120d310a3854ba2ba6444fb6a7279a11e2a0b4705 +"@sern/ioc@npm:^1.0.3": + version: 1.0.3 + resolution: "@sern/ioc@npm:1.0.3" + checksum: 2c640cabbf3927d923b57233e660be1d6d4da1cd376a4ba77b118fd9aa5ef81c465d287357a15a7cd7827306dd614c73bde68751978d2030c3a4877dcbb0d02d languageName: node linkType: hard From 2f778f4dc2510724f049f19e69e0afca26d6bcad Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:28:15 -0500 Subject: [PATCH 74/90] s --- src/core/ioc.ts | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/core/ioc.ts diff --git a/src/core/ioc.ts b/src/core/ioc.ts new file mode 100644 index 00000000..ad32f31d --- /dev/null +++ b/src/core/ioc.ts @@ -0,0 +1,119 @@ +import type { IntoDependencies } from '../types/ioc'; +import { Service as $Service, Services as $Services } from '@sern/ioc/global' +import { Container } from '@sern/ioc'; +import * as __Services from './structures/default-services'; +import type { Logging } from './interfaces'; +import { __init_container, useContainerRaw } from '@sern/ioc/global'; +import { EventEmitter } from 'node:events'; + +export function disposeAll(logger: Logging|undefined) { + useContainerRaw() + ?.disposeAll() + .then(() => logger?.info({ message: 'Cleaning container and crashing' })); +} + +type Insertable = | ((container: Dependencies) => object) + | object + +const dependencyBuilder = (container: Container) => { + return { + /** + * Insert a dependency into your container. + * Supply the correct key and dependency + */ + add(key: keyof Dependencies, v: Insertable) { + if(typeof v !== 'function') { + container.addSingleton(key, v) + } else { + //@ts-ignore + container.addWiredSingleton(key, (cntr) => v(cntr)) + } + }, + /** + * @param key the key of the dependency + * @param v The dependency to swap out. + * Swap out a preexisting dependency. + */ + swap(key: keyof Dependencies, v: Insertable) { + container.swap(key, v); + }, + }; +}; + +type ValidDependencyConfig = + (c: ReturnType) => any + +/** + * makeDependencies constructs a dependency injection container for sern handler to use. + * This is required to start the handler, and is to be called before Sern.init. + * @example + * ```ts + * await makeDependencies(({ add }) => { + * add('@sern/client', new Client({ intents, partials }) + * }) + * ``` + */ +export async function makeDependencies (conf: ValidDependencyConfig) { + const container = await __init_container({ autowire: false }); + //We only include logger if it does not exist + const includeLogger = !container.hasKey('@sern/logger'); + + if(includeLogger) { + container.addSingleton('@sern/logger', new __Services.DefaultLogging); + } + container.addSingleton('@sern/errors', new __Services.DefaultErrorHandling); + container.addSingleton('@sern/modules', new Map); + container.addSingleton('@sern/emitter', new EventEmitter) + container.addWiredSingleton('@sern/cron', + (deps) => new __Services.Cron(deps as unknown as Dependencies)) + conf(dependencyBuilder(container)); + await container.ready(); +} + + +/** + * The new Service api, a cleaner alternative to useContainer + * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. + * Usually our scaffolding tool takes care of this. + * Note: this method only works AFTER your container has been initiated + * @since 3.0.0 + * @example + * ```ts + * const client = Service('@sern/client'); + * ``` + * @param key a key that corresponds to a dependency registered. + * + */ +export function Service(key: T) { + return $Service(key) as Dependencies[T] +} +/** + * @since 3.0.0 + * The plural version of {@link Service} + * @returns array of dependencies, in the same order of keys provided + */ +export function Services(...keys: [...T]) { + return $Services>(...keys) +} + +/** + * @deprecated + * Creates a singleton object. + * @param cb + */ +export function single(cb: () => T) { + console.log('The `single` function is deprecated and has no effect') + return cb(); +} + +/** + * @deprecated + * @since 2.0.0 + * Creates a transient object + * @param cb + */ +export function transient(cb: () => () => T) { + console.log('The `transient` function is deprecated and has no effect') + return cb()(); +} + From 90f5ea7bdaf02a3b0c420d77be2cc6f939ec6985 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:27:23 -0500 Subject: [PATCH 75/90] update locals api, docs, tests --- package.json | 3 ++- src/core/modules.ts | 13 +++++++------ src/handlers/event-utils.ts | 32 +++++++++++++++++--------------- src/handlers/ready.ts | 4 ++-- src/types/core-modules.ts | 9 +++++---- src/types/core-plugin.ts | 2 +- src/types/dependencies.d.ts | 15 +++++++++++++++ src/types/ioc.ts | 18 ++++++++++++++++++ test/handlers.test.ts | 19 ++++++++++--------- yarn.lock | 18 +++++++++++++----- 10 files changed, 90 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 1ed40164..0e3faf4e 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,9 @@ "author": "SernDevs", "license": "MIT", "dependencies": { - "@sern/ioc": "^1.0.3", + "@sern/ioc": "^1.0.4", "callsites": "^3.1.0", + "deepmerge": "^4.3.1", "node-cron": "^3.0.3", "rxjs": "^7.8.0", "ts-results-es": "^4.1.0" diff --git a/src/core/modules.ts b/src/core/modules.ts index 84d389e9..8d9d6f19 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -14,11 +14,10 @@ import type { Awaitable } from '../types/utility'; */ export function commandModule(mod: InputCommand): Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); - return { - ...mod, - onEvent, - plugins, - } as Module; + return { ...mod, + onEvent, + plugins, + locals: {} } as Module; } /** @@ -29,7 +28,9 @@ export function commandModule(mod: InputCommand): Module { export function eventModule(mod: InputEvent): Module { const [onEvent, plugins] = partitionPlugins(mod.plugins); if(onEvent.length !== 0) throw Error("Event modules cannot have ControlPlugins"); - return { ...mod, plugins } as Module; + return { ...mod, + plugins, + locals: {} } as Module; } /** Create event modules from discord.js client events, diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index f8352815..2f2f17a3 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -17,6 +17,7 @@ import { CommandType } from '../core/structures/enums' import { inspect } from 'node:util' import { disposeAll } from '../core/ioc'; import { resultPayload, isAutocomplete, treeSearch, fmt } from '../core/functions' +import merge from 'deepmerge' function handleError(crashHandler: ErrorHandling, emitter: Emitter, logging?: Logging) { return (pload: unknown, caught: Observable) => { @@ -213,25 +214,26 @@ export function createResultResolver(config: { }; }; -export async function callInitPlugins(module: Module, deps: Dependencies, emit?: boolean) { - let _module = module; +function isObject(item: unknown) { + return (item && typeof item === 'object' && !Array.isArray(item)); +} + +//_module is frozen, preventing from mutations +export async function callInitPlugins(_module: Module, deps: Dependencies, emit?: boolean) { + let module = _module; const emitter = deps['@sern/emitter']; - for(const plugin of _module.plugins ?? []) { - const res = await plugin.execute({ - module: _module, - absPath: _module.meta.absPath, - deps - }); - if (!res) throw Error("Plugin did not return anything. " + inspect(plugin, false, Infinity, true)); - if(res.isErr()) { + for(const plugin of module.plugins ?? []) { + const result = await plugin.execute({ module, absPath: module.meta.absPath, deps }); + if (!result) throw Error("Plugin did not return anything. " + inspect(plugin, false, Infinity, true)); + if(result.isErr()) { if(emit) { emitter?.emit('module.register', - resultPayload('failure', module, res.error ?? SernError.PluginFailure)); + resultPayload('failure', module, result.error ?? SernError.PluginFailure)); } - throw Error(res.error ?? SernError.PluginFailure); + throw Error(result.error ?? SernError.PluginFailure); } } - return _module + return module } async function callPlugins({ args, module, deps, params }: ExecutePayload) { @@ -241,8 +243,8 @@ async function callPlugins({ args, module, deps, params }: ExecutePayload) { if(result.isErr()) { return result; } - if(typeof result.value === 'object' && result.value !== null) { - state = { ...state, ...result.value, }; + if(isObject(result.value)) { + state = merge(state, result.value!); } } return Ok(state); diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 662b1bd0..83f485c5 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -23,8 +23,8 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - const resultModule = await callInitPlugins(module, deps, true); - // FREEZE! no more writing!! + const resultModule = await callInitPlugins(module, deps, true); // FREEZE! no more writing!! + commands.set(resultModule.meta.id, Object.freeze(resultModule)); sEmitter.emit('module.register', resultPayload('success', resultModule)); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 1b302d6b..8437fe2e 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -18,7 +18,7 @@ import type { } from 'discord.js'; import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' -import { AnyPlugin, ControlPlugin, InitPlugin } from './core-plugin'; +import { ControlPlugin, InitPlugin, Plugin } from './core-plugin'; import { Awaitable, SernEventsMapping } from './utility'; //state, deps, type (very original) @@ -41,6 +41,7 @@ export interface Module { id: string; absPath: string; } + locals: Record execute(...args: any[]): Awaitable; } @@ -191,10 +192,10 @@ export interface SernAutocompleteData } type CommandModuleNoPlugins = { - [T in CommandType]: Omit; + [T in CommandType]: Omit; }; type EventModulesNoPlugins = { - [T in EventType]: Omit ; + [T in EventType]: Omit ; }; export type InputEvent = { @@ -206,7 +207,7 @@ export type InputEvent = { export type InputCommand = { [T in CommandType]: CommandModuleNoPlugins[T] & { - plugins?: AnyPlugin[]; + plugins?: Plugin[]; }; }[CommandType]; diff --git a/src/types/core-plugin.ts b/src/types/core-plugin.ts index 7b0c9489..b63e23b9 100644 --- a/src/types/core-plugin.ts +++ b/src/types/core-plugin.ts @@ -33,7 +33,6 @@ import type { } from 'discord.js'; export type PluginResult = Awaitable|undefined, string|undefined>>; - export interface InitArgs = Processed> { module: T; absPath: string; @@ -46,6 +45,7 @@ export interface Plugin { export interface InitPlugin extends Plugin { type: PluginType.Init; + execute: (...args: Args) => PluginResult; } export interface ControlPlugin extends Plugin { type: PluginType.Control; diff --git a/src/types/dependencies.d.ts b/src/types/dependencies.d.ts index ecc76d5d..a66dedd7 100644 --- a/src/types/dependencies.d.ts +++ b/src/types/dependencies.d.ts @@ -7,6 +7,21 @@ import { CoreDependencies } from './ioc'; declare global { + /** + * discord.js client. + * '@sern/client': Client + * sern emitter listens to events that happen throughout + * the handler. some include module.register, module.activate. + * '@sern/emitter': Contracts.Emitter; + * An error handler which is the final step before + * the sern process actually crashes. + '@sern/errors': Contracts.ErrorHandling; + * Optional logger. Performs ... logging + * '@sern/logger'?: Contracts.Logging; + * Readonly module store. sern stores these + * by module.meta.id -> Module + * '@sern/modules': Map; + */ interface Dependencies extends CoreDependencies {} } diff --git a/src/types/ioc.ts b/src/types/ioc.ts index 6e543ac7..d9095c3f 100644 --- a/src/types/ioc.ts +++ b/src/types/ioc.ts @@ -6,10 +6,28 @@ import { Module } from './core-modules'; export interface CoreDependencies { + /** + * discord.js client. + */ '@sern/client': Client; + /** + * sern emitter listens to events that happen throughout + * the handler. some include module.register, module.activate. + */ '@sern/emitter': Contracts.Emitter; + /** + * An error handler which is the final step before + * the sern process actually crashes. + */ '@sern/errors': Contracts.ErrorHandling; + /** + * Optional logger. Performs ... logging + */ '@sern/logger'?: Contracts.Logging; + /** + * Readonly module store. sern stores these + * by module.meta.id -> Module + */ '@sern/modules': Map; } diff --git a/test/handlers.test.ts b/test/handlers.test.ts index 35e6c02f..a00117b5 100644 --- a/test/handlers.test.ts +++ b/test/handlers.test.ts @@ -57,13 +57,8 @@ vi.mock('discord.js', async (importOriginal) => { function createRandomPlugin (s: 'go', mut?: Partial) { return CommandInitPlugin(({ module }) => { - if(mut) { - for(const [k,v] of Object.entries(mut)) { - module[k] = v - } - } return s == 'go' - ? controller.next() + ? controller.next(mut) : controller.stop() }) } @@ -103,16 +98,22 @@ describe('eventDispatcher standard', () => { }); }); -test ('mutate with init plugins', async () => { +test ('call init plugins', async () => { const deps = mockDeps() const plugins = createRandomPlugin('go', { name: "abc" }) const mod = createRandomModule([plugins]) - console.log(mod) const s = await callInitPlugins(mod, deps, false) - console.log(s) expect("abc").equal(s.name) }) +test('init plugins replace array', async () => { + const deps = mockDeps() + const plugins = createRandomPlugin('go', { opts: [] }) + const plugins2 = createRandomPlugin('go', { opts: ['a'] }) + const mod = createRandomModule([plugins, plugins2]) + const s = await callInitPlugins(mod, deps, false) + expect(['a']).deep.equal(s.opts) +}) test('call control plugin ', async () => { const plugin = CommandControlPlugin((ctx,sdt) => { diff --git a/yarn.lock b/yarn.lock index 6ffc01f9..73fcc0c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -553,12 +553,13 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 - "@sern/ioc": ^1.0.3 + "@sern/ioc": ^1.0.4 "@types/node": ^20.0.0 "@types/node-cron": ^3.0.11 "@typescript-eslint/eslint-plugin": 5.58.0 "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 + deepmerge: ^4.3.1 discord.js: ^14.x.x eslint: 8.39.0 node-cron: ^3.0.3 @@ -569,10 +570,10 @@ __metadata: languageName: unknown linkType: soft -"@sern/ioc@npm:^1.0.3": - version: 1.0.3 - resolution: "@sern/ioc@npm:1.0.3" - checksum: 2c640cabbf3927d923b57233e660be1d6d4da1cd376a4ba77b118fd9aa5ef81c465d287357a15a7cd7827306dd614c73bde68751978d2030c3a4877dcbb0d02d +"@sern/ioc@npm:^1.0.4": + version: 1.0.4 + resolution: "@sern/ioc@npm:1.0.4" + checksum: 3d1a63099b3e8ff0d44bb73007b1d66c3f3b27cf7a193c2d9122e021cb72be1ced535ea98efaf72602f371a489177e3b144ed72da8d7de80887c0408ce79cce2 languageName: node linkType: hard @@ -1172,6 +1173,13 @@ __metadata: languageName: node linkType: hard +"deepmerge@npm:^4.3.1": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 + languageName: node + linkType: hard + "diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" From 7c8e39defbafdd6312a04a2d30750d647a3ab22b Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:31:05 -0500 Subject: [PATCH 76/90] fix tests --- test/handlers.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/handlers.test.ts b/test/handlers.test.ts index a00117b5..2428df7a 100644 --- a/test/handlers.test.ts +++ b/test/handlers.test.ts @@ -57,8 +57,13 @@ vi.mock('discord.js', async (importOriginal) => { function createRandomPlugin (s: 'go', mut?: Partial) { return CommandInitPlugin(({ module }) => { + if(mut) { + Object.entries(mut).forEach(([k, v]) => { + module[k] = v + }) + } return s == 'go' - ? controller.next(mut) + ? controller.next() : controller.stop() }) } From 1d8dbb89627f6d3d3309e3f33e533cf5dd5fbc96 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 22 Jun 2024 12:10:52 -0500 Subject: [PATCH 77/90] fix up tests and cleanup --- src/core/ioc.ts | 39 ++++++++++++++++- src/core/{create-plugins.ts => plugin.ts} | 3 ++ src/core/presences.ts | 2 +- src/index.ts | 20 ++++++--- src/types/dependencies.d.ts | 2 +- src/types/ioc.ts | 51 ----------------------- test/core/create-plugin.test.ts | 2 +- test/handlers.test.ts | 2 +- 8 files changed, 60 insertions(+), 61 deletions(-) rename src/core/{create-plugins.ts => plugin.ts} (96%) delete mode 100644 src/types/ioc.ts diff --git a/src/core/ioc.ts b/src/core/ioc.ts index ad32f31d..0f0a7b1a 100644 --- a/src/core/ioc.ts +++ b/src/core/ioc.ts @@ -1,10 +1,13 @@ -import type { IntoDependencies } from '../types/ioc'; import { Service as $Service, Services as $Services } from '@sern/ioc/global' import { Container } from '@sern/ioc'; +import * as Contracts from './interfaces'; import * as __Services from './structures/default-services'; import type { Logging } from './interfaces'; import { __init_container, useContainerRaw } from '@sern/ioc/global'; import { EventEmitter } from 'node:events'; +import { Client } from 'discord.js'; +import { Module } from '../types/core-modules'; +import { UnpackFunction } from '../types/utility'; export function disposeAll(logger: Logging|undefined) { useContainerRaw() @@ -117,3 +120,37 @@ export function transient(cb: () => () => T) { return cb()(); } +export type DependencyFromKey = Dependencies[T]; + + + +export type IntoDependencies = { + [Index in keyof Tuple]: UnpackFunction>>; //Unpack and make NonNullable +} & { length: Tuple['length'] }; + +export interface CoreDependencies { + /** + * discord.js client. + */ + '@sern/client': Client; + /** + * sern emitter listens to events that happen throughout + * the handler. some include module.register, module.activate. + */ + '@sern/emitter': Contracts.Emitter; + /** + * An error handler which is the final step before + * the sern process actually crashes. + */ + '@sern/errors': Contracts.ErrorHandling; + /** + * Optional logger. Performs ... logging + */ + '@sern/logger'?: Contracts.Logging; + /** + * Readonly module store. sern stores these + * by module.meta.id -> Module + */ + '@sern/modules': Map; +} + diff --git a/src/core/create-plugins.ts b/src/core/plugin.ts similarity index 96% rename from src/core/create-plugins.ts rename to src/core/plugin.ts index 9006b099..65c49cf9 100644 --- a/src/core/create-plugins.ts +++ b/src/core/plugin.ts @@ -40,3 +40,6 @@ export const controller = { next: (val?: Record) => Ok(val), stop: (val?: string) => Err(val), }; + + +export type Controller = typeof controller; diff --git a/src/core/presences.ts b/src/core/presences.ts index 78b1024d..4060fbc2 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -1,5 +1,5 @@ import type { ActivitiesOptions } from "discord.js"; -import type { IntoDependencies } from "../types/ioc"; +import type { IntoDependencies } from "./ioc"; import type { Emitter } from "./interfaces"; type Status = 'online' | 'idle' | 'invisible' | 'dnd' diff --git a/src/index.ts b/src/index.ts index 76396926..183cb634 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,6 @@ export type { export type { Payload, SernEventsMapping } from './types/utility'; -export type { CoreDependencies } from './types/ioc'; export { commandModule, @@ -48,12 +47,23 @@ export { export * from './core/presences' export * from './core/interfaces' -import type { controller } from './core/create-plugins'; -export type Controller = typeof controller -export * from './core/create-plugins'; +export * from './core/plugin'; export { CommandType, PluginType, PayloadType, EventType } from './core/structures/enums'; export { Context } from './core/structures/context'; -export { makeDependencies, single, transient, Service, Services } from './core/ioc'; +export { type CoreDependencies, makeDependencies, single, transient, Service, Services } from './core/ioc'; +import type { Container } from '@sern/ioc'; +/** + * @deprecated This old signature will be incompatible with future versions of sern. + * ```ts + * To switch your old code: + await makeDependencies(({ add }) => { + add('@sern/client', new Client()) + }) + * ``` + */ +export interface DependencyConfiguration { + build: (root: Container) => Container; +} diff --git a/src/types/dependencies.d.ts b/src/types/dependencies.d.ts index a66dedd7..55db7279 100644 --- a/src/types/dependencies.d.ts +++ b/src/types/dependencies.d.ts @@ -4,7 +4,7 @@ /* eslint-disable @typescript-eslint/consistent-type-imports */ -import { CoreDependencies } from './ioc'; +import { CoreDependencies } from '../core/ioc'; declare global { /** diff --git a/src/types/ioc.ts b/src/types/ioc.ts deleted file mode 100644 index d9095c3f..00000000 --- a/src/types/ioc.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { Container } from '@sern/ioc'; -import * as Contracts from '../core/interfaces'; -import type { UnpackFunction } from './utility' -import type { Client } from 'discord.js' -import { Module } from './core-modules'; - - -export interface CoreDependencies { - /** - * discord.js client. - */ - '@sern/client': Client; - /** - * sern emitter listens to events that happen throughout - * the handler. some include module.register, module.activate. - */ - '@sern/emitter': Contracts.Emitter; - /** - * An error handler which is the final step before - * the sern process actually crashes. - */ - '@sern/errors': Contracts.ErrorHandling; - /** - * Optional logger. Performs ... logging - */ - '@sern/logger'?: Contracts.Logging; - /** - * Readonly module store. sern stores these - * by module.meta.id -> Module - */ - '@sern/modules': Map; -} - -export type DependencyFromKey = Dependencies[T]; - -export type IntoDependencies = { - [Index in keyof Tuple]: UnpackFunction>>; //Unpack and make NonNullable -} & { length: Tuple['length'] }; - -/** - * @deprecated This old signature will be incompatible with future versions of sern. - * ```ts - * To switch your old code: - await makeDependencies(({ add }) => { - add('@sern/client', new Client()) - }) - * ``` - */ -export interface DependencyConfiguration { - build: (root: Container) => Container; -} diff --git a/test/core/create-plugin.test.ts b/test/core/create-plugin.test.ts index 5236a61b..3aaa8069 100644 --- a/test/core/create-plugin.test.ts +++ b/test/core/create-plugin.test.ts @@ -3,7 +3,7 @@ import { CommandControlPlugin, CommandInitPlugin, EventInitPlugin, -} from '../../src/core/create-plugins'; +} from '../../src'; import { PluginType, controller } from '../../src'; describe('create-plugins', () => { diff --git a/test/handlers.test.ts b/test/handlers.test.ts index 2428df7a..e066ec97 100644 --- a/test/handlers.test.ts +++ b/test/handlers.test.ts @@ -7,7 +7,7 @@ import { faker } from '@faker-js/faker'; import { Module } from '../src/types/core-modules'; import { Processed } from '../src/types/core-modules'; import { EventEmitter } from 'events'; -import { EventType } from '../dist/core/structures/enums'; +import { EventType } from '../src/core/structures/enums'; import { CommandControlPlugin, CommandInitPlugin, CommandType, controller } from '../src'; vi.mock('discord.js', async (importOriginal) => { From 908d584cc5ef95c6bdb6474999c74ea277389594 Mon Sep 17 00:00:00 2001 From: jacob Date: Mon, 24 Jun 2024 23:18:19 -0500 Subject: [PATCH 78/90] fix --- package.json | 2 +- yarn.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 0e3faf4e..2555191d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@types/node-cron": "^3.0.11", "@typescript-eslint/eslint-plugin": "5.58.0", "@typescript-eslint/parser": "5.59.1", - "discord.js": "^14.x.x", + "discord.js": "^14.15.3", "eslint": "8.39.0", "typescript": "5.0.2", "vitest": "^1.6.0" diff --git a/yarn.lock b/yarn.lock index 73fcc0c9..65b266f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,9 +12,9 @@ __metadata: languageName: node linkType: hard -"@discordjs/builders@npm:^1.8.1": - version: 1.8.1 - resolution: "@discordjs/builders@npm:1.8.1" +"@discordjs/builders@npm:^1.8.2": + version: 1.8.2 + resolution: "@discordjs/builders@npm:1.8.2" dependencies: "@discordjs/formatters": ^0.4.0 "@discordjs/util": ^1.1.0 @@ -23,7 +23,7 @@ __metadata: fast-deep-equal: ^3.1.3 ts-mixer: ^6.0.4 tslib: ^2.6.2 - checksum: 21e826004ddddf6f9717cbdacafe4ff748d03103634d82883c66f605b068a5ae12a952aaa2558a2c21f3ec717427a12bb9b57f0f8670f8a4ab6a0757bb3b229d + checksum: 65c707f28fb40b2875ebc08d580b6902eaf988c0e70ad674e33893abfdde74b52fc491476336a312c4f18de2fc599e1299341af152265d84864c907a12749a8e languageName: node linkType: hard @@ -74,9 +74,9 @@ __metadata: languageName: node linkType: hard -"@discordjs/ws@npm:^1.1.0": - version: 1.1.0 - resolution: "@discordjs/ws@npm:1.1.0" +"@discordjs/ws@npm:^1.1.1": + version: 1.1.1 + resolution: "@discordjs/ws@npm:1.1.1" dependencies: "@discordjs/collection": ^2.1.0 "@discordjs/rest": ^2.3.0 @@ -87,7 +87,7 @@ __metadata: discord-api-types: 0.37.83 tslib: ^2.6.2 ws: ^8.16.0 - checksum: a187977572f028d0d92bed16e25ad0b4cb86025372a5f632a15a00d3d0c8ad27a264530c364fee2ca6e5f3637ccf970b8af3e6009ec5ad193d2f3211ab70a133 + checksum: 42ba6dad56d6d340b34e400144cb6cd0433c963b16c51e24496b43a1a23cc01c663cb24c492b9fc8c1f7dd528ce32f7d34e2ed379dbc57352468f5505fe21486 languageName: node linkType: hard @@ -560,7 +560,7 @@ __metadata: "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 deepmerge: ^4.3.1 - discord.js: ^14.x.x + discord.js: ^14.15.3 eslint: 8.39.0 node-cron: ^3.0.3 rxjs: ^7.8.0 @@ -1203,23 +1203,23 @@ __metadata: languageName: node linkType: hard -"discord.js@npm:^14.x.x": - version: 14.15.2 - resolution: "discord.js@npm:14.15.2" +"discord.js@npm:^14.15.3": + version: 14.15.3 + resolution: "discord.js@npm:14.15.3" dependencies: - "@discordjs/builders": ^1.8.1 + "@discordjs/builders": ^1.8.2 "@discordjs/collection": 1.5.3 "@discordjs/formatters": ^0.4.0 "@discordjs/rest": ^2.3.0 "@discordjs/util": ^1.1.0 - "@discordjs/ws": ^1.1.0 + "@discordjs/ws": ^1.1.1 "@sapphire/snowflake": 3.5.3 discord-api-types: 0.37.83 fast-deep-equal: 3.1.3 lodash.snakecase: 4.1.1 tslib: 2.6.2 undici: 6.13.0 - checksum: a6ff7f014996fbea36f7fc7a8ce03f31ded8f3f434ba6c96173721d1d0e18963fcf59c4f00298fd2f01f523bf578582843f80bd99328bade5c4e2b31f82ae368 + checksum: 0b521caee9040c3a39200e6bf01b60230e9abd89b13e632054be2a2e08b74708b0776dd61ccf5e737968c33907e824c7fca9aeb62a293700cd5d517ce82f795d languageName: node linkType: hard From 14e80016daff0ce9b02b1b06eb3336fc8ec14bbb Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 30 Jun 2024 17:32:08 -0500 Subject: [PATCH 79/90] Update src/core/functions.ts Co-authored-by: Evo <85353424+EvolutionX-10@users.noreply.github.com> --- src/core/functions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/functions.ts b/src/core/functions.ts index 18154c73..1e65d385 100644 --- a/src/core/functions.ts +++ b/src/core/functions.ts @@ -20,7 +20,7 @@ import type { Payload } from '../types/utility'; * @returns The message without the prefix * @example * message.content = '!ping'; - * console.log(fmt(message, '!')); + * console.log(fmt(message.content, '!')); * // [ 'ping' ] */ export function fmt(msg: string, prefix?: string): string[] { From 3128b441c5ae10481c38bb61c0a67eb199be78b6 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 30 Jun 2024 17:34:55 -0500 Subject: [PATCH 80/90] better documentation --- src/index.ts | 3 +- yarn.lock | 524 +++++++++++++++++++++++++-------------------------- 2 files changed, 258 insertions(+), 269 deletions(-) diff --git a/src/index.ts b/src/index.ts index 183cb634..1667ff98 100644 --- a/src/index.ts +++ b/src/index.ts @@ -56,7 +56,8 @@ export { type CoreDependencies, makeDependencies, single, transient, Service, Se import type { Container } from '@sern/ioc'; /** - * @deprecated This old signature will be incompatible with future versions of sern. + * @deprecated This old signature will be incompatible with future versions of sern >= 4.0.0. See {@link makeDependencies} + * @example * ```ts * To switch your old code: await makeDependencies(({ add }) => { diff --git a/yarn.lock b/yarn.lock index 65b266f1..4fca6641 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,13 +5,6 @@ __metadata: version: 6 cacheKey: 8 -"@aashutoshrathi/word-wrap@npm:^1.2.3": - version: 1.2.6 - resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" - checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd - languageName: node - linkType: hard - "@discordjs/builders@npm:^1.8.2": version: 1.8.2 resolution: "@discordjs/builders@npm:1.8.2" @@ -91,163 +84,163 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/aix-ppc64@npm:0.20.2" +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm64@npm:0.20.2" +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-arm@npm:0.20.2" +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/android-x64@npm:0.20.2" +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-arm64@npm:0.20.2" +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/darwin-x64@npm:0.20.2" +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-arm64@npm:0.20.2" +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/freebsd-x64@npm:0.20.2" +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm64@npm:0.20.2" +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-arm@npm:0.20.2" +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ia32@npm:0.20.2" +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-loong64@npm:0.20.2" +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-mips64el@npm:0.20.2" +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-ppc64@npm:0.20.2" +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-riscv64@npm:0.20.2" +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-s390x@npm:0.20.2" +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/linux-x64@npm:0.20.2" +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/netbsd-x64@npm:0.20.2" +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/openbsd-x64@npm:0.20.2" +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/sunos-x64@npm:0.20.2" +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-arm64@npm:0.20.2" +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-ia32@npm:0.20.2" +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.20.2": - version: 0.20.2 - resolution: "@esbuild/win32-x64@npm:0.20.2" +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -264,15 +257,15 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.4.0": - version: 4.8.0 - resolution: "@eslint-community/regexpp@npm:4.8.0" - checksum: 601e6d033d556e98e8c929905bef335f20d7389762812df4d0f709d9b4d2631610dda975fb272e23b5b68e24a163b3851b114c8080a0a19fb4c141a1eff6305b + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 97d2fe46690b69417a551bd19a3dc53b6d9590d2295c43cc4c4e44e64131af541e2f4a44d5c12e87de990403654d3dae9d33600081f3a2f0386b368abc9111ec languageName: node linkType: hard "@eslint/eslintrc@npm:^2.0.2": - version: 2.1.2 - resolution: "@eslint/eslintrc@npm:2.1.2" + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: ^6.12.4 debug: ^4.3.2 @@ -283,7 +276,7 @@ __metadata: js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: bc742a1e3b361f06fedb4afb6bf32cbd27171292ef7924f61c62f2aed73048367bcc7ac68f98c06d4245cd3fabc43270f844e3c1699936d4734b3ac5398814a7 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 languageName: node linkType: hard @@ -295,20 +288,20 @@ __metadata: linkType: hard "@faker-js/faker@npm:^8.0.1": - version: 8.0.2 - resolution: "@faker-js/faker@npm:8.0.2" - checksum: cf73daf9a50397eb0b3f04a7ef3fbb6f54acc026b167707136a7e58a517fd805a46c9e8c5f017f3022f104a4ff984765daaeee2cb98b3c34646db05c2acad441 + version: 8.4.1 + resolution: "@faker-js/faker@npm:8.4.1" + checksum: d802d531f8929562715adc279cfec763c9a4bc596ec67b0ce43fd0ae61b285d2b0eec6f1f4aa852452a63721a842fe7e81926dce7bd92acca94b01e2a1f55f5a languageName: node linkType: hard "@humanwhocodes/config-array@npm:^0.11.8": - version: 0.11.11 - resolution: "@humanwhocodes/config-array@npm:0.11.11" + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: - "@humanwhocodes/object-schema": ^1.2.1 - debug: ^4.1.1 + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 minimatch: ^3.0.5 - checksum: db84507375ab77b8ffdd24f498a5b49ad6b64391d30dd2ac56885501d03964d29637e05b1ed5aefa09d57ac667e28028bc22d2da872bfcd619652fbdb5f4ca19 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 languageName: node linkType: hard @@ -319,10 +312,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.1": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1 +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -592,9 +585,9 @@ __metadata: linkType: hard "@types/json-schema@npm:^7.0.9": - version: 7.0.12 - resolution: "@types/json-schema@npm:7.0.12" - checksum: 00239e97234eeb5ceefb0c1875d98ade6e922bfec39dd365ec6bd360b5c2f825e612ac4f6e5f1d13601b8b30f378f15e6faa805a3a732f4a1bbe61915163d293 + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 languageName: node linkType: hard @@ -606,18 +599,18 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:^20.0.0": - version: 20.12.12 - resolution: "@types/node@npm:20.12.12" + version: 20.14.9 + resolution: "@types/node@npm:20.14.9" dependencies: undici-types: ~5.26.4 - checksum: 5373983874b9af7c216e7ca5d26b32a8d9829c703a69f1e66f2113598b5be8582c0e009ca97369f1ec9a6282b3f92812208d06eb1e9fc3bd9b939b022303d042 + checksum: 5e9eda1ac8c6cc6bcd1063903ae195eaede9aad1bdad00408a919409cfbcdd2d6535aa3d50346f0d385528f9e03dafc7d1b3bad25aedb1dcd79a6ad39d06c35d languageName: node linkType: hard "@types/semver@npm:^7.3.12": - version: 7.5.1 - resolution: "@types/semver@npm:7.5.1" - checksum: 2fffe938c7ac168711f245a16e1856a3578d77161ca17e29a05c3e02c7be3e9c5beefa29a3350f6c1bd982fb70aa28cc52e4845eb7d36246bcdc0377170d584d + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -851,9 +844,9 @@ __metadata: linkType: hard "@vladfrangu/async_event_emitter@npm:^2.2.4": - version: 2.2.4 - resolution: "@vladfrangu/async_event_emitter@npm:2.2.4" - checksum: ff65ebc4d89639adecd249e24e4f6f97b7696404f2a4461160efdff628d91de543e982727c18de62a4edada3f66381b5a3cd1d4f4f33098075d839c1b4f46979 + version: 2.4.0 + resolution: "@vladfrangu/async_event_emitter@npm:2.4.0" + checksum: dc22762fb3a46cd96fc0062974abc08a6f457c64890dcb4c431f82e4ba9155d2c2745cd331763d7d652f69a167ea4f4e2faa5be5c7fa8e56b6e2deeea9850da8 languageName: node linkType: hard @@ -874,27 +867,20 @@ __metadata: linkType: hard "acorn-walk@npm:^8.3.2": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 - languageName: node - linkType: hard - -"acorn@npm:^8.11.3": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" - bin: - acorn: bin/acorn - checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + version: 8.3.3 + resolution: "acorn-walk@npm:8.3.3" + dependencies: + acorn: ^8.11.0 + checksum: 0f09d351fc30b69b2b9982bf33dc30f3d35a34e030e5f1ed3c49fc4e3814a192bf3101e4c30912a0595410f5e91bb70ddba011ea73398b3ecbfe41c7334c6dd0 languageName: node linkType: hard -"acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" +"acorn@npm:^8.11.0, acorn@npm:^8.11.3, acorn@npm:^8.9.0": + version: 8.12.0 + resolution: "acorn@npm:8.12.0" bin: acorn: bin/acorn - checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d + checksum: ae142de8739ef15a5d936c550c1d267fc4dedcdbe62ad1aa2c0009afed1de84dd0a584684a5d200bb55d8db14f3e09a95c6e92a5303973c04b9a7413c36d1df0 languageName: node linkType: hard @@ -1013,12 +999,12 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: ^7.0.1 - checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 languageName: node linkType: hard @@ -1145,24 +1131,24 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" +"debug@npm:4, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.3.5 + resolution: "debug@npm:4.3.5" dependencies: ms: 2.1.2 peerDependenciesMeta: supports-color: optional: true - checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 + checksum: 7c002b51e256257f936dda09eb37167df952758c57badf6bf44bdc40b89a4bcb8e5a0a2e4c7b53f97c69e2970dd5272d33a757378a12c8f8e64ea7bf99e8e86e languageName: node linkType: hard "deep-eql@npm:^4.1.3": - version: 4.1.3 - resolution: "deep-eql@npm:4.1.3" + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" dependencies: type-detect: ^4.0.0 - checksum: 7f6d30cb41c713973dc07eaadded848b2ab0b835e518a88b91bea72f34e08c4c71d167a722a6f302d3a6108f05afd8e6d7650689a84d5d29ec7fe6220420397f + checksum: 01c3ca78ff40d79003621b157054871411f94228ceb9b2cab78da913c606631c46e8aa79efc4aa0faf3ace3092acd5221255aab3ef0e8e7b438834f0ca9a16c7 languageName: node linkType: hard @@ -1276,33 +1262,33 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.20.1": - version: 0.20.2 - resolution: "esbuild@npm:0.20.2" - dependencies: - "@esbuild/aix-ppc64": 0.20.2 - "@esbuild/android-arm": 0.20.2 - "@esbuild/android-arm64": 0.20.2 - "@esbuild/android-x64": 0.20.2 - "@esbuild/darwin-arm64": 0.20.2 - "@esbuild/darwin-x64": 0.20.2 - "@esbuild/freebsd-arm64": 0.20.2 - "@esbuild/freebsd-x64": 0.20.2 - "@esbuild/linux-arm": 0.20.2 - "@esbuild/linux-arm64": 0.20.2 - "@esbuild/linux-ia32": 0.20.2 - "@esbuild/linux-loong64": 0.20.2 - "@esbuild/linux-mips64el": 0.20.2 - "@esbuild/linux-ppc64": 0.20.2 - "@esbuild/linux-riscv64": 0.20.2 - "@esbuild/linux-s390x": 0.20.2 - "@esbuild/linux-x64": 0.20.2 - "@esbuild/netbsd-x64": 0.20.2 - "@esbuild/openbsd-x64": 0.20.2 - "@esbuild/sunos-x64": 0.20.2 - "@esbuild/win32-arm64": 0.20.2 - "@esbuild/win32-ia32": 0.20.2 - "@esbuild/win32-x64": 0.20.2 +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": 0.21.5 + "@esbuild/android-arm": 0.21.5 + "@esbuild/android-arm64": 0.21.5 + "@esbuild/android-x64": 0.21.5 + "@esbuild/darwin-arm64": 0.21.5 + "@esbuild/darwin-x64": 0.21.5 + "@esbuild/freebsd-arm64": 0.21.5 + "@esbuild/freebsd-x64": 0.21.5 + "@esbuild/linux-arm": 0.21.5 + "@esbuild/linux-arm64": 0.21.5 + "@esbuild/linux-ia32": 0.21.5 + "@esbuild/linux-loong64": 0.21.5 + "@esbuild/linux-mips64el": 0.21.5 + "@esbuild/linux-ppc64": 0.21.5 + "@esbuild/linux-riscv64": 0.21.5 + "@esbuild/linux-s390x": 0.21.5 + "@esbuild/linux-x64": 0.21.5 + "@esbuild/netbsd-x64": 0.21.5 + "@esbuild/openbsd-x64": 0.21.5 + "@esbuild/sunos-x64": 0.21.5 + "@esbuild/win32-arm64": 0.21.5 + "@esbuild/win32-ia32": 0.21.5 + "@esbuild/win32-x64": 0.21.5 dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -1352,7 +1338,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: bc88050fc1ca5c1bd03648f9979e514bdefb956a63aa3974373bb7b9cbac0b3aac9b9da1b5bdca0b3490e39d6b451c72815dbd6b7d7f978c91fbe9c9e9aa4e4c + checksum: 2911c7b50b23a9df59a7d6d4cdd3a4f85855787f374dce751148dbb13305e0ce7e880dde1608c2ab7a927fc6cec3587b80995f7fc87a64b455f8b70b55fd8ec1 languageName: node linkType: hard @@ -1531,15 +1517,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.2.9": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": ^2.0.2 "@nodelib/fs.walk": ^1.2.3 glob-parent: ^5.1.2 merge2: ^1.3.0 micromatch: ^4.0.4 - checksum: b6f3add6403e02cf3a798bfbb1183d0f6da2afd368f27456010c0bc1f9640aea308243d4cb2c0ab142f618276e65ecb8be1661d7c62a7b4e5ba774b9ce5432e5 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 languageName: node linkType: hard @@ -1558,11 +1544,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.15.0 - resolution: "fastq@npm:1.15.0" + version: 1.17.1 + resolution: "fastq@npm:1.17.1" dependencies: reusify: ^1.0.4 - checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a + checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 languageName: node linkType: hard @@ -1575,12 +1561,12 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: ^5.0.1 - checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 languageName: node linkType: hard @@ -1595,30 +1581,30 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.1.0 - resolution: "flat-cache@npm:3.1.0" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: - flatted: ^3.2.7 + flatted: ^3.2.9 keyv: ^4.5.3 rimraf: ^3.0.2 - checksum: 99312601d5b90f44aef403f17f056dc09be7e437703740b166cdc9386d99e681f74e6b6e8bd7d010bda66904ea643c9527276b1b80308a2119741d94108a4d8f + checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec languageName: node linkType: hard -"flatted@npm:^3.2.7": - version: 3.2.7 - resolution: "flatted@npm:3.2.7" - checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35 +"flatted@npm:^3.2.9": + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 languageName: node linkType: hard "foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" + version: 3.2.1 + resolution: "foreground-child@npm:3.2.1" dependencies: cross-spawn: ^7.0.0 signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + checksum: 3e2e844d6003c96d70affe8ae98d7eaaba269a868c14d997620c088340a8775cd5d2d9043e6ceebae1928d8d9a874911c4d664b9a267e8995945df20337aebc0 languageName: node linkType: hard @@ -1699,17 +1685,18 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.4.1 - resolution: "glob@npm:10.4.1" + version: 10.4.2 + resolution: "glob@npm:10.4.2" dependencies: foreground-child: ^3.1.0 jackspeak: ^3.1.2 minimatch: ^9.0.4 minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 path-scurry: ^1.11.1 bin: glob: dist/esm/bin.mjs - checksum: 5d33c686c80bf6877f4284adf99a8c3cbb2a6eccbc92342943fe5d4b42c01d78c1881f2223d950c92a938d0f857e12e37b86a8e5483ab2141822e053b67d0dde + checksum: bd7c0e30701136e936f414e5f6f82c7f04503f01df77408f177aa584927412f0bde0338e6ec541618cd21eacc57dde33e7b3c6c0a779cc1c6e6a0e14f3d15d9b languageName: node linkType: hard @@ -1728,11 +1715,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.21.0 - resolution: "globals@npm:13.21.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: ^0.20.2 - checksum: 86c92ca8a04efd864c10852cd9abb1ebe6d447dcc72936783e66eaba1087d7dba5c9c3421a48d6ca722c319378754dbcc3f3f732dbe47592d7de908edf58a773 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c languageName: node linkType: hard @@ -1789,12 +1776,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 + checksum: 2e1a28960f13b041a50702ee74f240add8e75146a5c37fc98f1960f0496710f6918b3a9fe1e5aba41e50f58e6df48d107edd9c405c5f0d73ac260dabf2210857 languageName: node linkType: hard @@ -1815,9 +1802,9 @@ __metadata: linkType: hard "ignore@npm:^5.2.0": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef + version: 5.3.1 + resolution: "ignore@npm:5.3.1" + checksum: 71d7bb4c1dbe020f915fd881108cbe85a0db3d636a0ea3ba911393c53946711d13a9b1143c7e70db06d571a5822c0a324a6bcde5c9904e7ca5047f01f1bf8cd3 languageName: node linkType: hard @@ -1938,15 +1925,15 @@ __metadata: linkType: hard "jackspeak@npm:^3.1.2": - version: 3.1.2 - resolution: "jackspeak@npm:3.1.2" + version: 3.4.0 + resolution: "jackspeak@npm:3.4.0" dependencies: "@isaacs/cliui": ^8.0.2 "@pkgjs/parseargs": ^0.11.0 dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: 134276d5f785c518930701a0dcba1f3b0e9ce3e5b1c3e300898e2ae0bbd9b5195088b77252bf2110768de072c426e9e39f47e13912b0b002da4a3f4ff6e16eac + checksum: 350f6f311018bb175ffbe736b19c26ac0b134bb5a17a638169e89594eb0c24ab1c658ab3a2fda24ff63b3b19292e1a5ec19d2255bc526df704e8168d392bef85 languageName: node linkType: hard @@ -2004,11 +1991,11 @@ __metadata: linkType: hard "keyv@npm:^4.5.3": - version: 4.5.3 - resolution: "keyv@npm:4.5.3" + version: 4.5.4 + resolution: "keyv@npm:4.5.4" dependencies: json-buffer: 3.0.1 - checksum: 3ffb4d5b72b6b4b4af443bbb75ca2526b23c750fccb5ac4c267c6116888b4b65681015c2833cb20d26cf3e6e32dac6b988c77f7f022e1a571b7d90f1442257da + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 languageName: node linkType: hard @@ -2072,18 +2059,9 @@ __metadata: linkType: hard "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.2 - resolution: "lru-cache@npm:10.2.2" - checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e - languageName: node - linkType: hard - -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: ^4.0.0 - checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 + version: 10.3.0 + resolution: "lru-cache@npm:10.3.0" + checksum: f2289639bd94cf3c87bfd8a77ac991f9afe3af004ddca3548c3dae63ead1c73bba449a60a4e270992e16cf3261b3d4130943234d52ca3a4d4de2fc074a3cc7b5 languageName: node linkType: hard @@ -2138,12 +2116,12 @@ __metadata: linkType: hard "micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" + version: 4.0.7 + resolution: "micromatch@npm:4.0.7" dependencies: - braces: ^3.0.2 + braces: ^3.0.3 picomatch: ^2.3.1 - checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + checksum: 3cde047d70ad80cf60c787b77198d680db3b8c25b23feb01de5e2652205d9c19f43bd81882f69a0fd1f0cde6a7a122d774998aad3271ddb1b8accf8a0f480cf7 languageName: node linkType: hard @@ -2164,11 +2142,11 @@ __metadata: linkType: hard "minimatch@npm:^9.0.4": - version: 9.0.4 - resolution: "minimatch@npm:9.0.4" + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" dependencies: brace-expansion: ^2.0.1 - checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 + checksum: 2c035575eda1e50623c731ec6c14f65a85296268f749b9337005210bb2b34e2705f8ef1a358b188f69892286ab99dc42c8fb98a57bde55c8d81b3023c19cea28 languageName: node linkType: hard @@ -2266,14 +2244,14 @@ __metadata: linkType: hard "mlly@npm:^1.4.2, mlly@npm:^1.7.0": - version: 1.7.0 - resolution: "mlly@npm:1.7.0" + version: 1.7.1 + resolution: "mlly@npm:1.7.1" dependencies: acorn: ^8.11.3 pathe: ^1.1.2 - pkg-types: ^1.1.0 + pkg-types: ^1.1.1 ufo: ^1.5.3 - checksum: c1548f4dd0e31ce15d293ebb7c61778bd28c405573dc43dcf799eaeb8f6b776d7dadd95e957d6631b9cc4bb963cd01079d58b7e2290ed540aa460e061bdbd1fa + checksum: 956a6d54119eef782f302580f63a9800654e588cd70015b4218a00069c6ef11b87984e8ffe140a4668b0100ad4022b11d1f9b11ac2c6dbafa4d8bc33ae3a08a8 languageName: node linkType: hard @@ -2382,16 +2360,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.1": - version: 0.9.3 - resolution: "optionator@npm:0.9.3" + version: 0.9.4 + resolution: "optionator@npm:0.9.4" dependencies: - "@aashutoshrathi/word-wrap": ^1.2.3 deep-is: ^0.1.3 fast-levenshtein: ^2.0.6 levn: ^0.4.1 prelude-ls: ^1.2.1 type-check: ^0.4.0 - checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + word-wrap: ^1.2.5 + checksum: ecbd010e3dc73e05d239976422d9ef54a82a13f37c11ca5911dff41c98a6c7f0f163b27f922c37e7f8340af9d36febd3b6e9cef508f3339d4c393d7276d716bb languageName: node linkType: hard @@ -2431,6 +2409,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.0 + resolution: "package-json-from-dist@npm:1.0.0" + checksum: ac706ec856a5a03f5261e4e48fa974f24feb044d51f84f8332e2af0af04fbdbdd5bbbfb9cbbe354190409bc8307c83a9e38c6672c3c8855f709afb0006a009ea + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -2499,7 +2484,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": version: 1.0.1 resolution: "picocolors@npm:1.0.1" checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 @@ -2513,7 +2498,7 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.0.3, pkg-types@npm:^1.1.0": +"pkg-types@npm:^1.0.3, pkg-types@npm:^1.1.1": version: 1.1.1 resolution: "pkg-types@npm:1.1.1" dependencies: @@ -2525,13 +2510,13 @@ __metadata: linkType: hard "postcss@npm:^8.4.38": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" + version: 8.4.39 + resolution: "postcss@npm:8.4.39" dependencies: nanoid: ^3.3.7 - picocolors: ^1.0.0 + picocolors: ^1.0.1 source-map-js: ^1.2.0 - checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 + checksum: 14b130c90f165961772bdaf99c67f907f3d16494adf0868e57ef68baa67e0d1f6762db9d41ab0f4d09bab6fb7888588dba3596afd1a235fd5c2d43fba7006ac6 languageName: node linkType: hard @@ -2578,9 +2563,9 @@ __metadata: linkType: hard "punycode@npm:^2.1.0": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 languageName: node linkType: hard @@ -2718,7 +2703,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5": +"semver@npm:^7.3.5, semver@npm:^7.3.7": version: 7.6.2 resolution: "semver@npm:7.6.2" bin: @@ -2727,17 +2712,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.7": - version: 7.5.4 - resolution: "semver@npm:7.5.4" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 - languageName: node - linkType: hard - "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -2783,17 +2757,17 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.3 - resolution: "socks-proxy-agent@npm:8.0.3" + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" dependencies: agent-base: ^7.1.1 debug: ^4.3.4 - socks: ^2.7.1 - checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 + socks: ^2.8.3 + checksum: b2ec5051d85fe49072f9a250c427e0e9571fd09d5db133819192d078fd291276e1f0f50f6dbc04329b207738b1071314cee8bdbb4b12e27de42dbcf1d4233c67 languageName: node linkType: hard -"socks@npm:^2.7.1": +"socks@npm:^2.8.3": version: 2.8.3 resolution: "socks@npm:2.8.3" dependencies: @@ -2971,13 +2945,13 @@ __metadata: linkType: hard "ts-results-es@npm:^4.1.0": - version: 4.1.0 - resolution: "ts-results-es@npm:4.1.0" - checksum: c04fd553a37930d234b7d7d31a4c3ea4396e47986a34e528f572af93d070db5cc64f6fcf0587f3c2f9b7061132427e89033572706bfdda112a29929439c5ec46 + version: 4.2.0 + resolution: "ts-results-es@npm:4.2.0" + checksum: ff475c2f6d44377e0204211e6eafdbcabddf3ad09d40540ad5dee3d817eefbd48c07a21f5ad86864ef82cd8a5542a266af9dd8dd4d58d4766fdd6e79370519bb languageName: node linkType: hard -"tslib@npm:2.6.2, tslib@npm:^2.1.0, tslib@npm:^2.6.2": +"tslib@npm:2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad @@ -2991,6 +2965,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.1.0, tslib@npm:^2.6.2": + version: 2.6.3 + resolution: "tslib@npm:2.6.3" + checksum: 74fce0e100f1ebd95b8995fbbd0e6c91bdd8f4c35c00d4da62e285a3363aaa534de40a80db30ecfd388ed7c313c42d930ee0eaf108e8114214b180eec3dbe6f5 + languageName: node + linkType: hard + "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -3118,10 +3099,10 @@ __metadata: linkType: hard "vite@npm:^5.0.0": - version: 5.2.11 - resolution: "vite@npm:5.2.11" + version: 5.3.2 + resolution: "vite@npm:5.3.2" dependencies: - esbuild: ^0.20.1 + esbuild: ^0.21.3 fsevents: ~2.3.3 postcss: ^8.4.38 rollup: ^4.13.0 @@ -3153,7 +3134,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 3f9f976cc6ada93aca56abcc683a140e807725b351abc241a1ec0763ec561a4bf5760e1ad94de4e59505904ddaa88727de66af02f61ecf540c7720045de55d0a + checksum: d6872cb72701ec4b8d8dbccc5deacb5af03c3f247df02750787d6dcf4e49e207effed7a06e4f103008a918188cdf0789ff7348db451ebd0d59ef1a22ae4a267d languageName: node linkType: hard @@ -3241,6 +3222,13 @@ __metadata: languageName: node linkType: hard +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: f93ba3586fc181f94afdaff3a6fef27920b4b6d9eaefed0f428f8e07adea2a7f54a5f2830ce59406c8416f033f86902b91eb824072354645eea687dff3691ccb + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -3271,8 +3259,8 @@ __metadata: linkType: hard "ws@npm:^8.16.0": - version: 8.17.0 - resolution: "ws@npm:8.17.0" + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -3281,7 +3269,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 147ef9eab0251364e1d2c55338ad0efb15e6913923ccbfdf20f7a8a6cb8f88432bcd7f4d8f66977135bfad35575644f9983201c1a361019594a4e53977bf6d4e + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf languageName: node linkType: hard @@ -3300,8 +3288,8 @@ __metadata: linkType: hard "yocto-queue@npm:^1.0.0": - version: 1.0.0 - resolution: "yocto-queue@npm:1.0.0" - checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c languageName: node linkType: hard From e0f631a8e29c6c27b227eb110f18dfd0d2cd9edb Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 30 Jun 2024 17:38:55 -0500 Subject: [PATCH 81/90] temp fix --- package.json | 8 +++++++- yarn.lock | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2555191d..ffde8ce0 100644 --- a/package.json +++ b/package.json @@ -88,5 +88,11 @@ "engines": { "node": ">= 20.0.x" }, - "homepage": "https://sern.dev" + "homepage": "https://sern.dev", + "overrides": { + "ws": "8.17.1" + }, + "resolutions": { + "ws": "8.17.1" + } } diff --git a/yarn.lock b/yarn.lock index 4fca6641..064b9d75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3258,7 +3258,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.16.0": +"ws@npm:8.17.1": version: 8.17.1 resolution: "ws@npm:8.17.1" peerDependencies: From 92ca9eb85919f7a0a276d322f1eecb7a5f69a4d1 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Wed, 3 Jul 2024 22:25:24 -0500 Subject: [PATCH 82/90] namespace presence types again --- src/core/presences.ts | 36 ++++++++++++++++++++---------------- src/handlers/presence.ts | 8 ++++---- src/sern.ts | 4 ++-- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/core/presences.ts b/src/core/presences.ts index 4060fbc2..ee2850b7 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -3,16 +3,9 @@ import type { IntoDependencies } from "./ioc"; import type { Emitter } from "./interfaces"; type Status = 'online' | 'idle' | 'invisible' | 'dnd' -type PresenceReduce = (previous: PresenceResult) => PresenceResult; +type PresenceReduce = (previous: Presence.Result) => Presence.Result; + -export interface PresenceResult { - status?: Status; - afk?: boolean; - activities?: ActivitiesOptions[]; - shardId?: number[]; - repeat?: number | [Emitter, string]; - onRepeat?: (previous: PresenceResult) => PresenceResult; -} export const Presence = { /** @@ -20,13 +13,13 @@ export const Presence = { * Create a Presence module which **MUST** be put in a file called presence.(language-extension) * adjacent to the file where **Sern.init** is CALLED. */ - module : (conf: PresenceConfig) => conf, + module : (conf: Presence.Config) => conf, /** * Create a Presence body which can be either: * - once, the presence is activated only once. * - repeated, per cycle or event, the presence can be changed. */ - of : (root: Omit) => { + of : (root: Omit) => { return { /** * @example @@ -56,9 +49,20 @@ export const Presence = { }; } } +export declare namespace Presence { + type Config = { + inject?: [...T] + execute: (...v: IntoDependencies) => Presence.Result; + + } + + export interface Result { + status?: Status; + afk?: boolean; + activities?: ActivitiesOptions[]; + shardId?: number[]; + repeat?: number | [Emitter, string]; + onRepeat?: (previous: Result) => Result; + } +} -export type PresenceConfig = { - inject?: [...T] - execute: (...v: IntoDependencies) => PresenceResult; - -}; diff --git a/src/handlers/presence.ts b/src/handlers/presence.ts index f2528b6f..2282e3d3 100644 --- a/src/handlers/presence.ts +++ b/src/handlers/presence.ts @@ -1,11 +1,11 @@ import { concatMap, from, interval, of, map, scan, startWith, fromEvent, take } from "rxjs" -import { PresenceConfig, PresenceResult } from "../core/presences"; +import { Presence } from "../core/presences"; import { Services } from "../core/ioc"; import assert from "node:assert"; import * as Files from "../core/module-loading"; -type SetPresence = (conf: PresenceResult) => Promise +type SetPresence = (conf: Presence.Result) => Promise -const parseConfig = async (conf: Promise) => { +const parseConfig = async (conf: Promise) => { return conf.then(s => { if('repeat' in s) { const { onRepeat, repeat } = s; @@ -23,7 +23,7 @@ const parseConfig = async (conf: Promise) => { export const presenceHandler = (path: string, setPresence: SetPresence) => { const presence = Files - .importModule>(path) + .importModule>(path) .then(({ module }) => { //fetch services with the order preserved, passing it to the execute fn const fetchedServices = Services(...module.inject ?? []); diff --git a/src/sern.ts b/src/sern.ts index 85f8aab3..07f50a9d 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -11,7 +11,7 @@ import interactionHandler from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; import { handleCrash } from './handlers/event-utils'; import { UnpackedDependencies } from './types/utility'; -import type { PresenceResult } from './core/presences'; +import type { Presence} from './core/presences'; interface Wrapper { commands: string; @@ -52,7 +52,7 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { const time = ((performance.now() - startTime) / 1000).toFixed(2); deps['@sern/logger']?.info({ message: `sern: registered in ${time} s` }); if(presencePath.exists) { - const setPresence = async (p: PresenceResult) => { + const setPresence = async (p: Presence.Result) => { return deps['@sern/client'].user?.setPresence(p); } presenceHandler(presencePath.path, setPresence).subscribe(); From c2528549548fab00ef40694cb562f305e0cb4f3b Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:18:52 -0500 Subject: [PATCH 83/90] revising cron modules and better error messages --- .npmignore | 1 + package.json | 6 +-- src/core/ioc.ts | 4 +- src/core/presences.ts | 8 ++- src/core/schedule.ts | 43 +++++++++++++++ src/core/structures/default-services.ts | 70 +++++++++---------------- src/core/structures/enums.ts | 1 - src/handlers/event-utils.ts | 5 +- src/handlers/interaction.ts | 5 +- src/handlers/message.ts | 6 ++- src/handlers/tasks.ts | 23 ++++++++ src/handlers/user-defined-events.ts | 8 +-- src/sern.ts | 7 ++- src/types/core-modules.ts | 12 +---- yarn.lock | 54 ++++++++++--------- 15 files changed, 148 insertions(+), 105 deletions(-) create mode 100644 src/core/schedule.ts create mode 100644 src/handlers/tasks.ts diff --git a/.npmignore b/.npmignore index 243080d9..dd784f7c 100644 --- a/.npmignore +++ b/.npmignore @@ -113,3 +113,4 @@ tsconfig-cjs.json tsconfig-esm.json renovate.json +fortnite diff --git a/package.json b/package.json index ffde8ce0..83075b12 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@sern/handler", "packageManager": "yarn@3.5.0", - "version": "3.3.4", + "version": "4.0.0", "description": "A complete, customizable, typesafe, & reactive framework for discord bots.", "main": "./dist/index.js", "module": "./dist/index.js", @@ -35,10 +35,10 @@ "author": "SernDevs", "license": "MIT", "dependencies": { - "@sern/ioc": "^1.0.4", + "@sern/ioc": "^1.1.0", "callsites": "^3.1.0", + "cron": "^3.1.7", "deepmerge": "^4.3.1", - "node-cron": "^3.0.3", "rxjs": "^7.8.0", "ts-results-es": "^4.1.0" }, diff --git a/src/core/ioc.ts b/src/core/ioc.ts index 0f0a7b1a..65a6c587 100644 --- a/src/core/ioc.ts +++ b/src/core/ioc.ts @@ -67,8 +67,8 @@ export async function makeDependencies (conf: ValidDependencyConfig) { container.addSingleton('@sern/errors', new __Services.DefaultErrorHandling); container.addSingleton('@sern/modules', new Map); container.addSingleton('@sern/emitter', new EventEmitter) - container.addWiredSingleton('@sern/cron', - (deps) => new __Services.Cron(deps as unknown as Dependencies)) + container.addWiredSingleton('@sern/scheduler', + (deps) => new __Services.CronScheduler(deps as unknown as Dependencies)) conf(dependencyBuilder(container)); await container.ready(); } diff --git a/src/core/presences.ts b/src/core/presences.ts index ee2850b7..3dbc9d64 100644 --- a/src/core/presences.ts +++ b/src/core/presences.ts @@ -39,10 +39,8 @@ export const Presence = { * @example * ```ts * Presence.of({ - * activities: [ - * { name: "Chilling out" } - * ] - * }).once() // Sets the presence once, with what's provided in '.of()' + * activities: [{ name: "Chilling out" }] + * }).once() // Sets the presence once, with what's provided in '.of()' * ``` */ once: () => root @@ -50,7 +48,7 @@ export const Presence = { } } export declare namespace Presence { - type Config = { + export type Config = { inject?: [...T] execute: (...v: IntoDependencies) => Presence.Result; diff --git a/src/core/schedule.ts b/src/core/schedule.ts new file mode 100644 index 00000000..fea65c49 --- /dev/null +++ b/src/core/schedule.ts @@ -0,0 +1,43 @@ +import { CronJob } from 'cron'; +export class TaskScheduler { + private __tasks: Map = new Map(); + + scheduleTask(taskName: string, cronExpression: string, task: () => void): boolean { + if (this.__tasks.has(taskName)) { + return false; + } + try { + const job = new CronJob(cronExpression, task); + job.start(); + this.__tasks.set(taskName, job); + return true; + } catch (error) { + return false; + } + } + + private stopTask(taskName: string): boolean { + const job = this.__tasks.get(taskName); + if (job) { + job.stop(); + this.__tasks.delete(taskName); + return true; + } + return false; + } + + private restartTask(taskName: string): boolean { + const job = this.__tasks.get(taskName); + if (job) { + job.start(); + return true; + } + return false; + } + + + tasks(): string[] { + return Array.from(this.__tasks.keys()); + } + +} diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 474a6e49..18ddc77f 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,8 +1,6 @@ import type { LogPayload, Logging, ErrorHandling, Emitter } from '../interfaces'; import { AnyFunction, UnpackedDependencies } from '../../types/utility'; -import cron from 'node-cron' -import type { CronEventCommand, Module } from '../../types/core-modules' -import { EventType } from './enums'; + /** * @internal * @since 2.0.0 @@ -42,48 +40,30 @@ export class DefaultLogging implements Logging { } } -export class Cron implements Emitter { +export class CronScheduler { tasks: string[] = []; - modules: Map = new Map(); constructor(private deps: UnpackedDependencies) {} - private sanityCheck(eventName: string | symbol) : asserts eventName is string { - if(typeof eventName === 'symbol') throw Error("Cron cannot add symbol based listener") - } - addCronModule(module: Module) { - if(module.type !== EventType.Cron) { - throw Error("Can only add cron modules"); - } - //@ts-ignore - if(!cron.validate(module.pattern)) { - throw Error("Invalid cron expression while adding " + module.name) - } - (module as CronEventCommand) - this.modules.set(module.name!, module as CronEventCommand); - } - addListener(eventName: string | symbol, listener: AnyFunction): this { - this.sanityCheck(eventName); - const retrievedModule = this.modules.get(eventName); - if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); - const { pattern, name, runOnInit, timezone } = retrievedModule; - cron.schedule(pattern, - (date) => listener({ date, deps: this.deps }), - { name, runOnInit, timezone, scheduled: true }); - return this; - } - removeListener(eventName: string | symbol, listener: AnyFunction) { - this.sanityCheck(eventName); - const retrievedModule = this.modules.get(eventName); - if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); - const task = cron.getTasks().get(retrievedModule.name!) - if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found"); - task.stop(); - return this; - } - emit(eventName: string | symbol, ...payload: any[]): boolean { - this.sanityCheck(eventName); - const retrievedModule = this.modules.get(eventName); - if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); - const task= cron.getTasks().get(retrievedModule.name!) - return task?.emit(eventName, payload) ?? false; - } +// addListener(eventName: string | symbol, listener: AnyFunction): this { +// const retrievedModule = this.modules.get(eventName); +// if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); +// const { pattern, name, runOnInit, timezone } = retrievedModule; +// cron.schedule(pattern, +// (date) => listener({ date, deps: this.deps }), +// { name, runOnInit, timezone, scheduled: true }); +// return this; +// } +// removeListener(eventName: string | symbol, listener: AnyFunction) { +// const retrievedModule = this.modules.get(eventName); +// if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); +// const task = cron.getTasks().get(retrievedModule.name!) +// if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found"); +// task.stop(); +// return this; +// } +// emit(eventName: string | symbol, ...payload: any[]): boolean { +// const retrievedModule = this.modules.get(eventName); +// if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); +// const task= cron.getTasks().get(retrievedModule.name!) +// return task?.emit(eventName, payload) ?? false; +// } } diff --git a/src/core/structures/enums.ts b/src/core/structures/enums.ts index 2990c2e7..83675a77 100644 --- a/src/core/structures/enums.ts +++ b/src/core/structures/enums.ts @@ -58,7 +58,6 @@ export enum EventType { * Could be for example, `process` events, database events */ External, - Cron } /** diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index 2f2f17a3..a6a4089d 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -262,10 +262,9 @@ export function intoTask(onStop: (m: Module) => unknown) { return createResultResolver({ onStop, onNext }); } -export const handleCrash = - ({ "@sern/errors": err, '@sern/emitter': sem, '@sern/logger': log } : UnpackedDependencies) => +export const handleCrash = ({ "@sern/errors": err, '@sern/emitter': sem, '@sern/logger': log } : UnpackedDependencies, metadata: string) => pipe(catchError(handleError(err, sem, log)), finalize(() => { - log?.info({ message: 'A stream closed or reached end of lifetime' }); + log?.info({ message: 'A stream closed: ' + metadata }); disposeAll(log); })) diff --git a/src/handlers/interaction.ts b/src/handlers/interaction.ts index e09eeef5..6b57e415 100644 --- a/src/handlers/interaction.ts +++ b/src/handlers/interaction.ts @@ -1,6 +1,6 @@ import type { Interaction } from 'discord.js'; import { mergeMap, merge, concatMap, EMPTY } from 'rxjs'; -import { createInteractionHandler, executeModule, intoTask, sharedEventStream, filterTap } from './event-utils'; +import { createInteractionHandler, executeModule, intoTask, sharedEventStream, filterTap, handleCrash } from './event-utils'; import { SernError } from '../core/structures/enums' import { isAutocomplete, isCommand, isMessageComponent, isModal, resultPayload } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; @@ -25,5 +25,6 @@ export default function interactionHandler(deps: UnpackedDependencies, defaultPr if(payload) return executeModule(emitter, payload) return EMPTY; - })); + }), + handleCrash(deps, "interaction handling")); } diff --git a/src/handlers/message.ts b/src/handlers/message.ts index 60b3b8de..4fac7d2e 100644 --- a/src/handlers/message.ts +++ b/src/handlers/message.ts @@ -1,6 +1,6 @@ import { EMPTY, mergeMap, concatMap } from 'rxjs'; import type { Message } from 'discord.js'; -import { createMessageHandler, executeModule, intoTask, sharedEventStream, filterTap} from './event-utils'; +import { createMessageHandler, executeModule, intoTask, sharedEventStream, filterTap, handleCrash} from './event-utils'; import { SernError } from '../core/structures/enums' import { resultPayload } from '../core/functions' import { UnpackedDependencies } from '../types/utility'; @@ -44,5 +44,7 @@ function (deps: UnpackedDependencies, defaultPrefix?: string) { if(payload) return executeModule(emitter, payload) return EMPTY; - })); + }), + handleCrash(deps, "message handling") + ) } diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts new file mode 100644 index 00000000..441b1cf8 --- /dev/null +++ b/src/handlers/tasks.ts @@ -0,0 +1,23 @@ +import { TaskScheduler } from "../core/schedule" +import * as Files from '../core/module-loading' +import { UnpackedDependencies } from "../types/utility"; + +interface ScheduledTaskModule { + name?: string; + description?: string; + pattern: string; + execute(deps: UnpackedDependencies, tasks: string[]): any +} + +export const registerTasks = async (path: string, deps: UnpackedDependencies) => { + const taskManager = new TaskScheduler() + + for await (const f of Files.readRecursive(path)) { + let { module } = await Files.importModule(f); + //module.name is assigned by Files.importModule<> + taskManager.scheduleTask(module.name!, module.pattern, () => { + module.execute(deps, taskManager.tasks()) + }) + } + +} diff --git a/src/handlers/user-defined-events.ts b/src/handlers/user-defined-events.ts index ebbe4b9b..aea565a5 100644 --- a/src/handlers/user-defined-events.ts +++ b/src/handlers/user-defined-events.ts @@ -14,12 +14,6 @@ const intoDispatcher = (deps: UnpackedDependencies) => return eventDispatcher(deps, module, deps['@sern/client']); case EventType.External: return eventDispatcher(deps, module, deps[module.emitter]); - case EventType.Cron: { - //@ts-ignore - const cron = deps['@sern/cron']; - cron.addCronModule(module); - return eventDispatcher(deps, module, cron); - } default: throw Error(SernError.InvalidModuleType + ' while creating event handler'); } }; @@ -34,6 +28,6 @@ export default async function(deps: UnpackedDependencies, eventDir: string) { from(eventModules) .pipe(map(intoDispatcher(deps)), mergeAll(), // all eventListeners are turned on - handleCrash(deps)) + handleCrash(deps, "event modules")) .subscribe(); } diff --git a/src/sern.ts b/src/sern.ts index 07f50a9d..72ea4b3d 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -12,11 +12,13 @@ import { presenceHandler } from './handlers/presence'; import { handleCrash } from './handlers/event-utils'; import { UnpackedDependencies } from './types/utility'; import type { Presence} from './core/presences'; +import { registerTasks } from './handlers/tasks'; interface Wrapper { commands: string; defaultPrefix?: string; events?: string; + tasks?: string; } /** * @since 1.0.0 @@ -57,11 +59,14 @@ export function init(maybeWrapper: Wrapper = { commands: "./dist/commands" }) { } presenceHandler(presencePath.path, setPresence).subscribe(); } + if(maybeWrapper.tasks) { + registerTasks(maybeWrapper.tasks, deps); + } }) .catch(err => { throw err }); const messages$ = messageHandler(deps, maybeWrapper.defaultPrefix); const interactions$ = interactionHandler(deps, maybeWrapper.defaultPrefix); // listening to the message stream and interaction stream - merge(messages$, interactions$).pipe(handleCrash(deps)).subscribe(); + merge(messages$, interactions$).subscribe(); } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 8437fe2e..a9bf143b 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -58,14 +58,7 @@ export interface ExternalEventCommand extends Module { type: EventType.External; execute(...args: unknown[]): Awaitable; } -export interface CronEventCommand extends Module { - type: EventType.Cron; - name?: string; - pattern: string; - runOnInit?: boolean - timezone?: string; - execute(...args: unknown[]): Awaitable; -} + export interface ContextMenuUser extends Module { type: CommandType.CtxUser; @@ -142,7 +135,7 @@ export interface BothCommand extends Module { execute: (ctx: Context, tbd: SDT) => Awaitable; } -export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand | CronEventCommand; +export type EventModule = DiscordEventCommand | SernEventCommand | ExternalEventCommand; export type CommandModule = | TextCommand | SlashCommand @@ -178,7 +171,6 @@ export interface EventModuleDefs { [EventType.Sern]: SernEventCommand; [EventType.Discord]: DiscordEventCommand; [EventType.External]: ExternalEventCommand; - [EventType.Cron]: CronEventCommand; } export interface SernAutocompleteData diff --git a/yarn.lock b/yarn.lock index 064b9d75..177077c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -546,16 +546,16 @@ __metadata: resolution: "@sern/handler@workspace:." dependencies: "@faker-js/faker": ^8.0.1 - "@sern/ioc": ^1.0.4 + "@sern/ioc": ^1.1.0 "@types/node": ^20.0.0 "@types/node-cron": ^3.0.11 "@typescript-eslint/eslint-plugin": 5.58.0 "@typescript-eslint/parser": 5.59.1 callsites: ^3.1.0 + cron: ^3.1.7 deepmerge: ^4.3.1 discord.js: ^14.15.3 eslint: 8.39.0 - node-cron: ^3.0.3 rxjs: ^7.8.0 ts-results-es: ^4.1.0 typescript: 5.0.2 @@ -563,10 +563,10 @@ __metadata: languageName: unknown linkType: soft -"@sern/ioc@npm:^1.0.4": - version: 1.0.4 - resolution: "@sern/ioc@npm:1.0.4" - checksum: 3d1a63099b3e8ff0d44bb73007b1d66c3f3b27cf7a193c2d9122e021cb72be1ced535ea98efaf72602f371a489177e3b144ed72da8d7de80887c0408ce79cce2 +"@sern/ioc@npm:^1.1.0": + version: 1.1.0 + resolution: "@sern/ioc@npm:1.1.0" + checksum: 0882ef51c3fcd28e7fe803762f2a8d7eb3dca4e494d3475ef7d4a43158d3b24243bda3679c3d58485c89bdc820719d22351007503e44b5cf8e6f2d0efe342921 languageName: node linkType: hard @@ -591,6 +591,13 @@ __metadata: languageName: node linkType: hard +"@types/luxon@npm:~3.4.0": + version: 3.4.2 + resolution: "@types/luxon@npm:3.4.2" + checksum: 6f92d5bd02e89f310395753506bcd9cef3a56f5940f7a50db2a2b9822bce753553ac767d143cb5b4f9ed5ddd4a84e64f89ff538082ceb4d18739af7781b56925 + languageName: node + linkType: hard + "@types/node-cron@npm:^3.0.11": version: 3.0.11 resolution: "@types/node-cron@npm:3.0.11" @@ -1120,6 +1127,16 @@ __metadata: languageName: node linkType: hard +"cron@npm:^3.1.7": + version: 3.1.7 + resolution: "cron@npm:3.1.7" + dependencies: + "@types/luxon": ~3.4.0 + luxon: ~3.4.0 + checksum: d98ee5297543c138221d96dd49270bf6576db80134e6041f4ce4a3c0cb6060863d76910209b34fee66fbf134461449ec3bd283d6a76d1c50da220cde7fc10c65 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -2065,6 +2082,13 @@ __metadata: languageName: node linkType: hard +"luxon@npm:~3.4.0": + version: 3.4.4 + resolution: "luxon@npm:3.4.4" + checksum: 36c1f99c4796ee4bfddf7dc94fa87815add43ebc44c8934c924946260a58512f0fd2743a629302885df7f35ccbd2d13f178c15df046d0e3b6eb71db178f1c60c + languageName: node + linkType: hard + "magic-bytes.js@npm:^1.10.0": version: 1.10.0 resolution: "magic-bytes.js@npm:1.10.0" @@ -2292,15 +2316,6 @@ __metadata: languageName: node linkType: hard -"node-cron@npm:^3.0.3": - version: 3.0.3 - resolution: "node-cron@npm:3.0.3" - dependencies: - uuid: 8.3.2 - checksum: 351c37491ebf717d0ae69cc941465de118e5c2ef5d48bc3f87c98556241b060f100402c8a618c7b86f9f626b44756b20d8b5385b70e52f80716f21e55db0f1c5 - languageName: node - linkType: hard - "node-gyp@npm:latest": version: 10.1.0 resolution: "node-gyp@npm:10.1.0" @@ -3074,15 +3089,6 @@ __metadata: languageName: node linkType: hard -"uuid@npm:8.3.2": - version: 8.3.2 - resolution: "uuid@npm:8.3.2" - bin: - uuid: dist/bin/uuid - checksum: 5575a8a75c13120e2f10e6ddc801b2c7ed7d8f3c8ac22c7ed0c7b2ba6383ec0abda88c905085d630e251719e0777045ae3236f04c812184b7c765f63a70e58df - languageName: node - linkType: hard - "vite-node@npm:1.6.0": version: 1.6.0 resolution: "vite-node@npm:1.6.0" From 210aa41c7e1005df7b5b79271af9d38f6fa2e73d Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 5 Jul 2024 14:46:31 -0500 Subject: [PATCH 84/90] scheduler ids --- src/core/modules.ts | 6 ++++++ src/core/schedule.ts | 12 ++++++++++-- src/handlers/ready.ts | 4 ++-- src/handlers/tasks.ts | 32 +++++++++++++++++++------------- src/index.ts | 4 +++- src/types/core-modules.ts | 20 +++++++++++++++++++- 6 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/core/modules.ts b/src/core/modules.ts index 8d9d6f19..81ffbabe 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -4,6 +4,7 @@ import type { InputCommand, InputEvent, Module, + ScheduledTask, } from '../types/core-modules'; import { partitionPlugins } from './functions' import type { Awaitable } from '../types/utility'; @@ -46,3 +47,8 @@ export function discordEvent(mod: { return eventModule({ type: EventType.Discord, ...mod, }); } + +export function scheduledTask(i : ScheduledTask) { + return i +} + diff --git a/src/core/schedule.ts b/src/core/schedule.ts index fea65c49..966da128 100644 --- a/src/core/schedule.ts +++ b/src/core/schedule.ts @@ -2,16 +2,24 @@ import { CronJob } from 'cron'; export class TaskScheduler { private __tasks: Map = new Map(); - scheduleTask(taskName: string, cronExpression: string, task: () => void): boolean { + scheduleTask(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined): boolean { if (this.__tasks.has(taskName)) { + console.warn("While scheduling a task", + "found another task of same name. Not scheduling", + taskName, "again"); return false; } try { - const job = new CronJob(cronExpression, task); + const job = CronJob.from({ + cronTime: cronExpression, + onTick: task, + timeZone: tz + }); job.start(); this.__tasks.set(taskName, job); return true; } catch (error) { + console.error("While scheduling a task " + error); return false; } } diff --git a/src/handlers/ready.ts b/src/handlers/ready.ts index 83f485c5..662b1bd0 100644 --- a/src/handlers/ready.ts +++ b/src/handlers/ready.ts @@ -23,8 +23,8 @@ export default async function(dir: string, deps : UnpackedDependencies) { if(!validType) { throw Error(`Found ${module.name} at ${module.meta.absPath}, which has incorrect \`type\``); } - const resultModule = await callInitPlugins(module, deps, true); // FREEZE! no more writing!! - + const resultModule = await callInitPlugins(module, deps, true); + // FREEZE! no more writing!! commands.set(resultModule.meta.id, Object.freeze(resultModule)); sEmitter.emit('module.register', resultPayload('success', resultModule)); } diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts index 441b1cf8..1f5a80f4 100644 --- a/src/handlers/tasks.ts +++ b/src/handlers/tasks.ts @@ -1,23 +1,29 @@ import { TaskScheduler } from "../core/schedule" import * as Files from '../core/module-loading' import { UnpackedDependencies } from "../types/utility"; +import { ScheduledTask } from "../types/core-modules"; +import { CronJob } from "cron"; +import { relative } from "path"; +import { fileURLToPath } from "url"; -interface ScheduledTaskModule { - name?: string; - description?: string; - pattern: string; - execute(deps: UnpackedDependencies, tasks: string[]): any -} - -export const registerTasks = async (path: string, deps: UnpackedDependencies) => { +export const registerTasks = async (tasksPath: string, deps: UnpackedDependencies) => { const taskManager = new TaskScheduler() - for await (const f of Files.readRecursive(path)) { - let { module } = await Files.importModule(f); + for await (const f of Files.readRecursive(tasksPath)) { + let { module } = await Files.importModule(f); + //module.name is assigned by Files.importModule<> - taskManager.scheduleTask(module.name!, module.pattern, () => { - module.execute(deps, taskManager.tasks()) - }) + // the id created for the task is unique + const uuid = module.name!+":"+relative(tasksPath,fileURLToPath(f)) + taskManager.scheduleTask(uuid, module.pattern, function(this: CronJob) { + module.execute({ + deps, + runningTasks: taskManager.tasks(), + lastTimeExecution: this.lastExecution, + nextTimeExecution: this.nextDate().toJSDate() + }) + }, + module.timezone) } } diff --git a/src/index.ts b/src/index.ts index 1667ff98..7de8cdca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,7 +25,8 @@ export type { SernOptionsData, SernSubCommandData, SernSubCommandGroupData, - SDT + SDT, + ScheduledTask } from './types/core-modules'; export type { @@ -43,6 +44,7 @@ export { commandModule, eventModule, discordEvent, + scheduledTask } from './core/modules'; export * from './core/presences' diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index a9bf143b..d8c380b3 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -19,7 +19,7 @@ import type { import type { CommandType, EventType } from '../core/structures/enums'; import { Context } from '../core/structures/context' import { ControlPlugin, InitPlugin, Plugin } from './core-plugin'; -import { Awaitable, SernEventsMapping } from './utility'; +import { Awaitable, SernEventsMapping, UnpackedDependencies } from './utility'; //state, deps, type (very original) export type SDT = { @@ -222,3 +222,21 @@ export interface SernSubCommandGroupData extends BaseApplicationCommandOptionsDa type: ApplicationCommandOptionType.SubcommandGroup; options?: SernSubCommandData[]; } + + +interface ScheduledTaskContext { + deps: UnpackedDependencies, + lastTimeExecution: Date | null; + runningTasks: string[]; + nextTimeExecution: Date | null; +} + +export interface ScheduledTask { + name?: string; + pattern: string | Date; + description?: string; + timezone?: string; + execute(tasks: ScheduledTaskContext): Awaitable +} + + From 870972000db0686034d5bdf8676dbc9e901233a3 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 5 Jul 2024 15:48:55 -0500 Subject: [PATCH 85/90] more descriptive errors --- src/core/schedule.ts | 21 ++++++++------------- src/handlers/tasks.ts | 8 +++----- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/core/schedule.ts b/src/core/schedule.ts index 966da128..30c10c50 100644 --- a/src/core/schedule.ts +++ b/src/core/schedule.ts @@ -1,26 +1,21 @@ import { CronJob } from 'cron'; +import { Err, Ok, type Result } from 'ts-results-es' export class TaskScheduler { private __tasks: Map = new Map(); - scheduleTask(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined): boolean { + scheduleTask(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined): Result { if (this.__tasks.has(taskName)) { - console.warn("While scheduling a task", - "found another task of same name. Not scheduling", - taskName, "again"); - return false; + return Err("while scheduling a task \ + found another task of same name. Not scheduling " + + taskName + "again." ); } try { - const job = CronJob.from({ - cronTime: cronExpression, - onTick: task, - timeZone: tz - }); + const job = CronJob.from({ cronTime: cronExpression, onTick: task, timeZone: tz }); job.start(); this.__tasks.set(taskName, job); - return true; + return Ok.EMPTY; } catch (error) { - console.error("While scheduling a task " + error); - return false; + return Err(`while scheduling a task ${taskName} ` + error); } } diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts index 1f5a80f4..c869e93d 100644 --- a/src/handlers/tasks.ts +++ b/src/handlers/tasks.ts @@ -14,16 +14,14 @@ export const registerTasks = async (tasksPath: string, deps: UnpackedDependencie //module.name is assigned by Files.importModule<> // the id created for the task is unique - const uuid = module.name!+":"+relative(tasksPath,fileURLToPath(f)) - taskManager.scheduleTask(uuid, module.pattern, function(this: CronJob) { + const uuid = module.name!+"/"+relative(tasksPath,fileURLToPath(f)) + taskManager.scheduleTask(uuid, module.pattern, function(this: CronJob) { module.execute({ deps, runningTasks: taskManager.tasks(), lastTimeExecution: this.lastExecution, nextTimeExecution: this.nextDate().toJSDate() }) - }, - module.timezone) + }, module.timezone).unwrap() } - } From 482105712bfae55356a0160bb118a995fc754938 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Fri, 5 Jul 2024 17:18:26 -0500 Subject: [PATCH 86/90] refactor to not type leak and job cancellation --- src/core/ioc.ts | 5 +- src/core/schedule.ts | 46 ---------------- src/core/structures/default-services.ts | 72 +++++++++++++++---------- src/handlers/tasks.ts | 11 ++-- src/types/core-modules.ts | 16 +++++- 5 files changed, 66 insertions(+), 84 deletions(-) delete mode 100644 src/core/schedule.ts diff --git a/src/core/ioc.ts b/src/core/ioc.ts index 65a6c587..32bb56dc 100644 --- a/src/core/ioc.ts +++ b/src/core/ioc.ts @@ -67,8 +67,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { container.addSingleton('@sern/errors', new __Services.DefaultErrorHandling); container.addSingleton('@sern/modules', new Map); container.addSingleton('@sern/emitter', new EventEmitter) - container.addWiredSingleton('@sern/scheduler', - (deps) => new __Services.CronScheduler(deps as unknown as Dependencies)) + container.addSingleton('@sern/scheduler', new __Services.TaskScheduler) conf(dependencyBuilder(container)); await container.ready(); } @@ -152,5 +151,7 @@ export interface CoreDependencies { * by module.meta.id -> Module */ '@sern/modules': Map; + + '@sern/scheduler': __Services.TaskScheduler } diff --git a/src/core/schedule.ts b/src/core/schedule.ts deleted file mode 100644 index 30c10c50..00000000 --- a/src/core/schedule.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { CronJob } from 'cron'; -import { Err, Ok, type Result } from 'ts-results-es' -export class TaskScheduler { - private __tasks: Map = new Map(); - - scheduleTask(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined): Result { - if (this.__tasks.has(taskName)) { - return Err("while scheduling a task \ - found another task of same name. Not scheduling " + - taskName + "again." ); - } - try { - const job = CronJob.from({ cronTime: cronExpression, onTick: task, timeZone: tz }); - job.start(); - this.__tasks.set(taskName, job); - return Ok.EMPTY; - } catch (error) { - return Err(`while scheduling a task ${taskName} ` + error); - } - } - - private stopTask(taskName: string): boolean { - const job = this.__tasks.get(taskName); - if (job) { - job.stop(); - this.__tasks.delete(taskName); - return true; - } - return false; - } - - private restartTask(taskName: string): boolean { - const job = this.__tasks.get(taskName); - if (job) { - job.start(); - return true; - } - return false; - } - - - tasks(): string[] { - return Array.from(this.__tasks.keys()); - } - -} diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 18ddc77f..c4126adb 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,5 +1,5 @@ -import type { LogPayload, Logging, ErrorHandling, Emitter } from '../interfaces'; -import { AnyFunction, UnpackedDependencies } from '../../types/utility'; +import type { LogPayload, Logging, ErrorHandling } from '../interfaces'; +import { CronJob } from 'cron'; /** * @internal @@ -40,30 +40,46 @@ export class DefaultLogging implements Logging { } } -export class CronScheduler { - tasks: string[] = []; - constructor(private deps: UnpackedDependencies) {} -// addListener(eventName: string | symbol, listener: AnyFunction): this { -// const retrievedModule = this.modules.get(eventName); -// if(!retrievedModule) throw Error("Adding task: module " +eventName +"was not found"); -// const { pattern, name, runOnInit, timezone } = retrievedModule; -// cron.schedule(pattern, -// (date) => listener({ date, deps: this.deps }), -// { name, runOnInit, timezone, scheduled: true }); -// return this; -// } -// removeListener(eventName: string | symbol, listener: AnyFunction) { -// const retrievedModule = this.modules.get(eventName); -// if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); -// const task = cron.getTasks().get(retrievedModule.name!) -// if(!task) throw Error("Finding cron task with"+ retrievedModule.name + " not found"); -// task.stop(); -// return this; -// } -// emit(eventName: string | symbol, ...payload: any[]): boolean { -// const retrievedModule = this.modules.get(eventName); -// if(!retrievedModule) throw Error("Removing cron: module " +eventName +"was not found"); -// const task= cron.getTasks().get(retrievedModule.name!) -// return task?.emit(eventName, payload) ?? false; -// } + +export class TaskScheduler { + private __tasks: Map = new Map(); + + schedule(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined) { + if (this.__tasks.has(taskName)) { + throw Error("while scheduling a task \ + found another task of same name. Not scheduling " + + taskName + "again." ); + } + try { + const job = CronJob.from({ cronTime: cronExpression, onTick: task, timeZone: tz }); + job.start(); + this.__tasks.set(taskName, job); + } catch (error) { + throw Error(`while scheduling a task ${taskName} ` + error); + } + } + + kill(taskName: string): boolean { + const job = this.__tasks.get(taskName); + if (job) { + job.stop(); + this.__tasks.delete(taskName); + return true; + } + return false; + } + + private restartTask(taskName: string): boolean { + const job = this.__tasks.get(taskName); + if (job) { + job.start(); + return true; + } + return false; + } + + get tasks(): string[] { + return Array.from(this.__tasks.keys()); + } + } diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts index c869e93d..a722df45 100644 --- a/src/handlers/tasks.ts +++ b/src/handlers/tasks.ts @@ -1,4 +1,3 @@ -import { TaskScheduler } from "../core/schedule" import * as Files from '../core/module-loading' import { UnpackedDependencies } from "../types/utility"; import { ScheduledTask } from "../types/core-modules"; @@ -7,21 +6,21 @@ import { relative } from "path"; import { fileURLToPath } from "url"; export const registerTasks = async (tasksPath: string, deps: UnpackedDependencies) => { - const taskManager = new TaskScheduler() + const taskManager = deps['@sern/scheduler'] for await (const f of Files.readRecursive(tasksPath)) { - let { module } = await Files.importModule(f); + let { module } = await Files.importModule(f); //module.name is assigned by Files.importModule<> // the id created for the task is unique const uuid = module.name!+"/"+relative(tasksPath,fileURLToPath(f)) - taskManager.scheduleTask(uuid, module.pattern, function(this: CronJob) { + taskManager.schedule(uuid, module.trigger, function(this: CronJob) { module.execute({ deps, - runningTasks: taskManager.tasks(), + id: uuid, lastTimeExecution: this.lastExecution, nextTimeExecution: this.nextDate().toJSDate() }) - }, module.timezone).unwrap() + }, module.timezone) } } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index d8c380b3..3b7d3024 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -225,15 +225,27 @@ export interface SernSubCommandGroupData extends BaseApplicationCommandOptionsDa interface ScheduledTaskContext { + /** + * An object of dependencies configured in `makeDependencies` + */ deps: UnpackedDependencies, + /** + * the uuid of the current task being run + */ + id: string; + /** + * the last time this task was executed. If this is the first time, it is null. + */ lastTimeExecution: Date | null; - runningTasks: string[]; + /** + * The next time this task will be executed. + */ nextTimeExecution: Date | null; } export interface ScheduledTask { name?: string; - pattern: string | Date; + trigger: string | Date; description?: string; timezone?: string; execute(tasks: ScheduledTaskContext): Awaitable From 2014e0ea8edacd530c48913ea535305a979fc241 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sat, 6 Jul 2024 14:12:03 -0500 Subject: [PATCH 87/90] refactor n better signatures for task scheduler --- src/core/modules.ts | 5 ++- src/core/structures/default-services.ts | 46 ++++++++++++++----------- src/handlers/event-utils.ts | 2 +- src/handlers/tasks.ts | 15 ++------ src/types/core-modules.ts | 4 +-- 5 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/core/modules.ts b/src/core/modules.ts index 81ffbabe..24c34d81 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -47,8 +47,7 @@ export function discordEvent(mod: { return eventModule({ type: EventType.Discord, ...mod, }); } - -export function scheduledTask(i : ScheduledTask) { - return i +export function scheduledTask(ism: ScheduledTask) { + return ism } diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index c4126adb..4c7cf275 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -1,4 +1,5 @@ -import type { LogPayload, Logging, ErrorHandling } from '../interfaces'; +import { ScheduledTask } from '../../types/core-modules'; +import type { LogPayload, Logging, ErrorHandling, Disposable } from '../interfaces'; import { CronJob } from 'cron'; /** @@ -41,21 +42,28 @@ export class DefaultLogging implements Logging { } -export class TaskScheduler { - private __tasks: Map = new Map(); +export class TaskScheduler implements Disposable { + private __tasks: Map> = new Map(); - schedule(taskName: string, cronExpression: string | Date, task: () => void, tz: string| undefined) { - if (this.__tasks.has(taskName)) { + schedule(uuid: string, task: ScheduledTask, deps: Dependencies) { + if (this.__tasks.has(uuid)) { throw Error("while scheduling a task \ - found another task of same name. Not scheduling " + - taskName + "again." ); + found another task of same name. Not scheduling " + + uuid + "again." ); } try { - const job = CronJob.from({ cronTime: cronExpression, onTick: task, timeZone: tz }); - job.start(); - this.__tasks.set(taskName, job); + const onTick = async function(this: CronJob) { + task.execute({ + deps, id: uuid, + lastTimeExecution: this.lastExecution, + nextTimeExecution: this.nextDate().toJSDate() + }) + } + const job = CronJob.from({ cronTime: task.trigger, onTick, timeZone: task.timezone }); + job.start(); + this.__tasks.set(uuid, job); } catch (error) { - throw Error(`while scheduling a task ${taskName} ` + error); + throw Error(`while scheduling a task ${uuid} ` + error); } } @@ -69,17 +77,15 @@ export class TaskScheduler { return false; } - private restartTask(taskName: string): boolean { - const job = this.__tasks.get(taskName); - if (job) { - job.start(); - return true; - } - return false; - } - get tasks(): string[] { return Array.from(this.__tasks.keys()); } + + dispose() { + for(const [id,] of this.__tasks){ + this.kill(id); + this.__tasks.delete(id); + } + } } diff --git a/src/handlers/event-utils.ts b/src/handlers/event-utils.ts index a6a4089d..fbe25659 100644 --- a/src/handlers/event-utils.ts +++ b/src/handlers/event-utils.ts @@ -236,7 +236,7 @@ export async function callInitPlugins(_module: Module, deps: Dependencies, emit? return module } -async function callPlugins({ args, module, deps, params }: ExecutePayload) { +export async function callPlugins({ args, module, deps, params }: ExecutePayload) { let state = {}; for(const plugin of module.onEvent??[]) { const result = await plugin.execute(...args, { state, deps, params, type: module.type }); diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts index a722df45..cf01605b 100644 --- a/src/handlers/tasks.ts +++ b/src/handlers/tasks.ts @@ -1,26 +1,17 @@ import * as Files from '../core/module-loading' import { UnpackedDependencies } from "../types/utility"; -import { ScheduledTask } from "../types/core-modules"; +import type { ScheduledTask } from "../types/core-modules"; import { CronJob } from "cron"; import { relative } from "path"; import { fileURLToPath } from "url"; export const registerTasks = async (tasksPath: string, deps: UnpackedDependencies) => { - const taskManager = deps['@sern/scheduler'] for await (const f of Files.readRecursive(tasksPath)) { let { module } = await Files.importModule(f); - //module.name is assigned by Files.importModule<> // the id created for the task is unique - const uuid = module.name!+"/"+relative(tasksPath,fileURLToPath(f)) - taskManager.schedule(uuid, module.trigger, function(this: CronJob) { - module.execute({ - deps, - id: uuid, - lastTimeExecution: this.lastExecution, - nextTimeExecution: this.nextDate().toJSDate() - }) - }, module.timezone) + const uuid = module.name+"/"+relative(tasksPath,fileURLToPath(f)) + taskManager.schedule(uuid, module, deps) } } diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index 3b7d3024..f03b7956 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -224,7 +224,7 @@ export interface SernSubCommandGroupData extends BaseApplicationCommandOptionsDa } -interface ScheduledTaskContext { +export interface ScheduledTaskContext { /** * An object of dependencies configured in `makeDependencies` */ @@ -243,10 +243,10 @@ interface ScheduledTaskContext { nextTimeExecution: Date | null; } + export interface ScheduledTask { name?: string; trigger: string | Date; - description?: string; timezone?: string; execute(tasks: ScheduledTaskContext): Awaitable } From 5d0260ab4e873d9bbe37b1bfbd5b08aab81c2891 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Sun, 7 Jul 2024 18:21:16 -0500 Subject: [PATCH 88/90] documentation --- src/core/ioc.ts | 8 +++++--- src/core/modules.ts | 6 ++---- src/core/structures/default-services.ts | 7 ++++--- src/handlers/tasks.ts | 1 - 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/ioc.ts b/src/core/ioc.ts index 32bb56dc..a605a88e 100644 --- a/src/core/ioc.ts +++ b/src/core/ioc.ts @@ -74,9 +74,9 @@ export async function makeDependencies (conf: ValidDependencyConfig) { /** - * The new Service api, a cleaner alternative to useContainer + * The Service api, which allows users to access dependencies in places IOC cannot reach. * To obtain intellisense, ensure a .d.ts file exists in the root of compilation. - * Usually our scaffolding tool takes care of this. + * Our scaffolding tool takes care of this. * Note: this method only works AFTER your container has been initiated * @since 3.0.0 * @example @@ -84,7 +84,7 @@ export async function makeDependencies (conf: ValidDependencyConfig) { * const client = Service('@sern/client'); * ``` * @param key a key that corresponds to a dependency registered. - * + * @throws if container is absent or not present */ export function Service(key: T) { return $Service(key) as Dependencies[T] @@ -92,7 +92,9 @@ export function Service(key: T) { /** * @since 3.0.0 * The plural version of {@link Service} + * @throws if container is absent or not present * @returns array of dependencies, in the same order of keys provided + * */ export function Services(...keys: [...T]) { return $Services>(...keys) diff --git a/src/core/modules.ts b/src/core/modules.ts index 24c34d81..4de590af 100644 --- a/src/core/modules.ts +++ b/src/core/modules.ts @@ -37,17 +37,15 @@ export function eventModule(mod: InputEvent): Module { /** Create event modules from discord.js client events, * This is an {@link eventModule} for discord events, * where typings can be very bad. - * @Experimental * @param mod */ export function discordEvent(mod: { name: T; + once?: boolean; execute: (...args: ClientEvents[T]) => Awaitable; }) { return eventModule({ type: EventType.Discord, ...mod, }); } -export function scheduledTask(ism: ScheduledTask) { - return ism -} +export function scheduledTask(ism: ScheduledTask) { return ism } diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 4c7cf275..2700f1cf 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -54,7 +54,8 @@ export class TaskScheduler implements Disposable { try { const onTick = async function(this: CronJob) { task.execute({ - deps, id: uuid, + deps, + id: uuid, lastTimeExecution: this.lastExecution, nextTimeExecution: this.nextDate().toJSDate() }) @@ -82,10 +83,10 @@ export class TaskScheduler implements Disposable { } dispose() { - for(const [id,] of this.__tasks){ + this.__tasks.forEach((_, id) => { this.kill(id); this.__tasks.delete(id); - } + }) } } diff --git a/src/handlers/tasks.ts b/src/handlers/tasks.ts index cf01605b..a204fc5c 100644 --- a/src/handlers/tasks.ts +++ b/src/handlers/tasks.ts @@ -1,7 +1,6 @@ import * as Files from '../core/module-loading' import { UnpackedDependencies } from "../types/utility"; import type { ScheduledTask } from "../types/core-modules"; -import { CronJob } from "cron"; import { relative } from "path"; import { fileURLToPath } from "url"; From c35337c3cfc90742ee17ade6484b5b5b16aac823 Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 16 Jul 2024 23:09:24 -0500 Subject: [PATCH 89/90] fix swap not accepting functions --- src/core/ioc.ts | 6 +++++- src/sern.ts | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/ioc.ts b/src/core/ioc.ts index a605a88e..ebd4deaa 100644 --- a/src/core/ioc.ts +++ b/src/core/ioc.ts @@ -38,7 +38,11 @@ const dependencyBuilder = (container: Container) => { * Swap out a preexisting dependency. */ swap(key: keyof Dependencies, v: Insertable) { - container.swap(key, v); + if(typeof v !== 'function') { + container.swap(key, v); + } else { + container.swap(key, v(container.deps())); + } }, }; }; diff --git a/src/sern.ts b/src/sern.ts index 72ea4b3d..4f8faf44 100644 --- a/src/sern.ts +++ b/src/sern.ts @@ -9,7 +9,6 @@ import ready from './handlers/ready'; import messageHandler from './handlers/message'; import interactionHandler from './handlers/interaction'; import { presenceHandler } from './handlers/presence'; -import { handleCrash } from './handlers/event-utils'; import { UnpackedDependencies } from './types/utility'; import type { Presence} from './core/presences'; import { registerTasks } from './handlers/tasks'; From d1680e51fcbf3e0cb125452dc2c68faf189c0122 Mon Sep 17 00:00:00 2001 From: Jacob Nguyen <76754747+jacoobes@users.noreply.github.com> Date: Thu, 18 Jul 2024 16:47:07 -0500 Subject: [PATCH 90/90] change task signature --- src/core/structures/default-services.ts | 9 +++------ src/types/core-modules.ts | 14 +++++++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/core/structures/default-services.ts b/src/core/structures/default-services.ts index 2700f1cf..a9581969 100644 --- a/src/core/structures/default-services.ts +++ b/src/core/structures/default-services.ts @@ -53,12 +53,9 @@ export class TaskScheduler implements Disposable { } try { const onTick = async function(this: CronJob) { - task.execute({ - deps, - id: uuid, - lastTimeExecution: this.lastExecution, - nextTimeExecution: this.nextDate().toJSDate() - }) + task.execute({ id: uuid, + lastTimeExecution: this.lastExecution, + nextTimeExecution: this.nextDate().toJSDate() }, { deps }) } const job = CronJob.from({ cronTime: task.trigger, onTick, timeZone: task.timezone }); job.start(); diff --git a/src/types/core-modules.ts b/src/types/core-modules.ts index f03b7956..a4dc9267 100644 --- a/src/types/core-modules.ts +++ b/src/types/core-modules.ts @@ -225,10 +225,7 @@ export interface SernSubCommandGroupData extends BaseApplicationCommandOptionsDa export interface ScheduledTaskContext { - /** - * An object of dependencies configured in `makeDependencies` - */ - deps: UnpackedDependencies, + /** * the uuid of the current task being run */ @@ -243,12 +240,19 @@ export interface ScheduledTaskContext { nextTimeExecution: Date | null; } +//name subject to change +interface TaskAttrs { + /** + * An object of dependencies configured in `makeDependencies` + */ + deps: UnpackedDependencies +} export interface ScheduledTask { name?: string; trigger: string | Date; timezone?: string; - execute(tasks: ScheduledTaskContext): Awaitable + execute(tasks: ScheduledTaskContext, sdt: TaskAttrs): Awaitable }