jazz-react-native 0.9.23 → 0.10.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +22 -0
- package/dist/ReactNativeContextManager.js +38 -0
- package/dist/ReactNativeContextManager.js.map +1 -0
- package/dist/auth/DemoAuthUI.js +45 -101
- package/dist/auth/DemoAuthUI.js.map +1 -1
- package/dist/auth/auth.js +1 -0
- package/dist/auth/auth.js.map +1 -1
- package/dist/hooks.js +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/platform.js +120 -40
- package/dist/platform.js.map +1 -1
- package/dist/provider.js +39 -64
- package/dist/provider.js.map +1 -1
- package/package.json +6 -6
- package/src/ReactNativeContextManager.ts +70 -0
- package/src/auth/DemoAuthUI.tsx +71 -165
- package/src/auth/auth.ts +1 -0
- package/src/hooks.tsx +9 -1
- package/src/platform.ts +161 -86
- package/src/provider.tsx +66 -89
- package/dist/auth/DemoAuthMethod.js +0 -182
- package/dist/auth/DemoAuthMethod.js.map +0 -1
- package/dist/createWebSocketPeerWithReconnection.js +0 -58
- package/dist/createWebSocketPeerWithReconnection.js.map +0 -1
- package/dist/tests/DemoAuthMethod.test.js +0 -207
- package/dist/tests/DemoAuthMethod.test.js.map +0 -1
- package/dist/tests/createWebSocketPeerWithReconnection.test.js +0 -106
- package/dist/tests/createWebSocketPeerWithReconnection.test.js.map +0 -1
- package/src/auth/DemoAuthMethod.ts +0 -259
- package/src/createWebSocketPeerWithReconnection.ts +0 -79
- package/src/tests/DemoAuthMethod.test.ts +0 -309
- package/src/tests/createWebSocketPeerWithReconnection.test.ts +0 -163
@@ -1,58 +0,0 @@
|
|
1
|
-
import NetInfo from "@react-native-community/netinfo";
|
2
|
-
import { createWebSocketPeer } from "cojson-transport-ws";
|
3
|
-
export function createWebSocketPeerWithReconnection(peer, reconnectionTimeout, addPeer) {
|
4
|
-
const firstWsPeer = createWebSocketPeer({
|
5
|
-
websocket: new WebSocket(peer),
|
6
|
-
id: peer,
|
7
|
-
role: "server",
|
8
|
-
onClose: reconnectWebSocket,
|
9
|
-
});
|
10
|
-
const initialReconnectionTimeout = reconnectionTimeout || 500;
|
11
|
-
let shouldTryToReconnect = true;
|
12
|
-
let currentReconnectionTimeout = initialReconnectionTimeout;
|
13
|
-
const unsubscribeNetworkChange = NetInfo.addEventListener((state) => {
|
14
|
-
if (state.isConnected) {
|
15
|
-
currentReconnectionTimeout = initialReconnectionTimeout;
|
16
|
-
}
|
17
|
-
});
|
18
|
-
async function reconnectWebSocket() {
|
19
|
-
if (!shouldTryToReconnect)
|
20
|
-
return;
|
21
|
-
console.log("Websocket disconnected, trying to reconnect in " +
|
22
|
-
currentReconnectionTimeout +
|
23
|
-
"ms");
|
24
|
-
currentReconnectionTimeout = Math.min(currentReconnectionTimeout * 2, 30000);
|
25
|
-
await waitForOnline(currentReconnectionTimeout);
|
26
|
-
if (!shouldTryToReconnect)
|
27
|
-
return;
|
28
|
-
addPeer(createWebSocketPeer({
|
29
|
-
websocket: new WebSocket(peer),
|
30
|
-
id: peer,
|
31
|
-
role: "server",
|
32
|
-
onClose: reconnectWebSocket,
|
33
|
-
}));
|
34
|
-
}
|
35
|
-
return {
|
36
|
-
peer: firstWsPeer,
|
37
|
-
done: () => {
|
38
|
-
shouldTryToReconnect = false;
|
39
|
-
unsubscribeNetworkChange();
|
40
|
-
},
|
41
|
-
};
|
42
|
-
}
|
43
|
-
function waitForOnline(timeout) {
|
44
|
-
return new Promise((resolve) => {
|
45
|
-
const unsubscribeNetworkChange = NetInfo.addEventListener((state) => {
|
46
|
-
if (state.isConnected) {
|
47
|
-
handleTimeoutOrOnline();
|
48
|
-
}
|
49
|
-
});
|
50
|
-
function handleTimeoutOrOnline() {
|
51
|
-
clearTimeout(timer);
|
52
|
-
unsubscribeNetworkChange();
|
53
|
-
resolve();
|
54
|
-
}
|
55
|
-
const timer = setTimeout(handleTimeoutOrOnline, timeout);
|
56
|
-
});
|
57
|
-
}
|
58
|
-
//# sourceMappingURL=createWebSocketPeerWithReconnection.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"createWebSocketPeerWithReconnection.js","sourceRoot":"","sources":["../src/createWebSocketPeerWithReconnection.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,iCAAiC,CAAC;AAEtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,UAAU,mCAAmC,CACjD,IAAY,EACZ,mBAAuC,EACvC,OAA6B;IAE7B,MAAM,WAAW,GAAG,mBAAmB,CAAC;QACtC,SAAS,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC;QAC9B,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAC;IAEH,MAAM,0BAA0B,GAAG,mBAAmB,IAAI,GAAG,CAAC;IAC9D,IAAI,oBAAoB,GAAG,IAAI,CAAC;IAChC,IAAI,0BAA0B,GAAG,0BAA0B,CAAC;IAE5D,MAAM,wBAAwB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,EAAE;QAClE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,0BAA0B,GAAG,0BAA0B,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,kBAAkB;QAC/B,IAAI,CAAC,oBAAoB;YAAE,OAAO;QAElC,OAAO,CAAC,GAAG,CACT,iDAAiD;YAC/C,0BAA0B;YAC1B,IAAI,CACP,CAAC;QACF,0BAA0B,GAAG,IAAI,CAAC,GAAG,CACnC,0BAA0B,GAAG,CAAC,EAC9B,KAAK,CACN,CAAC;QAEF,MAAM,aAAa,CAAC,0BAA0B,CAAC,CAAC;QAEhD,IAAI,CAAC,oBAAoB;YAAE,OAAO;QAElC,OAAO,CACL,mBAAmB,CAAC;YAClB,SAAS,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC;YAC9B,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,kBAAkB;SAC5B,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,GAAG,EAAE;YACT,oBAAoB,GAAG,KAAK,CAAC;YAC7B,wBAAwB,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,MAAM,wBAAwB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,EAAE;YAClE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gBACtB,qBAAqB,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,SAAS,qBAAqB;YAC5B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,wBAAwB,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
@@ -1,207 +0,0 @@
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
2
|
-
import { RNDemoAuth, encodeUsername } from "../auth/DemoAuthMethod";
|
3
|
-
import { KvStoreContext } from "../storage/kv-store-context";
|
4
|
-
// Initialize mock storage
|
5
|
-
const mockStorage = {};
|
6
|
-
function validateKey(key) {
|
7
|
-
if (key.includes("+") || key.includes("/") || key.includes("=")) {
|
8
|
-
throw new Error("Invalid key");
|
9
|
-
}
|
10
|
-
}
|
11
|
-
// Mock KvStore implementation
|
12
|
-
const mockKvStore = {
|
13
|
-
get: vi.fn(async (key) => {
|
14
|
-
validateKey(key);
|
15
|
-
return mockStorage[key] || null;
|
16
|
-
}),
|
17
|
-
set: vi.fn(async (key, value) => {
|
18
|
-
validateKey(key);
|
19
|
-
mockStorage[key] = value;
|
20
|
-
}),
|
21
|
-
delete: vi.fn(async (key) => {
|
22
|
-
validateKey(key);
|
23
|
-
delete mockStorage[key];
|
24
|
-
}),
|
25
|
-
clearAll: vi.fn(async () => {
|
26
|
-
Object.keys(mockStorage).forEach((key) => delete mockStorage[key]);
|
27
|
-
}),
|
28
|
-
};
|
29
|
-
KvStoreContext.getInstance().initialize(mockKvStore);
|
30
|
-
beforeEach(() => {
|
31
|
-
mockKvStore.clearAll();
|
32
|
-
vi.clearAllMocks();
|
33
|
-
});
|
34
|
-
function setup() {
|
35
|
-
const mockDriver = {
|
36
|
-
onReady: vi.fn(),
|
37
|
-
onSignedIn: vi.fn(),
|
38
|
-
onError: vi.fn(),
|
39
|
-
};
|
40
|
-
return {
|
41
|
-
mockStorage,
|
42
|
-
mockKvStore,
|
43
|
-
mockDriver,
|
44
|
-
};
|
45
|
-
}
|
46
|
-
describe("RNDemoAuth", () => {
|
47
|
-
describe("initialization", () => {
|
48
|
-
it("should initialize with seed accounts", async () => {
|
49
|
-
const { mockKvStore, mockDriver } = setup();
|
50
|
-
const seedAccounts = {
|
51
|
-
testUser: {
|
52
|
-
accountID: "test-account-id",
|
53
|
-
accountSecret: "test-secret",
|
54
|
-
},
|
55
|
-
};
|
56
|
-
await RNDemoAuth.init(mockDriver, seedAccounts);
|
57
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser");
|
58
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + encodeUsername("testUser"), expect.any(String));
|
59
|
-
});
|
60
|
-
});
|
61
|
-
describe("authentication", () => {
|
62
|
-
it("should handle new user signup", async () => {
|
63
|
-
const { mockDriver } = setup();
|
64
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
65
|
-
signUp("testUser");
|
66
|
-
});
|
67
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
68
|
-
const result = await auth.start();
|
69
|
-
expect(mockDriver.onReady).toHaveBeenCalled();
|
70
|
-
expect(result.type).toBe("new");
|
71
|
-
expect(result.saveCredentials).toBeDefined();
|
72
|
-
});
|
73
|
-
it("should convert unsupported chars from base64 to a valid key", async () => {
|
74
|
-
const { mockDriver } = setup();
|
75
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
76
|
-
signUp(atob("+/=="));
|
77
|
-
});
|
78
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
79
|
-
const result = await auth.start();
|
80
|
-
expect(mockDriver.onReady).toHaveBeenCalled();
|
81
|
-
expect(result.type).toBe("new");
|
82
|
-
expect(result.saveCredentials).toBeDefined();
|
83
|
-
});
|
84
|
-
it("should handle existing user login", async () => {
|
85
|
-
const { mockStorage, mockDriver } = setup();
|
86
|
-
// Set up existing user in storage
|
87
|
-
const existingUser = {
|
88
|
-
accountID: "test-account-id",
|
89
|
-
accountSecret: "test-secret",
|
90
|
-
};
|
91
|
-
mockStorage["demo-auth-logged-in-secret"] = JSON.stringify(existingUser);
|
92
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
93
|
-
const result = await auth.start();
|
94
|
-
if (result.type !== "existing") {
|
95
|
-
throw new Error("Result is not a existing user");
|
96
|
-
}
|
97
|
-
expect(result.type).toBe("existing");
|
98
|
-
expect(result.credentials).toEqual({
|
99
|
-
accountID: existingUser.accountID,
|
100
|
-
secret: existingUser.accountSecret,
|
101
|
-
});
|
102
|
-
});
|
103
|
-
it("should handle logout", async () => {
|
104
|
-
const { mockKvStore, mockDriver } = setup();
|
105
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
106
|
-
signUp("testUser");
|
107
|
-
});
|
108
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
109
|
-
const result = await auth.start();
|
110
|
-
await result.logOut();
|
111
|
-
expect(mockKvStore.delete).toHaveBeenCalledWith("demo-auth-logged-in-secret");
|
112
|
-
});
|
113
|
-
});
|
114
|
-
describe("user management", () => {
|
115
|
-
it("should signup a new user", async () => {
|
116
|
-
const { mockKvStore, mockDriver } = setup();
|
117
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
118
|
-
return signUp("testUser");
|
119
|
-
});
|
120
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
121
|
-
const result = await auth.start();
|
122
|
-
if (result.type !== "new") {
|
123
|
-
throw new Error("Result is not a new user");
|
124
|
-
}
|
125
|
-
await result.saveCredentials({
|
126
|
-
accountID: "test-account-id",
|
127
|
-
secret: "test-secret",
|
128
|
-
});
|
129
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + encodeUsername("testUser"), expect.any(String));
|
130
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser");
|
131
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-logged-in-secret", expect.any(String));
|
132
|
-
});
|
133
|
-
it("should login an existing user", async () => {
|
134
|
-
const { mockStorage, mockKvStore, mockDriver } = setup();
|
135
|
-
const credentials = {
|
136
|
-
accountID: "test-account-id",
|
137
|
-
accountSecret: "test-secret",
|
138
|
-
};
|
139
|
-
mockStorage["demo-auth-existing-users-" + encodeUsername("testUser")] =
|
140
|
-
JSON.stringify(credentials);
|
141
|
-
mockDriver.onReady = vi.fn(({ logInAs }) => {
|
142
|
-
return logInAs("testUser");
|
143
|
-
});
|
144
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
145
|
-
const result = await auth.start();
|
146
|
-
if (result.type !== "existing") {
|
147
|
-
throw new Error("Result is not a existing user");
|
148
|
-
}
|
149
|
-
expect(result.credentials).toEqual({
|
150
|
-
accountID: credentials.accountID,
|
151
|
-
secret: credentials.accountSecret,
|
152
|
-
});
|
153
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-logged-in-secret", JSON.stringify(credentials));
|
154
|
-
});
|
155
|
-
it("should handle duplicate usernames by adding suffix", async () => {
|
156
|
-
const { mockStorage, mockKvStore, mockDriver } = setup();
|
157
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
158
|
-
return signUp("testUser");
|
159
|
-
});
|
160
|
-
mockStorage["demo-auth-existing-users"] = "testUser";
|
161
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
162
|
-
const result = await auth.start();
|
163
|
-
if (result.type !== "new") {
|
164
|
-
throw new Error("Result is not a new user");
|
165
|
-
}
|
166
|
-
await result.saveCredentials({
|
167
|
-
accountID: "test-account-id",
|
168
|
-
secret: "test-secret",
|
169
|
-
});
|
170
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + encodeUsername("testUser-2"), expect.any(String));
|
171
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users", "testUser,testUser-2");
|
172
|
-
});
|
173
|
-
it("should retrieve existing users", async () => {
|
174
|
-
const { mockStorage, mockDriver } = setup();
|
175
|
-
mockDriver.onReady = vi.fn(({ signUp }) => {
|
176
|
-
return signUp("testUser");
|
177
|
-
});
|
178
|
-
mockStorage["demo-auth-existing-users"] = "user1,user2,user3";
|
179
|
-
const auth = await RNDemoAuth.init(mockDriver);
|
180
|
-
const result = await auth.start();
|
181
|
-
if (result.type !== "new") {
|
182
|
-
throw new Error("Result is not a new user");
|
183
|
-
}
|
184
|
-
await result.saveCredentials({
|
185
|
-
accountID: "test-account-id",
|
186
|
-
secret: "test-secret",
|
187
|
-
});
|
188
|
-
const onReadyCall = vi.mocked(mockDriver.onReady).mock.calls[0][0];
|
189
|
-
const existingUsers = await onReadyCall.getExistingUsers();
|
190
|
-
expect(existingUsers).toEqual(["user1", "user2", "user3", "testUser"]);
|
191
|
-
});
|
192
|
-
it("should migrate legacy user keys to the new format", async () => {
|
193
|
-
const { mockStorage, mockKvStore, mockDriver } = setup();
|
194
|
-
const value = JSON.stringify({
|
195
|
-
accountID: "test-account-id",
|
196
|
-
accountSecret: "test-secret",
|
197
|
-
});
|
198
|
-
mockStorage["demo-auth-existing-users"] = "testUser";
|
199
|
-
mockStorage["demo-auth-existing-users-testUser"] = value;
|
200
|
-
await RNDemoAuth.init(mockDriver);
|
201
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-existing-users-" + encodeUsername("testUser"), value);
|
202
|
-
expect(mockKvStore.set).toHaveBeenCalledWith("demo-auth-storage-version", "2");
|
203
|
-
expect(mockKvStore.delete).toHaveBeenCalledWith("demo-auth-existing-users-testUser");
|
204
|
-
});
|
205
|
-
});
|
206
|
-
});
|
207
|
-
//# sourceMappingURL=DemoAuthMethod.test.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"DemoAuthMethod.test.js","sourceRoot":"","sources":["../../src/tests/DemoAuthMethod.test.ts"],"names":[],"mappings":"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"}
|
@@ -1,106 +0,0 @@
|
|
1
|
-
// @vitest-environment happy-dom
|
2
|
-
import NetInfo from "@react-native-community/netinfo";
|
3
|
-
import { createWebSocketPeer } from "cojson-transport-ws";
|
4
|
-
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
5
|
-
import { createWebSocketPeerWithReconnection } from "../createWebSocketPeerWithReconnection.js";
|
6
|
-
// Mock WebSocket
|
7
|
-
class MockWebSocket {
|
8
|
-
addEventListener = vi.fn();
|
9
|
-
removeEventListener = vi.fn();
|
10
|
-
close = vi.fn();
|
11
|
-
readyState = 1;
|
12
|
-
}
|
13
|
-
vi.mock("@react-native-community/netinfo", async () => {
|
14
|
-
return {
|
15
|
-
default: {
|
16
|
-
addEventListener: vi.fn(),
|
17
|
-
},
|
18
|
-
};
|
19
|
-
});
|
20
|
-
vi.mock("cojson-transport-ws", () => ({
|
21
|
-
createWebSocketPeer: vi.fn().mockImplementation(({ onClose }) => ({
|
22
|
-
id: "test-peer",
|
23
|
-
incoming: { push: vi.fn() },
|
24
|
-
outgoing: { push: vi.fn(), close: vi.fn() },
|
25
|
-
onClose,
|
26
|
-
})),
|
27
|
-
}));
|
28
|
-
let listeners = new Set();
|
29
|
-
let unsubscribe = undefined;
|
30
|
-
function mockNetInfo() {
|
31
|
-
listeners.clear();
|
32
|
-
vi.mocked(NetInfo.addEventListener).mockImplementation((listener) => {
|
33
|
-
listeners.add(listener);
|
34
|
-
unsubscribe = vi.fn();
|
35
|
-
return unsubscribe;
|
36
|
-
});
|
37
|
-
}
|
38
|
-
function dispatchNetInfoChange(isConnected) {
|
39
|
-
listeners.forEach((listener) => listener({ isConnected }));
|
40
|
-
}
|
41
|
-
describe("createWebSocketPeerWithReconnection", () => {
|
42
|
-
beforeEach(() => {
|
43
|
-
vi.clearAllMocks();
|
44
|
-
vi.stubGlobal("WebSocket", MockWebSocket);
|
45
|
-
mockNetInfo();
|
46
|
-
});
|
47
|
-
afterEach(() => {
|
48
|
-
vi.useRealTimers();
|
49
|
-
});
|
50
|
-
test("should reset reconnection timeout when coming online", async () => {
|
51
|
-
vi.useFakeTimers();
|
52
|
-
const addPeerMock = vi.fn();
|
53
|
-
const { done } = createWebSocketPeerWithReconnection("ws://localhost:8080", 500, addPeerMock);
|
54
|
-
// Simulate multiple disconnections to increase timeout
|
55
|
-
const initialPeer = vi.mocked(createWebSocketPeer).mock.results[0].value;
|
56
|
-
initialPeer.onClose();
|
57
|
-
await vi.advanceTimersByTimeAsync(1000);
|
58
|
-
expect(addPeerMock).toHaveBeenCalledTimes(1);
|
59
|
-
vi.mocked(createWebSocketPeer).mock.results[1].value.onClose();
|
60
|
-
await vi.advanceTimersByTimeAsync(2000);
|
61
|
-
expect(addPeerMock).toHaveBeenCalledTimes(2);
|
62
|
-
// Resets the timeout to initial value
|
63
|
-
dispatchNetInfoChange(true);
|
64
|
-
// Next reconnection should use initial timeout
|
65
|
-
vi.mocked(createWebSocketPeer).mock.results[2].value.onClose();
|
66
|
-
await vi.advanceTimersByTimeAsync(1000);
|
67
|
-
expect(addPeerMock).toHaveBeenCalledTimes(3);
|
68
|
-
done();
|
69
|
-
});
|
70
|
-
test("should wait for online event or timeout before reconnecting", async () => {
|
71
|
-
vi.useFakeTimers();
|
72
|
-
const addPeerMock = vi.fn();
|
73
|
-
const { done } = createWebSocketPeerWithReconnection("ws://localhost:8080", 500, addPeerMock);
|
74
|
-
const initialPeer = vi.mocked(createWebSocketPeer).mock.results[0].value;
|
75
|
-
// Simulate offline state
|
76
|
-
vi.stubGlobal("navigator", { onLine: false });
|
77
|
-
initialPeer.onClose();
|
78
|
-
// Advance timer but not enough to trigger reconnection
|
79
|
-
await vi.advanceTimersByTimeAsync(500);
|
80
|
-
expect(createWebSocketPeer).toHaveBeenCalledTimes(1);
|
81
|
-
// Simulate coming back online
|
82
|
-
dispatchNetInfoChange(true);
|
83
|
-
// Wait for event loop to settle
|
84
|
-
await Promise.resolve().then();
|
85
|
-
// Should reconnect immediately after coming online
|
86
|
-
expect(createWebSocketPeer).toHaveBeenCalledTimes(2);
|
87
|
-
done();
|
88
|
-
});
|
89
|
-
test("should clean up event listeners when done", () => {
|
90
|
-
const addPeerMock = vi.fn();
|
91
|
-
const { done } = createWebSocketPeerWithReconnection("ws://localhost:8080", 1000, addPeerMock);
|
92
|
-
done();
|
93
|
-
expect(unsubscribe).toHaveBeenCalled();
|
94
|
-
});
|
95
|
-
test("should not attempt reconnection after done is called", async () => {
|
96
|
-
vi.useFakeTimers();
|
97
|
-
const addPeerMock = vi.fn();
|
98
|
-
const { done } = createWebSocketPeerWithReconnection("ws://localhost:8080", 500, addPeerMock);
|
99
|
-
const initialPeer = vi.mocked(createWebSocketPeer).mock.results[0].value;
|
100
|
-
done();
|
101
|
-
initialPeer.onClose();
|
102
|
-
await vi.advanceTimersByTimeAsync(1000);
|
103
|
-
expect(createWebSocketPeer).toHaveBeenCalledTimes(1);
|
104
|
-
});
|
105
|
-
});
|
106
|
-
//# sourceMappingURL=createWebSocketPeerWithReconnection.test.js.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"createWebSocketPeerWithReconnection.test.js","sourceRoot":"","sources":["../../src/tests/createWebSocketPeerWithReconnection.test.ts"],"names":[],"mappings":"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"}
|
@@ -1,259 +0,0 @@
|
|
1
|
-
import { AgentSecret } from "cojson";
|
2
|
-
import { Account, AuthMethod, AuthResult, ID } from "jazz-tools";
|
3
|
-
import { KvStore, KvStoreContext } from "../storage/kv-store-context.js";
|
4
|
-
|
5
|
-
type StorageData = {
|
6
|
-
accountID: ID<Account>;
|
7
|
-
accountSecret: AgentSecret;
|
8
|
-
};
|
9
|
-
|
10
|
-
/** @category Auth Providers */
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-namespace
|
12
|
-
export namespace RNDemoAuth {
|
13
|
-
export interface Driver {
|
14
|
-
onReady: (next: {
|
15
|
-
signUp: (username: string) => Promise<void>;
|
16
|
-
getExistingUsers: () => Promise<string[]>;
|
17
|
-
logInAs: (existingUser: string) => Promise<void>;
|
18
|
-
}) => void;
|
19
|
-
onSignedIn: (next: { logOut: () => void }) => void;
|
20
|
-
onError: (error: string | Error) => void;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
const localStorageKey = "demo-auth-logged-in-secret";
|
25
|
-
|
26
|
-
export function encodeUsername(username: string) {
|
27
|
-
return btoa(username)
|
28
|
-
.replace(/=/g, "-")
|
29
|
-
.replace(/\+/g, "_")
|
30
|
-
.replace(/\//g, ".");
|
31
|
-
}
|
32
|
-
|
33
|
-
function getUserStorageKey(username: string) {
|
34
|
-
return `demo-auth-existing-users-${encodeUsername(username)}`;
|
35
|
-
}
|
36
|
-
|
37
|
-
function getLegacyUserStorageKey(username: string) {
|
38
|
-
return `demo-auth-existing-users-${username}`;
|
39
|
-
}
|
40
|
-
|
41
|
-
async function getStorageVersion(kvStore: KvStore) {
|
42
|
-
try {
|
43
|
-
const version = await kvStore.get("demo-auth-storage-version");
|
44
|
-
return version ? parseInt(version) : 1;
|
45
|
-
} catch (error) {
|
46
|
-
return 1;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
async function setStorageVersion(kvStore: KvStore, version: number) {
|
51
|
-
await kvStore.set("demo-auth-storage-version", version.toString());
|
52
|
-
}
|
53
|
-
|
54
|
-
async function getExistingUsers(kvStore: KvStore) {
|
55
|
-
const existingUsers = await kvStore.get("demo-auth-existing-users");
|
56
|
-
return existingUsers ? existingUsers.split(",") : [];
|
57
|
-
}
|
58
|
-
|
59
|
-
async function addUserToExistingUsers(username: string, kvStore: KvStore) {
|
60
|
-
const existingUsers = await getExistingUsers(kvStore);
|
61
|
-
|
62
|
-
if (existingUsers.includes(username)) {
|
63
|
-
return;
|
64
|
-
}
|
65
|
-
|
66
|
-
await kvStore.set(
|
67
|
-
"demo-auth-existing-users",
|
68
|
-
existingUsers.concat(username).join(","),
|
69
|
-
);
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Migrates existing users keys to use a base64 encoded username.
|
74
|
-
*
|
75
|
-
* This is done to avoid issues with special characters in the username.
|
76
|
-
*/
|
77
|
-
async function migrateExistingUsersKeys(kvStore: KvStore) {
|
78
|
-
if ((await getStorageVersion(kvStore)) >= 2) {
|
79
|
-
return;
|
80
|
-
}
|
81
|
-
|
82
|
-
await setStorageVersion(kvStore, 2);
|
83
|
-
|
84
|
-
const existingUsers = await getExistingUsers(kvStore);
|
85
|
-
|
86
|
-
for (const existingUsername of existingUsers) {
|
87
|
-
const legacyKey = getLegacyUserStorageKey(existingUsername);
|
88
|
-
const storageData = await kvStore.get(legacyKey);
|
89
|
-
if (storageData) {
|
90
|
-
await kvStore.set(getUserStorageKey(existingUsername), storageData);
|
91
|
-
await kvStore.delete(legacyKey);
|
92
|
-
}
|
93
|
-
}
|
94
|
-
}
|
95
|
-
|
96
|
-
export class RNDemoAuth implements AuthMethod {
|
97
|
-
private constructor(
|
98
|
-
private driver: RNDemoAuth.Driver,
|
99
|
-
private kvStore: KvStore,
|
100
|
-
) {}
|
101
|
-
|
102
|
-
public static async init(
|
103
|
-
driver: RNDemoAuth.Driver,
|
104
|
-
seedAccounts?: {
|
105
|
-
[name: string]: {
|
106
|
-
accountID: ID<Account>;
|
107
|
-
accountSecret: AgentSecret;
|
108
|
-
};
|
109
|
-
},
|
110
|
-
store?: KvStore | undefined,
|
111
|
-
) {
|
112
|
-
let kvStore = store;
|
113
|
-
|
114
|
-
const kvStoreContext = KvStoreContext.getInstance();
|
115
|
-
|
116
|
-
if (!kvStoreContext.isInitialized()) {
|
117
|
-
if (!kvStore) {
|
118
|
-
const { ExpoSecureStoreAdapter } = await import(
|
119
|
-
"../storage/expo-secure-store-adapter.js"
|
120
|
-
);
|
121
|
-
|
122
|
-
kvStoreContext.initialize(new ExpoSecureStoreAdapter());
|
123
|
-
} else {
|
124
|
-
kvStoreContext.initialize(kvStore);
|
125
|
-
}
|
126
|
-
}
|
127
|
-
|
128
|
-
kvStore = kvStoreContext.getStorage();
|
129
|
-
|
130
|
-
await migrateExistingUsersKeys(kvStore);
|
131
|
-
|
132
|
-
for (const [name, credentials] of Object.entries(seedAccounts || {})) {
|
133
|
-
const storageData = JSON.stringify(credentials satisfies StorageData);
|
134
|
-
|
135
|
-
await addUserToExistingUsers(name, kvStore);
|
136
|
-
await kvStore.set(getUserStorageKey(name), storageData);
|
137
|
-
}
|
138
|
-
|
139
|
-
return new RNDemoAuth(driver, kvStore);
|
140
|
-
}
|
141
|
-
|
142
|
-
async start() {
|
143
|
-
try {
|
144
|
-
if (await this.kvStore.get(localStorageKey)) {
|
145
|
-
const localStorageData = JSON.parse(
|
146
|
-
(await this.kvStore.get(localStorageKey)) ?? "{}",
|
147
|
-
) as StorageData;
|
148
|
-
|
149
|
-
const accountID = localStorageData.accountID as ID<Account>;
|
150
|
-
const secret = localStorageData.accountSecret;
|
151
|
-
|
152
|
-
return {
|
153
|
-
type: "existing",
|
154
|
-
credentials: { accountID, secret },
|
155
|
-
onSuccess: () => {
|
156
|
-
this.driver.onSignedIn({ logOut });
|
157
|
-
},
|
158
|
-
onError: (error: string | Error) => {
|
159
|
-
this.kvStore.delete(localStorageKey);
|
160
|
-
this.driver.onError(error);
|
161
|
-
},
|
162
|
-
logOut: async () => {
|
163
|
-
void (await this.kvStore.delete(localStorageKey));
|
164
|
-
},
|
165
|
-
} satisfies AuthResult;
|
166
|
-
} else {
|
167
|
-
return new Promise<AuthResult>((resolve) => {
|
168
|
-
this.driver.onReady({
|
169
|
-
// @ts-expect-error asd
|
170
|
-
signUp: (username: string) => {
|
171
|
-
resolve({
|
172
|
-
type: "new",
|
173
|
-
creationProps: { name: username },
|
174
|
-
saveCredentials: async (credentials: {
|
175
|
-
accountID: ID<Account>;
|
176
|
-
secret: AgentSecret;
|
177
|
-
}) => {
|
178
|
-
const storageData = JSON.stringify({
|
179
|
-
accountID: credentials.accountID,
|
180
|
-
accountSecret: credentials.secret,
|
181
|
-
} satisfies StorageData);
|
182
|
-
|
183
|
-
const existingUsernames = await getExistingUsers(
|
184
|
-
this.kvStore,
|
185
|
-
);
|
186
|
-
|
187
|
-
// Determine if the username already exists and generate a unique username
|
188
|
-
let uniqueUsername = username;
|
189
|
-
let counter = 1;
|
190
|
-
while (existingUsernames.includes(uniqueUsername)) {
|
191
|
-
counter++;
|
192
|
-
uniqueUsername = `${username}-${counter}`;
|
193
|
-
}
|
194
|
-
|
195
|
-
// Save credentials using the unique username
|
196
|
-
await this.kvStore.set(localStorageKey, storageData);
|
197
|
-
await this.kvStore.set(
|
198
|
-
getUserStorageKey(uniqueUsername),
|
199
|
-
storageData,
|
200
|
-
);
|
201
|
-
|
202
|
-
await addUserToExistingUsers(uniqueUsername, this.kvStore);
|
203
|
-
},
|
204
|
-
onSuccess: () => {
|
205
|
-
this.driver.onSignedIn({ logOut });
|
206
|
-
},
|
207
|
-
onError: (error: string | Error) => {
|
208
|
-
this.driver.onError(error);
|
209
|
-
},
|
210
|
-
logOut: async () => {
|
211
|
-
void (await this.kvStore.delete(localStorageKey));
|
212
|
-
},
|
213
|
-
});
|
214
|
-
},
|
215
|
-
getExistingUsers: async () => {
|
216
|
-
return await getExistingUsers(this.kvStore);
|
217
|
-
},
|
218
|
-
logInAs: async (existingUser) => {
|
219
|
-
const storageData = JSON.parse(
|
220
|
-
(await this.kvStore.get(getUserStorageKey(existingUser))) ??
|
221
|
-
"{}",
|
222
|
-
) as StorageData;
|
223
|
-
|
224
|
-
await this.kvStore.set(
|
225
|
-
localStorageKey,
|
226
|
-
JSON.stringify(storageData),
|
227
|
-
);
|
228
|
-
|
229
|
-
resolve({
|
230
|
-
type: "existing",
|
231
|
-
credentials: {
|
232
|
-
accountID: storageData.accountID,
|
233
|
-
secret: storageData.accountSecret,
|
234
|
-
},
|
235
|
-
onSuccess: () => {
|
236
|
-
this.driver.onSignedIn({ logOut });
|
237
|
-
},
|
238
|
-
onError: (error: string | Error) => {
|
239
|
-
this.driver.onError(error);
|
240
|
-
},
|
241
|
-
logOut: async () => {
|
242
|
-
void (await this.kvStore.delete(localStorageKey));
|
243
|
-
},
|
244
|
-
});
|
245
|
-
},
|
246
|
-
});
|
247
|
-
});
|
248
|
-
}
|
249
|
-
} catch (error) {
|
250
|
-
console.error("error", error);
|
251
|
-
throw error;
|
252
|
-
}
|
253
|
-
}
|
254
|
-
}
|
255
|
-
|
256
|
-
async function logOut() {
|
257
|
-
const kvStore = KvStoreContext.getInstance().getStorage();
|
258
|
-
void (await kvStore.delete(localStorageKey));
|
259
|
-
}
|