@symbiote-native/local-auth 0.4.0 → 1.0.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 (2) hide show
  1. package/README.md +126 -18
  2. package/package.json +27 -15
package/README.md CHANGED
@@ -3,11 +3,11 @@
3
3
  A wrapper package for [SymbioteNative](../../README.md) that makes
4
4
  [`expo-local-authentication`](https://github.com/expo/expo/tree/main/packages/expo-local-authentication)
5
5
  — FaceID/TouchID on iOS, the Fingerprint/Biometric API on Android — usable from **every**
6
- adapter, React, Vue, and Angular, not just React. Unlike this repo's other Expo wrapper
6
+ adapter, React, Vue, Svelte, Solid, and Angular, not just React. Unlike this repo's other Expo wrapper
7
7
  ([`@symbiote-native/sensors`](../sensors), an `EventEmitter` + live-subscription surface),
8
8
  every function here is a one-shot async call with no per-instance state, so there is no hook/
9
- composable/service to wrap — the React, Vue, and Angular entry points are plain re-exports of
10
- the same `core`.
9
+ composable/service to wrap — the React, Vue, Svelte, Solid, and Angular entry points are plain
10
+ re-exports of the same `core`.
11
11
 
12
12
  ## Install
13
13
 
@@ -55,9 +55,10 @@ src/core/ hasHardwareAsync / isEnrolledAsync / getEnrolledLevelAsync /
55
55
  src/angular/ @symbiote-native/local-auth/angular — export * from '../core'
56
56
  ```
57
57
 
58
- `./react`, `./vue`, and `./svelte` are `exports`-map aliases straight onto `src/core/` — no
59
- physical per-framework file, since there's nothing to subscribe to or clean up. `./angular` stays
60
- a physical file/subpath since Angular ships through a separate `ngc`/AOT build (`build-ngc/`).
58
+ `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto
59
+ `src/core/` — no physical per-framework file, since there's nothing to subscribe to or clean up.
60
+ `./angular` stays a physical file/subpath since Angular ships through a separate `ngc`/AOT build
61
+ (`build-ngc/`).
61
62
 
62
63
  ## Use it
63
64
 
@@ -164,6 +165,108 @@ function handleAuthenticate(): void {
164
165
  </template>
165
166
  ```
166
167
 
168
+ ```svelte
169
+ <!-- Svelte -->
170
+ <script lang="ts">
171
+ import { Platform, Pressable, Text, View } from '@symbiote-native/svelte';
172
+ import {
173
+ authenticateAsync,
174
+ cancelAuthenticate,
175
+ hasHardwareAsync,
176
+ isEnrolledAsync,
177
+ } from '@symbiote-native/local-auth/svelte';
178
+ import type { ILocalAuthenticationResult } from '@symbiote-native/local-auth/svelte';
179
+
180
+ let hasHardware = $state(false);
181
+ let isEnrolled = $state(false);
182
+ let authResult = $state<ILocalAuthenticationResult | null>(null);
183
+
184
+ $effect(() => {
185
+ hasHardwareAsync().then(value => (hasHardware = value));
186
+ isEnrolledAsync().then(value => (isEnrolled = value));
187
+ });
188
+
189
+ function handleAuthenticate(): void {
190
+ authenticateAsync({ promptMessage: 'Confirm it is you' }).then(value => {
191
+ authResult = value;
192
+ });
193
+ }
194
+ </script>
195
+
196
+ <View>
197
+ <Text>
198
+ {hasHardware && isEnrolled ? 'Ready to authenticate' : 'No biometrics enrolled'}
199
+ </Text>
200
+ <Pressable onPress={handleAuthenticate}>
201
+ <Text>Authenticate</Text>
202
+ </Pressable>
203
+ {#if Platform.OS === 'android'}
204
+ <Pressable onPress={() => cancelAuthenticate()}>
205
+ <Text>Cancel</Text>
206
+ </Pressable>
207
+ {/if}
208
+ {#if authResult}
209
+ <Text>{authResult.success ? 'Success' : `Failed: ${authResult.error}`}</Text>
210
+ {/if}
211
+ </View>
212
+ ```
213
+
214
+ ```tsx
215
+ // Solid
216
+ import { Show, createSignal, onMount } from 'solid-js';
217
+ import { Platform, Pressable, Text, View } from '@symbiote-native/solid';
218
+ import {
219
+ authenticateAsync,
220
+ cancelAuthenticate,
221
+ hasHardwareAsync,
222
+ isEnrolledAsync,
223
+ } from '@symbiote-native/local-auth/solid';
224
+ import type { ILocalAuthenticationResult } from '@symbiote-native/local-auth/solid';
225
+
226
+ function LocalAuthScreen() {
227
+ const [hasHardware, setHasHardware] = createSignal(false);
228
+ const [isEnrolled, setIsEnrolled] = createSignal(false);
229
+ const [authResult, setAuthResult] =
230
+ createSignal<ILocalAuthenticationResult | null>(null);
231
+
232
+ onMount(() => {
233
+ void hasHardwareAsync().then(setHasHardware);
234
+ void isEnrolledAsync().then(setIsEnrolled);
235
+ });
236
+
237
+ const handleAuthenticate = () => {
238
+ void authenticateAsync({ promptMessage: 'Confirm it is you' }).then(
239
+ setAuthResult,
240
+ );
241
+ };
242
+
243
+ return (
244
+ <View>
245
+ <Text>
246
+ {hasHardware() && isEnrolled()
247
+ ? 'Ready to authenticate'
248
+ : 'No biometrics enrolled'}
249
+ </Text>
250
+ <Pressable onPress={handleAuthenticate}>
251
+ <Text>Authenticate</Text>
252
+ </Pressable>
253
+ {Platform.OS === 'android' && (
254
+ <Pressable onPress={() => cancelAuthenticate()}>
255
+ <Text>Cancel</Text>
256
+ </Pressable>
257
+ )}
258
+ <Show when={authResult()} keyed>
259
+ {result => (
260
+ <Text>
261
+ {result.success ? 'Success' : `Failed: ${result.error}`}
262
+ </Text>
263
+ )}
264
+ </Show>
265
+ </View>
266
+ );
267
+ }
268
+ ```
269
+
167
270
  ```ts
168
271
  // Angular
169
272
  import { Component, signal } from '@angular/core';
@@ -226,17 +329,19 @@ export class LocalAuthScreen {
226
329
  ```
227
330
 
228
331
  There's no per-instance service to `inject()` in the Angular case — every function is a plain
229
- free function off the core package, called straight from the constructor. All three examples are
230
- trimmed from the real canary demo screens (`examples/expo-react/screens/LocalAuthScreen.tsx`,
332
+ free function off the core package, called straight from the constructor. The React/Vue/Angular
333
+ examples are trimmed from the real canary demo screens
334
+ (`examples/expo-react/screens/LocalAuthScreen.tsx`,
231
335
  `examples/expo-vue-sfc/screens/LocalAuthScreen.vue`, `examples/expo-vue-tsx/screens/LocalAuthScreen.tsx`,
232
336
  `examples/expo-angular/src/screens/LocalAuthScreen.ts`), which also cover
233
- `getEnrolledLevelAsync`/`supportedAuthenticationTypesAsync` and render a capabilities card.
337
+ `getEnrolledLevelAsync`/`supportedAuthenticationTypesAsync` and render a capabilities card. No
338
+ canary demo screen exists yet for Svelte/Solid — the two snippets above follow the same surface.
234
339
 
235
340
  ## API
236
341
 
237
342
  Free functions, no event stream, no per-instance state — upstream ships a handful of async
238
- functions and two enums, not a subscribable sensor, so the React/Vue/Angular entry points above
239
- are plain re-exports of `core` with nothing adapter-specific to add.
343
+ functions and two enums, not a subscribable sensor, so the React/Vue/Svelte/Solid/Angular entry
344
+ points above are plain re-exports of `core` with nothing adapter-specific to add.
240
345
 
241
346
  ```ts
242
347
  hasHardwareAsync(): Promise<boolean>
@@ -260,6 +365,8 @@ import {
260
365
  // or the framework-scoped entry points — identical surface, re-exported verbatim:
261
366
  import { authenticateAsync } from '@symbiote-native/local-auth/react';
262
367
  import { authenticateAsync } from '@symbiote-native/local-auth/vue';
368
+ import { authenticateAsync } from '@symbiote-native/local-auth/svelte';
369
+ import { authenticateAsync } from '@symbiote-native/local-auth/solid';
263
370
  import { authenticateAsync } from '@symbiote-native/local-auth/angular';
264
371
  ```
265
372
 
@@ -286,10 +393,11 @@ a view or per-instance state. Tests inject a fake native-module object in place
286
393
  `src/core/types.test.ts`, `vitest`) — no `installFabric()`, no ViewConfig. Native rendering itself
287
394
  is verified on-device (see the parent [README](../../README.md) for the project's testing model).
288
395
 
289
- Native autolinking wiring is done in the four Expo canary apps
290
- (`examples/expo-react`, `examples/expo-vue-sfc`, `examples/expo-vue-tsx`, `examples/expo-angular`)
291
- — iOS Podfile/`AppDelegate.swift` + `NSFaceIDUsageDescription`, Android Gradle/
292
- `MainApplication.kt` + `USE_BIOMETRIC`, all four confirmed present. The one remaining gap: this
293
- package isn't yet demoed in the plain, non-Expo `examples/react`/`vue-sfc`/`vue-tsx`/`angular`
294
- canaries, since an `expo-modules-core` package needs the `expo-modules-autolinking` wiring only
295
- the `examples/expo-*` apps have set up so far.
396
+ Native autolinking wiring is done in all six Expo canary apps
397
+ (`examples/expo-react`, `examples/expo-vue-sfc`, `examples/expo-vue-tsx`, `examples/expo-svelte`,
398
+ `examples/expo-solid`, `examples/expo-angular`) — iOS Podfile/`AppDelegate.swift` +
399
+ `NSFaceIDUsageDescription`, Android Gradle/`MainApplication.kt` + `USE_BIOMETRIC`, all six
400
+ confirmed present. The one remaining gap: this package isn't yet demoed in the plain, non-Expo
401
+ `examples/react`/`vue-sfc`/`vue-tsx`/`svelte`/`solid`/`angular` canaries, since an
402
+ `expo-modules-core` package needs the `expo-modules-autolinking` wiring only the
403
+ `examples/expo-*` apps have set up so far.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symbiote-native/local-auth",
3
- "version": "0.4.0",
3
+ "version": "1.0.0",
4
4
  "description": "expo-local-authentication wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. FaceID/TouchID on iOS, the Fingerprint/Biometric API on Android.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,6 +13,18 @@
13
13
  "url": "https://github.com/OneEyed1366/symbiote-native/issues"
14
14
  },
15
15
  "author": "Andrey Prokopenko <psevdoproger@gmail.com>",
16
+ "keywords": [
17
+ "react-native",
18
+ "symbiote-native",
19
+ "expo-local-authentication",
20
+ "react",
21
+ "vue",
22
+ "svelte",
23
+ "solid",
24
+ "angular",
25
+ "biometrics",
26
+ "face-id"
27
+ ],
16
28
  "type": "module",
17
29
  "main": "./build/core/index.js",
18
30
  "module": "./build/core/index.js",
@@ -62,19 +74,19 @@
62
74
  "invariant": "^2.2.4"
63
75
  },
64
76
  "peerDependencies": {
65
- "@symbiote-native/angular": ">=0.6.2",
66
- "@symbiote-native/engine": ">=0.1.7",
67
- "@symbiote-native/react": ">=0.2.8",
68
- "@symbiote-native/solid": ">=0.0.1",
69
- "@symbiote-native/svelte": ">=0.1.0",
70
- "@symbiote-native/vue": ">=0.3.8",
71
77
  "@angular/core": ">=20",
72
78
  "@vue/runtime-core": "^3.5.13",
73
79
  "react": ">=19.0.0",
74
80
  "react-native": ">=0.86",
75
81
  "solid-js": ">=1.9.0",
76
82
  "svelte": ">=5.56.0",
77
- "vue": ">=3.5.0"
83
+ "vue": ">=3.5.0",
84
+ "@symbiote-native/angular": "^1.0.0",
85
+ "@symbiote-native/engine": "^0.4.0",
86
+ "@symbiote-native/react": "^1.0.0",
87
+ "@symbiote-native/solid": "^1.0.0",
88
+ "@symbiote-native/svelte": "^1.0.0",
89
+ "@symbiote-native/vue": "^1.0.0"
78
90
  },
79
91
  "peerDependenciesMeta": {
80
92
  "@symbiote-native/angular": {
@@ -123,13 +135,13 @@
123
135
  "solid-js": "^1.9.14",
124
136
  "svelte": "^5.56.0",
125
137
  "typescript": "~6.0.0",
126
- "@symbiote-native/angular": "0.8.0",
127
- "@symbiote-native/engine": "0.3.0",
128
- "@symbiote-native/react": "0.4.0",
129
- "@symbiote-native/solid": "0.1.0",
130
- "@symbiote-native/svelte": "0.3.0",
131
- "@symbiote-native/test-utils": "0.2.0",
132
- "@symbiote-native/vue": "0.5.0"
138
+ "@symbiote-native/angular": "1.0.0",
139
+ "@symbiote-native/engine": "0.4.0",
140
+ "@symbiote-native/react": "1.0.0",
141
+ "@symbiote-native/solid": "1.0.0",
142
+ "@symbiote-native/svelte": "1.0.0",
143
+ "@symbiote-native/test-utils": "0.3.0",
144
+ "@symbiote-native/vue": "1.0.0"
133
145
  },
134
146
  "scripts": {
135
147
  "typecheck": "tsc --build",