Skip to content
sern

Release 2.0.0

2.0 Release

Join our discord!
Wow! We’re finally increasing our semantic versioning by +1.7.9.
What does this mean?

Plugin Support for Event Modules

You can now use plugins for event modules. Previous version would throw an error if the plugins field was populated.

1
export function commandPlTest(): SernEmitterPlugin {
2
return {
3
type: PluginType.Command,
4
execute: ({ mod }, controller) => {
5
if (mod.name === "module.register") {
6
console.log("Event Module created correctly");
7
return controller.next();
8
}
9
console.log("event name is wrong");
10
return controller.stop();
11
},
12
};
13
}

Applying this plugin to some eventModule:

1
export default eventModule({
2
name: "error",
3
type: EventType.Sern,
4
plugins: [commandPlTest()],
5
execute(m) {
6
console.log(m);
7
},
8
});

Dependency Injection and Decoupling

The powerful npm package iti decouples sern even more. Decoupling data structures with the Inversion of Control pattern separates data from logic, which will help speed production and make sern even more customizable than before.

How do I start?

src/index.ts
1
//With typescript, you can customize / augment your typings.
2
interface MyDependencies extends Dependencies {
3
"@sern/client": Singleton<Client>;
4
"@sern/logger": Singleton<DefaultLogging>;
5
}
6
7
export const useContainer = Sern.makeDependencies<MyDependencies>({
8
// exclude: new Set(['@sern/logger']), don't autofill optional dependencies
9
build: (root) =>
10
root
11
.add({ "@sern/client": single(client) })
12
.add({ "@sern/logger": single(new DefaultLogging()) }),
13
});
14
15
Sern.init({
16
defaultPrefix: "!", // removing defaultPrefix will shut down text commands
17
commands: "src/commands",
18
// events: 'src/events' (optional),
19
containerConfig: {
20
get: useContainer, //pass in your dependency getter here
21
},
22
});

Using the Sern#makeDependencies function, inject your dependencies. We’ll use specific dependencies that are created with the @sern/keyword key. Using typescript to display all keywords and what they represent:

1
export interface Dependencies {
2
"@sern/client": Singleton<EventEmitter>; //Discord Client
3
"@sern/logger"?: Singleton<Logging>; //Logger
4
"@sern/emitter": Singleton<SernEmitter>; //SernEmitter
5
"@sern/store": Singleton<ModuleStore>; //Stores all Command Modules
6
"@sern/modules": Singleton<ModuleManager>; //Manages Modules
7
"@sern/errors": Singleton<ErrorHandling>; //A Lifetime / Crash Handler
8
}

At the moment, one optional dependency, @sern/logger, exists. If not added explicitly, we’ll autofill with a DefaultLogger.

Use your generated dependency getter useContainer (use whatever name you want), access them from anywhere.

The build field follows createContainer function call.

New CommandTypes

2.0 includes all the new role select menus. CommandType.MenuSelect has been renamed into CommandType.StringSelect. The remaining SelectMenus are CommandType.RoleSelect, CommandType.ChannelSelect, CommandType.UserSelect, CommandType.MentionableSelect

commands/roleselect.ts
1
export default commandModule({
2
type: CommandType.RoleSelect,
3
execute(ctx) {
4
ctx.reply("role select");
5
},
6
});

In addition, commandModules with ContextMenus have been renamed.

CommandType.MenuUser, CommandType.MenuMsg
CommandType.CtxUser, CommandType.CtxMsg

Typings Simplification

Pre 2.0:


Post 2.0:

CommandPlugin<T> and EventPlugin<T> typings have also been static’ified, transformed from types to interfaces

Breaking Changes


All deprecation warnings from previous versions have taken effect, and are removed in 2.0.
type Module = EventModule | CommandModule
type AnyModule = EventModule | CommandModule
export type SpreadParams<T extends (...args: never) => unknown> = (
args: Parameters<T>[number],
) => unknown;

Override type has been removed due to redundancy

discord.js : 14.5
discord.js : 14.7
typescript: 4.7
typescript: 4.9
interface Wrapper {
readonly defaultPrefix?: string;
readonly commands: string;
readonly events?: string;
readonly containerConfig : {
get: (...keys: (keyof Dependencies)[]) => unknown[];
}
}
interface Wrapper {
readonly client: Client;
readonly sernEmitter?: SernEmitter;
readonly defaultPrefix?: string;
readonly commands: string;
readonly events?:
| string
| { mod: EventModule; absPath: string }[]
| (() => { mod: EventModule; absPath: string }[]);
}
DefaultLogger
DefaultModuleManager
SernEmitter
DefaultErrorHandling
type Singleton<T> = () => T
type Transient<T> = () => () => T;
type LogPayload<T = unknown> = { message: T }
export const single = <T>() => T
export const many = <T>() => () => T

Including the previous section, some names to symbols and data structures were altered to be better represented. view changelog

Context refactoring

The context data structure has been internally altered to represent its dynamics better.