@onekeyfe/hd-transport-electron 1.2.2-alpha.100 → 1.2.2-alpha.101

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.
@@ -1 +1 @@
1
- {"version":3,"file":"desktop-api.d.ts","sourceRoot":"","sources":["../../src/types/desktop-api.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACzD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,cAAc,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACnF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAOvF,oBAAoB,EAAE,CACpB,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;KAAE,KAAK,IAAI,KACpF,MAAM,IAAI,CAAC;IAChB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB"}
1
+ {"version":3,"file":"desktop-api.d.ts","sourceRoot":"","sources":["../../src/types/desktop-api.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,uBAAuB,CAAC;CAChC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACzD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,cAAc,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACnF,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAOvF,oBAAoB,EAAE,CACpB,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;KAAE,KAAK,IAAI,KACpF,MAAM,IAAI,CAAC;IAChB,iBAAiB,EAAE,MAAM,OAAO,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC,CAAC;CACJ;AAGD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB"}
@@ -22,6 +22,7 @@ export interface NobleModule {
22
22
  export interface Logger {
23
23
  info(message: string, ...args: any[]): void;
24
24
  debug(message: string, ...args: any[]): void;
25
+ warn(message: string, ...args: any[]): void;
25
26
  error(message: string, ...args: any[]): void;
26
27
  }
27
28
  export declare function safeLog(logger: Logger | null, level: 'info' | 'debug' | 'error', message: string, ...args: any[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"noble-extended.d.ts","sourceRoot":"","sources":["../../src/types/noble-extended.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,MAAM,WAAW,UAAW,SAAQ,oBAAoB;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAGD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CACX,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GACjC,IAAI,CAAC;IACR,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC1C,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IACxE,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9E,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;CACrF;AAGD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC9C;AAGD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EACjC,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,GAAG,EAAE,GACb,IAAI,CAMN"}
1
+ {"version":3,"file":"noble-extended.d.ts","sourceRoot":"","sources":["../../src/types/noble-extended.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,MAAM,WAAW,UAAW,SAAQ,oBAAoB;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAGD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CACX,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GACjC,IAAI,CAAC;IACR,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC1C,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IACxE,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9E,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;CACrF;AAGD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC9C;AAGD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EACjC,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,GAAG,EAAE,GACb,IAAI,CAMN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-electron",
3
- "version": "1.2.2-alpha.100",
3
+ "version": "1.2.2-alpha.101",
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.2-alpha.100",
29
- "@onekeyfe/hd-shared": "1.2.2-alpha.100",
30
- "@onekeyfe/hd-transport": "1.2.2-alpha.100",
28
+ "@onekeyfe/hd-core": "1.2.2-alpha.101",
29
+ "@onekeyfe/hd-shared": "1.2.2-alpha.101",
30
+ "@onekeyfe/hd-transport": "1.2.2-alpha.101",
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": "c40dad085297b0e3cc2020bd218c146dff6ed3e1"
39
+ "gitHead": "b9a5ca0c73e5e2cc979c91c007ace476e442718c"
40
40
  }
@@ -1,6 +1,13 @@
1
- import { resolveBlePacketCapacity } from '../ble-packet-capacity';
1
+ import { resolveBlePacketCapacity, resolveNobleAttMtu } from '../ble-packet-capacity';
2
2
 
3
3
  describe('resolveBlePacketCapacity', () => {
4
+ test('normalizes Noble platform reports to ATT MTU', () => {
5
+ expect(resolveNobleAttMtu(244, 'darwin')).toBe(247);
6
+ expect(resolveNobleAttMtu(244, 'win32')).toBe(247);
7
+ expect(resolveNobleAttMtu(247, 'linux')).toBe(247);
8
+ expect(resolveNobleAttMtu(null, 'darwin')).toBeUndefined();
9
+ });
10
+
4
11
  test('uses ATT MTU payload capacity with an upper bound', () => {
5
12
  expect(resolveBlePacketCapacity(247, 244, 192)).toBe(244);
6
13
  expect(resolveBlePacketCapacity(185, 244, 192)).toBe(182);
@@ -1,8 +1,8 @@
1
1
  import { EventEmitter } from 'events';
2
- import { EOneKeyBleMessageKeys } from '@onekeyfe/hd-shared';
2
+ import { EOneKeyBleMessageKeys, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
3
 
4
4
  import {
5
- NOBLE_BLE_CONNECTION_TIMEOUT_MS,
5
+ NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS,
6
6
  NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS,
7
7
  } from '../noble-ble-timeouts';
8
8
 
@@ -26,9 +26,93 @@ describe('Electron Noble BLE device discovery', () => {
26
26
  jest.clearAllMocks();
27
27
  });
28
28
 
29
- test('allows enough time for a slow targeted scan and connection', () => {
29
+ test('bounds targeted scans and subscription callbacks independently', () => {
30
30
  expect(NOBLE_BLE_TARGETED_SCAN_TIMEOUT_MS).toBe(5_000);
31
- expect(NOBLE_BLE_CONNECTION_TIMEOUT_MS).toBe(10_000);
31
+ expect(NOBLE_BLE_SUBSCRIBE_TIMEOUT_MS).toBe(10_000);
32
+ });
33
+
34
+ test('maps structured macOS stale pairing failures without parsing localized text', async () => {
35
+ const { createNobleBleConnectionError } = await import('../noble-ble-handler');
36
+
37
+ const staleBondError = createNobleBleConnectionError(
38
+ Object.assign(new Error('Peer removed pairing information on the device side'), {
39
+ nativeErrorCode: 14,
40
+ nativeErrorDomain: 'CBErrorDomain',
41
+ })
42
+ );
43
+ expect(staleBondError).toMatchObject({
44
+ errorCode: HardwareErrorCode.BleBondInvalid,
45
+ params: {
46
+ nativeErrorMessage: 'Peer removed pairing information on the device side',
47
+ },
48
+ });
49
+ expect(staleBondError.message).toContain('Peer removed pairing information on the device side');
50
+ expect(createNobleBleConnectionError(new Error('Encryption is insufficient'))).toMatchObject({
51
+ errorCode: HardwareErrorCode.BleConnectedError,
52
+ });
53
+ expect(
54
+ createNobleBleConnectionError(
55
+ Object.assign(new Error('localized native message'), {
56
+ nativeErrorCode: 14,
57
+ nativeErrorDomain: 'CBATTErrorDomain',
58
+ })
59
+ )
60
+ ).toMatchObject({
61
+ errorCode: HardwareErrorCode.BleConnectedError,
62
+ });
63
+ expect(createNobleBleConnectionError(new Error('connection failed'))).toMatchObject({
64
+ errorCode: HardwareErrorCode.BleConnectedError,
65
+ });
66
+ });
67
+
68
+ test('serializes HardwareError fields for the Noble IPC boundary', async () => {
69
+ const { createNobleBleIpcErrorResponse } = await import('../noble-ble-handler');
70
+
71
+ expect(
72
+ createNobleBleIpcErrorResponse({
73
+ name: 'HardwareError',
74
+ message: 'Bluetooth pairing information is no longer valid',
75
+ errorCode: HardwareErrorCode.BleBondInvalid,
76
+ params: { nativeErrorMessage: 'native message' },
77
+ })
78
+ ).toEqual({
79
+ type: 'NobleBleIpcError',
80
+ success: false,
81
+ error: {
82
+ name: 'HardwareError',
83
+ message: 'Bluetooth pairing information is no longer valid',
84
+ errorCode: HardwareErrorCode.BleBondInvalid,
85
+ params: { nativeErrorMessage: 'native message' },
86
+ },
87
+ });
88
+
89
+ expect(createNobleBleIpcErrorResponse(new Error('untyped failure'))).toEqual({
90
+ type: 'NobleBleIpcError',
91
+ success: false,
92
+ error: {
93
+ name: 'Error',
94
+ message: 'untyped failure',
95
+ errorCode: HardwareErrorCode.UnknownError,
96
+ },
97
+ });
98
+
99
+ const circularParams: { self?: unknown } = {};
100
+ circularParams.self = circularParams;
101
+ expect(
102
+ createNobleBleIpcErrorResponse({
103
+ message: 'failure with unsafe params',
104
+ errorCode: HardwareErrorCode.BleConnectedError,
105
+ params: circularParams,
106
+ })
107
+ ).toEqual({
108
+ type: 'NobleBleIpcError',
109
+ success: false,
110
+ error: {
111
+ name: 'Error',
112
+ message: 'failure with unsafe params',
113
+ errorCode: HardwareErrorCode.BleConnectedError,
114
+ },
115
+ });
32
116
  });
33
117
 
34
118
  test('keeps safe pacing by default and allows an explicit high-throughput bypass', async () => {
@@ -176,79 +260,45 @@ describe('Electron Noble BLE device discovery', () => {
176
260
  expect(peripheral.connect).not.toHaveBeenCalled();
177
261
 
178
262
  stopScanningCallback?.();
179
- await expect(connectPromise).rejects.toThrow('expected test connection failure');
263
+ await expect(connectPromise).resolves.toEqual({
264
+ type: 'NobleBleIpcError',
265
+ success: false,
266
+ error: {
267
+ name: 'HardwareError',
268
+ message: 'expected test connection failure',
269
+ errorCode: HardwareErrorCode.BleConnectedError,
270
+ },
271
+ });
180
272
  expect(peripheral.connect).toHaveBeenCalledTimes(1);
181
273
  });
182
274
 
183
- test('disconnects a connection callback that arrives after timeout', async () => {
184
- jest.useFakeTimers({ doNotFake: ['performance'] });
185
-
186
- const handlers = new Map<string, IpcHandler>();
187
- const ipcMain = {
188
- handle: jest.fn((channel: string, handler: IpcHandler) => {
189
- handlers.set(channel, handler);
190
- }),
191
- removeHandler: jest.fn((channel: string) => {
192
- handlers.delete(channel);
193
- }),
194
- };
195
- const noble = new EventEmitter() as EventEmitter & {
196
- state: string;
197
- startScanning: jest.Mock;
198
- stopScanning: jest.Mock;
199
- };
200
- let connectCallback: ((error?: Error) => void) | undefined;
201
- let resolveConnectStarted = () => undefined;
202
- const connectStarted = new Promise<void>(resolve => {
203
- resolveConnectStarted = resolve;
275
+ test('settles a pending Noble connect with the native disconnect error', () => {
276
+ // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
277
+ const Noble = require('@stoprocent/noble/lib/noble');
278
+ const bindings = Object.assign(new EventEmitter(), {
279
+ connect: jest.fn(),
204
280
  });
205
- const peripheral = Object.assign(
206
- new EventEmitter(),
207
- createPeripheral('slow-device', 'Pro2 A1B2'),
208
- {
209
- connect: jest.fn((callback: (error?: Error) => void) => {
210
- connectCallback = callback;
211
- resolveConnectStarted();
212
- }),
213
- disconnect: jest.fn((callback: () => void) => callback()),
214
- }
281
+ const noble = new Noble(bindings);
282
+ noble._registerListeners();
283
+ const peripheral = noble._createPeripheral(
284
+ 'aabbccdd',
285
+ '',
286
+ 'unknown',
287
+ true,
288
+ { localName: 'Pro2 A1B2', serviceUuids: ['0001'] },
289
+ -50,
290
+ false
215
291
  );
216
- noble.state = 'poweredOn';
217
- noble.startScanning = jest.fn((_services, _duplicates, callback) => {
218
- callback?.();
219
- noble.emit('discover', peripheral);
220
- });
221
- noble.stopScanning = jest.fn(callback => callback?.());
292
+ const connectCallback = jest.fn();
222
293
 
223
- jest.doMock('@stoprocent/noble', () => noble);
224
- jest.doMock('electron', () => ({ ipcMain }));
225
- jest.doMock('electron-log', () => ({
226
- info: jest.fn(),
227
- debug: jest.fn(),
228
- error: jest.fn(),
229
- }));
230
-
231
- const { setupNobleBleHandlers } = await import('../noble-ble-handler');
232
- setupNobleBleHandlers({
233
- on: jest.fn(),
234
- send: jest.fn(),
235
- } as unknown as WebContents);
236
-
237
- const connect = handlers.get(EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT);
238
- if (!connect) {
239
- throw new Error('Electron Noble BLE connect handler was not registered');
240
- }
241
-
242
- const connectPromise = Promise.resolve(connect(undefined, 'slow-device'));
243
- await connectStarted;
244
- expect(peripheral.connect).toHaveBeenCalledTimes(1);
245
-
246
- jest.advanceTimersByTime(NOBLE_BLE_CONNECTION_TIMEOUT_MS);
247
- await expect(connectPromise).rejects.toThrow('Connection timeout');
294
+ peripheral.connect(connectCallback);
295
+ const nativeError = new Error(
296
+ 'CBErrorDomain:14 Peer removed pairing information on the device side'
297
+ );
298
+ bindings.emit('disconnect', 'aabbccdd', nativeError);
248
299
 
249
- connectCallback?.();
250
- await Promise.resolve();
251
- expect(peripheral.disconnect).toHaveBeenCalledTimes(1);
300
+ expect(connectCallback).toHaveBeenCalledWith(nativeError);
301
+ expect(peripheral.state).toBe('disconnected');
252
302
  });
253
303
 
254
304
  test('enumerates a Pro2 communication advertisement after Find My changes its name', async () => {
@@ -1,5 +1,19 @@
1
1
  const BLE_ATT_HEADER_BYTES = 3;
2
2
 
3
+ export function resolveNobleAttMtu(
4
+ reportedMtu: number | null | undefined,
5
+ platform: NodeJS.Platform = process.platform
6
+ ): number | undefined {
7
+ if (typeof reportedMtu !== 'number' || !Number.isFinite(reportedMtu) || reportedMtu <= 0) {
8
+ return undefined;
9
+ }
10
+
11
+ const normalizedMtu = Math.floor(reportedMtu);
12
+ return platform === 'darwin' || platform === 'win32'
13
+ ? normalizedMtu + BLE_ATT_HEADER_BYTES
14
+ : normalizedMtu;
15
+ }
16
+
3
17
  export function resolveBlePacketCapacity(
4
18
  mtu: number | null | undefined,
5
19
  maximumPacketCapacity: number,
package/src/index.ts CHANGED
@@ -3,7 +3,13 @@ import type { WebContents } from 'electron';
3
3
  export * from './types';
4
4
 
5
5
  // Export Desktop API types for other packages to reuse
6
- export type { DesktopAPI, NobleBleAPI, NobleBleWriteOptions } from './types/desktop-api';
6
+ export type {
7
+ DesktopAPI,
8
+ NobleBleAPI,
9
+ NobleBleIpcErrorPayload,
10
+ NobleBleIpcErrorResponse,
11
+ NobleBleWriteOptions,
12
+ } from './types/desktop-api';
7
13
 
8
14
  export async function initNobleBleSupport(webContents: WebContents) {
9
15
  const { setupNobleBleHandlers } = await import('./noble-ble-handler');