Glowup
Companion package
Device
@its/glowup-device is the headless hardware layer beside the kit: device info, location, the camera, network, battery, keep-awake, orientation, haptics, biometrics, a secure store, the motion sensors, the photo library, background location with geofencing, Bluetooth Low Energy, UHF RFID readers and hardware barcode scanners, each behind an adapter your app can replace. It renders no UI of its own — every page here is built with Glowup components on top of it.
Capabilities
One subpath each, so an app installs only the Expo modules of the capabilities it imports.
Install
The package's config plugin writes the purpose strings and permissions of the capabilities you list, and nothing else: foreground location only, the microphone only with recordAudio, no activity recognition for the sensors, no media read permission for the library.
Terminal
npm install @its/glowup-device # then only the Expo modules of the subpaths you import: npx expo install expo-device expo-application # /info npx expo install expo-location # /location npx expo install expo-camera # /camera npx expo install @react-native-community/netinfo # /network npx expo install expo-battery # /battery npx expo install expo-keep-awake # /keep-awake npx expo install expo-screen-orientation # /orientation npx expo install expo-haptics # /haptics npx expo install expo-local-authentication # /biometrics npx expo install expo-secure-store # /secure-store npx expo install expo-sensors # /sensors npx expo install expo-image-picker # /media-picker npx expo install expo-media-library # /media-library npx expo install expo-location expo-task-manager # /background-location npx expo install react-native-ble-manager # /bluetooth npm install @its/rfid-honeywell # /rfid: one vendor package npm install @its/scanner-honeywell # /scanner: one vendor package
app.config.ts
// app.config.ts — configures only what you list plugins: [ [ "@its/glowup-device", { location: { whenInUsePermission: "Shows the shops near you." }, camera: { cameraPermission: "Scans the QR code on your ticket.", microphonePermission: "Records your voice in video reviews.", recordAudio: true, // omit it if videos need no sound }, biometrics: { faceIDPermission: "Unlocks your saved cards." }, secureStore: true, sensors: { motionPermission: "Counts the floors you climb." }, mediaPicker: true, mediaLibrary: { savePermission: "Saves your edited photos." }, backgroundLocation: { geofencing: true, alwaysPermission: "Records your trip while the app is closed.", }, bluetooth: { permission: "Reads your heart rate monitor." }, }, ], ],
Adapters and tests
Hooks and CameraView talk to an adapter, never to Expo directly. The Expo one is the default; DeviceAdaptersProvider swaps any of them for a subtree — in tests, for the in-memory adapters of @its/glowup-device/testing.
Screen.test.tsx
import { DeviceAdaptersProvider } from "@its/glowup-device"; import { createMockCameraAdapter, createMockLocationAdapter, } from "@its/glowup-device/testing"; // In a test: no hardware, no jest.mock of Expo modules. const location = createMockLocationAdapter({ permission: "granted" }); render( <DeviceAdaptersProvider adapters={{ location, camera: createMockCameraAdapter() }}> <Screen /> </DeviceAdaptersProvider>, ); location.emit(buildPosition({ latitude: 45.46, longitude: 9.19 }));