tirecheck-device-sdk 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -62,12 +62,49 @@ implementation so that test passes.
62
62
  Focus on one small improvement at a time - one failing test, then make it pass, then another failing test, etc. Mentally
63
63
  this approach is much easier because you don't need to think about system as a whole
64
64
 
65
+ ### Local testing in app
66
+
67
+ To test the library in your application, without publishing them to npm, please, run following commands:
68
+
69
+ ```
70
+ // From /Work/tirecheck-device-sdk
71
+ pnpm build
72
+
73
+ // From /Work/my-app
74
+ pnpm link ../tirecheck-device-sdk
75
+ ```
76
+
77
+ This will temporarily ensure that package is taken from your local directory and not from package.json.
78
+
65
79
  ### Conventions
66
80
 
67
81
  - use `deviceMeta` for storing generic device info and methods for processing advertisement for all supported devices
68
82
  - this is to avoid importing full device services before we're connected to them
69
83
  - use `devices/*` for exposed logic related to devices after they're connected. That includes methods `connect` and
70
84
  `disconnect`.
85
+ - For more complicated devices, such as `bridge`, it is useful to create `bridgeCommands` file, that contain _commands_.
86
+ Command = method that accepts human-readable arguments and converts them to _single_ low-level call of `ble` (i.e. it
87
+ just converts human-readable data to binary data and sends them to `ble`).
88
+
89
+ ```
90
+ // bridge.ts - methods from this file are exposed to library users
91
+ import bridgeCommands from './bridgeCommands'
92
+
93
+ export default {
94
+ // You can expose command directly...
95
+ getMeasurement: bridgeCommands.getMeasurement,
96
+
97
+ // Or expose method that calls sequence of commands
98
+ async getVehicleSchema() {
99
+ const axles = await bridgeCommands.getVehicleAxles()
100
+ for(let i = 0; i < axles.length; i++) {
101
+ const tyres = await bridgeCommands.getVehicleTyres(i)
102
+ }
103
+ return { axles, tyres }
104
+ }
105
+ }
106
+ ```
107
+
71
108
  - use `services/*` for logic shared between devices. Those files won't be exposed in the build.
72
109
  - expose only top-level functions. So, expose `bridge.writeConfiguration` or `bridge.writeAxleSetup` instead of generic
73
110
  `bridge.writeMessage`
@@ -96,6 +133,14 @@ export default {
96
133
  function foo() {}
97
134
  ```
98
135
 
136
+ ### Simulator
137
+
138
+ For each supported device, you must provide a simulator. It is important for testing final apps. **Simulator replaces
139
+ high-level calls** - i.e. it works with human-readable data and doesn't need to convert data to binary
140
+
141
+ - For complex devices with `commands` layer, such as bridge example above, we advice to simulate only `commands` layer,
142
+ and leave top-level as is
143
+
99
144
  ### Submitting changes
100
145
 
101
146
  If you wish to include a new change, process is as follows:
@@ -117,6 +162,10 @@ You can contact tirecheck if you need support - admin@tirecheck.com
117
162
 
118
163
  [x] Initial structure
119
164
 
165
+ [x] Simulators
166
+
167
+ [x] Ability to test against real devices
168
+
120
169
  [] Full CAN bridge support
121
170
 
122
171
  [] CAN Bridge Firmware Update support
package/dist/index.cjs CHANGED
@@ -309,19 +309,19 @@ const deviceMeta = {
309
309
 
310
310
  const checkUnreachableDevicesTimeouts = {};
311
311
  const checkConnectedStateIntervals = {};
312
- const deviceAdvertisingCallbacks = [];
313
- const deviceUpdateCallbacks = [];
314
- const deviceUnreachableCallbacks = [];
312
+ let deviceAdvertisingCallback;
313
+ let deviceUpdateCallback;
314
+ let deviceUnreachableCallback;
315
315
  const bluetooth = {
316
316
  /** Triggered when "scanDevices" detects device supported by SDK */
317
- onDeviceAdvertising(deviceAdvertisingCallback) {
318
- deviceAdvertisingCallbacks.push(deviceAdvertisingCallback);
317
+ onDeviceAdvertising(callback) {
318
+ deviceAdvertisingCallback = callback;
319
319
  },
320
- onDeviceUpdate(deviceUpdateCallback) {
321
- deviceUpdateCallbacks.push(deviceUpdateCallback);
320
+ onDeviceUpdate(callback) {
321
+ deviceUpdateCallback = callback;
322
322
  },
323
- onDeviceUnreachable(deviceUnreachableCallback) {
324
- deviceUnreachableCallbacks.push(deviceUnreachableCallback);
323
+ onDeviceUnreachable(callback) {
324
+ deviceUnreachableCallback = callback;
325
325
  },
326
326
  async scanDevices(services = []) {
327
327
  await ble.stopScan();
@@ -339,9 +339,7 @@ const bluetooth = {
339
339
  const processedDevice = processDevice(device);
340
340
  if (!processedDevice)
341
341
  return;
342
- for (const c of deviceAdvertisingCallbacks) {
343
- c(processedDevice);
344
- }
342
+ deviceAdvertisingCallback?.(processedDevice);
345
343
  },
346
344
  (e) => console.error("ble.startScanWithOptions error:", e)
347
345
  );
@@ -392,9 +390,7 @@ function monitorConnectedState(deviceId) {
392
390
  } catch {
393
391
  isConnected = false;
394
392
  }
395
- for (const c of deviceUpdateCallbacks) {
396
- c({ deviceId, isConnected });
397
- }
393
+ deviceUpdateCallback?.({ deviceId, isConnected });
398
394
  }, 1e3);
399
395
  }
400
396
  function refreshUnreachableTimeouts(deviceId) {
@@ -402,9 +398,7 @@ function refreshUnreachableTimeouts(deviceId) {
402
398
  clearTimeout(checkUnreachableDevicesTimeouts[deviceId]);
403
399
  }
404
400
  checkUnreachableDevicesTimeouts[deviceId] = setTimeout(() => {
405
- for (const c of deviceUnreachableCallbacks) {
406
- c(deviceId);
407
- }
401
+ deviceUnreachableCallback?.(deviceId);
408
402
  if (checkConnectedStateIntervals[deviceId]) {
409
403
  clearInterval(checkConnectedStateIntervals[deviceId]);
410
404
  delete checkConnectedStateIntervals[deviceId];
package/dist/index.d.cts CHANGED
@@ -28,6 +28,89 @@ interface PeripheralData {
28
28
  }
29
29
  type PeripheralState = 'disconnected' | 'disconnecting' | 'connecting' | 'connected';
30
30
 
31
+ declare const _default: {
32
+ bridge: {
33
+ nameRegex: RegExp;
34
+ characteristic: {
35
+ serviceId: string;
36
+ characteristicId: string;
37
+ };
38
+ capabilities: never[];
39
+ manufacturerId: number;
40
+ mtu: number;
41
+ getDeviceInfoFromAdvertising: (device: PeripheralData) => BleBridge | undefined;
42
+ };
43
+ bridgeOta: {
44
+ nameRegex: RegExp;
45
+ characteristic: {
46
+ serviceId: string;
47
+ characteristicId: string;
48
+ };
49
+ capabilities: never[];
50
+ getDeviceInfoFromAdvertising: () => void;
51
+ };
52
+ flexiGaugeTpms: {
53
+ nameRegex: RegExp;
54
+ characteristic: {
55
+ serviceId: string;
56
+ characteristicId: string;
57
+ };
58
+ getDeviceInfoFromAdvertising: () => void;
59
+ capabilities: {
60
+ id: string;
61
+ regex: RegExp;
62
+ }[];
63
+ reconnect: boolean;
64
+ };
65
+ pressureStick: {
66
+ nameRegex: RegExp;
67
+ characteristic: {
68
+ serviceId: string;
69
+ characteristicId: string;
70
+ };
71
+ getDeviceInfoFromAdvertising: () => void;
72
+ capabilities: {
73
+ id: string;
74
+ regex: RegExp;
75
+ }[];
76
+ };
77
+ };
78
+
79
+ interface BluetoothDeviceCharacteristic {
80
+ serviceId: string;
81
+ characteristicId: string;
82
+ }
83
+ interface BluetoothDeviceCapability {
84
+ id: string;
85
+ processFn: Function;
86
+ regex: RegExp;
87
+ }
88
+ interface BluetoothDeviceHandler {
89
+ /** Characteristic on which device sends messages, will be subscribed by connect function */
90
+ characteristic: BluetoothDeviceCharacteristic;
91
+ capabilities: BluetoothDeviceCapability[];
92
+ name: string;
93
+ /** Icon to display in bluetooth device list, e.g. "mdi-bluetooth" or "icon-flexigauge" */
94
+ icon: string;
95
+ regex: RegExp;
96
+ /** Used for messages and responses from device */
97
+ processMessage: Function;
98
+ tpmsScan?: Function;
99
+ getPinFn?: Function;
100
+ /** Used to increase/decrease byte count recieved, when library splits messages */
101
+ mtu?: number;
102
+ /** If true application will remember this device and will try to reconnect to it on app launch */
103
+ reconnect?: boolean;
104
+ /** Will be run repeatedly if defined, should return keep alive command, interval, characteristic */
105
+ keepAliveFn?: Function;
106
+ /** Used to get information from device advertising */
107
+ processAdvertising?: Function;
108
+ /** Will be run after successfull connection is established as a part of connect() promise */
109
+ onConnected?: Function;
110
+ /** Will be run after successfull disconnection as a part of disconnect() promise */
111
+ onDisconnected?: Function;
112
+ }
113
+ type BleDeviceType = keyof typeof _default;
31
114
  type BleDevice = BleBridge;
32
115
  interface BleBridge {
33
116
  id: string;
@@ -55,14 +138,14 @@ interface BleBridgeAdvertisingData {
55
138
 
56
139
  declare function createTirecheckDeviceSdk(bleImplementation: BleImplementation): {
57
140
  bluetooth: {
58
- onDeviceAdvertising(deviceAdvertisingCallback: (device: BleDevice) => void): void;
59
- onDeviceUpdate(deviceUpdateCallback: (update: {
141
+ onDeviceAdvertising(callback: (device: BleDevice) => void): void;
142
+ onDeviceUpdate(callback: (update: {
60
143
  deviceId: string;
61
144
  isConnected: boolean;
62
145
  }) => void): void;
63
- onDeviceUnreachable(deviceUnreachableCallback: (deviceId: string) => void): void;
146
+ onDeviceUnreachable(callback: (deviceId: string) => void): void;
64
147
  scanDevices(services?: string[]): Promise<void>;
65
148
  };
66
149
  };
67
150
 
68
- export { createTirecheckDeviceSdk };
151
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleDevice, type BleDeviceType, type BluetoothDeviceCapability, type BluetoothDeviceCharacteristic, type BluetoothDeviceHandler, createTirecheckDeviceSdk };
package/dist/index.d.mts CHANGED
@@ -28,6 +28,89 @@ interface PeripheralData {
28
28
  }
29
29
  type PeripheralState = 'disconnected' | 'disconnecting' | 'connecting' | 'connected';
30
30
 
31
+ declare const _default: {
32
+ bridge: {
33
+ nameRegex: RegExp;
34
+ characteristic: {
35
+ serviceId: string;
36
+ characteristicId: string;
37
+ };
38
+ capabilities: never[];
39
+ manufacturerId: number;
40
+ mtu: number;
41
+ getDeviceInfoFromAdvertising: (device: PeripheralData) => BleBridge | undefined;
42
+ };
43
+ bridgeOta: {
44
+ nameRegex: RegExp;
45
+ characteristic: {
46
+ serviceId: string;
47
+ characteristicId: string;
48
+ };
49
+ capabilities: never[];
50
+ getDeviceInfoFromAdvertising: () => void;
51
+ };
52
+ flexiGaugeTpms: {
53
+ nameRegex: RegExp;
54
+ characteristic: {
55
+ serviceId: string;
56
+ characteristicId: string;
57
+ };
58
+ getDeviceInfoFromAdvertising: () => void;
59
+ capabilities: {
60
+ id: string;
61
+ regex: RegExp;
62
+ }[];
63
+ reconnect: boolean;
64
+ };
65
+ pressureStick: {
66
+ nameRegex: RegExp;
67
+ characteristic: {
68
+ serviceId: string;
69
+ characteristicId: string;
70
+ };
71
+ getDeviceInfoFromAdvertising: () => void;
72
+ capabilities: {
73
+ id: string;
74
+ regex: RegExp;
75
+ }[];
76
+ };
77
+ };
78
+
79
+ interface BluetoothDeviceCharacteristic {
80
+ serviceId: string;
81
+ characteristicId: string;
82
+ }
83
+ interface BluetoothDeviceCapability {
84
+ id: string;
85
+ processFn: Function;
86
+ regex: RegExp;
87
+ }
88
+ interface BluetoothDeviceHandler {
89
+ /** Characteristic on which device sends messages, will be subscribed by connect function */
90
+ characteristic: BluetoothDeviceCharacteristic;
91
+ capabilities: BluetoothDeviceCapability[];
92
+ name: string;
93
+ /** Icon to display in bluetooth device list, e.g. "mdi-bluetooth" or "icon-flexigauge" */
94
+ icon: string;
95
+ regex: RegExp;
96
+ /** Used for messages and responses from device */
97
+ processMessage: Function;
98
+ tpmsScan?: Function;
99
+ getPinFn?: Function;
100
+ /** Used to increase/decrease byte count recieved, when library splits messages */
101
+ mtu?: number;
102
+ /** If true application will remember this device and will try to reconnect to it on app launch */
103
+ reconnect?: boolean;
104
+ /** Will be run repeatedly if defined, should return keep alive command, interval, characteristic */
105
+ keepAliveFn?: Function;
106
+ /** Used to get information from device advertising */
107
+ processAdvertising?: Function;
108
+ /** Will be run after successfull connection is established as a part of connect() promise */
109
+ onConnected?: Function;
110
+ /** Will be run after successfull disconnection as a part of disconnect() promise */
111
+ onDisconnected?: Function;
112
+ }
113
+ type BleDeviceType = keyof typeof _default;
31
114
  type BleDevice = BleBridge;
32
115
  interface BleBridge {
33
116
  id: string;
@@ -55,14 +138,14 @@ interface BleBridgeAdvertisingData {
55
138
 
56
139
  declare function createTirecheckDeviceSdk(bleImplementation: BleImplementation): {
57
140
  bluetooth: {
58
- onDeviceAdvertising(deviceAdvertisingCallback: (device: BleDevice) => void): void;
59
- onDeviceUpdate(deviceUpdateCallback: (update: {
141
+ onDeviceAdvertising(callback: (device: BleDevice) => void): void;
142
+ onDeviceUpdate(callback: (update: {
60
143
  deviceId: string;
61
144
  isConnected: boolean;
62
145
  }) => void): void;
63
- onDeviceUnreachable(deviceUnreachableCallback: (deviceId: string) => void): void;
146
+ onDeviceUnreachable(callback: (deviceId: string) => void): void;
64
147
  scanDevices(services?: string[]): Promise<void>;
65
148
  };
66
149
  };
67
150
 
68
- export { createTirecheckDeviceSdk };
151
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleDevice, type BleDeviceType, type BluetoothDeviceCapability, type BluetoothDeviceCharacteristic, type BluetoothDeviceHandler, createTirecheckDeviceSdk };
package/dist/index.d.ts CHANGED
@@ -28,6 +28,89 @@ interface PeripheralData {
28
28
  }
29
29
  type PeripheralState = 'disconnected' | 'disconnecting' | 'connecting' | 'connected';
30
30
 
31
+ declare const _default: {
32
+ bridge: {
33
+ nameRegex: RegExp;
34
+ characteristic: {
35
+ serviceId: string;
36
+ characteristicId: string;
37
+ };
38
+ capabilities: never[];
39
+ manufacturerId: number;
40
+ mtu: number;
41
+ getDeviceInfoFromAdvertising: (device: PeripheralData) => BleBridge | undefined;
42
+ };
43
+ bridgeOta: {
44
+ nameRegex: RegExp;
45
+ characteristic: {
46
+ serviceId: string;
47
+ characteristicId: string;
48
+ };
49
+ capabilities: never[];
50
+ getDeviceInfoFromAdvertising: () => void;
51
+ };
52
+ flexiGaugeTpms: {
53
+ nameRegex: RegExp;
54
+ characteristic: {
55
+ serviceId: string;
56
+ characteristicId: string;
57
+ };
58
+ getDeviceInfoFromAdvertising: () => void;
59
+ capabilities: {
60
+ id: string;
61
+ regex: RegExp;
62
+ }[];
63
+ reconnect: boolean;
64
+ };
65
+ pressureStick: {
66
+ nameRegex: RegExp;
67
+ characteristic: {
68
+ serviceId: string;
69
+ characteristicId: string;
70
+ };
71
+ getDeviceInfoFromAdvertising: () => void;
72
+ capabilities: {
73
+ id: string;
74
+ regex: RegExp;
75
+ }[];
76
+ };
77
+ };
78
+
79
+ interface BluetoothDeviceCharacteristic {
80
+ serviceId: string;
81
+ characteristicId: string;
82
+ }
83
+ interface BluetoothDeviceCapability {
84
+ id: string;
85
+ processFn: Function;
86
+ regex: RegExp;
87
+ }
88
+ interface BluetoothDeviceHandler {
89
+ /** Characteristic on which device sends messages, will be subscribed by connect function */
90
+ characteristic: BluetoothDeviceCharacteristic;
91
+ capabilities: BluetoothDeviceCapability[];
92
+ name: string;
93
+ /** Icon to display in bluetooth device list, e.g. "mdi-bluetooth" or "icon-flexigauge" */
94
+ icon: string;
95
+ regex: RegExp;
96
+ /** Used for messages and responses from device */
97
+ processMessage: Function;
98
+ tpmsScan?: Function;
99
+ getPinFn?: Function;
100
+ /** Used to increase/decrease byte count recieved, when library splits messages */
101
+ mtu?: number;
102
+ /** If true application will remember this device and will try to reconnect to it on app launch */
103
+ reconnect?: boolean;
104
+ /** Will be run repeatedly if defined, should return keep alive command, interval, characteristic */
105
+ keepAliveFn?: Function;
106
+ /** Used to get information from device advertising */
107
+ processAdvertising?: Function;
108
+ /** Will be run after successfull connection is established as a part of connect() promise */
109
+ onConnected?: Function;
110
+ /** Will be run after successfull disconnection as a part of disconnect() promise */
111
+ onDisconnected?: Function;
112
+ }
113
+ type BleDeviceType = keyof typeof _default;
31
114
  type BleDevice = BleBridge;
32
115
  interface BleBridge {
33
116
  id: string;
@@ -55,14 +138,14 @@ interface BleBridgeAdvertisingData {
55
138
 
56
139
  declare function createTirecheckDeviceSdk(bleImplementation: BleImplementation): {
57
140
  bluetooth: {
58
- onDeviceAdvertising(deviceAdvertisingCallback: (device: BleDevice) => void): void;
59
- onDeviceUpdate(deviceUpdateCallback: (update: {
141
+ onDeviceAdvertising(callback: (device: BleDevice) => void): void;
142
+ onDeviceUpdate(callback: (update: {
60
143
  deviceId: string;
61
144
  isConnected: boolean;
62
145
  }) => void): void;
63
- onDeviceUnreachable(deviceUnreachableCallback: (deviceId: string) => void): void;
146
+ onDeviceUnreachable(callback: (deviceId: string) => void): void;
64
147
  scanDevices(services?: string[]): Promise<void>;
65
148
  };
66
149
  };
67
150
 
68
- export { createTirecheckDeviceSdk };
151
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleDevice, type BleDeviceType, type BluetoothDeviceCapability, type BluetoothDeviceCharacteristic, type BluetoothDeviceHandler, createTirecheckDeviceSdk };
package/dist/index.mjs CHANGED
@@ -303,19 +303,19 @@ const deviceMeta = {
303
303
 
304
304
  const checkUnreachableDevicesTimeouts = {};
305
305
  const checkConnectedStateIntervals = {};
306
- const deviceAdvertisingCallbacks = [];
307
- const deviceUpdateCallbacks = [];
308
- const deviceUnreachableCallbacks = [];
306
+ let deviceAdvertisingCallback;
307
+ let deviceUpdateCallback;
308
+ let deviceUnreachableCallback;
309
309
  const bluetooth = {
310
310
  /** Triggered when "scanDevices" detects device supported by SDK */
311
- onDeviceAdvertising(deviceAdvertisingCallback) {
312
- deviceAdvertisingCallbacks.push(deviceAdvertisingCallback);
311
+ onDeviceAdvertising(callback) {
312
+ deviceAdvertisingCallback = callback;
313
313
  },
314
- onDeviceUpdate(deviceUpdateCallback) {
315
- deviceUpdateCallbacks.push(deviceUpdateCallback);
314
+ onDeviceUpdate(callback) {
315
+ deviceUpdateCallback = callback;
316
316
  },
317
- onDeviceUnreachable(deviceUnreachableCallback) {
318
- deviceUnreachableCallbacks.push(deviceUnreachableCallback);
317
+ onDeviceUnreachable(callback) {
318
+ deviceUnreachableCallback = callback;
319
319
  },
320
320
  async scanDevices(services = []) {
321
321
  await ble.stopScan();
@@ -333,9 +333,7 @@ const bluetooth = {
333
333
  const processedDevice = processDevice(device);
334
334
  if (!processedDevice)
335
335
  return;
336
- for (const c of deviceAdvertisingCallbacks) {
337
- c(processedDevice);
338
- }
336
+ deviceAdvertisingCallback?.(processedDevice);
339
337
  },
340
338
  (e) => console.error("ble.startScanWithOptions error:", e)
341
339
  );
@@ -386,9 +384,7 @@ function monitorConnectedState(deviceId) {
386
384
  } catch {
387
385
  isConnected = false;
388
386
  }
389
- for (const c of deviceUpdateCallbacks) {
390
- c({ deviceId, isConnected });
391
- }
387
+ deviceUpdateCallback?.({ deviceId, isConnected });
392
388
  }, 1e3);
393
389
  }
394
390
  function refreshUnreachableTimeouts(deviceId) {
@@ -396,9 +392,7 @@ function refreshUnreachableTimeouts(deviceId) {
396
392
  clearTimeout(checkUnreachableDevicesTimeouts[deviceId]);
397
393
  }
398
394
  checkUnreachableDevicesTimeouts[deviceId] = setTimeout(() => {
399
- for (const c of deviceUnreachableCallbacks) {
400
- c(deviceId);
401
- }
395
+ deviceUnreachableCallback?.(deviceId);
402
396
  if (checkConnectedStateIntervals[deviceId]) {
403
397
  clearInterval(checkConnectedStateIntervals[deviceId]);
404
398
  delete checkConnectedStateIntervals[deviceId];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirecheck-device-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "SDK for working with various devices produced by Tirecheck via Bluetooth (CAN Bridge, Routers, Sensors, FlexiGauge, PressureStick, etc)",
5
5
  "author": "Leonid Buneev <leonid.buneev@tirecheck.com>",
6
6
  "license": "ISC",
@@ -11,22 +11,42 @@
11
11
  "files": [
12
12
  "dist"
13
13
  ],
14
+ "engines": {
15
+ "node": ">=18"
16
+ },
14
17
  "dependencies": {
15
- "lodash": "^4.17.21"
18
+ "crypto-js": "^4.2.0",
19
+ "lodash": "^4.17.21",
20
+ "uuid": "^10.0.0"
16
21
  },
17
22
  "devDependencies": {
18
23
  "@antfu/eslint-config": "^2.25.1",
24
+ "@types/express": "^4.17.21",
19
25
  "@types/lodash": "^4.17.7",
26
+ "@types/websocket": "^1.0.10",
20
27
  "@vitest/ui": "^2.0.5",
28
+ "chalk": "^5.3.0",
21
29
  "eslint": "^9.9.0",
22
30
  "eslint-plugin-format": "^0.1.2",
23
31
  "eslint-plugin-tyrecheck": "^2.64.0",
32
+ "express": "^4.19.2",
33
+ "express-ws": "^5.0.2",
34
+ "h3": "^1.12.0",
35
+ "ngrok": "5.0.0-beta.2",
36
+ "ts-node": "^10.9.2",
37
+ "typescript": "^5.6.2",
24
38
  "unbuild": "^2.0.0",
25
- "vitest": "^2.0.5"
39
+ "uqr": "^0.1.2",
40
+ "vitest": "^2.0.5",
41
+ "websocket": "^1.0.35"
26
42
  },
27
43
  "scripts": {
28
44
  "test": "vitest --ui",
45
+ "typecheck": "pnpm tsc --noEmit",
29
46
  "dev": "pnpm install && vitest --ui",
47
+ "dev-server-old": "ts-node ./devServer/devServer.ts",
48
+ "dev-server": "npx --yes listhen -w --ws --open ./devServer/devServer.ts",
49
+ "dev-ngrok": "node --loader ts-node/esm ./devServer/ngrok.mts",
30
50
  "build": "unbuild"
31
51
  }
32
52
  }