@nexcord/config
v0.0.1
Published
<div align="center">
Readme
@nexcord/config
A tiny, dependency-injection-aware shared config store for Nexcord bots.
Part of the Nexcord ecosystem.
@nexcord/config is deliberately small: a single shared object, and two functions to populate it. It exists to answer one question — how do I compute a config value using my own services, exactly once, without wiring that up by hand?
registerConfig(
'messages.welcome',
(prefix: PrefixService) => `Welcome! Type ${prefix.get()}help to get started.`,
PrefixService
);PrefixService here is resolved from Nexcord's dependency injection container automatically — the same singleton instance your commands and listeners already use — and the result is written into a shared store that ConfigService (part of @nexcord/core) reads from throughout your bot.
Table of Contents
- Requirements
- Installation
- Quick Start
- API Reference
- Service & Value Resolution
- Waiting for the Client to Be Ready
- Reading Values Back
- Notes
- License
Requirements
@nexcord/core—registerConfigresolves services throughNexCord.get(), andregisterConfigWaitlistens onNexCord.client.- TypeScript
^5.
Installation
bun add @nexcord/config @nexcord/corenpm install @nexcord/config @nexcord/core
pnpm add @nexcord/config @nexcord/core
yarn add @nexcord/config @nexcord/coreQuick Start
Config files live in src/configs/ in a standard Nexcord project, and are autoloaded on startup — you only need to call registerConfig, nothing needs to be exported or returned.
// src/configs/general.config.ts
import { registerConfig } from '@nexcord/config';
registerConfig('bot.startedAt', () => Date.now());A config value can just as easily depend on one of your own services:
// src/configs/welcome.config.ts
import { registerConfig } from '@nexcord/config';
import { PrefixService } from '../common/services/Prefix.service';
registerConfig(
'messages.welcome',
(prefix: PrefixService) => `Welcome! Type ${prefix.get()}help to get started.`,
PrefixService
);API Reference
NexConfigObject
const NexConfigObject: Record<string, any>;The shared, in-memory store every config value is written to. You generally won't touch this directly — registerConfig writes to it, and ConfigService (from @nexcord/core) reads from it — but it's exported for advanced cases.
registerConfig(key, configFactory, ...services)
function registerConfig(
key: string,
configFactory: (...args: any[]) => any,
...services: any[]
): void;Resolves each entry in services (see Service & Value Resolution), calls configFactory with the resolved values in order, and stores the return value at NexConfigObject[key]. Runs immediately, synchronously, when called.
registerConfigWait(key, configFactory, ...services)
function registerConfigWait(
key: string,
configFactory: (...args: any[]) => any,
...services: any[]
): void;Same signature and behavior as registerConfig, except it defers to the client's clientReady event first — see Waiting for the Client to Be Ready.
Service & Value Resolution
Every extra argument passed to registerConfig / registerConfigWait after the factory is resolved the same way:
NexCord.get(s)?.instance ?? s- If
sis a class registered with Nexcord (@Service(),@Listener(), etc.), you get its live singleton instance. - If it isn't — a string, a number, an already-built object,
process.env.SOMETHING— it's passed through to your factory unchanged.
That means you can freely mix services and plain values in the same call:
registerConfig(
'app.environment',
(env: string) => env.toUpperCase(),
process.env.NODE_ENV ?? 'development'
);Waiting for the Client to Be Ready
Some config values need live Discord data — a guild's name, its channel list, its member count — which isn't available until the client has actually connected. registerConfigWait defers registration until the clientReady event fires once:
// src/configs/server.config.ts
import { registerConfigWait } from '@nexcord/config';
import { NexCord } from '@nexcord/core';
registerConfigWait(
'server.name',
() => NexCord.client.guilds.cache.first()?.name ?? 'Unknown Server'
);Use registerConfig for anything computable immediately at startup, and registerConfigWait for anything that needs the bot to actually be online first.
Reading Values Back
@nexcord/config only writes — reading is ConfigService's job, from @nexcord/core. Inject it like any other service:
@Service()
export class WelcomeService {
constructor(private readonly config: ConfigService) {}
message(): string {
return this.config.get<string>('messages.welcome') ?? 'Welcome!';
}
}@nexcord/config itself performs a single flat assignment — NexConfigObject[key] = result — it doesn't parse key for dots. The 'messages.welcome'-style dotted keys used throughout this document are a convention, not a requirement of this package: they line up with the dot-notation get() / set() API that ConfigService provides on top of this same store. You're free to use flat keys ('welcomeMessage') if you don't need nested access.
Notes
@nexcord/configis beta software, tracking@nexcord/core's beta status.- This package has no logic of its own beyond the store and the two functions above — all the DI resolution and readiness-gating happens through
@nexcord/core, which makes it a required companion, not an optional one.
License
Released under the MIT License.
Part of the Nexcord ecosystem — see @nexcord/core and @nexcord/tsx · Built by SignorMassimo
