Skip to content

Commit e980fd3

Browse files
committed
Format code
1 parent 0bad9b9 commit e980fd3

4 files changed

Lines changed: 132 additions & 86 deletions

File tree

examples/react-expo/app/index.tsx

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as Evolu from "@evolu/common";
22
import { createUseEvolu, EvoluProvider, useQuery } from "@evolu/react";
3-
import { evoluReactNativeDeps, localAuth, EvoluAvatar } from "@evolu/react-native/expo-sqlite";
3+
import {
4+
evoluReactNativeDeps,
5+
localAuth,
6+
EvoluAvatar,
7+
} from "@evolu/react-native/expo-sqlite";
48
import { FC, Suspense, use, useEffect, useMemo, useState } from "react";
59
import type { Evolu as EvoluType } from "@evolu/common";
610

@@ -61,9 +65,10 @@ export default function Index(): React.ReactNode {
6165
setAuthResult(authResult);
6266

6367
/**
64-
* Subscribe to unexpected Evolu errors (database, network, sync issues). These
65-
* should not happen in normal operation, so always log them for debugging. Show
66-
* users a friendly error message instead of technical details.
68+
* Subscribe to unexpected Evolu errors (database, network, sync issues).
69+
* These should not happen in normal operation, so always log them for
70+
* debugging. Show users a friendly error message instead of technical
71+
* details.
6772
*/
6873
return evolu.subscribeError(() => {
6974
const error = evolu.getError();
@@ -87,11 +92,7 @@ export default function Index(): React.ReactNode {
8792

8893
return (
8994
<EvoluProvider value={evolu}>
90-
<EvoluDemo
91-
evolu={evolu}
92-
ownerIds={ownerIds}
93-
authResult={authResult}
94-
/>
95+
<EvoluDemo evolu={evolu} ownerIds={ownerIds} authResult={authResult} />
9596
</EvoluProvider>
9697
);
9798
}
@@ -151,7 +152,10 @@ function EvoluDemo({
151152

152153
return (
153154
<View
154-
style={[styles.todosContainer, { paddingTop: todos.length > 0 ? 6 : 24 }]}
155+
style={[
156+
styles.todosContainer,
157+
{ paddingTop: todos.length > 0 ? 6 : 24 },
158+
]}
155159
>
156160
<View
157161
style={[
@@ -233,7 +237,10 @@ function EvoluDemo({
233237
onPress={handleToggleCompletedPress}
234238
>
235239
<View
236-
style={[styles.checkbox, isCompleted ? styles.checkboxChecked : null]}
240+
style={[
241+
styles.checkbox,
242+
isCompleted ? styles.checkboxChecked : null,
243+
]}
237244
>
238245
<Text
239246
style={[
@@ -382,7 +389,7 @@ function EvoluDemo({
382389
() => ownerIds?.filter(({ ownerId }) => ownerId !== appOwner?.id) ?? [],
383390
[appOwner?.id, ownerIds],
384391
);
385-
392+
386393
// Create a new owner and register it to a passkey.
387394
const handleRegisterPress = async () => {
388395
Alert.prompt(
@@ -394,16 +401,16 @@ function EvoluDemo({
394401
text: "Register",
395402
onPress: async (username?: string) => {
396403
if (username == null) return;
397-
404+
398405
// Determine if this is a guest login or a new owner.
399406
const isGuest = !Boolean(authResult?.owner);
400-
407+
401408
// Register the guest owner or create a new one if this is already registered.
402409
const mnemonic = isGuest ? appOwner?.mnemonic : undefined;
403-
const result = await localAuth.register(
404-
username,
405-
{ service, mnemonic },
406-
);
410+
const result = await localAuth.register(username, {
411+
service,
412+
mnemonic,
413+
});
407414
if (result) {
408415
// If this is a guest owner, we should clear the database and reload.
409416
// The owner is transferred to a new database on next login.
@@ -422,7 +429,7 @@ function EvoluDemo({
422429
"plain-text",
423430
);
424431
};
425-
432+
426433
// Login with a specific owner id using the registered passkey.
427434
const handleLoginPress = async (ownerId: Evolu.OwnerId) => {
428435
const result = await localAuth.login(ownerId, { service });
@@ -432,7 +439,7 @@ function EvoluDemo({
432439
Alert.alert("Error", "Failed to login");
433440
}
434441
};
435-
442+
436443
// Clear all data including passkeys and metadata.
437444
const handleClearAllPress = async () => {
438445
Alert.alert(
@@ -451,7 +458,7 @@ function EvoluDemo({
451458
],
452459
);
453460
};
454-
461+
455462
return (
456463
<View style={styles.authActionsContainer}>
457464
<Text style={styles.sectionTitle}>Passkeys</Text>
@@ -497,7 +504,11 @@ function EvoluDemo({
497504
<EvoluAvatar id={ownerId} />
498505
<View style={styles.ownerDetails}>
499506
<Text style={styles.ownerUsername}>{username}</Text>
500-
<Text style={styles.ownerIdText} numberOfLines={1} ellipsizeMode="middle">
507+
<Text
508+
style={styles.ownerIdText}
509+
numberOfLines={1}
510+
ellipsizeMode="middle"
511+
>
501512
{ownerId as string}
502513
</Text>
503514
</View>
@@ -538,7 +549,7 @@ function EvoluDemo({
538549
</TouchableOpacity>
539550
);
540551
};
541-
552+
542553
return (
543554
<SafeAreaView style={styles.container}>
544555
<ScrollView

packages/common/src/Evolu/LocalAuth.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import {
1010
OwnerWriteKey,
1111
} from "./Owner.js";
1212

13-
/**
14-
* Local authentication and authorization system for Evolu.
15-
* This is API is subject to change and not recommended for production use.
13+
/**
14+
* Local authentication and authorization system for Evolu. This is API is
15+
* subject to change and not recommended for production use.
1616
*
1717
* @experimental
1818
*/
@@ -178,10 +178,22 @@ export const createLocalAuth = (
178178
return {
179179
...newOptions,
180180
authenticationPrompt: {
181-
title: replaceMessageTokens(newOptions.authenticationPrompt?.title ?? "", username),
182-
cancel: replaceMessageTokens(newOptions.authenticationPrompt?.cancel ?? "", username),
183-
subtitle: replaceMessageTokens(newOptions.authenticationPrompt?.subtitle ?? "", username),
184-
description: replaceMessageTokens(newOptions.authenticationPrompt?.description ?? "", username),
181+
title: replaceMessageTokens(
182+
newOptions.authenticationPrompt?.title ?? "",
183+
username,
184+
),
185+
cancel: replaceMessageTokens(
186+
newOptions.authenticationPrompt?.cancel ?? "",
187+
username,
188+
),
189+
subtitle: replaceMessageTokens(
190+
newOptions.authenticationPrompt?.subtitle ?? "",
191+
username,
192+
),
193+
description: replaceMessageTokens(
194+
newOptions.authenticationPrompt?.description ?? "",
195+
username,
196+
),
185197
},
186198
};
187199
};
Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { View } from 'react-native';
2-
import { SvgXml } from 'react-native-svg';
3-
import { FC, useMemo } from 'react';
4-
import { bloSvg } from 'blo';
5-
import { OwnerId } from '@evolu/common';
1+
import { View } from "react-native";
2+
import { SvgXml } from "react-native-svg";
3+
import { FC, useMemo } from "react";
4+
import { bloSvg } from "blo";
5+
import { OwnerId } from "@evolu/common";
66

77
export const EvoluAvatar: FC<{
88
id: OwnerId;
@@ -11,17 +11,15 @@ export const EvoluAvatar: FC<{
1111
}> = ({ id, size = 32, borderRadius = 3 }) => {
1212
const svg = useMemo(() => bloSvg(`0x${id}`), [id]);
1313
return id ? (
14-
<View style={{
15-
width: size,
16-
height: size,
17-
borderRadius,
18-
overflow: 'hidden',
19-
}}>
20-
<SvgXml
21-
xml={svg}
22-
width={size}
23-
height={size}
24-
/>
14+
<View
15+
style={{
16+
width: size,
17+
height: size,
18+
borderRadius,
19+
overflow: "hidden",
20+
}}
21+
>
22+
<SvgXml xml={svg} width={size} height={size} />
2523
</View>
2624
) : null;
27-
}
25+
};
Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
1-
import KVStore from 'expo-sqlite/kv-store';
2-
import * as SecureStore from 'expo-secure-store';
3-
import { AUTH_DEFAULT_OPTIONS } from '@evolu/common';
1+
import KVStore from "expo-sqlite/kv-store";
2+
import * as SecureStore from "expo-secure-store";
3+
import { AUTH_DEFAULT_OPTIONS } from "@evolu/common";
44

5-
import type { LocalAuthOptions, SecureStorage, SensitiveInfoItem, StorageMetadata, AccessControl } from "@evolu/common";
5+
import type {
6+
LocalAuthOptions,
7+
SecureStorage,
8+
SensitiveInfoItem,
9+
StorageMetadata,
10+
AccessControl,
11+
} from "@evolu/common";
612

713
export const createSecureStore = (): SecureStorage => {
814
const store: SecureStorage = {
915
setItem: async (key, value, options) => {
1016
const rnsiOpts = convertOptions(options);
11-
const service = options?.service ?? 'default';
12-
const metadata = createMetadata(options?.accessControl === 'none');
13-
await KVStore.setItem(`${service}-${key}`, '1');
14-
await SecureStore.setItemAsync(key, JSON.stringify({value, metadata}), rnsiOpts);
17+
const service = options?.service ?? "default";
18+
const metadata = createMetadata(options?.accessControl === "none");
19+
await KVStore.setItem(`${service}-${key}`, "1");
20+
await SecureStore.setItemAsync(
21+
key,
22+
JSON.stringify({ value, metadata }),
23+
rnsiOpts,
24+
);
1525
return { metadata };
1626
},
1727

1828
getItem: async (key, options) => {
1929
const rnsiOpts = convertOptions(options);
20-
const service = options?.service ?? 'default';
21-
let data: {value: string; metadata: StorageMetadata};
30+
const service = options?.service ?? "default";
31+
let data: { value: string; metadata: StorageMetadata };
2232
try {
2333
const result = await SecureStore.getItemAsync(key, rnsiOpts);
2434
if (!result) return null;
25-
data = JSON.parse(result) as {value: string; metadata: StorageMetadata};
35+
data = JSON.parse(result) as {
36+
value: string;
37+
metadata: StorageMetadata;
38+
};
2639
} catch (_error) {
2740
return null;
2841
}
@@ -31,7 +44,7 @@ export const createSecureStore = (): SecureStorage => {
3144

3245
deleteItem: async (key, options) => {
3346
const rnsiOpts = convertOptions(options);
34-
const service = options?.service ?? 'default';
47+
const service = options?.service ?? "default";
3548
await Promise.all([
3649
KVStore.removeItemAsync(`${service}-${key}`),
3750
SecureStore.deleteItemAsync(key, rnsiOpts),
@@ -41,21 +54,27 @@ export const createSecureStore = (): SecureStorage => {
4154

4255
getAllItems: async (options) => {
4356
const keys = await KVStore.getAllKeysAsync();
44-
const service = options?.service ?? 'default';
45-
const metadata = createMetadata(options?.accessControl === 'none');
57+
const service = options?.service ?? "default";
58+
const metadata = createMetadata(options?.accessControl === "none");
4659
return keys
47-
.filter(key => key.startsWith(`${service}-`))
48-
.map(key => ({ key: key.slice(service.length + 1), service, metadata }));
60+
.filter((key) => key.startsWith(`${service}-`))
61+
.map((key) => ({
62+
key: key.slice(service.length + 1),
63+
service,
64+
metadata,
65+
}));
4966
},
5067

5168
clearService: async (options) => {
5269
const rnsiOpts = convertOptions(options);
53-
const service = options?.service ?? 'default';
70+
const service = options?.service ?? "default";
5471
const items = await store.getAllItems(options);
55-
await KVStore.multiRemove(items.map(item => `${service}-${item.key}`));
56-
await Promise.all(items.map(async (item) => {
57-
await SecureStore.deleteItemAsync(item.key, rnsiOpts);
58-
}));
72+
await KVStore.multiRemove(items.map((item) => `${service}-${item.key}`));
73+
await Promise.all(
74+
items.map(async (item) => {
75+
await SecureStore.deleteItemAsync(item.key, rnsiOpts);
76+
}),
77+
);
5978
},
6079
};
6180

@@ -75,29 +94,34 @@ const createMetadata = (isSecure = true): SensitiveInfoItem["metadata"] => {
7594
};
7695
};
7796

78-
function convertOptions(options?: LocalAuthOptions): SecureStore.SecureStoreOptions {
79-
const accessGroup = options?.keychainGroup
80-
?? AUTH_DEFAULT_OPTIONS.keychainGroup
81-
?? '';
82-
const keychainService = options?.service
83-
?? AUTH_DEFAULT_OPTIONS.service
84-
?? '';
85-
const keychainAccessible = convertKeychainAccessible(options?.accessControl
86-
?? AUTH_DEFAULT_OPTIONS.accessControl
87-
?? 'biometryCurrentSet');
88-
const authenticationPrompt = options?.authenticationPrompt?.title
89-
?? AUTH_DEFAULT_OPTIONS.authenticationPrompt?.title
90-
?? '';
97+
function convertOptions(
98+
options?: LocalAuthOptions,
99+
): SecureStore.SecureStoreOptions {
100+
const accessGroup =
101+
options?.keychainGroup ?? AUTH_DEFAULT_OPTIONS.keychainGroup ?? "";
102+
const keychainService =
103+
options?.service ?? AUTH_DEFAULT_OPTIONS.service ?? "";
104+
const keychainAccessible = convertKeychainAccessible(
105+
options?.accessControl ??
106+
AUTH_DEFAULT_OPTIONS.accessControl ??
107+
"biometryCurrentSet",
108+
);
109+
const authenticationPrompt =
110+
options?.authenticationPrompt?.title ??
111+
AUTH_DEFAULT_OPTIONS.authenticationPrompt?.title ??
112+
"";
91113
return {
92114
accessGroup,
93115
keychainService,
94116
keychainAccessible,
95117
authenticationPrompt,
96-
requireAuthentication: options?.accessControl !== 'none',
118+
requireAuthentication: options?.accessControl !== "none",
97119
};
98120
}
99121

100-
function convertKeychainAccessible(accessControl: AccessControl): SecureStore.KeychainAccessibilityConstant {
122+
function convertKeychainAccessible(
123+
accessControl: AccessControl,
124+
): SecureStore.KeychainAccessibilityConstant {
101125
switch (accessControl) {
102126
case "none":
103127
// eslint-disable-next-line @typescript-eslint/no-deprecated
@@ -111,8 +135,9 @@ function convertKeychainAccessible(accessControl: AccessControl): SecureStore.Ke
111135
case "secureEnclaveBiometry":
112136
return SecureStore.AFTER_FIRST_UNLOCK;
113137
// Exhaustive check
114-
default: accessControl satisfies never;
115-
// Default (for typescript, should never hit)
116-
return SecureStore.AFTER_FIRST_UNLOCK;
138+
default:
139+
accessControl satisfies never;
140+
// Default (for typescript, should never hit)
141+
return SecureStore.AFTER_FIRST_UNLOCK;
117142
}
118143
}

0 commit comments

Comments
 (0)