@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.
- package/README.md +126 -18
- 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
|
|
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 `./
|
|
59
|
-
physical per-framework file, since there's nothing to subscribe to or clean up.
|
|
60
|
-
a physical file/subpath since Angular ships through a separate `ngc`/AOT build
|
|
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.
|
|
230
|
-
trimmed from the real canary demo screens
|
|
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
|
|
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
|
|
290
|
-
(`examples/expo-react`, `examples/expo-vue-sfc`, `examples/expo-vue-tsx`, `examples/expo-
|
|
291
|
-
— iOS Podfile/`AppDelegate.swift` +
|
|
292
|
-
`MainApplication.kt` + `USE_BIOMETRIC`, all
|
|
293
|
-
package isn't yet demoed in the plain, non-Expo
|
|
294
|
-
|
|
295
|
-
|
|
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.
|
|
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.
|
|
127
|
-
"@symbiote-native/engine": "0.
|
|
128
|
-
"@symbiote-native/react": "0.
|
|
129
|
-
"@symbiote-native/solid": "
|
|
130
|
-
"@symbiote-native/svelte": "0.
|
|
131
|
-
"@symbiote-native/test-utils": "0.
|
|
132
|
-
"@symbiote-native/vue": "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",
|