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] 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 b795945..f759ef4 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 b632ba6..fcf878d 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 ab57476..e06055e 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 06d1bf1..84d389e 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 d006c44..78b1024 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 6baefda..54c042e 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 2e8ebb3..1b302d6 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 89f8a12..7b0c948 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 77a1358..35e6c02 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'] }); + }); })