@voltras/node-sdk 0.1.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 (203) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +272 -0
  3. package/dist/cjs/bluetooth/adapters/base.js +116 -0
  4. package/dist/cjs/bluetooth/adapters/base.js.map +1 -0
  5. package/dist/cjs/bluetooth/adapters/index.js +58 -0
  6. package/dist/cjs/bluetooth/adapters/index.js.map +1 -0
  7. package/dist/cjs/bluetooth/adapters/native.js +473 -0
  8. package/dist/cjs/bluetooth/adapters/native.js.map +1 -0
  9. package/dist/cjs/bluetooth/adapters/node.js +228 -0
  10. package/dist/cjs/bluetooth/adapters/node.js.map +1 -0
  11. package/dist/cjs/bluetooth/adapters/types.js +11 -0
  12. package/dist/cjs/bluetooth/adapters/types.js.map +1 -0
  13. package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js +187 -0
  14. package/dist/cjs/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
  15. package/dist/cjs/bluetooth/adapters/web.js +112 -0
  16. package/dist/cjs/bluetooth/adapters/web.js.map +1 -0
  17. package/dist/cjs/bluetooth/controllers/scanner-controller.js +145 -0
  18. package/dist/cjs/bluetooth/controllers/scanner-controller.js.map +1 -0
  19. package/dist/cjs/bluetooth/index.js +27 -0
  20. package/dist/cjs/bluetooth/index.js.map +1 -0
  21. package/dist/cjs/bluetooth/models/connection.js +68 -0
  22. package/dist/cjs/bluetooth/models/connection.js.map +1 -0
  23. package/dist/cjs/bluetooth/models/device.js +26 -0
  24. package/dist/cjs/bluetooth/models/device.js.map +1 -0
  25. package/dist/cjs/bluetooth/models/environment.js +106 -0
  26. package/dist/cjs/bluetooth/models/environment.js.map +1 -0
  27. package/dist/cjs/errors.js +167 -0
  28. package/dist/cjs/errors.js.map +1 -0
  29. package/dist/cjs/index.js +116 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/cjs/react/hooks.js +262 -0
  32. package/dist/cjs/react/hooks.js.map +1 -0
  33. package/dist/cjs/react/index.js +18 -0
  34. package/dist/cjs/react/index.js.map +1 -0
  35. package/dist/cjs/sdk/index.js +14 -0
  36. package/dist/cjs/sdk/index.js.map +1 -0
  37. package/dist/cjs/sdk/types.js +8 -0
  38. package/dist/cjs/sdk/types.js.map +1 -0
  39. package/dist/cjs/sdk/voltra-client.js +632 -0
  40. package/dist/cjs/sdk/voltra-client.js.map +1 -0
  41. package/dist/cjs/sdk/voltra-manager.js +419 -0
  42. package/dist/cjs/sdk/voltra-manager.js.map +1 -0
  43. package/dist/cjs/shared/index.js +12 -0
  44. package/dist/cjs/shared/index.js.map +1 -0
  45. package/dist/cjs/shared/utils.js +51 -0
  46. package/dist/cjs/shared/utils.js.map +1 -0
  47. package/dist/cjs/voltra/index.js +56 -0
  48. package/dist/cjs/voltra/index.js.map +1 -0
  49. package/dist/cjs/voltra/models/connection.js +68 -0
  50. package/dist/cjs/voltra/models/connection.js.map +1 -0
  51. package/dist/cjs/voltra/models/device-filter.js +28 -0
  52. package/dist/cjs/voltra/models/device-filter.js.map +1 -0
  53. package/dist/cjs/voltra/models/device.js +152 -0
  54. package/dist/cjs/voltra/models/device.js.map +1 -0
  55. package/dist/cjs/voltra/models/telemetry/frame.js +46 -0
  56. package/dist/cjs/voltra/models/telemetry/frame.js.map +1 -0
  57. package/dist/cjs/voltra/models/telemetry/index.js +14 -0
  58. package/dist/cjs/voltra/models/telemetry/index.js.map +1 -0
  59. package/dist/cjs/voltra/protocol/commands.js +230 -0
  60. package/dist/cjs/voltra/protocol/commands.js.map +1 -0
  61. package/dist/cjs/voltra/protocol/constants.js +136 -0
  62. package/dist/cjs/voltra/protocol/constants.js.map +1 -0
  63. package/dist/cjs/voltra/protocol/data/chains.json +830 -0
  64. package/dist/cjs/voltra/protocol/data/eccentric.json +1598 -0
  65. package/dist/cjs/voltra/protocol/data/protocol.json +54 -0
  66. package/dist/cjs/voltra/protocol/data/weights.json +62 -0
  67. package/dist/cjs/voltra/protocol/index.js +25 -0
  68. package/dist/cjs/voltra/protocol/index.js.map +1 -0
  69. package/dist/cjs/voltra/protocol/telemetry-decoder.js +146 -0
  70. package/dist/cjs/voltra/protocol/telemetry-decoder.js.map +1 -0
  71. package/dist/esm/bluetooth/adapters/base.js +112 -0
  72. package/dist/esm/bluetooth/adapters/base.js.map +1 -0
  73. package/dist/esm/bluetooth/adapters/index.js +51 -0
  74. package/dist/esm/bluetooth/adapters/index.js.map +1 -0
  75. package/dist/esm/bluetooth/adapters/native.js +469 -0
  76. package/dist/esm/bluetooth/adapters/native.js.map +1 -0
  77. package/dist/esm/bluetooth/adapters/node.js +191 -0
  78. package/dist/esm/bluetooth/adapters/node.js.map +1 -0
  79. package/dist/esm/bluetooth/adapters/types.js +10 -0
  80. package/dist/esm/bluetooth/adapters/types.js.map +1 -0
  81. package/dist/esm/bluetooth/adapters/web-bluetooth-base.js +183 -0
  82. package/dist/esm/bluetooth/adapters/web-bluetooth-base.js.map +1 -0
  83. package/dist/esm/bluetooth/adapters/web.js +108 -0
  84. package/dist/esm/bluetooth/adapters/web.js.map +1 -0
  85. package/dist/esm/bluetooth/controllers/scanner-controller.js +141 -0
  86. package/dist/esm/bluetooth/controllers/scanner-controller.js.map +1 -0
  87. package/dist/esm/bluetooth/index.js +17 -0
  88. package/dist/esm/bluetooth/index.js.map +1 -0
  89. package/dist/esm/bluetooth/models/connection.js +63 -0
  90. package/dist/esm/bluetooth/models/connection.js.map +1 -0
  91. package/dist/esm/bluetooth/models/device.js +22 -0
  92. package/dist/esm/bluetooth/models/device.js.map +1 -0
  93. package/dist/esm/bluetooth/models/environment.js +101 -0
  94. package/dist/esm/bluetooth/models/environment.js.map +1 -0
  95. package/dist/esm/errors.js +155 -0
  96. package/dist/esm/errors.js.map +1 -0
  97. package/dist/esm/index.js +72 -0
  98. package/dist/esm/index.js.map +1 -0
  99. package/dist/esm/react/hooks.js +257 -0
  100. package/dist/esm/react/hooks.js.map +1 -0
  101. package/dist/esm/react/index.js +12 -0
  102. package/dist/esm/react/index.js.map +1 -0
  103. package/dist/esm/sdk/index.js +9 -0
  104. package/dist/esm/sdk/index.js.map +1 -0
  105. package/dist/esm/sdk/types.js +7 -0
  106. package/dist/esm/sdk/types.js.map +1 -0
  107. package/dist/esm/sdk/voltra-client.js +628 -0
  108. package/dist/esm/sdk/voltra-client.js.map +1 -0
  109. package/dist/esm/sdk/voltra-manager.js +415 -0
  110. package/dist/esm/sdk/voltra-manager.js.map +1 -0
  111. package/dist/esm/shared/index.js +5 -0
  112. package/dist/esm/shared/index.js.map +1 -0
  113. package/dist/esm/shared/utils.js +45 -0
  114. package/dist/esm/shared/utils.js.map +1 -0
  115. package/dist/esm/voltra/index.js +26 -0
  116. package/dist/esm/voltra/index.js.map +1 -0
  117. package/dist/esm/voltra/models/connection.js +63 -0
  118. package/dist/esm/voltra/models/connection.js.map +1 -0
  119. package/dist/esm/voltra/models/device-filter.js +23 -0
  120. package/dist/esm/voltra/models/device-filter.js.map +1 -0
  121. package/dist/esm/voltra/models/device.js +148 -0
  122. package/dist/esm/voltra/models/device.js.map +1 -0
  123. package/dist/esm/voltra/models/telemetry/frame.js +40 -0
  124. package/dist/esm/voltra/models/telemetry/frame.js.map +1 -0
  125. package/dist/esm/voltra/models/telemetry/index.js +7 -0
  126. package/dist/esm/voltra/models/telemetry/index.js.map +1 -0
  127. package/dist/esm/voltra/protocol/commands.js +224 -0
  128. package/dist/esm/voltra/protocol/commands.js.map +1 -0
  129. package/dist/esm/voltra/protocol/constants.js +130 -0
  130. package/dist/esm/voltra/protocol/constants.js.map +1 -0
  131. package/dist/esm/voltra/protocol/data/chains.json +830 -0
  132. package/dist/esm/voltra/protocol/data/eccentric.json +1598 -0
  133. package/dist/esm/voltra/protocol/data/protocol.json +54 -0
  134. package/dist/esm/voltra/protocol/data/weights.json +62 -0
  135. package/dist/esm/voltra/protocol/index.js +9 -0
  136. package/dist/esm/voltra/protocol/index.js.map +1 -0
  137. package/dist/esm/voltra/protocol/telemetry-decoder.js +140 -0
  138. package/dist/esm/voltra/protocol/telemetry-decoder.js.map +1 -0
  139. package/dist/types/bluetooth/adapters/base.d.ts +85 -0
  140. package/dist/types/bluetooth/adapters/base.d.ts.map +1 -0
  141. package/dist/types/bluetooth/adapters/index.d.ts +35 -0
  142. package/dist/types/bluetooth/adapters/index.d.ts.map +1 -0
  143. package/dist/types/bluetooth/adapters/native.d.ts +109 -0
  144. package/dist/types/bluetooth/adapters/native.d.ts.map +1 -0
  145. package/dist/types/bluetooth/adapters/node.d.ts +91 -0
  146. package/dist/types/bluetooth/adapters/node.d.ts.map +1 -0
  147. package/dist/types/bluetooth/adapters/types.d.ts +102 -0
  148. package/dist/types/bluetooth/adapters/types.d.ts.map +1 -0
  149. package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts +90 -0
  150. package/dist/types/bluetooth/adapters/web-bluetooth-base.d.ts.map +1 -0
  151. package/dist/types/bluetooth/adapters/web.d.ts +57 -0
  152. package/dist/types/bluetooth/adapters/web.d.ts.map +1 -0
  153. package/dist/types/bluetooth/controllers/scanner-controller.d.ts +93 -0
  154. package/dist/types/bluetooth/controllers/scanner-controller.d.ts.map +1 -0
  155. package/dist/types/bluetooth/index.d.ts +14 -0
  156. package/dist/types/bluetooth/index.d.ts.map +1 -0
  157. package/dist/types/bluetooth/models/connection.d.ts +37 -0
  158. package/dist/types/bluetooth/models/connection.d.ts.map +1 -0
  159. package/dist/types/bluetooth/models/device.d.ts +25 -0
  160. package/dist/types/bluetooth/models/device.d.ts.map +1 -0
  161. package/dist/types/bluetooth/models/environment.d.ts +45 -0
  162. package/dist/types/bluetooth/models/environment.d.ts.map +1 -0
  163. package/dist/types/errors.d.ts +113 -0
  164. package/dist/types/errors.d.ts.map +1 -0
  165. package/dist/types/index.d.ts +55 -0
  166. package/dist/types/index.d.ts.map +1 -0
  167. package/dist/types/react/hooks.d.ts +130 -0
  168. package/dist/types/react/hooks.d.ts.map +1 -0
  169. package/dist/types/react/index.d.ts +12 -0
  170. package/dist/types/react/index.d.ts.map +1 -0
  171. package/dist/types/sdk/index.d.ts +11 -0
  172. package/dist/types/sdk/index.d.ts.map +1 -0
  173. package/dist/types/sdk/types.d.ts +104 -0
  174. package/dist/types/sdk/types.d.ts.map +1 -0
  175. package/dist/types/sdk/voltra-client.d.ts +221 -0
  176. package/dist/types/sdk/voltra-client.d.ts.map +1 -0
  177. package/dist/types/sdk/voltra-manager.d.ts +226 -0
  178. package/dist/types/sdk/voltra-manager.d.ts.map +1 -0
  179. package/dist/types/shared/index.d.ts +5 -0
  180. package/dist/types/shared/index.d.ts.map +1 -0
  181. package/dist/types/shared/utils.d.ts +25 -0
  182. package/dist/types/shared/utils.d.ts.map +1 -0
  183. package/dist/types/voltra/index.d.ts +13 -0
  184. package/dist/types/voltra/index.d.ts.map +1 -0
  185. package/dist/types/voltra/models/connection.d.ts +37 -0
  186. package/dist/types/voltra/models/connection.d.ts.map +1 -0
  187. package/dist/types/voltra/models/device-filter.d.ts +19 -0
  188. package/dist/types/voltra/models/device-filter.d.ts.map +1 -0
  189. package/dist/types/voltra/models/device.d.ts +105 -0
  190. package/dist/types/voltra/models/device.d.ts.map +1 -0
  191. package/dist/types/voltra/models/telemetry/frame.d.ts +41 -0
  192. package/dist/types/voltra/models/telemetry/frame.d.ts.map +1 -0
  193. package/dist/types/voltra/models/telemetry/index.d.ts +8 -0
  194. package/dist/types/voltra/models/telemetry/index.d.ts.map +1 -0
  195. package/dist/types/voltra/protocol/commands.d.ts +99 -0
  196. package/dist/types/voltra/protocol/commands.d.ts.map +1 -0
  197. package/dist/types/voltra/protocol/constants.d.ts +103 -0
  198. package/dist/types/voltra/protocol/constants.d.ts.map +1 -0
  199. package/dist/types/voltra/protocol/index.d.ts +9 -0
  200. package/dist/types/voltra/protocol/index.d.ts.map +1 -0
  201. package/dist/types/voltra/protocol/telemetry-decoder.d.ts +45 -0
  202. package/dist/types/voltra/protocol/telemetry-decoder.d.ts.map +1 -0
  203. package/package.json +111 -0
@@ -0,0 +1,628 @@
1
+ /**
2
+ * VoltraClient
3
+ *
4
+ * High-level API for connecting to and controlling a single Voltra device.
5
+ * Handles connection lifecycle, authentication, device settings, and telemetry.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { VoltraClient, WebBLEAdapter, BLE } from '@voltras/node-sdk';
10
+ *
11
+ * const adapter = new WebBLEAdapter({ ble: BLE });
12
+ * const client = new VoltraClient({ adapter });
13
+ *
14
+ * // Connect to device
15
+ * const devices = await client.scan();
16
+ * await client.connect(devices[0]);
17
+ *
18
+ * // Configure settings
19
+ * await client.setWeight(50);
20
+ *
21
+ * // Listen for telemetry
22
+ * client.onFrame((frame) => {
23
+ * console.log('Position:', frame.position, 'Velocity:', frame.velocity);
24
+ * });
25
+ *
26
+ * // Start recording
27
+ * await client.startRecording();
28
+ * // ... workout ...
29
+ * await client.stopRecording();
30
+ *
31
+ * // Cleanup
32
+ * client.dispose();
33
+ * ```
34
+ */
35
+ import { isValidVoltraTransition } from '../voltra/models/connection';
36
+ import { filterVoltraDevices } from '../voltra/models/device-filter';
37
+ import { Auth, Init, Timing, Workout } from '../voltra/protocol/constants';
38
+ import { WeightCommands, ChainsCommands, EccentricCommands } from '../voltra/protocol/commands';
39
+ import { decodeNotification } from '../voltra/protocol/telemetry-decoder';
40
+ import { delay } from '../shared/utils';
41
+ import { ConnectionError, AuthenticationError, NotConnectedError, InvalidSettingError, CommandError, TimeoutError, ErrorCode, } from '../errors';
42
+ /**
43
+ * Default client options.
44
+ */
45
+ const DEFAULT_OPTIONS = {
46
+ autoReconnect: false,
47
+ maxReconnectAttempts: 3,
48
+ reconnectDelayMs: 1000,
49
+ };
50
+ /**
51
+ * Default device settings.
52
+ */
53
+ const DEFAULT_SETTINGS = {
54
+ weight: 0,
55
+ chains: 0,
56
+ eccentric: 0,
57
+ };
58
+ /**
59
+ * High-level client for connecting to and controlling a Voltra device.
60
+ */
61
+ export class VoltraClient {
62
+ constructor(options = {}) {
63
+ // State
64
+ this._connectionState = 'disconnected';
65
+ this._connectedDeviceId = null;
66
+ this._connectedDeviceName = null;
67
+ this._settings = { ...DEFAULT_SETTINGS };
68
+ this._recordingState = 'idle';
69
+ this._isReconnecting = false;
70
+ this._reconnectAttempt = 0;
71
+ this._error = null;
72
+ this._lastConnectedDevice = null;
73
+ // Notification handling
74
+ this.notificationUnsubscribe = null;
75
+ // Event listeners
76
+ this.listeners = new Set();
77
+ this.frameListeners = new Set();
78
+ // Disposed flag
79
+ this.disposed = false;
80
+ this.options = { ...DEFAULT_OPTIONS, ...options };
81
+ this.adapter = options.adapter ?? null;
82
+ }
83
+ // ===========================================================================
84
+ // Public Getters
85
+ // ===========================================================================
86
+ /**
87
+ * Get current connection state.
88
+ */
89
+ get connectionState() {
90
+ return this._connectionState;
91
+ }
92
+ /**
93
+ * Check if connected to a device.
94
+ */
95
+ get isConnected() {
96
+ return this._connectionState === 'connected';
97
+ }
98
+ /**
99
+ * Check if currently reconnecting.
100
+ */
101
+ get isReconnecting() {
102
+ return this._isReconnecting;
103
+ }
104
+ /**
105
+ * Get connected device ID.
106
+ */
107
+ get connectedDeviceId() {
108
+ return this._connectedDeviceId;
109
+ }
110
+ /**
111
+ * Get connected device name.
112
+ */
113
+ get connectedDeviceName() {
114
+ return this._connectedDeviceName;
115
+ }
116
+ /**
117
+ * Get current device settings.
118
+ */
119
+ get settings() {
120
+ return { ...this._settings };
121
+ }
122
+ /**
123
+ * Get current recording state.
124
+ */
125
+ get recordingState() {
126
+ return this._recordingState;
127
+ }
128
+ /**
129
+ * Check if currently recording.
130
+ */
131
+ get isRecording() {
132
+ return this._recordingState === 'active';
133
+ }
134
+ /**
135
+ * Get last error.
136
+ */
137
+ get error() {
138
+ return this._error;
139
+ }
140
+ /**
141
+ * Get full state snapshot.
142
+ */
143
+ get state() {
144
+ return {
145
+ connectionState: this._connectionState,
146
+ isConnected: this.isConnected,
147
+ isReconnecting: this._isReconnecting,
148
+ connectedDeviceId: this._connectedDeviceId,
149
+ connectedDeviceName: this._connectedDeviceName,
150
+ settings: { ...this._settings },
151
+ recordingState: this._recordingState,
152
+ isRecording: this.isRecording,
153
+ error: this._error,
154
+ };
155
+ }
156
+ // ===========================================================================
157
+ // Adapter Management
158
+ // ===========================================================================
159
+ /**
160
+ * Set the BLE adapter to use.
161
+ * Must be called before connect() if not provided in constructor.
162
+ */
163
+ setAdapter(adapter) {
164
+ this.ensureNotDisposed();
165
+ if (this.isConnected) {
166
+ throw new Error('Cannot change adapter while connected');
167
+ }
168
+ this.adapter = adapter;
169
+ }
170
+ /**
171
+ * Get the current adapter.
172
+ */
173
+ getAdapter() {
174
+ return this.adapter;
175
+ }
176
+ // ===========================================================================
177
+ // Discovery
178
+ // ===========================================================================
179
+ /**
180
+ * Scan for Voltra devices.
181
+ *
182
+ * Note: In browser environments, this triggers the Web Bluetooth device picker.
183
+ * The returned array will contain only the user-selected device.
184
+ *
185
+ * @param options Scan options
186
+ * @returns Array of discovered Voltra devices
187
+ */
188
+ async scan(options = {}) {
189
+ this.ensureNotDisposed();
190
+ this.ensureAdapter();
191
+ const { timeout = 10000, filterVoltra = true } = options;
192
+ const devices = await this.adapter.scan(timeout);
193
+ return filterVoltra ? filterVoltraDevices(devices) : devices;
194
+ }
195
+ // ===========================================================================
196
+ // Connection
197
+ // ===========================================================================
198
+ /**
199
+ * Connect to a Voltra device.
200
+ * Handles BLE connection, authentication, and initialization.
201
+ *
202
+ * @param device Device to connect to
203
+ */
204
+ async connect(device) {
205
+ this.ensureNotDisposed();
206
+ this.ensureAdapter();
207
+ if (this.isConnected) {
208
+ throw new ConnectionError('Already connected to a device', ErrorCode.ALREADY_CONNECTED);
209
+ }
210
+ this._error = null;
211
+ this._lastConnectedDevice = device;
212
+ try {
213
+ // Connect
214
+ this.setConnectionState('connecting');
215
+ await this.adapter.connect(device.id);
216
+ // Setup notification handler before auth
217
+ this.setupNotificationHandler();
218
+ // Authenticate
219
+ this.setConnectionState('authenticating');
220
+ await this.authenticate();
221
+ // Initialize
222
+ await this.initialize();
223
+ // Success
224
+ this._connectedDeviceId = device.id;
225
+ this._connectedDeviceName = device.name ?? null;
226
+ this._settings = { ...DEFAULT_SETTINGS };
227
+ this.setConnectionState('connected');
228
+ this.emit({ type: 'connected', deviceId: device.id, deviceName: device.name ?? null });
229
+ // Setup disconnect handler for auto-reconnect
230
+ this.setupDisconnectHandler();
231
+ }
232
+ catch (e) {
233
+ this.cleanup();
234
+ this.setConnectionState('disconnected');
235
+ const error = this.wrapError(e, 'Connection failed');
236
+ this._error = error;
237
+ this.emit({ type: 'error', error });
238
+ throw error;
239
+ }
240
+ }
241
+ /**
242
+ * Disconnect from the current device.
243
+ */
244
+ async disconnect() {
245
+ if (!this._connectedDeviceId) {
246
+ return;
247
+ }
248
+ const deviceId = this._connectedDeviceId;
249
+ try {
250
+ // Stop recording if active
251
+ if (this._recordingState !== 'idle') {
252
+ await this.stopRecording().catch(() => { });
253
+ }
254
+ await this.adapter?.disconnect();
255
+ }
256
+ catch (e) {
257
+ console.warn('[VoltraClient] Disconnect error:', e);
258
+ }
259
+ this.cleanup();
260
+ this.setConnectionState('disconnected');
261
+ this.emit({ type: 'disconnected', deviceId });
262
+ }
263
+ // ===========================================================================
264
+ // Device Settings
265
+ // ===========================================================================
266
+ /**
267
+ * Set weight in pounds.
268
+ *
269
+ * @param lbs Weight (5-200 in increments of 5)
270
+ */
271
+ async setWeight(lbs) {
272
+ this.ensureConnected();
273
+ const cmd = WeightCommands.get(lbs);
274
+ if (!cmd) {
275
+ throw new InvalidSettingError('weight', lbs, WeightCommands.getAvailable());
276
+ }
277
+ try {
278
+ await this.adapter.write(cmd);
279
+ this._settings.weight = lbs;
280
+ }
281
+ catch (e) {
282
+ throw new CommandError(`Failed to set weight: ${this.getErrorMessage(e)}`, 'setWeight');
283
+ }
284
+ }
285
+ /**
286
+ * Set chains (reverse resistance) in pounds.
287
+ *
288
+ * @param lbs Chains weight (0-100)
289
+ */
290
+ async setChains(lbs) {
291
+ this.ensureConnected();
292
+ const cmds = ChainsCommands.get(lbs);
293
+ if (!cmds) {
294
+ throw new InvalidSettingError('chains', lbs, ChainsCommands.getAvailable());
295
+ }
296
+ try {
297
+ await this.adapter.write(cmds.step1);
298
+ await delay(Timing.DUAL_COMMAND_DELAY_MS);
299
+ await this.adapter.write(cmds.step2);
300
+ this._settings.chains = lbs;
301
+ }
302
+ catch (e) {
303
+ throw new CommandError(`Failed to set chains: ${this.getErrorMessage(e)}`, 'setChains');
304
+ }
305
+ }
306
+ /**
307
+ * Set eccentric load adjustment.
308
+ *
309
+ * @param percent Eccentric adjustment (-195 to +195)
310
+ */
311
+ async setEccentric(percent) {
312
+ this.ensureConnected();
313
+ const cmds = EccentricCommands.get(percent);
314
+ if (!cmds) {
315
+ throw new InvalidSettingError('eccentric', percent, EccentricCommands.getAvailable());
316
+ }
317
+ try {
318
+ await this.adapter.write(cmds.step1);
319
+ await delay(Timing.DUAL_COMMAND_DELAY_MS);
320
+ await this.adapter.write(cmds.step2);
321
+ this._settings.eccentric = percent;
322
+ }
323
+ catch (e) {
324
+ throw new CommandError(`Failed to set eccentric: ${this.getErrorMessage(e)}`, 'setEccentric');
325
+ }
326
+ }
327
+ /**
328
+ * Get available weight values.
329
+ */
330
+ getAvailableWeights() {
331
+ return WeightCommands.getAvailable();
332
+ }
333
+ /**
334
+ * Get available chains values.
335
+ */
336
+ getAvailableChains() {
337
+ return ChainsCommands.getAvailable();
338
+ }
339
+ /**
340
+ * Get available eccentric values.
341
+ */
342
+ getAvailableEccentric() {
343
+ return EccentricCommands.getAvailable();
344
+ }
345
+ // ===========================================================================
346
+ // Recording
347
+ // ===========================================================================
348
+ /**
349
+ * Prepare for recording (sends PREPARE + SETUP commands).
350
+ * Call this before starting a set to minimize latency.
351
+ */
352
+ async prepareRecording() {
353
+ this.ensureConnected();
354
+ try {
355
+ this.setRecordingState('preparing');
356
+ await this.adapter.write(Workout.PREPARE);
357
+ await delay(200);
358
+ await this.adapter.write(Workout.SETUP);
359
+ await delay(300);
360
+ this.setRecordingState('ready');
361
+ }
362
+ catch (e) {
363
+ this.setRecordingState('idle');
364
+ throw new CommandError(`Failed to prepare: ${this.getErrorMessage(e)}`, 'prepareRecording');
365
+ }
366
+ }
367
+ /**
368
+ * Start recording (engage motor).
369
+ * If not prepared, will prepare first.
370
+ */
371
+ async startRecording() {
372
+ this.ensureConnected();
373
+ // Prepare if not ready
374
+ if (this._recordingState !== 'ready') {
375
+ await this.prepareRecording();
376
+ }
377
+ try {
378
+ await this.adapter.write(Workout.GO);
379
+ this.setRecordingState('active');
380
+ }
381
+ catch (e) {
382
+ throw new CommandError(`Failed to start: ${this.getErrorMessage(e)}`, 'startRecording');
383
+ }
384
+ }
385
+ /**
386
+ * Stop recording (disengage motor and exit workout mode).
387
+ */
388
+ async stopRecording() {
389
+ if (this._recordingState === 'idle') {
390
+ return;
391
+ }
392
+ this.setRecordingState('stopping');
393
+ try {
394
+ if (this.adapter) {
395
+ await this.adapter.write(Workout.STOP);
396
+ }
397
+ }
398
+ catch (e) {
399
+ console.warn('[VoltraClient] Stop error:', e);
400
+ }
401
+ this.setRecordingState('idle');
402
+ }
403
+ /**
404
+ * End the current set but stay in workout mode.
405
+ * Use this between sets when there are more sets to do.
406
+ */
407
+ async endSet() {
408
+ if (this._recordingState !== 'active') {
409
+ return;
410
+ }
411
+ try {
412
+ await this.adapter.write(Workout.STOP);
413
+ this.setRecordingState('ready');
414
+ }
415
+ catch (e) {
416
+ console.warn('[VoltraClient] End set error:', e);
417
+ }
418
+ }
419
+ // ===========================================================================
420
+ // Event Subscriptions
421
+ // ===========================================================================
422
+ /**
423
+ * Subscribe to client events.
424
+ *
425
+ * @param listener Event listener
426
+ * @returns Unsubscribe function
427
+ */
428
+ subscribe(listener) {
429
+ this.listeners.add(listener);
430
+ return () => this.listeners.delete(listener);
431
+ }
432
+ /**
433
+ * Subscribe to telemetry frames.
434
+ * Shorthand for subscribing to 'frame' events.
435
+ *
436
+ * @param listener Frame listener
437
+ * @returns Unsubscribe function
438
+ */
439
+ onFrame(listener) {
440
+ this.frameListeners.add(listener);
441
+ return () => this.frameListeners.delete(listener);
442
+ }
443
+ /**
444
+ * Subscribe to connection state changes.
445
+ *
446
+ * @param listener State listener
447
+ * @returns Unsubscribe function
448
+ */
449
+ onConnectionStateChange(listener) {
450
+ const wrappedListener = (event) => {
451
+ if (event.type === 'connectionStateChanged') {
452
+ listener(event.state);
453
+ }
454
+ };
455
+ this.listeners.add(wrappedListener);
456
+ return () => this.listeners.delete(wrappedListener);
457
+ }
458
+ // ===========================================================================
459
+ // Lifecycle
460
+ // ===========================================================================
461
+ /**
462
+ * Dispose of the client and release all resources.
463
+ * After calling dispose(), the client cannot be used.
464
+ */
465
+ dispose() {
466
+ if (this.disposed) {
467
+ return;
468
+ }
469
+ this.disposed = true;
470
+ // Disconnect if connected
471
+ if (this.isConnected) {
472
+ this.disconnect().catch(() => { });
473
+ }
474
+ // Clear listeners
475
+ this.listeners.clear();
476
+ this.frameListeners.clear();
477
+ // Cleanup
478
+ this.cleanup();
479
+ }
480
+ // ===========================================================================
481
+ // Private Methods
482
+ // ===========================================================================
483
+ async authenticate() {
484
+ try {
485
+ await this.adapter.write(Auth.DEVICE_ID);
486
+ await delay(Timing.AUTH_TIMEOUT_MS);
487
+ }
488
+ catch (e) {
489
+ throw new AuthenticationError(`Authentication failed: ${this.getErrorMessage(e)}`);
490
+ }
491
+ }
492
+ async initialize() {
493
+ try {
494
+ for (const cmd of Init.SEQUENCE) {
495
+ await this.adapter.write(cmd);
496
+ await delay(Timing.INIT_COMMAND_DELAY_MS);
497
+ }
498
+ }
499
+ catch (e) {
500
+ throw new ConnectionError(`Initialization failed: ${this.getErrorMessage(e)}`);
501
+ }
502
+ }
503
+ setupNotificationHandler() {
504
+ if (!this.adapter)
505
+ return;
506
+ const handler = (data) => {
507
+ const result = decodeNotification(data);
508
+ if (!result)
509
+ return;
510
+ if (result.type === 'frame') {
511
+ this.emit({ type: 'frame', frame: result.frame });
512
+ this.frameListeners.forEach((listener) => listener(result.frame));
513
+ }
514
+ };
515
+ this.notificationUnsubscribe = this.adapter.onNotification(handler);
516
+ }
517
+ setupDisconnectHandler() {
518
+ if (!this.adapter || !this.options.autoReconnect)
519
+ return;
520
+ // Monitor connection state
521
+ const checkConnection = this.adapter.onConnectionStateChange?.((state) => {
522
+ if (state === 'disconnected' && this._connectionState === 'connected') {
523
+ this.handleUnexpectedDisconnect();
524
+ }
525
+ });
526
+ // Store for cleanup if the adapter supports it
527
+ if (checkConnection) {
528
+ const originalUnsubscribe = this.notificationUnsubscribe;
529
+ this.notificationUnsubscribe = () => {
530
+ originalUnsubscribe?.();
531
+ checkConnection();
532
+ };
533
+ }
534
+ }
535
+ async handleUnexpectedDisconnect() {
536
+ if (!this.options.autoReconnect || !this._lastConnectedDevice) {
537
+ this.cleanup();
538
+ this.setConnectionState('disconnected');
539
+ this.emit({ type: 'disconnected', deviceId: this._connectedDeviceId ?? 'unknown' });
540
+ return;
541
+ }
542
+ this._isReconnecting = true;
543
+ this._reconnectAttempt = 0;
544
+ while (this._reconnectAttempt < this.options.maxReconnectAttempts) {
545
+ this._reconnectAttempt++;
546
+ this.emit({
547
+ type: 'reconnecting',
548
+ attempt: this._reconnectAttempt,
549
+ maxAttempts: this.options.maxReconnectAttempts,
550
+ });
551
+ try {
552
+ await delay(this.options.reconnectDelayMs);
553
+ await this.connect(this._lastConnectedDevice);
554
+ this._isReconnecting = false;
555
+ return;
556
+ }
557
+ catch {
558
+ // Continue to next attempt
559
+ }
560
+ }
561
+ // Reconnect failed
562
+ this._isReconnecting = false;
563
+ this.cleanup();
564
+ this.setConnectionState('disconnected');
565
+ this.emit({ type: 'disconnected', deviceId: this._connectedDeviceId ?? 'unknown' });
566
+ }
567
+ cleanup() {
568
+ this.notificationUnsubscribe?.();
569
+ this.notificationUnsubscribe = null;
570
+ this._connectedDeviceId = null;
571
+ this._connectedDeviceName = null;
572
+ this._settings = { ...DEFAULT_SETTINGS };
573
+ this._recordingState = 'idle';
574
+ }
575
+ setConnectionState(state) {
576
+ if (!isValidVoltraTransition(this._connectionState, state)) {
577
+ console.warn(`[VoltraClient] Invalid state transition: ${this._connectionState} -> ${state}`);
578
+ }
579
+ this._connectionState = state;
580
+ this.emit({ type: 'connectionStateChanged', state });
581
+ }
582
+ setRecordingState(state) {
583
+ this._recordingState = state;
584
+ this.emit({ type: 'recordingStateChanged', state });
585
+ }
586
+ emit(event) {
587
+ this.listeners.forEach((listener) => {
588
+ try {
589
+ listener(event);
590
+ }
591
+ catch (e) {
592
+ console.error('[VoltraClient] Event listener error:', e);
593
+ }
594
+ });
595
+ }
596
+ ensureNotDisposed() {
597
+ if (this.disposed) {
598
+ throw new Error('Client has been disposed');
599
+ }
600
+ }
601
+ ensureAdapter() {
602
+ if (!this.adapter) {
603
+ throw new Error('No adapter configured. Call setAdapter() or provide adapter in constructor.');
604
+ }
605
+ }
606
+ ensureConnected() {
607
+ this.ensureNotDisposed();
608
+ if (!this.isConnected) {
609
+ throw new NotConnectedError();
610
+ }
611
+ }
612
+ wrapError(e, context) {
613
+ if (e instanceof Error) {
614
+ if (e.message.includes('timeout')) {
615
+ return new TimeoutError(`${context}: ${e.message}`, Timing.AUTH_TIMEOUT_MS, e);
616
+ }
617
+ if (e.message.includes('auth')) {
618
+ return new AuthenticationError(`${context}: ${e.message}`, ErrorCode.AUTH_FAILED, e);
619
+ }
620
+ return new ConnectionError(`${context}: ${e.message}`, ErrorCode.CONNECTION_FAILED, e);
621
+ }
622
+ return new ConnectionError(`${context}: ${String(e)}`);
623
+ }
624
+ getErrorMessage(e) {
625
+ return e instanceof Error ? e.message : String(e);
626
+ }
627
+ }
628
+ //# sourceMappingURL=voltra-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voltra-client.js","sourceRoot":"","sources":["../../../src/sdk/voltra-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAMH,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACZ,SAAS,GACV,MAAM,WAAW,CAAC;AAUnB;;GAEG;AACH,MAAM,eAAe,GAAmD;IACtE,aAAa,EAAE,KAAK;IACpB,oBAAoB,EAAE,CAAC;IACvB,gBAAgB,EAAE,IAAI;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,gBAAgB,GAAyB;IAC7C,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,CAAC;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,YAAY;IA4BvB,YAAY,UAA+B,EAAE;QArB7C,QAAQ;QACA,qBAAgB,GAA0B,cAAc,CAAC;QACzD,uBAAkB,GAAkB,IAAI,CAAC;QACzC,yBAAoB,GAAkB,IAAI,CAAC;QAC3C,cAAS,GAAyB,EAAE,GAAG,gBAAgB,EAAE,CAAC;QAC1D,oBAAe,GAAyB,MAAM,CAAC;QAC/C,oBAAe,GAAG,KAAK,CAAC;QACxB,sBAAiB,GAAG,CAAC,CAAC;QACtB,WAAM,GAAiB,IAAI,CAAC;QAC5B,yBAAoB,GAA4B,IAAI,CAAC;QAE7D,wBAAwB;QAChB,4BAAuB,GAAwB,IAAI,CAAC;QAE5D,kBAAkB;QACV,cAAS,GAAmC,IAAI,GAAG,EAAE,CAAC;QACtD,mBAAc,GAAuB,IAAI,GAAG,EAAE,CAAC;QAEvD,gBAAgB;QACR,aAAQ,GAAG,KAAK,CAAC;QAGvB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;QAClD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;IACzC,CAAC;IAED,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E;;OAEG;IACH,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,gBAAgB,KAAK,WAAW,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,IAAI,mBAAmB;QACrB,OAAO,IAAI,CAAC,oBAAoB,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,IAAI,KAAK;QACP,OAAO;YACL,eAAe,EAAE,IAAI,CAAC,gBAAgB;YACtC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,iBAAiB,EAAE,IAAI,CAAC,kBAAkB;YAC1C,mBAAmB,EAAE,IAAI,CAAC,oBAAoB;YAC9C,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE;YAC/B,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,KAAK,EAAE,IAAI,CAAC,MAAM;SACnB,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,qBAAqB;IACrB,8EAA8E;IAE9E;;;OAGG;IACH,UAAU,CAAC,OAAmB;QAC5B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAC,UAAuB,EAAE;QAClC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE,YAAY,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;QAEzD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/D,CAAC;IAED,8EAA8E;IAC9E,aAAa;IACb,8EAA8E;IAE9E;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,MAAwB;QACpC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,eAAe,CAAC,+BAA+B,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC1F,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC;QAEnC,IAAI,CAAC;YACH,UAAU;YACV,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;YACtC,MAAM,IAAI,CAAC,OAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAEvC,yCAAyC;YACzC,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAEhC,eAAe;YACf,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;YAC1C,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAE1B,aAAa;YACb,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAExB,UAAU;YACV,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;YAChD,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAC;YACzC,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAErC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YAEvF,8CAA8C;YAC9C,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;YAExC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;YACrD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACpC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC;QAEzC,IAAI,CAAC;YACH,2BAA2B;YAC3B,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;YAED,MAAM,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,CAAC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,GAAW;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,GAAG,EAAE,cAAc,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC;QAC9B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,yBAAyB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,GAAW;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,GAAG,EAAE,cAAc,CAAC,YAAY,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,MAAM,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAC1C,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,GAAG,CAAC;QAC9B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,yBAAyB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAAC,OAAe;QAChC,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,mBAAmB,CAAC,WAAW,EAAE,OAAO,EAAE,iBAAiB,CAAC,YAAY,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,MAAM,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAC1C,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,4BAA4B,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IAED;;OAEG;IACH,mBAAmB;QACjB,OAAO,cAAc,CAAC,YAAY,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,cAAc,CAAC,YAAY,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,OAAO,iBAAiB,CAAC,YAAY,EAAE,CAAC;IAC1C,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;OAGG;IACH,KAAK,CAAC,gBAAgB;QACpB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAEpC,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YACjB,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAEjB,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC/B,MAAM,IAAI,YAAY,CAAC,sBAAsB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,uBAAuB;QACvB,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAChC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,oBAAoB,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE,CAAC;YACpC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAEnC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,sBAAsB;IACtB,8EAA8E;IAE9E;;;;;OAKG;IACH,SAAS,CAAC,QAAmC;QAC3C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,QAAuB;QAC7B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACH,uBAAuB,CAAC,QAAgD;QACtE,MAAM,eAAe,GAA8B,CAAC,KAAK,EAAE,EAAE;YAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;gBAC5C,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACpC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAE9E;;;OAGG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,0BAA0B;QAC1B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAE5B,UAAU;QACV,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAEtE,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,mBAAmB,CAAC,0BAA0B,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,IAAI,CAAC;YACH,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/B,MAAM,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,eAAe,CAAC,0BAA0B,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAEO,wBAAwB;QAC9B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAE1B,MAAM,OAAO,GAAyB,CAAC,IAAI,EAAE,EAAE;YAC7C,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEpB,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;gBAClD,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACtE,CAAC;IAEO,sBAAsB;QAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa;YAAE,OAAO;QAEzD,2BAA2B;QAC3B,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE;YACvE,IAAI,KAAK,KAAK,cAAc,IAAI,IAAI,CAAC,gBAAgB,KAAK,WAAW,EAAE,CAAC;gBACtE,IAAI,CAAC,0BAA0B,EAAE,CAAC;YACpC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,+CAA+C;QAC/C,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,mBAAmB,GAAG,IAAI,CAAC,uBAAuB,CAAC;YACzD,IAAI,CAAC,uBAAuB,GAAG,GAAG,EAAE;gBAClC,mBAAmB,EAAE,EAAE,CAAC;gBACxB,eAAe,EAAE,CAAC;YACpB,CAAC,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,0BAA0B;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,CAAC,kBAAkB,IAAI,SAAS,EAAE,CAAC,CAAC;YACpF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAE3B,OAAO,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC;YAClE,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC;gBACR,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,IAAI,CAAC,iBAAiB;gBAC/B,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,oBAAoB;aAC/C,CAAC,CAAC;YAEH,IAAI,CAAC;gBACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;gBAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAC9C,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;gBAC7B,OAAO;YACT,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,CAAC,kBAAkB,IAAI,SAAS,EAAE,CAAC,CAAC;IACtF,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,uBAAuB,EAAE,EAAE,CAAC;QACjC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;QACpC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAC;QACzC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;IAChC,CAAC;IAEO,kBAAkB,CAAC,KAA4B;QACrD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,4CAA4C,IAAI,CAAC,gBAAgB,OAAO,KAAK,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;IAEO,iBAAiB,CAAC,KAA2B;QACnD,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;IAEO,IAAI,CAAC,KAAwB;QACnC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAClC,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,CAAC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,iBAAiB,EAAE,CAAC;QAChC,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,CAAU,EAAE,OAAe;QAC3C,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,OAAO,IAAI,YAAY,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;YACjF,CAAC;YACD,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,OAAO,IAAI,mBAAmB,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YACvF,CAAC;YACD,OAAO,IAAI,eAAe,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,IAAI,eAAe,CAAC,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAEO,eAAe,CAAC,CAAU;QAChC,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;CACF"}