@onekeyfe/hd-transport-electron 1.0.34-alpha.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.
@@ -0,0 +1,54 @@
1
+ import { WebContents } from 'electron';
2
+
3
+ interface BluetoothPairingDetails {
4
+ deviceId: string;
5
+ pairingKind: 'confirm' | 'confirmPin' | 'providePin';
6
+ pin?: string;
7
+ }
8
+ interface BluetoothPairingResponse {
9
+ confirmed: boolean;
10
+ pin?: string;
11
+ }
12
+ interface BluetoothDevice {
13
+ deviceId: string;
14
+ deviceName: string | null;
15
+ }
16
+ interface BleDevice {
17
+ id: string;
18
+ name: string;
19
+ paired?: boolean;
20
+ }
21
+ interface BleEnumerateOptions {
22
+ timeout?: number;
23
+ forceScan?: boolean;
24
+ }
25
+ interface ElectronBleAPI {
26
+ enumerate(options?: BleEnumerateOptions): Promise<BleDevice[]>;
27
+ onBleSelect(callback: (devices: BleDevice[]) => void): () => void;
28
+ selectBleDevice(deviceId: string): void;
29
+ cancelBleRequest(): void;
30
+ onBlePairingRequest(callback: (details: BluetoothPairingDetails) => void): () => void;
31
+ respondToPairing(response: BluetoothPairingResponse): void;
32
+ onBleDeviceDisconnected(callback: (device: {
33
+ id: string;
34
+ name: string | null;
35
+ }) => void): () => void;
36
+ }
37
+ declare const IPC_CHANNELS: {
38
+ readonly BLE_ENUMERATE: "ble-enumerate";
39
+ readonly BLE_ENUMERATE_RESULT: "ble-enumerate-result";
40
+ readonly BLE_SCAN_TIMEOUT: "ble-scan-timeout";
41
+ readonly BLE_SELECT: "ble-select";
42
+ readonly BLE_SELECT_RESULT: "ble-select-result";
43
+ readonly BLE_PAIRING_REQUEST: "ble-pairing-request";
44
+ readonly BLE_PAIRING_RESPONSE: "ble-pairing-response";
45
+ };
46
+ declare global {
47
+ interface Window {
48
+ electronBleAPI: ElectronBleAPI;
49
+ }
50
+ }
51
+
52
+ declare function initElectronBleBridge(webContents: WebContents): void;
53
+
54
+ export { BleDevice, BleEnumerateOptions, BluetoothDevice, BluetoothPairingDetails, BluetoothPairingResponse, ElectronBleAPI, IPC_CHANNELS, initElectronBleBridge };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,UAAU,CAAC;AAGjE,cAAc,SAAS,CAAC;AAmBxB,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,QAmK7D"}
package/dist/index.js ADDED
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var hdShared = require('@onekeyfe/hd-shared');
6
+
7
+ const IPC_CHANNELS = {
8
+ BLE_ENUMERATE: 'ble-enumerate',
9
+ BLE_ENUMERATE_RESULT: 'ble-enumerate-result',
10
+ BLE_SCAN_TIMEOUT: 'ble-scan-timeout',
11
+ BLE_SELECT: 'ble-select',
12
+ BLE_SELECT_RESULT: 'ble-select-result',
13
+ BLE_PAIRING_REQUEST: 'ble-pairing-request',
14
+ BLE_PAIRING_RESPONSE: 'ble-pairing-response',
15
+ };
16
+
17
+ function initElectronBleBridge(webContents) {
18
+ const electron = require('electron');
19
+ const { ipcMain } = electron;
20
+ const logger = require('electron-log');
21
+ const { session } = webContents;
22
+ let selectBluetoothCallback = null;
23
+ let bluetoothPairingCallback = null;
24
+ let preSelectedDeviceId = null;
25
+ let lastLoggedDeviceList = '';
26
+ const logDeviceListIfChanged = (deviceList) => {
27
+ const sortedDevices = [...deviceList].sort((a, b) => a.deviceId.localeCompare(b.deviceId));
28
+ const deviceListString = JSON.stringify(sortedDevices.map(d => ({
29
+ deviceId: d.deviceId,
30
+ deviceName: d.deviceName,
31
+ })));
32
+ if (deviceListString !== lastLoggedDeviceList) {
33
+ logger.info('[Main] Raw device list:', deviceList);
34
+ lastLoggedDeviceList = deviceListString;
35
+ return true;
36
+ }
37
+ return false;
38
+ };
39
+ webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
40
+ event.preventDefault();
41
+ logger.info('[Main] select-bluetooth-device event triggered');
42
+ const deviceListChanged = logDeviceListIfChanged(deviceList);
43
+ if (!deviceListChanged) {
44
+ logger.info('[Main] Device list unchanged, continuing...');
45
+ }
46
+ logger.info('[Main] Pre-selected device:', preSelectedDeviceId);
47
+ selectBluetoothCallback = callback;
48
+ if (!deviceList.length) {
49
+ logger.info('[Main] Empty device list, waiting for more devices...');
50
+ return;
51
+ }
52
+ const filteredDevices = deviceList
53
+ .filter(d => hdShared.isOnekeyDevice(d.deviceName))
54
+ .map(d => ({ id: d.deviceId, name: d.deviceName }));
55
+ if (filteredDevices.length > 0) {
56
+ if (deviceListChanged) {
57
+ logger.info('[Main] Found OneKey devices:', filteredDevices);
58
+ }
59
+ if (preSelectedDeviceId) {
60
+ logger.info('[Main] Set Pre-selected device:', preSelectedDeviceId);
61
+ const targetDevice = filteredDevices.find(d => d.id === preSelectedDeviceId);
62
+ if (targetDevice) {
63
+ logger.info('[Main] Found pre-selected device:', targetDevice);
64
+ callback(targetDevice.id);
65
+ selectBluetoothCallback = null;
66
+ return;
67
+ }
68
+ }
69
+ webContents.send(hdShared.EOneKeyBleMessageKeys.BLE_SELECT, filteredDevices);
70
+ }
71
+ else if (deviceListChanged) {
72
+ logger.info('[Main] No OneKey devices in this batch, continue scanning...');
73
+ }
74
+ });
75
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_PRE_SELECT, (_event, deviceId) => {
76
+ logger.info('[Main] Pre-selecting device:', deviceId);
77
+ preSelectedDeviceId = deviceId;
78
+ lastLoggedDeviceList = '';
79
+ });
80
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_CLEAR_PRE_SELECT, () => {
81
+ logger.info('[Main] Clearing pre-selected device');
82
+ preSelectedDeviceId = null;
83
+ lastLoggedDeviceList = '';
84
+ });
85
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_SELECT_RESULT, (_event, deviceId) => {
86
+ logger.info('[Main] Received ble-select-result:', deviceId);
87
+ if (selectBluetoothCallback) {
88
+ selectBluetoothCallback(deviceId || '');
89
+ selectBluetoothCallback = null;
90
+ }
91
+ });
92
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_CANCEL_REQUEST, () => {
93
+ logger.info('[Main] Received cancel-bluetooth-request');
94
+ if (selectBluetoothCallback) {
95
+ selectBluetoothCallback('');
96
+ selectBluetoothCallback = null;
97
+ }
98
+ });
99
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_STOP_SCAN, () => {
100
+ logger.info('[Main] Received stop BLE scan request');
101
+ if (selectBluetoothCallback) {
102
+ selectBluetoothCallback('');
103
+ selectBluetoothCallback = null;
104
+ }
105
+ });
106
+ session.setBluetoothPairingHandler((details, callback) => {
107
+ logger.info('[Main] Bluetooth pairing request received:', details);
108
+ logger.info('[Main] Pairing device ID:', details.deviceId);
109
+ logger.info('[Main] Pairing type:', details.pairingKind);
110
+ bluetoothPairingCallback = callback;
111
+ webContents.send(hdShared.EOneKeyBleMessageKeys.BLE_PAIRING_REQUEST, details);
112
+ });
113
+ logger.info('[Main] Bluetooth pairing handler registered');
114
+ ipcMain.on(hdShared.EOneKeyBleMessageKeys.BLE_PAIRING_RESPONSE, (_event, response) => {
115
+ logger.info('[Main] Received pairing response:', response);
116
+ if (bluetoothPairingCallback) {
117
+ bluetoothPairingCallback(response);
118
+ }
119
+ });
120
+ }
121
+
122
+ exports.IPC_CHANNELS = IPC_CHANNELS;
123
+ exports.initElectronBleBridge = initElectronBleBridge;
@@ -0,0 +1,49 @@
1
+ export interface BluetoothPairingDetails {
2
+ deviceId: string;
3
+ pairingKind: 'confirm' | 'confirmPin' | 'providePin';
4
+ pin?: string;
5
+ }
6
+ export interface BluetoothPairingResponse {
7
+ confirmed: boolean;
8
+ pin?: string;
9
+ }
10
+ export interface BluetoothDevice {
11
+ deviceId: string;
12
+ deviceName: string | null;
13
+ }
14
+ export interface BleDevice {
15
+ id: string;
16
+ name: string;
17
+ paired?: boolean;
18
+ }
19
+ export interface BleEnumerateOptions {
20
+ timeout?: number;
21
+ forceScan?: boolean;
22
+ }
23
+ export interface ElectronBleAPI {
24
+ enumerate(options?: BleEnumerateOptions): Promise<BleDevice[]>;
25
+ onBleSelect(callback: (devices: BleDevice[]) => void): () => void;
26
+ selectBleDevice(deviceId: string): void;
27
+ cancelBleRequest(): void;
28
+ onBlePairingRequest(callback: (details: BluetoothPairingDetails) => void): () => void;
29
+ respondToPairing(response: BluetoothPairingResponse): void;
30
+ onBleDeviceDisconnected(callback: (device: {
31
+ id: string;
32
+ name: string | null;
33
+ }) => void): () => void;
34
+ }
35
+ export declare const IPC_CHANNELS: {
36
+ readonly BLE_ENUMERATE: "ble-enumerate";
37
+ readonly BLE_ENUMERATE_RESULT: "ble-enumerate-result";
38
+ readonly BLE_SCAN_TIMEOUT: "ble-scan-timeout";
39
+ readonly BLE_SELECT: "ble-select";
40
+ readonly BLE_SELECT_RESULT: "ble-select-result";
41
+ readonly BLE_PAIRING_REQUEST: "ble-pairing-request";
42
+ readonly BLE_PAIRING_RESPONSE: "ble-pairing-response";
43
+ };
44
+ declare global {
45
+ interface Window {
46
+ electronBleAPI: ElectronBleAPI;
47
+ }
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,SAAS,GAAG,YAAY,GAAG,YAAY,CAAC;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAIlC,OAAO,CAAC,EAAE,MAAM,CAAC;IAIjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAE7B,SAAS,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAG/D,WAAW,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,gBAAgB,IAAI,IAAI,CAAC;IAGzB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACtF,gBAAgB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAG3D,uBAAuB,CACrB,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,GAC9D,MAAM,IAAI,CAAC;CACf;AAGD,eAAO,MAAM,YAAY;;;;;;;;CAQf,CAAC;AAEX,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,cAAc,EAAE,cAAc,CAAC;KAChC;CACF"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@onekeyfe/hd-transport-electron",
3
+ "version": "1.0.34-alpha.0",
4
+ "author": "OneKey",
5
+ "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/OneKeyHQ/hardware-js-sdk.git"
15
+ },
16
+ "scripts": {
17
+ "dev": "rimraf dist && rollup -c ../../build/rollup.config.js -w",
18
+ "build": "rimraf dist && rollup -c ../../build/rollup.config.js",
19
+ "lint": "eslint .",
20
+ "lint:fix": "eslint . --fix"
21
+ },
22
+ "sideEffects": false,
23
+ "peerDependencies": {
24
+ "@onekeyfe/hd-transport-web-device": "^1.0.28",
25
+ "electron": ">=25.0.0",
26
+ "electron-log": ">=4.0.0"
27
+ },
28
+ "dependencies": {
29
+ "@onekeyfe/hd-shared": "^1.0.34-alpha.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/web-bluetooth": "^0.0.17",
33
+ "electron": "^25.0.0",
34
+ "typescript": "^5.3.3"
35
+ },
36
+ "gitHead": "a910879dea6198bd96016aec81429f31b9692bf1"
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,195 @@
1
+ /*
2
+ * Electron BLE bridge helper
3
+ * Running in Main process only. At runtime it dynamically requires 'electron',
4
+ * so projects that don't use Electron will tree-shake this file out and won't bundle electron.
5
+ */
6
+
7
+ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/ban-ts-comment, import/no-extraneous-dependencies, global-require, import/no-unresolved */
8
+
9
+ import { isOnekeyDevice, EOneKeyBleMessageKeys } from '@onekeyfe/hd-shared';
10
+ import type { WebContents, IpcMainEvent, Event } from 'electron';
11
+
12
+ // Export all type definitions
13
+ export * from './types';
14
+
15
+ // Internal interface definitions
16
+ interface BluetoothDevice {
17
+ deviceId: string;
18
+ deviceName: string;
19
+ }
20
+
21
+ interface BluetoothPairingDetails {
22
+ deviceId: string;
23
+ pairingKind: 'confirm' | 'confirmPin' | 'providePin';
24
+ pin?: string;
25
+ }
26
+
27
+ type BluetoothPairingResponse = {
28
+ confirmed: boolean;
29
+ pin?: string;
30
+ };
31
+
32
+ export function initElectronBleBridge(webContents: WebContents) {
33
+ // @ts-ignore – electron is only available at runtime within an Electron app
34
+ const electron = require('electron');
35
+ const { ipcMain } = electron;
36
+
37
+ // @ts-ignore – electron-log is only available at runtime within an Electron app
38
+ const logger = require('electron-log');
39
+
40
+ const { session } = webContents;
41
+
42
+ let selectBluetoothCallback: ((deviceId: string) => void) | null = null;
43
+ let bluetoothPairingCallback: ((response: BluetoothPairingResponse) => void) | null = null;
44
+ let preSelectedDeviceId: string | null = null;
45
+
46
+ // Track last logged device list to avoid duplicate logs
47
+ let lastLoggedDeviceList = '';
48
+
49
+ // Helper function to log device list only if changed
50
+ const logDeviceListIfChanged = (deviceList: BluetoothDevice[]): boolean => {
51
+ // Sort devices by deviceId to ensure consistent comparison regardless of order
52
+ const sortedDevices = [...deviceList].sort((a, b) => a.deviceId.localeCompare(b.deviceId));
53
+ const deviceListString = JSON.stringify(
54
+ sortedDevices.map(d => ({
55
+ deviceId: d.deviceId,
56
+ deviceName: d.deviceName,
57
+ }))
58
+ );
59
+
60
+ // Only log if the device list has changed
61
+ if (deviceListString !== lastLoggedDeviceList) {
62
+ logger.info('[Main] Raw device list:', deviceList);
63
+ lastLoggedDeviceList = deviceListString;
64
+ return true; // Logged
65
+ }
66
+
67
+ return false; // Not logged (duplicate)
68
+ };
69
+
70
+ // 1️⃣ Device selection events
71
+ webContents.on(
72
+ 'select-bluetooth-device',
73
+ (event: Event, deviceList: BluetoothDevice[], callback: (deviceId: string) => void) => {
74
+ event.preventDefault();
75
+
76
+ logger.info('[Main] select-bluetooth-device event triggered');
77
+
78
+ // Use helper function to log device list only if changed
79
+ const deviceListChanged = logDeviceListIfChanged(deviceList);
80
+
81
+ if (!deviceListChanged) {
82
+ // If device list hasn't changed, just log a simple message
83
+ logger.info('[Main] Device list unchanged, continuing...');
84
+ }
85
+
86
+ logger.info('[Main] Pre-selected device:', preSelectedDeviceId);
87
+
88
+ // Save callback for later use
89
+ selectBluetoothCallback = callback;
90
+
91
+ // If device list is empty, wait for next event
92
+ if (!deviceList.length) {
93
+ logger.info('[Main] Empty device list, waiting for more devices...');
94
+ return;
95
+ }
96
+
97
+ // Filter OneKey devices and send to renderer process
98
+ const filteredDevices = deviceList
99
+ .filter(d => isOnekeyDevice(d.deviceName))
100
+ .map(d => ({ id: d.deviceId, name: d.deviceName }));
101
+
102
+ if (filteredDevices.length > 0) {
103
+ // Only log found devices if the device list actually changed
104
+ if (deviceListChanged) {
105
+ logger.info('[Main] Found OneKey devices:', filteredDevices);
106
+ }
107
+
108
+ // If there's a pre-selected device, select it directly
109
+ if (preSelectedDeviceId) {
110
+ logger.info('[Main] Set Pre-selected device:', preSelectedDeviceId);
111
+ const targetDevice = filteredDevices.find(d => d.id === preSelectedDeviceId);
112
+ if (targetDevice) {
113
+ logger.info('[Main] Found pre-selected device:', targetDevice);
114
+ callback(targetDevice.id);
115
+ selectBluetoothCallback = null;
116
+ return;
117
+ }
118
+ }
119
+
120
+ // Continuously send newly discovered devices
121
+ webContents.send(EOneKeyBleMessageKeys.BLE_SELECT, filteredDevices);
122
+ } else if (deviceListChanged) {
123
+ logger.info('[Main] No OneKey devices in this batch, continue scanning...');
124
+ }
125
+ }
126
+ );
127
+
128
+ // Device pre-selection related
129
+ ipcMain.on(EOneKeyBleMessageKeys.BLE_PRE_SELECT, (_event: IpcMainEvent, deviceId: string) => {
130
+ logger.info('[Main] Pre-selecting device:', deviceId);
131
+ preSelectedDeviceId = deviceId;
132
+ // Reset device list tracking when pre-selecting
133
+ lastLoggedDeviceList = '';
134
+ });
135
+
136
+ ipcMain.on(EOneKeyBleMessageKeys.BLE_CLEAR_PRE_SELECT, () => {
137
+ logger.info('[Main] Clearing pre-selected device');
138
+ preSelectedDeviceId = null;
139
+ // Reset device list tracking when clearing pre-selection
140
+ lastLoggedDeviceList = '';
141
+ });
142
+
143
+ // Renderer process returns selection result
144
+ ipcMain.on(EOneKeyBleMessageKeys.BLE_SELECT_RESULT, (_event: IpcMainEvent, deviceId?: string) => {
145
+ logger.info('[Main] Received ble-select-result:', deviceId);
146
+ if (selectBluetoothCallback) {
147
+ selectBluetoothCallback(deviceId || '');
148
+ selectBluetoothCallback = null;
149
+ }
150
+ });
151
+
152
+ // Allow user to cancel
153
+ ipcMain.on(EOneKeyBleMessageKeys.BLE_CANCEL_REQUEST, () => {
154
+ logger.info('[Main] Received cancel-bluetooth-request');
155
+ if (selectBluetoothCallback) {
156
+ selectBluetoothCallback('');
157
+ selectBluetoothCallback = null;
158
+ }
159
+ });
160
+
161
+ // Handle stop scan requests
162
+ ipcMain.on(EOneKeyBleMessageKeys.BLE_STOP_SCAN, () => {
163
+ logger.info('[Main] Received stop BLE scan request');
164
+ if (selectBluetoothCallback) {
165
+ selectBluetoothCallback('');
166
+ selectBluetoothCallback = null;
167
+ }
168
+ });
169
+
170
+ // 2️⃣ PIN / Confirm handling
171
+ session.setBluetoothPairingHandler(
172
+ (details: BluetoothPairingDetails, callback: (response: BluetoothPairingResponse) => void) => {
173
+ logger.info('[Main] Bluetooth pairing request received:', details);
174
+ logger.info('[Main] Pairing device ID:', details.deviceId);
175
+ logger.info('[Main] Pairing type:', details.pairingKind);
176
+ bluetoothPairingCallback = callback;
177
+ webContents.send(EOneKeyBleMessageKeys.BLE_PAIRING_REQUEST, details);
178
+ }
179
+ );
180
+ logger.info('[Main] Bluetooth pairing handler registered');
181
+
182
+ // 3️⃣ Device disconnect handling
183
+ // Note: Electron doesn't provide a direct bluetooth-device-disconnected event
184
+ // Device disconnection should be handled at the Web Bluetooth API level in the renderer process
185
+
186
+ ipcMain.on(
187
+ EOneKeyBleMessageKeys.BLE_PAIRING_RESPONSE,
188
+ (_event: IpcMainEvent, response: BluetoothPairingResponse) => {
189
+ logger.info('[Main] Received pairing response:', response);
190
+ if (bluetoothPairingCallback) {
191
+ bluetoothPairingCallback(response);
192
+ }
193
+ }
194
+ );
195
+ }
package/src/types.ts ADDED
@@ -0,0 +1,68 @@
1
+ export interface BluetoothPairingDetails {
2
+ deviceId: string;
3
+ pairingKind: 'confirm' | 'confirmPin' | 'providePin';
4
+ pin?: string;
5
+ }
6
+
7
+ export interface BluetoothPairingResponse {
8
+ confirmed: boolean;
9
+ pin?: string;
10
+ }
11
+
12
+ export interface BluetoothDevice {
13
+ deviceId: string;
14
+ deviceName: string | null;
15
+ }
16
+
17
+ export interface BleDevice {
18
+ id: string;
19
+ name: string;
20
+ paired?: boolean;
21
+ }
22
+
23
+ export interface BleEnumerateOptions {
24
+ /**
25
+ * Scan timeout in milliseconds (default: 30s)
26
+ */
27
+ timeout?: number;
28
+ /**
29
+ * Whether to force a new scan even if paired devices exist
30
+ */
31
+ forceScan?: boolean;
32
+ }
33
+
34
+ export interface ElectronBleAPI {
35
+ // Device enumeration
36
+ enumerate(options?: BleEnumerateOptions): Promise<BleDevice[]>;
37
+
38
+ // Device selection
39
+ onBleSelect(callback: (devices: BleDevice[]) => void): () => void;
40
+ selectBleDevice(deviceId: string): void;
41
+ cancelBleRequest(): void;
42
+
43
+ // Device pairing
44
+ onBlePairingRequest(callback: (details: BluetoothPairingDetails) => void): () => void;
45
+ respondToPairing(response: BluetoothPairingResponse): void;
46
+
47
+ // Device disconnection
48
+ onBleDeviceDisconnected(
49
+ callback: (device: { id: string; name: string | null }) => void
50
+ ): () => void;
51
+ }
52
+
53
+ // IPC Channel Names
54
+ export const IPC_CHANNELS = {
55
+ BLE_ENUMERATE: 'ble-enumerate',
56
+ BLE_ENUMERATE_RESULT: 'ble-enumerate-result',
57
+ BLE_SCAN_TIMEOUT: 'ble-scan-timeout',
58
+ BLE_SELECT: 'ble-select',
59
+ BLE_SELECT_RESULT: 'ble-select-result',
60
+ BLE_PAIRING_REQUEST: 'ble-pairing-request',
61
+ BLE_PAIRING_RESPONSE: 'ble-pairing-response',
62
+ } as const;
63
+
64
+ declare global {
65
+ interface Window {
66
+ electronBleAPI: ElectronBleAPI;
67
+ }
68
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "types": [
6
+ "node",
7
+ "web-bluetooth"
8
+ ]
9
+ },
10
+ "include": ["./src", "../hd-transport-web-device/src/electron-ble-transport.ts"]
11
+ }