@tx5dr/contracts 1.2.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.
Files changed (180) hide show
  1. package/CLAUDE.md +41 -0
  2. package/dist/index.d.ts +55 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +86 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/schema/__tests__/plugin-runtime-log.schema.test.d.ts +2 -0
  7. package/dist/schema/__tests__/plugin-runtime-log.schema.test.d.ts.map +1 -0
  8. package/dist/schema/__tests__/plugin-runtime-log.schema.test.js +78 -0
  9. package/dist/schema/__tests__/plugin-runtime-log.schema.test.js.map +1 -0
  10. package/dist/schema/ability.d.ts +85 -0
  11. package/dist/schema/ability.d.ts.map +1 -0
  12. package/dist/schema/ability.js +119 -0
  13. package/dist/schema/ability.js.map +1 -0
  14. package/dist/schema/api-response.schema.d.ts +1017 -0
  15. package/dist/schema/api-response.schema.d.ts.map +1 -0
  16. package/dist/schema/api-response.schema.js +137 -0
  17. package/dist/schema/api-response.schema.js.map +1 -0
  18. package/dist/schema/audio-sidecar.schema.d.ts +106 -0
  19. package/dist/schema/audio-sidecar.schema.d.ts.map +1 -0
  20. package/dist/schema/audio-sidecar.schema.js +47 -0
  21. package/dist/schema/audio-sidecar.schema.js.map +1 -0
  22. package/dist/schema/audio.schema.d.ts +227 -0
  23. package/dist/schema/audio.schema.d.ts.map +1 -0
  24. package/dist/schema/audio.schema.js +56 -0
  25. package/dist/schema/audio.schema.js.map +1 -0
  26. package/dist/schema/auth.schema.d.ts +738 -0
  27. package/dist/schema/auth.schema.d.ts.map +1 -0
  28. package/dist/schema/auth.schema.js +161 -0
  29. package/dist/schema/auth.schema.js.map +1 -0
  30. package/dist/schema/cycle.schema.d.ts +33 -0
  31. package/dist/schema/cycle.schema.d.ts.map +1 -0
  32. package/dist/schema/cycle.schema.js +23 -0
  33. package/dist/schema/cycle.schema.js.map +1 -0
  34. package/dist/schema/desktop-https.schema.d.ts +146 -0
  35. package/dist/schema/desktop-https.schema.d.ts.map +1 -0
  36. package/dist/schema/desktop-https.schema.js +31 -0
  37. package/dist/schema/desktop-https.schema.js.map +1 -0
  38. package/dist/schema/ft8.schema.d.ts +1107 -0
  39. package/dist/schema/ft8.schema.d.ts.map +1 -0
  40. package/dist/schema/ft8.schema.js +268 -0
  41. package/dist/schema/ft8.schema.js.map +1 -0
  42. package/dist/schema/hello.schema.d.ts +10 -0
  43. package/dist/schema/hello.schema.d.ts.map +1 -0
  44. package/dist/schema/hello.schema.js +5 -0
  45. package/dist/schema/hello.schema.js.map +1 -0
  46. package/dist/schema/logbook.schema.d.ts +1472 -0
  47. package/dist/schema/logbook.schema.d.ts.map +1 -0
  48. package/dist/schema/logbook.schema.js +256 -0
  49. package/dist/schema/logbook.schema.js.map +1 -0
  50. package/dist/schema/mode.schema.d.ts +130 -0
  51. package/dist/schema/mode.schema.d.ts.map +1 -0
  52. package/dist/schema/mode.schema.js +141 -0
  53. package/dist/schema/mode.schema.js.map +1 -0
  54. package/dist/schema/openwebrx.schema.d.ts +352 -0
  55. package/dist/schema/openwebrx.schema.d.ts.map +1 -0
  56. package/dist/schema/openwebrx.schema.js +139 -0
  57. package/dist/schema/openwebrx.schema.js.map +1 -0
  58. package/dist/schema/operator.schema.d.ts +883 -0
  59. package/dist/schema/operator.schema.d.ts.map +1 -0
  60. package/dist/schema/operator.schema.js +97 -0
  61. package/dist/schema/operator.schema.js.map +1 -0
  62. package/dist/schema/plugin.schema.d.ts +1579 -0
  63. package/dist/schema/plugin.schema.d.ts.map +1 -0
  64. package/dist/schema/plugin.schema.js +336 -0
  65. package/dist/schema/plugin.schema.js.map +1 -0
  66. package/dist/schema/process-monitor.schema.d.ts +282 -0
  67. package/dist/schema/process-monitor.schema.d.ts.map +1 -0
  68. package/dist/schema/process-monitor.schema.js +31 -0
  69. package/dist/schema/process-monitor.schema.js.map +1 -0
  70. package/dist/schema/pskreporter.schema.d.ts +185 -0
  71. package/dist/schema/pskreporter.schema.d.ts.map +1 -0
  72. package/dist/schema/pskreporter.schema.js +80 -0
  73. package/dist/schema/pskreporter.schema.js.map +1 -0
  74. package/dist/schema/qso.schema.d.ts +419 -0
  75. package/dist/schema/qso.schema.d.ts.map +1 -0
  76. package/dist/schema/qso.schema.js +137 -0
  77. package/dist/schema/qso.schema.js.map +1 -0
  78. package/dist/schema/radio-capability.schema.d.ts +625 -0
  79. package/dist/schema/radio-capability.schema.d.ts.map +1 -0
  80. package/dist/schema/radio-capability.schema.js +191 -0
  81. package/dist/schema/radio-capability.schema.js.map +1 -0
  82. package/dist/schema/radio-power-support.d.ts +45 -0
  83. package/dist/schema/radio-power-support.d.ts.map +1 -0
  84. package/dist/schema/radio-power-support.js +64 -0
  85. package/dist/schema/radio-power-support.js.map +1 -0
  86. package/dist/schema/radio-power.schema.d.ts +319 -0
  87. package/dist/schema/radio-power.schema.d.ts.map +1 -0
  88. package/dist/schema/radio-power.schema.js +87 -0
  89. package/dist/schema/radio-power.schema.js.map +1 -0
  90. package/dist/schema/radio-profile.schema.d.ts +2694 -0
  91. package/dist/schema/radio-profile.schema.d.ts.map +1 -0
  92. package/dist/schema/radio-profile.schema.js +71 -0
  93. package/dist/schema/radio-profile.schema.js.map +1 -0
  94. package/dist/schema/radio.schema.d.ts +1438 -0
  95. package/dist/schema/radio.schema.d.ts.map +1 -0
  96. package/dist/schema/radio.schema.js +314 -0
  97. package/dist/schema/radio.schema.js.map +1 -0
  98. package/dist/schema/realtime.schema.d.ts +1299 -0
  99. package/dist/schema/realtime.schema.d.ts.map +1 -0
  100. package/dist/schema/realtime.schema.js +184 -0
  101. package/dist/schema/realtime.schema.js.map +1 -0
  102. package/dist/schema/rigctld.schema.d.ts +151 -0
  103. package/dist/schema/rigctld.schema.d.ts.map +1 -0
  104. package/dist/schema/rigctld.schema.js +42 -0
  105. package/dist/schema/rigctld.schema.js.map +1 -0
  106. package/dist/schema/server-message-keys.d.ts +21 -0
  107. package/dist/schema/server-message-keys.d.ts.map +1 -0
  108. package/dist/schema/server-message-keys.js +22 -0
  109. package/dist/schema/server-message-keys.js.map +1 -0
  110. package/dist/schema/slot-info.schema.d.ts +696 -0
  111. package/dist/schema/slot-info.schema.d.ts.map +1 -0
  112. package/dist/schema/slot-info.schema.js +144 -0
  113. package/dist/schema/slot-info.schema.js.map +1 -0
  114. package/dist/schema/spectrum.schema.d.ts +716 -0
  115. package/dist/schema/spectrum.schema.d.ts.map +1 -0
  116. package/dist/schema/spectrum.schema.js +128 -0
  117. package/dist/schema/spectrum.schema.js.map +1 -0
  118. package/dist/schema/station-info.schema.d.ts +202 -0
  119. package/dist/schema/station-info.schema.d.ts.map +1 -0
  120. package/dist/schema/station-info.schema.js +32 -0
  121. package/dist/schema/station-info.schema.js.map +1 -0
  122. package/dist/schema/system.schema.d.ts +113 -0
  123. package/dist/schema/system.schema.d.ts.map +1 -0
  124. package/dist/schema/system.schema.js +95 -0
  125. package/dist/schema/system.schema.js.map +1 -0
  126. package/dist/schema/transmission.schema.d.ts +413 -0
  127. package/dist/schema/transmission.schema.d.ts.map +1 -0
  128. package/dist/schema/transmission.schema.js +78 -0
  129. package/dist/schema/transmission.schema.js.map +1 -0
  130. package/dist/schema/voice.schema.d.ts +38 -0
  131. package/dist/schema/voice.schema.d.ts.map +1 -0
  132. package/dist/schema/voice.schema.js +24 -0
  133. package/dist/schema/voice.schema.js.map +1 -0
  134. package/dist/schema/websocket.schema.d.ts +16916 -0
  135. package/dist/schema/websocket.schema.d.ts.map +1 -0
  136. package/dist/schema/websocket.schema.js +1050 -0
  137. package/dist/schema/websocket.schema.js.map +1 -0
  138. package/dist/utils/grid.d.ts +13 -0
  139. package/dist/utils/grid.d.ts.map +1 -0
  140. package/dist/utils/grid.js +71 -0
  141. package/dist/utils/grid.js.map +1 -0
  142. package/eslint.config.js +15 -0
  143. package/package.json +28 -0
  144. package/src/index.ts +152 -0
  145. package/src/schema/__tests__/plugin-runtime-log.schema.test.ts +90 -0
  146. package/src/schema/ability.ts +205 -0
  147. package/src/schema/api-response.schema.ts +187 -0
  148. package/src/schema/audio-sidecar.schema.ts +53 -0
  149. package/src/schema/audio.schema.ts +73 -0
  150. package/src/schema/auth.schema.ts +224 -0
  151. package/src/schema/cycle.schema.ts +25 -0
  152. package/src/schema/desktop-https.schema.ts +43 -0
  153. package/src/schema/ft8.schema.ts +362 -0
  154. package/src/schema/hello.schema.ts +7 -0
  155. package/src/schema/logbook.schema.ts +310 -0
  156. package/src/schema/mode.schema.ts +158 -0
  157. package/src/schema/openwebrx.schema.ts +160 -0
  158. package/src/schema/operator.schema.ts +112 -0
  159. package/src/schema/plugin.schema.ts +503 -0
  160. package/src/schema/process-monitor.schema.ts +41 -0
  161. package/src/schema/pskreporter.schema.ts +102 -0
  162. package/src/schema/qso.schema.ts +173 -0
  163. package/src/schema/radio-capability.schema.ts +244 -0
  164. package/src/schema/radio-power-support.ts +107 -0
  165. package/src/schema/radio-power.schema.ts +101 -0
  166. package/src/schema/radio-profile.schema.ts +91 -0
  167. package/src/schema/radio.schema.ts +385 -0
  168. package/src/schema/realtime.schema.ts +262 -0
  169. package/src/schema/rigctld.schema.ts +51 -0
  170. package/src/schema/server-message-keys.ts +26 -0
  171. package/src/schema/slot-info.schema.ts +162 -0
  172. package/src/schema/spectrum.schema.ts +166 -0
  173. package/src/schema/station-info.schema.ts +40 -0
  174. package/src/schema/system.schema.ts +121 -0
  175. package/src/schema/transmission.schema.ts +105 -0
  176. package/src/schema/voice.schema.ts +28 -0
  177. package/src/schema/websocket.schema.ts +1480 -0
  178. package/src/utils/grid.ts +94 -0
  179. package/test/mode-schema.test.ts +48 -0
  180. package/tsconfig.json +9 -0
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+
3
+ export const StationQthSchema = z.object({
4
+ /** Maidenhead grid locator, e.g. "PM01" or "PM01RP" */
5
+ grid: z
6
+ .string()
7
+ .regex(/^[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}([0-9]{2})?)?$/, 'Invalid Maidenhead grid locator')
8
+ .transform((s) => s.toUpperCase())
9
+ .optional()
10
+ .or(z.literal('')),
11
+ /** Human-readable location name, e.g. "Haidian, Beijing" */
12
+ location: z.string().max(100).optional(),
13
+ /** Precise latitude entered by the user (overrides grid-derived center) */
14
+ latitude: z.number().min(-90).max(90).optional(),
15
+ /** Precise longitude entered by the user (overrides grid-derived center) */
16
+ longitude: z.number().min(-180).max(180).optional(),
17
+ });
18
+
19
+ export const StationInfoSchema = z.object({
20
+ /** Station display name, e.g. "BG7XXX Remote Station" */
21
+ name: z.string().max(100).optional(),
22
+ /** Owner callsign, e.g. "BG7XXX" */
23
+ callsign: z.string().max(20).optional(),
24
+ /** Markdown-formatted description (antenna, power, radio model, etc.) */
25
+ description: z.string().max(2000).optional(),
26
+ /** Station QTH location */
27
+ qth: StationQthSchema.optional(),
28
+ });
29
+
30
+ export type StationQth = z.infer<typeof StationQthSchema>;
31
+ export type StationInfo = z.infer<typeof StationInfoSchema>;
32
+
33
+ export const UpdateStationInfoRequestSchema = StationInfoSchema;
34
+ export type UpdateStationInfoRequest = StationInfo;
35
+
36
+ export const StationInfoResponseSchema = z.object({
37
+ success: z.boolean(),
38
+ data: StationInfoSchema,
39
+ });
40
+ export type StationInfoResponse = z.infer<typeof StationInfoResponseSchema>;
@@ -0,0 +1,121 @@
1
+ import { z } from 'zod';
2
+
3
+ // ===== 网络信息 =====
4
+
5
+ export const NetworkAddressSchema = z.object({
6
+ ip: z.string(),
7
+ url: z.string(),
8
+ });
9
+
10
+ export type NetworkAddress = z.infer<typeof NetworkAddressSchema>;
11
+
12
+ export const NetworkInfoSchema = z.object({
13
+ addresses: z.array(NetworkAddressSchema),
14
+ hostname: z.string(),
15
+ webPort: z.number(),
16
+ });
17
+
18
+ export type NetworkInfo = z.infer<typeof NetworkInfoSchema>;
19
+
20
+ // ===== 时钟状态 =====
21
+
22
+ export const ClockSyncStateSchema = z.enum(['synced', 'stale', 'never', 'failed']);
23
+ export type ClockSyncState = z.infer<typeof ClockSyncStateSchema>;
24
+
25
+ export const ClockIndicatorStateSchema = z.enum(['ok', 'warn', 'alert', 'stale', 'failed', 'never']);
26
+ export type ClockIndicatorState = z.infer<typeof ClockIndicatorStateSchema>;
27
+
28
+ export const ClockStatusSummarySchema = z.object({
29
+ appliedOffsetMs: z.number(),
30
+ indicatorState: ClockIndicatorStateSchema,
31
+ });
32
+ export type ClockStatusSummary = z.infer<typeof ClockStatusSummarySchema>;
33
+
34
+ export const ClockStatusDetailSchema = ClockStatusSummarySchema.extend({
35
+ measuredOffsetMs: z.number(),
36
+ lastSyncTime: z.number().nullable(),
37
+ syncState: ClockSyncStateSchema,
38
+ serverUsed: z.string().nullable(),
39
+ errorMessage: z.string().nullable(),
40
+ });
41
+ export type ClockStatusDetail = z.infer<typeof ClockStatusDetailSchema>;
42
+
43
+ export const SetClockOffsetRequestSchema = z.object({
44
+ offsetMs: z.number().finite(),
45
+ });
46
+ export type SetClockOffsetRequest = z.infer<typeof SetClockOffsetRequestSchema>;
47
+
48
+ // ===== NTP server list settings =====
49
+
50
+ function isValidIPv4Address(value: string): boolean {
51
+ const parts = value.split('.');
52
+ if (parts.length !== 4) return false;
53
+ return parts.every((part) => {
54
+ if (!/^\d{1,3}$/.test(part)) return false;
55
+ const num = Number(part);
56
+ return Number.isInteger(num) && num >= 0 && num <= 255;
57
+ });
58
+ }
59
+
60
+ function isValidHostname(value: string): boolean {
61
+ if (value === 'localhost') return true;
62
+ if (value.length > 253) return false;
63
+ if (value.startsWith('.') || value.endsWith('.') || value.includes('..')) return false;
64
+ if (!/^[A-Za-z0-9.-]+$/.test(value)) return false;
65
+
66
+ const labels = value.split('.');
67
+ return labels.every((label) => (
68
+ label.length > 0
69
+ && label.length <= 63
70
+ && !label.startsWith('-')
71
+ && !label.endsWith('-')
72
+ && /^[A-Za-z0-9-]+$/.test(label)
73
+ ));
74
+ }
75
+
76
+ export function isValidNtpServerHost(value: string): boolean {
77
+ const trimmed = value.trim();
78
+ if (!trimmed) return false;
79
+ if (
80
+ trimmed.includes('://')
81
+ || trimmed.includes('/')
82
+ || trimmed.includes('?')
83
+ || trimmed.includes('#')
84
+ || trimmed.includes(':')
85
+ || trimmed.includes('[')
86
+ || trimmed.includes(']')
87
+ ) {
88
+ return false;
89
+ }
90
+
91
+ return isValidIPv4Address(trimmed) || isValidHostname(trimmed);
92
+ }
93
+
94
+ export const NtpServerHostSchema = z.string().trim().min(1).refine(isValidNtpServerHost, {
95
+ message: 'Invalid NTP server host',
96
+ });
97
+
98
+ const NtpServerArraySchema = z.array(NtpServerHostSchema).min(1).superRefine((servers, ctx) => {
99
+ const seen = new Set<string>();
100
+ for (const server of servers) {
101
+ if (seen.has(server)) {
102
+ ctx.addIssue({
103
+ code: z.ZodIssueCode.custom,
104
+ message: `Duplicate NTP server: ${server}`,
105
+ });
106
+ return;
107
+ }
108
+ seen.add(server);
109
+ }
110
+ });
111
+
112
+ export const NtpServerListSettingsSchema = z.object({
113
+ servers: NtpServerArraySchema,
114
+ defaultServers: NtpServerArraySchema,
115
+ });
116
+ export type NtpServerListSettings = z.infer<typeof NtpServerListSettingsSchema>;
117
+
118
+ export const UpdateNtpServerListRequestSchema = z.object({
119
+ servers: NtpServerArraySchema,
120
+ });
121
+ export type UpdateNtpServerListRequest = z.infer<typeof UpdateNtpServerListRequestSchema>;
@@ -0,0 +1,105 @@
1
+ import { z } from 'zod';
2
+ import { FrameMessageSchema, SlotInfoSchema } from './slot-info.schema.js';
3
+ // 导入已存在的类型,避免重复定义
4
+ export { StrategiesResultSchema } from './qso.schema.js';
5
+ export type { StrategiesResult } from './qso.schema.js';
6
+ export { CycleInfoSchema } from './cycle.schema.js';
7
+ export type { CycleInfo } from './cycle.schema.js';
8
+
9
+ /**
10
+ * 传输策略相关类型定义
11
+ * 用于操作员运行时状态与插件策略交互
12
+ *
13
+ * 注意:StrategiesResult、CycleInfo 已在其他 schema 中定义,这里重新导出
14
+ */
15
+
16
+ // ========== 策略状态类型 ==========
17
+
18
+ /**
19
+ * 策略状态信息
20
+ */
21
+ export const StrategyStateSchema = z.object({
22
+ name: z.string(), // 策略名称(如 standard-qso)
23
+ state: z.string(), // 当前状态(如 TX1, TX2, IDLE 等)
24
+ availableSlots: z.array(z.string()), // 可用的时隙列表
25
+ metadata: z.record(z.any()).optional(), // 状态的额外信息
26
+ });
27
+
28
+ // ========== 呼叫请求类型 ==========
29
+
30
+ /**
31
+ * 呼叫请求参数
32
+ */
33
+ export const CallRequestSchema = z.object({
34
+ callsign: z.string(), // 目标呼号
35
+ lastMessage: z.object({
36
+ message: FrameMessageSchema,
37
+ slotInfo: SlotInfoSchema,
38
+ }).optional(), // 从目标接收到的最后一条消息
39
+ });
40
+
41
+ // ========== 传输请求类型 ==========
42
+
43
+ /**
44
+ * 传输请求(已在 websocket.schema.ts 中定义)
45
+ * TransmitRequestSchema
46
+ */
47
+
48
+ // ========== 时隙映射类型 ==========
49
+
50
+ /**
51
+ * 操作员时隙配置
52
+ */
53
+ export const OperatorSlotsSchema = z.object({
54
+ TX1: z.string().optional(),
55
+ TX2: z.string().optional(),
56
+ TX3: z.string().optional(),
57
+ TX4: z.string().optional(),
58
+ TX5: z.string().optional(),
59
+ TX6: z.string().optional(),
60
+ });
61
+
62
+ // ========== QSO 上下文类型 (已在 qso.schema.ts 中定义) ==========
63
+
64
+ /**
65
+ * QSO 上下文(已在 qso.schema.ts 中定义为 QSOContextSchema)
66
+ * 包含:myCall, myGrid, targetCall, targetGrid, reportSent, reportReceived 等
67
+ */
68
+
69
+ // ========== 操作员事件数据类型 ==========
70
+
71
+ /**
72
+ * 操作员时隙更新事件数据
73
+ */
74
+ export const OperatorSlotsUpdatedEventSchema = z.object({
75
+ operatorId: z.string(),
76
+ slots: OperatorSlotsSchema,
77
+ });
78
+
79
+ /**
80
+ * 操作员时隙内容变更事件数据
81
+ */
82
+ export const OperatorSlotContentChangedEventSchema = z.object({
83
+ operatorId: z.string(),
84
+ slotName: z.string(),
85
+ content: z.string(),
86
+ });
87
+
88
+ /**
89
+ * 操作员发射周期变更事件数据
90
+ */
91
+ export const OperatorTransmitCyclesChangedEventSchema = z.object({
92
+ operatorId: z.string(),
93
+ transmitCycles: z.array(z.number().min(0).max(1)),
94
+ });
95
+
96
+ // ========== 导出 TypeScript 类型 ==========
97
+
98
+ // StrategiesResult、CycleInfo 已在文件顶部重新导出
99
+
100
+ export type StrategyState = z.infer<typeof StrategyStateSchema>;
101
+ export type CallRequest = z.infer<typeof CallRequestSchema>;
102
+ export type OperatorSlots = z.infer<typeof OperatorSlotsSchema>;
103
+ export type OperatorSlotsUpdatedEvent = z.infer<typeof OperatorSlotsUpdatedEventSchema>;
104
+ export type OperatorSlotContentChangedEvent = z.infer<typeof OperatorSlotContentChangedEventSchema>;
105
+ export type OperatorTransmitCyclesChangedEvent = z.infer<typeof OperatorTransmitCyclesChangedEventSchema>;
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * 语音 PTT 锁状态
5
+ * 语音模式下同一时刻只能有一个用户发射,通过独占锁管理
6
+ */
7
+ export const VoicePTTLockSchema = z.object({
8
+ /** 是否被锁定(有人在发射) */
9
+ locked: z.boolean(),
10
+ /** 持有锁的客户端 ID */
11
+ lockedBy: z.string().nullable(),
12
+ /** 持有锁的用户显示名(token label 或 "Admin") */
13
+ lockedByLabel: z.string().nullable(),
14
+ /** 锁定时间戳 */
15
+ lockedAt: z.number().nullable(),
16
+ /** 超时时间(ms),超时后自动释放 */
17
+ timeoutMs: z.number().default(180000),
18
+ });
19
+
20
+ export type VoicePTTLock = z.infer<typeof VoicePTTLockSchema>;
21
+
22
+ /**
23
+ * 引擎模式枚举
24
+ * digital: FT8/FT4 等数字模式
25
+ * voice: 语音通联模式(SSB/FM/AM)
26
+ */
27
+ export const EngineModeSchema = z.enum(['digital', 'voice']);
28
+ export type EngineMode = z.infer<typeof EngineModeSchema>;