diff --git a/plugin/core/config.ts b/plugin/core/config.ts index 421ef5b..c8eada7 100644 --- a/plugin/core/config.ts +++ b/plugin/core/config.ts @@ -32,25 +32,25 @@ export function validateYonexusClientConfig(raw: unknown): YonexusClientConfig { const source = (raw && typeof raw === "object" ? raw : {}) as Record; const issues: string[] = []; - const mainHost = source.mainHost; - if (!isNonEmptyString(mainHost)) { + const rawMainHost = source.mainHost; + if (!isNonEmptyString(rawMainHost)) { issues.push("mainHost is required"); - } else if (!isValidWsUrl(mainHost.trim())) { + } else if (!isValidWsUrl(rawMainHost.trim())) { issues.push("mainHost must be a valid ws:// or wss:// URL"); } - const identifier = source.identifier; - if (!isNonEmptyString(identifier)) { + const rawIdentifier = source.identifier; + if (!isNonEmptyString(rawIdentifier)) { issues.push("identifier is required"); } - const notifyBotToken = source.notifyBotToken; - if (!isNonEmptyString(notifyBotToken)) { + const rawNotifyBotToken = source.notifyBotToken; + if (!isNonEmptyString(rawNotifyBotToken)) { issues.push("notifyBotToken is required"); } - const adminUserId = source.adminUserId; - if (!isNonEmptyString(adminUserId)) { + const rawAdminUserId = source.adminUserId; + if (!isNonEmptyString(rawAdminUserId)) { issues.push("adminUserId is required"); } @@ -58,10 +58,15 @@ export function validateYonexusClientConfig(raw: unknown): YonexusClientConfig { throw new YonexusClientConfigError(issues); } + const mainHost = (rawMainHost as string).trim(); + const identifier = (rawIdentifier as string).trim(); + const notifyBotToken = (rawNotifyBotToken as string).trim(); + const adminUserId = (rawAdminUserId as string).trim(); + return { - mainHost: mainHost.trim(), - identifier: identifier.trim(), - notifyBotToken: notifyBotToken.trim(), - adminUserId: adminUserId.trim() + mainHost, + identifier, + notifyBotToken, + adminUserId }; } diff --git a/plugin/core/state.ts b/plugin/core/state.ts index f6a9b08..fc45866 100644 --- a/plugin/core/state.ts +++ b/plugin/core/state.ts @@ -181,7 +181,8 @@ function assertClientStateShape( ); } - if (!Number.isInteger(candidate.updatedAt) || candidate.updatedAt < 0) { + const updatedAt = candidate.updatedAt; + if (typeof updatedAt !== "number" || !Number.isInteger(updatedAt) || updatedAt < 0) { throw new YonexusClientStateCorruptionError( `Client state file has invalid updatedAt value: ${filePath}` ); diff --git a/plugin/types/ws.d.ts b/plugin/types/ws.d.ts new file mode 100644 index 0000000..d8b7f2f --- /dev/null +++ b/plugin/types/ws.d.ts @@ -0,0 +1,24 @@ +declare module "ws" { + export type RawData = Buffer | ArrayBuffer | Buffer[] | string; + + export class WebSocket { + static readonly OPEN: number; + constructor(url: string); + readonly readyState: number; + send(data: string): void; + close(code?: number, reason?: string): void; + terminate(): void; + on(event: "open", listener: () => void): this; + on(event: "message", listener: (data: RawData) => void): this; + on(event: "close", listener: (code: number, reason: Buffer) => void): this; + on(event: "error", listener: (error: Error) => void): this; + once(event: "open", listener: () => void): this; + once(event: "error", listener: (error: Error) => void): this; + off(event: "error", listener: (error: Error) => void): this; + removeAllListeners?(event?: string): this; + } + + export class WebSocketServer { + constructor(options: { host?: string; port: number }); + } +} diff --git a/tsconfig.json b/tsconfig.json index cf17390..658f108 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "dist", - "rootDir": ".", + "rootDir": "..", "strict": true, "skipLibCheck": true, "esModuleInterop": true, @@ -15,7 +15,9 @@ }, "include": [ "plugin/**/*.ts", - "servers/**/*.ts" + "plugin/**/*.d.ts", + "servers/**/*.ts", + "../Yonexus.Protocol/src/**/*.ts" ], "exclude": [ "dist",