Browse Source

Zod WIP

pull/635/head
philon- 1 year ago
parent
commit
9ab1f160ce
  1. 2
      package.json
  2. 73
      src/validation/channel.ts
  3. 24
      src/validation/config/bluetooth.ts
  4. 64
      src/validation/config/device.ts
  5. 69
      src/validation/config/display.ts
  6. 92
      src/validation/config/lora.ts
  7. 14
      src/validation/config/network.ts
  8. 62
      src/validation/config/position.ts
  9. 49
      src/validation/config/power.ts
  10. 50
      src/validation/config/security.ts
  11. 37
      src/validation/moduleConfig/ambientLighting.ts
  12. 38
      src/validation/moduleConfig/audio.ts
  13. 65
      src/validation/moduleConfig/cannedMessage.ts
  14. 49
      src/validation/moduleConfig/detectionSensor.ts
  15. 77
      src/validation/moduleConfig/externalNotification.ts
  16. 81
      src/validation/moduleConfig/mqtt.ts
  17. 19
      src/validation/moduleConfig/neighborInfo.ts
  18. 25
      src/validation/moduleConfig/paxcounter.ts
  19. 21
      src/validation/moduleConfig/rangeTest.ts
  20. 49
      src/validation/moduleConfig/serial.ts
  21. 37
      src/validation/moduleConfig/storeForward.ts
  22. 55
      src/validation/moduleConfig/telemetry.ts
  23. 30
      src/validation/rasterSource.ts
  24. 4
      src/validation/validate.ts

2
package.json

@ -77,7 +77,7 @@
"react-qrcode-logo": "^3.0.0", "react-qrcode-logo": "^3.0.0",
"rfc4648": "^1.5.4", "rfc4648": "^1.5.4",
"vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-node-polyfills": "^0.23.0",
"zod": "^3.24.3", "zod": "^3.25.0",
"zustand": "5.0.4" "zustand": "5.0.4"
}, },
"devDependencies": { "devDependencies": {

73
src/validation/channel.ts

@ -1,51 +1,26 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import {
IsBoolean,
IsEnum,
IsInt,
IsNumber,
IsString,
Length,
} from "class-validator";
export class ChannelValidation const RoleEnum = z.enum(
implements Omit<Protobuf.Channel.Channel, keyof Message | "settings"> { Protobuf.Channel.Channel_Role,
@IsNumber() );
index: number;
export const Channel_SettingsValidationSchema = z.object({
settings: Channel_SettingsValidation; channelNum: z.number(),
psk: z.string(),
@IsEnum(Protobuf.Channel.Channel_Role) name: z.string().min(0).max(11),
role: Protobuf.Channel.Channel_Role; id: z.int(),
} uplinkEnabled: z.boolean(),
downlinkEnabled: z.boolean(),
export class Channel_SettingsValidation positionEnabled: z.boolean(),
implements Omit<Protobuf.Channel.ChannelSettings, keyof Message | "psk"> { preciseLocation: z.boolean(),
@IsNumber() positionPrecision: z.boolean(),
channelNum: number; });
@IsString() export const ChannelValidationSchema = z.object({
psk: string; index: z.number(),
settings: Channel_SettingsValidationSchema,
@Length(0, 11) role: RoleEnum,
name: string; });
@IsInt() export type ChannelValidation = z.infer<typeof ChannelValidationSchema>;
id: number;
@IsBoolean()
uplinkEnabled: boolean;
@IsBoolean()
downlinkEnabled: boolean;
@IsBoolean()
positionEnabled: boolean;
@IsBoolean()
preciseLocation: boolean;
@IsInt()
positionPrecision: number;
}

24
src/validation/config/bluetooth.ts

@ -1,18 +1,14 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt } from "class-validator";
export class BluetoothValidation implements const PairingModeEnum = z.enum(
Omit< Protobuf.Config.Config_BluetoothConfig_PairingMode,
Protobuf.Config.Config_BluetoothConfig, );
keyof Message | "deviceLoggingEnabled"
> {
@IsBoolean()
enabled: boolean;
@IsEnum(Protobuf.Config.Config_BluetoothConfig_PairingMode) export const BluetoothValidationSchema = z.object({
mode: Protobuf.Config.Config_BluetoothConfig_PairingMode; enabled: z.boolean(),
mode: PairingModeEnum,
fixedPin: z.int(),
});
@IsInt() export type BluetoothValidation = z.infer<typeof BluetoothValidationSchema>;
fixedPin: number;
}

64
src/validation/config/device.ts

@ -1,42 +1,26 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt, IsString } from "class-validator";
export class DeviceValidation const RoleEnum = z.enum(
implements Omit<Protobuf.Config.Config_DeviceConfig, keyof Message> { Protobuf.Config.Config_DeviceConfig_Role,
@IsEnum(Protobuf.Config.Config_DeviceConfig_Role) );
role: Protobuf.Config.Config_DeviceConfig_Role; const RebroadcastModeEnum = z.enum(
Protobuf.Config.Config_DeviceConfig_RebroadcastMode,
@IsBoolean() );
serialEnabled: boolean;
export const DeviceValidationSchema = z.object({
@IsBoolean() role: RoleEnum,
debugLogEnabled: boolean; serialEnabled: z.boolean(),
debugLogEnabled: z.boolean(),
@IsInt() buttonGpio: z.int(),
buttonGpio: number; buzzerGpio: z.int(),
rebroadcastMode: RebroadcastModeEnum,
@IsInt() nodeInfoBroadcastSecs: z.int(),
buzzerGpio: number; doubleTapAsButtonPress: z.boolean(),
isManaged: z.boolean(),
@IsEnum(Protobuf.Config.Config_DeviceConfig_RebroadcastMode) disableTripleClick: z.boolean(),
rebroadcastMode: Protobuf.Config.Config_DeviceConfig_RebroadcastMode; ledHeartbeatDisabled: z.boolean(),
tzdef: z.string(),
@IsInt() });
nodeInfoBroadcastSecs: number;
export type DeviceValidation = z.infer<typeof DeviceValidationSchema>;
@IsBoolean()
doubleTapAsButtonPress: boolean;
@IsBoolean()
isManaged: boolean;
@IsBoolean()
disableTripleClick: boolean;
@IsBoolean()
ledHeartbeatDisabled: boolean;
@IsString()
tzdef: string;
}

69
src/validation/config/display.ts

@ -1,39 +1,34 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt } from "class-validator";
export class DisplayValidation const GpsCoordinateEnum = z.enum(
implements Omit<Protobuf.Config.Config_DisplayConfig, keyof Message> { Protobuf.Config.Config_DisplayConfig_GpsCoordinateFormat,
@IsInt() );
screenOnSecs: number; const DisplayUnitsEnum = z.enum(
Protobuf.Config.Config_DisplayConfig_DisplayUnits,
@IsEnum(Protobuf.Config.Config_DisplayConfig_GpsCoordinateFormat) );
gpsFormat: Protobuf.Config.Config_DisplayConfig_GpsCoordinateFormat; const OledTypeEnum = z.enum(
Protobuf.Config.Config_DisplayConfig_OledType,
@IsInt() );
autoScreenCarouselSecs: number; const DisplayModeEnum = z.enum(
Protobuf.Config.Config_DisplayConfig_DisplayMode,
@IsBoolean() );
compassNorthTop: boolean; const CompassOrientationEnum = z.enum(
Protobuf.Config.Config_DisplayConfig_CompassOrientation,
@IsBoolean() );
flipScreen: boolean;
export const DisplayValidationSchema = z.object({
@IsEnum(Protobuf.Config.Config_DisplayConfig_DisplayUnits) screenOnSecs: z.int(),
units: Protobuf.Config.Config_DisplayConfig_DisplayUnits; gpsFormat: GpsCoordinateEnum,
autoScreenCarouselSecs: z.int(),
@IsEnum(Protobuf.Config.Config_DisplayConfig_OledType) compassNorthTop: z.boolean(),
oled: Protobuf.Config.Config_DisplayConfig_OledType; flipScreen: z.boolean(),
units: DisplayUnitsEnum,
@IsEnum(Protobuf.Config.Config_DisplayConfig_DisplayMode) oled: OledTypeEnum,
displaymode: Protobuf.Config.Config_DisplayConfig_DisplayMode; displaymode: DisplayModeEnum,
headingBold: z.boolean(),
@IsBoolean() wakeOnTapOrMotion: z.boolean(),
headingBold: boolean; compassOrientation: CompassOrientationEnum,
});
@IsBoolean()
wakeOnTapOrMotion: boolean; export type DisplayValidation = z.infer<typeof DisplayValidationSchema>;
@IsEnum(Protobuf.Config.Config_DisplayConfig_CompassOrientation)
compassOrientation: Protobuf.Config.Config_DisplayConfig_CompassOrientation;
}

92
src/validation/config/lora.ts

@ -1,65 +1,31 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsArray, IsBoolean, IsEnum, IsInt, Max, Min } from "class-validator";
export class LoRaValidation const ModemPresetEnum = z.enum(
implements Protobuf.Config.Config_LoRaConfig_ModemPreset,
Omit<Protobuf.Config.Config_LoRaConfig, keyof Message | "paFanDisabled"> { );
@IsBoolean() const RegionCodeEnum = z.enum(
usePreset: boolean; Protobuf.Config.Config_LoRaConfig_RegionCode,
);
@IsEnum(Protobuf.Config.Config_LoRaConfig_ModemPreset)
modemPreset: Protobuf.Config.Config_LoRaConfig_ModemPreset; export const LoRaValidationSchema = z.object({
usePreset: z.boolean(),
@IsInt() modemPreset: ModemPresetEnum,
bandwidth: number; bandwidth: z.int(),
spreadFactor: z.int().max(12),
@IsInt() codingRate: z.int().min(0).max(10),
// @Min(7) frequencyOffset: z.int(),
@Max(12) region: RegionCodeEnum,
spreadFactor: number; hopLimit: z.int().min(0).max(7),
txEnabled: z.boolean(),
@IsInt() txPower: z.int().min(0),
@Min(0) channelNum: z.int(),
@Max(10) overrideDutyCycle: z.boolean(),
codingRate: number; sx126xRxBoostedGain: z.boolean(),
overrideFrequency: z.int(),
@IsInt() ignoreIncoming: z.number().array(),
frequencyOffset: number; ignoreMqtt: z.boolean(),
configOkToMqtt: z.boolean(),
@IsEnum(Protobuf.Config.Config_LoRaConfig_RegionCode) });
region: Protobuf.Config.Config_LoRaConfig_RegionCode;
export type LoRaValidation = z.infer<typeof LoRaValidationSchema>;
@IsInt()
@Min(1)
@Max(7)
hopLimit: number;
@IsBoolean()
txEnabled: boolean;
@IsInt()
@Min(0)
txPower: number;
@IsInt()
channelNum: number;
@IsBoolean()
overrideDutyCycle: boolean;
@IsBoolean()
sx126xRxBoostedGain: boolean;
@IsInt()
overrideFrequency: number;
@IsArray()
ignoreIncoming: number[];
@IsBoolean()
ignoreMqtt: boolean;
@IsBoolean()
configOkToMqtt: boolean;
}

14
src/validation/config/network.ts

@ -1,18 +1,18 @@
import { z } from "zod"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
const AddressModeEnum = z.nativeEnum( const AddressModeEnum = z.enum(
Protobuf.Config.Config_NetworkConfig_AddressMode, Protobuf.Config.Config_NetworkConfig_AddressMode,
); );
const ProtocolFlagsEnum = z.nativeEnum( const ProtocolFlagsEnum = z.enum(
Protobuf.Config.Config_NetworkConfig_ProtocolFlags, Protobuf.Config.Config_NetworkConfig_ProtocolFlags,
); );
export const NetworkValidationIpV4ConfigSchema = z.object({ export const NetworkValidationIpV4ConfigSchema = z.object({
ip: z.string().ip(), ip: z.ipv4(),
gateway: z.string().ip(), gateway: z.ipv4(),
subnet: z.string().ip(), subnet: z.ipv4(),
dns: z.string().ip(), dns: z.ipv4(),
}); });
export const NetworkValidationSchema = z.object({ export const NetworkValidationSchema = z.object({

62
src/validation/config/position.ts

@ -1,44 +1,22 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt } from "class-validator";
const DeprecatedPositionValidationFields = ["gpsEnabled", "gpsAttemptTime"]; const GpsModeEnum = z.enum(
Protobuf.Config.Config_PositionConfig_GpsMode,
export class PositionValidation implements );
Omit<
Protobuf.Config.Config_PositionConfig, export const PositionValidationSchema = z.object({
keyof Message | (typeof DeprecatedPositionValidationFields)[number] positionBroadcastSecs: z.int(),
> { positionBroadcastSmartEnabled: z.boolean(),
@IsInt() fixedPosition: z.boolean(),
positionBroadcastSecs: number; gpsUpdateInterval: z.int(),
positionFlags: z.int(),
@IsBoolean() rxGpio: z.int(),
positionBroadcastSmartEnabled: boolean; txGpio: z.int(),
broadcastSmartMinimumDistance: z.int(),
@IsBoolean() broadcastSmartMinimumIntervalSecs: z.int(),
fixedPosition: boolean; gpsEnGpio: z.int(),
gpsMode: GpsModeEnum,
@IsInt() });
gpsUpdateInterval: number;
export type PositionValidation = z.infer<typeof PositionValidationSchema>;
@IsInt()
positionFlags: number;
@IsInt()
rxGpio: number;
@IsInt()
txGpio: number;
@IsInt()
broadcastSmartMinimumDistance: number;
@IsInt()
broadcastSmartMinimumIntervalSecs: number;
@IsInt()
gpsEnGpio: number;
@IsEnum(Protobuf.Config.Config_PositionConfig_GpsMode)
gpsMode: Protobuf.Config.Config_PositionConfig_GpsMode;
}

49
src/validation/config/power.ts

@ -1,35 +1,14 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt, IsNumber, Max, Min } from "class-validator"; export const PowerValidationSchema = z.object({
isPowerSaving: z.boolean(),
export class PowerValidation implements onBatteryShutdownAfterSecs: z.int(),
Omit< adcMultiplierOverride: z.number().min(2).max(4),
Protobuf.Config.Config_PowerConfig, waitBluetoothSecs: z.int(),
keyof Message | "powermonEnables" sdsSecs: z.int(),
> { lsSecs: z.int(),
@IsBoolean() minWakeSecs: z.int(),
isPowerSaving: boolean; deviceBatteryInaAddress: z.int(),
});
@IsInt()
onBatteryShutdownAfterSecs: number; export type PowerValidation = z.infer<typeof PowerValidationSchema>;
@IsNumber()
@Min(2)
@Max(4)
adcMultiplierOverride: number;
@IsInt()
waitBluetoothSecs: number;
@IsInt()
sdsSecs: number;
@IsInt()
lsSecs: number;
@IsInt()
minWakeSecs: number;
@IsInt()
deviceBatteryInaAddress: number;
}

50
src/validation/config/security.ts

@ -1,36 +1,14 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsString } from "class-validator"; export const SecurityValidationSchema = z.object({
adminChannelEnabled: z.boolean(),
export class SecurityValidation implements adminKey: z.string().array().length(3),
Omit< bluetoothLoggingEnabled: z.boolean(),
Protobuf.Config.Config_SecurityConfig, debugLogApiEnabled: z.boolean(),
| keyof Message isManaged: z.boolean(),
| "adminKey" privateKey: z.string(),
| "privateKey" publicKey: z.string(),
| "publicKey" serialEnabled: z.boolean(),
> { });
@IsBoolean()
adminChannelEnabled: boolean; export type SecurityValidation = z.infer<typeof SecurityValidationSchema>;
@IsString()
adminKey: [string, string, string];
@IsBoolean()
bluetoothLoggingEnabled: boolean;
@IsBoolean()
debugLogApiEnabled: boolean;
@IsBoolean()
isManaged: boolean;
@IsString()
privateKey: string;
@IsString()
publicKey: string;
@IsBoolean()
serialEnabled: boolean;
}

37
src/validation/moduleConfig/ambientLighting.ts

@ -1,24 +1,13 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator"; export const AmbientLightingValidationSchema = z.object({
ledState: z.boolean(),
export class AmbientLightingValidation implements current: z.int(),
Omit< red: z.int(),
Protobuf.ModuleConfig.ModuleConfig_AmbientLightingConfig, green: z.int(),
keyof Message blue: z.int(),
> { });
@IsBoolean()
ledState: boolean; export type AmbientLightingValidation = z.infer<
typeof AmbientLightingValidationSchema
@IsInt() >;
current: number;
@IsInt()
red: number;
@IsInt()
green: number;
@IsInt()
blue: number;
}

38
src/validation/moduleConfig/audio.ts

@ -1,28 +1,18 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt } from "class-validator";
export class AudioValidation const Audio_BaudEnum = z.enum(
implements Protobuf.ModuleConfig.ModuleConfig_AudioConfig_Audio_Baud,
Omit<Protobuf.ModuleConfig.ModuleConfig_AudioConfig, keyof Message> { );
@IsBoolean()
codec2Enabled: boolean;
@IsInt() export const AudioValidationSchema = z.object({
pttPin: number; codec2Enabled: z.boolean(),
pttPin: z.int(),
bitrate: Audio_BaudEnum,
i2sWs: z.int(),
i2sSd: z.int(),
i2sDin: z.int(),
i2sSck: z.int(),
});
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_AudioConfig_Audio_Baud) export type AudioValidation = z.infer<typeof AudioValidationSchema>;
bitrate: Protobuf.ModuleConfig.ModuleConfig_AudioConfig_Audio_Baud;
@IsInt()
i2sWs: number;
@IsInt()
i2sSd: number;
@IsInt()
i2sDin: number;
@IsInt()
i2sSck: number;
}

65
src/validation/moduleConfig/cannedMessage.ts

@ -1,45 +1,24 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt, Length } from "class-validator";
export class CannedMessageValidation implements const InputEventCharEnum = z.enum(
Omit< Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar,
Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig, );
keyof Message
> { export const CannedMessageValidationSchema = z.object({
@IsBoolean() rotary1Enabled: z.boolean(),
rotary1Enabled: boolean; inputbrokerPinA: z.int(),
inputbrokerPinB: z.int(),
@IsInt() inputbrokerPinPress: z.int(),
inputbrokerPinA: number; inputbrokerEventCw: InputEventCharEnum,
inputbrokerEventCcw: InputEventCharEnum,
@IsInt() inputbrokerEventPress: InputEventCharEnum,
inputbrokerPinB: number; updown1Enabled: z.boolean(),
enabled: z.boolean(),
@IsInt() allowInputSource: z.string().min(2).max(30),
inputbrokerPinPress: number; sendBell: z.boolean(),
});
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar)
inputbrokerEventCw: export type CannedMessageValidation = z.infer<
Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar; typeof CannedMessageValidationSchema
>;
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar)
inputbrokerEventCcw:
Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar;
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar)
inputbrokerEventPress:
Protobuf.ModuleConfig.ModuleConfig_CannedMessageConfig_InputEventChar;
@IsBoolean()
updown1Enabled: boolean;
@IsBoolean()
enabled: boolean;
@Length(2, 30)
allowInputSource: string;
@IsBoolean()
sendBell: boolean;
}

49
src/validation/moduleConfig/detectionSensor.ts

@ -1,33 +1,16 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt, Length } from "class-validator"; export const DetectionSensorValidationSchema = z.object({
enabled: z.boolean(),
export class DetectionSensorValidation implements minimumBroadcastSecs: z.int(),
Omit< stateBroadcastSecs: z.int(),
Protobuf.ModuleConfig.ModuleConfig_DetectionSensorConfig, sendBell: z.boolean(),
keyof Message name: z.string().min(0).max(20),
> { monitorPin: z.int(),
@IsBoolean() detectionTriggeredHigh: z.boolean(),
enabled: boolean; usePullup: z.boolean(),
});
@IsInt()
minimumBroadcastSecs: number; export type DetectionSensorValidation = z.infer<
typeof DetectionSensorValidationSchema
@IsInt() >;
stateBroadcastSecs: number;
@IsBoolean()
sendBell: boolean;
@Length(0, 20)
name: string;
@IsInt()
monitorPin: number;
@IsBoolean()
detectionTriggeredHigh: boolean;
@IsBoolean()
usePullup: boolean;
}

77
src/validation/moduleConfig/externalNotification.ts

@ -1,54 +1,23 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator"; export const DetectionSensorValidationSchema = z.object({
enabled: z.boolean(),
export class ExternalNotificationValidation implements outputMs: z.int(),
Omit< output: z.int(),
Protobuf.ModuleConfig.ModuleConfig_ExternalNotificationConfig, outputVibra: z.int(),
keyof Message outputBuzzer: z.int(),
> { active: z.boolean(),
@IsBoolean() alertMessage: z.boolean(),
enabled: boolean; alertMessageVibra: z.boolean(),
alertMessageBuzzer: z.boolean(),
@IsInt() alertBell: z.boolean(),
outputMs: number; alertBellVibra: z.boolean(),
alertBellBuzzer: z.boolean(),
@IsInt() usePwm: z.boolean(),
output: number; nagTimeout: z.int(),
useI2sAsBuzzer: z.boolean(),
@IsInt() });
outputVibra: number;
export type DetectionSensorValidation = z.infer<
@IsInt() typeof DetectionSensorValidationSchema
outputBuzzer: number; >;
@IsBoolean()
active: boolean;
@IsBoolean()
alertMessage: boolean;
@IsBoolean()
alertMessageVibra: boolean;
@IsBoolean()
alertMessageBuzzer: boolean;
@IsBoolean()
alertBell: boolean;
@IsBoolean()
alertBellVibra: boolean;
@IsBoolean()
alertBellBuzzer: boolean;
@IsBoolean()
usePwm: boolean;
@IsInt()
nagTimeout: number;
@IsBoolean()
useI2sAsBuzzer: boolean;
}

81
src/validation/moduleConfig/mqtt.ts

@ -1,59 +1,22 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { export const MqttValidationMapReportSettingsSchema = z.object({
IsBoolean, publishIntervalSecs: z.number().optional(),
IsNumber, positionPrecision: z.number().optional(),
IsOptional, });
IsString,
Length, export const MqttValidationSchema = z.object({
} from "class-validator"; enabled: z.boolean(),
address: z.string().min(0).max(30),
export class MqttValidation implements username: z.string().min(0).max(30),
Omit< password: z.string().min(0).max(30),
Protobuf.ModuleConfig.ModuleConfig_MQTTConfig, encryptionEnabled: z.boolean(),
keyof Message | "mapReportSettings" jsonEnabled: z.boolean(),
> { tlsEnabled: z.boolean(),
@IsBoolean() root: z.string(),
enabled: boolean; proxyToClientEnabled: z.boolean(),
mapReportingEnabled: z.boolean(),
@Length(0, 30) mapReportSettings: MqttValidationMapReportSettingsSchema,
address: string; });
@Length(0, 30) export type MqttValidation = z.infer<typeof MqttValidationSchema>;
username: string;
@Length(0, 30)
password: string;
@IsBoolean()
encryptionEnabled: boolean;
@IsBoolean()
jsonEnabled: boolean;
@IsBoolean()
tlsEnabled: boolean;
@IsString()
root: string;
@IsBoolean()
proxyToClientEnabled: boolean;
@IsBoolean()
mapReportingEnabled: boolean;
mapReportSettings: MqttValidationMapReportSettings;
}
export class MqttValidationMapReportSettings
implements
Omit<Protobuf.ModuleConfig.ModuleConfig_MapReportSettings, keyof Message> {
@IsNumber()
@IsOptional()
publishIntervalSecs: number;
@IsNumber()
@IsOptional()
positionPrecision: number;
}

19
src/validation/moduleConfig/neighborInfo.ts

@ -1,13 +1,10 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator";
export class NeighborInfoValidation export const NeighborInfoValidationSchema = z.object({
implements enabled: z.boolean(),
Omit<Protobuf.ModuleConfig.ModuleConfig_NeighborInfoConfig, keyof Message> { updateInterval: z.int(),
@IsBoolean() });
enabled: boolean;
@IsInt() export type NeighborInfoValidation = z.infer<
updateInterval: number; typeof NeighborInfoValidationSchema
} >;

25
src/validation/moduleConfig/paxcounter.ts

@ -1,19 +1,10 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator";
export class PaxcounterValidation export const PaxcounterValidationSchema = z.object({
implements enabled: z.boolean(),
Omit<Protobuf.ModuleConfig.ModuleConfig_PaxcounterConfig, keyof Message> { paxcounterUpdateInterval: z.int(),
@IsBoolean() bleThreshold: z.int(),
enabled: boolean; wifiThreshold: z.int(),
});
@IsInt() export type PaxcounterValidation = z.infer<typeof PaxcounterValidationSchema>;
paxcounterUpdateInterval: number;
@IsInt()
bleThreshold: number;
@IsInt()
wifiThreshold: number;
}

21
src/validation/moduleConfig/rangeTest.ts

@ -1,16 +1,9 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator";
export class RangeTestValidation export const RangeTestValidationSchema = z.object({
implements enabled: z.boolean(),
Omit<Protobuf.ModuleConfig.ModuleConfig_RangeTestConfig, keyof Message> { sender: z.int(),
@IsBoolean() save: z.boolean(),
enabled: boolean; });
@IsInt() export type RangeTestValidation = z.infer<typeof RangeTestValidationSchema>;
sender: number;
@IsBoolean()
save: boolean;
}

49
src/validation/moduleConfig/serial.ts

@ -1,31 +1,22 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import { Protobuf } from "@meshtastic/core"; import { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsEnum, IsInt } from "class-validator";
export class SerialValidation const Serial_BaudEnum = z.enum(
implements Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Baud,
Omit<Protobuf.ModuleConfig.ModuleConfig_SerialConfig, keyof Message> { );
@IsBoolean() const Serial_ModeEnum = z.enum(
enabled: boolean; Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Mode,
);
@IsBoolean()
echo: boolean; export const SerialValidationSchema = z.object({
enabled: z.boolean(),
@IsInt() echo: z.boolean(),
rxd: number; rxd: z.int(),
txd: z.int(),
@IsInt() baud: Serial_BaudEnum,
txd: number; timeout: z.int(),
mode: Serial_ModeEnum,
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Baud) overrideConsoleSerialPort: z.boolean(),
baud: Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Baud; });
@IsInt() export type SerialValidation = z.infer<typeof SerialValidationSchema>;
timeout: number;
@IsEnum(Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Mode)
mode: Protobuf.ModuleConfig.ModuleConfig_SerialConfig_Serial_Mode;
@IsBoolean()
overrideConsoleSerialPort: boolean;
}

37
src/validation/moduleConfig/storeForward.ts

@ -1,24 +1,13 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator"; export const StoreForwardValidationSchema = z.object({
enabled: z.boolean(),
export class StoreForwardValidation implements heartbeat: z.boolean(),
Omit< records: z.int(),
Protobuf.ModuleConfig.ModuleConfig_StoreForwardConfig, historyReturnMax: z.int(),
keyof Message | "isServer" historyReturnWindow: z.int(),
> { });
@IsBoolean()
enabled: boolean; export type StoreForwardValidation = z.infer<
typeof StoreForwardValidationSchema
@IsBoolean() >;
heartbeat: boolean;
@IsInt()
records: number;
@IsInt()
historyReturnMax: number;
@IsInt()
historyReturnWindow: number;
}

55
src/validation/moduleConfig/telemetry.ts

@ -1,37 +1,18 @@
import type { Message } from "@bufbuild/protobuf"; import { z } from "zod/v4";
import type { Protobuf } from "@meshtastic/core";
import { IsBoolean, IsInt } from "class-validator"; export const StoreForwardValidationSchema = z.object({
deviceUpdateInterval: z.int(),
export class TelemetryValidation environmentUpdateInterval: z.int(),
implements environmentMeasurementEnabled: z.boolean(),
Omit<Protobuf.ModuleConfig.ModuleConfig_TelemetryConfig, keyof Message> { environmentScreenEnabled: z.boolean(),
@IsInt() environmentDisplayFahrenheit: z.boolean(),
deviceUpdateInterval: number; airQualityEnabled: z.boolean(),
airQualityInterval: z.int(),
@IsInt() powerMeasurementEnabled: z.boolean(),
environmentUpdateInterval: number; powerUpdateInterval: z.int(),
powerScreenEnabled: z.boolean(),
@IsBoolean() });
environmentMeasurementEnabled: boolean;
export type StoreForwardValidation = z.infer<
@IsBoolean() typeof StoreForwardValidationSchema
environmentScreenEnabled: boolean; >;
@IsBoolean()
environmentDisplayFahrenheit: boolean;
@IsBoolean()
airQualityEnabled: boolean;
@IsInt()
airQualityInterval: number;
@IsBoolean()
powerMeasurementEnabled: boolean;
@IsInt()
powerUpdateInterval: number;
@IsBoolean()
powerScreenEnabled: boolean;
}

30
src/validation/rasterSource.ts

@ -1,22 +1,14 @@
import { IsArray, IsBoolean, IsNumber, IsString, IsUrl } from "class-validator"; import { z } from "zod/v4";
import type { RasterSource } from "@core/stores/appStore.ts"; export const MapValidation_RasterSourcesSchema = z.object({
enabled: z.boolean(),
title: z.string(),
tiles: z.url(),
tileSize: z.number(),
});
export class MapValidation { export const MapValidationSchema = z.object({
@IsArray() rasterSources: MapValidation_RasterSourcesSchema.array(),
rasterSources: MapValidation_RasterSources[]; });
}
export class MapValidation_RasterSources implements RasterSource { export type MapValidation = z.infer<typeof MapValidationSchema>;
@IsBoolean()
enabled: boolean;
@IsString()
title: string;
@IsUrl()
tiles: string;
@IsNumber()
tileSize: number;
}

4
src/validation/validate.ts

@ -1,7 +1,7 @@
import { ZodError, ZodSchema } from "zod"; import { ZodError, ZodType } from "zod/v4";
export function validateSchema<T>( export function validateSchema<T>(
schema: ZodSchema<T>, schema: ZodType<T>,
data: unknown, data: unknown,
): { success: true; data: T } | { success: false; errors: ZodError["issues"] } { ): { success: true; data: T } | { success: false; errors: ZodError["issues"] } {
const result = schema.safeParse(data); const result = schema.safeParse(data);

Loading…
Cancel
Save