@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,94 @@
1
+ const GRID_WHITESPACE_REGEX = /\s+/g;
2
+ const FOUR_CHARACTER_GRID_REGEX = /^[A-R]{2}[0-9]{2}$/;
3
+ const TWO_CHARACTER_GRID_REGEX = /^[A-R]{2}$/;
4
+
5
+ export function sanitizeGridInput(grid?: string | null): string {
6
+ if (!grid) {
7
+ return '';
8
+ }
9
+
10
+ return grid.toUpperCase().replace(GRID_WHITESPACE_REGEX, '');
11
+ }
12
+
13
+ export function getFourCharacterGrid(grid?: string | null): string | undefined {
14
+ const normalized = sanitizeGridInput(grid);
15
+ if (normalized.length < 4) {
16
+ return undefined;
17
+ }
18
+
19
+ const fourCharacterGrid = normalized.slice(0, 4);
20
+ return FOUR_CHARACTER_GRID_REGEX.test(fourCharacterGrid) ? fourCharacterGrid : undefined;
21
+ }
22
+
23
+ export function getTwoCharacterGrid(grid?: string | null): string | undefined {
24
+ const normalized = sanitizeGridInput(grid);
25
+ if (normalized.length < 2) {
26
+ return undefined;
27
+ }
28
+
29
+ const twoCharacterGrid = normalized.slice(0, 2);
30
+ return TWO_CHARACTER_GRID_REGEX.test(twoCharacterGrid) ? twoCharacterGrid : undefined;
31
+ }
32
+
33
+ export interface GridBounds {
34
+ lonMin: number;
35
+ lonMax: number;
36
+ latMin: number;
37
+ latMax: number;
38
+ centerLon: number;
39
+ centerLat: number;
40
+ }
41
+
42
+ export function getGridBounds(grid?: string | null): GridBounds | null {
43
+ const normalized = sanitizeGridInput(grid);
44
+ if (normalized.length < 2) {
45
+ return null;
46
+ }
47
+
48
+ const lonField = normalized.charCodeAt(0) - 65;
49
+ const latField = normalized.charCodeAt(1) - 65;
50
+
51
+ if (lonField < 0 || lonField > 17 || latField < 0 || latField > 17) {
52
+ return null;
53
+ }
54
+
55
+ let lonMin = lonField * 20 - 180;
56
+ let lonMax = lonMin + 20;
57
+ let latMin = latField * 10 - 90;
58
+ let latMax = latMin + 10;
59
+
60
+ if (normalized.length >= 4) {
61
+ const lonSquare = Number.parseInt(normalized[2], 10);
62
+ const latSquare = Number.parseInt(normalized[3], 10);
63
+ if (!Number.isFinite(lonSquare) || !Number.isFinite(latSquare)) {
64
+ return null;
65
+ }
66
+
67
+ lonMin += lonSquare * 2;
68
+ lonMax = lonMin + 2;
69
+ latMin += latSquare;
70
+ latMax = latMin + 1;
71
+ }
72
+
73
+ if (normalized.length >= 6) {
74
+ const lonSub = normalized.charCodeAt(4) - 65;
75
+ const latSub = normalized.charCodeAt(5) - 65;
76
+ if (lonSub < 0 || lonSub > 23 || latSub < 0 || latSub > 23) {
77
+ return null;
78
+ }
79
+
80
+ lonMin += lonSub * (2 / 24);
81
+ lonMax = lonMin + (2 / 24);
82
+ latMin += latSub * (1 / 24);
83
+ latMax = latMin + (1 / 24);
84
+ }
85
+
86
+ return {
87
+ lonMin,
88
+ lonMax,
89
+ latMin,
90
+ latMax,
91
+ centerLon: (lonMin + lonMax) / 2,
92
+ centerLat: (latMin + latMax) / 2,
93
+ };
94
+ }
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { MODES, FT4_WINDOW_PRESETS, FT8_WINDOW_PRESETS } from '../src/schema/mode.schema';
3
+
4
+ describe('MODES.FT4 timing constants', () => {
5
+ it('aligns FT4 transmitTiming with WSJT-X standard (T+0.5s signal start)', () => {
6
+ expect(MODES.FT4.transmitTiming).toBe(500);
7
+ });
8
+
9
+ it('keeps FT4 encodeAdvance large enough to finish encode before transmit', () => {
10
+ // FT4 slot is 7.5s; encoder takes 100-200ms. encodeStart must fire BEFORE
11
+ // transmitStart with enough slack for AudioMixer to schedule playback.
12
+ expect(MODES.FT4.encodeAdvance).toBeGreaterThanOrEqual(200);
13
+ expect(MODES.FT4.encodeAdvance).toBeLessThan(MODES.FT4.transmitTiming);
14
+ });
15
+
16
+ it('keeps FT4 windowTiming dual-pass with an early decode', () => {
17
+ expect(MODES.FT4.windowTiming).toEqual([-1500, 0]);
18
+ });
19
+
20
+ it('keeps FT4 slot length at the WSJT-X standard 7.5s', () => {
21
+ expect(MODES.FT4.slotMs).toBe(7500);
22
+ });
23
+ });
24
+
25
+ describe('MODES.FT8 timing constants (regression guard)', () => {
26
+ it('keeps FT8 untouched at WSJT-X standard 500ms / encodeAdvance 0', () => {
27
+ expect(MODES.FT8.transmitTiming).toBe(500);
28
+ expect(MODES.FT8.encodeAdvance).toBe(0);
29
+ expect(MODES.FT8.slotMs).toBe(15000);
30
+ });
31
+
32
+ it('keeps FT8 balanced window preset at WSJT-X 3-pass schedule', () => {
33
+ expect(FT8_WINDOW_PRESETS.balanced).toEqual([-3200, -1500, -300]);
34
+ });
35
+ });
36
+
37
+ describe('FT4_WINDOW_PRESETS', () => {
38
+ it('exposes maximum / balanced / lightweight in monotonically increasing order', () => {
39
+ for (const [preset, timings] of Object.entries(FT4_WINDOW_PRESETS)) {
40
+ const sorted = [...timings].sort((a, b) => a - b);
41
+ expect(timings, `${preset} should be already sorted ascending`).toEqual(sorted);
42
+ }
43
+ });
44
+
45
+ it('balanced preset keeps an early pass so next-cycle encodeStart sees fresh decodes', () => {
46
+ expect(FT4_WINDOW_PRESETS.balanced.some((o) => o < 0)).toBe(true);
47
+ });
48
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../shared-config/tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "noEmit": false
7
+ },
8
+ "include": ["src/**/*"]
9
+ }