@pixelume/sdk 0.4.0 → 0.6.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/CHANGELOG.md +62 -1
- package/README.md +97 -19
- package/dist/core/PixelumeClient.d.ts +10 -2
- package/dist/core/PixelumeClient.js +20 -2
- package/dist/core/PixelumeClient.js.map +1 -1
- package/dist/core/config.d.ts +18 -1
- package/dist/core/config.js +99 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/errors.d.ts +5 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/types.d.ts +78 -0
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/analytics/AnalyticsModule.d.ts +93 -0
- package/dist/modules/analytics/AnalyticsModule.js +461 -0
- package/dist/modules/analytics/AnalyticsModule.js.map +1 -0
- package/dist/modules/analytics/AnalyticsProvider.d.ts +51 -0
- package/dist/modules/analytics/AnalyticsProvider.js +23 -0
- package/dist/modules/analytics/AnalyticsProvider.js.map +1 -0
- package/dist/modules/analytics/PostHogAnalyticsProvider.d.ts +39 -0
- package/dist/modules/analytics/PostHogAnalyticsProvider.js +255 -0
- package/dist/modules/analytics/PostHogAnalyticsProvider.js.map +1 -0
- package/dist/modules/analytics/events.d.ts +30 -0
- package/dist/modules/analytics/events.js +153 -0
- package/dist/modules/analytics/events.js.map +1 -0
- package/dist/modules/auth/AuthModule.d.ts +20 -1
- package/dist/modules/auth/AuthModule.js +305 -21
- package/dist/modules/auth/AuthModule.js.map +1 -1
- package/dist/ui/widget.js +15 -5
- package/dist/ui/widget.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +4 -1
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CredentialsPolicy, FetchLike } from '../http/types.js';\nimport { PixelumeConfigError } from './errors.js';\nimport type { PixelumeClientOptions } from './types.js';\n\nexport const DEFAULT_API_URL = 'https://api.pixelume.com.br';\nexport const DEFAULT_AUTH_URL = 'https://auth.pixelume.com.br';\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_TIMEOUT_MS = 2_147_483_647; // setTimeout limit\nconst GAME_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/u;\nconst CLIENT_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/u;\nconst CREDENTIALS: readonly CredentialsPolicy[] = ['omit', 'same-origin', 'include'];\n\nexport interface ResolvedConfig {\n apiUrl: string;\n gameId: string | null;\n clientId: string | null;\n redirectUri: string | null;\n scope: 'profile' | 'profile saves';\n authUrl: string;\n restoreSession: boolean;\n allowInsecureHttp: boolean;\n browser: PixelumeClientOptions['browser'];\n timeoutMs: number;\n credentials: CredentialsPolicy;\n fetch: FetchLike;\n}\n\nexport function resolveConfig(options: PixelumeClientOptions): ResolvedConfig {\n const allowInsecureHttp = options.allowInsecureHttp === true;\n const gameId = options.gameId === undefined ? null : validateGameId(options.gameId);\n return {\n apiUrl: normalizeApiUrl(options.apiUrl ?? DEFAULT_API_URL, allowInsecureHttp),\n authUrl: normalizeOrigin(options.authUrl ?? DEFAULT_AUTH_URL, 'authUrl', allowInsecureHttp),\n gameId,\n clientId: options.clientId === undefined ? gameId : validateClientId(options.clientId),\n redirectUri: resolveRedirectUri(options, allowInsecureHttp),\n scope: validateScope(options.scope ?? 'profile'),\n restoreSession: validateBoolean('restoreSession', options.restoreSession ?? true),\n allowInsecureHttp,\n browser: options.browser,\n timeoutMs:\n options.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : validateTimeout(options.timeoutMs),\n credentials: validateCredentials(options.credentials ?? 'omit'),\n fetch: resolveFetch(options.fetch),\n };\n}\n\nfunction resolveRedirectUri(\n options: PixelumeClientOptions,\n allowInsecureHttp: boolean,\n): string | null {\n const value = options.redirectUri ?? defaultRedirectUri(options.browser);\n return value === null ? null : normalizeRedirectUri(value, allowInsecureHttp);\n}\n\nfunction validateScope(value: unknown): 'profile' | 'profile saves' {\n if (value !== 'profile' && value !== 'profile saves') {\n throw new PixelumeConfigError('scope must be \"profile\" or \"profile saves\"');\n }\n return value;\n}\n\nfunction validateBoolean(name: string, value: boolean): boolean {\n if (typeof value !== 'boolean') throw new PixelumeConfigError(`${name} must be a boolean`);\n return value;\n}\n\nfunction defaultRedirectUri(browser: PixelumeClientOptions['browser']): string | null {\n const location = Reflect.get(globalThis, 'location') as unknown;\n const current =\n browser?.currentUrl() ??\n (typeof location === 'object' && location !== null && 'href' in location\n ? String(location.href)\n : null);\n if (!current) return null;\n const url = new URL(current);\n return `${url.origin}/oauth/callback`;\n}\n\n/**\n * Accepts `https:` URLs, plus `http:` for loopback hosts (`localhost`, `*.localhost`, `127.0.0.0/8`,\n * `[::1]`). Other `http:` hosts (e.g. a LAN IP while testing on a phone) need `allowInsecureHttp`.\n */\nexport function normalizeApiUrl(value: string, allowInsecureHttp: boolean): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new PixelumeConfigError(\n 'apiUrl must be an absolute URL, e.g. https://api.pixelume.com.br',\n );\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new PixelumeConfigError('apiUrl must use https: (or http: for local development)');\n }\n if (url.protocol === 'http:' && !allowInsecureHttp && !isLoopbackHost(url.hostname)) {\n throw new PixelumeConfigError(\n 'apiUrl must use https:. Plain http: is only accepted for localhost unless allowInsecureHttp is set',\n );\n }\n if (url.username || url.password) {\n throw new PixelumeConfigError('apiUrl must not contain credentials');\n }\n if (url.search || url.hash) {\n throw new PixelumeConfigError('apiUrl must not contain a query string or fragment');\n }\n return `${url.origin}${url.pathname.replace(/\\/+$/u, '')}`;\n}\n\nfunction normalizeOrigin(value: string, name: string, allowInsecureHttp: boolean): string {\n const normalized = normalizeApiUrl(value, allowInsecureHttp);\n const url = new URL(normalized);\n if (url.pathname !== '/') {\n throw new PixelumeConfigError(`${name} must be an origin without a path`);\n }\n return url.origin;\n}\n\nexport function normalizeRedirectUri(value: string, allowInsecureHttp: boolean): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new PixelumeConfigError('redirectUri must be an absolute URL registered by the API');\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new PixelumeConfigError('redirectUri must use https: (or http: for local development)');\n }\n if (url.protocol === 'http:' && !allowInsecureHttp && !isLoopbackHost(url.hostname)) {\n throw new PixelumeConfigError('redirectUri must use https: outside localhost');\n }\n if (url.username || url.password || url.hash) {\n throw new PixelumeConfigError('redirectUri must not contain credentials or a fragment');\n }\n for (const key of ['code', 'state', 'error', 'error_description']) {\n if (url.searchParams.has(key)) {\n throw new PixelumeConfigError(\n `redirectUri must not contain the reserved query parameter \"${key}\"`,\n );\n }\n }\n return url.toString();\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n hostname === '[::1]' ||\n /^127(?:\\.\\d{1,3}){3}$/u.test(hostname)\n );\n}\n\n/**\n * Game identifiers are public, non-secret slugs (e.g. `rail-puzzle`): lowercase letters, digits\n * and inner hyphens, 1–64 characters. They identify a game, they never authorize anything.\n */\nexport function validateGameId(value: string): string {\n if (typeof value !== 'string' || !GAME_ID_PATTERN.test(value)) {\n throw new PixelumeConfigError(\n 'gameId must be a lowercase slug (a-z, 0-9 and inner hyphens, up to 64 characters)',\n );\n }\n return value;\n}\n\nexport function validateClientId(value: string): string {\n if (typeof value !== 'string' || !CLIENT_ID_PATTERN.test(value)) {\n throw new PixelumeConfigError(\n 'clientId must contain 1-128 letters, digits, dots, underscores or hyphens',\n );\n }\n return value;\n}\n\n/** For feature modules that need a game context (Cloud Saves). */\nexport function requireGameId(config: Pick<ResolvedConfig, 'gameId'>, feature: string): string {\n if (config.gameId === null) {\n throw new PixelumeConfigError(`${feature} requires the client to be created with a gameId`);\n }\n return config.gameId;\n}\n\nexport function validateTimeout(value: number): number {\n if (!Number.isInteger(value) || value <= 0 || value > MAX_TIMEOUT_MS) {\n throw new PixelumeConfigError('timeoutMs must be a positive integer number of milliseconds');\n }\n return value;\n}\n\nfunction validateCredentials(value: CredentialsPolicy): CredentialsPolicy {\n if (!CREDENTIALS.includes(value)) {\n throw new PixelumeConfigError(`credentials must be one of: ${CREDENTIALS.join(', ')}`);\n }\n return value;\n}\n\nfunction resolveFetch(custom: FetchLike | undefined): FetchLike {\n if (custom !== undefined) {\n if (typeof custom !== 'function') throw new PixelumeConfigError('fetch must be a function');\n return custom;\n }\n if (typeof globalThis.fetch !== 'function') {\n throw new PixelumeConfigError('No global fetch available; pass the fetch option');\n }\n // Looked up on each call so polyfills or test doubles installed later are honoured.\n return (input, init) => globalThis.fetch(input, init);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CredentialsPolicy, FetchLike } from '../http/types.js';\nimport { PixelumeConfigError } from './errors.js';\nimport type { PixelumeAnalyticsIssue, PixelumeClientOptions } from './types.js';\n\nexport const DEFAULT_API_URL = 'https://api.pixelume.com.br';\nexport const DEFAULT_AUTH_URL = 'https://auth.pixelume.com.br';\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_TIMEOUT_MS = 2_147_483_647; // setTimeout limit\nconst GAME_ID_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/u;\nconst CLIENT_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/u;\nconst CREDENTIALS: readonly CredentialsPolicy[] = ['omit', 'same-origin', 'include'];\nconst POSTHOG_PROJECT_TOKEN_PATTERN = /^phc_[A-Za-z0-9_-]{8,128}$/u;\nconst GAME_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,63}$/u;\n\n/** Validated analytics configuration. `null` in `ResolvedConfig` means \"no-op\". */\nexport interface ResolvedAnalyticsConfig {\n readonly provider: { readonly kind: 'posthog'; readonly token: string; readonly host: string };\n readonly gameId: string;\n readonly gameVersion: string | null;\n readonly rememberConsent: boolean;\n readonly onIssue: ((issue: PixelumeAnalyticsIssue) => void) | null;\n}\n\nexport interface ResolvedConfig {\n apiUrl: string;\n gameId: string | null;\n clientId: string | null;\n redirectUri: string | null;\n scope: 'profile' | 'profile saves';\n authUrl: string;\n restoreSession: boolean;\n /** `null` when cross-session restoration is disabled. */\n crossSessionRestore: { readonly maxAgeMs: number } | null;\n allowInsecureHttp: boolean;\n browser: PixelumeClientOptions['browser'];\n timeoutMs: number;\n credentials: CredentialsPolicy;\n fetch: FetchLike;\n analytics: ResolvedAnalyticsConfig | null;\n}\n\nexport function resolveConfig(options: PixelumeClientOptions): ResolvedConfig {\n const allowInsecureHttp = options.allowInsecureHttp === true;\n const gameId = options.gameId === undefined ? null : validateGameId(options.gameId);\n return {\n apiUrl: normalizeApiUrl(options.apiUrl ?? DEFAULT_API_URL, allowInsecureHttp),\n authUrl: normalizeOrigin(options.authUrl ?? DEFAULT_AUTH_URL, 'authUrl', allowInsecureHttp),\n gameId,\n clientId: options.clientId === undefined ? gameId : validateClientId(options.clientId),\n redirectUri: resolveRedirectUri(options, allowInsecureHttp),\n scope: validateScope(options.scope ?? 'profile'),\n restoreSession: validateBoolean('restoreSession', options.restoreSession ?? true),\n crossSessionRestore: resolveCrossSessionRestore(options.restoreAcrossSessions),\n allowInsecureHttp,\n browser: options.browser,\n timeoutMs:\n options.timeoutMs === undefined ? DEFAULT_TIMEOUT_MS : validateTimeout(options.timeoutMs),\n credentials: validateCredentials(options.credentials ?? 'omit'),\n fetch: resolveFetch(options.fetch),\n analytics: resolveAnalytics(options.analytics, gameId, allowInsecureHttp),\n };\n}\n\n/**\n * Missing configuration (no object, `enabled: false`, empty token or host) is a no-op, so a build\n * without the variables keeps working. A value that is present but wrong fails fast, like every\n * other option; a personal API key is always refused.\n */\nfunction resolveAnalytics(\n value: PixelumeClientOptions['analytics'],\n gameId: string | null,\n allowInsecureHttp: boolean,\n): ResolvedAnalyticsConfig | null {\n if (value === undefined) return null;\n // Validated at runtime: JavaScript callers may pass anything.\n const raw: unknown = value;\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new PixelumeConfigError('analytics must be an object');\n }\n const enabled = validateBoolean('analytics.enabled', value.enabled ?? true);\n const provider: unknown = value.provider ?? 'posthog';\n if (provider !== 'posthog') throw new PixelumeConfigError('analytics.provider must be \"posthog\"');\n const rememberConsent = validateBoolean(\n 'analytics.rememberConsent',\n value.rememberConsent ?? true,\n );\n const onIssue: unknown = value.onIssue;\n if (onIssue !== undefined && typeof onIssue !== 'function') {\n throw new PixelumeConfigError('analytics.onIssue must be a function');\n }\n // Like token and host, an empty value (build variable defined but blank) means \"not provided\".\n const rawGameVersion = optionalString('analytics.gameVersion', value.gameVersion);\n const gameVersion = rawGameVersion === null ? null : validateGameVersion(rawGameVersion);\n const posthog: unknown = value.posthog;\n if (posthog !== undefined && (typeof posthog !== 'object' || posthog === null)) {\n throw new PixelumeConfigError('analytics.posthog must be an object');\n }\n const token = optionalString('analytics.posthog.projectToken', value.posthog?.projectToken);\n const host = optionalString('analytics.posthog.host', value.posthog?.host);\n if (token !== null) validatePostHogToken(token);\n const normalizedHost = host === null ? null : normalizeAnalyticsHost(host, allowInsecureHttp);\n if (!enabled || token === null || normalizedHost === null) return null;\n if (gameId === null) {\n throw new PixelumeConfigError('analytics requires the client to be created with a gameId');\n }\n return Object.freeze({\n provider: Object.freeze({ kind: 'posthog' as const, token, host: normalizedHost }),\n gameId,\n gameVersion,\n rememberConsent,\n onIssue: (onIssue as ResolvedAnalyticsConfig['onIssue']) ?? null,\n });\n}\n\nfunction optionalString(name: string, value: unknown): string | null {\n if (value === undefined || value === null) return null;\n if (typeof value !== 'string') throw new PixelumeConfigError(`${name} must be a string`);\n const trimmed = value.trim();\n return trimmed === '' ? null : trimmed;\n}\n\nfunction validatePostHogToken(token: string): void {\n if (/^phx_/u.test(token)) {\n throw new PixelumeConfigError(\n 'analytics.posthog.projectToken must be the public project token (phc_...); personal API keys (phx_...) must never reach the browser',\n );\n }\n if (!POSTHOG_PROJECT_TOKEN_PATTERN.test(token)) {\n throw new PixelumeConfigError(\n 'analytics.posthog.projectToken must be a PostHog project token (phc_...)',\n );\n }\n}\n\n/** Same rules as `apiUrl`; a path is allowed for reverse proxies (e.g. `https://example.com/ingest`). */\nfunction normalizeAnalyticsHost(value: string, allowInsecureHttp: boolean): string {\n try {\n return normalizeApiUrl(value, allowInsecureHttp);\n } catch {\n throw new PixelumeConfigError(\n 'analytics.posthog.host must be an https: URL without credentials, query or fragment, e.g. https://us.i.posthog.com',\n );\n }\n}\n\nfunction validateGameVersion(value: unknown): string {\n if (typeof value !== 'string' || !GAME_VERSION_PATTERN.test(value)) {\n throw new PixelumeConfigError(\n 'analytics.gameVersion must be 1-64 letters, digits, dots, plus signs, underscores or hyphens',\n );\n }\n return value;\n}\n\nfunction resolveRedirectUri(\n options: PixelumeClientOptions,\n allowInsecureHttp: boolean,\n): string | null {\n const value = options.redirectUri ?? defaultRedirectUri(options.browser);\n return value === null ? null : normalizeRedirectUri(value, allowInsecureHttp);\n}\n\nfunction validateScope(value: unknown): 'profile' | 'profile saves' {\n if (value !== 'profile' && value !== 'profile saves') {\n throw new PixelumeConfigError('scope must be \"profile\" or \"profile saves\"');\n }\n return value;\n}\n\nconst DAY_MS = 24 * 60 * 60_000;\n\nfunction resolveCrossSessionRestore(\n value: PixelumeClientOptions['restoreAcrossSessions'],\n): { readonly maxAgeMs: number } | null {\n if (value === undefined || value === false) return null;\n if (value === true) return Object.freeze({ maxAgeMs: 30 * DAY_MS });\n // Validated at runtime: JavaScript callers may pass anything.\n const raw: unknown = value;\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n throw new PixelumeConfigError('restoreAcrossSessions must be a boolean or { maxAgeDays }');\n }\n const days: unknown = (raw as { maxAgeDays?: unknown }).maxAgeDays ?? 30;\n if (typeof days !== 'number' || !Number.isInteger(days) || days < 1 || days > 90) {\n throw new PixelumeConfigError(\n 'restoreAcrossSessions.maxAgeDays must be an integer from 1 to 90',\n );\n }\n return Object.freeze({ maxAgeMs: days * DAY_MS });\n}\n\nfunction validateBoolean(name: string, value: boolean): boolean {\n if (typeof value !== 'boolean') throw new PixelumeConfigError(`${name} must be a boolean`);\n return value;\n}\n\nfunction defaultRedirectUri(browser: PixelumeClientOptions['browser']): string | null {\n const location = Reflect.get(globalThis, 'location') as unknown;\n const current =\n browser?.currentUrl() ??\n (typeof location === 'object' && location !== null && 'href' in location\n ? String(location.href)\n : null);\n if (!current) return null;\n const url = new URL(current);\n return `${url.origin}/oauth/callback`;\n}\n\n/**\n * Accepts `https:` URLs, plus `http:` for loopback hosts (`localhost`, `*.localhost`, `127.0.0.0/8`,\n * `[::1]`). Other `http:` hosts (e.g. a LAN IP while testing on a phone) need `allowInsecureHttp`.\n */\nexport function normalizeApiUrl(value: string, allowInsecureHttp: boolean): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new PixelumeConfigError(\n 'apiUrl must be an absolute URL, e.g. https://api.pixelume.com.br',\n );\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new PixelumeConfigError('apiUrl must use https: (or http: for local development)');\n }\n if (url.protocol === 'http:' && !allowInsecureHttp && !isLoopbackHost(url.hostname)) {\n throw new PixelumeConfigError(\n 'apiUrl must use https:. Plain http: is only accepted for localhost unless allowInsecureHttp is set',\n );\n }\n if (url.username || url.password) {\n throw new PixelumeConfigError('apiUrl must not contain credentials');\n }\n if (url.search || url.hash) {\n throw new PixelumeConfigError('apiUrl must not contain a query string or fragment');\n }\n return `${url.origin}${url.pathname.replace(/\\/+$/u, '')}`;\n}\n\nfunction normalizeOrigin(value: string, name: string, allowInsecureHttp: boolean): string {\n const normalized = normalizeApiUrl(value, allowInsecureHttp);\n const url = new URL(normalized);\n if (url.pathname !== '/') {\n throw new PixelumeConfigError(`${name} must be an origin without a path`);\n }\n return url.origin;\n}\n\nexport function normalizeRedirectUri(value: string, allowInsecureHttp: boolean): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new PixelumeConfigError('redirectUri must be an absolute URL registered by the API');\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw new PixelumeConfigError('redirectUri must use https: (or http: for local development)');\n }\n if (url.protocol === 'http:' && !allowInsecureHttp && !isLoopbackHost(url.hostname)) {\n throw new PixelumeConfigError('redirectUri must use https: outside localhost');\n }\n if (url.username || url.password || url.hash) {\n throw new PixelumeConfigError('redirectUri must not contain credentials or a fragment');\n }\n for (const key of ['code', 'state', 'error', 'error_description']) {\n if (url.searchParams.has(key)) {\n throw new PixelumeConfigError(\n `redirectUri must not contain the reserved query parameter \"${key}\"`,\n );\n }\n }\n return url.toString();\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n hostname === '[::1]' ||\n /^127(?:\\.\\d{1,3}){3}$/u.test(hostname)\n );\n}\n\n/**\n * Game identifiers are public, non-secret slugs (e.g. `rail-puzzle`): lowercase letters, digits\n * and inner hyphens, 1–64 characters. They identify a game, they never authorize anything.\n */\nexport function validateGameId(value: string): string {\n if (typeof value !== 'string' || !GAME_ID_PATTERN.test(value)) {\n throw new PixelumeConfigError(\n 'gameId must be a lowercase slug (a-z, 0-9 and inner hyphens, up to 64 characters)',\n );\n }\n return value;\n}\n\nexport function validateClientId(value: string): string {\n if (typeof value !== 'string' || !CLIENT_ID_PATTERN.test(value)) {\n throw new PixelumeConfigError(\n 'clientId must contain 1-128 letters, digits, dots, underscores or hyphens',\n );\n }\n return value;\n}\n\n/** For feature modules that need a game context (Cloud Saves). */\nexport function requireGameId(config: Pick<ResolvedConfig, 'gameId'>, feature: string): string {\n if (config.gameId === null) {\n throw new PixelumeConfigError(`${feature} requires the client to be created with a gameId`);\n }\n return config.gameId;\n}\n\nexport function validateTimeout(value: number): number {\n if (!Number.isInteger(value) || value <= 0 || value > MAX_TIMEOUT_MS) {\n throw new PixelumeConfigError('timeoutMs must be a positive integer number of milliseconds');\n }\n return value;\n}\n\nfunction validateCredentials(value: CredentialsPolicy): CredentialsPolicy {\n if (!CREDENTIALS.includes(value)) {\n throw new PixelumeConfigError(`credentials must be one of: ${CREDENTIALS.join(', ')}`);\n }\n return value;\n}\n\nfunction resolveFetch(custom: FetchLike | undefined): FetchLike {\n if (custom !== undefined) {\n if (typeof custom !== 'function') throw new PixelumeConfigError('fetch must be a function');\n return custom;\n }\n if (typeof globalThis.fetch !== 'function') {\n throw new PixelumeConfigError('No global fetch available; pass the fetch option');\n }\n // Looked up on each call so polyfills or test doubles installed later are honoured.\n return (input, init) => globalThis.fetch(input, init);\n}\n"]}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export type PixelumeAuthErrorReason = 'browser_unavailable' | 'storage_unavailab
|
|
|
14
14
|
| 'session_expired'
|
|
15
15
|
/** The API rejected renewal because the game is disabled or unknown (`invalid_client`). */
|
|
16
16
|
| 'game_unavailable'
|
|
17
|
+
/**
|
|
18
|
+
* A cross-session restoration attempt (`restoreAcrossSessions`) was refused for a reason other
|
|
19
|
+
* than an ended central session, e.g. the remembered scope is no longer allowed for the game.
|
|
20
|
+
*/
|
|
21
|
+
| 'restore_rejected'
|
|
17
22
|
/**
|
|
18
23
|
* Renewal is not possible: the API rejected it for a non-recoverable reason (scope, origin,
|
|
19
24
|
* request) or the session has no refresh token (legacy authorization).
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Error hierarchy of the SDK.\n *\n * Every error thrown by the SDK is a {@link PixelumeError} with a stable `kind` discriminator.\n * Messages are deterministic and never include request/response bodies, headers, cookies or\n * query strings, so they are safe to log. Raw response payloads are kept on\n * {@link PixelumeHttpError.payload} as a non-enumerable property for programmatic inspection only.\n */\n\nconst PIXELUME_ERROR_BRAND = Symbol.for('pixelume.sdk.error');\n\nexport type PixelumeErrorKind =\n 'config' | 'auth' | 'http' | 'network' | 'timeout' | 'aborted' | 'invalid_response';\n\nexport type PixelumeAuthErrorReason =\n | 'browser_unavailable'\n | 'storage_unavailable'\n | 'crypto_unavailable'\n | 'invalid_callback'\n | 'state_mismatch'\n | 'authorization_expired'\n /** An operation needs a signed-in player and there is none. No request was sent. */\n | 'not_authenticated'\n /** The session ended and cannot be renewed (expired, revoked, logged out elsewhere). */\n | 'session_expired'\n /** The API rejected renewal because the game is disabled or unknown (`invalid_client`). */\n | 'game_unavailable'\n /**\n * Renewal is not possible: the API rejected it for a non-recoverable reason (scope, origin,\n * request) or the session has no refresh token (legacy authorization).\n */\n | 'renewal_rejected';\n\n/**\n * Error codes documented in the Pixelume API OpenAPI `ErrorEnvelope`.\n * The API may introduce new codes, so any string is accepted at runtime.\n */\nexport type PixelumeApiErrorCode =\n | 'INVALID_INPUT'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN_ORIGIN'\n | 'FORBIDDEN_HOST'\n | 'RATE_LIMITED'\n | 'REGISTRATION_DISABLED'\n | 'AUTH_TOKEN_INVALID'\n | 'OAUTH_INVALID_CLIENT'\n | 'OAUTH_INVALID_REDIRECT_URI'\n | 'OAUTH_INVALID_REQUEST'\n | 'OAUTH_INVALID_SCOPE'\n | 'OAUTH_REQUEST_EXPIRED'\n | 'OAUTH_INVALID_GRANT'\n | 'OAUTH_INVALID_TOKEN'\n | 'OAUTH_UNSUPPORTED_GRANT_TYPE'\n | 'OAUTH_INSUFFICIENT_SCOPE'\n | 'FORBIDDEN_GAME'\n | 'GAME_INACTIVE'\n | 'SAVE_NOT_FOUND'\n | 'SAVE_REVISION_CONFLICT'\n | 'SAVE_TOO_LARGE'\n | 'SAVE_QUOTA_EXCEEDED'\n | 'INTERNAL_ERROR'\n | 'NOT_FOUND'\n | (string & {});\n\n/** Identifies the request that failed. `path` never contains the query string. */\nexport interface PixelumeRequestInfo {\n readonly method: string;\n readonly path: string;\n}\n\n/** Base class of every error thrown by the SDK. */\nexport abstract class PixelumeError extends Error {\n abstract readonly kind: PixelumeErrorKind;\n\n protected constructor(name: string, message: string, options?: { cause?: unknown }) {\n super(message, options?.cause === undefined ? undefined : { cause: options.cause });\n // Explicit names survive minification of consumer bundles.\n this.name = name;\n Object.defineProperty(this, PIXELUME_ERROR_BRAND, { value: true });\n }\n}\n\n/** Invalid SDK configuration or invalid use of the SDK. Never caused by the network. */\nexport class PixelumeConfigError extends PixelumeError {\n readonly kind = 'config' as const;\n\n constructor(message: string) {\n super('PixelumeConfigError', message);\n }\n}\n\n/** A local browser authorization failure that happened before an API response was available. */\nexport class PixelumeAuthError extends PixelumeError {\n readonly kind = 'auth' as const;\n readonly reason: PixelumeAuthErrorReason;\n\n constructor(reason: PixelumeAuthErrorReason, options?: { cause?: unknown }) {\n super('PixelumeAuthError', `Pixelume authorization failed (${reason})`, options);\n this.reason = reason;\n }\n}\n\n/** Base class of errors tied to a specific HTTP request. */\nexport abstract class PixelumeRequestError extends PixelumeError {\n readonly method: string;\n readonly path: string;\n\n protected constructor(\n name: string,\n message: string,\n request: PixelumeRequestInfo,\n options?: { cause?: unknown },\n ) {\n super(name, message, options);\n this.method = request.method;\n this.path = request.path;\n }\n}\n\n/** The API answered with a non-2xx status. */\nexport class PixelumeHttpError extends PixelumeRequestError {\n readonly kind = 'http' as const;\n readonly status: number;\n /** `error.code` from the API error envelope, or `null` when the body is not an envelope. */\n readonly code: PixelumeApiErrorCode | null;\n /** `error.message` from the API error envelope (already sanitized by the API). */\n readonly apiMessage: string | null;\n /** Request ID from the envelope or the `x-request-id` header, useful for support. */\n readonly requestId: string | null;\n /**\n * `error.details` from the API envelope (e.g. `oauthError`, `quota`, conflict metadata), or\n * `null`. The API only exposes non-sensitive details here.\n */\n readonly details: Readonly<Record<string, unknown>> | null;\n /**\n * Decoded response body (JSON value, text or `undefined`). Non-enumerable so that\n * `JSON.stringify(error)` and structured loggers do not dump it by accident.\n */\n declare readonly payload: unknown;\n\n constructor(details: {\n request: PixelumeRequestInfo;\n status: number;\n code: string | null;\n apiMessage: string | null;\n requestId: string | null;\n details?: Readonly<Record<string, unknown>> | null;\n payload: unknown;\n }) {\n const suffix = details.code ? ` (${details.code})` : '';\n super(\n 'PixelumeHttpError',\n `Pixelume API request ${details.request.method} ${details.request.path} failed with status ${details.status}${suffix}`,\n details.request,\n );\n this.status = details.status;\n this.code = details.code;\n this.apiMessage = details.apiMessage;\n this.requestId = details.requestId;\n this.details = details.details ?? null;\n Object.defineProperty(this, 'payload', {\n value: details.payload,\n enumerable: false,\n writable: false,\n });\n }\n}\n\n/** Server-side metadata of a cloud save, as reported by the API. */\nexport interface PixelumeSaveMetadata {\n readonly gameId: string;\n readonly slotId: string;\n /** Version of the save format, chosen by the game (1–1 000 000). */\n readonly schemaVersion: number;\n /** Monotonic revision assigned by the server; never restarts, even after a delete. */\n readonly revision: number;\n /** UTF-8 size of the canonical JSON of `data`. */\n readonly sizeBytes: number;\n /** ISO 8601 timestamps assigned by the server. */\n readonly createdAt: string;\n readonly updatedAt: string;\n}\n\n/**\n * `409 SAVE_REVISION_CONFLICT`: the slot changed since `expectedRevision` (another device, tab or a\n * write whose response was lost). The SDK never retries or overwrites; the game decides.\n */\nexport class PixelumeSaveConflictError extends PixelumeHttpError {\n /** Current remote metadata, or `null` when the slot no longer has a live save. */\n readonly current: PixelumeSaveMetadata | null;\n /** The revision the rejected operation expected. */\n readonly expectedRevision: number;\n\n constructor(\n error: PixelumeHttpError,\n current: PixelumeSaveMetadata | null,\n expectedRevision: number,\n ) {\n super({\n request: { method: error.method, path: error.path },\n status: error.status,\n code: error.code,\n apiMessage: error.apiMessage,\n requestId: error.requestId,\n details: error.details,\n payload: error.payload,\n });\n this.name = 'PixelumeSaveConflictError';\n this.current = current;\n this.expectedRevision = expectedRevision;\n }\n}\n\n/**\n * The request did not produce an HTTP response: offline, DNS/TLS failure, connection reset,\n * or a browser CORS rejection (browsers do not distinguish these for security reasons).\n */\nexport class PixelumeNetworkError extends PixelumeRequestError {\n readonly kind = 'network' as const;\n\n constructor(request: PixelumeRequestInfo, options?: { cause?: unknown }) {\n super(\n 'PixelumeNetworkError',\n `Pixelume API request ${request.method} ${request.path} failed before a response was received (network failure or blocked by CORS)`,\n request,\n options,\n );\n }\n}\n\n/** The SDK timeout elapsed before the response (including its body) was received. */\nexport class PixelumeTimeoutError extends PixelumeRequestError {\n readonly kind = 'timeout' as const;\n readonly timeoutMs: number;\n\n constructor(request: PixelumeRequestInfo, timeoutMs: number, options?: { cause?: unknown }) {\n super(\n 'PixelumeTimeoutError',\n `Pixelume API request ${request.method} ${request.path} timed out after ${timeoutMs} ms`,\n request,\n options,\n );\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** The caller aborted the request through its `AbortSignal`. `cause` holds the abort reason. */\nexport class PixelumeAbortError extends PixelumeRequestError {\n readonly kind = 'aborted' as const;\n\n constructor(request: PixelumeRequestInfo, options?: { cause?: unknown }) {\n super(\n 'PixelumeAbortError',\n `Pixelume API request ${request.method} ${request.path} was aborted by the caller`,\n request,\n options,\n );\n }\n}\n\n/** A 2xx response did not match the contract expected by the SDK. */\nexport class PixelumeInvalidResponseError extends PixelumeRequestError {\n readonly kind = 'invalid_response' as const;\n readonly status: number;\n /** Short, payload-free description of the contract violation. */\n readonly reason: string;\n\n constructor(request: PixelumeRequestInfo, status: number, reason: string) {\n super(\n 'PixelumeInvalidResponseError',\n `Pixelume API request ${request.method} ${request.path} returned an unexpected response: ${reason}`,\n request,\n );\n this.status = status;\n this.reason = reason;\n }\n}\n\n/**\n * Returns `true` for any error thrown by the SDK. Works across duplicated copies of the package\n * (where `instanceof` would fail) because it checks a global symbol brand.\n */\nexport function isPixelumeError(value: unknown): value is PixelumeError {\n return (\n value instanceof Error &&\n (value as unknown as Record<symbol, unknown>)[PIXELUME_ERROR_BRAND] === true\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Error hierarchy of the SDK.\n *\n * Every error thrown by the SDK is a {@link PixelumeError} with a stable `kind` discriminator.\n * Messages are deterministic and never include request/response bodies, headers, cookies or\n * query strings, so they are safe to log. Raw response payloads are kept on\n * {@link PixelumeHttpError.payload} as a non-enumerable property for programmatic inspection only.\n */\n\nconst PIXELUME_ERROR_BRAND = Symbol.for('pixelume.sdk.error');\n\nexport type PixelumeErrorKind =\n 'config' | 'auth' | 'http' | 'network' | 'timeout' | 'aborted' | 'invalid_response';\n\nexport type PixelumeAuthErrorReason =\n | 'browser_unavailable'\n | 'storage_unavailable'\n | 'crypto_unavailable'\n | 'invalid_callback'\n | 'state_mismatch'\n | 'authorization_expired'\n /** An operation needs a signed-in player and there is none. No request was sent. */\n | 'not_authenticated'\n /** The session ended and cannot be renewed (expired, revoked, logged out elsewhere). */\n | 'session_expired'\n /** The API rejected renewal because the game is disabled or unknown (`invalid_client`). */\n | 'game_unavailable'\n /**\n * A cross-session restoration attempt (`restoreAcrossSessions`) was refused for a reason other\n * than an ended central session, e.g. the remembered scope is no longer allowed for the game.\n */\n | 'restore_rejected'\n /**\n * Renewal is not possible: the API rejected it for a non-recoverable reason (scope, origin,\n * request) or the session has no refresh token (legacy authorization).\n */\n | 'renewal_rejected';\n\n/**\n * Error codes documented in the Pixelume API OpenAPI `ErrorEnvelope`.\n * The API may introduce new codes, so any string is accepted at runtime.\n */\nexport type PixelumeApiErrorCode =\n | 'INVALID_INPUT'\n | 'UNAUTHENTICATED'\n | 'FORBIDDEN_ORIGIN'\n | 'FORBIDDEN_HOST'\n | 'RATE_LIMITED'\n | 'REGISTRATION_DISABLED'\n | 'AUTH_TOKEN_INVALID'\n | 'OAUTH_INVALID_CLIENT'\n | 'OAUTH_INVALID_REDIRECT_URI'\n | 'OAUTH_INVALID_REQUEST'\n | 'OAUTH_INVALID_SCOPE'\n | 'OAUTH_REQUEST_EXPIRED'\n | 'OAUTH_INVALID_GRANT'\n | 'OAUTH_INVALID_TOKEN'\n | 'OAUTH_UNSUPPORTED_GRANT_TYPE'\n | 'OAUTH_INSUFFICIENT_SCOPE'\n | 'FORBIDDEN_GAME'\n | 'GAME_INACTIVE'\n | 'SAVE_NOT_FOUND'\n | 'SAVE_REVISION_CONFLICT'\n | 'SAVE_TOO_LARGE'\n | 'SAVE_QUOTA_EXCEEDED'\n | 'INTERNAL_ERROR'\n | 'NOT_FOUND'\n | (string & {});\n\n/** Identifies the request that failed. `path` never contains the query string. */\nexport interface PixelumeRequestInfo {\n readonly method: string;\n readonly path: string;\n}\n\n/** Base class of every error thrown by the SDK. */\nexport abstract class PixelumeError extends Error {\n abstract readonly kind: PixelumeErrorKind;\n\n protected constructor(name: string, message: string, options?: { cause?: unknown }) {\n super(message, options?.cause === undefined ? undefined : { cause: options.cause });\n // Explicit names survive minification of consumer bundles.\n this.name = name;\n Object.defineProperty(this, PIXELUME_ERROR_BRAND, { value: true });\n }\n}\n\n/** Invalid SDK configuration or invalid use of the SDK. Never caused by the network. */\nexport class PixelumeConfigError extends PixelumeError {\n readonly kind = 'config' as const;\n\n constructor(message: string) {\n super('PixelumeConfigError', message);\n }\n}\n\n/** A local browser authorization failure that happened before an API response was available. */\nexport class PixelumeAuthError extends PixelumeError {\n readonly kind = 'auth' as const;\n readonly reason: PixelumeAuthErrorReason;\n\n constructor(reason: PixelumeAuthErrorReason, options?: { cause?: unknown }) {\n super('PixelumeAuthError', `Pixelume authorization failed (${reason})`, options);\n this.reason = reason;\n }\n}\n\n/** Base class of errors tied to a specific HTTP request. */\nexport abstract class PixelumeRequestError extends PixelumeError {\n readonly method: string;\n readonly path: string;\n\n protected constructor(\n name: string,\n message: string,\n request: PixelumeRequestInfo,\n options?: { cause?: unknown },\n ) {\n super(name, message, options);\n this.method = request.method;\n this.path = request.path;\n }\n}\n\n/** The API answered with a non-2xx status. */\nexport class PixelumeHttpError extends PixelumeRequestError {\n readonly kind = 'http' as const;\n readonly status: number;\n /** `error.code` from the API error envelope, or `null` when the body is not an envelope. */\n readonly code: PixelumeApiErrorCode | null;\n /** `error.message` from the API error envelope (already sanitized by the API). */\n readonly apiMessage: string | null;\n /** Request ID from the envelope or the `x-request-id` header, useful for support. */\n readonly requestId: string | null;\n /**\n * `error.details` from the API envelope (e.g. `oauthError`, `quota`, conflict metadata), or\n * `null`. The API only exposes non-sensitive details here.\n */\n readonly details: Readonly<Record<string, unknown>> | null;\n /**\n * Decoded response body (JSON value, text or `undefined`). Non-enumerable so that\n * `JSON.stringify(error)` and structured loggers do not dump it by accident.\n */\n declare readonly payload: unknown;\n\n constructor(details: {\n request: PixelumeRequestInfo;\n status: number;\n code: string | null;\n apiMessage: string | null;\n requestId: string | null;\n details?: Readonly<Record<string, unknown>> | null;\n payload: unknown;\n }) {\n const suffix = details.code ? ` (${details.code})` : '';\n super(\n 'PixelumeHttpError',\n `Pixelume API request ${details.request.method} ${details.request.path} failed with status ${details.status}${suffix}`,\n details.request,\n );\n this.status = details.status;\n this.code = details.code;\n this.apiMessage = details.apiMessage;\n this.requestId = details.requestId;\n this.details = details.details ?? null;\n Object.defineProperty(this, 'payload', {\n value: details.payload,\n enumerable: false,\n writable: false,\n });\n }\n}\n\n/** Server-side metadata of a cloud save, as reported by the API. */\nexport interface PixelumeSaveMetadata {\n readonly gameId: string;\n readonly slotId: string;\n /** Version of the save format, chosen by the game (1–1 000 000). */\n readonly schemaVersion: number;\n /** Monotonic revision assigned by the server; never restarts, even after a delete. */\n readonly revision: number;\n /** UTF-8 size of the canonical JSON of `data`. */\n readonly sizeBytes: number;\n /** ISO 8601 timestamps assigned by the server. */\n readonly createdAt: string;\n readonly updatedAt: string;\n}\n\n/**\n * `409 SAVE_REVISION_CONFLICT`: the slot changed since `expectedRevision` (another device, tab or a\n * write whose response was lost). The SDK never retries or overwrites; the game decides.\n */\nexport class PixelumeSaveConflictError extends PixelumeHttpError {\n /** Current remote metadata, or `null` when the slot no longer has a live save. */\n readonly current: PixelumeSaveMetadata | null;\n /** The revision the rejected operation expected. */\n readonly expectedRevision: number;\n\n constructor(\n error: PixelumeHttpError,\n current: PixelumeSaveMetadata | null,\n expectedRevision: number,\n ) {\n super({\n request: { method: error.method, path: error.path },\n status: error.status,\n code: error.code,\n apiMessage: error.apiMessage,\n requestId: error.requestId,\n details: error.details,\n payload: error.payload,\n });\n this.name = 'PixelumeSaveConflictError';\n this.current = current;\n this.expectedRevision = expectedRevision;\n }\n}\n\n/**\n * The request did not produce an HTTP response: offline, DNS/TLS failure, connection reset,\n * or a browser CORS rejection (browsers do not distinguish these for security reasons).\n */\nexport class PixelumeNetworkError extends PixelumeRequestError {\n readonly kind = 'network' as const;\n\n constructor(request: PixelumeRequestInfo, options?: { cause?: unknown }) {\n super(\n 'PixelumeNetworkError',\n `Pixelume API request ${request.method} ${request.path} failed before a response was received (network failure or blocked by CORS)`,\n request,\n options,\n );\n }\n}\n\n/** The SDK timeout elapsed before the response (including its body) was received. */\nexport class PixelumeTimeoutError extends PixelumeRequestError {\n readonly kind = 'timeout' as const;\n readonly timeoutMs: number;\n\n constructor(request: PixelumeRequestInfo, timeoutMs: number, options?: { cause?: unknown }) {\n super(\n 'PixelumeTimeoutError',\n `Pixelume API request ${request.method} ${request.path} timed out after ${timeoutMs} ms`,\n request,\n options,\n );\n this.timeoutMs = timeoutMs;\n }\n}\n\n/** The caller aborted the request through its `AbortSignal`. `cause` holds the abort reason. */\nexport class PixelumeAbortError extends PixelumeRequestError {\n readonly kind = 'aborted' as const;\n\n constructor(request: PixelumeRequestInfo, options?: { cause?: unknown }) {\n super(\n 'PixelumeAbortError',\n `Pixelume API request ${request.method} ${request.path} was aborted by the caller`,\n request,\n options,\n );\n }\n}\n\n/** A 2xx response did not match the contract expected by the SDK. */\nexport class PixelumeInvalidResponseError extends PixelumeRequestError {\n readonly kind = 'invalid_response' as const;\n readonly status: number;\n /** Short, payload-free description of the contract violation. */\n readonly reason: string;\n\n constructor(request: PixelumeRequestInfo, status: number, reason: string) {\n super(\n 'PixelumeInvalidResponseError',\n `Pixelume API request ${request.method} ${request.path} returned an unexpected response: ${reason}`,\n request,\n );\n this.status = status;\n this.reason = reason;\n }\n}\n\n/**\n * Returns `true` for any error thrown by the SDK. Works across duplicated copies of the package\n * (where `instanceof` would fail) because it checks a global symbol brand.\n */\nexport function isPixelumeError(value: unknown): value is PixelumeError {\n return (\n value instanceof Error &&\n (value as unknown as Record<symbol, unknown>)[PIXELUME_ERROR_BRAND] === true\n );\n}\n"]}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -16,6 +16,14 @@ export interface PixelumeBrowserAdapter {
|
|
|
16
16
|
navigate(url: string): void;
|
|
17
17
|
replaceUrl(url: string): void;
|
|
18
18
|
readonly sessionStorage: PixelumeSessionStorage;
|
|
19
|
+
/**
|
|
20
|
+
* Optional persistent storage (normally `localStorage`) for the non-secret cross-session hint
|
|
21
|
+
* of `restoreAcrossSessions`. Never receives tokens. When an injected adapter omits it,
|
|
22
|
+
* cross-session restoration is unavailable and the SDK behaves as without the option.
|
|
23
|
+
*/
|
|
24
|
+
readonly persistentStorage?: PixelumeSessionStorage | null;
|
|
25
|
+
/** Optional connectivity probe. Defaults to `navigator.onLine` (unknown counts as online). */
|
|
26
|
+
isOnline?(): boolean;
|
|
19
27
|
readonly crypto: Crypto;
|
|
20
28
|
/**
|
|
21
29
|
* Optional: calls `onResume` when the page may have been suspended (tab visible again, restored
|
|
@@ -55,6 +63,18 @@ export interface PixelumeClientOptions {
|
|
|
55
63
|
* a non-secret hint; access tokens remain memory-only. Defaults to `true`.
|
|
56
64
|
*/
|
|
57
65
|
restoreSession?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Opt-in: recover the account in a new tab or after the browser is reopened, while the central
|
|
68
|
+
* Pixelume session is still valid, without asking for the password again. After a successful
|
|
69
|
+
* login the SDK keeps a **non-secret** hint in `localStorage` (only "this game had a login on
|
|
70
|
+
* this browser", the granted scope and when); on a later start without an in-memory session it
|
|
71
|
+
* makes at most one authorization attempt with `prompt=none` — a brief top-level round trip that
|
|
72
|
+
* never shows a screen. If the central session ended, the API answers `login_required`, the hint
|
|
73
|
+
* is removed and the game continues as a visitor (`reason: 'session_ended'`), with no loop.
|
|
74
|
+
* Tokens stay memory-only. `true` uses a 30-day hint; `{ maxAgeDays }` (1–90) changes it.
|
|
75
|
+
* Defaults to `false`.
|
|
76
|
+
*/
|
|
77
|
+
restoreAcrossSessions?: boolean | PixelumeCrossSessionRestoreOptions;
|
|
58
78
|
/** Per-request timeout in milliseconds. Defaults to 10 000. */
|
|
59
79
|
timeoutMs?: number;
|
|
60
80
|
/**
|
|
@@ -69,6 +89,60 @@ export interface PixelumeClientOptions {
|
|
|
69
89
|
allowInsecureHttp?: boolean;
|
|
70
90
|
/** Advanced/test-only browser capability injection. Defaults to the current browser globals. */
|
|
71
91
|
browser?: PixelumeBrowserAdapter;
|
|
92
|
+
/**
|
|
93
|
+
* Opt-in gameplay analytics (`pixelume.analytics`). Without this option, with `enabled: false` or
|
|
94
|
+
* without a project token and host, analytics is a no-op: no storage, no network, no provider.
|
|
95
|
+
* Even when configured, nothing is sent before `analytics.setConsent(true)`.
|
|
96
|
+
*/
|
|
97
|
+
analytics?: PixelumeAnalyticsOptions;
|
|
98
|
+
}
|
|
99
|
+
/** Analytics configuration of one game. Contains only public, browser-safe values. */
|
|
100
|
+
export interface PixelumeAnalyticsOptions {
|
|
101
|
+
/** Defaults to `true` when the object is present. `false` keeps analytics a no-op. */
|
|
102
|
+
readonly enabled?: boolean;
|
|
103
|
+
/** Transport used for authorized events. Only `'posthog'` exists today (and is the default). */
|
|
104
|
+
readonly provider?: 'posthog';
|
|
105
|
+
readonly posthog?: PixelumePostHogOptions;
|
|
106
|
+
/** Version of the game build (e.g. `'1.4.0'`), sent as `game_version`. */
|
|
107
|
+
readonly gameVersion?: string;
|
|
108
|
+
/**
|
|
109
|
+
* Remember the player's choice in `localStorage` (`pixelume.analytics.consent.<gameId>`, only
|
|
110
|
+
* `{ version, granted, at }`), so the next visit starts with it. Defaults to `true`. With `false`
|
|
111
|
+
* the game stores the choice itself and calls `setConsent()` on every start.
|
|
112
|
+
*/
|
|
113
|
+
readonly rememberConsent?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Development diagnostics: called when the SDK drops an event or property, or when the provider
|
|
116
|
+
* fails. Never receives property values, tokens or identifiers. Errors thrown here are ignored.
|
|
117
|
+
*/
|
|
118
|
+
readonly onIssue?: (issue: PixelumeAnalyticsIssue) => void;
|
|
119
|
+
}
|
|
120
|
+
export interface PixelumePostHogOptions {
|
|
121
|
+
/**
|
|
122
|
+
* Public **project** token (`phc_…`). Never a personal API key (`phx_…`), which is rejected.
|
|
123
|
+
* Empty or missing keeps analytics a no-op (e.g. a build without the variable).
|
|
124
|
+
*/
|
|
125
|
+
readonly projectToken?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Ingestion host of the project's PostHog instance or of a reverse proxy, e.g.
|
|
128
|
+
* `https://us.i.posthog.com` or `https://eu.i.posthog.com`. Must match the project's region.
|
|
129
|
+
*/
|
|
130
|
+
readonly host?: string;
|
|
131
|
+
}
|
|
132
|
+
/** Why the SDK dropped analytics data or could not deliver it. Never contains values. */
|
|
133
|
+
export interface PixelumeAnalyticsIssue {
|
|
134
|
+
readonly code: 'invalid_event' | 'reserved_event' | 'invalid_level' | 'invalid_property' | 'reserved_property' | 'sensitive_property' | 'too_many_properties' | 'queue_full' | 'provider_unavailable' | 'provider_error';
|
|
135
|
+
/** Event involved, when the name is valid. */
|
|
136
|
+
readonly event: string | null;
|
|
137
|
+
/** Property key involved, when it is a valid key. */
|
|
138
|
+
readonly property: string | null;
|
|
139
|
+
}
|
|
140
|
+
export interface PixelumeCrossSessionRestoreOptions {
|
|
141
|
+
/**
|
|
142
|
+
* Days after the last successful login during which a new tab/browser start tries to recover the
|
|
143
|
+
* account. Defaults to 30 (the central session lifetime). Integer from 1 to 90.
|
|
144
|
+
*/
|
|
145
|
+
readonly maxAgeDays?: number;
|
|
72
146
|
}
|
|
73
147
|
/** Effective, validated configuration of a client. */
|
|
74
148
|
export interface PixelumeClientConfig {
|
|
@@ -79,8 +153,12 @@ export interface PixelumeClientConfig {
|
|
|
79
153
|
readonly scope: 'profile' | 'profile saves';
|
|
80
154
|
readonly authUrl: string;
|
|
81
155
|
readonly restoreSession: boolean;
|
|
156
|
+
/** Whether cross-session restoration (`restoreAcrossSessions`) is enabled. */
|
|
157
|
+
readonly restoreAcrossSessions: boolean;
|
|
82
158
|
readonly timeoutMs: number;
|
|
83
159
|
readonly credentials: PixelumeCredentialsPolicy;
|
|
160
|
+
/** Analytics provider configured for `pixelume.analytics`, or `null` when it is a no-op. */
|
|
161
|
+
readonly analytics: 'posthog' | null;
|
|
84
162
|
}
|
|
85
163
|
/** Options accepted by every SDK operation. */
|
|
86
164
|
export interface PixelumeRequestOptions {
|
package/dist/core/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CredentialsPolicy, FetchLike } from '../http/types.js';\n\nexport type PixelumeCredentialsPolicy = CredentialsPolicy;\nexport type PixelumeFetch = FetchLike;\n\n/** Minimal browser storage contract used for transient PKCE state and a non-secret session hint. */\nexport interface PixelumeSessionStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\n/**\n * Browser capabilities used by the redirect flow. Usually omitted; injection is useful in tests,\n * embedded runtimes and non-standard webviews.\n */\nexport interface PixelumeBrowserAdapter {\n currentUrl(): string;\n navigate(url: string): void;\n replaceUrl(url: string): void;\n readonly sessionStorage: PixelumeSessionStorage;\n readonly crypto: Crypto;\n /**\n * Optional: calls `onResume` when the page may have been suspended (tab visible again, restored\n * from the back/forward cache, back online) and returns an unsubscribe function. When omitted,\n * the SDK listens to `visibilitychange`, `pageshow` and `online` on the browser globals.\n */\n subscribeResume?(onResume: () => void): () => void;\n}\n\nexport interface PixelumeClientOptions {\n /**\n * Base URL of the Pixelume API. Defaults to `https://api.pixelume.com.br`.\n * Must be `https:`; `http:` is accepted for loopback hosts during local development.\n */\n apiUrl?: string;\n /**\n * Public identifier of the game, e.g. `rail-puzzle`. Optional in Phase 1 because no current\n * API contract uses it; future modules that need it will fail fast with a config error.\n * It is an identifier, never an authorization credential.\n */\n gameId?: string;\n /**\n * OAuth public client identifier registered by the Pixelume API. Defaults to `gameId`.\n * This is public metadata, never a secret.\n */\n clientId?: string;\n /** Exact callback URI registered for the OAuth client. Defaults to `<origin>/oauth/callback`. */\n redirectUri?: string;\n /**\n * Scope requested by `auth.login()`. Use `'profile saves'` for Cloud Saves; the game must have\n * `saves` enabled in the Pixelume Game Registry. Defaults to `'profile'`.\n */\n scope?: 'profile' | 'profile saves';\n /** Pixelume Auth portal origin. Defaults to `https://auth.pixelume.com.br`. */\n authUrl?: string;\n /**\n * Reauthorize after a same-tab reload when a previous SDK session existed. The SDK stores only\n * a non-secret hint; access tokens remain memory-only. Defaults to `true`.\n */\n restoreSession?: boolean;\n /** Per-request timeout in milliseconds. Defaults to 10 000. */\n timeoutMs?: number;\n /**\n * `fetch` credentials policy used by modules that do not set their own. Defaults to `'omit'`.\n * Cross-origin cookies are subject to the API's CORS allowlist and to browser policies;\n * the SDK never assumes they work.\n */\n credentials?: PixelumeCredentialsPolicy;\n /** Custom `fetch` implementation (tests, SSR, instrumentation). Defaults to `globalThis.fetch`. */\n fetch?: PixelumeFetch;\n /** Allows `http:` for non-loopback hosts (e.g. a LAN IP). Never enable it in production. */\n allowInsecureHttp?: boolean;\n /** Advanced/test-only browser capability injection. Defaults to the current browser globals. */\n browser?: PixelumeBrowserAdapter;\n}\n\n/** Effective, validated configuration of a client. */\nexport interface PixelumeClientConfig {\n readonly apiUrl: string;\n readonly gameId: string | null;\n readonly clientId: string | null;\n readonly redirectUri: string | null;\n readonly scope: 'profile' | 'profile saves';\n readonly authUrl: string;\n readonly restoreSession: boolean;\n readonly timeoutMs: number;\n readonly credentials: PixelumeCredentialsPolicy;\n}\n\n/** Options accepted by every SDK operation. */\nexport interface PixelumeRequestOptions {\n /** Aborts the operation; the promise rejects with `PixelumeAbortError`. */\n signal?: AbortSignal;\n /** Overrides the client timeout for this operation. */\n timeoutMs?: number;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CredentialsPolicy, FetchLike } from '../http/types.js';\n\nexport type PixelumeCredentialsPolicy = CredentialsPolicy;\nexport type PixelumeFetch = FetchLike;\n\n/** Minimal browser storage contract used for transient PKCE state and a non-secret session hint. */\nexport interface PixelumeSessionStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\n/**\n * Browser capabilities used by the redirect flow. Usually omitted; injection is useful in tests,\n * embedded runtimes and non-standard webviews.\n */\nexport interface PixelumeBrowserAdapter {\n currentUrl(): string;\n navigate(url: string): void;\n replaceUrl(url: string): void;\n readonly sessionStorage: PixelumeSessionStorage;\n /**\n * Optional persistent storage (normally `localStorage`) for the non-secret cross-session hint\n * of `restoreAcrossSessions`. Never receives tokens. When an injected adapter omits it,\n * cross-session restoration is unavailable and the SDK behaves as without the option.\n */\n readonly persistentStorage?: PixelumeSessionStorage | null;\n /** Optional connectivity probe. Defaults to `navigator.onLine` (unknown counts as online). */\n isOnline?(): boolean;\n readonly crypto: Crypto;\n /**\n * Optional: calls `onResume` when the page may have been suspended (tab visible again, restored\n * from the back/forward cache, back online) and returns an unsubscribe function. When omitted,\n * the SDK listens to `visibilitychange`, `pageshow` and `online` on the browser globals.\n */\n subscribeResume?(onResume: () => void): () => void;\n}\n\nexport interface PixelumeClientOptions {\n /**\n * Base URL of the Pixelume API. Defaults to `https://api.pixelume.com.br`.\n * Must be `https:`; `http:` is accepted for loopback hosts during local development.\n */\n apiUrl?: string;\n /**\n * Public identifier of the game, e.g. `rail-puzzle`. Optional in Phase 1 because no current\n * API contract uses it; future modules that need it will fail fast with a config error.\n * It is an identifier, never an authorization credential.\n */\n gameId?: string;\n /**\n * OAuth public client identifier registered by the Pixelume API. Defaults to `gameId`.\n * This is public metadata, never a secret.\n */\n clientId?: string;\n /** Exact callback URI registered for the OAuth client. Defaults to `<origin>/oauth/callback`. */\n redirectUri?: string;\n /**\n * Scope requested by `auth.login()`. Use `'profile saves'` for Cloud Saves; the game must have\n * `saves` enabled in the Pixelume Game Registry. Defaults to `'profile'`.\n */\n scope?: 'profile' | 'profile saves';\n /** Pixelume Auth portal origin. Defaults to `https://auth.pixelume.com.br`. */\n authUrl?: string;\n /**\n * Reauthorize after a same-tab reload when a previous SDK session existed. The SDK stores only\n * a non-secret hint; access tokens remain memory-only. Defaults to `true`.\n */\n restoreSession?: boolean;\n /**\n * Opt-in: recover the account in a new tab or after the browser is reopened, while the central\n * Pixelume session is still valid, without asking for the password again. After a successful\n * login the SDK keeps a **non-secret** hint in `localStorage` (only \"this game had a login on\n * this browser\", the granted scope and when); on a later start without an in-memory session it\n * makes at most one authorization attempt with `prompt=none` — a brief top-level round trip that\n * never shows a screen. If the central session ended, the API answers `login_required`, the hint\n * is removed and the game continues as a visitor (`reason: 'session_ended'`), with no loop.\n * Tokens stay memory-only. `true` uses a 30-day hint; `{ maxAgeDays }` (1–90) changes it.\n * Defaults to `false`.\n */\n restoreAcrossSessions?: boolean | PixelumeCrossSessionRestoreOptions;\n /** Per-request timeout in milliseconds. Defaults to 10 000. */\n timeoutMs?: number;\n /**\n * `fetch` credentials policy used by modules that do not set their own. Defaults to `'omit'`.\n * Cross-origin cookies are subject to the API's CORS allowlist and to browser policies;\n * the SDK never assumes they work.\n */\n credentials?: PixelumeCredentialsPolicy;\n /** Custom `fetch` implementation (tests, SSR, instrumentation). Defaults to `globalThis.fetch`. */\n fetch?: PixelumeFetch;\n /** Allows `http:` for non-loopback hosts (e.g. a LAN IP). Never enable it in production. */\n allowInsecureHttp?: boolean;\n /** Advanced/test-only browser capability injection. Defaults to the current browser globals. */\n browser?: PixelumeBrowserAdapter;\n /**\n * Opt-in gameplay analytics (`pixelume.analytics`). Without this option, with `enabled: false` or\n * without a project token and host, analytics is a no-op: no storage, no network, no provider.\n * Even when configured, nothing is sent before `analytics.setConsent(true)`.\n */\n analytics?: PixelumeAnalyticsOptions;\n}\n\n/** Analytics configuration of one game. Contains only public, browser-safe values. */\nexport interface PixelumeAnalyticsOptions {\n /** Defaults to `true` when the object is present. `false` keeps analytics a no-op. */\n readonly enabled?: boolean;\n /** Transport used for authorized events. Only `'posthog'` exists today (and is the default). */\n readonly provider?: 'posthog';\n readonly posthog?: PixelumePostHogOptions;\n /** Version of the game build (e.g. `'1.4.0'`), sent as `game_version`. */\n readonly gameVersion?: string;\n /**\n * Remember the player's choice in `localStorage` (`pixelume.analytics.consent.<gameId>`, only\n * `{ version, granted, at }`), so the next visit starts with it. Defaults to `true`. With `false`\n * the game stores the choice itself and calls `setConsent()` on every start.\n */\n readonly rememberConsent?: boolean;\n /**\n * Development diagnostics: called when the SDK drops an event or property, or when the provider\n * fails. Never receives property values, tokens or identifiers. Errors thrown here are ignored.\n */\n readonly onIssue?: (issue: PixelumeAnalyticsIssue) => void;\n}\n\nexport interface PixelumePostHogOptions {\n /**\n * Public **project** token (`phc_…`). Never a personal API key (`phx_…`), which is rejected.\n * Empty or missing keeps analytics a no-op (e.g. a build without the variable).\n */\n readonly projectToken?: string;\n /**\n * Ingestion host of the project's PostHog instance or of a reverse proxy, e.g.\n * `https://us.i.posthog.com` or `https://eu.i.posthog.com`. Must match the project's region.\n */\n readonly host?: string;\n}\n\n/** Why the SDK dropped analytics data or could not deliver it. Never contains values. */\nexport interface PixelumeAnalyticsIssue {\n readonly code:\n | 'invalid_event'\n | 'reserved_event'\n | 'invalid_level'\n | 'invalid_property'\n | 'reserved_property'\n | 'sensitive_property'\n | 'too_many_properties'\n | 'queue_full'\n | 'provider_unavailable'\n | 'provider_error';\n /** Event involved, when the name is valid. */\n readonly event: string | null;\n /** Property key involved, when it is a valid key. */\n readonly property: string | null;\n}\n\nexport interface PixelumeCrossSessionRestoreOptions {\n /**\n * Days after the last successful login during which a new tab/browser start tries to recover the\n * account. Defaults to 30 (the central session lifetime). Integer from 1 to 90.\n */\n readonly maxAgeDays?: number;\n}\n\n/** Effective, validated configuration of a client. */\nexport interface PixelumeClientConfig {\n readonly apiUrl: string;\n readonly gameId: string | null;\n readonly clientId: string | null;\n readonly redirectUri: string | null;\n readonly scope: 'profile' | 'profile saves';\n readonly authUrl: string;\n readonly restoreSession: boolean;\n /** Whether cross-session restoration (`restoreAcrossSessions`) is enabled. */\n readonly restoreAcrossSessions: boolean;\n readonly timeoutMs: number;\n readonly credentials: PixelumeCredentialsPolicy;\n /** Analytics provider configured for `pixelume.analytics`, or `null` when it is a no-op. */\n readonly analytics: 'posthog' | null;\n}\n\n/** Options accepted by every SDK operation. */\nexport interface PixelumeRequestOptions {\n /** Aborts the operation; the promise rejects with `PixelumeAbortError`. */\n signal?: AbortSignal;\n /** Overrides the client timeout for this operation. */\n timeoutMs?: number;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ export { DEFAULT_API_URL, DEFAULT_AUTH_URL, DEFAULT_TIMEOUT_MS } from './core/co
|
|
|
3
3
|
export { SDK_VERSION } from './version.js';
|
|
4
4
|
export { PixelumeError, PixelumeConfigError, PixelumeAuthError, PixelumeRequestError, PixelumeHttpError, PixelumeNetworkError, PixelumeTimeoutError, PixelumeAbortError, PixelumeInvalidResponseError, PixelumeSaveConflictError, isPixelumeError, } from './core/errors.js';
|
|
5
5
|
export type { PixelumeErrorKind, PixelumeApiErrorCode, PixelumeAuthErrorReason, PixelumeRequestInfo, PixelumeSaveMetadata, } from './core/errors.js';
|
|
6
|
-
export type { PixelumeClientOptions, PixelumeClientConfig, PixelumeRequestOptions, PixelumeCredentialsPolicy, PixelumeFetch, PixelumeBrowserAdapter, PixelumeSessionStorage, } from './core/types.js';
|
|
6
|
+
export type { PixelumeClientOptions, PixelumeClientConfig, PixelumeRequestOptions, PixelumeCredentialsPolicy, PixelumeFetch, PixelumeBrowserAdapter, PixelumeSessionStorage, PixelumeCrossSessionRestoreOptions, PixelumeAnalyticsOptions, PixelumePostHogOptions, PixelumeAnalyticsIssue, } from './core/types.js';
|
|
7
|
+
export type { PixelumeAnalyticsApi, PixelumeAnalyticsConsent, PixelumeAnalyticsProperties, PixelumeAnalyticsStatus, } from './modules/analytics/AnalyticsModule.js';
|
|
7
8
|
export type { PixelumeHealthApi, PixelumeHealthStatus, PixelumeRegistrationMode, } from './modules/health/HealthModule.js';
|
|
8
9
|
export type { PixelumeAuthApi, PixelumeAuthState, PixelumeAuthListener, PixelumeAnonymousReason, PixelumeLoginOptions, PixelumePlayer, PixelumeScopeRequest, } from './modules/auth/AuthModule.js';
|
|
9
10
|
export type { PixelumeScope, PixelumeSessionState, PixelumeSessionListener, } from './modules/auth/SessionManager.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,eAAe,GAChB,MAAM,kBAAkB,CAAC","sourcesContent":["export { PixelumeClient, Pixelume } from './core/PixelumeClient.js';\nexport { DEFAULT_API_URL, DEFAULT_AUTH_URL, DEFAULT_TIMEOUT_MS } from './core/config.js';\nexport { SDK_VERSION } from './version.js';\nexport {\n PixelumeError,\n PixelumeConfigError,\n PixelumeAuthError,\n PixelumeRequestError,\n PixelumeHttpError,\n PixelumeNetworkError,\n PixelumeTimeoutError,\n PixelumeAbortError,\n PixelumeInvalidResponseError,\n PixelumeSaveConflictError,\n isPixelumeError,\n} from './core/errors.js';\nexport type {\n PixelumeErrorKind,\n PixelumeApiErrorCode,\n PixelumeAuthErrorReason,\n PixelumeRequestInfo,\n PixelumeSaveMetadata,\n} from './core/errors.js';\nexport type {\n PixelumeClientOptions,\n PixelumeClientConfig,\n PixelumeRequestOptions,\n PixelumeCredentialsPolicy,\n PixelumeFetch,\n PixelumeBrowserAdapter,\n PixelumeSessionStorage,\n} from './core/types.js';\nexport type {\n PixelumeHealthApi,\n PixelumeHealthStatus,\n PixelumeRegistrationMode,\n} from './modules/health/HealthModule.js';\nexport type {\n PixelumeAuthApi,\n PixelumeAuthState,\n PixelumeAuthListener,\n PixelumeAnonymousReason,\n PixelumeLoginOptions,\n PixelumePlayer,\n PixelumeScopeRequest,\n} from './modules/auth/AuthModule.js';\nexport type {\n PixelumeScope,\n PixelumeSessionState,\n PixelumeSessionListener,\n} from './modules/auth/SessionManager.js';\nexport type {\n PixelumeSavesApi,\n PixelumeSave,\n PixelumeSaveList,\n PixelumeSaveWrite,\n PixelumeSaveResult,\n PixelumeSaveDeleteOptions,\n PixelumeSaveDeleteResult,\n PixelumeSavesActivity,\n PixelumeSavesListener,\n PixelumeSavesOperation,\n} from './modules/saves/SavesModule.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,eAAe,GAChB,MAAM,kBAAkB,CAAC","sourcesContent":["export { PixelumeClient, Pixelume } from './core/PixelumeClient.js';\nexport { DEFAULT_API_URL, DEFAULT_AUTH_URL, DEFAULT_TIMEOUT_MS } from './core/config.js';\nexport { SDK_VERSION } from './version.js';\nexport {\n PixelumeError,\n PixelumeConfigError,\n PixelumeAuthError,\n PixelumeRequestError,\n PixelumeHttpError,\n PixelumeNetworkError,\n PixelumeTimeoutError,\n PixelumeAbortError,\n PixelumeInvalidResponseError,\n PixelumeSaveConflictError,\n isPixelumeError,\n} from './core/errors.js';\nexport type {\n PixelumeErrorKind,\n PixelumeApiErrorCode,\n PixelumeAuthErrorReason,\n PixelumeRequestInfo,\n PixelumeSaveMetadata,\n} from './core/errors.js';\nexport type {\n PixelumeClientOptions,\n PixelumeClientConfig,\n PixelumeRequestOptions,\n PixelumeCredentialsPolicy,\n PixelumeFetch,\n PixelumeBrowserAdapter,\n PixelumeSessionStorage,\n PixelumeCrossSessionRestoreOptions,\n PixelumeAnalyticsOptions,\n PixelumePostHogOptions,\n PixelumeAnalyticsIssue,\n} from './core/types.js';\nexport type {\n PixelumeAnalyticsApi,\n PixelumeAnalyticsConsent,\n PixelumeAnalyticsProperties,\n PixelumeAnalyticsStatus,\n} from './modules/analytics/AnalyticsModule.js';\nexport type {\n PixelumeHealthApi,\n PixelumeHealthStatus,\n PixelumeRegistrationMode,\n} from './modules/health/HealthModule.js';\nexport type {\n PixelumeAuthApi,\n PixelumeAuthState,\n PixelumeAuthListener,\n PixelumeAnonymousReason,\n PixelumeLoginOptions,\n PixelumePlayer,\n PixelumeScopeRequest,\n} from './modules/auth/AuthModule.js';\nexport type {\n PixelumeScope,\n PixelumeSessionState,\n PixelumeSessionListener,\n} from './modules/auth/SessionManager.js';\nexport type {\n PixelumeSavesApi,\n PixelumeSave,\n PixelumeSaveList,\n PixelumeSaveWrite,\n PixelumeSaveResult,\n PixelumeSaveDeleteOptions,\n PixelumeSaveDeleteResult,\n PixelumeSavesActivity,\n PixelumeSavesListener,\n PixelumeSavesOperation,\n} from './modules/saves/SavesModule.js';\n"]}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { ResolvedAnalyticsConfig } from '../../core/config.js';
|
|
2
|
+
import type { PixelumeBrowserAdapter } from '../../core/types.js';
|
|
3
|
+
import type { PixelumeAuthListener, PixelumeAuthState } from '../auth/AuthModule.js';
|
|
4
|
+
import { type AnalyticsProvider } from './AnalyticsProvider.js';
|
|
5
|
+
/** Flat values accepted as event properties. Other values are dropped (see `onIssue`). */
|
|
6
|
+
export type PixelumeAnalyticsProperties = Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
7
|
+
/**
|
|
8
|
+
* - `unknown`: the player has not decided (or the choice is not remembered). Nothing is sent.
|
|
9
|
+
* - `granted`: events are sent.
|
|
10
|
+
* - `denied`: nothing is sent and the analytics identifiers were removed from the browser.
|
|
11
|
+
*/
|
|
12
|
+
export type PixelumeAnalyticsConsent = 'unknown' | 'granted' | 'denied';
|
|
13
|
+
/**
|
|
14
|
+
* - `disabled`: not configured (or the client was destroyed): every call is a no-op.
|
|
15
|
+
* - `waiting_consent`: configured, consent not granted. Events are discarded, not queued.
|
|
16
|
+
* - `loading`: consent granted, provider loading; events wait in a small in-memory queue.
|
|
17
|
+
* - `ready`: events are being delivered.
|
|
18
|
+
* - `unavailable`: the provider could not load here (no browser, blocked script/network). Events
|
|
19
|
+
* are discarded; a later `setConsent(true)` tries again.
|
|
20
|
+
*/
|
|
21
|
+
export type PixelumeAnalyticsStatus = 'disabled' | 'waiting_consent' | 'loading' | 'ready' | 'unavailable';
|
|
22
|
+
/**
|
|
23
|
+
* Gameplay analytics, decoupled from the provider (PostHog today). Every method is synchronous,
|
|
24
|
+
* never throws and never waits for the network: a failing provider cannot stop the game.
|
|
25
|
+
*
|
|
26
|
+
* A **game session** is one continuous play period defined by the game (e.g. from "Play" until the
|
|
27
|
+
* player returns to the menu, or one match); it is unrelated to the Pixelume login session.
|
|
28
|
+
*/
|
|
29
|
+
export interface PixelumeAnalyticsApi {
|
|
30
|
+
readonly consent: PixelumeAnalyticsConsent;
|
|
31
|
+
readonly status: PixelumeAnalyticsStatus;
|
|
32
|
+
/** Id of the current game session (`session_id` of every event), or `null` outside one. */
|
|
33
|
+
readonly sessionId: string | null;
|
|
34
|
+
/** `true` when events are (or will shortly be) delivered: configured, consented, available. */
|
|
35
|
+
isEnabled(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Records the player's explicit decision. `false` discards pending events, stops delivery and
|
|
38
|
+
* removes the analytics identifiers from the browser; `true` after `false` starts a new
|
|
39
|
+
* anonymous identity. Repeating the current value does nothing.
|
|
40
|
+
*/
|
|
41
|
+
setConsent(granted: boolean): void;
|
|
42
|
+
/** Custom event: snake_case name (1–64 chars) not in the built-in catalog. */
|
|
43
|
+
track(event: string, properties?: PixelumeAnalyticsProperties): void;
|
|
44
|
+
/** Starts a game session (`game_session_started`). Does nothing while one is active. */
|
|
45
|
+
startSession(properties?: PixelumeAnalyticsProperties): void;
|
|
46
|
+
/**
|
|
47
|
+
* Ends the current game session (`game_session_ended` with `duration_ms` and
|
|
48
|
+
* `visible_duration_ms`). Does nothing without an active session. Closing the tab does **not**
|
|
49
|
+
* end the session: only the game knows when play really ended.
|
|
50
|
+
*/
|
|
51
|
+
endSession(properties?: PixelumeAnalyticsProperties): void;
|
|
52
|
+
levelStarted(level: string | number, properties?: PixelumeAnalyticsProperties): void;
|
|
53
|
+
/** `level_completed`; carries `duration_ms` when the matching `levelStarted` was seen. */
|
|
54
|
+
levelCompleted(level: string | number, properties?: PixelumeAnalyticsProperties): void;
|
|
55
|
+
/** `level_failed` with an optional short `reason` (e.g. `'out_of_moves'`). */
|
|
56
|
+
levelFailed(level: string | number, reason?: string, properties?: PixelumeAnalyticsProperties): void;
|
|
57
|
+
}
|
|
58
|
+
/** Subset of `pixelume.auth` used to follow the player's identity. */
|
|
59
|
+
export interface AnalyticsAuthSource {
|
|
60
|
+
readonly state: PixelumeAuthState;
|
|
61
|
+
subscribe(listener: PixelumeAuthListener): () => void;
|
|
62
|
+
}
|
|
63
|
+
/** Visibility signals; tests inject a double. */
|
|
64
|
+
export interface VisibilitySource {
|
|
65
|
+
isVisible(): boolean;
|
|
66
|
+
subscribe(onChange: () => void): () => void;
|
|
67
|
+
}
|
|
68
|
+
export interface AnalyticsModuleOptions {
|
|
69
|
+
readonly config: ResolvedAnalyticsConfig | null;
|
|
70
|
+
readonly auth: AnalyticsAuthSource;
|
|
71
|
+
readonly browser?: PixelumeBrowserAdapter | undefined;
|
|
72
|
+
/** Test seams. */
|
|
73
|
+
readonly createProvider?: (config: ResolvedAnalyticsConfig) => AnalyticsProvider;
|
|
74
|
+
readonly visibility?: VisibilitySource | null;
|
|
75
|
+
readonly now?: () => number;
|
|
76
|
+
}
|
|
77
|
+
/** Events kept while the provider loads after consent; older ones are kept, newer dropped. */
|
|
78
|
+
export declare const MAX_PENDING_EVENTS = 100;
|
|
79
|
+
export declare class AnalyticsModule implements PixelumeAnalyticsApi {
|
|
80
|
+
#private;
|
|
81
|
+
constructor(options: AnalyticsModuleOptions);
|
|
82
|
+
get consent(): PixelumeAnalyticsConsent;
|
|
83
|
+
get status(): PixelumeAnalyticsStatus;
|
|
84
|
+
get sessionId(): string | null;
|
|
85
|
+
isEnabled(): boolean;
|
|
86
|
+
setConsent(granted: boolean): void;
|
|
87
|
+
track(event: string, properties?: PixelumeAnalyticsProperties): void;
|
|
88
|
+
startSession(properties?: PixelumeAnalyticsProperties): void;
|
|
89
|
+
endSession(properties?: PixelumeAnalyticsProperties): void;
|
|
90
|
+
levelStarted(level: string | number, properties?: PixelumeAnalyticsProperties): void;
|
|
91
|
+
levelCompleted(level: string | number, properties?: PixelumeAnalyticsProperties): void;
|
|
92
|
+
levelFailed(level: string | number, reason?: string, properties?: PixelumeAnalyticsProperties): void;
|
|
93
|
+
}
|