react-native-device-integrity 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.
Files changed (54) hide show
  1. package/DeviceIntegrity.podspec +21 -0
  2. package/LICENSE +20 -0
  3. package/README.md +286 -0
  4. package/android/build.gradle +55 -0
  5. package/android/src/main/AndroidManifest.xml +20 -0
  6. package/android/src/main/java/com/deviceintegrity/DeviceIntegrityModule.kt +48 -0
  7. package/android/src/main/java/com/deviceintegrity/DeviceIntegrityPackage.kt +31 -0
  8. package/android/src/main/java/com/deviceintegrity/IntegrityChecks.kt +454 -0
  9. package/app.plugin.js +1 -0
  10. package/ios/DIIntegrityChecks.h +15 -0
  11. package/ios/DIIntegrityChecks.m +395 -0
  12. package/ios/DeviceIntegrity.h +5 -0
  13. package/ios/DeviceIntegrity.mm +29 -0
  14. package/ios/PrivacyInfo.xcprivacy +14 -0
  15. package/lib/module/NativeDeviceIntegrity.js +5 -0
  16. package/lib/module/NativeDeviceIntegrity.js.map +1 -0
  17. package/lib/module/checkIntegrity.js +15 -0
  18. package/lib/module/checkIntegrity.js.map +1 -0
  19. package/lib/module/checkIntegrity.native.js +67 -0
  20. package/lib/module/checkIntegrity.native.js.map +1 -0
  21. package/lib/module/index.js +5 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/module/package.json +1 -0
  24. package/lib/module/resolveStatus.js +76 -0
  25. package/lib/module/resolveStatus.js.map +1 -0
  26. package/lib/module/types.js +4 -0
  27. package/lib/module/types.js.map +1 -0
  28. package/lib/module/useDeviceIntegrity.js +62 -0
  29. package/lib/module/useDeviceIntegrity.js.map +1 -0
  30. package/lib/typescript/package.json +1 -0
  31. package/lib/typescript/src/NativeDeviceIntegrity.d.ts +17 -0
  32. package/lib/typescript/src/NativeDeviceIntegrity.d.ts.map +1 -0
  33. package/lib/typescript/src/checkIntegrity.d.ts +6 -0
  34. package/lib/typescript/src/checkIntegrity.d.ts.map +1 -0
  35. package/lib/typescript/src/checkIntegrity.native.d.ts +3 -0
  36. package/lib/typescript/src/checkIntegrity.native.d.ts.map +1 -0
  37. package/lib/typescript/src/index.d.ts +4 -0
  38. package/lib/typescript/src/index.d.ts.map +1 -0
  39. package/lib/typescript/src/resolveStatus.d.ts +8 -0
  40. package/lib/typescript/src/resolveStatus.d.ts.map +1 -0
  41. package/lib/typescript/src/types.d.ts +23 -0
  42. package/lib/typescript/src/types.d.ts.map +1 -0
  43. package/lib/typescript/src/useDeviceIntegrity.d.ts +10 -0
  44. package/lib/typescript/src/useDeviceIntegrity.d.ts.map +1 -0
  45. package/package.json +210 -0
  46. package/plugin/build/index.d.ts +19 -0
  47. package/plugin/build/index.js +49 -0
  48. package/src/NativeDeviceIntegrity.ts +19 -0
  49. package/src/checkIntegrity.native.ts +88 -0
  50. package/src/checkIntegrity.ts +16 -0
  51. package/src/index.tsx +10 -0
  52. package/src/resolveStatus.ts +125 -0
  53. package/src/types.ts +41 -0
  54. package/src/useDeviceIntegrity.ts +92 -0
@@ -0,0 +1,21 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "DeviceIntegrity"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://github.com/RRigueira/react-native-device-integrity.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
+ s.resource_bundles = { "DeviceIntegrityPrivacy" => ["ios/PrivacyInfo.xcprivacy"] }
19
+
20
+ install_modules_dependencies(s)
21
+ end
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rui Rigueira
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # react-native-device-integrity
2
+
3
+ Jailbreak, root, hooking, debugger and emulator detection for React Native and Expo.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/react-native-device-integrity.svg)](https://www.npmjs.com/package/react-native-device-integrity)
6
+ [![npm license](https://img.shields.io/npm/l/react-native-device-integrity.svg)](https://www.npmjs.com/package/react-native-device-integrity)
7
+ [![CI](https://github.com/RRigueira/react-native-device-integrity/actions/workflows/ci.yml/badge.svg)](https://github.com/RRigueira/react-native-device-integrity/actions/workflows/ci.yml)
8
+ [![Expo config plugin](https://img.shields.io/badge/Expo-config%20plugin-4630EB)](https://docs.expo.dev/config-plugins/introduction/)
9
+ [![New Architecture](https://img.shields.io/badge/New%20Architecture-required-222)](https://reactnative.dev/docs/the-new-architecture/landing-page)
10
+
11
+ ## What it does / doesn't
12
+
13
+ **Does:** report client-side signals for jailbreak/root, hooking frameworks, attached debuggers, and emulator/simulator environments.
14
+
15
+ **Doesn't:** send telemetry, make network calls, or request permissions. Client-side only — **not** a replacement for commercial RASP/anti-tamper products or server-side attestation (App Attest / Play Integrity).
16
+
17
+ ## Requirements
18
+
19
+ - **New Architecture (TurboModule) required** — no old-architecture bridge fallback.
20
+ - Developed and tested with **React Native 0.86** and **Expo SDK 57**.
21
+ - **iOS 15.1+**, **Android minSdk 24**.
22
+ - Older RN (**≥ 0.76**) is expected to work but is not yet tested.
23
+ - **Expo Go is not supported** — use a development build / `prebuild`.
24
+
25
+ ## Installation
26
+
27
+ ### Expo
28
+
29
+ ```sh
30
+ npx expo install react-native-device-integrity
31
+ ```
32
+
33
+ Add the config plugin to `app.json` / `app.config.js`:
34
+
35
+ ```json
36
+ {
37
+ "expo": {
38
+ "plugins": ["react-native-device-integrity"]
39
+ }
40
+ }
41
+ ```
42
+
43
+ To skip Info.plist URL-scheme entries (e.g. you manage them yourself):
44
+
45
+ ```json
46
+ {
47
+ "expo": {
48
+ "plugins": [
49
+ [
50
+ "react-native-device-integrity",
51
+ { "ios": { "jailbreakUrlSchemes": false } }
52
+ ]
53
+ ]
54
+ }
55
+ }
56
+ ```
57
+
58
+ Then run `npx expo prebuild` or use a development build. Expo Go is not supported.
59
+
60
+ ### Bare React Native
61
+
62
+ ```sh
63
+ npm install react-native-device-integrity
64
+ # or: yarn add react-native-device-integrity
65
+
66
+ cd ios && pod install
67
+ ```
68
+
69
+ On iOS, add these schemes under `LSApplicationQueriesSchemes` in `Info.plist`:
70
+
71
+ `cydia`, `sileo`, `zbra`, `filza`, `undecimus`, `activator`
72
+
73
+ Without them, `canOpenURL` cannot query those schemes and the URL-scheme check **silently finds nothing**.
74
+
75
+ Android needs no extra setup — the library manifest `<queries>` list merges automatically via the Gradle manifest merger.
76
+
77
+ ## Usage
78
+
79
+ ```ts
80
+ import {
81
+ checkIntegrity,
82
+ useDeviceIntegrity,
83
+ } from 'react-native-device-integrity';
84
+
85
+ const result = await checkIntegrity({
86
+ treatEmulatorAsCompromised: false,
87
+ timeoutMs: 10_000,
88
+ });
89
+ // result.status: 'clean' | 'compromised' | 'unknown'
90
+ ```
91
+
92
+ ```tsx
93
+ import { Button, Text, View } from 'react-native';
94
+
95
+ function IntegrityStatus() {
96
+ const { status, signals, result, loading, refresh } = useDeviceIntegrity();
97
+
98
+ if (loading && result == null) {
99
+ return <Text>Checking…</Text>; // first check in flight
100
+ }
101
+
102
+ return (
103
+ <View>
104
+ <Text>Status: {status}</Text>
105
+ {signals.map((signal) => (
106
+ <Text key={signal.id}>{signal.id}</Text>
107
+ ))}
108
+ <Button title="Re-check" onPress={refresh} disabled={loading} />
109
+ </View>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ## API reference
115
+
116
+ ### `checkIntegrity(options?) → Promise<IntegrityResult>`
117
+
118
+ Never rejects. Failures map to `status: 'unknown'` with a `reason`.
119
+
120
+ #### `CheckIntegrityOptions`
121
+
122
+ | Option | Default | Description |
123
+ | --- | --- | --- |
124
+ | `treatEmulatorAsCompromised` | `false` | When `true`, emulator/simulator signals make `status` `'compromised'`. When `false`, they are reported but do not compromise. |
125
+ | `timeoutMs` | `10000` | Resolve as `'unknown'` with reason `'timeout'` if native does not answer in time. |
126
+
127
+ #### `IntegrityResult`
128
+
129
+ | Field | Type | Description |
130
+ | --- | --- | --- |
131
+ | `status` | `'clean' \| 'compromised' \| 'unknown'` | Resolved status (see [Result semantics](#result-semantics)). |
132
+ | `signals` | `Signal[]` | Detected signals (may be empty). |
133
+ | `platform` | `Platform.OS` | Platform the check ran on. |
134
+ | `reason?` | `UnknownReason` | Present when `status` is `'unknown'`. |
135
+ | `error?` | `string` | Optional message (e.g. native error text). |
136
+
137
+ #### `Signal`
138
+
139
+ | Field | Type |
140
+ | --- | --- |
141
+ | `id` | `string` (stable public API) |
142
+ | `category` | `SignalCategory` |
143
+ | `description` | `string` (generic; never includes matched paths/packages) |
144
+
145
+ #### `SignalCategory`
146
+
147
+ `'jailbreak'` | `'root'` | `'hooking'` | `'debugger'` | `'emulator'` | `'tamper'` | `'environment'`
148
+
149
+ `tamper` is reserved for future checks; no current signal uses it. A native category the JS layer doesn't recognise is reported as `environment`, never dropped.
150
+
151
+ #### `UnknownReason`
152
+
153
+ | Reason | When |
154
+ | --- | --- |
155
+ | `unsupported_platform` | `Platform.OS` is not `ios` or `android` (e.g. web). |
156
+ | `native_module_unavailable` | TurboModule is missing / null (wrong arch, Expo Go, failed link). |
157
+ | `native_error` | Native call threw/rejected, or the native report was malformed. |
158
+ | `timeout` | Native did not answer within `timeoutMs`. |
159
+ | `incomplete` | Native finished with `completed: false` (a check threw; compromise evidence still wins if any non-emulator signal is present). |
160
+ | `not_implemented` | Native report has `completed: false` and `reason: 'not_implemented'` (stub / unfinished native path). |
161
+
162
+ ### `useDeviceIntegrity(options?)`
163
+
164
+ Returns:
165
+
166
+ | Field | Type | Description |
167
+ | --- | --- | --- |
168
+ | `status` | `IntegrityStatus` | `result?.status ?? 'unknown'` |
169
+ | `signals` | `Signal[]` | `result?.signals ?? []` |
170
+ | `result` | `IntegrityResult \| null` | Latest completed result (null until first check finishes). |
171
+ | `loading` | `boolean` | `true` while a check is in flight. |
172
+ | `refresh` | `() => Promise<IntegrityResult>` | Run another check. |
173
+
174
+ Behaviour:
175
+
176
+ - Runs on mount.
177
+ - Re-checks when the app returns to the foreground (`background`/`inactive` → `active`).
178
+ - Latest-request-wins (stale responses are ignored).
179
+ - Keeps the previous `result` while refreshing (`loading` is `true`, `result` is not cleared).
180
+
181
+ ## Result semantics
182
+
183
+ Status is resolved from the native report + options:
184
+
185
+ 1. **Compromise evidence wins** — any non-emulator signal → `'compromised'`, even if the run was incomplete.
186
+ 2. Emulator/simulator signals compromise **only** when `treatEmulatorAsCompromised` is `true`.
187
+ 3. If the run did not complete (`completed: false`) and there is no compromising evidence → `'unknown'`.
188
+ 4. Otherwise → `'clean'`.
189
+
190
+ **`unknown` is never `clean`.** Incomplete, timed-out, missing-module, and unsupported-platform outcomes must not be treated as a safe device.
191
+
192
+ ## Recommended fail-closed usage
193
+
194
+ Treat only `'clean'` as safe. Block or degrade on both `'compromised'` and `'unknown'`. Re-check on foreground (the hook does this). For high-value actions, pair with server-side attestation.
195
+
196
+ ```tsx
197
+ function IntegrityGate({ children }: { children: React.ReactNode }) {
198
+ const { status, result, loading } = useDeviceIntegrity();
199
+
200
+ if (loading && result == null) {
201
+ return null; // or a spinner — do not flash protected UI
202
+ }
203
+
204
+ if (status === 'clean') {
205
+ return <>{children}</>;
206
+ }
207
+
208
+ // Block or degrade for both 'compromised' and 'unknown'
209
+ return <BlockedScreen status={status} />;
210
+ }
211
+ ```
212
+
213
+ ## Signal reference
214
+
215
+ Descriptions are generic on purpose (no matched paths or package names).
216
+
217
+ ### iOS
218
+
219
+ | id | category | Checks |
220
+ | --- | --- | --- |
221
+ | `simulator` | `emulator` | Running on the iOS Simulator. |
222
+ | `jailbreak_files` | `jailbreak` | Unexpected system paths associated with jailbreaks. |
223
+ | `jailbreak_url_schemes` | `jailbreak` | Jailbreak-related URL schemes are registered (`canOpenURL`). |
224
+ | `jailbreak_symlinks` | `jailbreak` | Unexpected symbolic links in system locations. |
225
+ | `jailbreak_writable_system` | `jailbreak` | A normally read-only system location is writable. |
226
+ | `hooking_libraries` | `hooking` | Suspicious dynamic libraries are loaded. |
227
+ | `hooking_dyld_insert` | `hooking` | `DYLD_INSERT_LIBRARIES` is set in the process environment. |
228
+ | `debugger_attached` | `debugger` | A debugger is attached to the process. |
229
+
230
+ ### Android
231
+
232
+ | id | category | Checks |
233
+ | --- | --- | --- |
234
+ | `emulator` | `emulator` | Device appears to be an emulator. |
235
+ | `root_su_binary` | `root` | A privileged elevation binary was found. |
236
+ | `root_management_apps` | `root` | A root or privilege-management app is installed. |
237
+ | `root_magisk_files` | `root` | Root framework artifacts were detected. |
238
+ | `root_test_keys` | `root` | Build was signed with test keys. |
239
+ | `root_dangerous_props` | `root` | System security properties indicate an insecure build. |
240
+ | `root_rw_system` | `root` | A system partition is mounted read-write. |
241
+ | `hooking_frida` | `hooking` | Instrumentation framework artifacts were detected. |
242
+ | `hooking_xposed` | `hooking` | Code-injection framework artifacts were detected. |
243
+ | `debugger_attached` | `debugger` | A debugger is attached to the process. |
244
+
245
+ ### Notes
246
+
247
+ - On the **iOS Simulator**, filesystem / URL-scheme / symlink / writable-system and `DYLD_INSERT_LIBRARIES` checks are **skipped** (they would inspect the host Mac). Skipped-by-design is not incomplete; hooking-library and debugger checks still run, plus the `simulator` signal.
248
+ - `debugger_attached` fires whenever a debugger is attached, including during normal Xcode / Android Studio debugging.
249
+ - Android emulators still run root checks (they may report root-related signals independently of `emulator`).
250
+
251
+ ## Limitations & threat model
252
+
253
+ These are **client-side risk indicators**. They can be bypassed by an attacker who controls the device, for example:
254
+
255
+ - Frida / objection hooking this module
256
+ - Rootless jailbreaks with hiding tweaks
257
+ - Magisk DenyList / Zygisk / Shamiko
258
+ - KernelSU hiding
259
+
260
+ Never rely on them alone for security decisions. For high-assurance flows, use **Apple App Attest / DeviceCheck** and the **Google Play Integrity API** server-side.
261
+
262
+ **Possible false positives:** custom ROMs, developer devices with test-keys builds, enterprise MDM environments.
263
+
264
+ **Store review:** no private APIs; no `QUERY_ALL_PACKAGES` (scoped `<queries>` list); no required-reason file-timestamp APIs; ships a [privacy manifest](ios/PrivacyInfo.xcprivacy) declaring no data collection.
265
+
266
+ ## Privacy
267
+
268
+ Nothing leaves the device. No data collection. No network access. Checks run locally and return an in-process result only.
269
+
270
+ ## Credits & prior art
271
+
272
+ - [OWASP MASVS / MASTG](https://mas.owasp.org/) (resilience / MASVS-RESILIENCE)
273
+ - [IOSSecuritySuite](https://github.com/securing/IOSSecuritySuite) by SecuRing (Wojciech Reguła) — Check categories and indicator lists were informed by version 1.9.11 and earlier, which are licensed BSD-2-Clause. Versions 2.0.0 and later are distributed under a proprietary EULA and were not used. No source code was copied.
274
+ - [RootBeer](https://github.com/scottyab/rootbeer) by Scott Alexander-Bown and contributors — Apache-2.0 — check categories and indicator lists informed by; independent implementation, no source code copied.
275
+
276
+ ## Contributing
277
+
278
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
279
+
280
+ ## Security
281
+
282
+ See [SECURITY.md](SECURITY.md).
283
+
284
+ ## License
285
+
286
+ [MIT](LICENSE)
@@ -0,0 +1,55 @@
1
+ buildscript {
2
+ ext.DeviceIntegrity = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36
6
+ ]
7
+
8
+ ext.getExtOrDefault = { prop ->
9
+ if (rootProject.ext.has(prop)) {
10
+ return rootProject.ext.get(prop)
11
+ }
12
+
13
+ return DeviceIntegrity[prop]
14
+ }
15
+
16
+ repositories {
17
+ google()
18
+ mavenCentral()
19
+ }
20
+
21
+ dependencies {
22
+ classpath "com.android.tools.build:gradle:8.7.2"
23
+ // noinspection DifferentKotlinGradleVersion
24
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
25
+ }
26
+ }
27
+
28
+
29
+ apply plugin: "com.android.library"
30
+
31
+ if (project.extensions.findByName("kotlin") == null) {
32
+ apply plugin: "kotlin-android"
33
+ }
34
+
35
+
36
+ apply plugin: "com.facebook.react"
37
+
38
+ android {
39
+ namespace "com.deviceintegrity"
40
+
41
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
42
+
43
+ defaultConfig {
44
+ minSdkVersion getExtOrDefault("minSdkVersion")
45
+ }
46
+
47
+ compileOptions {
48
+ sourceCompatibility JavaVersion.VERSION_17
49
+ targetCompatibility JavaVersion.VERSION_17
50
+ }
51
+ }
52
+
53
+ dependencies {
54
+ implementation "com.facebook.react:react-android"
55
+ }
@@ -0,0 +1,20 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <queries>
3
+ <package android:name="com.topjohnwu.magisk" />
4
+ <package android:name="io.github.huskydg.magisk" />
5
+ <package android:name="eu.chainfire.supersu" />
6
+ <package android:name="com.koushikdutta.superuser" />
7
+ <package android:name="com.noshufou.android.su" />
8
+ <package android:name="com.thirdparty.superuser" />
9
+ <package android:name="com.yellowes.su" />
10
+ <package android:name="com.kingroot.kinguser" />
11
+ <package android:name="com.kingo.root" />
12
+ <package android:name="com.zhiqupk.root.global" />
13
+ <package android:name="com.smedialink.oneclickroot" />
14
+ <package android:name="me.weishu.kernelsu" />
15
+ <package android:name="me.bmax.apatch" />
16
+ <package android:name="com.devadvance.rootcloak" />
17
+ <package android:name="de.robv.android.xposed.installer" />
18
+ <package android:name="org.lsposed.manager" />
19
+ </queries>
20
+ </manifest>
@@ -0,0 +1,48 @@
1
+ package com.deviceintegrity
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.Promise
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.WritableArray
7
+ import com.facebook.react.bridge.WritableMap
8
+ import java.util.concurrent.Executors
9
+
10
+ class DeviceIntegrityModule(reactContext: ReactApplicationContext) :
11
+ NativeDeviceIntegritySpec(reactContext) {
12
+
13
+ override fun checkIntegrity(promise: Promise) {
14
+ executor.execute {
15
+ try {
16
+ val report = IntegrityChecks(reactApplicationContext).run()
17
+ promise.resolve(toWritableMap(report))
18
+ } catch (t: Throwable) {
19
+ promise.reject("E_INTEGRITY", t.message ?: "Unexpected integrity check failure", t)
20
+ }
21
+ }
22
+ }
23
+
24
+ companion object {
25
+ const val NAME = NativeDeviceIntegritySpec.NAME
26
+
27
+ private val executor = Executors.newSingleThreadExecutor { runnable ->
28
+ Thread(runnable, "DeviceIntegrityChecks").apply { isDaemon = true }
29
+ }
30
+
31
+ private fun toWritableMap(report: IntegrityChecks.Report): WritableMap {
32
+ val map = Arguments.createMap()
33
+ map.putBoolean("completed", report.completed)
34
+ report.reason?.let { map.putString("reason", it) }
35
+
36
+ val signals: WritableArray = Arguments.createArray()
37
+ for (signal in report.signals) {
38
+ val entry = Arguments.createMap()
39
+ entry.putString("id", signal.id)
40
+ entry.putString("category", signal.category)
41
+ entry.putString("description", signal.description)
42
+ signals.pushMap(entry)
43
+ }
44
+ map.putArray("signals", signals)
45
+ return map
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,31 @@
1
+ package com.deviceintegrity
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import java.util.HashMap
9
+
10
+ class DeviceIntegrityPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == DeviceIntegrityModule.NAME) {
13
+ DeviceIntegrityModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
20
+ mapOf(
21
+ DeviceIntegrityModule.NAME to ReactModuleInfo(
22
+ name = DeviceIntegrityModule.NAME,
23
+ className = DeviceIntegrityModule.NAME,
24
+ canOverrideExistingModule = false,
25
+ needsEagerInit = false,
26
+ isCxxModule = false,
27
+ isTurboModule = true
28
+ )
29
+ )
30
+ }
31
+ }