Files
Yonexus.Client/plugin/core/config.ts
hzhang 12a0b8f5e6 feat: make notifyBotToken/adminUserId optional
The client never sends pairing notifications (the server does); these
Discord fields were required but unused. Make them optional + drop from
the config schema's required list. Back-compat: still accepted if set.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:59:08 +01:00

73 lines
2.0 KiB
TypeScript

export interface YonexusClientConfig {
mainHost: string;
identifier: string;
/**
* Optional. The client never sends pairing notifications (the server
* does); accepted for back-compat but no longer required.
*/
notifyBotToken?: string;
adminUserId?: string;
}
export class YonexusClientConfigError extends Error {
readonly issues: string[];
constructor(issues: string[]) {
super(`Invalid Yonexus.Client config: ${issues.join("; ")}`);
this.name = "YonexusClientConfigError";
this.issues = issues;
}
}
function isNonEmptyString(value: unknown): value is string {
return typeof value === "string" && value.trim().length > 0;
}
function isValidWsUrl(value: string): boolean {
try {
const url = new URL(value);
return url.protocol === "ws:" || url.protocol === "wss:";
} catch {
return false;
}
}
export function validateYonexusClientConfig(raw: unknown): YonexusClientConfig {
const source = (raw && typeof raw === "object" ? raw : {}) as Record<string, unknown>;
const issues: string[] = [];
const rawMainHost = source.mainHost;
if (!isNonEmptyString(rawMainHost)) {
issues.push("mainHost is required");
} else if (!isValidWsUrl(rawMainHost.trim())) {
issues.push("mainHost must be a valid ws:// or wss:// URL");
}
const rawIdentifier = source.identifier;
if (!isNonEmptyString(rawIdentifier)) {
issues.push("identifier is required");
}
// Optional (back-compat): the client does not send notifications.
const rawNotifyBotToken = source.notifyBotToken;
const rawAdminUserId = source.adminUserId;
if (issues.length > 0) {
throw new YonexusClientConfigError(issues);
}
const mainHost = (rawMainHost as string).trim();
const identifier = (rawIdentifier as string).trim();
return {
mainHost,
identifier,
notifyBotToken: isNonEmptyString(rawNotifyBotToken)
? rawNotifyBotToken.trim()
: undefined,
adminUserId: isNonEmptyString(rawAdminUserId)
? rawAdminUserId.trim()
: undefined
};
}