style: pretty

This commit is contained in:
Jacob Nguyen
2023-05-18 11:57:28 -05:00
parent f2b53dac32
commit 59a13765a5
32 changed files with 270 additions and 255 deletions

View File

@@ -18,6 +18,4 @@ export interface ErrorHandling {
* @param error
*/
updateAlive(error: Error): void;
}

View File

@@ -5,5 +5,5 @@ import { Awaitable } from '../../shared';
* Let dependencies implement this to initiate some logic.
*/
export interface Init {
init() : Awaitable<unknown>
init(): Awaitable<unknown>;
}

View File

@@ -9,6 +9,5 @@ export interface ModuleManager {
setMetadata(m: Module, c: CommandMeta): void;
set(id: string, path: string): void;
getPublishableCommands(): Promise<CommandModule[]>;
remove(id: string) : boolean
remove(id: string): boolean;
}

View File

@@ -1,9 +1,9 @@
import { CommandMeta, Module } from "../types/modules";
import { CommandMeta, Module } from '../types/modules';
/**
* Represents a core module store that stores IDs mapped to file paths.
*/
export interface CoreModuleStore {
commands : Map<string, string>;
metadata : WeakMap<Module, CommandMeta>
commands: Map<string, string>;
metadata: WeakMap<Module, CommandMeta>;
}

View File

@@ -8,14 +8,19 @@ import { PluginType } from './structures';
export const ok = /* @__PURE__*/ () => Ok.EMPTY;
export const err = /* @__PURE__*/ () => Err.EMPTY;
export function partitionPlugins(arr: (AnyEventPlugin|AnyCommandPlugin)[] = []): [Plugin[], Plugin[]] {
export function partitionPlugins(
arr: (AnyEventPlugin | AnyCommandPlugin)[] = [],
): [Plugin[], Plugin[]] {
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;
switch (el.type) {
case PluginType.Control:
controlPlugins.push(el);
break;
case PluginType.Init:
initPlugins.push(el);
break;
}
}
return [controlPlugins, initPlugins];
@@ -39,22 +44,22 @@ export function treeSearch(
switch (cur.type) {
case ApplicationCommandOptionType.Subcommand:
case ApplicationCommandOptionType.SubcommandGroup:
{
{
for (const option of cur.options ?? []) {
_options.push(option);
}
}
break;
}
break;
default:
{
if (cur.autocomplete) {
const choice = iAutocomplete.options.getFocused(true);
if (cur.name === choice.name && cur.autocomplete) {
autocompleteData = cur;
{
if (cur.autocomplete) {
const choice = iAutocomplete.options.getFocused(true);
if (cur.name === choice.name && cur.autocomplete) {
autocompleteData = cur;
}
}
}
}
break;
break;
}
}
return autocompleteData;

View File

@@ -24,12 +24,6 @@ export type {
EventModuleDefs,
BaseOptions,
SernAutocompleteData,
SernOptionsData
SernOptionsData,
} from './types/modules';
export type {
Controller,
PluginResult,
InitPlugin,
ControlPlugin,
Plugin
} from './types/plugins';
export type { Controller, PluginResult, InitPlugin, ControlPlugin, Plugin } from './types/plugins';

View File

@@ -3,8 +3,7 @@ import { composeRoot, useContainer } from './dependency-injection';
import { Dependencies, DependencyConfiguration } from './types';
import { CoreContainer } from '../structures/container';
//SIDE EFFECT: GLOBAL DI
//SIDE EFFECT: GLOBAL DI
let containerSubject: CoreContainer<Partial<Dependencies>>;
/**
@@ -14,7 +13,7 @@ let containerSubject: CoreContainer<Partial<Dependencies>>;
export function useContainerRaw() {
assert.ok(
containerSubject && containerSubject.isReady(),
"Could not find container or container wasn't ready. Did you call makeDependencies?"
"Could not find container or container wasn't ready. Did you call makeDependencies?",
);
return containerSubject;
}
@@ -33,4 +32,3 @@ export async function makeDependencies<const T extends Dependencies>(
return useContainer<T>();
}

View File

@@ -1,10 +1,15 @@
import type { DependencyConfiguration, MapDeps, IntoDependencies, Dependencies, CoreDependencies } from './types';
import type {
DependencyConfiguration,
MapDeps,
IntoDependencies,
Dependencies,
CoreDependencies,
} from './types';
import { DefaultLogging } from '../structures';
import { SernError } from '../structures/errors';
import { useContainerRaw } from './base';
import { CoreContainer } from '../structures/container';
/**
* @__PURE__
* @since 2.0.0.
@@ -18,7 +23,7 @@ export function single<T>(cb: () => T) {
/**
* @__PURE__
* @since 2.0.0
* Creates a transient object
* Creates a transient object
* @param cb
*/
export function transient<T>(cb: () => () => T) {
@@ -42,7 +47,7 @@ export function Services<const T extends (keyof Dependencies)[]>(...keys: [...T]
*/
export async function composeRoot(
container: CoreContainer<Partial<Dependencies>>,
conf: DependencyConfiguration
conf: DependencyConfiguration,
) {
//container should have no client or logger yet.
const hasLogger = conf.exclude?.has('@sern/logger');
@@ -71,11 +76,7 @@ export function useContainer<const T extends Dependencies>() {
Warning: using a container hook (useContainer) is not recommended.
Could lead to many unwanted side effects.
Use the new Service(s) api function instead.
`
);
`);
return <V extends (keyof T)[]>(...keys: [...V]) =>
keys.map(key => useContainerRaw().get(key as keyof Dependencies)) as MapDeps<T, V>;
}

View File

@@ -3,7 +3,6 @@ import * as Contract from '../contracts';
export type Singleton<T> = () => T;
export type Transient<T> = () => () => T;
export interface CoreDependencies {
'@sern/logger'?: Singleton<Contract.Logging>;
'@sern/emitter': Singleton<import('../structures/sern-emitter').SernEmitter>;
@@ -15,10 +14,10 @@ export interface CoreDependencies {
export interface Dependencies extends CoreDependencies {
'@sern/client': Singleton<import('node:events').EventEmitter>;
}
export type DependencyFromKey<T extends keyof Dependencies> = Dependencies[T];
export type DependencyFromKey<T extends keyof Dependencies> = Dependencies[T];
export type IntoDependencies<Tuple extends [...any[]]> = {
[Index in keyof Tuple]: UnpackFunction<DependencyFromKey<Tuple[Index]>&{}>; //Unpack and make NonNullable
[Index in keyof Tuple]: UnpackFunction<DependencyFromKey<Tuple[Index]> & {}>; //Unpack and make NonNullable
} & { length: Tuple['length'] };
export interface DependencyConfiguration {
@@ -38,4 +37,3 @@ export type MapDeps<Deps extends Dependencies, T extends readonly unknown[]> = T
...(MapDeps<Deps, Rest> extends [never] ? [] : MapDeps<Deps, Rest>),
]
: [never];

View File

@@ -9,19 +9,18 @@ import { CommandExecutable, clazz } from '../handler/commands';
export type ModuleResult<T> = Promise<Result<ImportPayload<T>, SernError>>;
function isClassModule(m: unknown): m is typeof CommandExecutable {
return m != undefined && Reflect.has(m, clazz);
}
export async function importModule<T>(absPath: string) {
let module =
/// #if MODE === 'esm'
import(absPath).then(i => i.default); // eslint-disable-line
let module =
/// #if MODE === 'esm'
import(absPath).then(i => i.default); // eslint-disable-line
/// #elif MODE === 'cjs'
require(absPath).default; // eslint-disable-line
/// #endif
return module.then(m => isClassModule(m) ? m.getInstance():m) as T;
return module.then(m => (isClassModule(m) ? m.getInstance() : m)) as T;
}
export async function defaultModuleLoader<T extends Module>(absPath: string): ModuleResult<T> {
let module = await importModule<T>(absPath);
@@ -32,7 +31,6 @@ export async function defaultModuleLoader<T extends Module>(absPath: string): Mo
return Ok({ module, absPath });
}
export const fmtFileName = (n: string) => n.substring(0, n.length - 3);
/**
@@ -64,19 +62,18 @@ async function* readPaths(dir: string, shouldDebug: boolean): AsyncGenerator<str
const base = basename(file);
if (fileStats.isDirectory()) {
//Todo: refactor so that i dont repeat myself for files (line 71)
if(base.endsWith('-ignore!')) {
if(shouldDebug)
console.info(`ignored directory: ${fullPath}`);
if (base.endsWith('-ignore!')) {
if (shouldDebug) console.info(`ignored directory: ${fullPath}`);
} else {
yield* readPaths(fullPath, shouldDebug);
}
} else {
const isSkippable = fmtFileName(base).endsWith('-ignore!')
|| !['.js', '.cjs', '.mts', '.mjs'].includes(extname(base));
const isSkippable =
fmtFileName(base).endsWith('-ignore!') ||
!['.js', '.cjs', '.mts', '.mjs'].includes(extname(base));
if(isSkippable) {
if(shouldDebug)
console.info(`ignored: ${fullPath}`);
if (isSkippable) {
if (shouldDebug) console.info(`ignored: ${fullPath}`);
} else {
/// #if MODE === 'esm'
yield 'file:///' + fullPath;
@@ -90,4 +87,3 @@ async function* readPaths(dir: string, shouldDebug: boolean): AsyncGenerator<str
throw err;
}
}

View File

@@ -97,9 +97,7 @@ export const sharedObservable = <T>(e: EventEmitter, eventName: string) => {
export function handleError<C>(crashHandler: ErrorHandling, logging?: Logging) {
return (pload: unknown, caught: Observable<C>) => {
// This is done to fit the ErrorHandling contract
const err = pload instanceof Error
? pload
: Error(util.inspect(pload, { colors: true }));
const err = pload instanceof Error ? pload : Error(util.inspect(pload, { colors: true }));
if (crashHandler.keepAlive == 0) {
crashHandler.crash(err);
}

View File

@@ -1,6 +1,6 @@
import { Container } from 'iti';
import { DefaultErrorHandling, DefaultModuleManager, SernEmitter } from '../';
import { isAsyncFunction} from 'node:util/types';
import { isAsyncFunction } from 'node:util/types';
import * as assert from 'node:assert';
import { Subject } from 'rxjs';
import { ModuleStore } from './module-store';
@@ -22,34 +22,35 @@ export class CoreContainer<T extends Partial<Dependencies>> extends Container<T,
'@sern/errors': () => new DefaultErrorHandling(),
'@sern/emitter': () => new SernEmitter(),
'@sern/store': () => new ModuleStore(),
}).add(ctx => {
})
.add(ctx => {
return { '@sern/modules': () => new DefaultModuleManager(ctx['@sern/store']) };
});
}
private listenForInsertions() {
assert.ok(!this.isReady(), 'listening for init functions should only occur prior to sern being ready.');
const unsubscriber = this.on('containerUpserted', this.callInitHooks);
this.ready$.subscribe({
complete: unsubscriber
});
private listenForInsertions() {
assert.ok(
!this.isReady(),
'listening for init functions should only occur prior to sern being ready.',
);
const unsubscriber = this.on('containerUpserted', this.callInitHooks);
this.ready$.subscribe({
complete: unsubscriber,
});
}
private async callInitHooks(e: { key: keyof T, newContainer: T[keyof T]|null }) {
private async callInitHooks(e: { key: keyof T; newContainer: T[keyof T] | null }) {
const dep = e.newContainer;
assert.ok(dep);
//Ignore any dependencies that are not objects or array
if(typeof(dep) !== 'object' || Array.isArray(dep)) {
if (typeof dep !== 'object' || Array.isArray(dep)) {
return;
}
if('init' in dep && typeof dep.init === 'function') {
isAsyncFunction(dep.init)
? await dep.init()
: dep.init();
}
if ('init' in dep && typeof dep.init === 'function') {
isAsyncFunction(dep.init) ? await dep.init() : dep.init();
}
}
isReady() {

View File

@@ -92,4 +92,3 @@ export class Context extends CoreContext<Message, ChatInputCommandInteraction> {
function safeUnwrap<T>(res: Result<T, T>) {
return res.val;
}

View File

@@ -7,6 +7,6 @@ import { Module, CommandMeta } from '../types/modules';
* For interacting with modules, use the ModuleManager instead.
*/
export class ModuleStore implements CoreModuleStore {
metadata = new WeakMap<Module, CommandMeta>();
metadata = new WeakMap<Module, CommandMeta>();
commands = new Map<string, string>();
}

View File

@@ -7,7 +7,6 @@ import { Module } from '../types/modules';
* @since 1.0.0
*/
export class SernEmitter extends EventEmitter {
constructor() {
super({ captureRejections: true });
}

View File

@@ -3,42 +3,42 @@ import { CoreModuleStore, ModuleManager } from '../../contracts';
import { importModule } from '../../module-loading';
import { CommandMeta, CommandModule, Module } from '../../types/modules';
/**
* @internal
* @since 2.0.0
* Version 4.0.0 will internalize this api. Please refrain from using ModuleStore!
*/
* @internal
* @since 2.0.0
* Version 4.0.0 will internalize this api. Please refrain from using ModuleStore!
*/
export class DefaultModuleManager implements ModuleManager {
constructor(private moduleStore: CoreModuleStore) {}
setMetadata(m: Module, c: CommandMeta): void {
constructor(private moduleStore: CoreModuleStore) {}
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 " + maybeModule);
}
return maybeModule;
}
remove(id: string): boolean {
throw new Error('Method not implemented.');
}
getMetadata(m: Module): CommandMeta {
const maybeModule = this.moduleStore.metadata.get(m);
if (!maybeModule) {
throw Error('Could not find metadata in store for ' + maybeModule);
}
return maybeModule;
}
get(id: string) {
return this.moduleStore.commands.get(id);
}
set(id: string, path: string): void {
this.moduleStore.commands.set(id, path);
}
//not tested
getPublishableCommands(): Promise<CommandModule[]> {
const entries = this.moduleStore.commands.entries();
const publishable = 0b000000110;
return Promise.all(
Array.from(entries)
.filter(([id]) => !(Number.parseInt(id.at(-1)!) & publishable))
.map(([, path]) => importModule<CommandModule>(path))
);
}
remove(id: string): boolean {
throw new Error('Method not implemented.');
}
get(id: string) {
return this.moduleStore.commands.get(id);
}
set(id: string, path: string): void {
this.moduleStore.commands.set(id, path);
}
//not tested
getPublishableCommands(): Promise<CommandModule[]> {
const entries = this.moduleStore.commands.entries();
const publishable = 0b000000110;
return Promise.all(
Array.from(entries)
.filter(([id]) => !(Number.parseInt(id.at(-1)!) & publishable))
.map(([, path]) => importModule<CommandModule>(path)),
);
}
}

View File

@@ -29,8 +29,6 @@ import { Awaitable, SernEventsMapping } from '../../shared';
import { Processed } from '../../handler/types';
import { Args, SlashOptions } from '../../shared';
export interface CommandMeta {
fullPath: string;
id: string;

View File

@@ -12,11 +12,40 @@
*/
import type { Err, Ok, Result } from 'ts-results-es';
import type { BothCommand, ButtonCommand, ChannelSelectCommand, CommandModule, ContextMenuMsg, ContextMenuUser, DiscordEventCommand, EventModule, ExternalEventCommand, MentionableSelectCommand, ModalSubmitCommand, RoleSelectCommand, SernEventCommand, SlashCommand, StringSelectCommand, TextCommand, UserSelectCommand } from './modules';
import type {
BothCommand,
ButtonCommand,
ChannelSelectCommand,
CommandModule,
ContextMenuMsg,
ContextMenuUser,
DiscordEventCommand,
EventModule,
ExternalEventCommand,
MentionableSelectCommand,
ModalSubmitCommand,
RoleSelectCommand,
SernEventCommand,
SlashCommand,
StringSelectCommand,
TextCommand,
UserSelectCommand,
} from './modules';
import { Args, Awaitable, Payload, SlashOptions } from '../../shared';
import { CommandType, Context, EventType, PluginType } from '../structures';
import { InitArgs, Processed } from '../../handler/types';
import { ButtonInteraction, ChannelSelectMenuInteraction, ClientEvents, MentionableSelectMenuInteraction, MessageContextMenuCommandInteraction, ModalSubmitInteraction, RoleSelectMenuInteraction, StringSelectMenuInteraction, UserContextMenuCommandInteraction, UserSelectMenuInteraction } from 'discord.js';
import {
ButtonInteraction,
ChannelSelectMenuInteraction,
ClientEvents,
MentionableSelectMenuInteraction,
MessageContextMenuCommandInteraction,
ModalSubmitInteraction,
RoleSelectMenuInteraction,
StringSelectMenuInteraction,
UserContextMenuCommandInteraction,
UserSelectMenuInteraction,
} from 'discord.js';
export type PluginResult = Awaitable<VoidResult>;
export type VoidResult = Result<void, void>;