メインコンテンツまでスキップ
バージョン: v2 Next 🚧

サービス

Service はアプリケーション横断のロジック・状態(設定、データベース、 外部 API クライアントなど)を担うコンポーネントです。services/ に 置くだけで自動ロードされ、どのコンポーネントからも import なしで this.services.<名前> として参照できます — モジュール同士の結びつきが 1か所に収束します。

src/services/ConfigService.ts
import { createEnv, Service } from "@cc-discord-framework/core";

const env = createEnv(); // 環境変数の定番の読み方(詳細は「環境変数」)

@Service.define()
export class ConfigService extends Service {
readonly ownerIds = env.list("OWNER_IDS");
readonly defaultPrefix = env.text("DEFAULT_PREFIX") ?? "!";
}

declare module "@cc-discord-framework/core" {
interface Services {
config: ConfigService;
}
}
// どこかのコマンド — ConfigService の import は不要
@Command.define({ description: "..." })
export class ExampleCommand extends Command {
override async chatInputRun(interaction: ChatInputCommandInteraction) {
const { ownerIds } = this.services.config; // 完全に型付き
}
}

名前

サービス名はプロパティとして自然に参照できるよう lowerCamelCase で 導出されます: ConfigServiceconfigGuildSettingsServiceguildSettings@Service.define({ name }) で明示もできます。

型を効かせる鍵は Services インターフェースの宣言マージです。サービスを 定義したファイルに必ず併記してください(上の例)。

ライフサイクル

サービスにもコンポーネントのライフサイクルがそのまま適用されます。 接続を開くのは onLoad、閉じるのは onUnload です:

src/services/SettingsService.ts
// bun:sqlite の例
import { Database } from "bun:sqlite";
import { Service } from "@cc-discord-framework/core";

@Service.define()
export class SettingsService extends Service {
#db!: Database;

override onLoad() {
this.#db = new Database(Bun.env.DATABASE_PATH ?? "bot.sqlite", { create: true });
}

override onUnload() {
this.#db.close(); // client.destroy() で呼ばれる
}
}
注記

フレームワークのコアは Prisma / SQLite / Redis などの具体を一切 知りません。データベースはただのサービスです — services/ に置いて onLoad で接続し、onUnload で閉じてください。

ロード順

サービスストアは最初にロードされるため、コマンドやリスナーの onLoad からもサービスを利用できます。fetchPrefix などのクライアント オプション内でも、実行は必ずロード後なので安全に参照できます:

fetchPrefix: (message, container) =>
container.services.settings.getPrefix(message.guildId) ?? "!",

サービス同士の参照

サービスから別のサービスも this.services.<名前> で参照できます。 ただし onLoad 内で他サービスに依存する場合はロード順(ファイル名の 辞書順)に注意し、依存が複雑になるなら参照を実行時(メソッド内)まで 遅延させてください。

コンテナとの使い分け

this.services は「services/ に置いた自分のクラス」の置き場、 コンテナ直下 (container.client など)はフレームワーク組み込みのサービスです。 プラグインが提供する値はどちらの形もあり得ます(プラグインの ドキュメントに従ってください)。