Dependencies
Manage objects which contain lots of state. If you were a previous user of Sapphire, dependency injection is the moral equivalent of container
.
Dependency injection promotes maintainability and helps organize imports.
For example, a minimal setup for any project might look like this:
Directorysrc/
- index.js (your main file and client)
- dependencies.d.ts (for intellisense)
1const client = new Client({2 ...options,3});4
5await makeDependencies((root) => {6 root.add("@sern/client", client),7});
Everything else is handled. However, you may want customize things.
Adding Dependencies to Root
When makeDependencies is called, sern implicility adds dependencies to the container. A few of these are shown:
@sern/logger
: Loggers implementLogging
@sern/modules
: A map of all command modules. ID -> Module@sern/errors
: Handling errors and lifetime →ErrorHandling
@sern/emitter
: Emit events that occur throughout the lifecycle of a project →Emitter
Lifecycle Hooks
Dependencies can call a function throughout you bot’s lifetime.
Init
Your object needs to initiate things. Developers are allowed to use
async
andawait
.
-
Do you need to perform intializing behavior for a dependency?
src/database.js 1import pg from 'pg'2const { Client } = pg3class Database {4__database = new Client()5async init() {6await this.__database.connect();7}8} -
Modify your
Dependencies
interface:src/dependencies.d.ts 1import { Database } from './services/database.js'2interface Dependencies extends CoreDependencies {3database: Database;4} -
Make sure its been added:
src/index.ts 1await makeDependencies(({ add }) => {2add('database', new Database())3}) -
Now, when your bot starts, the
init
method will be called. 🎉
Dispose
Your object needs to destroy things before shutdown, if a crash occurs
-
Do you need to perform intializing behavior for a dependency?
src/database.js 1import pg from 'pg'2const { Client } = pg3class Database {4__database = new Client()5async init() {6await this.__database.connect();7}8async dispose() {9console.log("Disposing database")10}11} -
Make sure its been added:
src/index.ts 1await makeDependencies(({ add }) => {2add('database', new Database())3}) -
Now, when your bot starts, the
dispose
method will be called. 🎉
Usage in Commands
This is for command modules, plugins only. event modules would have to use the
Service
api
Your dependencies are located in SDT.
1export default commandModule({2 type: CommandType.Slash,3 execute: (ctx, sdt) =>{4 sdt.deps.database // Database5 }6})
Service
The Service api is used for places where sern cannot inject into parameters properly. View
When to use Dependency injection
Leveraging dependency injection in your projects is recommended because DI creates a loose coupling between the parts of your application. As a result, the codebase is more modular and easier to test and refactor