feat: upgrade buttplug package to protocol v4 and WASM v10
All checks were successful
Build and Push Docker Image to Gitea / build-and-push (push) Successful in 7m30s

Upgrade the buttplug TypeScript client from class-based v3 protocol to
interface-based v4 protocol, and the Rust/WASM server from the monolithic
buttplug 9.0.9 crate to the split buttplug_core/buttplug_server/
buttplug_server_device_config 10.0.0 crates.

TypeScript changes:
- Messages are now plain interfaces with msgId()/setMsgId() helpers
- ActuatorType → OutputType, SensorType → InputType
- ScalarCmd/RotateCmd/LinearCmd → OutputCmd, SensorReadCmd → InputCmd
- Client.ts → ButtplugClient.ts, new DeviceCommand/DeviceFeature files
- Devices getter returns Map instead of array
- Removed class-transformer/reflect-metadata dependencies

Rust/WASM changes:
- Split imports across buttplug_core, buttplug_server, buttplug_server_device_config
- Removed ButtplugServerDowngradeWrapper (use ButtplugServer directly)
- Replaced ButtplugFuture/ButtplugFutureStateShared with tokio::sync::oneshot
- Updated Hardware::new for new 6-arg signature
- Uses git fork (valknarthing/buttplug) to fix missing wasm deps in buttplug_core

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-06 14:46:47 +01:00
parent fed2dd65e5
commit 6ea4ed1933
31 changed files with 1763 additions and 2441 deletions

View File

@@ -6,96 +6,102 @@
* @copyright Copyright (c) Nonpolynomial Labs LLC. All rights reserved.
*/
import * as Messages from "./Messages";
import { ButtplugLogger } from "./Logging";
import * as Messages from './Messages';
import { ButtplugLogger } from './Logging';
export class ButtplugError extends Error {
public get ErrorClass(): Messages.ErrorClass {
return this.errorClass;
}
public get ErrorClass(): Messages.ErrorClass {
return this.errorClass;
}
public get InnerError(): Error | undefined {
return this.innerError;
}
public get InnerError(): Error | undefined {
return this.innerError;
}
public get Id(): number | undefined {
return this.messageId;
}
public get Id(): number | undefined {
return this.messageId;
}
public get ErrorMessage(): Messages.ButtplugMessage {
return new Messages.Error(this.message, this.ErrorClass, this.Id);
}
public get ErrorMessage(): Messages.ButtplugMessage {
return {
Error: {
Id: this.Id,
ErrorCode: this.ErrorClass,
ErrorMessage: this.message
}
}
}
public static LogAndError<T extends ButtplugError>(
constructor: new (str: string, num: number) => T,
logger: ButtplugLogger,
message: string,
id: number = Messages.SYSTEM_MESSAGE_ID,
): T {
logger.Error(message);
return new constructor(message, id);
}
public static LogAndError<T extends ButtplugError>(
constructor: new (str: string, num: number) => T,
logger: ButtplugLogger,
message: string,
id: number = Messages.SYSTEM_MESSAGE_ID
): T {
logger.Error(message);
return new constructor(message, id);
}
public static FromError(error: Messages.Error) {
switch (error.ErrorCode) {
case Messages.ErrorClass.ERROR_DEVICE:
return new ButtplugDeviceError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_INIT:
return new ButtplugInitError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_UNKNOWN:
return new ButtplugUnknownError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_PING:
return new ButtplugPingError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_MSG:
return new ButtplugMessageError(error.ErrorMessage, error.Id);
default:
throw new Error(`Message type ${error.ErrorCode} not handled`);
}
}
public static FromError(error: Messages.Error) {
switch (error.ErrorCode) {
case Messages.ErrorClass.ERROR_DEVICE:
return new ButtplugDeviceError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_INIT:
return new ButtplugInitError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_UNKNOWN:
return new ButtplugUnknownError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_PING:
return new ButtplugPingError(error.ErrorMessage, error.Id);
case Messages.ErrorClass.ERROR_MSG:
return new ButtplugMessageError(error.ErrorMessage, error.Id);
default:
throw new Error(`Message type ${error.ErrorCode} not handled`);
}
}
public errorClass: Messages.ErrorClass = Messages.ErrorClass.ERROR_UNKNOWN;
public innerError: Error | undefined;
public messageId: number | undefined;
public errorClass: Messages.ErrorClass = Messages.ErrorClass.ERROR_UNKNOWN;
public innerError: Error | undefined;
public messageId: number | undefined;
protected constructor(
message: string,
errorClass: Messages.ErrorClass,
id: number = Messages.SYSTEM_MESSAGE_ID,
inner?: Error,
) {
super(message);
this.errorClass = errorClass;
this.innerError = inner;
this.messageId = id;
}
protected constructor(
message: string,
errorClass: Messages.ErrorClass,
id: number = Messages.SYSTEM_MESSAGE_ID,
inner?: Error
) {
super(message);
this.errorClass = errorClass;
this.innerError = inner;
this.messageId = id;
}
}
export class ButtplugInitError extends ButtplugError {
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_INIT, id);
}
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_INIT, id);
}
}
export class ButtplugDeviceError extends ButtplugError {
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_DEVICE, id);
}
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_DEVICE, id);
}
}
export class ButtplugMessageError extends ButtplugError {
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_MSG, id);
}
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_MSG, id);
}
}
export class ButtplugPingError extends ButtplugError {
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_PING, id);
}
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_PING, id);
}
}
export class ButtplugUnknownError extends ButtplugError {
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_UNKNOWN, id);
}
public constructor(message: string, id: number = Messages.SYSTEM_MESSAGE_ID) {
super(message, Messages.ErrorClass.ERROR_UNKNOWN, id);
}
}