@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.
- package/README.md +1037 -0
- package/dist/DesyncDetector.d.ts +80 -0
- package/dist/DesyncDetector.d.ts.map +1 -0
- package/dist/DesyncDetector.js +93 -0
- package/dist/DesyncDetector.js.map +1 -0
- package/dist/DeterministicRandom.d.ts +78 -0
- package/dist/DeterministicRandom.d.ts.map +1 -0
- package/dist/DeterministicRandom.js +122 -0
- package/dist/DeterministicRandom.js.map +1 -0
- package/dist/EventEmitter.d.ts +65 -0
- package/dist/EventEmitter.d.ts.map +1 -0
- package/dist/EventEmitter.js +102 -0
- package/dist/EventEmitter.js.map +1 -0
- package/dist/FixedMath.d.ts +22 -0
- package/dist/FixedMath.d.ts.map +1 -0
- package/dist/FixedMath.js +26 -0
- package/dist/FixedMath.js.map +1 -0
- package/dist/PhalanxClient.d.ts +335 -0
- package/dist/PhalanxClient.d.ts.map +1 -0
- package/dist/PhalanxClient.js +844 -0
- package/dist/PhalanxClient.js.map +1 -0
- package/dist/RenderLoop.d.ts +95 -0
- package/dist/RenderLoop.d.ts.map +1 -0
- package/dist/RenderLoop.js +192 -0
- package/dist/RenderLoop.js.map +1 -0
- package/dist/SocketManager.d.ts +228 -0
- package/dist/SocketManager.d.ts.map +1 -0
- package/dist/SocketManager.js +584 -0
- package/dist/SocketManager.js.map +1 -0
- package/dist/StateHasher.d.ts +76 -0
- package/dist/StateHasher.d.ts.map +1 -0
- package/dist/StateHasher.js +129 -0
- package/dist/StateHasher.js.map +1 -0
- package/dist/auth/AuthManager.d.ts +188 -0
- package/dist/auth/AuthManager.d.ts.map +1 -0
- package/dist/auth/AuthManager.js +462 -0
- package/dist/auth/AuthManager.js.map +1 -0
- package/dist/auth/adapters/GoogleOAuthAdapter.d.ts +164 -0
- package/dist/auth/adapters/GoogleOAuthAdapter.d.ts.map +1 -0
- package/dist/auth/adapters/GoogleOAuthAdapter.js +521 -0
- package/dist/auth/adapters/GoogleOAuthAdapter.js.map +1 -0
- package/dist/auth/index.d.ts +45 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +54 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/storage.d.ts +56 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +78 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/auth/types.d.ts +212 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +7 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/index.js.map +1 -0
- package/dist/recovery/BrowserLifecycle.d.ts +33 -0
- package/dist/recovery/BrowserLifecycle.d.ts.map +1 -0
- package/dist/recovery/BrowserLifecycle.js +62 -0
- package/dist/recovery/BrowserLifecycle.js.map +1 -0
- package/dist/recovery/GuestPlayerIdStore.d.ts +17 -0
- package/dist/recovery/GuestPlayerIdStore.d.ts.map +1 -0
- package/dist/recovery/GuestPlayerIdStore.js +31 -0
- package/dist/recovery/GuestPlayerIdStore.js.map +1 -0
- package/dist/recovery/KeyValueStorage.d.ts +32 -0
- package/dist/recovery/KeyValueStorage.d.ts.map +1 -0
- package/dist/recovery/KeyValueStorage.js +58 -0
- package/dist/recovery/KeyValueStorage.js.map +1 -0
- package/dist/recovery/MobileTransport.d.ts +12 -0
- package/dist/recovery/MobileTransport.d.ts.map +1 -0
- package/dist/recovery/MobileTransport.js +24 -0
- package/dist/recovery/MobileTransport.js.map +1 -0
- package/dist/recovery/NetworkQuality.d.ts +22 -0
- package/dist/recovery/NetworkQuality.d.ts.map +1 -0
- package/dist/recovery/NetworkQuality.js +35 -0
- package/dist/recovery/NetworkQuality.js.map +1 -0
- package/dist/recovery/RoomPersistence.d.ts +55 -0
- package/dist/recovery/RoomPersistence.d.ts.map +1 -0
- package/dist/recovery/RoomPersistence.js +68 -0
- package/dist/recovery/RoomPersistence.js.map +1 -0
- package/dist/recovery/RoomRecoveryController.d.ts +146 -0
- package/dist/recovery/RoomRecoveryController.d.ts.map +1 -0
- package/dist/recovery/RoomRecoveryController.js +348 -0
- package/dist/recovery/RoomRecoveryController.js.map +1 -0
- package/dist/recovery/index.d.ts +13 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +8 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/types.d.ts +501 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phalanx Auth Storage
|
|
3
|
+
*
|
|
4
|
+
* Storage interface and implementations for persisting auth data.
|
|
5
|
+
*/
|
|
6
|
+
import type { StoredAuthData } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Interface for auth data storage.
|
|
9
|
+
* Implement this interface to provide custom storage (e.g., React Native SecureStore).
|
|
10
|
+
*/
|
|
11
|
+
export interface AuthStorage {
|
|
12
|
+
/**
|
|
13
|
+
* Retrieve stored auth data.
|
|
14
|
+
* @returns Stored data or null if not found
|
|
15
|
+
*/
|
|
16
|
+
get(): Promise<StoredAuthData | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Store auth data.
|
|
19
|
+
* @param data - Auth data to store
|
|
20
|
+
*/
|
|
21
|
+
set(data: StoredAuthData): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Clear stored auth data.
|
|
24
|
+
*/
|
|
25
|
+
clear(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Default storage implementation using localStorage.
|
|
29
|
+
* Suitable for web browsers.
|
|
30
|
+
*
|
|
31
|
+
* Note: For production, consider using httpOnly cookies for refresh tokens
|
|
32
|
+
* or a custom storage implementation with encryption.
|
|
33
|
+
*/
|
|
34
|
+
export declare class LocalStorageAdapter implements AuthStorage {
|
|
35
|
+
private key;
|
|
36
|
+
/**
|
|
37
|
+
* Create a new LocalStorageAdapter.
|
|
38
|
+
* @param key - Storage key prefix (default: 'phalanx_auth')
|
|
39
|
+
*/
|
|
40
|
+
constructor(key?: string);
|
|
41
|
+
get(): Promise<StoredAuthData | null>;
|
|
42
|
+
set(data: StoredAuthData): Promise<void>;
|
|
43
|
+
clear(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* In-memory storage implementation.
|
|
47
|
+
* Useful for testing or environments without persistent storage.
|
|
48
|
+
* Data is lost on page refresh.
|
|
49
|
+
*/
|
|
50
|
+
export declare class MemoryStorageAdapter implements AuthStorage {
|
|
51
|
+
private data;
|
|
52
|
+
get(): Promise<StoredAuthData | null>;
|
|
53
|
+
set(data: StoredAuthData): Promise<void>;
|
|
54
|
+
clear(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,GAAG,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAMD;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,GAAG,CAAS;IAEpB;;;OAGG;gBACS,GAAG,GAAE,MAAuB;IAIlC,GAAG,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAYrC,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B;AAMD;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,IAAI,CAA+B;IAErC,GAAG,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAIrC,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phalanx Auth Storage
|
|
3
|
+
*
|
|
4
|
+
* Storage interface and implementations for persisting auth data.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================
|
|
7
|
+
// LocalStorage Implementation
|
|
8
|
+
// ============================================
|
|
9
|
+
/**
|
|
10
|
+
* Default storage implementation using localStorage.
|
|
11
|
+
* Suitable for web browsers.
|
|
12
|
+
*
|
|
13
|
+
* Note: For production, consider using httpOnly cookies for refresh tokens
|
|
14
|
+
* or a custom storage implementation with encryption.
|
|
15
|
+
*/
|
|
16
|
+
export class LocalStorageAdapter {
|
|
17
|
+
key;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new LocalStorageAdapter.
|
|
20
|
+
* @param key - Storage key prefix (default: 'phalanx_auth')
|
|
21
|
+
*/
|
|
22
|
+
constructor(key = 'phalanx_auth') {
|
|
23
|
+
this.key = key;
|
|
24
|
+
}
|
|
25
|
+
async get() {
|
|
26
|
+
try {
|
|
27
|
+
if (typeof localStorage === 'undefined') {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const data = localStorage.getItem(this.key);
|
|
31
|
+
return data ? JSON.parse(data) : null;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async set(data) {
|
|
38
|
+
if (typeof localStorage === 'undefined') {
|
|
39
|
+
console.warn('[AuthStorage] localStorage is not available');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// Security warning for production
|
|
43
|
+
if (typeof process !== 'undefined' &&
|
|
44
|
+
process.env?.NODE_ENV === 'production' &&
|
|
45
|
+
data.refreshToken) {
|
|
46
|
+
console.warn('[AuthStorage] Storing refresh token in localStorage is not recommended for production. ' +
|
|
47
|
+
'Consider using httpOnly cookies or a custom storage implementation.');
|
|
48
|
+
}
|
|
49
|
+
localStorage.setItem(this.key, JSON.stringify(data));
|
|
50
|
+
}
|
|
51
|
+
async clear() {
|
|
52
|
+
if (typeof localStorage === 'undefined') {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
localStorage.removeItem(this.key);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ============================================
|
|
59
|
+
// Memory Storage Implementation
|
|
60
|
+
// ============================================
|
|
61
|
+
/**
|
|
62
|
+
* In-memory storage implementation.
|
|
63
|
+
* Useful for testing or environments without persistent storage.
|
|
64
|
+
* Data is lost on page refresh.
|
|
65
|
+
*/
|
|
66
|
+
export class MemoryStorageAdapter {
|
|
67
|
+
data = null;
|
|
68
|
+
async get() {
|
|
69
|
+
return this.data;
|
|
70
|
+
}
|
|
71
|
+
async set(data) {
|
|
72
|
+
this.data = data;
|
|
73
|
+
}
|
|
74
|
+
async clear() {
|
|
75
|
+
this.data = null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA+BH,+CAA+C;AAC/C,8BAA8B;AAC9B,+CAA+C;AAE/C;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IACtB,GAAG,CAAS;IAEpB;;;OAGG;IACH,YAAY,MAAc,cAAc;QACtC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,GAAG;QACP,IAAI,CAAC;YACH,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;gBACxC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAoB;QAC5B,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,kCAAkC;QAClC,IACE,OAAO,OAAO,KAAK,WAAW;YAC9B,OAAO,CAAC,GAAG,EAAE,QAAQ,KAAK,YAAY;YACtC,IAAI,CAAC,YAAY,EACjB,CAAC;YACD,OAAO,CAAC,IAAI,CACV,yFAAyF;gBACvF,qEAAqE,CACxE,CAAC;QACJ,CAAC;QAED,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QACD,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;CACF;AAED,+CAA+C;AAC/C,gCAAgC;AAChC,+CAA+C;AAE/C;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IACvB,IAAI,GAA0B,IAAI,CAAC;IAE3C,KAAK,CAAC,GAAG;QACP,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAoB;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phalanx Auth Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the managed OAuth authentication system.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Interface that all OAuth adapters must implement.
|
|
8
|
+
* Provides a consistent API for different OAuth providers.
|
|
9
|
+
*/
|
|
10
|
+
export interface AuthAdapter {
|
|
11
|
+
/** The provider name (e.g., 'google', 'discord', 'steam') */
|
|
12
|
+
readonly provider: string;
|
|
13
|
+
/**
|
|
14
|
+
* Generate the OAuth authorization URL.
|
|
15
|
+
* User will be redirected to this URL to authenticate.
|
|
16
|
+
*/
|
|
17
|
+
getLoginUrl(options?: LoginOptions): string;
|
|
18
|
+
/**
|
|
19
|
+
* Handle the OAuth callback.
|
|
20
|
+
* Called when user is redirected back from OAuth provider.
|
|
21
|
+
*/
|
|
22
|
+
handleCallback(params: CallbackParams): Promise<AuthResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Refresh an expired token.
|
|
25
|
+
* Returns null if refresh is not supported or refresh token is invalid.
|
|
26
|
+
*/
|
|
27
|
+
refreshToken(refreshToken: string): Promise<AuthResult | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Revoke the token (logout from provider).
|
|
30
|
+
* Optional - not all providers support token revocation.
|
|
31
|
+
*/
|
|
32
|
+
revokeToken?(token: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if this adapter supports the given token.
|
|
35
|
+
* Used for multi-provider setups to route tokens to correct adapter.
|
|
36
|
+
*/
|
|
37
|
+
canHandle?(token: string): boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Options for initiating the login flow.
|
|
41
|
+
*/
|
|
42
|
+
export interface LoginOptions {
|
|
43
|
+
/** Override the redirect URI */
|
|
44
|
+
redirectUri?: string;
|
|
45
|
+
/** Additional OAuth scopes */
|
|
46
|
+
scopes?: string[];
|
|
47
|
+
/** Login hint (email) to pre-fill */
|
|
48
|
+
loginHint?: string;
|
|
49
|
+
/** Force account selection even if already logged in */
|
|
50
|
+
prompt?: 'none' | 'consent' | 'select_account';
|
|
51
|
+
/** Custom state parameter (default: random) */
|
|
52
|
+
state?: string;
|
|
53
|
+
/** Nonce for ID token validation */
|
|
54
|
+
nonce?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parameters received from OAuth provider callback.
|
|
58
|
+
*/
|
|
59
|
+
export interface CallbackParams {
|
|
60
|
+
/** Authorization code from OAuth provider */
|
|
61
|
+
code?: string;
|
|
62
|
+
/** State parameter for CSRF validation */
|
|
63
|
+
state?: string;
|
|
64
|
+
/** Error code if auth failed */
|
|
65
|
+
error?: string;
|
|
66
|
+
/** Error description */
|
|
67
|
+
errorDescription?: string;
|
|
68
|
+
/** Full URL (for parsing) */
|
|
69
|
+
url?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Result of an authentication attempt.
|
|
73
|
+
*/
|
|
74
|
+
export interface AuthResult {
|
|
75
|
+
/** Whether authentication was successful */
|
|
76
|
+
valid: boolean;
|
|
77
|
+
/** Unique player ID from the provider */
|
|
78
|
+
playerId?: string;
|
|
79
|
+
/** Display username */
|
|
80
|
+
username?: string;
|
|
81
|
+
/** Email address */
|
|
82
|
+
email?: string;
|
|
83
|
+
/** URL to user's avatar image */
|
|
84
|
+
avatarUrl?: string;
|
|
85
|
+
/** Provider name */
|
|
86
|
+
provider?: string;
|
|
87
|
+
/** ID token or access token (main token for auth) */
|
|
88
|
+
token?: string;
|
|
89
|
+
/** Access token for API calls */
|
|
90
|
+
accessToken?: string;
|
|
91
|
+
/** Refresh token for token refresh */
|
|
92
|
+
refreshToken?: string;
|
|
93
|
+
/** Token expiration timestamp in milliseconds */
|
|
94
|
+
expiresAt?: number;
|
|
95
|
+
/** Human-readable error message */
|
|
96
|
+
error?: string;
|
|
97
|
+
/** Error code */
|
|
98
|
+
errorCode?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Authenticated user information.
|
|
102
|
+
*/
|
|
103
|
+
export interface AuthUser {
|
|
104
|
+
/** Unique user ID from the provider */
|
|
105
|
+
id: string;
|
|
106
|
+
/** Display username */
|
|
107
|
+
username?: string;
|
|
108
|
+
/** Email address */
|
|
109
|
+
email?: string;
|
|
110
|
+
/** URL to user's avatar image */
|
|
111
|
+
avatarUrl?: string;
|
|
112
|
+
/** OAuth provider name */
|
|
113
|
+
provider: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Current authentication state.
|
|
117
|
+
*/
|
|
118
|
+
export interface AuthState {
|
|
119
|
+
/** Whether user is currently authenticated */
|
|
120
|
+
isAuthenticated: boolean;
|
|
121
|
+
/** Whether auth check is in progress */
|
|
122
|
+
isLoading: boolean;
|
|
123
|
+
/** Authenticated user info (null if not authenticated) */
|
|
124
|
+
user: AuthUser | null;
|
|
125
|
+
/** Current auth token (null if not authenticated) */
|
|
126
|
+
token: string | null;
|
|
127
|
+
/** Token expiration timestamp in milliseconds */
|
|
128
|
+
expiresAt: number | null;
|
|
129
|
+
/** OAuth provider name */
|
|
130
|
+
provider: string | null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Data persisted to storage.
|
|
134
|
+
*/
|
|
135
|
+
export interface StoredAuthData {
|
|
136
|
+
/** User information */
|
|
137
|
+
user: AuthUser;
|
|
138
|
+
/** Auth token (ID token) */
|
|
139
|
+
token: string;
|
|
140
|
+
/** Access token (for API calls and revocation) */
|
|
141
|
+
accessToken?: string;
|
|
142
|
+
/** Refresh token (if available) */
|
|
143
|
+
refreshToken?: string;
|
|
144
|
+
/** Token expiration timestamp */
|
|
145
|
+
expiresAt?: number;
|
|
146
|
+
/** OAuth provider name */
|
|
147
|
+
provider: string;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Authentication error with additional context.
|
|
151
|
+
*/
|
|
152
|
+
export interface AuthError extends Error {
|
|
153
|
+
/** Error code */
|
|
154
|
+
code: string;
|
|
155
|
+
/** OAuth provider (if applicable) */
|
|
156
|
+
provider?: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Google OAuth configuration.
|
|
160
|
+
*/
|
|
161
|
+
export interface GoogleOAuthConfig {
|
|
162
|
+
/** Google OAuth 2.0 Client ID */
|
|
163
|
+
clientId: string;
|
|
164
|
+
/** OAuth scopes (default: ['openid', 'profile', 'email']) */
|
|
165
|
+
scopes?: string[];
|
|
166
|
+
/** Redirect URI after auth (default: window.location.origin + '/auth/callback') */
|
|
167
|
+
redirectUri?: string;
|
|
168
|
+
/** Google Workspace domain to restrict to */
|
|
169
|
+
hostedDomain?: string;
|
|
170
|
+
/**
|
|
171
|
+
* Backend endpoint URL for token exchange.
|
|
172
|
+
* The server exchanges the auth code for tokens using client_secret.
|
|
173
|
+
* This keeps the client_secret secure on the server.
|
|
174
|
+
*
|
|
175
|
+
* Example: 'https://your-game-server.com/auth/token'
|
|
176
|
+
*
|
|
177
|
+
* If not provided, the adapter will try to exchange directly with Google
|
|
178
|
+
* (which will fail for Web application clients that require client_secret).
|
|
179
|
+
*/
|
|
180
|
+
tokenExchangeUrl?: string;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Discord OAuth configuration.
|
|
184
|
+
*/
|
|
185
|
+
export interface DiscordOAuthConfig {
|
|
186
|
+
/** Discord OAuth Client ID */
|
|
187
|
+
clientId: string;
|
|
188
|
+
/** OAuth scopes (default: ['identify', 'email']) */
|
|
189
|
+
scopes?: string[];
|
|
190
|
+
/** Redirect URI after auth */
|
|
191
|
+
redirectUri?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Discord OAuth requires client_secret for token exchange.
|
|
194
|
+
* This MUST be done server-side. Provide your backend endpoint.
|
|
195
|
+
*/
|
|
196
|
+
tokenExchangeEndpoint: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Steam OpenID configuration.
|
|
200
|
+
*/
|
|
201
|
+
export interface SteamAuthConfig {
|
|
202
|
+
/** Your domain (realm) - e.g., 'https://mygame.com' */
|
|
203
|
+
realm: string;
|
|
204
|
+
/** Return URL after Steam authentication */
|
|
205
|
+
returnUrl: string;
|
|
206
|
+
/**
|
|
207
|
+
* Backend endpoint to validate Steam OpenID response.
|
|
208
|
+
* Steam validation MUST be done server-side.
|
|
209
|
+
*/
|
|
210
|
+
validationEndpoint: string;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phalanx Client Library
|
|
3
|
+
*
|
|
4
|
+
* Client-side library for connecting to Phalanx Engine servers.
|
|
5
|
+
* Provides a type-safe API for matchmaking, game synchronization,
|
|
6
|
+
* command submission, and reconnection handling.
|
|
7
|
+
*
|
|
8
|
+
* ## Quick Start
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { PhalanxClient } from '@phalanx-engine/client';
|
|
12
|
+
*
|
|
13
|
+
* // Create and connect
|
|
14
|
+
* const client = await PhalanxClient.create({
|
|
15
|
+
* serverUrl: 'http://localhost:3000',
|
|
16
|
+
* playerId: 'player-123',
|
|
17
|
+
* username: 'MyPlayer',
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Matchmaking
|
|
21
|
+
* client.onMatchFound((data) => console.log('Match found!', data));
|
|
22
|
+
* client.joinQueue();
|
|
23
|
+
*
|
|
24
|
+
* // Game loop - just two callbacks!
|
|
25
|
+
* client.onTick((tick, commands) => {
|
|
26
|
+
* // Process commands from all players
|
|
27
|
+
* for (const [playerId, playerCommands] of Object.entries(commands.commands)) {
|
|
28
|
+
* for (const cmd of playerCommands) {
|
|
29
|
+
* handleCommand(playerId, cmd);
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* // Run simulation
|
|
33
|
+
* world.simulate();
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* client.onFrame((alpha, dt) => {
|
|
37
|
+
* // Interpolate positions for smooth rendering
|
|
38
|
+
* interpolate(alpha);
|
|
39
|
+
* // Render
|
|
40
|
+
* scene.render();
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Send commands
|
|
44
|
+
* client.sendCommand('move', { targetX: 10, targetZ: 20 });
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @packageDocumentation
|
|
48
|
+
*/
|
|
49
|
+
export { PhalanxClient } from './PhalanxClient.js';
|
|
50
|
+
export { EventEmitter } from './EventEmitter.js';
|
|
51
|
+
export { RenderLoop } from './RenderLoop.js';
|
|
52
|
+
export type { RenderLoopConfig, CommandFlushCallback } from './RenderLoop.js';
|
|
53
|
+
export { SocketManager } from './SocketManager.js';
|
|
54
|
+
export type { SocketManagerConfig, SocketManagerCallbacks, } from './SocketManager.js';
|
|
55
|
+
export { DeterministicRandom } from './DeterministicRandom.js';
|
|
56
|
+
export { FP, FPVector2, FPVector3, FixedPoint } from './FixedMath.js';
|
|
57
|
+
export type { FPVector2Interface, FPVector3Interface } from './FixedMath.js';
|
|
58
|
+
export { StateHasher } from './StateHasher.js';
|
|
59
|
+
export { DesyncDetector } from './DesyncDetector.js';
|
|
60
|
+
export type { DesyncConfig, DesyncEvent } from './DesyncDetector.js';
|
|
61
|
+
export { RoomRecoveryController, RoomPersistence, isMobileBrowser, pickMobileFriendlyTransports, loadOrCreateGuestPlayerId, MemoryKeyValueStorage, defaultKeyValueStorage, getRecoverTimeoutMs, DEFAULT_RECOVER_TIMEOUT_BUDGET, armBrowserLifecycle, } from './recovery/index.js';
|
|
62
|
+
export type { RoomRecoveryConfig, RoomRecoveryStatusEvent, RoomRecoveryPhase, RoomTerminatedEvent, RoomRecoveryControllerEvents, RecoveryClientPort, RoomPersistenceConfig, PersistedRoom, RoomRole, KeyValueStorage, RecoverTimeoutBudget, BrowserLifecycleHandle, BrowserLifecycleHandlers, } from './recovery/index.js';
|
|
63
|
+
export { AuthManager } from './auth/AuthManager.js';
|
|
64
|
+
export type { AuthManagerConfig } from './auth/AuthManager.js';
|
|
65
|
+
export { GoogleOAuthAdapter } from './auth/adapters/GoogleOAuthAdapter.js';
|
|
66
|
+
export { LocalStorageAdapter, MemoryStorageAdapter } from './auth/storage.js';
|
|
67
|
+
export type { AuthStorage } from './auth/storage.js';
|
|
68
|
+
export type { AuthAdapter, AuthResult, AuthState, AuthUser, AuthError, CallbackParams, LoginOptions, GoogleOAuthConfig, DiscordOAuthConfig, SteamAuthConfig, StoredAuthData, } from './auth/types.js';
|
|
69
|
+
export type { PhalanxClientConfig, PhalanxAuthConfig, PhalanxRoomRecoveryConfig, PauseConfig, SocketTransport, PhalanxAuthState, PhalanxAuthUser, PlayerCommand, CommandsBatch, TickHandler, FrameHandler, Unsubscribe, PauseHandler, MatchPlayerInfo, MatchFoundEvent, CountdownEvent, GameStartEvent, MatchEndEvent, GamePausedEvent, GameResumedEvent, TickSyncEvent, CommandsBatchEvent, QueueStatusEvent, PlayerDisconnectedEvent, PlayerReconnectedEvent, PlayerReadyEvent, ReconnectStateEvent, TickCommandsHistory, ReconnectStatusEvent, SubmitCommandsAck, PhalanxError, ConnectionState, ClientState, HashComparisonEvent, RoomCreatedEvent, RoomErrorEvent, RoomExpiredEvent, RoomCancelledEvent, RoomRecoveredEvent, PhalanxClientEvents, } from './types.js';
|
|
70
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAMH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG9E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EACV,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG7E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMrE,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,8BAA8B,EAC9B,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,4BAA4B,EAC5B,kBAAkB,EAClB,qBAAqB,EACrB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAO7B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAG3E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,YAAY,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,EACR,SAAS,EACT,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,cAAc,GACf,MAAM,iBAAiB,CAAC;AAMzB,YAAY,EAEV,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EACzB,WAAW,EACX,eAAe,EAGf,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,aAAa,EAGb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EAGZ,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,EACd,aAAa,EAGb,eAAe,EACf,gBAAgB,EAGhB,aAAa,EACb,kBAAkB,EAGlB,gBAAgB,EAGhB,uBAAuB,EACvB,sBAAsB,EACtB,gBAAgB,EAGhB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EAGpB,iBAAiB,EAGjB,YAAY,EAGZ,eAAe,EACf,WAAW,EAGX,mBAAmB,EAGnB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAGlB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phalanx Client Library
|
|
3
|
+
*
|
|
4
|
+
* Client-side library for connecting to Phalanx Engine servers.
|
|
5
|
+
* Provides a type-safe API for matchmaking, game synchronization,
|
|
6
|
+
* command submission, and reconnection handling.
|
|
7
|
+
*
|
|
8
|
+
* ## Quick Start
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { PhalanxClient } from '@phalanx-engine/client';
|
|
12
|
+
*
|
|
13
|
+
* // Create and connect
|
|
14
|
+
* const client = await PhalanxClient.create({
|
|
15
|
+
* serverUrl: 'http://localhost:3000',
|
|
16
|
+
* playerId: 'player-123',
|
|
17
|
+
* username: 'MyPlayer',
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Matchmaking
|
|
21
|
+
* client.onMatchFound((data) => console.log('Match found!', data));
|
|
22
|
+
* client.joinQueue();
|
|
23
|
+
*
|
|
24
|
+
* // Game loop - just two callbacks!
|
|
25
|
+
* client.onTick((tick, commands) => {
|
|
26
|
+
* // Process commands from all players
|
|
27
|
+
* for (const [playerId, playerCommands] of Object.entries(commands.commands)) {
|
|
28
|
+
* for (const cmd of playerCommands) {
|
|
29
|
+
* handleCommand(playerId, cmd);
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* // Run simulation
|
|
33
|
+
* world.simulate();
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* client.onFrame((alpha, dt) => {
|
|
37
|
+
* // Interpolate positions for smooth rendering
|
|
38
|
+
* interpolate(alpha);
|
|
39
|
+
* // Render
|
|
40
|
+
* scene.render();
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* // Send commands
|
|
44
|
+
* client.sendCommand('move', { targetX: 10, targetZ: 20 });
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @packageDocumentation
|
|
48
|
+
*/
|
|
49
|
+
// ============================================
|
|
50
|
+
// Main Client
|
|
51
|
+
// ============================================
|
|
52
|
+
export { PhalanxClient } from './PhalanxClient.js';
|
|
53
|
+
// ============================================
|
|
54
|
+
// Utilities
|
|
55
|
+
// ============================================
|
|
56
|
+
// Event emitter (for building custom clients or extensions)
|
|
57
|
+
export { EventEmitter } from './EventEmitter.js';
|
|
58
|
+
// Render loop (for custom rendering setups)
|
|
59
|
+
export { RenderLoop } from './RenderLoop.js';
|
|
60
|
+
// Socket manager (for custom networking setups)
|
|
61
|
+
export { SocketManager } from './SocketManager.js';
|
|
62
|
+
// Deterministic random number generator
|
|
63
|
+
export { DeterministicRandom } from './DeterministicRandom.js';
|
|
64
|
+
// Fixed-point math (deterministic across all platforms)
|
|
65
|
+
export { FP, FPVector2, FPVector3, FixedPoint } from './FixedMath.js';
|
|
66
|
+
// State hasher utility for desync detection
|
|
67
|
+
export { StateHasher } from './StateHasher.js';
|
|
68
|
+
// Desync detector (advanced usage - for custom desync handling)
|
|
69
|
+
export { DesyncDetector } from './DesyncDetector.js';
|
|
70
|
+
// ============================================
|
|
71
|
+
// Room Recovery (mobile-friendly reconnection)
|
|
72
|
+
// ============================================
|
|
73
|
+
export { RoomRecoveryController, RoomPersistence, isMobileBrowser, pickMobileFriendlyTransports, loadOrCreateGuestPlayerId, MemoryKeyValueStorage, defaultKeyValueStorage, getRecoverTimeoutMs, DEFAULT_RECOVER_TIMEOUT_BUDGET, armBrowserLifecycle, } from './recovery/index.js';
|
|
74
|
+
// ============================================
|
|
75
|
+
// Authentication
|
|
76
|
+
// ============================================
|
|
77
|
+
// Auth manager (managed OAuth for Google, Discord, Steam)
|
|
78
|
+
export { AuthManager } from './auth/AuthManager.js';
|
|
79
|
+
// Google OAuth adapter
|
|
80
|
+
export { GoogleOAuthAdapter } from './auth/adapters/GoogleOAuthAdapter.js';
|
|
81
|
+
// Storage adapters
|
|
82
|
+
export { LocalStorageAdapter, MemoryStorageAdapter } from './auth/storage.js';
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,+CAA+C;AAC/C,cAAc;AACd,+CAA+C;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,+CAA+C;AAC/C,YAAY;AACZ,+CAA+C;AAE/C,4DAA4D;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,4CAA4C;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,gDAAgD;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOnD,wCAAwC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,wDAAwD;AACxD,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGtE,4CAA4C;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,gEAAgE;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,+CAA+C;AAC/C,+CAA+C;AAC/C,+CAA+C;AAE/C,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,8BAA8B,EAC9B,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAiB7B,+CAA+C;AAC/C,iBAAiB;AACjB,+CAA+C;AAE/C,0DAA0D;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,mBAAmB;AACnB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserLifecycle — wires the small bag of DOM listeners every
|
|
3
|
+
* mobile-friendly recovery flow needs:
|
|
4
|
+
*
|
|
5
|
+
* - `visibilitychange` — fires when the user returns to the tab from
|
|
6
|
+
* another app or another tab (most reliable signal on Android).
|
|
7
|
+
* - `pageshow` — fires when iOS Safari restores the page from
|
|
8
|
+
* bfcache (in some cases `visibilitychange` does not fire).
|
|
9
|
+
* - `online` — the OS reports the network came back; useful for the
|
|
10
|
+
* "wait for network to stabilize" portion of recovery.
|
|
11
|
+
*
|
|
12
|
+
* Idempotent and SSR-safe (no-ops when `document`/`window` are
|
|
13
|
+
* unavailable). Returned object exposes `dispose()` for clean unwiring.
|
|
14
|
+
*/
|
|
15
|
+
export interface BrowserLifecycleHandle {
|
|
16
|
+
dispose(): void;
|
|
17
|
+
}
|
|
18
|
+
export interface BrowserLifecycleHandlers {
|
|
19
|
+
/** Called on visibilitychange→visible and on pageshow. */
|
|
20
|
+
onVisible?: () => void;
|
|
21
|
+
/** Called on `window` `online` event. */
|
|
22
|
+
onOnline?: () => void;
|
|
23
|
+
}
|
|
24
|
+
export declare function armBrowserLifecycle(handlers: BrowserLifecycleHandlers): BrowserLifecycleHandle;
|
|
25
|
+
/** True if the OS reports the device is currently online. */
|
|
26
|
+
export declare function isOnline(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve when the next `online` event fires, or after `timeoutMs`,
|
|
29
|
+
* whichever comes first. Used to gate recovery attempts behind a fresh
|
|
30
|
+
* network signal so we don't burn retries while the radio is still off.
|
|
31
|
+
*/
|
|
32
|
+
export declare function waitForOnlineEvent(timeoutMs: number): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=BrowserLifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserLifecycle.d.ts","sourceRoot":"","sources":["../../src/recovery/BrowserLifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,wBAAwB,GACjC,sBAAsB,CAmCxB;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,IAAI,OAAO,CAGlC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function armBrowserLifecycle(handlers) {
|
|
2
|
+
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
|
3
|
+
return { dispose: () => { } };
|
|
4
|
+
}
|
|
5
|
+
const visibilityHandler = () => {
|
|
6
|
+
if (document.visibilityState !== 'visible')
|
|
7
|
+
return;
|
|
8
|
+
handlers.onVisible?.();
|
|
9
|
+
};
|
|
10
|
+
const pageShowHandler = () => {
|
|
11
|
+
handlers.onVisible?.();
|
|
12
|
+
};
|
|
13
|
+
const onlineHandler = () => {
|
|
14
|
+
handlers.onOnline?.();
|
|
15
|
+
};
|
|
16
|
+
if (handlers.onVisible) {
|
|
17
|
+
document.addEventListener('visibilitychange', visibilityHandler);
|
|
18
|
+
window.addEventListener('pageshow', pageShowHandler);
|
|
19
|
+
}
|
|
20
|
+
if (handlers.onOnline) {
|
|
21
|
+
window.addEventListener('online', onlineHandler);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
dispose() {
|
|
25
|
+
if (handlers.onVisible) {
|
|
26
|
+
document.removeEventListener('visibilitychange', visibilityHandler);
|
|
27
|
+
window.removeEventListener('pageshow', pageShowHandler);
|
|
28
|
+
}
|
|
29
|
+
if (handlers.onOnline) {
|
|
30
|
+
window.removeEventListener('online', onlineHandler);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** True if the OS reports the device is currently online. */
|
|
36
|
+
export function isOnline() {
|
|
37
|
+
if (typeof navigator === 'undefined')
|
|
38
|
+
return true;
|
|
39
|
+
return navigator.onLine !== false;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve when the next `online` event fires, or after `timeoutMs`,
|
|
43
|
+
* whichever comes first. Used to gate recovery attempts behind a fresh
|
|
44
|
+
* network signal so we don't burn retries while the radio is still off.
|
|
45
|
+
*/
|
|
46
|
+
export function waitForOnlineEvent(timeoutMs) {
|
|
47
|
+
if (typeof window === 'undefined')
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
const onOnline = () => {
|
|
51
|
+
window.removeEventListener('online', onOnline);
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
resolve();
|
|
54
|
+
};
|
|
55
|
+
const timer = setTimeout(() => {
|
|
56
|
+
window.removeEventListener('online', onOnline);
|
|
57
|
+
resolve();
|
|
58
|
+
}, timeoutMs);
|
|
59
|
+
window.addEventListener('online', onOnline);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=BrowserLifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserLifecycle.js","sourceRoot":"","sources":["../../src/recovery/BrowserLifecycle.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,mBAAmB,CACjC,QAAkC;IAElC,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACrE,OAAO,EAAE,OAAO,EAAE,GAAS,EAAE,GAAE,CAAC,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,iBAAiB,GAAG,GAAS,EAAE;QACnC,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS;YAAE,OAAO;QACnD,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,eAAe,GAAG,GAAS,EAAE;QACjC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC;IACxB,CAAC,CAAC;IAEF,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QACvB,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;QACjE,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACnD,CAAC;IAED,OAAO;QACL,OAAO;YACL,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACvB,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;gBACpE,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,QAAQ;IACtB,IAAI,OAAO,SAAS,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAClD,OAAO,SAAS,CAAC,MAAM,KAAK,KAAK,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5D,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/C,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type KeyValueStorage } from './KeyValueStorage.js';
|
|
2
|
+
/**
|
|
3
|
+
* Load (or generate-and-persist) a stable guest player id.
|
|
4
|
+
*
|
|
5
|
+
* `PhalanxClient` generates a fresh id in its constructor when none is
|
|
6
|
+
* supplied — that id changes on every page reload, which silently
|
|
7
|
+
* breaks any server-side state keyed by playerId, most importantly the
|
|
8
|
+
* host record inside a private room. Persisting the guest id in
|
|
9
|
+
* localStorage lets cold-start recovery succeed for unauthenticated
|
|
10
|
+
* users.
|
|
11
|
+
*
|
|
12
|
+
* Falls back to an in-memory id when storage is unavailable (Safari
|
|
13
|
+
* private mode etc.) — recovery won't work in that environment, but
|
|
14
|
+
* regular play still does.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadOrCreateGuestPlayerId(storageKey: string, storage?: KeyValueStorage): string;
|
|
17
|
+
//# sourceMappingURL=GuestPlayerIdStore.d.ts.map
|