@tx5dr/contracts 1.7.12 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/schema/__tests__/android-operator-audio.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/android-operator-audio.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/android-operator-audio.schema.test.js +27 -0
- package/dist/schema/__tests__/android-operator-audio.schema.test.js.map +1 -0
- package/dist/schema/__tests__/assisted-queue.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/assisted-queue.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/assisted-queue.schema.test.js +114 -0
- package/dist/schema/__tests__/assisted-queue.schema.test.js.map +1 -0
- package/dist/schema/__tests__/audio-sidecar.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/audio-sidecar.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/audio-sidecar.schema.test.js +42 -0
- package/dist/schema/__tests__/audio-sidecar.schema.test.js.map +1 -0
- package/dist/schema/__tests__/audio.schema.test.js +92 -1
- package/dist/schema/__tests__/audio.schema.test.js.map +1 -1
- package/dist/schema/__tests__/diagnostics.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/diagnostics.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/diagnostics.schema.test.js +31 -0
- package/dist/schema/__tests__/diagnostics.schema.test.js.map +1 -0
- package/dist/schema/__tests__/logbook-health.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/logbook-health.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/logbook-health.schema.test.js +104 -0
- package/dist/schema/__tests__/logbook-health.schema.test.js.map +1 -0
- package/dist/schema/__tests__/meter.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/meter.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/meter.schema.test.js +27 -0
- package/dist/schema/__tests__/meter.schema.test.js.map +1 -0
- package/dist/schema/__tests__/observability.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/observability.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/observability.schema.test.js +12 -0
- package/dist/schema/__tests__/observability.schema.test.js.map +1 -0
- package/dist/schema/__tests__/operator-context-report.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/operator-context-report.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/operator-context-report.schema.test.js +70 -0
- package/dist/schema/__tests__/operator-context-report.schema.test.js.map +1 -0
- package/dist/schema/__tests__/operator.schema.test.js +9 -3
- package/dist/schema/__tests__/operator.schema.test.js.map +1 -1
- package/dist/schema/__tests__/plugin-market.schema.test.js +149 -3
- package/dist/schema/__tests__/plugin-market.schema.test.js.map +1 -1
- package/dist/schema/__tests__/qso.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/qso.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/qso.schema.test.js +70 -0
- package/dist/schema/__tests__/qso.schema.test.js.map +1 -0
- package/dist/schema/__tests__/radio-power-support.test.js +15 -0
- package/dist/schema/__tests__/radio-power-support.test.js.map +1 -1
- package/dist/schema/__tests__/radio-profile.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/radio-profile.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/radio-profile.schema.test.js +36 -0
- package/dist/schema/__tests__/radio-profile.schema.test.js.map +1 -0
- package/dist/schema/__tests__/radio.schema.test.js +92 -1
- package/dist/schema/__tests__/radio.schema.test.js.map +1 -1
- package/dist/schema/__tests__/realtime-settings.schema.test.js +2 -1
- package/dist/schema/__tests__/realtime-settings.schema.test.js.map +1 -1
- package/dist/schema/__tests__/remote-access.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/remote-access.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/remote-access.schema.test.js +18 -0
- package/dist/schema/__tests__/remote-access.schema.test.js.map +1 -0
- package/dist/schema/__tests__/spectrum.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/spectrum.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/spectrum.schema.test.js +107 -0
- package/dist/schema/__tests__/spectrum.schema.test.js.map +1 -0
- package/dist/schema/__tests__/strategy-transmission.schema.test.d.ts +2 -0
- package/dist/schema/__tests__/strategy-transmission.schema.test.d.ts.map +1 -0
- package/dist/schema/__tests__/strategy-transmission.schema.test.js +95 -0
- package/dist/schema/__tests__/strategy-transmission.schema.test.js.map +1 -0
- package/dist/schema/android-operator-audio.schema.d.ts +174 -0
- package/dist/schema/android-operator-audio.schema.d.ts.map +1 -0
- package/dist/schema/android-operator-audio.schema.js +38 -0
- package/dist/schema/android-operator-audio.schema.js.map +1 -0
- package/dist/schema/api-response.schema.d.ts +503 -44
- package/dist/schema/api-response.schema.d.ts.map +1 -1
- package/dist/schema/api-response.schema.js +9 -0
- package/dist/schema/api-response.schema.js.map +1 -1
- package/dist/schema/audio-sidecar.schema.d.ts +75 -0
- package/dist/schema/audio-sidecar.schema.d.ts.map +1 -1
- package/dist/schema/audio-sidecar.schema.js +32 -0
- package/dist/schema/audio-sidecar.schema.js.map +1 -1
- package/dist/schema/audio.schema.d.ts +4749 -3
- package/dist/schema/audio.schema.d.ts.map +1 -1
- package/dist/schema/audio.schema.js +101 -2
- package/dist/schema/audio.schema.js.map +1 -1
- package/dist/schema/auth.schema.d.ts +173 -14
- package/dist/schema/auth.schema.d.ts.map +1 -1
- package/dist/schema/auth.schema.js +65 -1
- package/dist/schema/auth.schema.js.map +1 -1
- package/dist/schema/cpu-profile.schema.d.ts +2 -2
- package/dist/schema/cw-decoder.schema.d.ts +74 -74
- package/dist/schema/cw-keyer.schema.d.ts +20 -14
- package/dist/schema/cw-keyer.schema.d.ts.map +1 -1
- package/dist/schema/cw-keyer.schema.js +3 -0
- package/dist/schema/cw-keyer.schema.js.map +1 -1
- package/dist/schema/desktop-https.schema.d.ts +6 -6
- package/dist/schema/device-ui.schema.d.ts +16 -16
- package/dist/schema/diagnostics.schema.d.ts +163 -0
- package/dist/schema/diagnostics.schema.d.ts.map +1 -0
- package/dist/schema/diagnostics.schema.js +46 -0
- package/dist/schema/diagnostics.schema.js.map +1 -0
- package/dist/schema/ft8.schema.d.ts +12 -2
- package/dist/schema/ft8.schema.d.ts.map +1 -1
- package/dist/schema/ft8.schema.js +8 -0
- package/dist/schema/ft8.schema.js.map +1 -1
- package/dist/schema/image-radio.schema.d.ts +2597 -0
- package/dist/schema/image-radio.schema.d.ts.map +1 -0
- package/dist/schema/image-radio.schema.js +283 -0
- package/dist/schema/image-radio.schema.js.map +1 -0
- package/dist/schema/logbook.schema.d.ts +2128 -18
- package/dist/schema/logbook.schema.d.ts.map +1 -1
- package/dist/schema/logbook.schema.js +159 -1
- package/dist/schema/logbook.schema.js.map +1 -1
- package/dist/schema/mode.schema.d.ts +4 -6
- package/dist/schema/mode.schema.d.ts.map +1 -1
- package/dist/schema/mode.schema.js +18 -6
- package/dist/schema/mode.schema.js.map +1 -1
- package/dist/schema/observability.schema.d.ts +66 -0
- package/dist/schema/observability.schema.d.ts.map +1 -0
- package/dist/schema/observability.schema.js +20 -0
- package/dist/schema/observability.schema.js.map +1 -0
- package/dist/schema/openwebrx.schema.d.ts +2 -2
- package/dist/schema/operator.schema.d.ts +2682 -6
- package/dist/schema/operator.schema.d.ts.map +1 -1
- package/dist/schema/operator.schema.js +10 -20
- package/dist/schema/operator.schema.js.map +1 -1
- package/dist/schema/plugin.schema.d.ts +1977 -492
- package/dist/schema/plugin.schema.d.ts.map +1 -1
- package/dist/schema/plugin.schema.js +165 -14
- package/dist/schema/plugin.schema.js.map +1 -1
- package/dist/schema/process-monitor.schema.d.ts +132 -132
- package/dist/schema/pskreporter.schema.d.ts +1 -3
- package/dist/schema/pskreporter.schema.d.ts.map +1 -1
- package/dist/schema/pskreporter.schema.js +1 -3
- package/dist/schema/pskreporter.schema.js.map +1 -1
- package/dist/schema/qso.schema.d.ts +246 -1
- package/dist/schema/qso.schema.d.ts.map +1 -1
- package/dist/schema/qso.schema.js +68 -0
- package/dist/schema/qso.schema.js.map +1 -1
- package/dist/schema/radio-capability.schema.d.ts +31 -40
- package/dist/schema/radio-capability.schema.d.ts.map +1 -1
- package/dist/schema/radio-capability.schema.js +8 -15
- package/dist/schema/radio-capability.schema.js.map +1 -1
- package/dist/schema/radio-power-support.d.ts.map +1 -1
- package/dist/schema/radio-power-support.js +3 -0
- package/dist/schema/radio-power-support.js.map +1 -1
- package/dist/schema/radio-power.schema.d.ts +102 -13
- package/dist/schema/radio-power.schema.d.ts.map +1 -1
- package/dist/schema/radio-power.schema.js +15 -8
- package/dist/schema/radio-power.schema.js.map +1 -1
- package/dist/schema/radio-profile.schema.d.ts +1491 -97
- package/dist/schema/radio-profile.schema.d.ts.map +1 -1
- package/dist/schema/radio-profile.schema.js +7 -0
- package/dist/schema/radio-profile.schema.js.map +1 -1
- package/dist/schema/radio.schema.d.ts +442 -48
- package/dist/schema/radio.schema.d.ts.map +1 -1
- package/dist/schema/radio.schema.js +75 -7
- package/dist/schema/radio.schema.js.map +1 -1
- package/dist/schema/realtime.schema.d.ts +60 -52
- package/dist/schema/realtime.schema.d.ts.map +1 -1
- package/dist/schema/realtime.schema.js +9 -1
- package/dist/schema/realtime.schema.js.map +1 -1
- package/dist/schema/rigctld.schema.d.ts +6 -6
- package/dist/schema/slot-info.schema.d.ts +28 -9
- package/dist/schema/slot-info.schema.d.ts.map +1 -1
- package/dist/schema/slot-info.schema.js +17 -10
- package/dist/schema/slot-info.schema.js.map +1 -1
- package/dist/schema/spectrum-config.schema.d.ts +638 -0
- package/dist/schema/spectrum-config.schema.d.ts.map +1 -0
- package/dist/schema/spectrum-config.schema.js +129 -0
- package/dist/schema/spectrum-config.schema.js.map +1 -0
- package/dist/schema/spectrum.schema.d.ts +1323 -30
- package/dist/schema/spectrum.schema.d.ts.map +1 -1
- package/dist/schema/spectrum.schema.js +72 -0
- package/dist/schema/spectrum.schema.js.map +1 -1
- package/dist/schema/station-info.schema.d.ts +5 -0
- package/dist/schema/station-info.schema.d.ts.map +1 -1
- package/dist/schema/station-info.schema.js +5 -0
- package/dist/schema/station-info.schema.js.map +1 -1
- package/dist/schema/system.schema.d.ts +56 -6
- package/dist/schema/system.schema.d.ts.map +1 -1
- package/dist/schema/system.schema.js +22 -0
- package/dist/schema/system.schema.js.map +1 -1
- package/dist/schema/transmission.schema.d.ts +8 -7
- package/dist/schema/transmission.schema.d.ts.map +1 -1
- package/dist/schema/transmission.schema.js +2 -7
- package/dist/schema/transmission.schema.js.map +1 -1
- package/dist/schema/tx-audio-input.schema.d.ts +8 -0
- package/dist/schema/tx-audio-input.schema.d.ts.map +1 -0
- package/dist/schema/tx-audio-input.schema.js +19 -0
- package/dist/schema/tx-audio-input.schema.js.map +1 -0
- package/dist/schema/voice-keyer.schema.d.ts +16 -16
- package/dist/schema/voice.schema.d.ts +1 -1
- package/dist/schema/voice.schema.d.ts.map +1 -1
- package/dist/schema/voice.schema.js +1 -1
- package/dist/schema/voice.schema.js.map +1 -1
- package/dist/schema/websocket.schema.d.ts +35811 -7829
- package/dist/schema/websocket.schema.d.ts.map +1 -1
- package/dist/schema/websocket.schema.js +453 -9
- package/dist/schema/websocket.schema.js.map +1 -1
- package/package.json +6 -1
- package/src/index.ts +7 -0
- package/src/schema/__tests__/android-operator-audio.schema.test.ts +31 -0
- package/src/schema/__tests__/assisted-queue.schema.test.ts +122 -0
- package/src/schema/__tests__/audio-sidecar.schema.test.ts +48 -0
- package/src/schema/__tests__/audio.schema.test.ts +102 -0
- package/src/schema/__tests__/diagnostics.schema.test.ts +32 -0
- package/src/schema/__tests__/logbook-health.schema.test.ts +117 -0
- package/src/schema/__tests__/meter.schema.test.ts +28 -0
- package/src/schema/__tests__/observability.schema.test.ts +15 -0
- package/src/schema/__tests__/operator-context-report.schema.test.ts +77 -0
- package/src/schema/__tests__/operator.schema.test.ts +11 -3
- package/src/schema/__tests__/plugin-market.schema.test.ts +165 -2
- package/src/schema/__tests__/qso.schema.test.ts +91 -0
- package/src/schema/__tests__/radio-power-support.test.ts +17 -0
- package/src/schema/__tests__/radio-profile.schema.test.ts +44 -0
- package/src/schema/__tests__/radio.schema.test.ts +108 -1
- package/src/schema/__tests__/realtime-settings.schema.test.ts +2 -1
- package/src/schema/__tests__/remote-access.schema.test.ts +22 -0
- package/src/schema/__tests__/spectrum.schema.test.ts +119 -0
- package/src/schema/__tests__/strategy-transmission.schema.test.ts +106 -0
- package/src/schema/android-operator-audio.schema.ts +49 -0
- package/src/schema/api-response.schema.ts +11 -0
- package/src/schema/audio-sidecar.schema.ts +35 -0
- package/src/schema/audio.schema.ts +115 -2
- package/src/schema/auth.schema.ts +79 -1
- package/src/schema/cw-keyer.schema.ts +5 -0
- package/src/schema/diagnostics.schema.ts +55 -0
- package/src/schema/ft8.schema.ts +8 -0
- package/src/schema/image-radio.schema.ts +342 -0
- package/src/schema/logbook.schema.ts +205 -1
- package/src/schema/mode.schema.ts +18 -6
- package/src/schema/observability.schema.ts +26 -0
- package/src/schema/operator.schema.ts +11 -20
- package/src/schema/plugin.schema.ts +186 -15
- package/src/schema/pskreporter.schema.ts +1 -3
- package/src/schema/qso.schema.ts +78 -0
- package/src/schema/radio-capability.schema.ts +8 -15
- package/src/schema/radio-power-support.ts +3 -0
- package/src/schema/radio-power.schema.ts +15 -8
- package/src/schema/radio-profile.schema.ts +7 -0
- package/src/schema/radio.schema.ts +90 -7
- package/src/schema/realtime.schema.ts +9 -1
- package/src/schema/slot-info.schema.ts +18 -11
- package/src/schema/spectrum-config.schema.ts +156 -0
- package/src/schema/spectrum.schema.ts +89 -0
- package/src/schema/station-info.schema.ts +5 -0
- package/src/schema/system.schema.ts +29 -0
- package/src/schema/transmission.schema.ts +2 -7
- package/src/schema/tx-audio-input.schema.ts +22 -0
- package/src/schema/voice.schema.ts +1 -1
- package/src/schema/websocket.schema.ts +601 -13
- package/test/image-radio-schema.test.ts +107 -0
- package/test/plugin-slot-schema.test.ts +31 -0
- package/test/radio-capability-schema.test.ts +44 -0
- package/CLAUDE.md +0 -41
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
+
export const AudioDeviceBackendSchema = z.enum([
|
|
4
|
+
'rtaudio',
|
|
5
|
+
'android',
|
|
6
|
+
'icom-wlan',
|
|
7
|
+
'openwebrx',
|
|
8
|
+
'tci',
|
|
9
|
+
'network',
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
export const AudioDeviceKindSchema = z.enum([
|
|
13
|
+
'usb',
|
|
14
|
+
'wired-headset',
|
|
15
|
+
'wired-headphones',
|
|
16
|
+
'analog-line',
|
|
17
|
+
'builtin-mic',
|
|
18
|
+
'builtin-speaker',
|
|
19
|
+
'network',
|
|
20
|
+
'virtual',
|
|
21
|
+
'unknown',
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export const AudioDeviceTransportSchema = z.enum([
|
|
25
|
+
'usb',
|
|
26
|
+
'analog',
|
|
27
|
+
'builtin',
|
|
28
|
+
'network',
|
|
29
|
+
'virtual',
|
|
30
|
+
'unknown',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
export const AudioDeviceConnectorSchema = z.enum([
|
|
34
|
+
'usb',
|
|
35
|
+
'3.5mm',
|
|
36
|
+
'builtin',
|
|
37
|
+
'network',
|
|
38
|
+
'virtual',
|
|
39
|
+
'unknown',
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
export const AudioDeviceRouteStateSchema = z.enum([
|
|
43
|
+
'idle',
|
|
44
|
+
'opening',
|
|
45
|
+
'verified',
|
|
46
|
+
'lost',
|
|
47
|
+
'unavailable',
|
|
48
|
+
'failed',
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
export const AudioDeviceCapabilitiesSchema = z.object({
|
|
52
|
+
sampleRates: z.array(z.number().int().positive()).optional(),
|
|
53
|
+
bufferSizes: z.array(z.number().int().positive()).optional(),
|
|
54
|
+
channelCounts: z.array(z.number().int().positive()).optional(),
|
|
55
|
+
sampleFormats: z.array(z.enum(['float32', 'int16'])).optional(),
|
|
56
|
+
channelModes: z.array(z.enum(['mono', 'left', 'right', 'both'])).optional(),
|
|
57
|
+
sampleRateConfigurable: z.boolean().optional(),
|
|
58
|
+
bufferSizeConfigurable: z.boolean().optional(),
|
|
59
|
+
sampleFormatConfigurable: z.boolean().optional(),
|
|
60
|
+
channelModeConfigurable: z.boolean().optional(),
|
|
61
|
+
outputRouteAck: z.boolean().optional(),
|
|
62
|
+
fixedSampleRate: z.number().int().positive().optional(),
|
|
63
|
+
fixedBufferSize: z.number().int().positive().optional(),
|
|
64
|
+
fixedChannelCount: z.number().int().positive().optional(),
|
|
65
|
+
});
|
|
66
|
+
|
|
3
67
|
// 音频设备信息
|
|
4
68
|
export const AudioDeviceSchema = z.object({
|
|
5
69
|
id: z.string(),
|
|
@@ -12,6 +76,26 @@ export const AudioDeviceSchema = z.object({
|
|
|
12
76
|
availability: z.enum(['available', 'cached', 'active']).optional(),
|
|
13
77
|
isActiveByTx5dr: z.boolean().optional(),
|
|
14
78
|
lastSeenAt: z.number().int().positive().optional(),
|
|
79
|
+
backend: AudioDeviceBackendSchema.optional(),
|
|
80
|
+
kind: AudioDeviceKindSchema.optional(),
|
|
81
|
+
routeKey: z.string().min(1).optional(),
|
|
82
|
+
transport: AudioDeviceTransportSchema.optional(),
|
|
83
|
+
connector: AudioDeviceConnectorSchema.optional(),
|
|
84
|
+
clientConnected: z.boolean().optional(),
|
|
85
|
+
routeVerified: z.boolean().optional(),
|
|
86
|
+
routeState: AudioDeviceRouteStateSchema.optional(),
|
|
87
|
+
failureReason: z.string().min(1).optional(),
|
|
88
|
+
capabilities: AudioDeviceCapabilitiesSchema.optional(),
|
|
89
|
+
/** Human-readable secondary label (radio identity · VID:PID · USB path). */
|
|
90
|
+
detail: z.string().optional(),
|
|
91
|
+
/** Stable hardware identity when available (e.g. usb:1-7.2.4). */
|
|
92
|
+
hardwareId: z.string().optional(),
|
|
93
|
+
vendorId: z.string().optional(),
|
|
94
|
+
productId: z.string().optional(),
|
|
95
|
+
serialNumber: z.string().optional(),
|
|
96
|
+
usbPath: z.string().optional(),
|
|
97
|
+
alsaCard: z.number().int().nonnegative().optional(),
|
|
98
|
+
alsaCardId: z.string().optional(),
|
|
15
99
|
});
|
|
16
100
|
|
|
17
101
|
export const AudioDeviceResolutionStatusSchema = z.enum([
|
|
@@ -23,6 +107,9 @@ export const AudioDeviceResolutionStatusSchema = z.enum([
|
|
|
23
107
|
|
|
24
108
|
export const AudioDeviceResolutionSchema = z.object({
|
|
25
109
|
configuredDeviceName: z.string().nullable(),
|
|
110
|
+
configuredRouteKey: z.string().nullable().optional(),
|
|
111
|
+
configuredDeviceId: z.string().nullable().optional(),
|
|
112
|
+
configuredHardwareId: z.string().nullable().optional(),
|
|
26
113
|
configuredDevice: AudioDeviceSchema.nullable(),
|
|
27
114
|
effectiveDevice: AudioDeviceSchema.nullable(),
|
|
28
115
|
status: AudioDeviceResolutionStatusSchema,
|
|
@@ -37,6 +124,13 @@ export const AudioDeviceResolutionSetSchema = z.object({
|
|
|
37
124
|
export const AudioOutputSampleFormatSchema = z.enum(['float32', 'int16']);
|
|
38
125
|
export const AudioOutputChannelModeSchema = z.enum(['mono', 'left', 'right', 'both']);
|
|
39
126
|
|
|
127
|
+
/**
|
|
128
|
+
* How USB/ACC capture PCM should be interpreted before the internal 12 kHz AF ring.
|
|
129
|
+
* - af: already-demodulated SSB baseband (default)
|
|
130
|
+
* - icom-12k-if: Icom ACC/USB Output Select=IF (~12 kHz IF); software SSB demod required
|
|
131
|
+
*/
|
|
132
|
+
export const AudioInputSignalTypeSchema = z.enum(['af', 'icom-12k-if']);
|
|
133
|
+
|
|
40
134
|
// 音频设备列表响应
|
|
41
135
|
export const AudioDevicesResponseSchema = z.object({
|
|
42
136
|
inputDevices: z.array(AudioDeviceSchema),
|
|
@@ -48,13 +142,25 @@ export const AudioDevicesResponseSchema = z.object({
|
|
|
48
142
|
// 音频设备设置请求
|
|
49
143
|
export const AudioDeviceSettingsSchema = z.object({
|
|
50
144
|
inputDeviceName: z.string().optional(), // 使用设备名称而非ID
|
|
51
|
-
outputDeviceName: z.string().optional(), // 使用设备名称而非ID
|
|
145
|
+
outputDeviceName: z.string().optional(), // 使用设备名称而非ID
|
|
146
|
+
inputRouteKey: z.string().min(1).nullable().optional(),
|
|
147
|
+
outputRouteKey: z.string().min(1).nullable().optional(),
|
|
148
|
+
/** Runtime device id (e.g. input-130). Preferred over name when unique. */
|
|
149
|
+
inputDeviceId: z.string().optional(),
|
|
150
|
+
outputDeviceId: z.string().optional(),
|
|
151
|
+
/** Stable hardware id when available (e.g. usb:1-7.2.4). Preferred over runtime id. */
|
|
152
|
+
inputHardwareId: z.string().optional(),
|
|
153
|
+
outputHardwareId: z.string().optional(),
|
|
52
154
|
inputSampleRate: z.number().optional(),
|
|
53
155
|
outputSampleRate: z.number().optional(),
|
|
54
156
|
inputBufferSize: z.number().optional(),
|
|
55
157
|
outputBufferSize: z.number().optional(),
|
|
56
158
|
outputSampleFormat: AudioOutputSampleFormatSchema.optional(),
|
|
57
159
|
outputChannelMode: AudioOutputChannelModeSchema.optional(),
|
|
160
|
+
/** Capture signal interpretation. Defaults to demodulated AF baseband. */
|
|
161
|
+
inputSignalType: AudioInputSignalTypeSchema.optional(),
|
|
162
|
+
/** IF center frequency in Hz when inputSignalType is icom-12k-if (default 12000). */
|
|
163
|
+
ifCenterHz: z.number().positive().max(24000).optional(),
|
|
58
164
|
sampleRate: z.number().optional(),
|
|
59
165
|
bufferSize: z.number().optional(),
|
|
60
166
|
});
|
|
@@ -69,7 +175,7 @@ export const AudioDeviceSettingsResponseSchema = z.object({
|
|
|
69
175
|
|
|
70
176
|
export const AudioSettingsResolveRequestSchema = z.object({
|
|
71
177
|
audio: AudioDeviceSettingsSchema,
|
|
72
|
-
radioType: z.enum(['none', 'network', 'serial', 'icom-wlan']).optional(),
|
|
178
|
+
radioType: z.enum(['none', 'network', 'serial', 'icom-wlan', 'tci']).optional(),
|
|
73
179
|
});
|
|
74
180
|
|
|
75
181
|
export const AudioSettingsResolveResponseSchema = z.object({
|
|
@@ -110,11 +216,18 @@ export const VolumeGainSchema = z.object({
|
|
|
110
216
|
|
|
111
217
|
// 导出类型
|
|
112
218
|
export type AudioDevice = z.infer<typeof AudioDeviceSchema>;
|
|
219
|
+
export type AudioDeviceBackend = z.infer<typeof AudioDeviceBackendSchema>;
|
|
220
|
+
export type AudioDeviceKind = z.infer<typeof AudioDeviceKindSchema>;
|
|
221
|
+
export type AudioDeviceTransport = z.infer<typeof AudioDeviceTransportSchema>;
|
|
222
|
+
export type AudioDeviceConnector = z.infer<typeof AudioDeviceConnectorSchema>;
|
|
223
|
+
export type AudioDeviceRouteState = z.infer<typeof AudioDeviceRouteStateSchema>;
|
|
224
|
+
export type AudioDeviceCapabilities = z.infer<typeof AudioDeviceCapabilitiesSchema>;
|
|
113
225
|
export type AudioDeviceResolutionStatus = z.infer<typeof AudioDeviceResolutionStatusSchema>;
|
|
114
226
|
export type AudioDeviceResolution = z.infer<typeof AudioDeviceResolutionSchema>;
|
|
115
227
|
export type AudioDeviceResolutionSet = z.infer<typeof AudioDeviceResolutionSetSchema>;
|
|
116
228
|
export type AudioOutputSampleFormat = z.infer<typeof AudioOutputSampleFormatSchema>;
|
|
117
229
|
export type AudioOutputChannelMode = z.infer<typeof AudioOutputChannelModeSchema>;
|
|
230
|
+
export type AudioInputSignalType = z.infer<typeof AudioInputSignalTypeSchema>;
|
|
118
231
|
export type AudioDevicesResponse = z.infer<typeof AudioDevicesResponseSchema>;
|
|
119
232
|
export type AudioDeviceSettings = z.infer<typeof AudioDeviceSettingsSchema>;
|
|
120
233
|
export type AudioDeviceSettingsResponse = z.infer<typeof AudioDeviceSettingsResponseSchema>;
|
|
@@ -82,6 +82,19 @@ export const LoginResponseSchema = z.object({
|
|
|
82
82
|
|
|
83
83
|
export type LoginResponse = z.infer<typeof LoginResponseSchema>;
|
|
84
84
|
|
|
85
|
+
export const BrowserLoginCodeResponseSchema = z.object({
|
|
86
|
+
code: z.string().min(1),
|
|
87
|
+
expiresAt: z.number(),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export type BrowserLoginCodeResponse = z.infer<typeof BrowserLoginCodeResponseSchema>;
|
|
91
|
+
|
|
92
|
+
export const ExchangeBrowserLoginCodeRequestSchema = z.object({
|
|
93
|
+
code: z.string().min(1),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export type ExchangeBrowserLoginCodeRequest = z.infer<typeof ExchangeBrowserLoginCodeRequestSchema>;
|
|
97
|
+
|
|
85
98
|
// ===== Token 管理(Admin API) =====
|
|
86
99
|
|
|
87
100
|
export const LoginCredentialSummarySchema = z.object({
|
|
@@ -211,11 +224,76 @@ export const UpdateAuthConfigRequestSchema = z.object({
|
|
|
211
224
|
|
|
212
225
|
export type UpdateAuthConfigRequest = z.infer<typeof UpdateAuthConfigRequestSchema>;
|
|
213
226
|
|
|
227
|
+
export const RemoteAccessPresetSchema = z.enum(['local', 'lan', 'public']);
|
|
228
|
+
export type RemoteAccessPreset = z.infer<typeof RemoteAccessPresetSchema>;
|
|
229
|
+
|
|
230
|
+
export function isPrivateRemoteAccessHostname(hostname: string): boolean {
|
|
231
|
+
if (['localhost', '127.0.0.1', '::1'].includes(hostname)) return true;
|
|
232
|
+
if (hostname.includes(':')) {
|
|
233
|
+
const normalized = hostname.toLowerCase();
|
|
234
|
+
return normalized.startsWith('fc') || normalized.startsWith('fd') || normalized.startsWith('fe8')
|
|
235
|
+
|| normalized.startsWith('fe9') || normalized.startsWith('fea') || normalized.startsWith('feb');
|
|
236
|
+
}
|
|
237
|
+
const parts = hostname.split('.').map(Number);
|
|
238
|
+
if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255)) return false;
|
|
239
|
+
return parts[0] === 10
|
|
240
|
+
|| (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31)
|
|
241
|
+
|| (parts[0] === 192 && parts[1] === 168)
|
|
242
|
+
|| (parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127)
|
|
243
|
+
|| (parts[0] === 169 && parts[1] === 254);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function normalizeRemoteAccessOrigin(value: string): string | null {
|
|
247
|
+
try {
|
|
248
|
+
const parsed = new URL(value.trim());
|
|
249
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return null;
|
|
250
|
+
if (parsed.username || parsed.password || parsed.pathname !== '/' || parsed.search || parsed.hash) return null;
|
|
251
|
+
return parsed.origin;
|
|
252
|
+
} catch {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function isSecureRemoteAccessOrigin(value: string): boolean {
|
|
258
|
+
const normalized = normalizeRemoteAccessOrigin(value);
|
|
259
|
+
if (!normalized) return false;
|
|
260
|
+
const parsed = new URL(normalized);
|
|
261
|
+
return parsed.protocol === 'https:' || isPrivateRemoteAccessHostname(parsed.hostname);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export const RemoteAccessSecurityConfigSchema = z.object({
|
|
265
|
+
preset: RemoteAccessPresetSchema.default('lan'),
|
|
266
|
+
allowedOrigins: z.array(z.string().url().refine(
|
|
267
|
+
value => normalizeRemoteAccessOrigin(value) !== null,
|
|
268
|
+
'Expected a complete HTTP(S) origin without a path',
|
|
269
|
+
)).max(32).default([]),
|
|
270
|
+
maxConnections: z.number().int().min(1).max(512).default(32),
|
|
271
|
+
maxConnectionsPerIp: z.number().int().min(1).max(128).default(16),
|
|
272
|
+
maxPendingAuth: z.number().int().min(1).max(128).default(32),
|
|
273
|
+
authTimeoutMs: z.number().int().min(3_000).max(60_000).default(10_000),
|
|
274
|
+
handshakeTimeoutMs: z.number().int().min(3_000).max(60_000).default(10_000),
|
|
275
|
+
});
|
|
276
|
+
export type RemoteAccessSecurityConfig = z.infer<typeof RemoteAccessSecurityConfigSchema>;
|
|
277
|
+
|
|
278
|
+
export const UpdateRemoteAccessSecurityRequestSchema = RemoteAccessSecurityConfigSchema.partial().extend({
|
|
279
|
+
allowPublicViewing: z.boolean().optional(),
|
|
280
|
+
});
|
|
281
|
+
export type UpdateRemoteAccessSecurityRequest = z.infer<typeof UpdateRemoteAccessSecurityRequestSchema>;
|
|
282
|
+
|
|
283
|
+
export const RemoteAccessSecurityStatusSchema = RemoteAccessSecurityConfigSchema.extend({
|
|
284
|
+
allowPublicViewing: z.boolean(),
|
|
285
|
+
activeConnections: z.number().int().nonnegative(),
|
|
286
|
+
pendingConnections: z.number().int().nonnegative(),
|
|
287
|
+
});
|
|
288
|
+
export type RemoteAccessSecurityStatus = z.infer<typeof RemoteAccessSecurityStatusSchema>;
|
|
289
|
+
|
|
214
290
|
// ===== 认证配置(持久化到 auth.json) =====
|
|
215
291
|
|
|
216
292
|
export const AuthConfigSchema = z.object({
|
|
217
293
|
enabled: z.boolean().default(true),
|
|
218
|
-
|
|
294
|
+
// Existing installations persist their explicit value; new installations opt in.
|
|
295
|
+
allowPublicViewing: z.boolean().default(false),
|
|
296
|
+
remoteAccess: RemoteAccessSecurityConfigSchema.default({}),
|
|
219
297
|
jwtSecret: z.string().optional(),
|
|
220
298
|
jwtExpiresInSeconds: z.number().default(7 * 24 * 3600), // 7 days
|
|
221
299
|
tokens: z.array(AuthTokenSchema).default([]),
|
|
@@ -6,6 +6,9 @@ import { z } from 'zod';
|
|
|
6
6
|
export const CWKeyerBackendSchema = z.enum(['cat', 'serial']);
|
|
7
7
|
export type CWKeyerBackend = z.infer<typeof CWKeyerBackendSchema>;
|
|
8
8
|
|
|
9
|
+
export const CWKeyActiveLevelSchema = z.enum(['high', 'low']);
|
|
10
|
+
export type CWKeyActiveLevel = z.infer<typeof CWKeyActiveLevelSchema>;
|
|
11
|
+
|
|
9
12
|
export const CWKeyerConfigSchema = z.object({
|
|
10
13
|
/** CW 发报后端:cat=Hamlib 整报文,serial=DTR/RTS 时序键控 */
|
|
11
14
|
backend: CWKeyerBackendSchema.default('cat'),
|
|
@@ -13,6 +16,8 @@ export const CWKeyerConfigSchema = z.object({
|
|
|
13
16
|
keyPort: z.string(),
|
|
14
17
|
/** CW 键控引脚类型 */
|
|
15
18
|
keyMethod: z.enum(['dtr', 'rts']),
|
|
19
|
+
/** CW 键控有效电平:high=高电平按下,low=低电平按下 */
|
|
20
|
+
keyActiveLevel: CWKeyActiveLevelSchema.default('high'),
|
|
16
21
|
/** 莫尔斯码速度 (WPM, 5-60) */
|
|
17
22
|
wpm: z.number().int().min(5).max(60).default(20),
|
|
18
23
|
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const DiagnosticLogSourceIdSchema = z.enum(['server', 'electron-main', 'client-tools']);
|
|
4
|
+
export type DiagnosticLogSourceId = z.infer<typeof DiagnosticLogSourceIdSchema>;
|
|
5
|
+
|
|
6
|
+
export const DiagnosticLogSourceSchema = z.object({
|
|
7
|
+
id: DiagnosticLogSourceIdSchema,
|
|
8
|
+
fileName: z.string().min(1),
|
|
9
|
+
fileCount: z.number().int().positive(),
|
|
10
|
+
totalBytes: z.number().int().nonnegative(),
|
|
11
|
+
availableFromMs: z.number().int().positive().nullable(),
|
|
12
|
+
availableToMs: z.number().int().positive().nullable(),
|
|
13
|
+
});
|
|
14
|
+
export type DiagnosticLogSource = z.infer<typeof DiagnosticLogSourceSchema>;
|
|
15
|
+
|
|
16
|
+
export const DiagnosticLogSourcesResponseSchema = z.object({
|
|
17
|
+
sources: z.array(DiagnosticLogSourceSchema),
|
|
18
|
+
limits: z.object({
|
|
19
|
+
maxRangeMs: z.number().int().positive(),
|
|
20
|
+
maxUncompressedBytes: z.number().int().positive(),
|
|
21
|
+
maxCompressedBytes: z.number().int().positive(),
|
|
22
|
+
feedbackMaxCharacters: z.number().int().positive(),
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
export type DiagnosticLogSourcesResponse = z.infer<typeof DiagnosticLogSourcesResponseSchema>;
|
|
26
|
+
|
|
27
|
+
export const CreateDiagnosticUploadRequestSchema = z.object({
|
|
28
|
+
sourceId: DiagnosticLogSourceIdSchema,
|
|
29
|
+
fromMs: z.number().int().positive(),
|
|
30
|
+
toMs: z.number().int().positive(),
|
|
31
|
+
feedback: z.string().trim().max(2000).optional(),
|
|
32
|
+
}).strict().superRefine((value, context) => {
|
|
33
|
+
if (value.toMs <= value.fromMs) {
|
|
34
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['toMs'], message: 'toMs must be later than fromMs' });
|
|
35
|
+
}
|
|
36
|
+
if (value.toMs - value.fromMs > 7 * 24 * 60 * 60 * 1000) {
|
|
37
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['toMs'], message: 'time range exceeds seven days' });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
export type CreateDiagnosticUploadRequest = z.infer<typeof CreateDiagnosticUploadRequestSchema>;
|
|
41
|
+
|
|
42
|
+
export const DiagnosticUploadReceiptSchema = z.object({
|
|
43
|
+
uploadId: z.string().uuid(),
|
|
44
|
+
sourceId: DiagnosticLogSourceIdSchema,
|
|
45
|
+
requestedFromMs: z.number().int().positive(),
|
|
46
|
+
requestedToMs: z.number().int().positive(),
|
|
47
|
+
includedFromMs: z.number().int().positive(),
|
|
48
|
+
includedToMs: z.number().int().positive(),
|
|
49
|
+
lineCount: z.number().int().positive(),
|
|
50
|
+
uncompressedBytes: z.number().int().positive(),
|
|
51
|
+
compressedBytes: z.number().int().positive(),
|
|
52
|
+
acceptedAt: z.string().datetime(),
|
|
53
|
+
retainedUntil: z.string().datetime(),
|
|
54
|
+
});
|
|
55
|
+
export type DiagnosticUploadReceipt = z.infer<typeof DiagnosticUploadReceiptSchema>;
|
package/src/schema/ft8.schema.ts
CHANGED
|
@@ -276,6 +276,9 @@ export const FT8MessageSchema = z.discriminatedUnion('type', [
|
|
|
276
276
|
* This is the main plugin-facing FT8 payload. It combines RF metrics from the
|
|
277
277
|
* decoder (`snr`, `dt`, `df`), the original unparsed text (`rawMessage`), the
|
|
278
278
|
* normalized semantic form (`message`) and optional logbook enrichment.
|
|
279
|
+
* `snr` is dB, `dt` is seconds from the expected decode timing, `df` is audio
|
|
280
|
+
* offset in hertz, and `timestamp` is Unix epoch milliseconds. `slotId` ties
|
|
281
|
+
* the decode back to its `SlotInfo`/`SlotPack`.
|
|
279
282
|
*/
|
|
280
283
|
export const ParsedFT8MessageSchema = z.object({
|
|
281
284
|
snr: z.number(),
|
|
@@ -285,6 +288,11 @@ export const ParsedFT8MessageSchema = z.object({
|
|
|
285
288
|
message: FT8MessageSchema,
|
|
286
289
|
slotId: z.string(),
|
|
287
290
|
timestamp: z.number(),
|
|
291
|
+
/**
|
|
292
|
+
* 标记该消息为 WSJT-X 部分解码(含 `<...>` 未解码呼号占位符)。
|
|
293
|
+
* 部分解码消息不得作为自动呼叫/回复目标,仅供监控与防御使用。
|
|
294
|
+
*/
|
|
295
|
+
isPartialDecode: z.boolean().optional(),
|
|
288
296
|
logbookAnalysis: LogbookAnalysisSchema.optional(),
|
|
289
297
|
});
|
|
290
298
|
|