@symbiote-native/device 3.0.1 → 3.0.3

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 (2) hide show
  1. package/README.md +41 -29
  2. package/package.json +15 -15
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # @symbiote-native/device
2
2
 
3
3
  A wrapper package for [SymbioteNative](../../README.md) that makes
4
- [`expo-device`](https://github.com/expo/expo/tree/main/packages/expo-device)
5
- — physical device information: brand/model/OS constants, uptime, max-memory,
6
- root/jailbreak detection, side-loading detection, and platform-feature queries — usable from
4
+ [`expo-device`](https://github.com/expo/expo/tree/main/packages/expo-device):
5
+ physical device information: brand/model/OS constants, uptime, max-memory,
6
+ root/jailbreak detection, side-loading detection, and platform-feature queries - usable from
7
7
  **every** adapter, React, Vue, Svelte, Solid, and Angular, not just React. Like
8
8
  [`@symbiote-native/local-auth`](../local-auth) and unlike this repo's stateful Expo wrapper
9
9
  ([`@symbiote-native/sensors`](../sensors), an `EventEmitter` + live-subscription surface), every
10
10
  export here is either an eagerly-resolved constant or a one-shot async call with no per-instance
11
- state, so there is no hook/composable/service to wrap — the React, Vue, and Angular entry points
11
+ state, so there is no hook/composable/service to wrap - the React, Vue, and Angular entry points
12
12
  are plain re-exports of the same `core`.
13
13
 
14
14
  ## Install
@@ -25,39 +25,39 @@ npx @symbiote-native/cli new my-app --device
25
25
  npx @symbiote-native/cli add --device
26
26
  ```
27
27
 
28
- Either way: installs `@symbiote-native/device` and wires the native autolinking automatically — see
28
+ Either way: installs `@symbiote-native/device` and wires the native autolinking automatically - see
29
29
  [`@symbiote-native/cli`](../cli).
30
30
 
31
31
  <details>
32
- <summary>Manual install (no CLI — installing and wiring native autolinking by hand)</summary>
32
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
33
33
 
34
34
  ```bash
35
35
  npm install @symbiote-native/device
36
36
  ```
37
37
 
38
38
  `expo-device` and `expo-modules-core` come along as regular dependencies, pinned to exact
39
- versions — never install either yourself, and never add the `expo` meta-package to your project
39
+ versions - never install either yourself, and never add the `expo` meta-package to your project
40
40
  (it bundles its own Metro/Babel pipeline, which conflicts with this project's own).
41
41
 
42
42
  ## Required one-time step: native autolinking wiring
43
43
 
44
44
  Unlike a plain RN native module, `expo-device`'s native code is discovered by
45
- `expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism — this needs wiring
45
+ `expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism - this needs wiring
46
46
  into the native host app **once**, covering this package and every other `expo-modules-core`
47
47
  package with zero further changes:
48
48
 
49
49
  | Platform | Touches |
50
50
  | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
51
- | iOS | `ios/Podfile` — add `use_expo_modules!` |
52
- | iOS | `AppDelegate.swift` — Expo's runtime-bootstrap hook |
53
- | Android | `settings.gradle` / `app/build.gradle` — resolve and include the Expo Gradle projects |
54
- | Android | `MainApplication.kt` — Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
51
+ | iOS | `ios/Podfile` - add `use_expo_modules!` |
52
+ | iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
53
+ | Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
54
+ | Android | `MainApplication.kt` - Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
55
55
 
56
56
  Full mechanics live in the `symbiote-expo-native-module` project skill. Reference
57
57
  implementation: `examples/expo-react/ios/Podfile` and
58
58
  `examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt`.
59
59
 
60
- `expo-device` needs no runtime permission on either platform — every constant and function here
60
+ `expo-device` needs no runtime permission on either platform - every constant and function here
61
61
  reads plain system/build information, nothing gated by a permission prompt.
62
62
 
63
63
  </details>
@@ -73,11 +73,11 @@ src/core/ Eager constants (isDevice, brand, manufacturer, modelId, modelName
73
73
  isSideLoadingEnabledAsync / getPlatformFeaturesAsync / hasPlatformFeatureAsync,
74
74
  and the DeviceType enum. native-module.ts resolves the native module via
75
75
  expo-modules-core's requireNativeModule.
76
- src/angular/ @symbiote-native/device/angular — export * from '../core'
76
+ src/angular/ @symbiote-native/device/angular - export * from '../core'
77
77
  ```
78
78
 
79
79
  `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto
80
- `src/core/` — no physical per-framework file, since there's nothing to subscribe to or clean up.
80
+ `src/core/` - no physical per-framework file, since there's nothing to subscribe to or clean up.
81
81
  `./angular` stays a physical file/subpath since Angular ships through a separate `ngc`/AOT build
82
82
  (`build-ngc/`).
83
83
 
@@ -201,7 +201,7 @@ onMounted(() => {
201
201
  ```
202
202
 
203
203
  ```tsx
204
- // Solid — a component body runs once, so the two async values need a signal; the eager
204
+ // Solid - a component body runs once, so the two async values need a signal; the eager
205
205
  // constants (brand, modelName, ...) are plain reads with nothing to subscribe to.
206
206
  import { createSignal, onMount } from 'solid-js';
207
207
  import {
@@ -296,21 +296,21 @@ export class DeviceScreen {
296
296
  }
297
297
  ```
298
298
 
299
- There's no per-instance service to `inject()` in the Angular case — every constant/function is a
299
+ There's no per-instance service to `inject()` in the Angular case - every constant/function is a
300
300
  plain export off the core package, read straight in the constructor or class-field initializer.
301
- These snippets mirror the real canary demo screens — `examples/expo-react/screens/DeviceScreen.tsx`,
301
+ These snippets mirror the real canary demo screens - `examples/expo-react/screens/DeviceScreen.tsx`,
302
302
  `examples/expo-vue-sfc/screens/DeviceScreen.vue`, `examples/expo-vue-tsx/screens/DeviceScreen.tsx`,
303
303
  `examples/expo-svelte/screens/DeviceScreen.svelte`, `examples/expo-solid/screens/DeviceScreen.tsx`,
304
304
  `examples/expo-angular/src/screens/DeviceScreen.ts`.
305
305
 
306
306
  ## API
307
307
 
308
- Eagerly-resolved constants, plus a handful of one-shot async functions — no event stream, no
309
- per-instance state — so the React/Vue/Svelte/Solid/Angular entry points above are plain
308
+ Eagerly-resolved constants, plus a handful of one-shot async functions - no event stream, no
309
+ per-instance state - so the React/Vue/Svelte/Solid/Angular entry points above are plain
310
310
  re-exports of `core` with nothing adapter-specific to add.
311
311
 
312
312
  ```ts
313
- // Constants — resolved once, at import time, straight off the native module:
313
+ // Constants - resolved once, at import time, straight off the native module:
314
314
  isDevice: boolean
315
315
  brand: string | null
316
316
  manufacturer: string | null
@@ -340,12 +340,12 @@ getPlatformFeaturesAsync(): Promise<string[]> // Android only; [] elsewhe
340
340
  hasPlatformFeatureAsync(feature: string): Promise<boolean> // Android only; false elsewhere, never throws
341
341
  ```
342
342
 
343
- Plus `DeviceType` (`UNKNOWN`/`PHONE`/`TABLET`/`DESKTOP`/`TV`) — ported from upstream's
343
+ Plus `DeviceType` (`UNKNOWN`/`PHONE`/`TABLET`/`DESKTOP`/`TV`) - ported from upstream's
344
344
  `Device.types.ts`.
345
345
 
346
346
  ```ts
347
347
  import { getDeviceTypeAsync, isDevice } from '@symbiote-native/device';
348
- // or the framework-scoped entry points — identical surface, re-exported verbatim:
348
+ // or the framework-scoped entry points - identical surface, re-exported verbatim:
349
349
  import { getDeviceTypeAsync } from '@symbiote-native/device/react';
350
350
  import { getDeviceTypeAsync } from '@symbiote-native/device/vue';
351
351
  import { getDeviceTypeAsync } from '@symbiote-native/device/svelte';
@@ -357,26 +357,38 @@ import { getDeviceTypeAsync } from '@symbiote-native/device/angular';
357
357
 
358
358
  - **Every function except `getPlatformFeaturesAsync`/`hasPlatformFeatureAsync` throws an
359
359
  `UnavailabilityError` when the native method is missing.** Those two are the deliberate
360
- exceptions — they resolve to `[]`/`false` instead, matching upstream, since a platform-feature
360
+ exceptions - they resolve to `[]`/`false` instead, matching upstream, since a platform-feature
361
361
  query on a platform with no such concept (iOS) is a normal "no" answer, not an error.
362
362
  - **`getMaxMemoryAsync`'s `-1` native sentinel means "no inherent limit"** and is normalized to
363
- `Number.MAX_SAFE_INTEGER` before it reaches your code — you never see the raw `-1`.
364
- - **`isRootedExperimentalAsync` is a best-effort check, not a guarantee** — root/jailbreak
363
+ `Number.MAX_SAFE_INTEGER` before it reaches your code - you never see the raw `-1`.
364
+ - **`isRootedExperimentalAsync` is a best-effort check, not a guarantee** - root/jailbreak
365
365
  detection bypasses exist on both platforms; a `false` result does not prove the device is
366
366
  unmodified.
367
367
 
368
+ ## Common questions
369
+
370
+ - **`deviceName` is "iPhone" on iOS 16+.** Needs the `user-assigned-device-name` entitlement.
371
+ - **`modelName` / `deviceName` is `null`.** Not determinable on that device.
372
+ - **`isDevice` is `true` on the iOS Simulator.** Reported upstream; do not rely on it.
373
+ - **`getDeviceTypeAsync` says `TABLET` on a phone.** Reported on some Android models.
374
+
375
+ Sources: [Expo docs: Device](https://docs.expo.dev/versions/latest/sdk/device/),
376
+ [expo/expo#19639](https://github.com/expo/expo/issues/19639),
377
+ [expo/expo#19869](https://github.com/expo/expo/issues/19869),
378
+ [expo/expo#11409](https://github.com/expo/expo/issues/11409).
379
+
368
380
  ## Test it
369
381
 
370
- No Fabric/Descriptor angle at all — every export here is a pure constant or async-function
382
+ No Fabric/Descriptor angle at all - every export here is a pure constant or async-function
371
383
  surface, never a view or per-instance state. Tests inject a fake native-module object in place of
372
- the real `requireNativeModule` resolution (`src/core/device.test.ts`, `vitest`) — no
384
+ the real `requireNativeModule` resolution (`src/core/device.test.ts`, `vitest`) - no
373
385
  `installFabric()`, no ViewConfig. Native rendering itself is verified on-device (see the parent
374
386
  [README](../../README.md) for the project's testing model).
375
387
 
376
388
  Native autolinking wiring for `expo-modules-core` packages is already done in all six Expo
377
389
  canary apps (`examples/expo-react`, `examples/expo-vue-sfc`, `examples/expo-vue-tsx`,
378
390
  `examples/expo-svelte`, `examples/expo-solid`, `examples/expo-angular`) via
379
- `@symbiote-native/local-auth`/`@symbiote-native/sensors` — this
391
+ `@symbiote-native/local-auth`/`@symbiote-native/sensors` - this
380
392
  package reuses that same wiring with zero further app-side changes, since
381
393
  `expo-modules-autolinking` discovers any `expo-modules-core` package already present in
382
394
  `node_modules`. A dedicated `DeviceScreen` demo has not been wired into those canaries yet.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/device",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "expo-device wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Device brand/model/OS constants, uptime, max-memory, root/jailbreak detection, side-loading detection, and platform-feature queries.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "expo-device": "57.0.1",
73
- "expo-modules-core": "57.0.5"
73
+ "expo-modules-core": "57.0.20"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@angular/core": ">=20",
@@ -80,12 +80,12 @@
80
80
  "solid-js": ">=1.9.0",
81
81
  "svelte": ">=5.56.0",
82
82
  "vue": ">=3.5.0",
83
- "@symbiote-native/angular": "^3.1.1",
84
- "@symbiote-native/engine": "^1.3.0",
85
- "@symbiote-native/react": "^3.0.3",
86
- "@symbiote-native/solid": "^3.0.3",
87
- "@symbiote-native/svelte": "^3.0.3",
88
- "@symbiote-native/vue": "^3.0.3"
83
+ "@symbiote-native/angular": "^3.2.0",
84
+ "@symbiote-native/engine": "^1.5.0",
85
+ "@symbiote-native/react": "^3.2.0",
86
+ "@symbiote-native/solid": "^3.1.0",
87
+ "@symbiote-native/svelte": "^3.1.0",
88
+ "@symbiote-native/vue": "^3.2.0"
89
89
  },
90
90
  "peerDependenciesMeta": {
91
91
  "@symbiote-native/angular": {
@@ -133,13 +133,13 @@
133
133
  "solid-js": "^1.9.14",
134
134
  "svelte": "^5.56.0",
135
135
  "typescript": "~6.0.0",
136
- "@symbiote-native/angular": "3.1.1",
137
- "@symbiote-native/engine": "1.3.0",
138
- "@symbiote-native/react": "3.0.3",
139
- "@symbiote-native/solid": "3.0.3",
140
- "@symbiote-native/svelte": "3.0.3",
141
- "@symbiote-native/test-utils": "0.4.3",
142
- "@symbiote-native/vue": "3.0.3"
136
+ "@symbiote-native/angular": "3.2.0",
137
+ "@symbiote-native/engine": "1.5.0",
138
+ "@symbiote-native/react": "3.2.0",
139
+ "@symbiote-native/solid": "3.1.0",
140
+ "@symbiote-native/svelte": "3.1.0",
141
+ "@symbiote-native/test-utils": "0.4.6",
142
+ "@symbiote-native/vue": "3.2.0"
143
143
  },
144
144
  "scripts": {
145
145
  "typecheck": "tsc --build",