@xiboplayer/utils 0.5.20 → 0.6.1
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/package.json +2 -2
- package/src/config.js +42 -0
- package/src/fetch-retry.js +11 -0
- package/src/index.d.ts +12 -0
- package/src/index.js +25 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiboplayer/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Shared utilities for Xibo Player packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"./config": "./src/config.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@xiboplayer/crypto": "0.
|
|
15
|
+
"@xiboplayer/crypto": "0.6.1"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"vitest": "^2.0.0"
|
package/src/config.js
CHANGED
|
@@ -334,3 +334,45 @@ export class Config {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
export const config = new Config();
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Shell-only config keys common to ALL player shells (Electron, Chromium, etc.).
|
|
340
|
+
* These control the native shell window/process and must NOT be forwarded to the PWA.
|
|
341
|
+
*
|
|
342
|
+
* Each shell may have additional shell-specific keys — pass them as extraShellKeys
|
|
343
|
+
* to extractPwaConfig().
|
|
344
|
+
*
|
|
345
|
+
* Electron extras: autoLaunch
|
|
346
|
+
* Chromium extras: browser, extraBrowserFlags, relaxSslCerts
|
|
347
|
+
*/
|
|
348
|
+
export const SHELL_ONLY_KEYS = new Set([
|
|
349
|
+
'serverPort',
|
|
350
|
+
'kioskMode',
|
|
351
|
+
'fullscreen',
|
|
352
|
+
'hideMouseCursor',
|
|
353
|
+
'preventSleep',
|
|
354
|
+
'width',
|
|
355
|
+
'height',
|
|
356
|
+
]);
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Extract PWA config from a full shell config.json.
|
|
360
|
+
*
|
|
361
|
+
* Uses a deny-list approach: filters out shell-only keys, passes everything else.
|
|
362
|
+
* This is future-proof — new config.json fields automatically reach the PWA
|
|
363
|
+
* without code changes in each shell.
|
|
364
|
+
*
|
|
365
|
+
* @param {Object} config - Full config object from config.json
|
|
366
|
+
* @param {Iterable<string>} [extraShellKeys] - Additional shell-specific keys to exclude
|
|
367
|
+
* @returns {Object} Config to pass to the PWA (via proxy pwaConfig)
|
|
368
|
+
*/
|
|
369
|
+
export function extractPwaConfig(config, extraShellKeys) {
|
|
370
|
+
const exclude = new Set([...SHELL_ONLY_KEYS, ...(extraShellKeys || [])]);
|
|
371
|
+
const pwaConfig = {};
|
|
372
|
+
for (const [key, value] of Object.entries(config)) {
|
|
373
|
+
if (!exclude.has(key)) {
|
|
374
|
+
pwaConfig[key] = value;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return Object.keys(pwaConfig).length > 0 ? pwaConfig : undefined;
|
|
378
|
+
}
|
package/src/fetch-retry.js
CHANGED
|
@@ -83,6 +83,17 @@ export async function fetchWithRetry(url, options = {}, retryOptions = {}) {
|
|
|
83
83
|
lastResponse = response;
|
|
84
84
|
lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
85
85
|
lastError.status = response.status;
|
|
86
|
+
|
|
87
|
+
// Respect Retry-After on 503 Service Unavailable (e.g. CMS cache warming)
|
|
88
|
+
if (response.status === 503 && attempt < maxRetries) {
|
|
89
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
90
|
+
if (retryAfter) {
|
|
91
|
+
const delayMs = parseRetryAfter(retryAfter);
|
|
92
|
+
log.debug(`503 Service Unavailable, Retry-After: ${retryAfter} (${delayMs}ms)`);
|
|
93
|
+
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
86
97
|
} catch (error) {
|
|
87
98
|
// Network error — retryable
|
|
88
99
|
lastError = error;
|
package/src/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const VERSION: string;
|
|
2
|
+
export let PLAYER_API: string;
|
|
2
3
|
|
|
3
4
|
export interface Logger {
|
|
4
5
|
debug(...args: any[]): void;
|
|
@@ -56,6 +57,17 @@ export class Config {
|
|
|
56
57
|
|
|
57
58
|
export const config: Config;
|
|
58
59
|
|
|
60
|
+
export const SHELL_ONLY_KEYS: Set<string>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Extract PWA config from a full shell config.json.
|
|
64
|
+
* Filters out shell-only keys, passes everything else to the PWA.
|
|
65
|
+
*/
|
|
66
|
+
export function extractPwaConfig(
|
|
67
|
+
config: Record<string, any>,
|
|
68
|
+
extraShellKeys?: Iterable<string>
|
|
69
|
+
): Record<string, any> | undefined;
|
|
70
|
+
|
|
59
71
|
export function fetchWithRetry(
|
|
60
72
|
url: string,
|
|
61
73
|
options?: RequestInit,
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,30 @@ import pkg from '../package.json' with { type: 'json' };
|
|
|
3
3
|
export const VERSION = pkg.version;
|
|
4
4
|
export { createLogger, setLogLevel, getLogLevel, isDebug, applyCmsLogLevel, mapCmsLogLevel, registerLogSink, unregisterLogSink, LOG_LEVELS } from './logger.js';
|
|
5
5
|
export { EventEmitter } from './event-emitter.js';
|
|
6
|
-
|
|
6
|
+
import { config as _config } from './config.js';
|
|
7
|
+
export { config, SHELL_ONLY_KEYS, extractPwaConfig } from './config.js';
|
|
7
8
|
export { fetchWithRetry } from './fetch-retry.js';
|
|
8
9
|
export { CmsApiClient, CmsApiError } from './cms-api.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* CMS Player API base path — all media, dependencies, and widgets are served
|
|
13
|
+
* under this prefix.
|
|
14
|
+
*
|
|
15
|
+
* Default: '/api/v2/player' (standalone index.php endpoint).
|
|
16
|
+
* Override: set `playerApiBase` in config.json / localStorage, or call
|
|
17
|
+
* setPlayerApi('/new/path') before route registration (proxy).
|
|
18
|
+
*
|
|
19
|
+
* Browser: reads from config.data.playerApiBase at import time.
|
|
20
|
+
* Node: call setPlayerApi() before createProxyApp().
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_PLAYER_API = '/api/v2/player';
|
|
23
|
+
let _playerApi = _config.data?.playerApiBase || DEFAULT_PLAYER_API;
|
|
24
|
+
|
|
25
|
+
/** Current Player API base path (no trailing slash). */
|
|
26
|
+
export let PLAYER_API = _playerApi;
|
|
27
|
+
|
|
28
|
+
/** Override the Player API base path at runtime (call before route registration). */
|
|
29
|
+
export function setPlayerApi(base) {
|
|
30
|
+
_playerApi = base.replace(/\/+$/, '');
|
|
31
|
+
PLAYER_API = _playerApi;
|
|
32
|
+
}
|