@onekeyfe/hd-transport-electron 1.2.8-alpha.2 → 1.2.8-alpha.21
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/dist/{index-5135e7b9.js → index-21e34fdb.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-043a7c23.js → noble-ble-handler-c4530a1b.js} +17 -14
- package/dist/noble-ble-handler.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/noble-ble-handler.test.ts +70 -4
- package/src/noble-ble-handler.ts +17 -15
|
@@ -55,13 +55,13 @@ function invokeNobleBleIpc(request) {
|
|
|
55
55
|
|
|
56
56
|
function initNobleBleSupport(webContents) {
|
|
57
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
-
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-
|
|
58
|
+
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-c4530a1b.js'); });
|
|
59
59
|
setupNobleBleHandlers(webContents);
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
function disposeNobleBleSupport(releaseNoble) {
|
|
63
63
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
-
const handler = yield Promise.resolve().then(function () { return require('./noble-ble-handler-
|
|
64
|
+
const handler = yield Promise.resolve().then(function () { return require('./noble-ble-handler-c4530a1b.js'); });
|
|
65
65
|
yield handler.disposeNobleBleSupport(releaseNoble);
|
|
66
66
|
});
|
|
67
67
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-21e34fdb.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var pRetry = require('p-retry');
|
|
6
6
|
|
|
@@ -376,8 +376,18 @@ function updateBluetoothState(state) {
|
|
|
376
376
|
function initializeNoble() {
|
|
377
377
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
378
378
|
assertBleActive();
|
|
379
|
-
if (noble)
|
|
379
|
+
if (noble) {
|
|
380
|
+
if (noble.state === 'poweredOff') {
|
|
381
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BlePoweredOff);
|
|
382
|
+
}
|
|
383
|
+
if (noble.state === 'unsupported') {
|
|
384
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleUnsupported);
|
|
385
|
+
}
|
|
386
|
+
if (noble.state === 'unauthorized') {
|
|
387
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError);
|
|
388
|
+
}
|
|
380
389
|
return;
|
|
390
|
+
}
|
|
381
391
|
try {
|
|
382
392
|
noble = require('@stoprocent/noble');
|
|
383
393
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Noble library loaded');
|
|
@@ -418,7 +428,7 @@ function initializeNoble() {
|
|
|
418
428
|
}
|
|
419
429
|
else if (state === 'unauthorized') {
|
|
420
430
|
cleanup();
|
|
421
|
-
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.
|
|
431
|
+
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleLocationError));
|
|
422
432
|
}
|
|
423
433
|
};
|
|
424
434
|
const cancel = () => {
|
|
@@ -427,6 +437,7 @@ function initializeNoble() {
|
|
|
427
437
|
};
|
|
428
438
|
pendingCancellations.add(cancel);
|
|
429
439
|
noble.on('stateChange', onStateChange);
|
|
440
|
+
onStateChange(noble.state);
|
|
430
441
|
});
|
|
431
442
|
assertBleActive();
|
|
432
443
|
if (!persistentDiscoverListener) {
|
|
@@ -439,7 +450,7 @@ function initializeNoble() {
|
|
|
439
450
|
}
|
|
440
451
|
catch (error) {
|
|
441
452
|
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Failed to initialize Noble:', error);
|
|
442
|
-
bluetoothState.unsupported =
|
|
453
|
+
bluetoothState.unsupported = (noble === null || noble === void 0 ? void 0 : noble.state) === 'unsupported';
|
|
443
454
|
bluetoothState.initialized = true;
|
|
444
455
|
throw error;
|
|
445
456
|
}
|
|
@@ -868,9 +879,7 @@ function performTargetedScan(targetDeviceId, timeoutMs = NOBLE_BLE_TARGETED_SCAN
|
|
|
868
879
|
}
|
|
869
880
|
function enumerateDevices(isWindowDestroyed) {
|
|
870
881
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
871
|
-
|
|
872
|
-
yield initializeNoble();
|
|
873
|
-
}
|
|
882
|
+
yield initializeNoble();
|
|
874
883
|
if (!noble) {
|
|
875
884
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
876
885
|
}
|
|
@@ -1250,10 +1259,6 @@ function tryDirectConnectById(deviceId) {
|
|
|
1250
1259
|
deviceId,
|
|
1251
1260
|
error: String(error),
|
|
1252
1261
|
});
|
|
1253
|
-
const nativeError = error;
|
|
1254
|
-
if (nativeError.nativeErrorCode === 14 && nativeError.nativeErrorDomain === 'CBErrorDomain') {
|
|
1255
|
-
throw createNobleBleConnectionError(nativeError);
|
|
1256
|
-
}
|
|
1257
1262
|
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1258
1263
|
return undefined;
|
|
1259
1264
|
}
|
|
@@ -1267,6 +1272,7 @@ function tryDirectConnectById(deviceId) {
|
|
|
1267
1272
|
function connectDevice(deviceId, webContents) {
|
|
1268
1273
|
var _a, _b, _c;
|
|
1269
1274
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
1275
|
+
yield initializeNoble();
|
|
1270
1276
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connect device request:', {
|
|
1271
1277
|
deviceId,
|
|
1272
1278
|
hasDiscovered: discoveredDevices.has(deviceId),
|
|
@@ -1280,9 +1286,6 @@ function connectDevice(deviceId, webContents) {
|
|
|
1280
1286
|
peripheral = undefined;
|
|
1281
1287
|
}
|
|
1282
1288
|
if (!peripheral) {
|
|
1283
|
-
if (!noble) {
|
|
1284
|
-
yield initializeNoble();
|
|
1285
|
-
}
|
|
1286
1289
|
if (!noble) {
|
|
1287
1290
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
1288
1291
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAiC1F,KAAK,mBAAmB,GAAG,KAAK,GAAG;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,SAAK,+CAG3F;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAgCvF;AA+KD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;
|
|
1
|
+
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,KAAK,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAiC1F,KAAK,mBAAmB,GAAG,KAAK,GAAG;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,mBAAmB,EAAE,aAAa,SAAK,+CAG3F;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAgCvF;AA+KD,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE,oBAAoB,UAI7E;AAkzDD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAkOpE;AAOD,wBAAgB,sBAAsB,CACpC,YAAY,GAAE,CAAC,QAAQ,EAAE;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,KAAK,IAAkC,GAC/E,OAAO,CAAC,IAAI,CAAC,CAiEf"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-electron",
|
|
3
|
-
"version": "1.2.8-alpha.
|
|
3
|
+
"version": "1.2.8-alpha.21",
|
|
4
4
|
"author": "OneKey",
|
|
5
5
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"electron-log": ">=4.0.0"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@onekeyfe/hd-core": "1.2.8-alpha.
|
|
29
|
-
"@onekeyfe/hd-shared": "1.2.8-alpha.
|
|
30
|
-
"@onekeyfe/hd-transport": "1.2.8-alpha.
|
|
28
|
+
"@onekeyfe/hd-core": "1.2.8-alpha.21",
|
|
29
|
+
"@onekeyfe/hd-shared": "1.2.8-alpha.21",
|
|
30
|
+
"@onekeyfe/hd-transport": "1.2.8-alpha.21",
|
|
31
31
|
"@stoprocent/noble": "2.3.16",
|
|
32
32
|
"p-retry": "^4.6.2"
|
|
33
33
|
},
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"electron": "^25.0.0",
|
|
37
37
|
"typescript": "^5.3.3"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "acc31b02db0a507a597775fc88306c9104c1b5d1"
|
|
40
40
|
}
|
|
@@ -292,9 +292,13 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
292
292
|
}
|
|
293
293
|
);
|
|
294
294
|
|
|
295
|
-
test.each([
|
|
296
|
-
'
|
|
297
|
-
|
|
295
|
+
test.each([
|
|
296
|
+
['Pro A1B2', 'unavailable'],
|
|
297
|
+
['Pro2 A1B2', 'unavailable'],
|
|
298
|
+
['Pro2 A1B2', 'native error 14'],
|
|
299
|
+
])(
|
|
300
|
+
'refreshes a retained disconnected %s peripheral before cold connecting (direct: %s)',
|
|
301
|
+
async (name, directConnectResult) => {
|
|
298
302
|
const handlers = new Map<string, IpcHandler>();
|
|
299
303
|
const stalePeripheral = Object.assign(new EventEmitter(), createPeripheral('device', name), {
|
|
300
304
|
connect: jest.fn(),
|
|
@@ -311,7 +315,16 @@ describe('Electron Noble BLE device discovery', () => {
|
|
|
311
315
|
noble.emit('discover', freshPeripheral);
|
|
312
316
|
}),
|
|
313
317
|
stopScanning: jest.fn(callback => callback?.()),
|
|
314
|
-
connectAsync: jest.fn(() =>
|
|
318
|
+
connectAsync: jest.fn(() =>
|
|
319
|
+
directConnectResult === 'native error 14'
|
|
320
|
+
? Promise.reject(
|
|
321
|
+
Object.assign(new Error('native direct connection failure'), {
|
|
322
|
+
nativeErrorDomain: 'CBErrorDomain',
|
|
323
|
+
nativeErrorCode: 14,
|
|
324
|
+
})
|
|
325
|
+
)
|
|
326
|
+
: Promise.resolve(undefined)
|
|
327
|
+
),
|
|
315
328
|
});
|
|
316
329
|
jest.doMock('@stoprocent/noble', () => noble);
|
|
317
330
|
jest.doMock('electron', () => ({
|
|
@@ -918,6 +931,59 @@ describe('Noble BLE process shutdown', () => {
|
|
|
918
931
|
expect(handlers.size).toBe(0);
|
|
919
932
|
});
|
|
920
933
|
|
|
934
|
+
test.each([
|
|
935
|
+
['poweredOff', HardwareErrorCode.BlePoweredOff],
|
|
936
|
+
['unauthorized', HardwareErrorCode.BleLocationError],
|
|
937
|
+
['unsupported', HardwareErrorCode.BleUnsupported],
|
|
938
|
+
])(
|
|
939
|
+
'preserves adapter state %s across repeated scans and connections',
|
|
940
|
+
async (state, errorCode) => {
|
|
941
|
+
jest.useFakeTimers({ doNotFake: ['performance'] });
|
|
942
|
+
const { sdk, native, handlers } = await setup(state);
|
|
943
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
944
|
+
for (const channel of [
|
|
945
|
+
EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE,
|
|
946
|
+
EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT,
|
|
947
|
+
]) {
|
|
948
|
+
await expect(handlers.get(channel)?.({}, 'device')).resolves.toMatchObject({
|
|
949
|
+
success: false,
|
|
950
|
+
error: { errorCode },
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
expect(native.startScanning).not.toHaveBeenCalled();
|
|
955
|
+
expect(native.listenerCount('stateChange')).toBe(1);
|
|
956
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
957
|
+
await sdk.disposeNobleBleSupport();
|
|
958
|
+
}
|
|
959
|
+
);
|
|
960
|
+
|
|
961
|
+
test.each([
|
|
962
|
+
['poweredOff', HardwareErrorCode.BlePoweredOff],
|
|
963
|
+
['unauthorized', HardwareErrorCode.BleLocationError],
|
|
964
|
+
['unsupported', HardwareErrorCode.BleUnsupported],
|
|
965
|
+
])('checks adapter state %s again after initialization', async (state, errorCode) => {
|
|
966
|
+
const { sdk, native, handlers } = await setup();
|
|
967
|
+
const checkAvailability = handlers.get(EOneKeyBleMessageKeys.BLE_AVAILABILITY_CHECK);
|
|
968
|
+
await expect(checkAvailability?.({})).resolves.toMatchObject({ available: true });
|
|
969
|
+
native.state = state;
|
|
970
|
+
native.emit('stateChange', state);
|
|
971
|
+
for (const channel of [
|
|
972
|
+
EOneKeyBleMessageKeys.NOBLE_BLE_ENUMERATE,
|
|
973
|
+
EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT,
|
|
974
|
+
]) {
|
|
975
|
+
await expect(handlers.get(channel)?.({}, 'device')).resolves.toMatchObject({
|
|
976
|
+
success: false,
|
|
977
|
+
error: { errorCode },
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
expect(native.startScanning).not.toHaveBeenCalled();
|
|
981
|
+
native.state = 'poweredOn';
|
|
982
|
+
native.emit('stateChange', native.state);
|
|
983
|
+
await expect(checkAvailability?.({})).resolves.toMatchObject({ available: true });
|
|
984
|
+
await sdk.disposeNobleBleSupport();
|
|
985
|
+
});
|
|
986
|
+
|
|
921
987
|
test('cancels an active scan, ignores its late callback and releases native once', async () => {
|
|
922
988
|
jest.useFakeTimers({ doNotFake: ['performance'] });
|
|
923
989
|
const { sdk, native, handlers } = await setup();
|
package/src/noble-ble-handler.ts
CHANGED
|
@@ -429,7 +429,18 @@ function updateBluetoothState(state: string): void {
|
|
|
429
429
|
// Initialize Noble
|
|
430
430
|
async function initializeNoble(): Promise<void> {
|
|
431
431
|
assertBleActive();
|
|
432
|
-
if (noble)
|
|
432
|
+
if (noble) {
|
|
433
|
+
if (noble.state === 'poweredOff') {
|
|
434
|
+
throw ERRORS.TypedError(HardwareErrorCode.BlePoweredOff);
|
|
435
|
+
}
|
|
436
|
+
if (noble.state === 'unsupported') {
|
|
437
|
+
throw ERRORS.TypedError(HardwareErrorCode.BleUnsupported);
|
|
438
|
+
}
|
|
439
|
+
if (noble.state === 'unauthorized') {
|
|
440
|
+
throw ERRORS.TypedError(HardwareErrorCode.BleLocationError);
|
|
441
|
+
}
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
433
444
|
|
|
434
445
|
try {
|
|
435
446
|
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
|
@@ -482,7 +493,7 @@ async function initializeNoble(): Promise<void> {
|
|
|
482
493
|
reject(ERRORS.TypedError(HardwareErrorCode.BlePoweredOff));
|
|
483
494
|
} else if (state === 'unauthorized') {
|
|
484
495
|
cleanup();
|
|
485
|
-
reject(ERRORS.TypedError(HardwareErrorCode.
|
|
496
|
+
reject(ERRORS.TypedError(HardwareErrorCode.BleLocationError));
|
|
486
497
|
}
|
|
487
498
|
};
|
|
488
499
|
|
|
@@ -494,6 +505,7 @@ async function initializeNoble(): Promise<void> {
|
|
|
494
505
|
};
|
|
495
506
|
pendingCancellations.add(cancel);
|
|
496
507
|
noble.on('stateChange', onStateChange);
|
|
508
|
+
onStateChange(noble.state);
|
|
497
509
|
});
|
|
498
510
|
|
|
499
511
|
assertBleActive();
|
|
@@ -508,7 +520,7 @@ async function initializeNoble(): Promise<void> {
|
|
|
508
520
|
logger?.info('[NobleBLE] Noble initialized successfully');
|
|
509
521
|
} catch (error) {
|
|
510
522
|
logger?.error('[NobleBLE] Failed to initialize Noble:', error);
|
|
511
|
-
bluetoothState.unsupported =
|
|
523
|
+
bluetoothState.unsupported = noble?.state === 'unsupported';
|
|
512
524
|
bluetoothState.initialized = true;
|
|
513
525
|
throw error;
|
|
514
526
|
}
|
|
@@ -1137,9 +1149,7 @@ async function performTargetedScan(
|
|
|
1137
1149
|
|
|
1138
1150
|
// Enumerate devices
|
|
1139
1151
|
async function enumerateDevices(isWindowDestroyed: () => boolean): Promise<DeviceInfo[]> {
|
|
1140
|
-
|
|
1141
|
-
await initializeNoble();
|
|
1142
|
-
}
|
|
1152
|
+
await initializeNoble();
|
|
1143
1153
|
|
|
1144
1154
|
if (!noble) {
|
|
1145
1155
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
@@ -1730,10 +1740,6 @@ async function tryDirectConnectById(deviceId: string): Promise<Peripheral | unde
|
|
|
1730
1740
|
deviceId,
|
|
1731
1741
|
error: String(error),
|
|
1732
1742
|
});
|
|
1733
|
-
const nativeError = error as NobleBleNativeError;
|
|
1734
|
-
if (nativeError.nativeErrorCode === 14 && nativeError.nativeErrorDomain === 'CBErrorDomain') {
|
|
1735
|
-
throw createNobleBleConnectionError(nativeError);
|
|
1736
|
-
}
|
|
1737
1743
|
directConnectCooldownUntil.set(deviceId, Date.now() + DIRECT_CONNECT_COOLDOWN_MS);
|
|
1738
1744
|
return undefined;
|
|
1739
1745
|
} finally {
|
|
@@ -1744,6 +1750,7 @@ async function tryDirectConnectById(deviceId: string): Promise<Peripheral | unde
|
|
|
1744
1750
|
|
|
1745
1751
|
// Connect to device - supports both discovered and direct connection modes
|
|
1746
1752
|
async function connectDevice(deviceId: string, webContents: WebContents): Promise<void> {
|
|
1753
|
+
await initializeNoble();
|
|
1747
1754
|
logger?.info('[NobleBLE] Connect device request:', {
|
|
1748
1755
|
deviceId,
|
|
1749
1756
|
hasDiscovered: discoveredDevices.has(deviceId),
|
|
@@ -1761,11 +1768,6 @@ async function connectDevice(deviceId: string, webContents: WebContents): Promis
|
|
|
1761
1768
|
}
|
|
1762
1769
|
|
|
1763
1770
|
if (!peripheral) {
|
|
1764
|
-
// Initialize Noble if not already done
|
|
1765
|
-
if (!noble) {
|
|
1766
|
-
await initializeNoble();
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
1771
|
if (!noble) {
|
|
1770
1772
|
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Noble not available');
|
|
1771
1773
|
}
|