jazz-react-native 0.8.44 → 0.8.46
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +20 -0
- package/dist/auth/DemoAuthMethod.js +58 -23
- package/dist/auth/DemoAuthMethod.js.map +1 -1
- package/dist/crypto/RNQuickCrypto.d.ts +12 -0
- package/dist/crypto/RNQuickCrypto.js +31 -0
- package/dist/crypto/RNQuickCrypto.js.map +1 -0
- package/dist/crypto/index.d.ts +1 -0
- package/dist/crypto/index.js +2 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +52 -21
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +5 -5
- package/dist/provider.js +3 -1
- package/dist/provider.js.map +1 -1
- package/dist/tests/DemoAuthMethod.test.d.ts +1 -0
- package/dist/tests/DemoAuthMethod.test.js +186 -0
- package/dist/tests/DemoAuthMethod.test.js.map +1 -0
- package/package.json +11 -6
- package/src/auth/DemoAuthMethod.ts +77 -41
- package/src/crypto/RNQuickCrypto.ts +58 -0
- package/src/crypto/index.ts +1 -0
- package/src/index.ts +60 -25
- package/src/provider.tsx +8 -0
- package/src/tests/DemoAuthMethod.test.ts +282 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
2
|
+
import { RNDemoAuth } from "../auth/DemoAuthMethod";
|
3
|
+
import { KvStoreContext } from "../storage/kv-store-context";
|
4
|
+
// Initialize mock storage
|
5
|
+
const mockStorage = {};
|
6
|
+
// Mock KvStore implementation
|
7
|
+
const mockKvStore = {
|
8
|
+
get: vi.fn(async (key) => mockStorage[key] || null),
|
9
|
+
set: vi.fn(async (key, value) => {
|
10
|
+
mockStorage[key] = value;
|
11
|
+
}),
|
12
|
+
delete: vi.fn(async (key) => {
|
13
|
+
delete mockStorage[key];
|
14
|
+
}),
|
15
|
+
clearAll: vi.fn(async () => {
|
16
|
+
Object.keys(mockStorage).forEach((key) => delete mockStorage[key]);
|
17
|
+
}),
|
18
|
+
};
|
19
|
+
KvStoreContext.getInstance().initialize(mockKvStore);
|
20
|
+
beforeEach(() => {
|
21
|
+
mockKvStore.clearAll();
|
22
|
+
vi.clearAllMocks();
|
23
|
+
});
|
24
|
+
function setup() {
|
25
|
+
const mockDriver = {
|
26
|
+
onReady: vi.fn(),
|
27
|
+
onSignedIn: vi.fn(),
|
28
|
+
onError: vi.fn(),
|
29
|
+
};
|
30
|
+
return {
|
31
|
+
mockStorage,
|
32
|
+
mockKvStore,
|
33
|
+
mockDriver,
|
34
|
+
};
|
35
|
+
}
|
36
|
+
describe("RNDemoAuth", () => {
|
37
|
+
describe("initialization", () => {
|
38
|
+
it("should initialize with seed accounts", async () => {
|
39
|
+
const { mockKvStore, mockDriver } = setup();
|
40
|
+
const seedAccounts = {
|
41
|
+
testUser: {
|
42
|
+
accountID: "test-account-id",
|
43
|
+
accountSecret: "test-secret",
|
44
|
+
},
|
45
|
+
};
|
46
|
+
await RNDemoAuth.init(mockDriver, seedAccounts);
|
47
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser");
|
48
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + btoa("testUser"), expect.any(String));
|
49
|
+
});
|
50
|
+
});
|
51
|
+
describe("authentication", () => {
|
52
|
+
it("should handle new user signup", async () => {
|
53
|
+
const { mockDriver } = setup();
|
54
|
+
mockDriver.onReady = vi.fn(({ signUp }) => {
|
55
|
+
signUp("testUser");
|
56
|
+
});
|
57
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
58
|
+
const result = await auth.start();
|
59
|
+
expect(mockDriver.onReady).toHaveBeenCalled();
|
60
|
+
expect(result.type).toBe("new");
|
61
|
+
expect(result.saveCredentials).toBeDefined();
|
62
|
+
});
|
63
|
+
it("should handle existing user login", async () => {
|
64
|
+
const { mockStorage, mockDriver } = setup();
|
65
|
+
// Set up existing user in storage
|
66
|
+
const existingUser = {
|
67
|
+
accountID: "test-account-id",
|
68
|
+
accountSecret: "test-secret",
|
69
|
+
};
|
70
|
+
mockStorage["demo-auth-logged-in-secret"] = JSON.stringify(existingUser);
|
71
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
72
|
+
const result = await auth.start();
|
73
|
+
if (result.type !== "existing") {
|
74
|
+
throw new Error("Result is not a existing user");
|
75
|
+
}
|
76
|
+
expect(result.type).toBe("existing");
|
77
|
+
expect(result.credentials).toEqual({
|
78
|
+
accountID: existingUser.accountID,
|
79
|
+
secret: existingUser.accountSecret,
|
80
|
+
});
|
81
|
+
});
|
82
|
+
it("should handle logout", async () => {
|
83
|
+
const { mockKvStore, mockDriver } = setup();
|
84
|
+
mockDriver.onReady = vi.fn(({ signUp }) => {
|
85
|
+
signUp("testUser");
|
86
|
+
});
|
87
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
88
|
+
const result = await auth.start();
|
89
|
+
await result.logOut();
|
90
|
+
expect(mockKvStore.delete).toHaveBeenCalledWith("demo-auth-logged-in-secret");
|
91
|
+
});
|
92
|
+
});
|
93
|
+
describe("user management", () => {
|
94
|
+
it("should signup a new user", async () => {
|
95
|
+
const { mockKvStore, mockDriver } = setup();
|
96
|
+
mockDriver.onReady = vi.fn(({ signUp }) => {
|
97
|
+
return signUp("testUser");
|
98
|
+
});
|
99
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
100
|
+
const result = await auth.start();
|
101
|
+
if (result.type !== "new") {
|
102
|
+
throw new Error("Result is not a new user");
|
103
|
+
}
|
104
|
+
await result.saveCredentials({
|
105
|
+
accountID: "test-account-id",
|
106
|
+
secret: "test-secret",
|
107
|
+
});
|
108
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + btoa("testUser"), expect.any(String));
|
109
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser");
|
110
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-logged-in-secret", expect.any(String));
|
111
|
+
});
|
112
|
+
it("should login an existing user", async () => {
|
113
|
+
const { mockStorage, mockKvStore, mockDriver } = setup();
|
114
|
+
const credentials = {
|
115
|
+
accountID: "test-account-id",
|
116
|
+
accountSecret: "test-secret",
|
117
|
+
};
|
118
|
+
mockStorage["demo-auth-existing-users-" + btoa("testUser")] =
|
119
|
+
JSON.stringify(credentials);
|
120
|
+
mockDriver.onReady = vi.fn(({ logInAs }) => {
|
121
|
+
return logInAs("testUser");
|
122
|
+
});
|
123
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
124
|
+
const result = await auth.start();
|
125
|
+
if (result.type !== "existing") {
|
126
|
+
throw new Error("Result is not a existing user");
|
127
|
+
}
|
128
|
+
expect(result.credentials).toEqual({
|
129
|
+
accountID: credentials.accountID,
|
130
|
+
secret: credentials.accountSecret,
|
131
|
+
});
|
132
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-logged-in-secret", JSON.stringify(credentials));
|
133
|
+
});
|
134
|
+
it("should handle duplicate usernames by adding suffix", async () => {
|
135
|
+
const { mockStorage, mockKvStore, mockDriver } = setup();
|
136
|
+
mockDriver.onReady = vi.fn(({ signUp }) => {
|
137
|
+
return signUp("testUser");
|
138
|
+
});
|
139
|
+
mockStorage["demo-auth-existing-users"] = "testUser";
|
140
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
141
|
+
const result = await auth.start();
|
142
|
+
if (result.type !== "new") {
|
143
|
+
throw new Error("Result is not a new user");
|
144
|
+
}
|
145
|
+
await result.saveCredentials({
|
146
|
+
accountID: "test-account-id",
|
147
|
+
secret: "test-secret",
|
148
|
+
});
|
149
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + btoa("testUser-2"), expect.any(String));
|
150
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser,testUser-2");
|
151
|
+
});
|
152
|
+
it("should retrieve existing users", async () => {
|
153
|
+
const { mockStorage, mockDriver } = setup();
|
154
|
+
mockDriver.onReady = vi.fn(({ signUp }) => {
|
155
|
+
return signUp("testUser");
|
156
|
+
});
|
157
|
+
mockStorage["demo-auth-existing-users"] = "user1,user2,user3";
|
158
|
+
const auth = await RNDemoAuth.init(mockDriver);
|
159
|
+
const result = await auth.start();
|
160
|
+
if (result.type !== "new") {
|
161
|
+
throw new Error("Result is not a new user");
|
162
|
+
}
|
163
|
+
await result.saveCredentials({
|
164
|
+
accountID: "test-account-id",
|
165
|
+
secret: "test-secret",
|
166
|
+
});
|
167
|
+
const onReadyCall = vi.mocked(mockDriver.onReady).mock.calls[0][0];
|
168
|
+
const existingUsers = await onReadyCall.getExistingUsers();
|
169
|
+
expect(existingUsers).toEqual(["user1", "user2", "user3", "testUser"]);
|
170
|
+
});
|
171
|
+
it("should migrate legacy user keys to the new format", async () => {
|
172
|
+
const { mockStorage, mockKvStore, mockDriver } = setup();
|
173
|
+
const value = JSON.stringify({
|
174
|
+
accountID: "test-account-id",
|
175
|
+
accountSecret: "test-secret",
|
176
|
+
});
|
177
|
+
mockStorage["demo-auth-existing-users"] = "testUser";
|
178
|
+
mockStorage["demo-auth-existing-users-testUser"] = value;
|
179
|
+
await RNDemoAuth.init(mockDriver);
|
180
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + btoa("testUser"), value);
|
181
|
+
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-storage-version", "2");
|
182
|
+
expect(mockKvStore.delete).toHaveBeenCalledWith("demo-auth-existing-users-testUser");
|
183
|
+
});
|
184
|
+
});
|
185
|
+
});
|
186
|
+
//# sourceMappingURL=DemoAuthMethod.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"DemoAuthMethod.test.js","sourceRoot":"","sources":["../../src/tests/DemoAuthMethod.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "jazz-react-native",
|
3
|
-
"version": "0.8.
|
3
|
+
"version": "0.8.46",
|
4
4
|
"type": "module",
|
5
5
|
"main": "./dist/index.js",
|
6
6
|
"module": "./dist/index.js",
|
@@ -11,24 +11,29 @@
|
|
11
11
|
"react-native": "./dist/index.js",
|
12
12
|
"types": "./dist/index.d.ts",
|
13
13
|
"default": "./dist/index.js"
|
14
|
+
},
|
15
|
+
"./crypto": {
|
16
|
+
"react-native": "./dist/crypto/index.js",
|
17
|
+
"types": "./dist/crypto/index.d.ts",
|
18
|
+
"default": "./dist/crypto/index.js"
|
14
19
|
}
|
15
20
|
},
|
16
21
|
"license": "MIT",
|
17
22
|
"dependencies": {
|
23
|
+
"@scure/base": "1.2.1",
|
18
24
|
"@scure/bip39": "^1.3.0",
|
19
|
-
"
|
20
|
-
"cojson
|
21
|
-
"
|
25
|
+
"react-native-quick-crypto": "1.0.0-beta.9",
|
26
|
+
"cojson": "0.8.45",
|
27
|
+
"cojson-transport-ws": "0.8.45",
|
28
|
+
"jazz-tools": "0.8.45"
|
22
29
|
},
|
23
30
|
"peerDependencies": {
|
24
31
|
"@react-native-community/netinfo": "*",
|
25
|
-
"expo-linking": "*",
|
26
32
|
"expo-secure-store": "*",
|
27
33
|
"react-native": "*"
|
28
34
|
},
|
29
35
|
"devDependencies": {
|
30
36
|
"@react-native-community/netinfo": "^11.4.1",
|
31
|
-
"expo-linking": "~7.0.3",
|
32
37
|
"expo-secure-store": "~14.0.0",
|
33
38
|
"react-native": "~0.76.3",
|
34
39
|
"typescript": "~5.6.2"
|
@@ -23,6 +23,69 @@ export namespace RNDemoAuth {
|
|
23
23
|
|
24
24
|
const localStorageKey = "demo-auth-logged-in-secret";
|
25
25
|
|
26
|
+
function getUserStorageKey(username: string) {
|
27
|
+
return `demo-auth-existing-users-${btoa(username)}`;
|
28
|
+
}
|
29
|
+
|
30
|
+
function getLegacyUserStorageKey(username: string) {
|
31
|
+
return `demo-auth-existing-users-${username}`;
|
32
|
+
}
|
33
|
+
|
34
|
+
async function getStorageVersion(kvStore: KvStore) {
|
35
|
+
try {
|
36
|
+
const version = await kvStore.get("demo-auth-storage-version");
|
37
|
+
return version ? parseInt(version) : 1;
|
38
|
+
} catch (error) {
|
39
|
+
return 1;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
async function setStorageVersion(kvStore: KvStore, version: number) {
|
44
|
+
await kvStore.set("demo-auth-storage-version", version.toString());
|
45
|
+
}
|
46
|
+
|
47
|
+
async function getExistingUsers(kvStore: KvStore) {
|
48
|
+
const existingUsers = await kvStore.get("demo-auth-existing-users");
|
49
|
+
return existingUsers ? existingUsers.split(",") : [];
|
50
|
+
}
|
51
|
+
|
52
|
+
async function addUserToExistingUsers(username: string, kvStore: KvStore) {
|
53
|
+
const existingUsers = await getExistingUsers(kvStore);
|
54
|
+
|
55
|
+
if (existingUsers.includes(username)) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
|
59
|
+
await kvStore.set(
|
60
|
+
"demo-auth-existing-users",
|
61
|
+
existingUsers.concat(username).join(","),
|
62
|
+
);
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Migrates existing users keys to use a base64 encoded username.
|
67
|
+
*
|
68
|
+
* This is done to avoid issues with special characters in the username.
|
69
|
+
*/
|
70
|
+
async function migrateExistingUsersKeys(kvStore: KvStore) {
|
71
|
+
if ((await getStorageVersion(kvStore)) >= 2) {
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
|
75
|
+
await setStorageVersion(kvStore, 2);
|
76
|
+
|
77
|
+
const existingUsers = await getExistingUsers(kvStore);
|
78
|
+
|
79
|
+
for (const existingUsername of existingUsers) {
|
80
|
+
const legacyKey = getLegacyUserStorageKey(existingUsername);
|
81
|
+
const storageData = await kvStore.get(legacyKey);
|
82
|
+
if (storageData) {
|
83
|
+
await kvStore.set(getUserStorageKey(existingUsername), storageData);
|
84
|
+
await kvStore.delete(legacyKey);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
26
89
|
export class RNDemoAuth implements AuthMethod {
|
27
90
|
private constructor(
|
28
91
|
private driver: RNDemoAuth.Driver,
|
@@ -39,27 +102,16 @@ export class RNDemoAuth implements AuthMethod {
|
|
39
102
|
},
|
40
103
|
) {
|
41
104
|
const kvStore = KvStoreContext.getInstance().getStorage();
|
105
|
+
|
106
|
+
await migrateExistingUsersKeys(kvStore);
|
107
|
+
|
42
108
|
for (const [name, credentials] of Object.entries(seedAccounts || {})) {
|
43
109
|
const storageData = JSON.stringify(credentials satisfies StorageData);
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
| string[]
|
48
|
-
| undefined
|
49
|
-
)?.includes(name)
|
50
|
-
) {
|
51
|
-
const existingUsers = await kvStore.get("demo-auth-existing-users");
|
52
|
-
if (existingUsers) {
|
53
|
-
await kvStore.set(
|
54
|
-
"demo-auth-existing-users",
|
55
|
-
existingUsers + "," + name,
|
56
|
-
);
|
57
|
-
} else {
|
58
|
-
await kvStore.set("demo-auth-existing-users", name);
|
59
|
-
}
|
60
|
-
}
|
61
|
-
await kvStore.set("demo-auth-existing-users-" + name, storageData);
|
110
|
+
|
111
|
+
await addUserToExistingUsers(name, kvStore);
|
112
|
+
await kvStore.set(getUserStorageKey(name), storageData);
|
62
113
|
}
|
114
|
+
|
63
115
|
return new RNDemoAuth(driver, kvStore);
|
64
116
|
}
|
65
117
|
|
@@ -103,13 +155,9 @@ export class RNDemoAuth implements AuthMethod {
|
|
103
155
|
accountSecret: credentials.secret,
|
104
156
|
} satisfies StorageData);
|
105
157
|
|
106
|
-
|
107
|
-
|
108
|
-
"demo-auth-existing-users",
|
158
|
+
const existingUsernames = await getExistingUsers(
|
159
|
+
this.kvStore,
|
109
160
|
);
|
110
|
-
const existingUsernames = existingUsers
|
111
|
-
? existingUsers.split(",")
|
112
|
-
: [];
|
113
161
|
|
114
162
|
// Determine if the username already exists and generate a unique username
|
115
163
|
let uniqueUsername = username;
|
@@ -122,18 +170,11 @@ export class RNDemoAuth implements AuthMethod {
|
|
122
170
|
// Save credentials using the unique username
|
123
171
|
await this.kvStore.set(localStorageKey, storageData);
|
124
172
|
await this.kvStore.set(
|
125
|
-
|
173
|
+
getUserStorageKey(uniqueUsername),
|
126
174
|
storageData,
|
127
175
|
);
|
128
176
|
|
129
|
-
|
130
|
-
const updatedUsers = existingUsers
|
131
|
-
? `${existingUsers},${uniqueUsername}`
|
132
|
-
: uniqueUsername;
|
133
|
-
await this.kvStore.set(
|
134
|
-
"demo-auth-existing-users",
|
135
|
-
updatedUsers,
|
136
|
-
);
|
177
|
+
await addUserToExistingUsers(uniqueUsername, this.kvStore);
|
137
178
|
},
|
138
179
|
onSuccess: () => {
|
139
180
|
this.driver.onSignedIn({ logOut });
|
@@ -149,17 +190,12 @@ export class RNDemoAuth implements AuthMethod {
|
|
149
190
|
});
|
150
191
|
},
|
151
192
|
getExistingUsers: async () => {
|
152
|
-
return (
|
153
|
-
(await this.kvStore.get("demo-auth-existing-users"))?.split(
|
154
|
-
",",
|
155
|
-
) ?? []
|
156
|
-
);
|
193
|
+
return await getExistingUsers(this.kvStore);
|
157
194
|
},
|
158
195
|
logInAs: async (existingUser) => {
|
159
196
|
const storageData = JSON.parse(
|
160
|
-
(await this.kvStore.get(
|
161
|
-
"
|
162
|
-
)) ?? "{}",
|
197
|
+
(await this.kvStore.get(getUserStorageKey(existingUser))) ??
|
198
|
+
"{}",
|
163
199
|
) as StorageData;
|
164
200
|
|
165
201
|
await this.kvStore.set(
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import { base58 } from "@scure/base";
|
2
|
+
import { JsonValue, PureJSCrypto } from "cojson/native";
|
3
|
+
import { CojsonInternalTypes, cojsonInternals } from "cojson/native";
|
4
|
+
import { Ed } from "react-native-quick-crypto";
|
5
|
+
const { stableStringify } = cojsonInternals;
|
6
|
+
|
7
|
+
const textEncoder = new TextEncoder();
|
8
|
+
|
9
|
+
export class RNQuickCrypto extends PureJSCrypto {
|
10
|
+
ed: Ed;
|
11
|
+
|
12
|
+
constructor() {
|
13
|
+
super();
|
14
|
+
this.ed = new Ed("ed25519", {});
|
15
|
+
}
|
16
|
+
|
17
|
+
static async create(): Promise<RNQuickCrypto> {
|
18
|
+
return new RNQuickCrypto();
|
19
|
+
}
|
20
|
+
|
21
|
+
newEd25519SigningKey(): Uint8Array {
|
22
|
+
this.ed.generateKeyPairSync();
|
23
|
+
return new Uint8Array(this.ed.getPrivateKey());
|
24
|
+
}
|
25
|
+
|
26
|
+
getSignerID(
|
27
|
+
secret: CojsonInternalTypes.SignerSecret,
|
28
|
+
): CojsonInternalTypes.SignerID {
|
29
|
+
return `signer_z${base58.encode(
|
30
|
+
base58.decode(secret.substring("signerSecret_z".length)),
|
31
|
+
)}`;
|
32
|
+
}
|
33
|
+
|
34
|
+
sign(
|
35
|
+
secret: CojsonInternalTypes.SignerSecret,
|
36
|
+
message: JsonValue,
|
37
|
+
): CojsonInternalTypes.Signature {
|
38
|
+
const signature = new Uint8Array(
|
39
|
+
this.ed.signSync(
|
40
|
+
textEncoder.encode(stableStringify(message)),
|
41
|
+
base58.decode(secret.substring("signerSecret_z".length)),
|
42
|
+
),
|
43
|
+
);
|
44
|
+
return `signature_z${base58.encode(signature)}`;
|
45
|
+
}
|
46
|
+
|
47
|
+
verify(
|
48
|
+
signature: CojsonInternalTypes.Signature,
|
49
|
+
message: JsonValue,
|
50
|
+
id: CojsonInternalTypes.SignerID,
|
51
|
+
): boolean {
|
52
|
+
return this.ed.verifySync(
|
53
|
+
base58.decode(signature.substring("signature_z".length)),
|
54
|
+
textEncoder.encode(stableStringify(message)),
|
55
|
+
base58.decode(id.substring("signer_z".length)),
|
56
|
+
);
|
57
|
+
}
|
58
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export { RNQuickCrypto } from "./RNQuickCrypto.js";
|
package/src/index.ts
CHANGED
@@ -15,15 +15,13 @@ import {
|
|
15
15
|
createJazzContext,
|
16
16
|
} from "jazz-tools";
|
17
17
|
|
18
|
-
import NetInfo from "@react-native-community/netinfo";
|
19
18
|
import { RawAccountID } from "cojson";
|
20
|
-
import { createWebSocketPeer } from "cojson-transport-ws";
|
21
|
-
import * as Linking from "expo-linking";
|
22
|
-
import { PureJSCrypto } from "jazz-tools/native";
|
23
19
|
|
24
20
|
export { RNDemoAuth } from "./auth/DemoAuthMethod.js";
|
25
21
|
|
22
|
+
import { PureJSCrypto } from "cojson/native";
|
26
23
|
import { createWebSocketPeerWithReconnection } from "./createWebSocketPeerWithReconnection.js";
|
24
|
+
import type { RNQuickCrypto } from "./crypto/RNQuickCrypto.js";
|
27
25
|
import { KvStoreContext } from "./storage/kv-store-context.js";
|
28
26
|
|
29
27
|
/** @category Context Creation */
|
@@ -51,7 +49,7 @@ export type BaseReactNativeContextOptions = {
|
|
51
49
|
peer: `wss://${string}` | `ws://${string}`;
|
52
50
|
reconnectionTimeout?: number;
|
53
51
|
storage?: "indexedDB" | "singleTabOPFS";
|
54
|
-
|
52
|
+
CryptoProvider?: typeof PureJSCrypto | typeof RNQuickCrypto;
|
55
53
|
};
|
56
54
|
|
57
55
|
/** @category Context Creation */
|
@@ -75,17 +73,19 @@ export async function createJazzRNContext<Acc extends Account>(
|
|
75
73
|
},
|
76
74
|
);
|
77
75
|
|
76
|
+
const CryptoProvider = options.CryptoProvider || PureJSCrypto;
|
77
|
+
|
78
78
|
const context =
|
79
79
|
"auth" in options
|
80
80
|
? await createJazzContext({
|
81
81
|
AccountSchema: options.AccountSchema,
|
82
82
|
auth: options.auth,
|
83
|
-
crypto: await
|
83
|
+
crypto: await CryptoProvider.create(),
|
84
84
|
peersToLoadFrom: [websocketPeer.peer],
|
85
85
|
sessionProvider: provideLockSession,
|
86
86
|
})
|
87
87
|
: await createJazzContext({
|
88
|
-
crypto: await
|
88
|
+
crypto: await CryptoProvider.create(),
|
89
89
|
peersToLoadFrom: [websocketPeer.peer],
|
90
90
|
});
|
91
91
|
|
@@ -165,6 +165,7 @@ export function createInviteLink<C extends CoValue>(
|
|
165
165
|
}
|
166
166
|
|
167
167
|
/** @category Invite Links */
|
168
|
+
// TODO: copied from jazz-browser, should be shared
|
168
169
|
export function parseInviteLink<C extends CoValue>(
|
169
170
|
inviteURL: string,
|
170
171
|
):
|
@@ -174,33 +175,67 @@ export function parseInviteLink<C extends CoValue>(
|
|
174
175
|
inviteSecret: InviteSecret;
|
175
176
|
}
|
176
177
|
| undefined {
|
177
|
-
const url =
|
178
|
-
const parts = url.
|
179
|
-
|
180
|
-
if (!parts || parts[0] !== "invite") {
|
181
|
-
return undefined;
|
182
|
-
}
|
178
|
+
const url = new URL(inviteURL);
|
179
|
+
const parts = url.hash.split("/");
|
183
180
|
|
184
181
|
let valueHint: string | undefined;
|
185
182
|
let valueID: ID<C> | undefined;
|
186
183
|
let inviteSecret: InviteSecret | undefined;
|
187
184
|
|
188
|
-
if (parts
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
185
|
+
if (parts[0] === "#" && parts[1] === "invite") {
|
186
|
+
if (parts.length === 5) {
|
187
|
+
valueHint = parts[2];
|
188
|
+
valueID = parts[3] as ID<C>;
|
189
|
+
inviteSecret = parts[4] as InviteSecret;
|
190
|
+
} else if (parts.length === 4) {
|
191
|
+
valueID = parts[2] as ID<C>;
|
192
|
+
inviteSecret = parts[3] as InviteSecret;
|
193
|
+
}
|
196
194
|
|
197
|
-
|
198
|
-
|
195
|
+
if (!valueID || !inviteSecret) {
|
196
|
+
return undefined;
|
197
|
+
}
|
198
|
+
return { valueID, inviteSecret, valueHint };
|
199
199
|
}
|
200
|
-
|
201
|
-
return { valueID, inviteSecret, valueHint };
|
202
200
|
}
|
203
201
|
|
202
|
+
// getting out of the `expo` business 🤞
|
203
|
+
// export function parseInviteLink<C extends CoValue>(
|
204
|
+
// inviteURL: string,
|
205
|
+
// ):
|
206
|
+
// | {
|
207
|
+
// valueID: ID<C>;
|
208
|
+
// valueHint?: string;
|
209
|
+
// inviteSecret: InviteSecret;
|
210
|
+
// }
|
211
|
+
// | undefined {
|
212
|
+
// const url = Linking.parse(inviteURL);
|
213
|
+
// const parts = url.path?.split("/");
|
214
|
+
|
215
|
+
// if (!parts || parts[0] !== "invite") {
|
216
|
+
// return undefined;
|
217
|
+
// }
|
218
|
+
|
219
|
+
// let valueHint: string | undefined;
|
220
|
+
// let valueID: ID<C> | undefined;
|
221
|
+
// let inviteSecret: InviteSecret | undefined;
|
222
|
+
|
223
|
+
// if (parts.length === 4) {
|
224
|
+
// valueHint = parts[1];
|
225
|
+
// valueID = parts[2] as ID<C>;
|
226
|
+
// inviteSecret = parts[3] as InviteSecret;
|
227
|
+
// } else if (parts.length === 3) {
|
228
|
+
// valueID = parts[1] as ID<C>;
|
229
|
+
// inviteSecret = parts[2] as InviteSecret;
|
230
|
+
// }
|
231
|
+
|
232
|
+
// if (!valueID || !inviteSecret) {
|
233
|
+
// return undefined;
|
234
|
+
// }
|
235
|
+
|
236
|
+
// return { valueID, inviteSecret, valueHint };
|
237
|
+
// }
|
238
|
+
|
204
239
|
/////////
|
205
240
|
|
206
241
|
export * from "./provider.js";
|
package/src/provider.tsx
CHANGED
@@ -14,6 +14,7 @@ import {
|
|
14
14
|
} from "jazz-tools";
|
15
15
|
import { Linking } from "react-native";
|
16
16
|
import {
|
17
|
+
BaseReactNativeContextOptions,
|
17
18
|
KvStore,
|
18
19
|
KvStoreContext,
|
19
20
|
ReactNativeContext,
|
@@ -27,6 +28,11 @@ import { ExpoSecureStoreAdapter } from "./storage/expo-secure-store-adapter.js";
|
|
27
28
|
export function createJazzRNApp<Acc extends Account>({
|
28
29
|
kvStore = new ExpoSecureStoreAdapter(),
|
29
30
|
AccountSchema = Account as unknown as AccountClass<Acc>,
|
31
|
+
CryptoProvider,
|
32
|
+
}: {
|
33
|
+
kvStore?: KvStore;
|
34
|
+
AccountSchema?: AccountClass<Acc>;
|
35
|
+
CryptoProvider?: BaseReactNativeContextOptions["CryptoProvider"];
|
30
36
|
} = {}): JazzReactApp<Acc> {
|
31
37
|
const JazzContext = React.createContext<
|
32
38
|
ReactNativeContext<Acc> | ReactNativeGuestContext | undefined
|
@@ -61,12 +67,14 @@ export function createJazzRNApp<Acc extends Account>({
|
|
61
67
|
? {
|
62
68
|
peer,
|
63
69
|
storage,
|
70
|
+
CryptoProvider,
|
64
71
|
}
|
65
72
|
: {
|
66
73
|
AccountSchema,
|
67
74
|
auth: auth,
|
68
75
|
peer,
|
69
76
|
storage,
|
77
|
+
CryptoProvider,
|
70
78
|
},
|
71
79
|
).then((context) => {
|
72
80
|
setCtx({
|