playkit-sdk 1.2.11 → 1.2.13
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/dist/playkit-sdk.cjs.js +90 -66
- package/dist/playkit-sdk.cjs.js.map +1 -1
- package/dist/playkit-sdk.d.ts +21 -3
- package/dist/playkit-sdk.esm.js +90 -66
- package/dist/playkit-sdk.esm.js.map +1 -1
- package/dist/playkit-sdk.umd.js +90 -66
- package/dist/playkit-sdk.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/playkit-sdk.umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* playkit-sdk v1.2.
|
|
2
|
+
* playkit-sdk v1.2.13
|
|
3
3
|
* PlayKit SDK for JavaScript
|
|
4
4
|
* @license SEE LICENSE IN LICENSE
|
|
5
5
|
*/
|
|
@@ -2398,53 +2398,56 @@
|
|
|
2398
2398
|
*
|
|
2399
2399
|
* @param options - Flow options
|
|
2400
2400
|
* @returns Promise resolving to DeviceAuthResult with tokens
|
|
2401
|
-
* @throws PlayKitError if a flow is already in progress
|
|
2402
2401
|
*/
|
|
2403
2402
|
async startFlow(options = {}) {
|
|
2404
|
-
//
|
|
2405
|
-
if (DeviceAuthFlowManager.
|
|
2406
|
-
this.logger.
|
|
2407
|
-
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2403
|
+
// If a flow is already in progress, return the shared promise so all callers get the same result
|
|
2404
|
+
if (DeviceAuthFlowManager.currentFlowPromise) {
|
|
2405
|
+
this.logger.debug('Device auth flow already in progress, waiting for existing flow');
|
|
2406
|
+
return DeviceAuthFlowManager.currentFlowPromise;
|
|
2407
|
+
}
|
|
2408
|
+
// Store the flow promise so subsequent calls can await the same result
|
|
2409
|
+
const flowPromise = this.executeFlow(options);
|
|
2410
|
+
DeviceAuthFlowManager.currentFlowPromise = flowPromise;
|
|
2410
2411
|
DeviceAuthFlowManager.activeInstance = this;
|
|
2412
|
+
try {
|
|
2413
|
+
return await flowPromise;
|
|
2414
|
+
}
|
|
2415
|
+
finally {
|
|
2416
|
+
// Clean up static state when flow completes (success or failure)
|
|
2417
|
+
DeviceAuthFlowManager.currentFlowPromise = null;
|
|
2418
|
+
DeviceAuthFlowManager.activeInstance = null;
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
/**
|
|
2422
|
+
* Internal method that executes the actual device auth flow
|
|
2423
|
+
* @private
|
|
2424
|
+
*/
|
|
2425
|
+
async executeFlow(options = {}) {
|
|
2411
2426
|
this.aborted = false;
|
|
2412
2427
|
this.currentLanguage = this.detectLanguage();
|
|
2413
2428
|
const scope = options.scope || 'player:play';
|
|
2414
2429
|
const openBrowser = options.openBrowser || this.defaultOpenBrowser.bind(this);
|
|
2415
|
-
// Helper to reset static flags when flow completes early (before polling)
|
|
2416
|
-
const resetFlowStateEarly = () => {
|
|
2417
|
-
DeviceAuthFlowManager.isFlowInProgress = false;
|
|
2418
|
-
DeviceAuthFlowManager.activeInstance = null;
|
|
2419
|
-
};
|
|
2420
2430
|
// Generate PKCE parameters (outside try block so codeVerifier is accessible for polling)
|
|
2421
2431
|
const codeVerifier = this.generateCodeVerifier();
|
|
2422
2432
|
const codeChallenge = await this.generateCodeChallenge(codeVerifier);
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
});
|
|
2438
|
-
|
|
2439
|
-
const error = await initResponse.json().catch(() => ({ error_description: 'Failed to initiate device auth' }));
|
|
2440
|
-
throw new PlayKitError(error.error_description || 'Failed to initiate device auth', error.error || 'INIT_FAILED', initResponse.status);
|
|
2441
|
-
}
|
|
2442
|
-
initData = await initResponse.json();
|
|
2443
|
-
}
|
|
2444
|
-
catch (err) {
|
|
2445
|
-
resetFlowStateEarly();
|
|
2446
|
-
throw err;
|
|
2433
|
+
// Step 1: Initiate device auth session
|
|
2434
|
+
const initResponse = await fetch(`${this.baseURL}/api/device-auth/initiate`, {
|
|
2435
|
+
method: 'POST',
|
|
2436
|
+
headers: {
|
|
2437
|
+
'Content-Type': 'application/json',
|
|
2438
|
+
},
|
|
2439
|
+
body: JSON.stringify({
|
|
2440
|
+
game_id: this.gameId,
|
|
2441
|
+
code_challenge: codeChallenge,
|
|
2442
|
+
code_challenge_method: 'S256',
|
|
2443
|
+
scope,
|
|
2444
|
+
}),
|
|
2445
|
+
});
|
|
2446
|
+
if (!initResponse.ok) {
|
|
2447
|
+
const error = await initResponse.json().catch(() => ({ error_description: 'Failed to initiate device auth' }));
|
|
2448
|
+
throw new PlayKitError(error.error_description || 'Failed to initiate device auth', error.error || 'INIT_FAILED', initResponse.status);
|
|
2447
2449
|
}
|
|
2450
|
+
const initData = await initResponse.json();
|
|
2448
2451
|
const { session_id, auth_url, poll_interval, expires_in, game } = initData;
|
|
2449
2452
|
// Update poll interval from server
|
|
2450
2453
|
if (poll_interval) {
|
|
@@ -2476,7 +2479,6 @@
|
|
|
2476
2479
|
}
|
|
2477
2480
|
catch (err) {
|
|
2478
2481
|
this.closeModal();
|
|
2479
|
-
resetFlowStateEarly();
|
|
2480
2482
|
throw err;
|
|
2481
2483
|
}
|
|
2482
2484
|
// User clicked login - open browser (in user click context, won't be blocked)
|
|
@@ -2488,23 +2490,16 @@
|
|
|
2488
2490
|
}
|
|
2489
2491
|
// Step 3: Poll for authorization
|
|
2490
2492
|
const expiresAt = Date.now() + (expires_in || 600) * 1000;
|
|
2491
|
-
// Helper to reset static flags when flow completes
|
|
2492
|
-
const resetFlowState = () => {
|
|
2493
|
-
DeviceAuthFlowManager.isFlowInProgress = false;
|
|
2494
|
-
DeviceAuthFlowManager.activeInstance = null;
|
|
2495
|
-
};
|
|
2496
2493
|
return new Promise((resolve, reject) => {
|
|
2497
2494
|
const poll = async () => {
|
|
2498
2495
|
if (this.aborted) {
|
|
2499
2496
|
this.closeModal();
|
|
2500
|
-
resetFlowState();
|
|
2501
2497
|
reject(new PlayKitError('Device auth flow was cancelled', 'CANCELLED'));
|
|
2502
2498
|
return;
|
|
2503
2499
|
}
|
|
2504
2500
|
// Check if session expired
|
|
2505
2501
|
if (Date.now() >= expiresAt) {
|
|
2506
2502
|
this.showModalError('expired', () => { });
|
|
2507
|
-
resetFlowState();
|
|
2508
2503
|
reject(new PlayKitError('Device auth session expired', 'EXPIRED'));
|
|
2509
2504
|
return;
|
|
2510
2505
|
}
|
|
@@ -2532,7 +2527,6 @@
|
|
|
2532
2527
|
}
|
|
2533
2528
|
this.emit('poll_status', 'authorized');
|
|
2534
2529
|
this.emit('authenticated', pollData);
|
|
2535
|
-
resetFlowState();
|
|
2536
2530
|
resolve({
|
|
2537
2531
|
access_token: pollData.access_token,
|
|
2538
2532
|
token_type: pollData.token_type,
|
|
@@ -2561,7 +2555,6 @@
|
|
|
2561
2555
|
options.onPollStatus('denied');
|
|
2562
2556
|
}
|
|
2563
2557
|
this.emit('poll_status', 'denied');
|
|
2564
|
-
resetFlowState();
|
|
2565
2558
|
reject(new PlayKitError(pollData.error_description || 'User denied authorization', 'ACCESS_DENIED'));
|
|
2566
2559
|
}
|
|
2567
2560
|
else if (error === 'expired_token') {
|
|
@@ -2570,12 +2563,10 @@
|
|
|
2570
2563
|
options.onPollStatus('expired');
|
|
2571
2564
|
}
|
|
2572
2565
|
this.emit('poll_status', 'expired');
|
|
2573
|
-
resetFlowState();
|
|
2574
2566
|
reject(new PlayKitError(pollData.error_description || 'Session expired', 'EXPIRED'));
|
|
2575
2567
|
}
|
|
2576
2568
|
else {
|
|
2577
2569
|
this.showModalError('failed', () => { });
|
|
2578
|
-
resetFlowState();
|
|
2579
2570
|
reject(new PlayKitError(pollData.error_description || 'Device auth failed', error || 'POLL_FAILED', pollResponse.status));
|
|
2580
2571
|
}
|
|
2581
2572
|
}
|
|
@@ -2600,11 +2591,6 @@
|
|
|
2600
2591
|
clearTimeout(this.pollTimeoutId);
|
|
2601
2592
|
this.pollTimeoutId = null;
|
|
2602
2593
|
}
|
|
2603
|
-
// Reset static flags if this is the active instance
|
|
2604
|
-
if (DeviceAuthFlowManager.activeInstance === this) {
|
|
2605
|
-
DeviceAuthFlowManager.isFlowInProgress = false;
|
|
2606
|
-
DeviceAuthFlowManager.activeInstance = null;
|
|
2607
|
-
}
|
|
2608
2594
|
this.emit('cancelled');
|
|
2609
2595
|
}
|
|
2610
2596
|
/**
|
|
@@ -2619,7 +2605,7 @@
|
|
|
2619
2605
|
* Check if a device auth flow is currently in progress (static method)
|
|
2620
2606
|
*/
|
|
2621
2607
|
static isInProgress() {
|
|
2622
|
-
return DeviceAuthFlowManager.
|
|
2608
|
+
return DeviceAuthFlowManager.currentFlowPromise !== null;
|
|
2623
2609
|
}
|
|
2624
2610
|
/**
|
|
2625
2611
|
* Initiate device auth without opening browser or showing UI.
|
|
@@ -2770,8 +2756,8 @@
|
|
|
2770
2756
|
});
|
|
2771
2757
|
}
|
|
2772
2758
|
}
|
|
2773
|
-
/**
|
|
2774
|
-
DeviceAuthFlowManager.
|
|
2759
|
+
/** Shared promise for the current flow - allows multiple callers to await the same result */
|
|
2760
|
+
DeviceAuthFlowManager.currentFlowPromise = null;
|
|
2775
2761
|
/** Reference to the currently active instance */
|
|
2776
2762
|
DeviceAuthFlowManager.activeInstance = null;
|
|
2777
2763
|
|
|
@@ -2789,6 +2775,10 @@
|
|
|
2789
2775
|
this.authFlowManager = null;
|
|
2790
2776
|
this.deviceAuthFlowManager = null;
|
|
2791
2777
|
this.logger = Logger.getLogger('AuthManager');
|
|
2778
|
+
/** Shared promise for current device auth flow - allows multiple callers to await the same result */
|
|
2779
|
+
this.currentDeviceAuthFlowPromise = null;
|
|
2780
|
+
/** Shared promise for current auth flow (startAuthFlow) - allows multiple callers to await the same result */
|
|
2781
|
+
this.currentAuthFlowPromise = null;
|
|
2792
2782
|
this.config = config;
|
|
2793
2783
|
// Create TokenStorage with appropriate mode for server vs browser environment
|
|
2794
2784
|
this.storage = new TokenStorage({
|
|
@@ -2897,12 +2887,27 @@
|
|
|
2897
2887
|
* @deprecated 'headless' authentication is deprecated and will be removed in v2.0. Use 'device' instead.
|
|
2898
2888
|
*/
|
|
2899
2889
|
async startAuthFlow(authMethod = 'device') {
|
|
2900
|
-
|
|
2901
|
-
if (this.
|
|
2902
|
-
|
|
2903
|
-
this.
|
|
2904
|
-
|
|
2890
|
+
// If a flow is already in progress, return the shared promise so all callers await the same result
|
|
2891
|
+
if (this.currentAuthFlowPromise) {
|
|
2892
|
+
this.logger.debug('Auth flow already in progress, waiting for existing flow');
|
|
2893
|
+
return this.currentAuthFlowPromise;
|
|
2894
|
+
}
|
|
2895
|
+
// Store the flow promise so subsequent calls can await the same result
|
|
2896
|
+
const flowPromise = this.executeAuthFlow(authMethod);
|
|
2897
|
+
this.currentAuthFlowPromise = flowPromise;
|
|
2898
|
+
try {
|
|
2899
|
+
return await flowPromise;
|
|
2900
|
+
}
|
|
2901
|
+
finally {
|
|
2902
|
+
this.currentAuthFlowPromise = null;
|
|
2905
2903
|
}
|
|
2904
|
+
}
|
|
2905
|
+
/**
|
|
2906
|
+
* Internal method that executes the actual auth flow
|
|
2907
|
+
* @private
|
|
2908
|
+
*/
|
|
2909
|
+
async executeAuthFlow(authMethod = 'device') {
|
|
2910
|
+
var _a, _b;
|
|
2906
2911
|
// Deprecation warning for headless auth
|
|
2907
2912
|
if (authMethod === 'headless') {
|
|
2908
2913
|
this.logger.warn('"headless" authentication is deprecated and will be removed in v2.0. ' +
|
|
@@ -3155,10 +3160,27 @@
|
|
|
3155
3160
|
* ```
|
|
3156
3161
|
*/
|
|
3157
3162
|
async startDeviceAuthFlow(options = {}) {
|
|
3158
|
-
|
|
3159
|
-
if (this.
|
|
3160
|
-
|
|
3163
|
+
// If a flow is already in progress, return the shared promise so all callers get the same result
|
|
3164
|
+
if (this.currentDeviceAuthFlowPromise) {
|
|
3165
|
+
this.logger.debug('Device auth flow already in progress, waiting for existing flow');
|
|
3166
|
+
return this.currentDeviceAuthFlowPromise;
|
|
3167
|
+
}
|
|
3168
|
+
// Store the flow promise so subsequent calls can await the same result
|
|
3169
|
+
const flowPromise = this.executeDeviceAuthFlow(options);
|
|
3170
|
+
this.currentDeviceAuthFlowPromise = flowPromise;
|
|
3171
|
+
try {
|
|
3172
|
+
return await flowPromise;
|
|
3161
3173
|
}
|
|
3174
|
+
finally {
|
|
3175
|
+
this.currentDeviceAuthFlowPromise = null;
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
/**
|
|
3179
|
+
* Internal method that executes the actual device auth flow
|
|
3180
|
+
* @private
|
|
3181
|
+
*/
|
|
3182
|
+
async executeDeviceAuthFlow(options = {}) {
|
|
3183
|
+
var _a;
|
|
3162
3184
|
try {
|
|
3163
3185
|
this.deviceAuthFlowManager = new DeviceAuthFlowManager(this.baseURL, this.config.gameId);
|
|
3164
3186
|
const result = await this.deviceAuthFlowManager.startFlow(options);
|
|
@@ -3211,8 +3233,10 @@
|
|
|
3211
3233
|
* ```
|
|
3212
3234
|
*/
|
|
3213
3235
|
async initiateDeviceAuth(scope = 'player:play') {
|
|
3236
|
+
// If there's an existing manager, clean it up first (allows restarting flow)
|
|
3214
3237
|
if (this.deviceAuthFlowManager) {
|
|
3215
|
-
|
|
3238
|
+
this.logger.debug('Cleaning up existing device auth manager before initiating new flow');
|
|
3239
|
+
this.deviceAuthFlowManager.destroy();
|
|
3216
3240
|
}
|
|
3217
3241
|
this.deviceAuthFlowManager = new DeviceAuthFlowManager(this.baseURL, this.config.gameId);
|
|
3218
3242
|
return this.deviceAuthFlowManager.initiateAuth(scope);
|