feat(server): add pairing service and notify stub

This commit is contained in:
nav
2026-04-08 21:34:46 +00:00
parent f7c7531385
commit cd09fe6043
5 changed files with 375 additions and 0 deletions

View File

@@ -19,6 +19,11 @@ import {
} from "./persistence.js";
import type { YonexusServerStore } from "./store.js";
import { type ClientConnection, type ServerTransport } from "./transport.js";
import { createPairingService, type PairingService } from "../services/pairing.js";
import {
createDiscordNotificationService,
type DiscordNotificationService
} from "../notifications/discord.js";
export interface YonexusServerRuntimeOptions {
config: YonexusServerConfig;
@@ -36,7 +41,10 @@ export class YonexusServerRuntime {
private readonly options: YonexusServerRuntimeOptions;
private readonly now: () => number;
private readonly registry: ServerRegistry;
private readonly pairingService: PairingService;
private readonly notificationService: DiscordNotificationService;
private started = false;
constructor(options: YonexusServerRuntimeOptions) {
this.options = options;
this.now = options.now ?? (() => Math.floor(Date.now() / 1000));
@@ -44,6 +52,11 @@ export class YonexusServerRuntime {
clients: new Map(),
sessions: new Map()
};
this.pairingService = createPairingService({ now: this.now });
this.notificationService = createDiscordNotificationService({
botToken: options.config.notifyBotToken,
adminUserId: options.config.adminUserId
});
}
get state(): ServerLifecycleState {
@@ -180,6 +193,10 @@ export class YonexusServerRuntime {
)
);
if (nextAction === "pair_required") {
await this.beginPairing(record);
}
await this.persist();
}
@@ -206,6 +223,20 @@ export class YonexusServerRuntime {
return created;
}
private async beginPairing(record: ClientRecord): Promise<void> {
if (hasPendingPairing(record) && !isPairingExpired(record, this.now())) {
return;
}
const request = this.pairingService.createPairingRequest(record);
const notified = await this.notificationService.sendPairingNotification(request);
if (notified) {
this.pairingService.markNotificationSent(record);
} else {
this.pairingService.markNotificationFailed(record);
}
}
private async persist(): Promise<void> {
await this.options.store.save(this.registry.clients.values());
}