react-native-ble-nitro 1.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +298 -0
- package/android/build.gradle +55 -0
- package/android/src/main/AndroidManifest.xml +23 -0
- package/android/src/main/kotlin/co/zyke/ble/BleNitroBleManager.kt +651 -0
- package/android/src/main/kotlin/co/zyke/ble/BleNitroPackage.kt +37 -0
- package/ios/BleNitro.podspec +37 -0
- package/ios/BleNitroBleManager.swift +509 -0
- package/ios/BleNitroModule.swift +31 -0
- package/lib/BleManagerCompatFactory.d.ts +53 -0
- package/lib/BleManagerCompatFactory.js +191 -0
- package/lib/BleManagerFactory.d.ts +12 -0
- package/lib/BleManagerFactory.js +22 -0
- package/lib/compatibility/constants.d.ts +49 -0
- package/lib/compatibility/constants.js +50 -0
- package/lib/compatibility/deviceWrapper.d.ts +99 -0
- package/lib/compatibility/deviceWrapper.js +259 -0
- package/lib/compatibility/enums.d.ts +43 -0
- package/lib/compatibility/enums.js +124 -0
- package/lib/compatibility/index.d.ts +11 -0
- package/lib/compatibility/index.js +12 -0
- package/lib/compatibility/serviceData.d.ts +51 -0
- package/lib/compatibility/serviceData.js +70 -0
- package/lib/errors/BleError.d.ts +59 -0
- package/lib/errors/BleError.js +120 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +12 -0
- package/lib/specs/BleManager.nitro.d.ts +36 -0
- package/lib/specs/BleManager.nitro.js +1 -0
- package/lib/specs/Characteristic.nitro.d.ts +26 -0
- package/lib/specs/Characteristic.nitro.js +1 -0
- package/lib/specs/Descriptor.nitro.d.ts +17 -0
- package/lib/specs/Descriptor.nitro.js +1 -0
- package/lib/specs/Device.nitro.d.ts +37 -0
- package/lib/specs/Device.nitro.js +1 -0
- package/lib/specs/Service.nitro.d.ts +19 -0
- package/lib/specs/Service.nitro.js +1 -0
- package/lib/specs/types.d.ts +228 -0
- package/lib/specs/types.js +146 -0
- package/lib/utils/base64.d.ts +25 -0
- package/lib/utils/base64.js +80 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/uuid.d.ts +9 -0
- package/lib/utils/uuid.js +37 -0
- package/nitro.json +15 -0
- package/package.json +102 -0
- package/plugin/build/index.d.ts +28 -0
- package/plugin/build/index.js +29 -0
- package/plugin/build/withBleNitro.d.ts +31 -0
- package/plugin/build/withBleNitro.js +87 -0
- package/react-native.config.js +13 -0
- package/src/BleManagerCompatFactory.ts +373 -0
- package/src/BleManagerFactory.ts +30 -0
- package/src/__tests__/BleManager.test.ts +327 -0
- package/src/__tests__/compatibility/deviceWrapper.test.ts +563 -0
- package/src/__tests__/compatibility/enums.test.ts +254 -0
- package/src/compatibility/constants.ts +71 -0
- package/src/compatibility/deviceWrapper.ts +427 -0
- package/src/compatibility/enums.ts +160 -0
- package/src/compatibility/index.ts +24 -0
- package/src/compatibility/serviceData.ts +85 -0
- package/src/errors/BleError.ts +193 -0
- package/src/index.ts +30 -0
- package/src/specs/BleManager.nitro.ts +152 -0
- package/src/specs/Characteristic.nitro.ts +61 -0
- package/src/specs/Descriptor.nitro.ts +28 -0
- package/src/specs/Device.nitro.ts +104 -0
- package/src/specs/Service.nitro.ts +64 -0
- package/src/specs/types.ts +259 -0
- package/src/utils/base64.ts +80 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/uuid.ts +45 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
+
import type { Identifier, UUID, DeviceId, Base64, TransactionId, CharacteristicSubscriptionType, NativeCharacteristic, NativeDescriptor, CharacteristicMonitorListener, Subscription } from './types';
|
|
3
|
+
export interface Service extends HybridObject<{
|
|
4
|
+
ios: 'swift';
|
|
5
|
+
android: 'kotlin';
|
|
6
|
+
}> {
|
|
7
|
+
readonly id: Identifier;
|
|
8
|
+
readonly uuid: UUID;
|
|
9
|
+
readonly deviceID: DeviceId;
|
|
10
|
+
readonly isPrimary: boolean;
|
|
11
|
+
characteristics(): Promise<NativeCharacteristic[]>;
|
|
12
|
+
readCharacteristic(characteristicUUID: UUID, transactionId?: TransactionId): Promise<NativeCharacteristic>;
|
|
13
|
+
writeCharacteristicWithResponse(characteristicUUID: UUID, valueBase64: Base64, transactionId?: TransactionId): Promise<NativeCharacteristic>;
|
|
14
|
+
writeCharacteristicWithoutResponse(characteristicUUID: UUID, valueBase64: Base64, transactionId?: TransactionId): Promise<NativeCharacteristic>;
|
|
15
|
+
monitorCharacteristic(characteristicUUID: UUID, listener: CharacteristicMonitorListener, transactionId?: TransactionId, subscriptionType?: CharacteristicSubscriptionType): Subscription;
|
|
16
|
+
descriptorsForCharacteristic(characteristicUUID: UUID): Promise<NativeDescriptor[]>;
|
|
17
|
+
readDescriptorForCharacteristic(characteristicUUID: UUID, descriptorUUID: UUID, transactionId?: TransactionId): Promise<NativeDescriptor>;
|
|
18
|
+
writeDescriptorForCharacteristic(characteristicUUID: UUID, descriptorUUID: UUID, valueBase64: Base64, transactionId?: TransactionId): Promise<NativeDescriptor>;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
export type Base64 = string;
|
|
2
|
+
export type UUID = string;
|
|
3
|
+
export type Identifier = number;
|
|
4
|
+
export type DeviceId = string;
|
|
5
|
+
export type TransactionId = string;
|
|
6
|
+
export declare enum RefreshGattMoment {
|
|
7
|
+
OnConnected = 0
|
|
8
|
+
}
|
|
9
|
+
export declare enum CharacteristicSubscriptionType {
|
|
10
|
+
Notification = 0,
|
|
11
|
+
Indication = 1
|
|
12
|
+
}
|
|
13
|
+
export interface ServiceDataEntry {
|
|
14
|
+
uuid: UUID;
|
|
15
|
+
data: Base64;
|
|
16
|
+
}
|
|
17
|
+
export declare enum State {
|
|
18
|
+
Unknown = 0,
|
|
19
|
+
Resetting = 1,
|
|
20
|
+
Unsupported = 2,
|
|
21
|
+
Unauthorized = 3,
|
|
22
|
+
PoweredOff = 4,
|
|
23
|
+
PoweredOn = 5
|
|
24
|
+
}
|
|
25
|
+
export declare enum LogLevel {
|
|
26
|
+
None = 0,
|
|
27
|
+
Verbose = 1,
|
|
28
|
+
Debug = 2,
|
|
29
|
+
Info = 3,
|
|
30
|
+
Warning = 4,
|
|
31
|
+
Error = 5
|
|
32
|
+
}
|
|
33
|
+
export declare enum ScanMode {
|
|
34
|
+
Opportunistic = -1,
|
|
35
|
+
LowPower = 0,
|
|
36
|
+
Balanced = 1,
|
|
37
|
+
LowLatency = 2
|
|
38
|
+
}
|
|
39
|
+
export declare enum ScanCallbackType {
|
|
40
|
+
AllMatches = 1,
|
|
41
|
+
FirstMatch = 2,
|
|
42
|
+
MatchLost = 4
|
|
43
|
+
}
|
|
44
|
+
export declare enum ConnectionPriority {
|
|
45
|
+
Balanced = 0,
|
|
46
|
+
High = 1,
|
|
47
|
+
LowPower = 2
|
|
48
|
+
}
|
|
49
|
+
export declare enum BleErrorCode {
|
|
50
|
+
UnknownError = 0,
|
|
51
|
+
BluetoothManagerDestroyed = 1,
|
|
52
|
+
OperationCancelled = 2,
|
|
53
|
+
OperationTimedOut = 3,
|
|
54
|
+
OperationStartFailed = 4,
|
|
55
|
+
InvalidIdentifiers = 5,
|
|
56
|
+
BluetoothUnsupported = 100,
|
|
57
|
+
BluetoothUnauthorized = 101,
|
|
58
|
+
BluetoothPoweredOff = 102,
|
|
59
|
+
BluetoothInUnknownState = 103,
|
|
60
|
+
BluetoothResetting = 104,
|
|
61
|
+
BluetoothStateChangeFailed = 105,
|
|
62
|
+
DeviceConnectionFailed = 200,
|
|
63
|
+
DeviceDisconnected = 201,
|
|
64
|
+
DeviceRSSIReadFailed = 202,
|
|
65
|
+
DeviceAlreadyConnected = 203,
|
|
66
|
+
DeviceNotFound = 204,
|
|
67
|
+
DeviceNotConnected = 205,
|
|
68
|
+
DeviceMTUChangeFailed = 206,
|
|
69
|
+
ServicesDiscoveryFailed = 300,
|
|
70
|
+
IncludedServicesDiscoveryFailed = 301,
|
|
71
|
+
ServiceNotFound = 302,
|
|
72
|
+
ServicesNotDiscovered = 303,
|
|
73
|
+
CharacteristicsDiscoveryFailed = 400,
|
|
74
|
+
CharacteristicWriteFailed = 401,
|
|
75
|
+
CharacteristicReadFailed = 402,
|
|
76
|
+
CharacteristicNotifyChangeFailed = 403,
|
|
77
|
+
CharacteristicNotFound = 404,
|
|
78
|
+
CharacteristicsNotDiscovered = 405,
|
|
79
|
+
CharacteristicInvalidDataFormat = 406,
|
|
80
|
+
DescriptorsDiscoveryFailed = 500,
|
|
81
|
+
DescriptorWriteFailed = 501,
|
|
82
|
+
DescriptorReadFailed = 502,
|
|
83
|
+
DescriptorNotFound = 503,
|
|
84
|
+
DescriptorsNotDiscovered = 504,
|
|
85
|
+
DescriptorInvalidDataFormat = 505,
|
|
86
|
+
DescriptorWriteNotAllowed = 506,
|
|
87
|
+
ScanStartFailed = 600,
|
|
88
|
+
LocationServicesDisabled = 601
|
|
89
|
+
}
|
|
90
|
+
export declare enum BleATTErrorCode {
|
|
91
|
+
Success = 0,
|
|
92
|
+
InvalidHandle = 1,
|
|
93
|
+
ReadNotPermitted = 2,
|
|
94
|
+
WriteNotPermitted = 3,
|
|
95
|
+
InvalidPdu = 4,
|
|
96
|
+
InsufficientAuthentication = 5,
|
|
97
|
+
RequestNotSupported = 6,
|
|
98
|
+
InvalidOffset = 7,
|
|
99
|
+
InsufficientAuthorization = 8,
|
|
100
|
+
PrepareQueueFull = 9,
|
|
101
|
+
AttributeNotFound = 10,
|
|
102
|
+
AttributeNotLong = 11,
|
|
103
|
+
InsufficientEncryptionKeySize = 12,
|
|
104
|
+
InvalidAttributeValueLength = 13,
|
|
105
|
+
UnlikelyError = 14,
|
|
106
|
+
InsufficientEncryption = 15,
|
|
107
|
+
UnsupportedGroupType = 16,
|
|
108
|
+
InsufficientResources = 17
|
|
109
|
+
}
|
|
110
|
+
export declare enum BleIOSErrorCode {
|
|
111
|
+
Unknown = 0,
|
|
112
|
+
InvalidParameters = 1,
|
|
113
|
+
InvalidHandle = 2,
|
|
114
|
+
NotConnected = 3,
|
|
115
|
+
OutOfSpace = 4,
|
|
116
|
+
OperationCancelled = 5,
|
|
117
|
+
ConnectionTimeout = 6,
|
|
118
|
+
PeripheralDisconnected = 7,
|
|
119
|
+
UuidNotAllowed = 8,
|
|
120
|
+
AlreadyAdvertising = 9,
|
|
121
|
+
ConnectionFailed = 10,
|
|
122
|
+
ConnectionLimitReached = 11,
|
|
123
|
+
UnknownDevice = 12
|
|
124
|
+
}
|
|
125
|
+
export declare enum BleAndroidErrorCode {
|
|
126
|
+
NoResources = 128,
|
|
127
|
+
InternalError = 129,
|
|
128
|
+
WrongState = 130,
|
|
129
|
+
DbFull = 131,
|
|
130
|
+
Busy = 132,
|
|
131
|
+
Error = 133,
|
|
132
|
+
CmdStarted = 134,
|
|
133
|
+
IllegalParameter = 135,
|
|
134
|
+
Pending = 136,
|
|
135
|
+
AuthFail = 137,
|
|
136
|
+
More = 138,
|
|
137
|
+
InvalidCfg = 139,
|
|
138
|
+
ServiceStarted = 140,
|
|
139
|
+
EncrypedNoMitm = 141,
|
|
140
|
+
NotEncrypted = 142,
|
|
141
|
+
Congested = 143
|
|
142
|
+
}
|
|
143
|
+
export interface ScanOptions {
|
|
144
|
+
allowDuplicates?: boolean;
|
|
145
|
+
scanMode?: ScanMode;
|
|
146
|
+
callbackType?: ScanCallbackType;
|
|
147
|
+
legacyScan?: boolean;
|
|
148
|
+
}
|
|
149
|
+
export interface ConnectionOptions {
|
|
150
|
+
autoConnect: boolean;
|
|
151
|
+
requestMTU: number;
|
|
152
|
+
timeout: number;
|
|
153
|
+
}
|
|
154
|
+
export interface BleManagerOptions {
|
|
155
|
+
restoreStateIdentifier?: string;
|
|
156
|
+
restoreStateFunction?: (restoredState: BleRestoredState | null) => void;
|
|
157
|
+
errorCodesToMessagesMapping?: BleErrorCodeMessageMapping;
|
|
158
|
+
}
|
|
159
|
+
export interface BleRestoredState {
|
|
160
|
+
connectedPeripherals: NativeDevice[];
|
|
161
|
+
}
|
|
162
|
+
export type BleErrorCodeMessageMapping = {
|
|
163
|
+
[key in BleErrorCode]: string;
|
|
164
|
+
};
|
|
165
|
+
export interface NativeDevice {
|
|
166
|
+
id: DeviceId;
|
|
167
|
+
name: string | null;
|
|
168
|
+
rssi: number | null;
|
|
169
|
+
mtu: number;
|
|
170
|
+
manufacturerData: Base64 | null;
|
|
171
|
+
rawScanRecord: Base64;
|
|
172
|
+
serviceData: ServiceDataEntry[] | null;
|
|
173
|
+
serviceUUIDs: UUID[] | null;
|
|
174
|
+
localName: string | null;
|
|
175
|
+
txPowerLevel: number | null;
|
|
176
|
+
solicitedServiceUUIDs: UUID[] | null;
|
|
177
|
+
isConnectable: boolean | null;
|
|
178
|
+
overflowServiceUUIDs: UUID[] | null;
|
|
179
|
+
}
|
|
180
|
+
export interface NativeService {
|
|
181
|
+
id: Identifier;
|
|
182
|
+
uuid: UUID;
|
|
183
|
+
deviceID: DeviceId;
|
|
184
|
+
isPrimary: boolean;
|
|
185
|
+
}
|
|
186
|
+
export interface NativeCharacteristic {
|
|
187
|
+
id: Identifier;
|
|
188
|
+
uuid: UUID;
|
|
189
|
+
serviceID: Identifier;
|
|
190
|
+
serviceUUID: UUID;
|
|
191
|
+
deviceID: DeviceId;
|
|
192
|
+
isReadable: boolean;
|
|
193
|
+
isWritableWithResponse: boolean;
|
|
194
|
+
isWritableWithoutResponse: boolean;
|
|
195
|
+
isNotifiable: boolean;
|
|
196
|
+
isNotifying: boolean;
|
|
197
|
+
isIndicatable: boolean;
|
|
198
|
+
value: Base64 | null;
|
|
199
|
+
}
|
|
200
|
+
export interface NativeDescriptor {
|
|
201
|
+
id: Identifier;
|
|
202
|
+
uuid: UUID;
|
|
203
|
+
characteristicID: Identifier;
|
|
204
|
+
characteristicUUID: UUID;
|
|
205
|
+
serviceID: Identifier;
|
|
206
|
+
serviceUUID: UUID;
|
|
207
|
+
deviceID: DeviceId;
|
|
208
|
+
value: Base64 | null;
|
|
209
|
+
}
|
|
210
|
+
export interface NativeBleError {
|
|
211
|
+
errorCode: BleErrorCode;
|
|
212
|
+
attErrorCode: BleATTErrorCode | null;
|
|
213
|
+
iosErrorCode: BleIOSErrorCode | null;
|
|
214
|
+
androidErrorCode: BleAndroidErrorCode | null;
|
|
215
|
+
reason: string | null;
|
|
216
|
+
deviceID?: string;
|
|
217
|
+
serviceUUID?: string;
|
|
218
|
+
characteristicUUID?: string;
|
|
219
|
+
descriptorUUID?: string;
|
|
220
|
+
internalMessage?: string;
|
|
221
|
+
}
|
|
222
|
+
export interface Subscription {
|
|
223
|
+
remove(): void;
|
|
224
|
+
}
|
|
225
|
+
export type StateListener = (newState: State) => void;
|
|
226
|
+
export type DeviceScanListener = (error: NativeBleError | null, scannedDevice: NativeDevice | null) => void;
|
|
227
|
+
export type DeviceDisconnectedListener = (error: NativeBleError | null, device: NativeDevice | null) => void;
|
|
228
|
+
export type CharacteristicMonitorListener = (error: NativeBleError | null, characteristic: NativeCharacteristic | null) => void;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export var RefreshGattMoment;
|
|
2
|
+
(function (RefreshGattMoment) {
|
|
3
|
+
RefreshGattMoment[RefreshGattMoment["OnConnected"] = 0] = "OnConnected";
|
|
4
|
+
})(RefreshGattMoment || (RefreshGattMoment = {}));
|
|
5
|
+
export var CharacteristicSubscriptionType;
|
|
6
|
+
(function (CharacteristicSubscriptionType) {
|
|
7
|
+
CharacteristicSubscriptionType[CharacteristicSubscriptionType["Notification"] = 0] = "Notification";
|
|
8
|
+
CharacteristicSubscriptionType[CharacteristicSubscriptionType["Indication"] = 1] = "Indication";
|
|
9
|
+
})(CharacteristicSubscriptionType || (CharacteristicSubscriptionType = {}));
|
|
10
|
+
// Enums
|
|
11
|
+
export var State;
|
|
12
|
+
(function (State) {
|
|
13
|
+
State[State["Unknown"] = 0] = "Unknown";
|
|
14
|
+
State[State["Resetting"] = 1] = "Resetting";
|
|
15
|
+
State[State["Unsupported"] = 2] = "Unsupported";
|
|
16
|
+
State[State["Unauthorized"] = 3] = "Unauthorized";
|
|
17
|
+
State[State["PoweredOff"] = 4] = "PoweredOff";
|
|
18
|
+
State[State["PoweredOn"] = 5] = "PoweredOn";
|
|
19
|
+
})(State || (State = {}));
|
|
20
|
+
export var LogLevel;
|
|
21
|
+
(function (LogLevel) {
|
|
22
|
+
LogLevel[LogLevel["None"] = 0] = "None";
|
|
23
|
+
LogLevel[LogLevel["Verbose"] = 1] = "Verbose";
|
|
24
|
+
LogLevel[LogLevel["Debug"] = 2] = "Debug";
|
|
25
|
+
LogLevel[LogLevel["Info"] = 3] = "Info";
|
|
26
|
+
LogLevel[LogLevel["Warning"] = 4] = "Warning";
|
|
27
|
+
LogLevel[LogLevel["Error"] = 5] = "Error";
|
|
28
|
+
})(LogLevel || (LogLevel = {}));
|
|
29
|
+
export var ScanMode;
|
|
30
|
+
(function (ScanMode) {
|
|
31
|
+
ScanMode[ScanMode["Opportunistic"] = -1] = "Opportunistic";
|
|
32
|
+
ScanMode[ScanMode["LowPower"] = 0] = "LowPower";
|
|
33
|
+
ScanMode[ScanMode["Balanced"] = 1] = "Balanced";
|
|
34
|
+
ScanMode[ScanMode["LowLatency"] = 2] = "LowLatency";
|
|
35
|
+
})(ScanMode || (ScanMode = {}));
|
|
36
|
+
export var ScanCallbackType;
|
|
37
|
+
(function (ScanCallbackType) {
|
|
38
|
+
ScanCallbackType[ScanCallbackType["AllMatches"] = 1] = "AllMatches";
|
|
39
|
+
ScanCallbackType[ScanCallbackType["FirstMatch"] = 2] = "FirstMatch";
|
|
40
|
+
ScanCallbackType[ScanCallbackType["MatchLost"] = 4] = "MatchLost";
|
|
41
|
+
})(ScanCallbackType || (ScanCallbackType = {}));
|
|
42
|
+
export var ConnectionPriority;
|
|
43
|
+
(function (ConnectionPriority) {
|
|
44
|
+
ConnectionPriority[ConnectionPriority["Balanced"] = 0] = "Balanced";
|
|
45
|
+
ConnectionPriority[ConnectionPriority["High"] = 1] = "High";
|
|
46
|
+
ConnectionPriority[ConnectionPriority["LowPower"] = 2] = "LowPower";
|
|
47
|
+
})(ConnectionPriority || (ConnectionPriority = {}));
|
|
48
|
+
// Complex error code enums
|
|
49
|
+
export var BleErrorCode;
|
|
50
|
+
(function (BleErrorCode) {
|
|
51
|
+
BleErrorCode[BleErrorCode["UnknownError"] = 0] = "UnknownError";
|
|
52
|
+
BleErrorCode[BleErrorCode["BluetoothManagerDestroyed"] = 1] = "BluetoothManagerDestroyed";
|
|
53
|
+
BleErrorCode[BleErrorCode["OperationCancelled"] = 2] = "OperationCancelled";
|
|
54
|
+
BleErrorCode[BleErrorCode["OperationTimedOut"] = 3] = "OperationTimedOut";
|
|
55
|
+
BleErrorCode[BleErrorCode["OperationStartFailed"] = 4] = "OperationStartFailed";
|
|
56
|
+
BleErrorCode[BleErrorCode["InvalidIdentifiers"] = 5] = "InvalidIdentifiers";
|
|
57
|
+
BleErrorCode[BleErrorCode["BluetoothUnsupported"] = 100] = "BluetoothUnsupported";
|
|
58
|
+
BleErrorCode[BleErrorCode["BluetoothUnauthorized"] = 101] = "BluetoothUnauthorized";
|
|
59
|
+
BleErrorCode[BleErrorCode["BluetoothPoweredOff"] = 102] = "BluetoothPoweredOff";
|
|
60
|
+
BleErrorCode[BleErrorCode["BluetoothInUnknownState"] = 103] = "BluetoothInUnknownState";
|
|
61
|
+
BleErrorCode[BleErrorCode["BluetoothResetting"] = 104] = "BluetoothResetting";
|
|
62
|
+
BleErrorCode[BleErrorCode["BluetoothStateChangeFailed"] = 105] = "BluetoothStateChangeFailed";
|
|
63
|
+
BleErrorCode[BleErrorCode["DeviceConnectionFailed"] = 200] = "DeviceConnectionFailed";
|
|
64
|
+
BleErrorCode[BleErrorCode["DeviceDisconnected"] = 201] = "DeviceDisconnected";
|
|
65
|
+
BleErrorCode[BleErrorCode["DeviceRSSIReadFailed"] = 202] = "DeviceRSSIReadFailed";
|
|
66
|
+
BleErrorCode[BleErrorCode["DeviceAlreadyConnected"] = 203] = "DeviceAlreadyConnected";
|
|
67
|
+
BleErrorCode[BleErrorCode["DeviceNotFound"] = 204] = "DeviceNotFound";
|
|
68
|
+
BleErrorCode[BleErrorCode["DeviceNotConnected"] = 205] = "DeviceNotConnected";
|
|
69
|
+
BleErrorCode[BleErrorCode["DeviceMTUChangeFailed"] = 206] = "DeviceMTUChangeFailed";
|
|
70
|
+
BleErrorCode[BleErrorCode["ServicesDiscoveryFailed"] = 300] = "ServicesDiscoveryFailed";
|
|
71
|
+
BleErrorCode[BleErrorCode["IncludedServicesDiscoveryFailed"] = 301] = "IncludedServicesDiscoveryFailed";
|
|
72
|
+
BleErrorCode[BleErrorCode["ServiceNotFound"] = 302] = "ServiceNotFound";
|
|
73
|
+
BleErrorCode[BleErrorCode["ServicesNotDiscovered"] = 303] = "ServicesNotDiscovered";
|
|
74
|
+
BleErrorCode[BleErrorCode["CharacteristicsDiscoveryFailed"] = 400] = "CharacteristicsDiscoveryFailed";
|
|
75
|
+
BleErrorCode[BleErrorCode["CharacteristicWriteFailed"] = 401] = "CharacteristicWriteFailed";
|
|
76
|
+
BleErrorCode[BleErrorCode["CharacteristicReadFailed"] = 402] = "CharacteristicReadFailed";
|
|
77
|
+
BleErrorCode[BleErrorCode["CharacteristicNotifyChangeFailed"] = 403] = "CharacteristicNotifyChangeFailed";
|
|
78
|
+
BleErrorCode[BleErrorCode["CharacteristicNotFound"] = 404] = "CharacteristicNotFound";
|
|
79
|
+
BleErrorCode[BleErrorCode["CharacteristicsNotDiscovered"] = 405] = "CharacteristicsNotDiscovered";
|
|
80
|
+
BleErrorCode[BleErrorCode["CharacteristicInvalidDataFormat"] = 406] = "CharacteristicInvalidDataFormat";
|
|
81
|
+
BleErrorCode[BleErrorCode["DescriptorsDiscoveryFailed"] = 500] = "DescriptorsDiscoveryFailed";
|
|
82
|
+
BleErrorCode[BleErrorCode["DescriptorWriteFailed"] = 501] = "DescriptorWriteFailed";
|
|
83
|
+
BleErrorCode[BleErrorCode["DescriptorReadFailed"] = 502] = "DescriptorReadFailed";
|
|
84
|
+
BleErrorCode[BleErrorCode["DescriptorNotFound"] = 503] = "DescriptorNotFound";
|
|
85
|
+
BleErrorCode[BleErrorCode["DescriptorsNotDiscovered"] = 504] = "DescriptorsNotDiscovered";
|
|
86
|
+
BleErrorCode[BleErrorCode["DescriptorInvalidDataFormat"] = 505] = "DescriptorInvalidDataFormat";
|
|
87
|
+
BleErrorCode[BleErrorCode["DescriptorWriteNotAllowed"] = 506] = "DescriptorWriteNotAllowed";
|
|
88
|
+
BleErrorCode[BleErrorCode["ScanStartFailed"] = 600] = "ScanStartFailed";
|
|
89
|
+
BleErrorCode[BleErrorCode["LocationServicesDisabled"] = 601] = "LocationServicesDisabled";
|
|
90
|
+
})(BleErrorCode || (BleErrorCode = {}));
|
|
91
|
+
export var BleATTErrorCode;
|
|
92
|
+
(function (BleATTErrorCode) {
|
|
93
|
+
BleATTErrorCode[BleATTErrorCode["Success"] = 0] = "Success";
|
|
94
|
+
BleATTErrorCode[BleATTErrorCode["InvalidHandle"] = 1] = "InvalidHandle";
|
|
95
|
+
BleATTErrorCode[BleATTErrorCode["ReadNotPermitted"] = 2] = "ReadNotPermitted";
|
|
96
|
+
BleATTErrorCode[BleATTErrorCode["WriteNotPermitted"] = 3] = "WriteNotPermitted";
|
|
97
|
+
BleATTErrorCode[BleATTErrorCode["InvalidPdu"] = 4] = "InvalidPdu";
|
|
98
|
+
BleATTErrorCode[BleATTErrorCode["InsufficientAuthentication"] = 5] = "InsufficientAuthentication";
|
|
99
|
+
BleATTErrorCode[BleATTErrorCode["RequestNotSupported"] = 6] = "RequestNotSupported";
|
|
100
|
+
BleATTErrorCode[BleATTErrorCode["InvalidOffset"] = 7] = "InvalidOffset";
|
|
101
|
+
BleATTErrorCode[BleATTErrorCode["InsufficientAuthorization"] = 8] = "InsufficientAuthorization";
|
|
102
|
+
BleATTErrorCode[BleATTErrorCode["PrepareQueueFull"] = 9] = "PrepareQueueFull";
|
|
103
|
+
BleATTErrorCode[BleATTErrorCode["AttributeNotFound"] = 10] = "AttributeNotFound";
|
|
104
|
+
BleATTErrorCode[BleATTErrorCode["AttributeNotLong"] = 11] = "AttributeNotLong";
|
|
105
|
+
BleATTErrorCode[BleATTErrorCode["InsufficientEncryptionKeySize"] = 12] = "InsufficientEncryptionKeySize";
|
|
106
|
+
BleATTErrorCode[BleATTErrorCode["InvalidAttributeValueLength"] = 13] = "InvalidAttributeValueLength";
|
|
107
|
+
BleATTErrorCode[BleATTErrorCode["UnlikelyError"] = 14] = "UnlikelyError";
|
|
108
|
+
BleATTErrorCode[BleATTErrorCode["InsufficientEncryption"] = 15] = "InsufficientEncryption";
|
|
109
|
+
BleATTErrorCode[BleATTErrorCode["UnsupportedGroupType"] = 16] = "UnsupportedGroupType";
|
|
110
|
+
BleATTErrorCode[BleATTErrorCode["InsufficientResources"] = 17] = "InsufficientResources";
|
|
111
|
+
})(BleATTErrorCode || (BleATTErrorCode = {}));
|
|
112
|
+
export var BleIOSErrorCode;
|
|
113
|
+
(function (BleIOSErrorCode) {
|
|
114
|
+
BleIOSErrorCode[BleIOSErrorCode["Unknown"] = 0] = "Unknown";
|
|
115
|
+
BleIOSErrorCode[BleIOSErrorCode["InvalidParameters"] = 1] = "InvalidParameters";
|
|
116
|
+
BleIOSErrorCode[BleIOSErrorCode["InvalidHandle"] = 2] = "InvalidHandle";
|
|
117
|
+
BleIOSErrorCode[BleIOSErrorCode["NotConnected"] = 3] = "NotConnected";
|
|
118
|
+
BleIOSErrorCode[BleIOSErrorCode["OutOfSpace"] = 4] = "OutOfSpace";
|
|
119
|
+
BleIOSErrorCode[BleIOSErrorCode["OperationCancelled"] = 5] = "OperationCancelled";
|
|
120
|
+
BleIOSErrorCode[BleIOSErrorCode["ConnectionTimeout"] = 6] = "ConnectionTimeout";
|
|
121
|
+
BleIOSErrorCode[BleIOSErrorCode["PeripheralDisconnected"] = 7] = "PeripheralDisconnected";
|
|
122
|
+
BleIOSErrorCode[BleIOSErrorCode["UuidNotAllowed"] = 8] = "UuidNotAllowed";
|
|
123
|
+
BleIOSErrorCode[BleIOSErrorCode["AlreadyAdvertising"] = 9] = "AlreadyAdvertising";
|
|
124
|
+
BleIOSErrorCode[BleIOSErrorCode["ConnectionFailed"] = 10] = "ConnectionFailed";
|
|
125
|
+
BleIOSErrorCode[BleIOSErrorCode["ConnectionLimitReached"] = 11] = "ConnectionLimitReached";
|
|
126
|
+
BleIOSErrorCode[BleIOSErrorCode["UnknownDevice"] = 12] = "UnknownDevice";
|
|
127
|
+
})(BleIOSErrorCode || (BleIOSErrorCode = {}));
|
|
128
|
+
export var BleAndroidErrorCode;
|
|
129
|
+
(function (BleAndroidErrorCode) {
|
|
130
|
+
BleAndroidErrorCode[BleAndroidErrorCode["NoResources"] = 128] = "NoResources";
|
|
131
|
+
BleAndroidErrorCode[BleAndroidErrorCode["InternalError"] = 129] = "InternalError";
|
|
132
|
+
BleAndroidErrorCode[BleAndroidErrorCode["WrongState"] = 130] = "WrongState";
|
|
133
|
+
BleAndroidErrorCode[BleAndroidErrorCode["DbFull"] = 131] = "DbFull";
|
|
134
|
+
BleAndroidErrorCode[BleAndroidErrorCode["Busy"] = 132] = "Busy";
|
|
135
|
+
BleAndroidErrorCode[BleAndroidErrorCode["Error"] = 133] = "Error";
|
|
136
|
+
BleAndroidErrorCode[BleAndroidErrorCode["CmdStarted"] = 134] = "CmdStarted";
|
|
137
|
+
BleAndroidErrorCode[BleAndroidErrorCode["IllegalParameter"] = 135] = "IllegalParameter";
|
|
138
|
+
BleAndroidErrorCode[BleAndroidErrorCode["Pending"] = 136] = "Pending";
|
|
139
|
+
BleAndroidErrorCode[BleAndroidErrorCode["AuthFail"] = 137] = "AuthFail";
|
|
140
|
+
BleAndroidErrorCode[BleAndroidErrorCode["More"] = 138] = "More";
|
|
141
|
+
BleAndroidErrorCode[BleAndroidErrorCode["InvalidCfg"] = 139] = "InvalidCfg";
|
|
142
|
+
BleAndroidErrorCode[BleAndroidErrorCode["ServiceStarted"] = 140] = "ServiceStarted";
|
|
143
|
+
BleAndroidErrorCode[BleAndroidErrorCode["EncrypedNoMitm"] = 141] = "EncrypedNoMitm";
|
|
144
|
+
BleAndroidErrorCode[BleAndroidErrorCode["NotEncrypted"] = 142] = "NotEncrypted";
|
|
145
|
+
BleAndroidErrorCode[BleAndroidErrorCode["Congested"] = 143] = "Congested";
|
|
146
|
+
})(BleAndroidErrorCode || (BleAndroidErrorCode = {}));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Base64 } from '../specs/types';
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for Base64 encoding/decoding
|
|
4
|
+
* Maintains compatibility with react-native-ble-plx Base64 operations
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Converts a string to Base64
|
|
8
|
+
*/
|
|
9
|
+
export declare function stringToBase64(str: string): Base64;
|
|
10
|
+
/**
|
|
11
|
+
* Converts Base64 to string
|
|
12
|
+
*/
|
|
13
|
+
export declare function base64ToString(base64: Base64): string;
|
|
14
|
+
/**
|
|
15
|
+
* Converts Uint8Array to Base64
|
|
16
|
+
*/
|
|
17
|
+
export declare function uint8ArrayToBase64(uint8Array: Uint8Array): Base64;
|
|
18
|
+
/**
|
|
19
|
+
* Converts Base64 to Uint8Array
|
|
20
|
+
*/
|
|
21
|
+
export declare function base64ToUint8Array(base64: Base64): Uint8Array;
|
|
22
|
+
/**
|
|
23
|
+
* Validates if a string is valid Base64
|
|
24
|
+
*/
|
|
25
|
+
export declare function isValidBase64(str: string): boolean;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for Base64 encoding/decoding
|
|
3
|
+
* Maintains compatibility with react-native-ble-plx Base64 operations
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Converts a string to Base64
|
|
7
|
+
*/
|
|
8
|
+
export function stringToBase64(str) {
|
|
9
|
+
if (typeof Buffer !== 'undefined') {
|
|
10
|
+
// Node.js environment
|
|
11
|
+
return Buffer.from(str, 'utf8').toString('base64');
|
|
12
|
+
}
|
|
13
|
+
else if (typeof btoa !== 'undefined') {
|
|
14
|
+
// Browser environment
|
|
15
|
+
return btoa(str);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
throw new Error('Base64 encoding not supported in this environment');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Converts Base64 to string
|
|
23
|
+
*/
|
|
24
|
+
export function base64ToString(base64) {
|
|
25
|
+
if (typeof Buffer !== 'undefined') {
|
|
26
|
+
// Node.js environment
|
|
27
|
+
return Buffer.from(base64, 'base64').toString('utf8');
|
|
28
|
+
}
|
|
29
|
+
else if (typeof atob !== 'undefined') {
|
|
30
|
+
// Browser environment
|
|
31
|
+
return atob(base64);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw new Error('Base64 decoding not supported in this environment');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Converts Uint8Array to Base64
|
|
39
|
+
*/
|
|
40
|
+
export function uint8ArrayToBase64(uint8Array) {
|
|
41
|
+
if (typeof Buffer !== 'undefined') {
|
|
42
|
+
// Node.js environment
|
|
43
|
+
return Buffer.from(uint8Array).toString('base64');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Browser environment
|
|
47
|
+
const binary = Array.from(uint8Array, byte => String.fromCharCode(byte)).join('');
|
|
48
|
+
return btoa(binary);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Converts Base64 to Uint8Array
|
|
53
|
+
*/
|
|
54
|
+
export function base64ToUint8Array(base64) {
|
|
55
|
+
if (typeof Buffer !== 'undefined') {
|
|
56
|
+
// Node.js environment
|
|
57
|
+
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Browser environment
|
|
61
|
+
const binary = atob(base64);
|
|
62
|
+
const uint8Array = new Uint8Array(binary.length);
|
|
63
|
+
for (let i = 0; i < binary.length; i++) {
|
|
64
|
+
uint8Array[i] = binary.charCodeAt(i);
|
|
65
|
+
}
|
|
66
|
+
return uint8Array;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validates if a string is valid Base64
|
|
71
|
+
*/
|
|
72
|
+
export function isValidBase64(str) {
|
|
73
|
+
try {
|
|
74
|
+
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
75
|
+
return base64Regex.test(str) && (str.length % 4 === 0);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UUID } from '../specs/types';
|
|
2
|
+
/**
|
|
3
|
+
* Converts UUID to full 128bit, lowercase format which should be used to compare UUID values.
|
|
4
|
+
* This function maintains 100% compatibility with react-native-ble-plx
|
|
5
|
+
*
|
|
6
|
+
* @param uuid 16bit, 32bit or 128bit UUID.
|
|
7
|
+
* @returns 128bit lowercase UUID.
|
|
8
|
+
*/
|
|
9
|
+
export declare function fullUUID(uuid: UUID): UUID;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts UUID to full 128bit, lowercase format which should be used to compare UUID values.
|
|
3
|
+
* This function maintains 100% compatibility with react-native-ble-plx
|
|
4
|
+
*
|
|
5
|
+
* @param uuid 16bit, 32bit or 128bit UUID.
|
|
6
|
+
* @returns 128bit lowercase UUID.
|
|
7
|
+
*/
|
|
8
|
+
export function fullUUID(uuid) {
|
|
9
|
+
if (typeof uuid !== 'string') {
|
|
10
|
+
throw new Error('UUID must be a string');
|
|
11
|
+
}
|
|
12
|
+
// Remove dashes and convert to lowercase
|
|
13
|
+
const cleanUuid = uuid.replace(/-/g, '').toLowerCase();
|
|
14
|
+
// 16-bit UUID (4 characters)
|
|
15
|
+
if (cleanUuid.length === 4) {
|
|
16
|
+
return `0000${cleanUuid}-0000-1000-8000-00805f9b34fb`;
|
|
17
|
+
}
|
|
18
|
+
// 32-bit UUID (8 characters)
|
|
19
|
+
if (cleanUuid.length === 8) {
|
|
20
|
+
return `${cleanUuid}-0000-1000-8000-00805f9b34fb`;
|
|
21
|
+
}
|
|
22
|
+
// 128-bit UUID (32 characters)
|
|
23
|
+
if (cleanUuid.length === 32) {
|
|
24
|
+
return [
|
|
25
|
+
cleanUuid.substring(0, 8),
|
|
26
|
+
cleanUuid.substring(8, 12),
|
|
27
|
+
cleanUuid.substring(12, 16),
|
|
28
|
+
cleanUuid.substring(16, 20),
|
|
29
|
+
cleanUuid.substring(20, 32)
|
|
30
|
+
].join('-');
|
|
31
|
+
}
|
|
32
|
+
// Already formatted UUID with dashes
|
|
33
|
+
if (cleanUuid.length === 36 && uuid.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)) {
|
|
34
|
+
return uuid.toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Invalid UUID format: ${uuid}`);
|
|
37
|
+
}
|
package/nitro.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://nitro.margelo.com/nitro.schema.json",
|
|
3
|
+
"cxxNamespace": ["co", "zyke", "ble"],
|
|
4
|
+
"ios": {
|
|
5
|
+
"iosModuleName": "BleNitro"
|
|
6
|
+
},
|
|
7
|
+
"android": {
|
|
8
|
+
"androidNamespace": ["co", "zyke", "ble"],
|
|
9
|
+
"androidCxxLibName": "BleNitro"
|
|
10
|
+
},
|
|
11
|
+
"autolinking": {},
|
|
12
|
+
"ignorePaths": [
|
|
13
|
+
"**/node_modules"
|
|
14
|
+
]
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-ble-nitro",
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "High-performance React Native BLE library built on Nitro Modules - drop-in replacement for react-native-ble-plx",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"react-native": "src/index.ts",
|
|
8
|
+
"source": "src/index.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"react-native": "./src/index.ts",
|
|
12
|
+
"import": "./lib/index.js",
|
|
13
|
+
"require": "./lib/index.js",
|
|
14
|
+
"types": "./lib/index.d.ts",
|
|
15
|
+
"default": "./lib/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./plugin": {
|
|
18
|
+
"import": "./plugin/build/index.js",
|
|
19
|
+
"require": "./plugin/build/index.js",
|
|
20
|
+
"types": "./plugin/build/index.d.ts",
|
|
21
|
+
"default": "./plugin/build/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "npm run clean && npm run build:plugin && tsc",
|
|
27
|
+
"build:plugin": "tsc --project plugin/tsconfig.json",
|
|
28
|
+
"prepare": "npm run build",
|
|
29
|
+
"prepublishOnly": "npm run build && npm run test",
|
|
30
|
+
"nitro-codegen": "nitro-codegen generate",
|
|
31
|
+
"clean": "rm -rf lib && rm -rf plugin/build",
|
|
32
|
+
"test": "jest",
|
|
33
|
+
"lint": "eslint src/ --ext .ts,.tsx",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"version": "npm run build",
|
|
36
|
+
"postversion": "git push && git push --tags"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"react-native",
|
|
40
|
+
"bluetooth",
|
|
41
|
+
"ble",
|
|
42
|
+
"bluetooth-low-energy",
|
|
43
|
+
"nitro-modules",
|
|
44
|
+
"expo",
|
|
45
|
+
"ios",
|
|
46
|
+
"android",
|
|
47
|
+
"performance"
|
|
48
|
+
],
|
|
49
|
+
"author": "Zyke (https://zyke.co)",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/zykeco/react-native-ble-nitro.git"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/zykeco/react-native-ble-nitro#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/zykeco/react-native-ble-nitro/issues"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=16.0.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"react-native": ">=0.76.0",
|
|
64
|
+
"react-native-nitro-modules": "*"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/jest": "^29.5.0",
|
|
68
|
+
"@types/node": "^20.0.0",
|
|
69
|
+
"@types/react": "^18.2.0",
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
71
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
72
|
+
"eslint": "^8.0.0",
|
|
73
|
+
"expo": "^52.0.47",
|
|
74
|
+
"jest": "^29.0.0",
|
|
75
|
+
"nitro-codegen": "^0.26.4",
|
|
76
|
+
"react-native": "^0.76.0",
|
|
77
|
+
"ts-jest": "^29.4.0",
|
|
78
|
+
"typescript": "^5.0.0"
|
|
79
|
+
},
|
|
80
|
+
"files": [
|
|
81
|
+
"lib/",
|
|
82
|
+
"src/",
|
|
83
|
+
"ios/",
|
|
84
|
+
"android/",
|
|
85
|
+
"plugin/build/",
|
|
86
|
+
"nitro.json",
|
|
87
|
+
"react-native.config.js",
|
|
88
|
+
"README.md",
|
|
89
|
+
"LICENSE"
|
|
90
|
+
],
|
|
91
|
+
"expo": {
|
|
92
|
+
"platforms": [
|
|
93
|
+
"ios",
|
|
94
|
+
"android"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
"codegenConfig": {
|
|
98
|
+
"name": "BleNitroSpec",
|
|
99
|
+
"type": "modules",
|
|
100
|
+
"jsSrcsDir": "src"
|
|
101
|
+
}
|
|
102
|
+
}
|