mirror of
https://github.com/sern-handler/handler
synced 2026-06-19 22:32:14 +00:00
feat!: new module resolution algorithm
This commit is contained in:
@@ -1,35 +1,45 @@
|
||||
import { readdirSync, statSync } from 'fs';
|
||||
import { join, basename } from 'path';
|
||||
import { readdir, stat } from 'fs/promises';
|
||||
import { join, basename, resolve } 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';
|
||||
import { Processed } from '../types/handler';
|
||||
import { Module } from '../types/module';
|
||||
import * as assert from 'node:assert'
|
||||
import * as util from 'node:util'
|
||||
|
||||
// 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;
|
||||
async function* readPath(dir: string): AsyncGenerator<string> {
|
||||
try {
|
||||
const files = await readdir(dir);
|
||||
for (const file of files) {
|
||||
const fullPath = join(dir, file);
|
||||
const fileStats = await stat(fullPath);
|
||||
if (fileStats.isDirectory()) {
|
||||
yield* readPath(fullPath);
|
||||
} else {
|
||||
/// #if MODE === 'esm'
|
||||
yield 'file:///'+fullPath;
|
||||
/// #elif MODE === 'cjs'
|
||||
yield fullPath;
|
||||
/// #endif
|
||||
}
|
||||
}
|
||||
|
||||
return arrayOfFiles;
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
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<T>(
|
||||
|
||||
export const fmtFileName = (n: string) => n.substring(0, n.length - 3);
|
||||
|
||||
export async function defaultModuleLoader<T extends Module>(
|
||||
absPath: string,
|
||||
): Promise<Result<ImportPayload<T>, SernError>> {
|
||||
): Promise<Result< Processed<T>, SernError>> {
|
||||
// prettier-ignore
|
||||
let module: T | undefined
|
||||
/// #if MODE === 'esm'
|
||||
= (await import(pathToFileURL(absPath).toString())).default
|
||||
= (await import(absPath)).default
|
||||
/// #elif MODE === 'cjs'
|
||||
= require(absPath).default; // eslint-disable-line
|
||||
/// #endif
|
||||
@@ -39,7 +49,12 @@ export async function defaultModuleLoader<T>(
|
||||
try {
|
||||
module = new (module as unknown as new () => T)();
|
||||
} catch {}
|
||||
return Ok({ module, absPath });
|
||||
checkIsProcessed(module)
|
||||
return Ok(module);
|
||||
}
|
||||
|
||||
function checkIsProcessed<T extends Module>(m: T): asserts m is Processed<T> {
|
||||
assert.ok(m.name !== undefined, `name is not defined for ${util.format(m)}`)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,15 +63,15 @@ export async function defaultModuleLoader<T>(
|
||||
* @returns {Observable<{ mod: Module; absPath: string; }[]>} data from command files
|
||||
* @param commandDir
|
||||
*/
|
||||
export function buildModuleStream<T>(
|
||||
export function buildModuleStream<T extends Module >(
|
||||
commandDir: string,
|
||||
): Observable<Result<ImportPayload<T>, SernError>> {
|
||||
): Observable<Result<Processed<T>, SernError>> {
|
||||
const commands = getCommands(commandDir);
|
||||
return from(commands).pipe(mergeMap(defaultModuleLoader<T>));
|
||||
}
|
||||
|
||||
export function getCommands(dir: string): string[] {
|
||||
return readPath(join(process.cwd(), dir));
|
||||
export function getCommands(dir: string) {
|
||||
return readPath(resolve(dir));
|
||||
}
|
||||
|
||||
export function filename(path: string) {
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import type { CommandModule } from '../../types/module';
|
||||
import type { Processed } from '../../types/handler';
|
||||
import { ApplicationCommandType, ComponentType } from './enums';
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
@@ -9,20 +5,7 @@ import { ApplicationCommandType, ComponentType } from './enums';
|
||||
* This dependency is usually injected into ModuleManager
|
||||
*/
|
||||
export class ModuleStore {
|
||||
readonly BothCommands = new Map<string, Processed<CommandModule>>();
|
||||
readonly ApplicationCommands = {
|
||||
[ApplicationCommandType.User]: new Map<string, Processed<CommandModule>>(),
|
||||
[ApplicationCommandType.Message]: new Map<string, Processed<CommandModule>>(),
|
||||
[ApplicationCommandType.ChatInput]: new Map<string, Processed<CommandModule>>(),
|
||||
};
|
||||
readonly ModalSubmit = new Map<string, Processed<CommandModule>>();
|
||||
readonly TextCommands = new Map<string, Processed<CommandModule>>();
|
||||
readonly InteractionHandlers = {
|
||||
[ComponentType.Button]: new Map<string, Processed<CommandModule>>(),
|
||||
[ComponentType.StringSelect]: new Map<string, Processed<CommandModule>>(),
|
||||
[ComponentType.ChannelSelect]: new Map<string, Processed<CommandModule>>(),
|
||||
[ComponentType.MentionableSelect]: new Map<string, Processed<CommandModule>>(),
|
||||
[ComponentType.RoleSelect]: new Map<string, Processed<CommandModule>>(),
|
||||
[ComponentType.UserSelect]: new Map<string, Processed<CommandModule>>(),
|
||||
};
|
||||
readonly Commands = new Map<string, string>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user