@phalanx-engine/client 0.1.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 (94) hide show
  1. package/README.md +1037 -0
  2. package/dist/DesyncDetector.d.ts +80 -0
  3. package/dist/DesyncDetector.d.ts.map +1 -0
  4. package/dist/DesyncDetector.js +93 -0
  5. package/dist/DesyncDetector.js.map +1 -0
  6. package/dist/DeterministicRandom.d.ts +78 -0
  7. package/dist/DeterministicRandom.d.ts.map +1 -0
  8. package/dist/DeterministicRandom.js +122 -0
  9. package/dist/DeterministicRandom.js.map +1 -0
  10. package/dist/EventEmitter.d.ts +65 -0
  11. package/dist/EventEmitter.d.ts.map +1 -0
  12. package/dist/EventEmitter.js +102 -0
  13. package/dist/EventEmitter.js.map +1 -0
  14. package/dist/FixedMath.d.ts +22 -0
  15. package/dist/FixedMath.d.ts.map +1 -0
  16. package/dist/FixedMath.js +26 -0
  17. package/dist/FixedMath.js.map +1 -0
  18. package/dist/PhalanxClient.d.ts +335 -0
  19. package/dist/PhalanxClient.d.ts.map +1 -0
  20. package/dist/PhalanxClient.js +844 -0
  21. package/dist/PhalanxClient.js.map +1 -0
  22. package/dist/RenderLoop.d.ts +95 -0
  23. package/dist/RenderLoop.d.ts.map +1 -0
  24. package/dist/RenderLoop.js +192 -0
  25. package/dist/RenderLoop.js.map +1 -0
  26. package/dist/SocketManager.d.ts +228 -0
  27. package/dist/SocketManager.d.ts.map +1 -0
  28. package/dist/SocketManager.js +584 -0
  29. package/dist/SocketManager.js.map +1 -0
  30. package/dist/StateHasher.d.ts +76 -0
  31. package/dist/StateHasher.d.ts.map +1 -0
  32. package/dist/StateHasher.js +129 -0
  33. package/dist/StateHasher.js.map +1 -0
  34. package/dist/auth/AuthManager.d.ts +188 -0
  35. package/dist/auth/AuthManager.d.ts.map +1 -0
  36. package/dist/auth/AuthManager.js +462 -0
  37. package/dist/auth/AuthManager.js.map +1 -0
  38. package/dist/auth/adapters/GoogleOAuthAdapter.d.ts +164 -0
  39. package/dist/auth/adapters/GoogleOAuthAdapter.d.ts.map +1 -0
  40. package/dist/auth/adapters/GoogleOAuthAdapter.js +521 -0
  41. package/dist/auth/adapters/GoogleOAuthAdapter.js.map +1 -0
  42. package/dist/auth/index.d.ts +45 -0
  43. package/dist/auth/index.d.ts.map +1 -0
  44. package/dist/auth/index.js +54 -0
  45. package/dist/auth/index.js.map +1 -0
  46. package/dist/auth/storage.d.ts +56 -0
  47. package/dist/auth/storage.d.ts.map +1 -0
  48. package/dist/auth/storage.js +78 -0
  49. package/dist/auth/storage.js.map +1 -0
  50. package/dist/auth/types.d.ts +212 -0
  51. package/dist/auth/types.d.ts.map +1 -0
  52. package/dist/auth/types.js +7 -0
  53. package/dist/auth/types.js.map +1 -0
  54. package/dist/index.d.ts +70 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +83 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/recovery/BrowserLifecycle.d.ts +33 -0
  59. package/dist/recovery/BrowserLifecycle.d.ts.map +1 -0
  60. package/dist/recovery/BrowserLifecycle.js +62 -0
  61. package/dist/recovery/BrowserLifecycle.js.map +1 -0
  62. package/dist/recovery/GuestPlayerIdStore.d.ts +17 -0
  63. package/dist/recovery/GuestPlayerIdStore.d.ts.map +1 -0
  64. package/dist/recovery/GuestPlayerIdStore.js +31 -0
  65. package/dist/recovery/GuestPlayerIdStore.js.map +1 -0
  66. package/dist/recovery/KeyValueStorage.d.ts +32 -0
  67. package/dist/recovery/KeyValueStorage.d.ts.map +1 -0
  68. package/dist/recovery/KeyValueStorage.js +58 -0
  69. package/dist/recovery/KeyValueStorage.js.map +1 -0
  70. package/dist/recovery/MobileTransport.d.ts +12 -0
  71. package/dist/recovery/MobileTransport.d.ts.map +1 -0
  72. package/dist/recovery/MobileTransport.js +24 -0
  73. package/dist/recovery/MobileTransport.js.map +1 -0
  74. package/dist/recovery/NetworkQuality.d.ts +22 -0
  75. package/dist/recovery/NetworkQuality.d.ts.map +1 -0
  76. package/dist/recovery/NetworkQuality.js +35 -0
  77. package/dist/recovery/NetworkQuality.js.map +1 -0
  78. package/dist/recovery/RoomPersistence.d.ts +55 -0
  79. package/dist/recovery/RoomPersistence.d.ts.map +1 -0
  80. package/dist/recovery/RoomPersistence.js +68 -0
  81. package/dist/recovery/RoomPersistence.js.map +1 -0
  82. package/dist/recovery/RoomRecoveryController.d.ts +146 -0
  83. package/dist/recovery/RoomRecoveryController.d.ts.map +1 -0
  84. package/dist/recovery/RoomRecoveryController.js +348 -0
  85. package/dist/recovery/RoomRecoveryController.js.map +1 -0
  86. package/dist/recovery/index.d.ts +13 -0
  87. package/dist/recovery/index.d.ts.map +1 -0
  88. package/dist/recovery/index.js +8 -0
  89. package/dist/recovery/index.js.map +1 -0
  90. package/dist/types.d.ts +501 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +6 -0
  93. package/dist/types.js.map +1 -0
  94. package/package.json +66 -0
@@ -0,0 +1,348 @@
1
+ import { armBrowserLifecycle, isOnline, waitForOnlineEvent, } from './BrowserLifecycle.js';
2
+ import { DEFAULT_RECOVER_TIMEOUT_BUDGET, getRecoverTimeoutMs, } from './NetworkQuality.js';
3
+ import { RoomPersistence } from './RoomPersistence.js';
4
+ const NETWORK_STABILIZE_DELAY_MS = 300;
5
+ const CONNECTED_RECOVER_DELAY_MS = 300;
6
+ const DISCONNECTED_RECOVER_DELAY_MS = 300;
7
+ const OFFLINE_WAIT_TIMEOUT_MS = 30_000;
8
+ const DEFAULT_MAX_RECOVER_ATTEMPTS = 5;
9
+ const DEFAULT_PRE_GAME_STALL_MS = 4_500;
10
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
11
+ /**
12
+ * Owns the entire mobile-friendly recovery state machine for a single
13
+ * private room: visibility/pageshow/online listeners, socket connect/
14
+ * disconnect hooks, exponential-backoff retry, and the localStorage
15
+ * persistence record. Emits typed status events instead of touching
16
+ * UI directly so each game can render its own strings.
17
+ *
18
+ * Lifecycle:
19
+ * client.roomRecovery.startTrackingHost(code) // host created room
20
+ * client.roomRecovery.trackGuestJoin(code) // guest is mid-join
21
+ * client.roomRecovery.resumeTrackingHost(code) // cold-start recover
22
+ * client.roomRecovery.stop() // cancel / match started
23
+ *
24
+ * The pre-game stall watchdog is auto-armed on every matchFound and
25
+ * disarmed on gameStart, so games no longer need their own
26
+ * `armPreGameStallWatchdog` helper.
27
+ */
28
+ export class RoomRecoveryController {
29
+ client;
30
+ persistence;
31
+ recoverBudget;
32
+ maxRecoverAttempts;
33
+ preGameStallEnabled;
34
+ preGameStallMs;
35
+ emit;
36
+ activeRoomCode = null;
37
+ isRecovering = false;
38
+ pendingRecoverRequested = false;
39
+ pendingForceReconnectRequested = false;
40
+ recoverAttempt = 0;
41
+ recoverRetryTimer = null;
42
+ recoverScheduleTimer = null;
43
+ lifecycleHandle = null;
44
+ clientEventUnsubs = [];
45
+ preGameStallTimer = null;
46
+ hasGameStartedSinceTracking = false;
47
+ constructor(client, config, emit) {
48
+ this.client = client;
49
+ this.persistence = new RoomPersistence({
50
+ storageKey: config.storageKey,
51
+ roomTtlMs: config.roomTtlMs,
52
+ storage: config.storage,
53
+ });
54
+ this.recoverBudget =
55
+ config.recoverTimeoutBudget ?? DEFAULT_RECOVER_TIMEOUT_BUDGET;
56
+ this.maxRecoverAttempts =
57
+ config.maxRecoverAttempts ?? DEFAULT_MAX_RECOVER_ATTEMPTS;
58
+ this.preGameStallEnabled = config.preGameStallWatchdog ?? true;
59
+ this.preGameStallMs = config.preGameStallMs ?? DEFAULT_PRE_GAME_STALL_MS;
60
+ this.emit = emit;
61
+ }
62
+ // ── Public surface ──────────────────────────────────────────────
63
+ hasActiveRoom() {
64
+ return this.activeRoomCode !== null;
65
+ }
66
+ getActiveRoomCode() {
67
+ return this.activeRoomCode;
68
+ }
69
+ /**
70
+ * Cold-start recovery: read the persisted host record (mobile killed
71
+ * the tab while the user was in a messenger) and validate it against
72
+ * the current playerId. Returns the code to recover, or null when
73
+ * there's nothing to do (no record, expired, or playerId drift).
74
+ */
75
+ loadColdStartCode() {
76
+ const persisted = this.persistence.load();
77
+ if (!persisted || persisted.role !== 'host')
78
+ return null;
79
+ const currentPlayerId = this.client.getPlayerId();
80
+ if (currentPlayerId && currentPlayerId === persisted.playerId) {
81
+ return persisted.code;
82
+ }
83
+ // playerId drift — abandon the stale entry rather than leaving
84
+ // the user staring at a permanently-failing recover attempt.
85
+ this.persistence.clear();
86
+ return null;
87
+ }
88
+ /** Begin tracking `code` as the active host-side room. */
89
+ startTrackingHost(code) {
90
+ this.activeRoomCode = code;
91
+ this.persistence.save({
92
+ code,
93
+ role: 'host',
94
+ playerId: this.client.getPlayerId(),
95
+ });
96
+ this.armHooks();
97
+ }
98
+ /**
99
+ * Variant used by cold-start recover: assumes the persistence record
100
+ * was already written by a previous tab and just rearms the hooks.
101
+ */
102
+ resumeTrackingHost(code) {
103
+ this.activeRoomCode = code;
104
+ this.armHooks();
105
+ }
106
+ /** Persist a guest-side join attempt for cold-start surfacing. */
107
+ trackGuestJoin(code) {
108
+ this.persistence.save({
109
+ code,
110
+ role: 'guest',
111
+ playerId: this.client.getPlayerId(),
112
+ });
113
+ }
114
+ /** Stop all recovery machinery and forget the active room. Idempotent. */
115
+ stop() {
116
+ this.disarmHooks();
117
+ this.clearPreGameStallWatchdog();
118
+ this.activeRoomCode = null;
119
+ this.pendingRecoverRequested = false;
120
+ this.pendingForceReconnectRequested = false;
121
+ this.recoverAttempt = 0;
122
+ this.hasGameStartedSinceTracking = false;
123
+ this.persistence.clear();
124
+ this.emit('recoveryStatus', { phase: 'idle' });
125
+ }
126
+ /**
127
+ * Recover through a fresh socket even if Socket.IO still reports the
128
+ * current one as connected. This handles mobile carrier/WebView
129
+ * stalls where server→client packets stop arriving but heartbeat has
130
+ * not fired yet, so the normal `disconnected` hook would be too late.
131
+ */
132
+ forceRecover(reason) {
133
+ if (!this.activeRoomCode)
134
+ return;
135
+ void reason;
136
+ this.pendingForceReconnectRequested = true;
137
+ this.scheduleRecover(NETWORK_STABILIZE_DELAY_MS);
138
+ }
139
+ /**
140
+ * Attempt one recovery cycle. Idempotent against concurrent calls
141
+ * (the visibility and `connected` hooks may fire near-simultaneously
142
+ * on mobile). Schedules its own backoff retry on transient failure.
143
+ */
144
+ async tryRecover() {
145
+ const code = this.activeRoomCode;
146
+ if (!code)
147
+ return;
148
+ if (this.isRecovering) {
149
+ this.pendingRecoverRequested = true;
150
+ return;
151
+ }
152
+ this.isRecovering = true;
153
+ const forceReconnect = this.pendingForceReconnectRequested;
154
+ this.pendingRecoverRequested = false;
155
+ this.pendingForceReconnectRequested = false;
156
+ if (this.recoverRetryTimer) {
157
+ clearTimeout(this.recoverRetryTimer);
158
+ this.recoverRetryTimer = null;
159
+ }
160
+ try {
161
+ this.emit('recoveryStatus', {
162
+ phase: 'recovering',
163
+ attempt: this.recoverAttempt + 1,
164
+ });
165
+ await this.waitForOnlineAndStabilize();
166
+ if (this.activeRoomCode !== code)
167
+ return;
168
+ // NOTE: we deliberately do NOT short-circuit on isConnected().
169
+ // socket.io auto-reconnect can produce a fresh connection while
170
+ // we were backgrounded — that socket has no record of being this
171
+ // room's host, so we must send `room-recover` on it either way.
172
+ // The server's recover path is idempotent and rebinds on the
173
+ // live socket.
174
+ if (forceReconnect && this.client.isConnected()) {
175
+ this.client.disconnect();
176
+ await delay(NETWORK_STABILIZE_DELAY_MS);
177
+ }
178
+ if (!this.client.isConnected()) {
179
+ await this.client.connect();
180
+ }
181
+ await this.client.recoverRoom(code, getRecoverTimeoutMs(this.recoverBudget));
182
+ this.recoverAttempt = 0;
183
+ this.emit('recoveryStatus', { phase: 'idle' });
184
+ }
185
+ catch (error) {
186
+ const message = error instanceof Error ? error.message : String(error);
187
+ console.warn(`[RoomRecovery] Recover failed: ${message}`);
188
+ // Only TERMINAL failure: server explicitly says the room is gone.
189
+ // Anything else (timeouts, dropped sockets) is transient.
190
+ if (message === 'Room expired' || message === 'Room not found') {
191
+ const reason = message === 'Room expired' ? 'expired' : 'not-found';
192
+ this.stop();
193
+ this.emit('roomTerminated', { reason });
194
+ return;
195
+ }
196
+ this.recoverAttempt += 1;
197
+ if (this.recoverAttempt >= this.maxRecoverAttempts) {
198
+ this.recoverAttempt = 0;
199
+ this.emit('recoveryStatus', { phase: 'gave-up' });
200
+ // Don't redirect — game's UI should still expose a manual cancel.
201
+ return;
202
+ }
203
+ const retryDelay = Math.min(2_000 * 2 ** (this.recoverAttempt - 1), 30_000);
204
+ this.emit('recoveryStatus', {
205
+ phase: 'retrying',
206
+ attempt: this.recoverAttempt,
207
+ nextRetryMs: retryDelay,
208
+ });
209
+ this.recoverRetryTimer = setTimeout(() => {
210
+ this.recoverRetryTimer = null;
211
+ void this.tryRecover();
212
+ }, retryDelay);
213
+ }
214
+ finally {
215
+ this.isRecovering = false;
216
+ if (this.pendingRecoverRequested &&
217
+ this.activeRoomCode &&
218
+ !this.recoverRetryTimer) {
219
+ this.scheduleRecover(NETWORK_STABILIZE_DELAY_MS);
220
+ }
221
+ }
222
+ }
223
+ // ── Pre-game stall watchdog ─────────────────────────────────────
224
+ /**
225
+ * Arm a one-shot timer: if `gameStart` doesn't arrive within
226
+ * `preGameStallMs` we proactively `forceRecover` because the most
227
+ * likely explanation is that the host's socket silently died mid-
228
+ * countdown. Auto-armed on `matchFound` / `countdown` events when
229
+ * `preGameStallWatchdog` is enabled — games rarely need to call this
230
+ * directly.
231
+ */
232
+ armPreGameStallWatchdog(reason) {
233
+ if (!this.preGameStallEnabled)
234
+ return;
235
+ if (this.hasGameStartedSinceTracking)
236
+ return;
237
+ this.clearPreGameStallWatchdog();
238
+ this.preGameStallTimer = setTimeout(() => {
239
+ this.preGameStallTimer = null;
240
+ if (this.hasGameStartedSinceTracking)
241
+ return;
242
+ if (!this.activeRoomCode)
243
+ return;
244
+ this.forceRecover(reason);
245
+ }, this.preGameStallMs);
246
+ }
247
+ clearPreGameStallWatchdog() {
248
+ if (!this.preGameStallTimer)
249
+ return;
250
+ clearTimeout(this.preGameStallTimer);
251
+ this.preGameStallTimer = null;
252
+ }
253
+ // ── Internal arming/disarming ───────────────────────────────────
254
+ armHooks() {
255
+ this.armBrowserLifecycle();
256
+ this.armClientEventHooks();
257
+ }
258
+ disarmHooks() {
259
+ this.lifecycleHandle?.dispose();
260
+ this.lifecycleHandle = null;
261
+ for (const unsub of this.clientEventUnsubs)
262
+ unsub();
263
+ this.clientEventUnsubs = [];
264
+ if (this.recoverRetryTimer) {
265
+ clearTimeout(this.recoverRetryTimer);
266
+ this.recoverRetryTimer = null;
267
+ }
268
+ if (this.recoverScheduleTimer) {
269
+ clearTimeout(this.recoverScheduleTimer);
270
+ this.recoverScheduleTimer = null;
271
+ }
272
+ }
273
+ armBrowserLifecycle() {
274
+ if (this.lifecycleHandle)
275
+ return;
276
+ this.lifecycleHandle = armBrowserLifecycle({
277
+ onVisible: () => this.scheduleRecover(),
278
+ });
279
+ }
280
+ armClientEventHooks() {
281
+ if (this.clientEventUnsubs.length > 0)
282
+ return;
283
+ // Auto-reconnect produced a fresh socket — claim back the room.
284
+ this.clientEventUnsubs.push(this.client.on('connected', () => {
285
+ if (!this.activeRoomCode)
286
+ return;
287
+ this.scheduleRecover(CONNECTED_RECOVER_DELAY_MS);
288
+ }));
289
+ // Mobile networks can drop the transport during the private-room
290
+ // countdown before PhalanxClient reaches `playing`. The generic
291
+ // SocketManager reconnect path intentionally only handles in-game
292
+ // reconnects, so private rooms must proactively recover themselves
293
+ // as soon as this pre-game disconnect is observed.
294
+ this.clientEventUnsubs.push(this.client.on('disconnected', () => {
295
+ if (!this.activeRoomCode)
296
+ return;
297
+ this.scheduleRecover(DISCONNECTED_RECOVER_DELAY_MS);
298
+ }));
299
+ this.clientEventUnsubs.push(this.client.on('roomExpired', () => {
300
+ this.stop();
301
+ this.emit('roomTerminated', { reason: 'expired' });
302
+ }));
303
+ this.clientEventUnsubs.push(this.client.on('roomCancelled', () => {
304
+ this.stop();
305
+ this.emit('roomTerminated', { reason: 'cancelled' });
306
+ }));
307
+ // Pre-game stall watchdog — auto-armed on the events that lead up
308
+ // to `gameStart`, auto-cleared once the game actually starts.
309
+ if (this.preGameStallEnabled) {
310
+ this.clientEventUnsubs.push(this.client.on('matchFound', () => {
311
+ this.armPreGameStallWatchdog('game-start missing after match-found');
312
+ }));
313
+ this.clientEventUnsubs.push(this.client.on('countdown', (event) => {
314
+ if (event.seconds > 0) {
315
+ this.armPreGameStallWatchdog(`countdown stalled after ${event.seconds}`);
316
+ }
317
+ }));
318
+ this.clientEventUnsubs.push(this.client.on('gameStart', () => {
319
+ this.hasGameStartedSinceTracking = true;
320
+ this.clearPreGameStallWatchdog();
321
+ }));
322
+ }
323
+ }
324
+ scheduleRecover(delayMs = 0) {
325
+ if (!this.activeRoomCode)
326
+ return;
327
+ this.pendingRecoverRequested = true;
328
+ if (this.isRecovering || this.recoverScheduleTimer)
329
+ return;
330
+ this.recoverScheduleTimer = setTimeout(() => {
331
+ this.recoverScheduleTimer = null;
332
+ if (!this.pendingRecoverRequested)
333
+ return;
334
+ void this.tryRecover();
335
+ }, delayMs);
336
+ }
337
+ async waitForOnlineAndStabilize() {
338
+ if (!isOnline()) {
339
+ this.emit('recoveryStatus', { phase: 'waiting-network' });
340
+ await waitForOnlineEvent(OFFLINE_WAIT_TIMEOUT_MS);
341
+ if (!isOnline()) {
342
+ throw new Error('Network offline');
343
+ }
344
+ }
345
+ await delay(NETWORK_STABILIZE_DELAY_MS);
346
+ }
347
+ }
348
+ //# sourceMappingURL=RoomRecoveryController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoomRecoveryController.js","sourceRoot":"","sources":["../../src/recovery/RoomRecoveryController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { RoomPersistence } from './RoomPersistence.js';
2
+ export type { PersistedRoom, RoomRole, RoomPersistenceConfig, } from './RoomPersistence.js';
3
+ export { RoomRecoveryController, } from './RoomRecoveryController.js';
4
+ export type { RoomRecoveryConfig, RoomRecoveryStatusEvent, RoomRecoveryPhase, RoomTerminatedEvent, RoomRecoveryControllerEvents, RecoveryClientPort, } from './RoomRecoveryController.js';
5
+ export { armBrowserLifecycle, isOnline, waitForOnlineEvent, } from './BrowserLifecycle.js';
6
+ export type { BrowserLifecycleHandle, BrowserLifecycleHandlers } from './BrowserLifecycle.js';
7
+ export { getRecoverTimeoutMs, DEFAULT_RECOVER_TIMEOUT_BUDGET, } from './NetworkQuality.js';
8
+ export type { RecoverTimeoutBudget } from './NetworkQuality.js';
9
+ export { isMobileBrowser, pickMobileFriendlyTransports } from './MobileTransport.js';
10
+ export { loadOrCreateGuestPlayerId } from './GuestPlayerIdStore.js';
11
+ export { LocalStorageAdapter, MemoryKeyValueStorage, defaultKeyValueStorage, } from './KeyValueStorage.js';
12
+ export type { KeyValueStorage } from './KeyValueStorage.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,aAAa,EACb,QAAQ,EACR,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,4BAA4B,EAC5B,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAE9F,OAAO,EACL,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAErF,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { RoomPersistence } from './RoomPersistence.js';
2
+ export { RoomRecoveryController, } from './RoomRecoveryController.js';
3
+ export { armBrowserLifecycle, isOnline, waitForOnlineEvent, } from './BrowserLifecycle.js';
4
+ export { getRecoverTimeoutMs, DEFAULT_RECOVER_TIMEOUT_BUDGET, } from './NetworkQuality.js';
5
+ export { isMobileBrowser, pickMobileFriendlyTransports } from './MobileTransport.js';
6
+ export { loadOrCreateGuestPlayerId } from './GuestPlayerIdStore.js';
7
+ export { LocalStorageAdapter, MemoryKeyValueStorage, defaultKeyValueStorage, } from './KeyValueStorage.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/recovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAOvD,OAAO,EACL,sBAAsB,GACvB,MAAM,6BAA6B,CAAC;AAUrC,OAAO,EACL,mBAAmB,EACnB,QAAQ,EACR,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAErF,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC"}