diff --git a/src/core/module-loading.ts b/src/core/module-loading.ts new file mode 100644 index 0000000..2cfa48c --- /dev/null +++ b/src/core/module-loading.ts @@ -0,0 +1,78 @@ +import { readdirSync, statSync } from 'fs'; +import { join, basename } from 'path'; +import { type Observable, from, mergeMap } from 'rxjs'; +import { SernError } from './structures/errors'; +import { type Result, Err, Ok } from 'ts-results-es'; +import { ImportPayload } from '../types/handler'; +import { pathToFileURL } from 'node:url'; + +// Courtesy @Townsy45 +function readPath(dir: string, arrayOfFiles: string[] = []): string[] { + try { + const files = readdirSync(dir); + for (const file of files) { + if (statSync(dir + '/' + file).isDirectory()) readPath(dir + '/' + file, arrayOfFiles); + else arrayOfFiles.push(join(dir, '/', file)); + } + } catch (err) { + throw err; + } + + return arrayOfFiles; +} +export const fmtFileName = (n: string) => n.substring(0, n.length - 3); +// export const isLazy = (n: string) => n.indexOf(".lazy.", n.length-9) !== -1; + +export async function defaultModuleLoader( + absPath: string, +): Promise, SernError>> { + // prettier-ignore + let module: T | undefined + /// #if MODE === 'esm' + = (await import(pathToFileURL(absPath).toString())).default + /// #elif MODE === 'cjs' + = require(absPath).default; // eslint-disable-line + /// #endif + if (module === undefined) { + return Err(SernError.UndefinedModule); + } + try { + module = new (module as unknown as new () => T)(); + } catch {} + return Ok({ module, absPath }); +} + +/** + * 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( + commandDir: string, +): Observable, SernError>> { + const commands = getCommands(commandDir); + return from(commands).pipe(mergeMap(defaultModuleLoader)); +} + +export function getCommands(dir: string): string[] { + return readPath(join(process.cwd(), dir)); +} +export function filename(path: string) { + return fmtFileName(basename(path)) +} +//https://stackoverflow.com/questions/16697791/nodejs-get-filename-of-caller-function +export function filePath() { + const err = new Error(); + + Error.prepareStackTrace = (_, stack) => stack; + + const stack = err.stack as unknown as NodeJS.CallSite[]; + + Error.prepareStackTrace = undefined; + const path = stack[2].getFileName(); + if(path === null) { + throw Error("Could not get the name of commandModule.") + } + return path; +} diff --git a/src/core/platform.ts b/src/core/platform.ts new file mode 100644 index 0000000..f776db2 --- /dev/null +++ b/src/core/platform.ts @@ -0,0 +1,43 @@ +export const enum DispatchType { + Websocket, + Serverless +} + +export type PlatformStrategy = + | WebsocketStrategy + | ServerlessStrategy; + +export interface WebsocketStrategy { + type: DispatchType.Websocket; + //icreate, messageCreate, ready + eventNames: [interactioncreate: string, messagecreate: string, ready: string] + defaultPrefix?: string; +} + +export interface ServerlessStrategy { + type: DispatchType.Serverless; + endpoint: string; +} + +export function makeWebsocketAdapter( + eventNames: [interactioncreate: string, messagecreate: string, ready: string], + defaultPrefix?: string +): WebsocketStrategy { + return { + type: DispatchType.Websocket, + eventNames, + defaultPrefix + }; +} + +export function makeServerlessAdapter(i : { endpoint: string }): ServerlessStrategy { + return { + type: DispatchType.Serverless , + ...i + }; +} + +export const discordjs = ( defaultPrefix?: string ) => makeWebsocketAdapter( + ['interactionCreate', 'messageCreate', 'ready'], + defaultPrefix +)