@magicred-1/react-native-lxmf 0.1.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.
- package/LxmfReactNative.podspec +25 -0
- package/README.md +57 -0
- package/android/build.gradle.kts +33 -0
- package/android/src/main/jniLibs/arm64-v8a/liblxmf_rn.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/liblxmf_rn.so +0 -0
- package/android/src/main/jniLibs/x86_64/liblxmf_rn.so +0 -0
- package/android/src/main/kotlin/expo/modules/lxmf/BleManager.kt +282 -0
- package/android/src/main/kotlin/expo/modules/lxmf/LxmfModule.kt +232 -0
- package/app.plugin.js +40 -0
- package/build/LxmfModule.d.ts +29 -0
- package/build/LxmfModule.js +31 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/build/useLxmf.d.ts +81 -0
- package/build/useLxmf.js +252 -0
- package/expo-module.config.json +10 -0
- package/ios/BLEManager.swift +494 -0
- package/ios/LxmfModule.swift +422 -0
- package/package.json +76 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import CoreBluetooth
|
|
3
|
+
|
|
4
|
+
// C FFI declarations — linked from the Rust staticlib (liblxmf_rn.a)
|
|
5
|
+
@_silgen_name("lxmf_init")
|
|
6
|
+
func lxmf_init(_ dbPath: UnsafePointer<CChar>?) -> Int32
|
|
7
|
+
|
|
8
|
+
@_silgen_name("lxmf_start")
|
|
9
|
+
func lxmf_start(
|
|
10
|
+
_ identityHex: UnsafePointer<CChar>?,
|
|
11
|
+
_ addressHex: UnsafePointer<CChar>?,
|
|
12
|
+
_ mode: UInt32,
|
|
13
|
+
_ announceIntervalMs: UInt64,
|
|
14
|
+
_ bleMtuHint: UInt16,
|
|
15
|
+
_ tcpInterfacesJson: UnsafePointer<CChar>?,
|
|
16
|
+
_ displayName: UnsafePointer<CChar>?
|
|
17
|
+
) -> Int32
|
|
18
|
+
|
|
19
|
+
@_silgen_name("lxmf_stop")
|
|
20
|
+
func lxmf_stop() -> Int32
|
|
21
|
+
|
|
22
|
+
@_silgen_name("lxmf_is_running")
|
|
23
|
+
func lxmf_is_running() -> Int32
|
|
24
|
+
|
|
25
|
+
@_silgen_name("lxmf_send")
|
|
26
|
+
func lxmf_send(
|
|
27
|
+
_ destPtr: UnsafePointer<UInt8>?,
|
|
28
|
+
_ bodyPtr: UnsafePointer<UInt8>?,
|
|
29
|
+
_ bodyLen: Int
|
|
30
|
+
) -> Int64
|
|
31
|
+
|
|
32
|
+
@_silgen_name("lxmf_broadcast")
|
|
33
|
+
func lxmf_broadcast(
|
|
34
|
+
_ destsPtr: UnsafePointer<UInt8>?,
|
|
35
|
+
_ destCount: Int,
|
|
36
|
+
_ bodyPtr: UnsafePointer<UInt8>?,
|
|
37
|
+
_ bodyLen: Int
|
|
38
|
+
) -> Int64
|
|
39
|
+
|
|
40
|
+
@_silgen_name("lxmf_poll_events")
|
|
41
|
+
func lxmf_poll_events(
|
|
42
|
+
_ timeoutMs: UInt64,
|
|
43
|
+
_ outBuf: UnsafeMutablePointer<UInt8>?,
|
|
44
|
+
_ outCapacity: Int
|
|
45
|
+
) -> Int32
|
|
46
|
+
|
|
47
|
+
@_silgen_name("lxmf_get_status")
|
|
48
|
+
func lxmf_get_status(
|
|
49
|
+
_ outBuf: UnsafeMutablePointer<UInt8>?,
|
|
50
|
+
_ outCapacity: Int
|
|
51
|
+
) -> Int32
|
|
52
|
+
|
|
53
|
+
@_silgen_name("lxmf_get_beacons")
|
|
54
|
+
func lxmf_get_beacons(
|
|
55
|
+
_ outBuf: UnsafeMutablePointer<UInt8>?,
|
|
56
|
+
_ outCapacity: Int
|
|
57
|
+
) -> Int32
|
|
58
|
+
|
|
59
|
+
@_silgen_name("lxmf_on_announce")
|
|
60
|
+
func lxmf_on_announce(
|
|
61
|
+
_ destHashPtr: UnsafePointer<UInt8>?,
|
|
62
|
+
_ appDataPtr: UnsafePointer<UInt8>?,
|
|
63
|
+
_ appDataLen: Int
|
|
64
|
+
) -> Int32
|
|
65
|
+
|
|
66
|
+
@_silgen_name("lxmf_set_log_level")
|
|
67
|
+
func lxmf_set_log_level(_ level: UInt32) -> Int32
|
|
68
|
+
|
|
69
|
+
@_silgen_name("lxmf_abi_version")
|
|
70
|
+
func lxmf_abi_version() -> UInt32
|
|
71
|
+
|
|
72
|
+
@_silgen_name("lxmf_hdlc_encode")
|
|
73
|
+
func lxmf_hdlc_encode(
|
|
74
|
+
_ dataPtr: UnsafePointer<UInt8>?,
|
|
75
|
+
_ dataLen: Int,
|
|
76
|
+
_ outPtr: UnsafeMutablePointer<UInt8>?,
|
|
77
|
+
_ outCapacity: Int
|
|
78
|
+
) -> Int32
|
|
79
|
+
|
|
80
|
+
@_silgen_name("lxmf_kiss_encode")
|
|
81
|
+
func lxmf_kiss_encode(
|
|
82
|
+
_ dataPtr: UnsafePointer<UInt8>?,
|
|
83
|
+
_ dataLen: Int,
|
|
84
|
+
_ outPtr: UnsafeMutablePointer<UInt8>?,
|
|
85
|
+
_ outCapacity: Int
|
|
86
|
+
) -> Int32
|
|
87
|
+
|
|
88
|
+
@_silgen_name("lxmf_fetch_messages")
|
|
89
|
+
func lxmf_fetch_messages(
|
|
90
|
+
_ limit: UInt32,
|
|
91
|
+
_ outBuf: UnsafeMutablePointer<UInt8>?,
|
|
92
|
+
_ outCapacity: Int
|
|
93
|
+
) -> Int32
|
|
94
|
+
|
|
95
|
+
// --- BLE Interface FFI ---
|
|
96
|
+
|
|
97
|
+
@_silgen_name("lxmf_ble_receive")
|
|
98
|
+
func lxmf_ble_receive(
|
|
99
|
+
_ peerAddr: UnsafePointer<UInt8>?,
|
|
100
|
+
_ data: UnsafePointer<UInt8>?,
|
|
101
|
+
_ dataLen: Int
|
|
102
|
+
) -> Int32
|
|
103
|
+
|
|
104
|
+
@_silgen_name("lxmf_ble_poll_tx")
|
|
105
|
+
func lxmf_ble_poll_tx(
|
|
106
|
+
_ outPeer: UnsafeMutablePointer<UInt8>?,
|
|
107
|
+
_ outData: UnsafeMutablePointer<UInt8>?,
|
|
108
|
+
_ outCapacity: Int
|
|
109
|
+
) -> Int32
|
|
110
|
+
|
|
111
|
+
@_silgen_name("lxmf_ble_connected")
|
|
112
|
+
func lxmf_ble_connected(
|
|
113
|
+
_ peerAddr: UnsafePointer<UInt8>?
|
|
114
|
+
) -> Int32
|
|
115
|
+
|
|
116
|
+
@_silgen_name("lxmf_ble_disconnected")
|
|
117
|
+
func lxmf_ble_disconnected(
|
|
118
|
+
_ peerAddr: UnsafePointer<UInt8>?
|
|
119
|
+
) -> Int32
|
|
120
|
+
|
|
121
|
+
@_silgen_name("lxmf_ble_peer_count")
|
|
122
|
+
func lxmf_ble_peer_count() -> Int32
|
|
123
|
+
|
|
124
|
+
// --- NUS Interface FFI (RNode BLE via Nordic UART Service) ---
|
|
125
|
+
|
|
126
|
+
@_silgen_name("lxmf_nus_receive")
|
|
127
|
+
func lxmf_nus_receive(
|
|
128
|
+
_ data: UnsafePointer<UInt8>?,
|
|
129
|
+
_ dataLen: Int
|
|
130
|
+
) -> Int32
|
|
131
|
+
|
|
132
|
+
@_silgen_name("lxmf_nus_poll_tx")
|
|
133
|
+
func lxmf_nus_poll_tx(
|
|
134
|
+
_ outData: UnsafeMutablePointer<UInt8>?,
|
|
135
|
+
_ outCapacity: Int
|
|
136
|
+
) -> Int32
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
public class LxmfModule: Module {
|
|
140
|
+
// Shared JSON buffer for FFI calls (64KB)
|
|
141
|
+
private var jsonBuf = [UInt8](repeating: 0, count: 65536)
|
|
142
|
+
|
|
143
|
+
// Poll timers
|
|
144
|
+
private var rxPollTimer: Timer?
|
|
145
|
+
private var txDrainTimer: Timer?
|
|
146
|
+
|
|
147
|
+
// BLE manager for phone-to-phone mesh
|
|
148
|
+
private lazy var bleManager = BLEManager()
|
|
149
|
+
|
|
150
|
+
public func definition() -> ModuleDefinition {
|
|
151
|
+
Name("LxmfModule")
|
|
152
|
+
|
|
153
|
+
// --- Events emitted to JavaScript ---
|
|
154
|
+
Events(
|
|
155
|
+
"onPacketReceived",
|
|
156
|
+
"onTxReceived",
|
|
157
|
+
"onBeaconDiscovered",
|
|
158
|
+
"onMessageReceived",
|
|
159
|
+
"onAnnounceReceived",
|
|
160
|
+
"onStatusChanged",
|
|
161
|
+
"onLog",
|
|
162
|
+
"onError",
|
|
163
|
+
"onOutgoingPacket"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
// --- Lifecycle ---
|
|
167
|
+
|
|
168
|
+
Function("init") { (dbPath: String?) -> Bool in
|
|
169
|
+
let result: Int32
|
|
170
|
+
if let path = dbPath {
|
|
171
|
+
result = path.withCString { lxmf_init($0) }
|
|
172
|
+
} else {
|
|
173
|
+
result = lxmf_init(nil)
|
|
174
|
+
}
|
|
175
|
+
return result == 0
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
AsyncFunction("start") { (
|
|
179
|
+
identityHex: String,
|
|
180
|
+
lxmfAddressHex: String,
|
|
181
|
+
mode: Int,
|
|
182
|
+
announceIntervalMs: Double,
|
|
183
|
+
bleMtuHint: Int,
|
|
184
|
+
tcpInterfaces: [[String: Any]],
|
|
185
|
+
displayName: String
|
|
186
|
+
) -> Bool in
|
|
187
|
+
// Serialize TCP interfaces to JSON (matches Android pattern)
|
|
188
|
+
let interfacesJson: String
|
|
189
|
+
if let data = try? JSONSerialization.data(withJSONObject: tcpInterfaces),
|
|
190
|
+
let str = String(data: data, encoding: .utf8) {
|
|
191
|
+
interfacesJson = str
|
|
192
|
+
} else {
|
|
193
|
+
interfacesJson = "[]"
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
let result = identityHex.withCString { idPtr in
|
|
197
|
+
lxmfAddressHex.withCString { addrPtr in
|
|
198
|
+
interfacesJson.withCString { ifacesPtr in
|
|
199
|
+
displayName.withCString { namePtr in
|
|
200
|
+
lxmf_start(
|
|
201
|
+
idPtr, addrPtr,
|
|
202
|
+
UInt32(mode), UInt64(announceIntervalMs),
|
|
203
|
+
UInt16(bleMtuHint), ifacesPtr, namePtr
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if result == 0 {
|
|
211
|
+
self.startPolling()
|
|
212
|
+
self.bleManager.start()
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result == 0
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
AsyncFunction("stop") { () -> Bool in
|
|
219
|
+
self.stopPolling()
|
|
220
|
+
self.bleManager.stop()
|
|
221
|
+
return lxmf_stop() == 0
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Function("isRunning") { () -> Bool in
|
|
225
|
+
return lxmf_is_running() != 0
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// --- Messaging ---
|
|
229
|
+
|
|
230
|
+
AsyncFunction("send") { (destHex: String, bodyBase64: String) -> Double in
|
|
231
|
+
guard let destBytes = Self.hexToBytes(destHex),
|
|
232
|
+
destBytes.count == 16,
|
|
233
|
+
let bodyData = Data(base64Encoded: bodyBase64) else {
|
|
234
|
+
return -1
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let opId = destBytes.withUnsafeBufferPointer { destBuf in
|
|
238
|
+
[UInt8](bodyData).withUnsafeBufferPointer { bodyBuf in
|
|
239
|
+
lxmf_send(destBuf.baseAddress, bodyBuf.baseAddress, bodyData.count)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return Double(opId)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
AsyncFunction("broadcast") { (destsHex: [String], bodyBase64: String) -> Double in
|
|
246
|
+
guard let bodyData = Data(base64Encoded: bodyBase64) else { return -1 }
|
|
247
|
+
|
|
248
|
+
var flatDests = [UInt8]()
|
|
249
|
+
for hex in destsHex {
|
|
250
|
+
guard let bytes = Self.hexToBytes(hex), bytes.count == 16 else { return -1 }
|
|
251
|
+
flatDests.append(contentsOf: bytes)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let opId = flatDests.withUnsafeBufferPointer { destBuf in
|
|
255
|
+
[UInt8](bodyData).withUnsafeBufferPointer { bodyBuf in
|
|
256
|
+
lxmf_broadcast(destBuf.baseAddress, destsHex.count, bodyBuf.baseAddress, bodyData.count)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return Double(opId)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// --- Status & Beacons ---
|
|
263
|
+
|
|
264
|
+
Function("getStatus") { () -> String? in
|
|
265
|
+
return self.callJsonFfi { buf, cap in lxmf_get_status(buf, cap) }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
Function("getBeacons") { () -> String? in
|
|
269
|
+
return self.callJsonFfi { buf, cap in lxmf_get_beacons(buf, cap) }
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
Function("fetchMessages") { (limit: Int) -> String? in
|
|
273
|
+
return self.callJsonFfi { buf, cap in lxmf_fetch_messages(UInt32(limit), buf, cap) }
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// --- Configuration ---
|
|
277
|
+
|
|
278
|
+
Function("setLogLevel") { (level: Int) -> Bool in
|
|
279
|
+
return lxmf_set_log_level(UInt32(level)) == 0
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
Function("abiVersion") { () -> Int in
|
|
283
|
+
return Int(lxmf_abi_version())
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// --- BLE interface control ---
|
|
287
|
+
|
|
288
|
+
Function("startBLE") { () -> Void in
|
|
289
|
+
self.bleManager.start()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
Function("stopBLE") { () -> Void in
|
|
293
|
+
self.bleManager.stop()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
Function("blePeerCount") { () -> Int in
|
|
297
|
+
return Int(lxmf_ble_peer_count())
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
Function("bleUnpairedRNodeCount") { () -> Int in
|
|
301
|
+
return self.bleManager.discoveredUnpairedRNodes.count
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// MARK: - Polling
|
|
306
|
+
|
|
307
|
+
private func startPolling() {
|
|
308
|
+
// Must schedule on main thread — AsyncFunction runs on a background
|
|
309
|
+
// dispatch queue whose RunLoop is not active, so timers would never fire.
|
|
310
|
+
DispatchQueue.main.async { [weak self] in
|
|
311
|
+
guard let self = self else { return }
|
|
312
|
+
|
|
313
|
+
// RX event poll: 80ms interval
|
|
314
|
+
self.rxPollTimer = Timer.scheduledTimer(withTimeInterval: 0.08, repeats: true) { [weak self] _ in
|
|
315
|
+
self?.drainEvents()
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// TX drain for BLE outgoing: 20ms interval
|
|
319
|
+
self.txDrainTimer = Timer.scheduledTimer(withTimeInterval: 0.02, repeats: true) { [weak self] _ in
|
|
320
|
+
self?.drainOutgoing()
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private func stopPolling() {
|
|
326
|
+
DispatchQueue.main.async { [weak self] in
|
|
327
|
+
self?.rxPollTimer?.invalidate()
|
|
328
|
+
self?.rxPollTimer = nil
|
|
329
|
+
self?.txDrainTimer?.invalidate()
|
|
330
|
+
self?.txDrainTimer = nil
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private func drainEvents() {
|
|
335
|
+
let len = jsonBuf.withUnsafeMutableBufferPointer { buf in
|
|
336
|
+
lxmf_poll_events(0, buf.baseAddress, buf.count)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
guard len > 0 else { return }
|
|
340
|
+
|
|
341
|
+
let jsonData = Data(jsonBuf[0..<Int(len)])
|
|
342
|
+
guard let events = try? JSONSerialization.jsonObject(with: jsonData) as? [[String: Any]] else { return }
|
|
343
|
+
|
|
344
|
+
for event in events {
|
|
345
|
+
guard let type_ = event["type"] as? String else { continue }
|
|
346
|
+
|
|
347
|
+
switch type_ {
|
|
348
|
+
case "statusChanged":
|
|
349
|
+
sendEvent("onStatusChanged", event)
|
|
350
|
+
case "packetReceived":
|
|
351
|
+
sendEvent("onPacketReceived", event)
|
|
352
|
+
case "txReceived":
|
|
353
|
+
sendEvent("onTxReceived", event)
|
|
354
|
+
case "beaconDiscovered":
|
|
355
|
+
sendEvent("onBeaconDiscovered", event)
|
|
356
|
+
case "messageReceived":
|
|
357
|
+
sendEvent("onMessageReceived", event)
|
|
358
|
+
case "announceReceived":
|
|
359
|
+
sendEvent("onAnnounceReceived", event)
|
|
360
|
+
case "log":
|
|
361
|
+
sendEvent("onLog", event)
|
|
362
|
+
case "error":
|
|
363
|
+
sendEvent("onError", event)
|
|
364
|
+
default:
|
|
365
|
+
break
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
private func drainOutgoing() {
|
|
371
|
+
// --- Mesh BLE: poll for peer-addressed frames ---
|
|
372
|
+
var peerAddr = [UInt8](repeating: 0, count: 6)
|
|
373
|
+
var dataBuf = [UInt8](repeating: 0, count: 512)
|
|
374
|
+
|
|
375
|
+
for _ in 0..<8 {
|
|
376
|
+
let len = peerAddr.withUnsafeMutableBufferPointer { peerBuf in
|
|
377
|
+
dataBuf.withUnsafeMutableBufferPointer { dataBuf in
|
|
378
|
+
lxmf_ble_poll_tx(peerBuf.baseAddress, dataBuf.baseAddress, dataBuf.count)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
guard len > 0 else { break }
|
|
382
|
+
|
|
383
|
+
let frameData = Data(dataBuf[0..<Int(len)])
|
|
384
|
+
let addr = Data(peerAddr)
|
|
385
|
+
bleManager.sendToPeerAddr(addr, data: frameData)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// --- NUS: poll for KISS-framed RNode data ---
|
|
389
|
+
var nusBuf = [UInt8](repeating: 0, count: 1024)
|
|
390
|
+
for _ in 0..<8 {
|
|
391
|
+
let len = nusBuf.withUnsafeMutableBufferPointer { buf in
|
|
392
|
+
lxmf_nus_poll_tx(buf.baseAddress, buf.count)
|
|
393
|
+
}
|
|
394
|
+
guard len > 0 else { break }
|
|
395
|
+
|
|
396
|
+
let kissData = Data(nusBuf[0..<Int(len)])
|
|
397
|
+
bleManager.sendToNus(kissData)
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// MARK: - Helpers
|
|
402
|
+
|
|
403
|
+
private func callJsonFfi(_ fn_: (UnsafeMutablePointer<UInt8>?, Int) -> Int32) -> String? {
|
|
404
|
+
let len = jsonBuf.withUnsafeMutableBufferPointer { buf in
|
|
405
|
+
fn_(buf.baseAddress, buf.count)
|
|
406
|
+
}
|
|
407
|
+
guard len > 0 else { return nil }
|
|
408
|
+
return String(bytes: jsonBuf[0..<Int(len)], encoding: .utf8)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
static func hexToBytes(_ hex: String) -> [UInt8]? {
|
|
412
|
+
let chars = Array(hex)
|
|
413
|
+
guard chars.count % 2 == 0 else { return nil }
|
|
414
|
+
var bytes = [UInt8]()
|
|
415
|
+
bytes.reserveCapacity(chars.count / 2)
|
|
416
|
+
for i in stride(from: 0, to: chars.count, by: 2) {
|
|
417
|
+
guard let byte = UInt8(String(chars[i...i+1]), radix: 16) else { return nil }
|
|
418
|
+
bytes.append(byte)
|
|
419
|
+
}
|
|
420
|
+
return bytes
|
|
421
|
+
}
|
|
422
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@magicred-1/react-native-lxmf",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "LXMF Reticulum mesh networking for React Native + Expo",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./build/index.d.ts",
|
|
10
|
+
"default": "./build/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"expo": {
|
|
15
|
+
"plugin": "./app.plugin.js"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "node -e \"const ts=require('typescript');const c=ts.readConfigFile('./tsconfig.json',ts.sys.readFile);const p=ts.parseJsonConfigFileContent(c.config,ts.sys,'./');const prog=ts.createProgram(p.fileNames,p.options);const r=prog.emit();const d=ts.getPreEmitDiagnostics(prog).concat(r.diagnostics);if(d.length){d.forEach(x=>console.error(ts.flattenDiagnosticMessageText(x.messageText,'\\n')));process.exit(1)}\"",
|
|
20
|
+
"clean": "rm -rf build",
|
|
21
|
+
"prepare": "npm run build",
|
|
22
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
23
|
+
"pack:check": "npm pack --dry-run",
|
|
24
|
+
"test": "jest",
|
|
25
|
+
"lint": "eslint src",
|
|
26
|
+
"type-check": "tsc --noEmit",
|
|
27
|
+
"rust:android": "bash ../scripts/build-rust-android.sh",
|
|
28
|
+
"rust:ios": "bash ../scripts/build-rust-ios.sh",
|
|
29
|
+
"build:android": "npm run rust:android && npm run build",
|
|
30
|
+
"build:ios": "npm run rust:ios && npm run build",
|
|
31
|
+
"build:all": "npm run rust:android && npm run rust:ios && npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"lxmf",
|
|
35
|
+
"reticulum",
|
|
36
|
+
"mesh",
|
|
37
|
+
"networking",
|
|
38
|
+
"ble",
|
|
39
|
+
"react-native",
|
|
40
|
+
"expo"
|
|
41
|
+
],
|
|
42
|
+
"homepage": "https://anonme.sh",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/anon0mesh/lxmf_react_native_rust.git"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"expo": "*",
|
|
53
|
+
"expo-modules-core": "*",
|
|
54
|
+
"react": "*",
|
|
55
|
+
"react-native": "*"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@expo/config-plugins": "^9.0.0"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/react": "^19.2.14",
|
|
62
|
+
"@types/react-native": "^0.72.0",
|
|
63
|
+
"expo-modules-core": "^3.0.0",
|
|
64
|
+
"typescript": "^5.0.0"
|
|
65
|
+
},
|
|
66
|
+
"files": [
|
|
67
|
+
"build",
|
|
68
|
+
"ios",
|
|
69
|
+
"android/build.gradle.kts",
|
|
70
|
+
"android/src/main",
|
|
71
|
+
"LxmfReactNative.podspec",
|
|
72
|
+
"expo-module.config.json",
|
|
73
|
+
"app.plugin.js",
|
|
74
|
+
"README.md"
|
|
75
|
+
]
|
|
76
|
+
}
|