@moviie/player-sdk 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.cjs +157 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -2
- package/dist/index.d.ts +79 -2
- package/dist/index.js +153 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -58,7 +58,8 @@ Fetches playback metadata for a public embed. Returns `Promise<MoviiePlaybackDat
|
|
|
58
58
|
| `MoviieAuthError` | `auth` | Invalid or missing publishable key. |
|
|
59
59
|
| `MoviieNotFoundError` | `not_found` | Embed UUID does not exist. |
|
|
60
60
|
| `MoviieBundleBlockedError` | `bundle_blocked` | Bundle ID not on the embed allowlist. |
|
|
61
|
-
| `MoviieReferrerBlockedError` | `referrer_blocked` | Request origin not on the embed allowlist. |
|
|
61
|
+
| `MoviieReferrerBlockedError` | `referrer_blocked` | Request origin present but not on the embed allowlist. |
|
|
62
|
+
| `MoviieDirectAccessBlockedError` | `direct_access_blocked` | Video opened directly (no origin) while direct-URL access is blocked. |
|
|
62
63
|
| `MoviieSubscriptionInactiveError` | `subscription_inactive` | Organization subscription is paused or expired. |
|
|
63
64
|
| `MoviieNetworkError` | `network` | Network request failed (timeout, unreachable). |
|
|
64
65
|
| `MoviieRateLimitError` | `rate_limit` | Too many requests in a short period. |
|
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,8 @@ var SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {
|
|
|
15
15
|
};
|
|
16
16
|
var HTTP_HEADER_MOVIIE_REASON = "x-moviie-reason";
|
|
17
17
|
var MOVIIE_BLOCK_REASON = {
|
|
18
|
-
BUNDLE: "bundle"
|
|
18
|
+
BUNDLE: "bundle",
|
|
19
|
+
DIRECT_ACCESS: "direct_access_blocked"
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
// src/config/moviie-endpoints.ts
|
|
@@ -94,6 +95,13 @@ var MoviieReferrerBlockedError = class extends Error {
|
|
|
94
95
|
this.name = "MoviieReferrerBlockedError";
|
|
95
96
|
}
|
|
96
97
|
};
|
|
98
|
+
var MoviieDirectAccessBlockedError = class extends Error {
|
|
99
|
+
code = "direct_access_blocked";
|
|
100
|
+
constructor(message = "Este v\xEDdeo n\xE3o pode ser reproduzido diretamente pela URL") {
|
|
101
|
+
super(message);
|
|
102
|
+
this.name = "MoviieDirectAccessBlockedError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
97
105
|
var MoviieSubscriptionInactiveError = class extends Error {
|
|
98
106
|
code = "subscription_inactive";
|
|
99
107
|
constructor(message = "Reprodu\xE7\xE3o temporariamente indispon\xEDvel para esta organiza\xE7\xE3o") {
|
|
@@ -255,6 +263,9 @@ async function fetchPlaybackData(params) {
|
|
|
255
263
|
if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {
|
|
256
264
|
throw new MoviieBundleBlockedError();
|
|
257
265
|
}
|
|
266
|
+
if (reason === MOVIIE_BLOCK_REASON.DIRECT_ACCESS) {
|
|
267
|
+
throw new MoviieDirectAccessBlockedError();
|
|
268
|
+
}
|
|
258
269
|
throw new MoviieReferrerBlockedError();
|
|
259
270
|
}
|
|
260
271
|
if (response.status >= 500) {
|
|
@@ -270,6 +281,102 @@ async function fetchPlaybackData(params) {
|
|
|
270
281
|
}
|
|
271
282
|
return parsed.data;
|
|
272
283
|
}
|
|
284
|
+
var matchSchema = zod.z.object({
|
|
285
|
+
segmentIndex: zod.z.number().int(),
|
|
286
|
+
startSeconds: zod.z.number(),
|
|
287
|
+
endSeconds: zod.z.number(),
|
|
288
|
+
text: zod.z.string()
|
|
289
|
+
});
|
|
290
|
+
var resultSchema = zod.z.object({
|
|
291
|
+
query: zod.z.string(),
|
|
292
|
+
language: zod.z.string().nullable(),
|
|
293
|
+
total: zod.z.number().int(),
|
|
294
|
+
matches: zod.z.array(matchSchema),
|
|
295
|
+
nextCursor: zod.z.number().int().nullable()
|
|
296
|
+
});
|
|
297
|
+
var TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250;
|
|
298
|
+
var TRANSCRIPT_SEARCH_MIN_LENGTH = 2;
|
|
299
|
+
var EMPTY_RESULT = (query) => ({
|
|
300
|
+
query,
|
|
301
|
+
language: null,
|
|
302
|
+
total: 0,
|
|
303
|
+
matches: [],
|
|
304
|
+
nextCursor: null
|
|
305
|
+
});
|
|
306
|
+
async function fetchTranscriptSearch(params) {
|
|
307
|
+
const response = await fetchWithRetry(params.url, {
|
|
308
|
+
method: "GET",
|
|
309
|
+
headers: params.headers,
|
|
310
|
+
signal: params.signal
|
|
311
|
+
});
|
|
312
|
+
if (response.status === 401) throw new MoviieAuthError();
|
|
313
|
+
if (response.status === 404) throw new MoviieNotFoundError();
|
|
314
|
+
if (response.status >= 500) throw new MoviieNetworkError();
|
|
315
|
+
if (!response.ok) throw new MoviieNetworkError();
|
|
316
|
+
const json = await response.json();
|
|
317
|
+
const parsed = resultSchema.safeParse(json);
|
|
318
|
+
if (!parsed.success) {
|
|
319
|
+
throw new MoviieNetworkError("Resposta de busca inv\xE1lida");
|
|
320
|
+
}
|
|
321
|
+
return parsed.data;
|
|
322
|
+
}
|
|
323
|
+
function createTranscriptSearchController(opts) {
|
|
324
|
+
const debounceMs = opts.debounceMs ?? TRANSCRIPT_SEARCH_DEBOUNCE_MS;
|
|
325
|
+
const minLength = opts.minLength ?? TRANSCRIPT_SEARCH_MIN_LENGTH;
|
|
326
|
+
let timer = null;
|
|
327
|
+
let inFlight = null;
|
|
328
|
+
function clearTimer() {
|
|
329
|
+
if (timer !== null) {
|
|
330
|
+
clearTimeout(timer);
|
|
331
|
+
timer = null;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function cancelInFlight() {
|
|
335
|
+
if (inFlight) {
|
|
336
|
+
inFlight.abort();
|
|
337
|
+
inFlight = null;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function search(rawQuery) {
|
|
341
|
+
const query = rawQuery.trim();
|
|
342
|
+
clearTimer();
|
|
343
|
+
if (query.length < minLength) {
|
|
344
|
+
cancelInFlight();
|
|
345
|
+
opts.onResult(EMPTY_RESULT(query));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
timer = setTimeout(() => {
|
|
349
|
+
timer = null;
|
|
350
|
+
cancelInFlight();
|
|
351
|
+
const controller = new AbortController();
|
|
352
|
+
inFlight = controller;
|
|
353
|
+
opts.onLoadingChange?.(true);
|
|
354
|
+
opts.fetcher(query, controller.signal).then((result) => {
|
|
355
|
+
if (!controller.signal.aborted) opts.onResult(result);
|
|
356
|
+
}).catch((error) => {
|
|
357
|
+
if (controller.signal.aborted) return;
|
|
358
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
359
|
+
opts.onError?.(error);
|
|
360
|
+
}).finally(() => {
|
|
361
|
+
if (inFlight === controller) {
|
|
362
|
+
inFlight = null;
|
|
363
|
+
opts.onLoadingChange?.(false);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
}, debounceMs);
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
search,
|
|
370
|
+
cancel() {
|
|
371
|
+
clearTimer();
|
|
372
|
+
cancelInFlight();
|
|
373
|
+
},
|
|
374
|
+
destroy() {
|
|
375
|
+
clearTimer();
|
|
376
|
+
cancelInFlight();
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
273
380
|
|
|
274
381
|
// src/client/moviie-client.ts
|
|
275
382
|
var videoEmbedResponseSchema = zod.z.object({
|
|
@@ -307,6 +414,50 @@ var MoviieClient = class {
|
|
|
307
414
|
signal
|
|
308
415
|
});
|
|
309
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Search the spoken content of the video a playback session is playing, and
|
|
419
|
+
* return the moments where the term appears (each with a timestamp). The
|
|
420
|
+
* session scopes the search to the video it actually loaded (swap-safe) and
|
|
421
|
+
* authorizes the request — it was gated when bootstrapped. Obtain the session
|
|
422
|
+
* id from the telemetry bootstrap. Matching is case- and accent-insensitive.
|
|
423
|
+
*/
|
|
424
|
+
async search(sessionId, query, opts) {
|
|
425
|
+
const key = this.options.publishableKey?.trim();
|
|
426
|
+
if (!key) {
|
|
427
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
428
|
+
}
|
|
429
|
+
if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
430
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN);
|
|
431
|
+
}
|
|
432
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
433
|
+
const params = new URLSearchParams({ q: query });
|
|
434
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
435
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
436
|
+
const url = `${base}/sessions/${encodeURIComponent(sessionId)}/search?${params.toString()}`;
|
|
437
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Private transcript search for an embed's video (feature 183) — the
|
|
441
|
+
* authenticated twin of {@link search}. Requires a PRIVATE API key (publishable
|
|
442
|
+
* keys are rejected) and is scoped to the key's organization; the embed must
|
|
443
|
+
* belong to it. Unlike {@link search} it needs no playback session. Matching is
|
|
444
|
+
* case- and accent-insensitive.
|
|
445
|
+
*/
|
|
446
|
+
async searchEmbedTranscript(embedId, query, opts) {
|
|
447
|
+
const key = this.options.publishableKey?.trim();
|
|
448
|
+
if (!key) {
|
|
449
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
450
|
+
}
|
|
451
|
+
if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
452
|
+
throw new MoviieAuthError("A busca privada exige uma chave de API privada (n\xE3o publishable).");
|
|
453
|
+
}
|
|
454
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
455
|
+
const params = new URLSearchParams({ q: query });
|
|
456
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
457
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
458
|
+
const url = `${base}/embeds/${encodeURIComponent(embedId)}/transcript/search?${params.toString()}`;
|
|
459
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
460
|
+
}
|
|
310
461
|
async getVideo(videoId, signal) {
|
|
311
462
|
const key = this.options.publishableKey?.trim();
|
|
312
463
|
if (!key) {
|
|
@@ -745,6 +896,7 @@ exports.MemoryViewerTokenStore = MemoryViewerTokenStore;
|
|
|
745
896
|
exports.MoviieAuthError = MoviieAuthError;
|
|
746
897
|
exports.MoviieBundleBlockedError = MoviieBundleBlockedError;
|
|
747
898
|
exports.MoviieClient = MoviieClient;
|
|
899
|
+
exports.MoviieDirectAccessBlockedError = MoviieDirectAccessBlockedError;
|
|
748
900
|
exports.MoviieNetworkError = MoviieNetworkError;
|
|
749
901
|
exports.MoviieNotFoundError = MoviieNotFoundError;
|
|
750
902
|
exports.MoviieRateLimitError = MoviieRateLimitError;
|
|
@@ -754,12 +906,16 @@ exports.PLAYBACK_EVENT_TYPE = PLAYBACK_EVENT_TYPE;
|
|
|
754
906
|
exports.SDK_PLAYBACK_AUTH_ERROR_MESSAGE = SDK_PLAYBACK_AUTH_ERROR_MESSAGE;
|
|
755
907
|
exports.SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE;
|
|
756
908
|
exports.TELEMETRY_TOKEN_CONFIG = TELEMETRY_TOKEN_CONFIG;
|
|
909
|
+
exports.TRANSCRIPT_SEARCH_DEBOUNCE_MS = TRANSCRIPT_SEARCH_DEBOUNCE_MS;
|
|
910
|
+
exports.TRANSCRIPT_SEARCH_MIN_LENGTH = TRANSCRIPT_SEARCH_MIN_LENGTH;
|
|
757
911
|
exports.TelemetryClient = TelemetryClient;
|
|
758
912
|
exports.buildClientHeaders = buildClientHeaders;
|
|
759
913
|
exports.configureMoviieEndpoints = configureMoviieEndpoints;
|
|
914
|
+
exports.createTranscriptSearchController = createTranscriptSearchController;
|
|
760
915
|
exports.deriveMoviieTelemetryBaseUrlFromApiBaseUrl = deriveMoviieTelemetryBaseUrlFromApiBaseUrl;
|
|
761
916
|
exports.deriveTelemetryEventsBaseUrlFromBootstrapUrl = deriveTelemetryEventsBaseUrlFromBootstrapUrl;
|
|
762
917
|
exports.fetchPlaybackData = fetchPlaybackData;
|
|
918
|
+
exports.fetchTranscriptSearch = fetchTranscriptSearch;
|
|
763
919
|
exports.getMoviieApiBaseUrl = getMoviieApiBaseUrl;
|
|
764
920
|
exports.getMoviieEventsBaseUrl = getMoviieEventsBaseUrl;
|
|
765
921
|
exports.planRefresh = planRefresh;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/config/moviie-endpoints.ts","../src/client/errors.ts","../src/client/http.ts","../src/client/client-headers.ts","../src/playback/fetch-playback.ts","../src/client/moviie-client.ts","../src/telemetry/types.ts","../src/telemetry/heartbeat-scheduler.ts","../src/telemetry/token-manager.ts","../src/telemetry/telemetry-client.ts","../src/telemetry/viewer-token-store.ts","../src/playback/playback-refresh.ts","../src/config/telemetry-bootstrap-url.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default Public REST API base URL for production clients (OpenAPI `/v1/*` paths).\n *\n * Requests use `{MOVIIE_DEFAULT_API_BASE_URL}/embeds/{embedId}/playback`, etc.\n */\nexport const MOVIIE_DEFAULT_API_BASE_URL = \"https://api.moviie.ai/v1\" as const\n\n/**\n * Path segment for telemetry on the **same origin** as the Public API (bootstrap, ingest, token refresh).\n */\nexport const MOVIIE_TELEMETRY_API_PATH_PREFIX = \"/telemetry/v1\" as const\n\nexport const SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = \"mvi_pub_\" as const\n\nexport const SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {\n KEY_REQUIRED: \"Publishable API key is required for playback.\",\n PRIVATE_KEY_FORBIDDEN:\n \"Do not use a private API key for playback; use a publishable key (mvi_pub_*).\",\n} as const\n\nexport const HTTP_HEADER_MOVIIE_REASON = \"x-moviie-reason\" as const\n\nexport const MOVIIE_BLOCK_REASON = {\n BUNDLE: \"bundle\",\n} as const\n","import {\n MOVIIE_DEFAULT_API_BASE_URL,\n MOVIIE_TELEMETRY_API_PATH_PREFIX,\n} from \"../constants\"\n\nlet configuredApiBaseUrl: string | null = null\nlet configuredEventsBaseUrl: string | null = null\n\nexport type MoviieEndpointsConfiguration = {\n /** API base URL override without trailing slash. Pass `null` or empty to clear. */\n apiBaseUrl?: string | null\n /**\n * Telemetry base (`…/telemetry/v1`) without trailing slash.\n * Pass `null` or empty to clear and derive from the API origin again.\n */\n eventsBaseUrl?: string | null\n}\n\nfunction normalizeEndpointBase(raw: string): string {\n return raw.trim().replace(/\\/+$/, \"\")\n}\n\n/**\n * Builds `{apiOrigin}/telemetry/v1` from a configured API base (e.g. `https://host/api/v1` → `https://host/telemetry/v1`).\n */\nexport function deriveMoviieTelemetryBaseUrlFromApiBaseUrl(apiBaseUrl: string): string {\n const trimmed = normalizeEndpointBase(apiBaseUrl)\n const href = trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`\n const u = new URL(href)\n return normalizeEndpointBase(`${u.origin}${MOVIIE_TELEMETRY_API_PATH_PREFIX}`)\n}\n\n/**\n * Applies global SDK endpoint configuration (e.g. Expo reads `expo.extra` at bootstrap).\n * When unset, `MoviieClient` uses `MOVIIE_DEFAULT_API_BASE_URL`.\n * Telemetry defaults to the same **origin** as the API with path `MOVIIE_TELEMETRY_API_PATH_PREFIX`.\n */\nexport function configureMoviieEndpoints(options: MoviieEndpointsConfiguration): void {\n if (options.apiBaseUrl !== undefined) {\n if (options.apiBaseUrl == null || options.apiBaseUrl.trim() === \"\") {\n configuredApiBaseUrl = null\n } else {\n configuredApiBaseUrl = normalizeEndpointBase(options.apiBaseUrl)\n }\n }\n if (options.eventsBaseUrl !== undefined) {\n if (options.eventsBaseUrl == null || options.eventsBaseUrl.trim() === \"\") {\n configuredEventsBaseUrl = null\n } else {\n configuredEventsBaseUrl = normalizeEndpointBase(options.eventsBaseUrl)\n }\n }\n}\n\n/** Clears configuration — use in tests between cases. */\nexport function resetMoviieEndpointsConfiguration(): void {\n configuredApiBaseUrl = null\n configuredEventsBaseUrl = null\n}\n\nexport function getMoviieApiBaseUrl(): string {\n return configuredApiBaseUrl ?? MOVIIE_DEFAULT_API_BASE_URL\n}\n\nexport function getMoviieEventsBaseUrl(): string {\n if (\n process.env.NODE_ENV === \"test\" &&\n process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE?.trim()\n ) {\n return normalizeEndpointBase(process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE)\n }\n if (configuredEventsBaseUrl != null) {\n return configuredEventsBaseUrl\n }\n return deriveMoviieTelemetryBaseUrlFromApiBaseUrl(getMoviieApiBaseUrl())\n}\n\nexport const MOVIIE_CDN_BASE = \"https://cdn.moviie.ai\"\n\nexport const MOVIIE_WATCH_BASE = \"https://watch.moviie.ai\"\n","export type MoviieErrorCode =\n | \"auth\"\n | \"not_found\"\n | \"bundle_blocked\"\n | \"referrer_blocked\"\n | \"subscription_inactive\"\n | \"network\"\n | \"rate_limit\"\n | \"unknown\"\n\nexport class MoviieAuthError extends Error {\n readonly code: MoviieErrorCode = \"auth\"\n\n constructor(message = \"Autenticação necessária ou chave inválida\") {\n super(message)\n this.name = \"MoviieAuthError\"\n }\n}\n\nexport class MoviieNotFoundError extends Error {\n readonly code: MoviieErrorCode = \"not_found\"\n\n constructor(message = \"Recurso não encontrado\") {\n super(message)\n this.name = \"MoviieNotFoundError\"\n }\n}\n\nexport class MoviieBundleBlockedError extends Error {\n readonly code: MoviieErrorCode = \"bundle_blocked\"\n\n constructor(message = \"Este aplicativo não está autorizado a reproduzir este vídeo\") {\n super(message)\n this.name = \"MoviieBundleBlockedError\"\n }\n}\n\nexport class MoviieReferrerBlockedError extends Error {\n readonly code: MoviieErrorCode = \"referrer_blocked\"\n\n constructor(message = \"Origem não autorizada para reprodução\") {\n super(message)\n this.name = \"MoviieReferrerBlockedError\"\n }\n}\n\nexport class MoviieSubscriptionInactiveError extends Error {\n readonly code: MoviieErrorCode = \"subscription_inactive\"\n\n constructor(message = \"Reprodução temporariamente indisponível para esta organização\") {\n super(message)\n this.name = \"MoviieSubscriptionInactiveError\"\n }\n}\n\nexport class MoviieNetworkError extends Error {\n readonly code: MoviieErrorCode = \"network\"\n\n constructor(message = \"Falha de rede. Tente novamente\") {\n super(message)\n this.name = \"MoviieNetworkError\"\n }\n}\n\nexport class MoviieRateLimitError extends Error {\n readonly code: MoviieErrorCode = \"rate_limit\"\n\n constructor(message = \"Muitas solicitações. Aguarde e tente novamente\") {\n super(message)\n this.name = \"MoviieRateLimitError\"\n }\n}\n","import {\n MoviieNetworkError,\n MoviieRateLimitError,\n} from \"./errors\"\n\nexport interface HttpRequestOptions extends RequestInit {\n timeoutMs?: number\n retries?: number\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_RETRIES = 2\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction backoffDelayMs(attempt: number): number {\n const base = 2 ** attempt * 200\n const jitter = Math.floor(Math.random() * 200)\n return base + jitter\n}\n\nfunction composeAbortSignals(\n external: AbortSignal | null | undefined,\n internal: AbortSignal\n): AbortSignal {\n if (!external) return internal\n if (external.aborted) return external\n\n const controller = new AbortController()\n const onAbort = (signal: AbortSignal) => () => {\n controller.abort(signal.reason)\n }\n external.addEventListener(\"abort\", onAbort(external), { once: true })\n internal.addEventListener(\"abort\", onAbort(internal), { once: true })\n return controller.signal\n}\n\nexport async function fetchWithRetry(\n input: string | URL,\n init: HttpRequestOptions = {}\n): Promise<Response> {\n const timeoutMs = init.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const maxRetries = init.retries ?? DEFAULT_RETRIES\n const { timeoutMs: _t, retries: _r, signal: externalSignal, ...rest } = init\n\n let lastError: unknown\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const timeoutController = new AbortController()\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs)\n const signal = composeAbortSignals(externalSignal, timeoutController.signal)\n\n try {\n const response = await fetch(input, { ...rest, signal })\n clearTimeout(timer)\n\n if (response.status === 429) {\n throw new MoviieRateLimitError()\n }\n\n if (response.status >= 500 && response.status < 600 && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n\n if (error instanceof MoviieRateLimitError) throw error\n\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const isAbort = error instanceof Error && error.name === \"AbortError\"\n if (isAbort && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n if (attempt >= maxRetries) {\n throw new MoviieNetworkError()\n }\n\n await delay(backoffDelayMs(attempt))\n }\n }\n\n throw lastError instanceof Error ? lastError : new MoviieNetworkError()\n}\n","import type { MoviieClientInfo } from \"../types\"\n\nconst SEPARATOR = \";\"\n\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[\\r\\n;]/g, \"\").trim()\n}\n\nexport function buildClientHeaders(params: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const key = params.publishableKey?.trim()\n if (key) {\n headers.Authorization = `Bearer ${key}`\n }\n\n const info = params.clientInfo\n if (info) {\n const parts: string[] = []\n if (info.bundleId) {\n parts.push(`bundle_id=${sanitizeSegment(info.bundleId)}`)\n }\n parts.push(`platform=${sanitizeSegment(info.platform)}`)\n const sdk = params.sdkVersion ?? info.sdkVersion\n if (sdk) {\n parts.push(`sdk=${sanitizeSegment(sdk)}`)\n }\n headers[\"X-Moviie-Client\"] = parts.join(SEPARATOR)\n }\n\n return headers\n}\n","import {\n HTTP_HEADER_MOVIIE_REASON,\n MOVIIE_BLOCK_REASON,\n} from \"../constants\"\nimport {\n MoviieAuthError,\n MoviieBundleBlockedError,\n MoviieNetworkError,\n MoviieNotFoundError,\n MoviieReferrerBlockedError,\n MoviieSubscriptionInactiveError,\n} from \"../client/errors\"\nimport { fetchWithRetry } from \"../client/http\"\nimport type { MoviiePlaybackData } from \"../types\"\n\nimport { z } from \"zod\"\n\nconst playbackPayloadSchema = z.object({\n uri: z.string().url(),\n contentType: z.enum([\"hls\", \"progressive\"]),\n expiresAt: z.string().nullable(),\n refreshAfter: z.string().nullable(),\n requestHeaders: z.record(z.string()).optional(),\n})\n\nexport const moviiePlaybackDataResponseSchema = z\n .object({\n embedId: z.string(),\n title: z.string(),\n smartProgressEnabled: z.boolean(),\n durationSeconds: z.number().nullable(),\n isVertical: z.boolean(),\n videoWidthPx: z.number().int().positive().nullable(),\n videoHeightPx: z.number().int().positive().nullable(),\n profile: z.string(),\n playback: playbackPayloadSchema,\n posterUrl: z.string().nullable(),\n branding: z.object({\n primaryColor: z.string().nullable(),\n showWatermark: z.boolean(),\n organizationName: z.string().nullable(),\n }),\n telemetry: z.object({\n bootstrapUrl: z.string().url(),\n }),\n })\n .passthrough()\n\nexport async function fetchPlaybackData(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<MoviiePlaybackData> {\n const response = await fetchWithRetry(params.url, {\n headers: params.headers,\n signal: params.signal,\n method: \"GET\",\n })\n\n const reason = response.headers.get(HTTP_HEADER_MOVIIE_REASON)?.toLowerCase()\n\n if (response.status === 401) {\n throw new MoviieAuthError()\n }\n\n if (response.status === 402) {\n throw new MoviieSubscriptionInactiveError()\n }\n\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n\n if (response.status === 403) {\n if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {\n throw new MoviieBundleBlockedError()\n }\n throw new MoviieReferrerBlockedError()\n }\n\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n\n if (!response.ok) {\n throw new MoviieNotFoundError(\"Não foi possível carregar a reprodução\")\n }\n\n const json: unknown = await response.json()\n const parsed = moviiePlaybackDataResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError(\"Resposta de playback inválida\")\n }\n\n return parsed.data as unknown as MoviiePlaybackData\n}\n","import { z } from \"zod\"\n\nimport {\n SDK_PLAYBACK_AUTH_ERROR_MESSAGE,\n SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE,\n} from \"../constants\"\nimport { getMoviieApiBaseUrl, getMoviieEventsBaseUrl } from \"../config/moviie-endpoints\"\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from \"./errors\"\nimport { fetchWithRetry } from \"./http\"\nimport { buildClientHeaders } from \"./client-headers\"\nimport { fetchPlaybackData } from \"../playback/fetch-playback\"\nimport type { MoviieClientInfo, MoviiePlaybackData, MoviieVideo } from \"../types\"\n\nconst videoEmbedResponseSchema = z.object({\n id: z.string().uuid(),\n embed_id: z.string().uuid(),\n})\n\nexport class MoviieClient {\n constructor(\n private readonly options: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n }\n ) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n ...buildClientHeaders({\n publishableKey: this.options.publishableKey ?? undefined,\n clientInfo: this.options.clientInfo ?? undefined,\n sdkVersion: this.options.sdkVersion,\n }),\n ...extra,\n }\n }\n\n async getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, \"\")\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/playback`\n return fetchPlaybackData({\n url,\n headers: this.headers(),\n signal,\n })\n }\n\n async getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(\"Chave de API obrigatória para buscar vídeo por ID\")\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(\"Chave publishable não pode listar vídeos administrativos\")\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, \"\")\n const url = `${base}/videos/${encodeURIComponent(videoId)}`\n const response = await fetchWithRetry(url, {\n method: \"GET\",\n headers: this.headers(),\n signal,\n })\n\n if (response.status === 401 || response.status === 403) {\n throw new MoviieAuthError()\n }\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n if (!response.ok) {\n throw new MoviieNotFoundError()\n }\n\n const json: unknown = await response.json()\n const parsed = videoEmbedResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError(\"Resposta de vídeo inválida\")\n }\n\n return {\n id: parsed.data.id,\n embedId: parsed.data.embed_id,\n }\n }\n\n async resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string> {\n const video = await this.getVideo(videoId, signal)\n if (!video.embedId) {\n throw new MoviieNotFoundError(\"Embed não encontrado para este vídeo\")\n }\n return video.embedId\n }\n\n getEventsBaseUrl(): string {\n return getMoviieEventsBaseUrl().replace(/\\/+$/, \"\")\n }\n}\n","import { z } from \"zod\"\n\nexport const PLAYBACK_EVENT_TYPE = {\n SESSION_START: \"session_start\",\n PLAY_START: \"play_start\",\n PAUSE: \"pause\",\n RESUME: \"resume\",\n HEARTBEAT: \"heartbeat\",\n ENDED: \"ended\",\n CTA_CLICK: \"cta_click\",\n ERROR: \"error\",\n} as const\n\nexport const PLAYBACK_EVENT_TYPE_VALUES = Object.values(PLAYBACK_EVENT_TYPE)\n\nexport const playbackEventTypeSchema = z.enum(\n PLAYBACK_EVENT_TYPE_VALUES as [string, ...string[]]\n)\n\nexport type PlaybackEventType = z.infer<typeof playbackEventTypeSchema>\n\nexport const TELEMETRY_TOKEN_CONFIG = {\n INGEST_TOKEN_EXPIRY_SECONDS: 600,\n REFRESH_TOKEN_EXPIRY_SECONDS: 86400,\n REFRESH_BUFFER_SECONDS: 120,\n} as const\n\nexport const HEARTBEAT_CONFIG = {\n INTERVAL_SECONDS: 10,\n WATCH_TIME_PER_HEARTBEAT_SECONDS: 10,\n} as const\n\nexport const bootstrapResponseSchema = z.object({\n sessionId: z.string().uuid(),\n eventsIngestToken: z.string(),\n eventsRefreshToken: z.string(),\n ctaId: z.string().optional(),\n})\n\nexport type BootstrapResponse = z.infer<typeof bootstrapResponseSchema>\n\nexport const tokenRefreshRequestSchema = z.object({\n sessionId: z.string().uuid(),\n eventsRefreshToken: z.string(),\n})\n\nexport const tokenRefreshResponseSchema = z.object({\n eventsIngestToken: z.string(),\n expiresInSeconds: z.number(),\n})\n\nexport type TokenRefreshResponse = z.infer<typeof tokenRefreshResponseSchema>\n\nexport const playbackEventSchema = z.object({\n eventId: z.string().uuid(),\n sessionId: z.string().uuid(),\n eventType: playbackEventTypeSchema,\n positionSeconds: z.number().int().min(0).optional(),\n ctaId: z.string().optional(),\n errorCode: z.string().max(50).optional(),\n})\n\nexport const eventIngestRequestSchema = z.object({\n events: z.array(playbackEventSchema).min(1).max(100),\n ingestToken: z.string().optional(),\n})\n\nexport type PlaybackTelemetryEvent = z.infer<typeof playbackEventSchema>\n","export class HeartbeatScheduler {\n private timer: ReturnType<typeof setInterval> | null = null\n private paused = false\n\n constructor(\n private readonly options: {\n intervalSeconds: number\n onTick: () => void\n }\n ) {}\n\n start(): void {\n if (this.timer) return\n const ms = Math.max(1_000, this.options.intervalSeconds * 1000)\n this.timer = setInterval(() => {\n if (!this.paused) {\n this.options.onTick()\n }\n }, ms)\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n pause(): void {\n this.paused = true\n }\n\n resume(): void {\n this.paused = false\n }\n\n destroy(): void {\n this.stop()\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport {\n bootstrapResponseSchema,\n TELEMETRY_TOKEN_CONFIG,\n tokenRefreshRequestSchema,\n tokenRefreshResponseSchema,\n type BootstrapResponse,\n} from \"./types\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst REFRESH_MIN_DELAY_MS = 5_000\nconst REFRESH_RETRY_BACKOFF_MS = [5_000, 15_000, 60_000]\n\nexport class TelemetryTokenManager {\n private ingestToken: string | null = null\n private refreshToken: string | null = null\n private sessionId: string | null = null\n private refreshTimer: ReturnType<typeof setTimeout> | null = null\n private refreshFailureCount = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n }\n ) {}\n\n getSessionId(): string | null {\n return this.sessionId\n }\n\n getIngestToken(): string | null {\n return this.ingestToken\n }\n\n async bootstrap(bootstrapUrl: string): Promise<BootstrapResponse> {\n const response = await fetchWithRetry(bootstrapUrl, {\n method: \"GET\",\n headers: this.options.defaultHeaders,\n })\n\n if (!response.ok) {\n throw new Error(`Bootstrap falhou: ${response.status}`)\n }\n\n const json: unknown = await response.json()\n const parsed = bootstrapResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new Error(\"Resposta de bootstrap inválida\")\n }\n\n this.sessionId = parsed.data.sessionId\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshToken = parsed.data.eventsRefreshToken\n\n const store = this.options.viewerTokenStore\n if (store && parsed.data.eventsRefreshToken) {\n await store.set(parsed.data.eventsRefreshToken, TELEMETRY_TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY_SECONDS)\n }\n\n this.refreshFailureCount = 0\n this.scheduleRefresh(TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS)\n return parsed.data\n }\n\n private scheduleRefresh(expirySeconds: number): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const delayMs =\n (expirySeconds - TELEMETRY_TOKEN_CONFIG.REFRESH_BUFFER_SECONDS) * 1000\n\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, Math.max(REFRESH_MIN_DELAY_MS, delayMs))\n }\n\n private scheduleRefreshRetry(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const index = Math.min(\n this.refreshFailureCount,\n REFRESH_RETRY_BACKOFF_MS.length - 1\n )\n const base = REFRESH_RETRY_BACKOFF_MS[index] ?? REFRESH_MIN_DELAY_MS\n const jitter = Math.floor(Math.random() * 1_000)\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, base + jitter)\n }\n\n private async refresh(refreshUrl: string): Promise<void> {\n if (!this.sessionId || !this.refreshToken) return\n\n const body = tokenRefreshRequestSchema.parse({\n sessionId: this.sessionId,\n eventsRefreshToken: this.refreshToken,\n })\n\n try {\n const response = await fetchWithRetry(refreshUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n const json: unknown = await response.json()\n const parsed = tokenRefreshResponseSchema.safeParse(json)\n if (!parsed.success) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshFailureCount = 0\n const nextExpiry =\n parsed.data.expiresInSeconds > 0\n ? parsed.data.expiresInSeconds\n : TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS\n this.scheduleRefresh(nextExpiry)\n } catch {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n }\n }\n\n destroy(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport { HEARTBEAT_CONFIG, PLAYBACK_EVENT_TYPE, type PlaybackEventType } from \"./types\"\nimport { HeartbeatScheduler } from \"./heartbeat-scheduler\"\nimport { TelemetryTokenManager } from \"./token-manager\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst BATCH_MAX = 10\nconst FLUSH_MS = 5_000\n\nfunction randomHex(length: number): string {\n let out = \"\"\n while (out.length < length) {\n out += Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, \"0\")\n }\n return out.slice(0, length)\n}\n\nfunction newEventId(): string {\n const g = globalThis as typeof globalThis & {\n crypto?: { randomUUID?: () => string }\n }\n if (typeof g.crypto?.randomUUID === \"function\") {\n return g.crypto.randomUUID()\n }\n return `${randomHex(8)}-${randomHex(4)}-4${randomHex(3)}-8${randomHex(3)}-${randomHex(12)}`\n}\n\nexport class TelemetryClient {\n private readonly tokenManager: TelemetryTokenManager\n private readonly heartbeat: HeartbeatScheduler\n private pending: Array<Record<string, unknown>> = []\n private flushTimer: ReturnType<typeof setTimeout> | null = null\n private positionSeconds = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n getPositionSeconds?: () => number\n }\n ) {\n this.tokenManager = new TelemetryTokenManager({\n eventsBaseUrl: options.eventsBaseUrl,\n defaultHeaders: options.defaultHeaders,\n viewerTokenStore: options.viewerTokenStore,\n })\n\n this.heartbeat = new HeartbeatScheduler({\n intervalSeconds: HEARTBEAT_CONFIG.INTERVAL_SECONDS,\n onTick: () => {\n const pos =\n typeof options.getPositionSeconds === \"function\"\n ? Math.floor(options.getPositionSeconds())\n : this.positionSeconds\n void this.recordEvent({\n eventType: PLAYBACK_EVENT_TYPE.HEARTBEAT,\n positionSeconds: Math.max(0, pos),\n })\n },\n })\n }\n\n async bootstrap(params: { bootstrapUrl: string }): Promise<{ sessionId: string }> {\n const res = await this.tokenManager.bootstrap(params.bootstrapUrl)\n return { sessionId: res.sessionId }\n }\n\n updatePosition(seconds: number): void {\n this.positionSeconds = Math.max(0, seconds)\n }\n\n async recordEvent(params: {\n eventType: PlaybackEventType\n positionSeconds?: number\n ctaId?: string\n errorCode?: string\n }): Promise<void> {\n const sessionId = this.tokenManager.getSessionId()\n if (!sessionId) return\n\n const payload: Record<string, unknown> = {\n eventId: newEventId(),\n sessionId,\n eventType: params.eventType,\n }\n if (params.positionSeconds !== undefined) {\n payload.positionSeconds = params.positionSeconds\n }\n if (params.ctaId !== undefined) {\n payload.ctaId = params.ctaId\n }\n if (params.errorCode !== undefined) {\n payload.errorCode = params.errorCode\n }\n\n this.pending.push(payload)\n if (this.pending.length >= BATCH_MAX) {\n await this.flush()\n } else {\n this.scheduleFlush()\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null\n void this.flush()\n }, FLUSH_MS)\n }\n\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = null\n }\n\n if (this.pending.length === 0) {\n return\n }\n\n const ingestToken = this.tokenManager.getIngestToken()\n const sessionId = this.tokenManager.getSessionId()\n if (!ingestToken || !sessionId) {\n this.scheduleFlush()\n return\n }\n\n const batch = this.pending.splice(0, BATCH_MAX)\n const eventsUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/events`\n\n try {\n const response = await fetchWithRetry(eventsUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${ingestToken}`,\n },\n body: JSON.stringify({ events: batch }),\n })\n if (!response.ok && response.status >= 500) {\n this.pending.unshift(...batch)\n }\n } catch {\n this.pending.unshift(...batch)\n }\n\n if (this.pending.length > 0) {\n this.scheduleFlush()\n }\n }\n\n startHeartbeats(): void {\n this.heartbeat.start()\n }\n\n stopHeartbeats(): void {\n this.heartbeat.stop()\n }\n\n pauseHeartbeats(): void {\n this.heartbeat.pause()\n }\n\n resumeHeartbeats(): void {\n this.heartbeat.resume()\n }\n\n async destroy(): Promise<void> {\n this.heartbeat.destroy()\n this.tokenManager.destroy()\n await this.flush()\n }\n}\n","export interface ViewerTokenStore {\n get(): Promise<string | null>\n set(token: string, ttlSec: number): Promise<void>\n}\n\nexport class MemoryViewerTokenStore implements ViewerTokenStore {\n private value: string | null = null\n\n async get(): Promise<string | null> {\n return this.value\n }\n\n async set(token: string, _ttlSec: number): Promise<void> {\n this.value = token\n }\n}\n","import type { MoviiePlaybackPayload } from \"../types\"\n\nconst REFRESH_BUFFER_MS = 60_000\n\nexport function planRefresh(params: {\n playback: Pick<MoviiePlaybackPayload, \"expiresAt\" | \"refreshAfter\">\n now: Date\n}): { delayMs: number } | null {\n const { expiresAt, refreshAfter } = params.playback\n if (!expiresAt && !refreshAfter) {\n return null\n }\n\n const anchorIso = refreshAfter ?? expiresAt\n if (!anchorIso) return null\n\n const anchor = Date.parse(anchorIso)\n if (!Number.isFinite(anchor)) return null\n\n const target = anchor - REFRESH_BUFFER_MS\n const delayMs = Math.max(0, target - params.now.getTime())\n return { delayMs }\n}\n","const BOOTSTRAP_SEGMENT_PATTERN = /\\/bootstrap\\/[^/]+\\/?$/i\n\nconst TELEMETRY_PATH_MARKER = \"/telemetry\"\n\nexport function deriveTelemetryEventsBaseUrlFromBootstrapUrl(\n bootstrapUrl: string\n): string | null {\n try {\n const u = new URL(bootstrapUrl)\n const stripped = u.pathname.replace(BOOTSTRAP_SEGMENT_PATTERN, \"\")\n if (!stripped.includes(TELEMETRY_PATH_MARKER)) {\n return null\n }\n const normalizedPath = stripped.replace(/\\/+$/, \"\") || \"/\"\n return `${u.origin}${normalizedPath}`\n } catch {\n return null\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/config/moviie-endpoints.ts","../src/client/errors.ts","../src/client/http.ts","../src/client/client-headers.ts","../src/playback/fetch-playback.ts","../src/search/transcript-search-client.ts","../src/client/moviie-client.ts","../src/telemetry/types.ts","../src/telemetry/heartbeat-scheduler.ts","../src/telemetry/token-manager.ts","../src/telemetry/telemetry-client.ts","../src/telemetry/viewer-token-store.ts","../src/playback/playback-refresh.ts","../src/config/telemetry-bootstrap-url.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Default Public REST API base URL for production clients (OpenAPI `/v1/*` paths).\n *\n * Requests use `{MOVIIE_DEFAULT_API_BASE_URL}/embeds/{embedId}/playback`, etc.\n */\nexport const MOVIIE_DEFAULT_API_BASE_URL = 'https://api.moviie.ai/v1' as const\n\n/**\n * Path segment for telemetry on the **same origin** as the Public API (bootstrap, ingest, token refresh).\n */\nexport const MOVIIE_TELEMETRY_API_PATH_PREFIX = '/telemetry/v1' as const\n\nexport const SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = 'mvi_pub_' as const\n\nexport const SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {\n KEY_REQUIRED: 'Publishable API key is required for playback.',\n PRIVATE_KEY_FORBIDDEN:\n 'Do not use a private API key for playback; use a publishable key (mvi_pub_*).',\n} as const\n\nexport const HTTP_HEADER_MOVIIE_REASON = 'x-moviie-reason' as const\n\nexport const MOVIIE_BLOCK_REASON = {\n BUNDLE: 'bundle',\n DIRECT_ACCESS: 'direct_access_blocked',\n} as const\n","import {\n MOVIIE_DEFAULT_API_BASE_URL,\n MOVIIE_TELEMETRY_API_PATH_PREFIX,\n} from \"../constants\"\n\nlet configuredApiBaseUrl: string | null = null\nlet configuredEventsBaseUrl: string | null = null\n\nexport type MoviieEndpointsConfiguration = {\n /** API base URL override without trailing slash. Pass `null` or empty to clear. */\n apiBaseUrl?: string | null\n /**\n * Telemetry base (`…/telemetry/v1`) without trailing slash.\n * Pass `null` or empty to clear and derive from the API origin again.\n */\n eventsBaseUrl?: string | null\n}\n\nfunction normalizeEndpointBase(raw: string): string {\n return raw.trim().replace(/\\/+$/, \"\")\n}\n\n/**\n * Builds `{apiOrigin}/telemetry/v1` from a configured API base (e.g. `https://host/api/v1` → `https://host/telemetry/v1`).\n */\nexport function deriveMoviieTelemetryBaseUrlFromApiBaseUrl(apiBaseUrl: string): string {\n const trimmed = normalizeEndpointBase(apiBaseUrl)\n const href = trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`\n const u = new URL(href)\n return normalizeEndpointBase(`${u.origin}${MOVIIE_TELEMETRY_API_PATH_PREFIX}`)\n}\n\n/**\n * Applies global SDK endpoint configuration (e.g. Expo reads `expo.extra` at bootstrap).\n * When unset, `MoviieClient` uses `MOVIIE_DEFAULT_API_BASE_URL`.\n * Telemetry defaults to the same **origin** as the API with path `MOVIIE_TELEMETRY_API_PATH_PREFIX`.\n */\nexport function configureMoviieEndpoints(options: MoviieEndpointsConfiguration): void {\n if (options.apiBaseUrl !== undefined) {\n if (options.apiBaseUrl == null || options.apiBaseUrl.trim() === \"\") {\n configuredApiBaseUrl = null\n } else {\n configuredApiBaseUrl = normalizeEndpointBase(options.apiBaseUrl)\n }\n }\n if (options.eventsBaseUrl !== undefined) {\n if (options.eventsBaseUrl == null || options.eventsBaseUrl.trim() === \"\") {\n configuredEventsBaseUrl = null\n } else {\n configuredEventsBaseUrl = normalizeEndpointBase(options.eventsBaseUrl)\n }\n }\n}\n\n/** Clears configuration — use in tests between cases. */\nexport function resetMoviieEndpointsConfiguration(): void {\n configuredApiBaseUrl = null\n configuredEventsBaseUrl = null\n}\n\nexport function getMoviieApiBaseUrl(): string {\n return configuredApiBaseUrl ?? MOVIIE_DEFAULT_API_BASE_URL\n}\n\nexport function getMoviieEventsBaseUrl(): string {\n if (\n process.env.NODE_ENV === \"test\" &&\n process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE?.trim()\n ) {\n return normalizeEndpointBase(process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE)\n }\n if (configuredEventsBaseUrl != null) {\n return configuredEventsBaseUrl\n }\n return deriveMoviieTelemetryBaseUrlFromApiBaseUrl(getMoviieApiBaseUrl())\n}\n\nexport const MOVIIE_CDN_BASE = \"https://cdn.moviie.ai\"\n\nexport const MOVIIE_WATCH_BASE = \"https://watch.moviie.ai\"\n","export type MoviieErrorCode =\n | 'auth'\n | 'not_found'\n | 'bundle_blocked'\n | 'referrer_blocked'\n | 'direct_access_blocked'\n | 'subscription_inactive'\n | 'network'\n | 'rate_limit'\n | 'unknown'\n\nexport class MoviieAuthError extends Error {\n readonly code: MoviieErrorCode = 'auth'\n\n constructor(message = 'Autenticação necessária ou chave inválida') {\n super(message)\n this.name = 'MoviieAuthError'\n }\n}\n\nexport class MoviieNotFoundError extends Error {\n readonly code: MoviieErrorCode = 'not_found'\n\n constructor(message = 'Recurso não encontrado') {\n super(message)\n this.name = 'MoviieNotFoundError'\n }\n}\n\nexport class MoviieBundleBlockedError extends Error {\n readonly code: MoviieErrorCode = 'bundle_blocked'\n\n constructor(message = 'Este aplicativo não está autorizado a reproduzir este vídeo') {\n super(message)\n this.name = 'MoviieBundleBlockedError'\n }\n}\n\nexport class MoviieReferrerBlockedError extends Error {\n readonly code: MoviieErrorCode = 'referrer_blocked'\n\n constructor(message = 'Origem não autorizada para reprodução') {\n super(message)\n this.name = 'MoviieReferrerBlockedError'\n }\n}\n\nexport class MoviieDirectAccessBlockedError extends Error {\n readonly code: MoviieErrorCode = 'direct_access_blocked'\n\n constructor(message = 'Este vídeo não pode ser reproduzido diretamente pela URL') {\n super(message)\n this.name = 'MoviieDirectAccessBlockedError'\n }\n}\n\nexport class MoviieSubscriptionInactiveError extends Error {\n readonly code: MoviieErrorCode = 'subscription_inactive'\n\n constructor(message = 'Reprodução temporariamente indisponível para esta organização') {\n super(message)\n this.name = 'MoviieSubscriptionInactiveError'\n }\n}\n\nexport class MoviieNetworkError extends Error {\n readonly code: MoviieErrorCode = 'network'\n\n constructor(message = 'Falha de rede. Tente novamente') {\n super(message)\n this.name = 'MoviieNetworkError'\n }\n}\n\nexport class MoviieRateLimitError extends Error {\n readonly code: MoviieErrorCode = 'rate_limit'\n\n constructor(message = 'Muitas solicitações. Aguarde e tente novamente') {\n super(message)\n this.name = 'MoviieRateLimitError'\n }\n}\n","import {\n MoviieNetworkError,\n MoviieRateLimitError,\n} from \"./errors\"\n\nexport interface HttpRequestOptions extends RequestInit {\n timeoutMs?: number\n retries?: number\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_RETRIES = 2\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction backoffDelayMs(attempt: number): number {\n const base = 2 ** attempt * 200\n const jitter = Math.floor(Math.random() * 200)\n return base + jitter\n}\n\nfunction composeAbortSignals(\n external: AbortSignal | null | undefined,\n internal: AbortSignal\n): AbortSignal {\n if (!external) return internal\n if (external.aborted) return external\n\n const controller = new AbortController()\n const onAbort = (signal: AbortSignal) => () => {\n controller.abort(signal.reason)\n }\n external.addEventListener(\"abort\", onAbort(external), { once: true })\n internal.addEventListener(\"abort\", onAbort(internal), { once: true })\n return controller.signal\n}\n\nexport async function fetchWithRetry(\n input: string | URL,\n init: HttpRequestOptions = {}\n): Promise<Response> {\n const timeoutMs = init.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const maxRetries = init.retries ?? DEFAULT_RETRIES\n const { timeoutMs: _t, retries: _r, signal: externalSignal, ...rest } = init\n\n let lastError: unknown\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const timeoutController = new AbortController()\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs)\n const signal = composeAbortSignals(externalSignal, timeoutController.signal)\n\n try {\n const response = await fetch(input, { ...rest, signal })\n clearTimeout(timer)\n\n if (response.status === 429) {\n throw new MoviieRateLimitError()\n }\n\n if (response.status >= 500 && response.status < 600 && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n\n if (error instanceof MoviieRateLimitError) throw error\n\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const isAbort = error instanceof Error && error.name === \"AbortError\"\n if (isAbort && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n if (attempt >= maxRetries) {\n throw new MoviieNetworkError()\n }\n\n await delay(backoffDelayMs(attempt))\n }\n }\n\n throw lastError instanceof Error ? lastError : new MoviieNetworkError()\n}\n","import type { MoviieClientInfo } from \"../types\"\n\nconst SEPARATOR = \";\"\n\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[\\r\\n;]/g, \"\").trim()\n}\n\nexport function buildClientHeaders(params: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const key = params.publishableKey?.trim()\n if (key) {\n headers.Authorization = `Bearer ${key}`\n }\n\n const info = params.clientInfo\n if (info) {\n const parts: string[] = []\n if (info.bundleId) {\n parts.push(`bundle_id=${sanitizeSegment(info.bundleId)}`)\n }\n parts.push(`platform=${sanitizeSegment(info.platform)}`)\n const sdk = params.sdkVersion ?? info.sdkVersion\n if (sdk) {\n parts.push(`sdk=${sanitizeSegment(sdk)}`)\n }\n headers[\"X-Moviie-Client\"] = parts.join(SEPARATOR)\n }\n\n return headers\n}\n","import { HTTP_HEADER_MOVIIE_REASON, MOVIIE_BLOCK_REASON } from '../constants'\nimport {\n MoviieAuthError,\n MoviieBundleBlockedError,\n MoviieDirectAccessBlockedError,\n MoviieNetworkError,\n MoviieNotFoundError,\n MoviieReferrerBlockedError,\n MoviieSubscriptionInactiveError,\n} from '../client/errors'\nimport { fetchWithRetry } from '../client/http'\nimport type { MoviiePlaybackData } from '../types'\n\nimport { z } from 'zod'\n\nconst playbackPayloadSchema = z.object({\n uri: z.string().url(),\n contentType: z.enum(['hls', 'progressive']),\n expiresAt: z.string().nullable(),\n refreshAfter: z.string().nullable(),\n requestHeaders: z.record(z.string()).optional(),\n})\n\nexport const moviiePlaybackDataResponseSchema = z\n .object({\n embedId: z.string(),\n title: z.string(),\n smartProgressEnabled: z.boolean(),\n durationSeconds: z.number().nullable(),\n isVertical: z.boolean(),\n videoWidthPx: z.number().int().positive().nullable(),\n videoHeightPx: z.number().int().positive().nullable(),\n profile: z.string(),\n playback: playbackPayloadSchema,\n posterUrl: z.string().nullable(),\n branding: z.object({\n primaryColor: z.string().nullable(),\n showWatermark: z.boolean(),\n organizationName: z.string().nullable(),\n }),\n telemetry: z.object({\n bootstrapUrl: z.string().url(),\n }),\n })\n .passthrough()\n\nexport async function fetchPlaybackData(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<MoviiePlaybackData> {\n const response = await fetchWithRetry(params.url, {\n headers: params.headers,\n signal: params.signal,\n method: 'GET',\n })\n\n const reason = response.headers.get(HTTP_HEADER_MOVIIE_REASON)?.toLowerCase()\n\n if (response.status === 401) {\n throw new MoviieAuthError()\n }\n\n if (response.status === 402) {\n throw new MoviieSubscriptionInactiveError()\n }\n\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n\n if (response.status === 403) {\n if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {\n throw new MoviieBundleBlockedError()\n }\n if (reason === MOVIIE_BLOCK_REASON.DIRECT_ACCESS) {\n throw new MoviieDirectAccessBlockedError()\n }\n throw new MoviieReferrerBlockedError()\n }\n\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n\n if (!response.ok) {\n throw new MoviieNotFoundError('Não foi possível carregar a reprodução')\n }\n\n const json: unknown = await response.json()\n const parsed = moviiePlaybackDataResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError('Resposta de playback inválida')\n }\n\n return parsed.data as unknown as MoviiePlaybackData\n}\n","import { z } from 'zod'\n\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from '../client/errors'\nimport { fetchWithRetry } from '../client/http'\n\n/** A single moment in the video where the term occurs. */\nexport interface TranscriptSearchMatch {\n segmentIndex: number\n startSeconds: number\n endSeconds: number\n /** The sentence/segment containing the term (length-bounded by the server). */\n text: string\n}\n\n/** Result set for one transcript search query. */\nexport interface TranscriptSearchResult {\n query: string\n language: string | null\n total: number\n matches: TranscriptSearchMatch[]\n nextCursor: number | null\n}\n\nconst matchSchema = z.object({\n segmentIndex: z.number().int(),\n startSeconds: z.number(),\n endSeconds: z.number(),\n text: z.string(),\n})\n\nconst resultSchema = z.object({\n query: z.string(),\n language: z.string().nullable(),\n total: z.number().int(),\n matches: z.array(matchSchema),\n nextCursor: z.number().int().nullable(),\n})\n\n/** Default debounce and minimum query length for the in-player search UI. */\nexport const TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250\nexport const TRANSCRIPT_SEARCH_MIN_LENGTH = 2\n\nconst EMPTY_RESULT = (query: string): TranscriptSearchResult => ({\n query,\n language: null,\n total: 0,\n matches: [],\n nextCursor: null,\n})\n\n/** Low-level fetch of the transcript search endpoint, with error mapping. */\nexport async function fetchTranscriptSearch(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<TranscriptSearchResult> {\n const response = await fetchWithRetry(params.url, {\n method: 'GET',\n headers: params.headers,\n signal: params.signal,\n })\n\n if (response.status === 401) throw new MoviieAuthError()\n // 429 is mapped to MoviieRateLimitError upstream by fetchWithRetry before a\n // Response is ever returned here, so no 429 branch is needed (or reachable).\n if (response.status === 404) throw new MoviieNotFoundError()\n if (response.status >= 500) throw new MoviieNetworkError()\n if (!response.ok) throw new MoviieNetworkError()\n\n const json: unknown = await response.json()\n const parsed = resultSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNetworkError('Resposta de busca inválida')\n }\n return parsed.data\n}\n\nexport interface TranscriptSearchController {\n /** Schedule a debounced search for the (trimmed) query. */\n search(query: string): void\n /** Cancel any pending debounce and in-flight request. */\n cancel(): void\n /** Tear down the controller. */\n destroy(): void\n}\n\n/**\n * UI controller that applies debounce + a minimum query length before calling\n * the search endpoint, and aborts any in-flight request when a newer query\n * arrives. Queries below the minimum length clear the results without hitting\n * the network — this is what keeps incomplete words from flooding the backend\n * (FR-003 / SC-002).\n */\nexport function createTranscriptSearchController(opts: {\n fetcher: (query: string, signal: AbortSignal) => Promise<TranscriptSearchResult>\n onResult: (result: TranscriptSearchResult) => void\n onError?: (error: unknown) => void\n onLoadingChange?: (loading: boolean) => void\n debounceMs?: number\n minLength?: number\n}): TranscriptSearchController {\n const debounceMs = opts.debounceMs ?? TRANSCRIPT_SEARCH_DEBOUNCE_MS\n const minLength = opts.minLength ?? TRANSCRIPT_SEARCH_MIN_LENGTH\n\n let timer: ReturnType<typeof setTimeout> | null = null\n let inFlight: AbortController | null = null\n\n function clearTimer(): void {\n if (timer !== null) {\n clearTimeout(timer)\n timer = null\n }\n }\n\n function cancelInFlight(): void {\n if (inFlight) {\n inFlight.abort()\n inFlight = null\n }\n }\n\n function search(rawQuery: string): void {\n const query = rawQuery.trim()\n clearTimer()\n\n if (query.length < minLength) {\n cancelInFlight()\n opts.onResult(EMPTY_RESULT(query))\n return\n }\n\n timer = setTimeout(() => {\n timer = null\n cancelInFlight()\n const controller = new AbortController()\n inFlight = controller\n opts.onLoadingChange?.(true)\n opts\n .fetcher(query, controller.signal)\n .then((result) => {\n if (!controller.signal.aborted) opts.onResult(result)\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted) return\n if (error instanceof Error && error.name === 'AbortError') return\n opts.onError?.(error)\n })\n .finally(() => {\n // Only the current request clears loading — a superseded/aborted\n // request must not hide the indicator belonging to a newer one.\n if (inFlight === controller) {\n inFlight = null\n opts.onLoadingChange?.(false)\n }\n })\n }, debounceMs)\n }\n\n return {\n search,\n cancel(): void {\n clearTimer()\n cancelInFlight()\n },\n destroy(): void {\n clearTimer()\n cancelInFlight()\n },\n }\n}\n","import { z } from 'zod'\n\nimport {\n SDK_PLAYBACK_AUTH_ERROR_MESSAGE,\n SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE,\n} from '../constants'\nimport { getMoviieApiBaseUrl, getMoviieEventsBaseUrl } from '../config/moviie-endpoints'\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from './errors'\nimport { fetchWithRetry } from './http'\nimport { buildClientHeaders } from './client-headers'\nimport { fetchPlaybackData } from '../playback/fetch-playback'\nimport {\n fetchTranscriptSearch,\n type TranscriptSearchResult,\n} from '../search/transcript-search-client'\nimport type { MoviieClientInfo, MoviiePlaybackData, MoviieVideo } from '../types'\n\nconst videoEmbedResponseSchema = z.object({\n id: z.string().uuid(),\n embed_id: z.string().uuid(),\n})\n\nexport class MoviieClient {\n constructor(\n private readonly options: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n }\n ) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n ...buildClientHeaders({\n publishableKey: this.options.publishableKey ?? undefined,\n clientInfo: this.options.clientInfo ?? undefined,\n sdkVersion: this.options.sdkVersion,\n }),\n ...extra,\n }\n }\n\n async getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/playback`\n return fetchPlaybackData({\n url,\n headers: this.headers(),\n signal,\n })\n }\n\n /**\n * Search the spoken content of the video a playback session is playing, and\n * return the moments where the term appears (each with a timestamp). The\n * session scopes the search to the video it actually loaded (swap-safe) and\n * authorizes the request — it was gated when bootstrapped. Obtain the session\n * id from the telemetry bootstrap. Matching is case- and accent-insensitive.\n */\n async search(\n sessionId: string,\n query: string,\n opts?: {\n limit?: number\n cursor?: number | null\n signal?: AbortSignal\n }\n ): Promise<TranscriptSearchResult> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const params = new URLSearchParams({ q: query })\n if (opts?.limit != null) params.set('limit', String(opts.limit))\n if (opts?.cursor != null) params.set('cursor', String(opts.cursor))\n const url = `${base}/sessions/${encodeURIComponent(sessionId)}/search?${params.toString()}`\n return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal })\n }\n\n /**\n * Private transcript search for an embed's video (feature 183) — the\n * authenticated twin of {@link search}. Requires a PRIVATE API key (publishable\n * keys are rejected) and is scoped to the key's organization; the embed must\n * belong to it. Unlike {@link search} it needs no playback session. Matching is\n * case- and accent-insensitive.\n */\n async searchEmbedTranscript(\n embedId: string,\n query: string,\n opts?: {\n limit?: number\n cursor?: number | null\n signal?: AbortSignal\n }\n ): Promise<TranscriptSearchResult> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError('A busca privada exige uma chave de API privada (não publishable).')\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const params = new URLSearchParams({ q: query })\n if (opts?.limit != null) params.set('limit', String(opts.limit))\n if (opts?.cursor != null) params.set('cursor', String(opts.cursor))\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/transcript/search?${params.toString()}`\n return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal })\n }\n\n async getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError('Chave de API obrigatória para buscar vídeo por ID')\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError('Chave publishable não pode listar vídeos administrativos')\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const url = `${base}/videos/${encodeURIComponent(videoId)}`\n const response = await fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n signal,\n })\n\n if (response.status === 401 || response.status === 403) {\n throw new MoviieAuthError()\n }\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n if (!response.ok) {\n throw new MoviieNotFoundError()\n }\n\n const json: unknown = await response.json()\n const parsed = videoEmbedResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError('Resposta de vídeo inválida')\n }\n\n return {\n id: parsed.data.id,\n embedId: parsed.data.embed_id,\n }\n }\n\n async resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string> {\n const video = await this.getVideo(videoId, signal)\n if (!video.embedId) {\n throw new MoviieNotFoundError('Embed não encontrado para este vídeo')\n }\n return video.embedId\n }\n\n getEventsBaseUrl(): string {\n return getMoviieEventsBaseUrl().replace(/\\/+$/, '')\n }\n}\n","import { z } from \"zod\"\n\nexport const PLAYBACK_EVENT_TYPE = {\n SESSION_START: \"session_start\",\n PLAY_START: \"play_start\",\n PAUSE: \"pause\",\n RESUME: \"resume\",\n HEARTBEAT: \"heartbeat\",\n ENDED: \"ended\",\n CTA_CLICK: \"cta_click\",\n ERROR: \"error\",\n} as const\n\nexport const PLAYBACK_EVENT_TYPE_VALUES = Object.values(PLAYBACK_EVENT_TYPE)\n\nexport const playbackEventTypeSchema = z.enum(\n PLAYBACK_EVENT_TYPE_VALUES as [string, ...string[]]\n)\n\nexport type PlaybackEventType = z.infer<typeof playbackEventTypeSchema>\n\nexport const TELEMETRY_TOKEN_CONFIG = {\n INGEST_TOKEN_EXPIRY_SECONDS: 600,\n REFRESH_TOKEN_EXPIRY_SECONDS: 86400,\n REFRESH_BUFFER_SECONDS: 120,\n} as const\n\nexport const HEARTBEAT_CONFIG = {\n INTERVAL_SECONDS: 10,\n WATCH_TIME_PER_HEARTBEAT_SECONDS: 10,\n} as const\n\nexport const bootstrapResponseSchema = z.object({\n sessionId: z.string().uuid(),\n eventsIngestToken: z.string(),\n eventsRefreshToken: z.string(),\n ctaId: z.string().optional(),\n})\n\nexport type BootstrapResponse = z.infer<typeof bootstrapResponseSchema>\n\nexport const tokenRefreshRequestSchema = z.object({\n sessionId: z.string().uuid(),\n eventsRefreshToken: z.string(),\n})\n\nexport const tokenRefreshResponseSchema = z.object({\n eventsIngestToken: z.string(),\n expiresInSeconds: z.number(),\n})\n\nexport type TokenRefreshResponse = z.infer<typeof tokenRefreshResponseSchema>\n\nexport const playbackEventSchema = z.object({\n eventId: z.string().uuid(),\n sessionId: z.string().uuid(),\n eventType: playbackEventTypeSchema,\n positionSeconds: z.number().int().min(0).optional(),\n ctaId: z.string().optional(),\n errorCode: z.string().max(50).optional(),\n})\n\nexport const eventIngestRequestSchema = z.object({\n events: z.array(playbackEventSchema).min(1).max(100),\n ingestToken: z.string().optional(),\n})\n\nexport type PlaybackTelemetryEvent = z.infer<typeof playbackEventSchema>\n","export class HeartbeatScheduler {\n private timer: ReturnType<typeof setInterval> | null = null\n private paused = false\n\n constructor(\n private readonly options: {\n intervalSeconds: number\n onTick: () => void\n }\n ) {}\n\n start(): void {\n if (this.timer) return\n const ms = Math.max(1_000, this.options.intervalSeconds * 1000)\n this.timer = setInterval(() => {\n if (!this.paused) {\n this.options.onTick()\n }\n }, ms)\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n pause(): void {\n this.paused = true\n }\n\n resume(): void {\n this.paused = false\n }\n\n destroy(): void {\n this.stop()\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport {\n bootstrapResponseSchema,\n TELEMETRY_TOKEN_CONFIG,\n tokenRefreshRequestSchema,\n tokenRefreshResponseSchema,\n type BootstrapResponse,\n} from \"./types\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst REFRESH_MIN_DELAY_MS = 5_000\nconst REFRESH_RETRY_BACKOFF_MS = [5_000, 15_000, 60_000]\n\nexport class TelemetryTokenManager {\n private ingestToken: string | null = null\n private refreshToken: string | null = null\n private sessionId: string | null = null\n private refreshTimer: ReturnType<typeof setTimeout> | null = null\n private refreshFailureCount = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n }\n ) {}\n\n getSessionId(): string | null {\n return this.sessionId\n }\n\n getIngestToken(): string | null {\n return this.ingestToken\n }\n\n async bootstrap(bootstrapUrl: string): Promise<BootstrapResponse> {\n const response = await fetchWithRetry(bootstrapUrl, {\n method: \"GET\",\n headers: this.options.defaultHeaders,\n })\n\n if (!response.ok) {\n throw new Error(`Bootstrap falhou: ${response.status}`)\n }\n\n const json: unknown = await response.json()\n const parsed = bootstrapResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new Error(\"Resposta de bootstrap inválida\")\n }\n\n this.sessionId = parsed.data.sessionId\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshToken = parsed.data.eventsRefreshToken\n\n const store = this.options.viewerTokenStore\n if (store && parsed.data.eventsRefreshToken) {\n await store.set(parsed.data.eventsRefreshToken, TELEMETRY_TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY_SECONDS)\n }\n\n this.refreshFailureCount = 0\n this.scheduleRefresh(TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS)\n return parsed.data\n }\n\n private scheduleRefresh(expirySeconds: number): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const delayMs =\n (expirySeconds - TELEMETRY_TOKEN_CONFIG.REFRESH_BUFFER_SECONDS) * 1000\n\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, Math.max(REFRESH_MIN_DELAY_MS, delayMs))\n }\n\n private scheduleRefreshRetry(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const index = Math.min(\n this.refreshFailureCount,\n REFRESH_RETRY_BACKOFF_MS.length - 1\n )\n const base = REFRESH_RETRY_BACKOFF_MS[index] ?? REFRESH_MIN_DELAY_MS\n const jitter = Math.floor(Math.random() * 1_000)\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, base + jitter)\n }\n\n private async refresh(refreshUrl: string): Promise<void> {\n if (!this.sessionId || !this.refreshToken) return\n\n const body = tokenRefreshRequestSchema.parse({\n sessionId: this.sessionId,\n eventsRefreshToken: this.refreshToken,\n })\n\n try {\n const response = await fetchWithRetry(refreshUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n const json: unknown = await response.json()\n const parsed = tokenRefreshResponseSchema.safeParse(json)\n if (!parsed.success) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshFailureCount = 0\n const nextExpiry =\n parsed.data.expiresInSeconds > 0\n ? parsed.data.expiresInSeconds\n : TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS\n this.scheduleRefresh(nextExpiry)\n } catch {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n }\n }\n\n destroy(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport { HEARTBEAT_CONFIG, PLAYBACK_EVENT_TYPE, type PlaybackEventType } from \"./types\"\nimport { HeartbeatScheduler } from \"./heartbeat-scheduler\"\nimport { TelemetryTokenManager } from \"./token-manager\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst BATCH_MAX = 10\nconst FLUSH_MS = 5_000\n\nfunction randomHex(length: number): string {\n let out = \"\"\n while (out.length < length) {\n out += Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, \"0\")\n }\n return out.slice(0, length)\n}\n\nfunction newEventId(): string {\n const g = globalThis as typeof globalThis & {\n crypto?: { randomUUID?: () => string }\n }\n if (typeof g.crypto?.randomUUID === \"function\") {\n return g.crypto.randomUUID()\n }\n return `${randomHex(8)}-${randomHex(4)}-4${randomHex(3)}-8${randomHex(3)}-${randomHex(12)}`\n}\n\nexport class TelemetryClient {\n private readonly tokenManager: TelemetryTokenManager\n private readonly heartbeat: HeartbeatScheduler\n private pending: Array<Record<string, unknown>> = []\n private flushTimer: ReturnType<typeof setTimeout> | null = null\n private positionSeconds = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n getPositionSeconds?: () => number\n }\n ) {\n this.tokenManager = new TelemetryTokenManager({\n eventsBaseUrl: options.eventsBaseUrl,\n defaultHeaders: options.defaultHeaders,\n viewerTokenStore: options.viewerTokenStore,\n })\n\n this.heartbeat = new HeartbeatScheduler({\n intervalSeconds: HEARTBEAT_CONFIG.INTERVAL_SECONDS,\n onTick: () => {\n const pos =\n typeof options.getPositionSeconds === \"function\"\n ? Math.floor(options.getPositionSeconds())\n : this.positionSeconds\n void this.recordEvent({\n eventType: PLAYBACK_EVENT_TYPE.HEARTBEAT,\n positionSeconds: Math.max(0, pos),\n })\n },\n })\n }\n\n async bootstrap(params: { bootstrapUrl: string }): Promise<{ sessionId: string }> {\n const res = await this.tokenManager.bootstrap(params.bootstrapUrl)\n return { sessionId: res.sessionId }\n }\n\n updatePosition(seconds: number): void {\n this.positionSeconds = Math.max(0, seconds)\n }\n\n async recordEvent(params: {\n eventType: PlaybackEventType\n positionSeconds?: number\n ctaId?: string\n errorCode?: string\n }): Promise<void> {\n const sessionId = this.tokenManager.getSessionId()\n if (!sessionId) return\n\n const payload: Record<string, unknown> = {\n eventId: newEventId(),\n sessionId,\n eventType: params.eventType,\n }\n if (params.positionSeconds !== undefined) {\n payload.positionSeconds = params.positionSeconds\n }\n if (params.ctaId !== undefined) {\n payload.ctaId = params.ctaId\n }\n if (params.errorCode !== undefined) {\n payload.errorCode = params.errorCode\n }\n\n this.pending.push(payload)\n if (this.pending.length >= BATCH_MAX) {\n await this.flush()\n } else {\n this.scheduleFlush()\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null\n void this.flush()\n }, FLUSH_MS)\n }\n\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = null\n }\n\n if (this.pending.length === 0) {\n return\n }\n\n const ingestToken = this.tokenManager.getIngestToken()\n const sessionId = this.tokenManager.getSessionId()\n if (!ingestToken || !sessionId) {\n this.scheduleFlush()\n return\n }\n\n const batch = this.pending.splice(0, BATCH_MAX)\n const eventsUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/events`\n\n try {\n const response = await fetchWithRetry(eventsUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${ingestToken}`,\n },\n body: JSON.stringify({ events: batch }),\n })\n if (!response.ok && response.status >= 500) {\n this.pending.unshift(...batch)\n }\n } catch {\n this.pending.unshift(...batch)\n }\n\n if (this.pending.length > 0) {\n this.scheduleFlush()\n }\n }\n\n startHeartbeats(): void {\n this.heartbeat.start()\n }\n\n stopHeartbeats(): void {\n this.heartbeat.stop()\n }\n\n pauseHeartbeats(): void {\n this.heartbeat.pause()\n }\n\n resumeHeartbeats(): void {\n this.heartbeat.resume()\n }\n\n async destroy(): Promise<void> {\n this.heartbeat.destroy()\n this.tokenManager.destroy()\n await this.flush()\n }\n}\n","export interface ViewerTokenStore {\n get(): Promise<string | null>\n set(token: string, ttlSec: number): Promise<void>\n}\n\nexport class MemoryViewerTokenStore implements ViewerTokenStore {\n private value: string | null = null\n\n async get(): Promise<string | null> {\n return this.value\n }\n\n async set(token: string, _ttlSec: number): Promise<void> {\n this.value = token\n }\n}\n","import type { MoviiePlaybackPayload } from \"../types\"\n\nconst REFRESH_BUFFER_MS = 60_000\n\nexport function planRefresh(params: {\n playback: Pick<MoviiePlaybackPayload, \"expiresAt\" | \"refreshAfter\">\n now: Date\n}): { delayMs: number } | null {\n const { expiresAt, refreshAfter } = params.playback\n if (!expiresAt && !refreshAfter) {\n return null\n }\n\n const anchorIso = refreshAfter ?? expiresAt\n if (!anchorIso) return null\n\n const anchor = Date.parse(anchorIso)\n if (!Number.isFinite(anchor)) return null\n\n const target = anchor - REFRESH_BUFFER_MS\n const delayMs = Math.max(0, target - params.now.getTime())\n return { delayMs }\n}\n","const BOOTSTRAP_SEGMENT_PATTERN = /\\/bootstrap\\/[^/]+\\/?$/i\n\nconst TELEMETRY_PATH_MARKER = \"/telemetry\"\n\nexport function deriveTelemetryEventsBaseUrlFromBootstrapUrl(\n bootstrapUrl: string\n): string | null {\n try {\n const u = new URL(bootstrapUrl)\n const stripped = u.pathname.replace(BOOTSTRAP_SEGMENT_PATTERN, \"\")\n if (!stripped.includes(TELEMETRY_PATH_MARKER)) {\n return null\n }\n const normalizedPath = stripped.replace(/\\/+$/, \"\") || \"/\"\n return `${u.origin}${normalizedPath}`\n } catch {\n return null\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export { PLAYER_API_EVENTS, PlayerAPIEvent, PlayerState } from '@moviie/player-types';
|
|
3
3
|
|
|
4
|
+
/** A single moment in the video where the term occurs. */
|
|
5
|
+
interface TranscriptSearchMatch {
|
|
6
|
+
segmentIndex: number;
|
|
7
|
+
startSeconds: number;
|
|
8
|
+
endSeconds: number;
|
|
9
|
+
/** The sentence/segment containing the term (length-bounded by the server). */
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
/** Result set for one transcript search query. */
|
|
13
|
+
interface TranscriptSearchResult {
|
|
14
|
+
query: string;
|
|
15
|
+
language: string | null;
|
|
16
|
+
total: number;
|
|
17
|
+
matches: TranscriptSearchMatch[];
|
|
18
|
+
nextCursor: number | null;
|
|
19
|
+
}
|
|
20
|
+
/** Default debounce and minimum query length for the in-player search UI. */
|
|
21
|
+
declare const TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250;
|
|
22
|
+
declare const TRANSCRIPT_SEARCH_MIN_LENGTH = 2;
|
|
23
|
+
/** Low-level fetch of the transcript search endpoint, with error mapping. */
|
|
24
|
+
declare function fetchTranscriptSearch(params: {
|
|
25
|
+
url: string;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
}): Promise<TranscriptSearchResult>;
|
|
29
|
+
interface TranscriptSearchController {
|
|
30
|
+
/** Schedule a debounced search for the (trimmed) query. */
|
|
31
|
+
search(query: string): void;
|
|
32
|
+
/** Cancel any pending debounce and in-flight request. */
|
|
33
|
+
cancel(): void;
|
|
34
|
+
/** Tear down the controller. */
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* UI controller that applies debounce + a minimum query length before calling
|
|
39
|
+
* the search endpoint, and aborts any in-flight request when a newer query
|
|
40
|
+
* arrives. Queries below the minimum length clear the results without hitting
|
|
41
|
+
* the network — this is what keeps incomplete words from flooding the backend
|
|
42
|
+
* (FR-003 / SC-002).
|
|
43
|
+
*/
|
|
44
|
+
declare function createTranscriptSearchController(opts: {
|
|
45
|
+
fetcher: (query: string, signal: AbortSignal) => Promise<TranscriptSearchResult>;
|
|
46
|
+
onResult: (result: TranscriptSearchResult) => void;
|
|
47
|
+
onError?: (error: unknown) => void;
|
|
48
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
49
|
+
debounceMs?: number;
|
|
50
|
+
minLength?: number;
|
|
51
|
+
}): TranscriptSearchController;
|
|
52
|
+
|
|
4
53
|
interface MoviieClientInfo {
|
|
5
54
|
bundleId?: string;
|
|
6
55
|
platform: "ios" | "android" | "web";
|
|
@@ -103,6 +152,30 @@ declare class MoviieClient {
|
|
|
103
152
|
});
|
|
104
153
|
private headers;
|
|
105
154
|
getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData>;
|
|
155
|
+
/**
|
|
156
|
+
* Search the spoken content of the video a playback session is playing, and
|
|
157
|
+
* return the moments where the term appears (each with a timestamp). The
|
|
158
|
+
* session scopes the search to the video it actually loaded (swap-safe) and
|
|
159
|
+
* authorizes the request — it was gated when bootstrapped. Obtain the session
|
|
160
|
+
* id from the telemetry bootstrap. Matching is case- and accent-insensitive.
|
|
161
|
+
*/
|
|
162
|
+
search(sessionId: string, query: string, opts?: {
|
|
163
|
+
limit?: number;
|
|
164
|
+
cursor?: number | null;
|
|
165
|
+
signal?: AbortSignal;
|
|
166
|
+
}): Promise<TranscriptSearchResult>;
|
|
167
|
+
/**
|
|
168
|
+
* Private transcript search for an embed's video (feature 183) — the
|
|
169
|
+
* authenticated twin of {@link search}. Requires a PRIVATE API key (publishable
|
|
170
|
+
* keys are rejected) and is scoped to the key's organization; the embed must
|
|
171
|
+
* belong to it. Unlike {@link search} it needs no playback session. Matching is
|
|
172
|
+
* case- and accent-insensitive.
|
|
173
|
+
*/
|
|
174
|
+
searchEmbedTranscript(embedId: string, query: string, opts?: {
|
|
175
|
+
limit?: number;
|
|
176
|
+
cursor?: number | null;
|
|
177
|
+
signal?: AbortSignal;
|
|
178
|
+
}): Promise<TranscriptSearchResult>;
|
|
106
179
|
getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo>;
|
|
107
180
|
resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string>;
|
|
108
181
|
getEventsBaseUrl(): string;
|
|
@@ -174,7 +247,7 @@ declare class TelemetryClient {
|
|
|
174
247
|
destroy(): Promise<void>;
|
|
175
248
|
}
|
|
176
249
|
|
|
177
|
-
type MoviieErrorCode =
|
|
250
|
+
type MoviieErrorCode = 'auth' | 'not_found' | 'bundle_blocked' | 'referrer_blocked' | 'direct_access_blocked' | 'subscription_inactive' | 'network' | 'rate_limit' | 'unknown';
|
|
178
251
|
declare class MoviieAuthError extends Error {
|
|
179
252
|
readonly code: MoviieErrorCode;
|
|
180
253
|
constructor(message?: string);
|
|
@@ -191,6 +264,10 @@ declare class MoviieReferrerBlockedError extends Error {
|
|
|
191
264
|
readonly code: MoviieErrorCode;
|
|
192
265
|
constructor(message?: string);
|
|
193
266
|
}
|
|
267
|
+
declare class MoviieDirectAccessBlockedError extends Error {
|
|
268
|
+
readonly code: MoviieErrorCode;
|
|
269
|
+
constructor(message?: string);
|
|
270
|
+
}
|
|
194
271
|
declare class MoviieSubscriptionInactiveError extends Error {
|
|
195
272
|
readonly code: MoviieErrorCode;
|
|
196
273
|
constructor(message?: string);
|
|
@@ -267,4 +344,4 @@ declare const MOVIIE_WATCH_BASE = "https://watch.moviie.ai";
|
|
|
267
344
|
|
|
268
345
|
declare function deriveTelemetryEventsBaseUrlFromBootstrapUrl(bootstrapUrl: string): string | null;
|
|
269
346
|
|
|
270
|
-
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, type MoviieCTA, type MoviieCaption, type MoviieChapter, MoviieClient, type MoviieClientInfo, type MoviieEndpointsConfiguration, type MoviieErrorCode, MoviieNetworkError, MoviieNotFoundError, type MoviiePlaybackControls, type MoviiePlaybackData, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, type MoviieVideo, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TelemetryClient, type ViewerTokenStore, buildClientHeaders, configureMoviieEndpoints, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
|
347
|
+
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, type MoviieCTA, type MoviieCaption, type MoviieChapter, MoviieClient, type MoviieClientInfo, MoviieDirectAccessBlockedError, type MoviieEndpointsConfiguration, type MoviieErrorCode, MoviieNetworkError, MoviieNotFoundError, type MoviiePlaybackControls, type MoviiePlaybackData, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, type MoviieVideo, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TRANSCRIPT_SEARCH_DEBOUNCE_MS, TRANSCRIPT_SEARCH_MIN_LENGTH, TelemetryClient, type TranscriptSearchController, type TranscriptSearchMatch, type TranscriptSearchResult, type ViewerTokenStore, buildClientHeaders, configureMoviieEndpoints, createTranscriptSearchController, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, fetchTranscriptSearch, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export { PLAYER_API_EVENTS, PlayerAPIEvent, PlayerState } from '@moviie/player-types';
|
|
3
3
|
|
|
4
|
+
/** A single moment in the video where the term occurs. */
|
|
5
|
+
interface TranscriptSearchMatch {
|
|
6
|
+
segmentIndex: number;
|
|
7
|
+
startSeconds: number;
|
|
8
|
+
endSeconds: number;
|
|
9
|
+
/** The sentence/segment containing the term (length-bounded by the server). */
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
/** Result set for one transcript search query. */
|
|
13
|
+
interface TranscriptSearchResult {
|
|
14
|
+
query: string;
|
|
15
|
+
language: string | null;
|
|
16
|
+
total: number;
|
|
17
|
+
matches: TranscriptSearchMatch[];
|
|
18
|
+
nextCursor: number | null;
|
|
19
|
+
}
|
|
20
|
+
/** Default debounce and minimum query length for the in-player search UI. */
|
|
21
|
+
declare const TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250;
|
|
22
|
+
declare const TRANSCRIPT_SEARCH_MIN_LENGTH = 2;
|
|
23
|
+
/** Low-level fetch of the transcript search endpoint, with error mapping. */
|
|
24
|
+
declare function fetchTranscriptSearch(params: {
|
|
25
|
+
url: string;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
}): Promise<TranscriptSearchResult>;
|
|
29
|
+
interface TranscriptSearchController {
|
|
30
|
+
/** Schedule a debounced search for the (trimmed) query. */
|
|
31
|
+
search(query: string): void;
|
|
32
|
+
/** Cancel any pending debounce and in-flight request. */
|
|
33
|
+
cancel(): void;
|
|
34
|
+
/** Tear down the controller. */
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* UI controller that applies debounce + a minimum query length before calling
|
|
39
|
+
* the search endpoint, and aborts any in-flight request when a newer query
|
|
40
|
+
* arrives. Queries below the minimum length clear the results without hitting
|
|
41
|
+
* the network — this is what keeps incomplete words from flooding the backend
|
|
42
|
+
* (FR-003 / SC-002).
|
|
43
|
+
*/
|
|
44
|
+
declare function createTranscriptSearchController(opts: {
|
|
45
|
+
fetcher: (query: string, signal: AbortSignal) => Promise<TranscriptSearchResult>;
|
|
46
|
+
onResult: (result: TranscriptSearchResult) => void;
|
|
47
|
+
onError?: (error: unknown) => void;
|
|
48
|
+
onLoadingChange?: (loading: boolean) => void;
|
|
49
|
+
debounceMs?: number;
|
|
50
|
+
minLength?: number;
|
|
51
|
+
}): TranscriptSearchController;
|
|
52
|
+
|
|
4
53
|
interface MoviieClientInfo {
|
|
5
54
|
bundleId?: string;
|
|
6
55
|
platform: "ios" | "android" | "web";
|
|
@@ -103,6 +152,30 @@ declare class MoviieClient {
|
|
|
103
152
|
});
|
|
104
153
|
private headers;
|
|
105
154
|
getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData>;
|
|
155
|
+
/**
|
|
156
|
+
* Search the spoken content of the video a playback session is playing, and
|
|
157
|
+
* return the moments where the term appears (each with a timestamp). The
|
|
158
|
+
* session scopes the search to the video it actually loaded (swap-safe) and
|
|
159
|
+
* authorizes the request — it was gated when bootstrapped. Obtain the session
|
|
160
|
+
* id from the telemetry bootstrap. Matching is case- and accent-insensitive.
|
|
161
|
+
*/
|
|
162
|
+
search(sessionId: string, query: string, opts?: {
|
|
163
|
+
limit?: number;
|
|
164
|
+
cursor?: number | null;
|
|
165
|
+
signal?: AbortSignal;
|
|
166
|
+
}): Promise<TranscriptSearchResult>;
|
|
167
|
+
/**
|
|
168
|
+
* Private transcript search for an embed's video (feature 183) — the
|
|
169
|
+
* authenticated twin of {@link search}. Requires a PRIVATE API key (publishable
|
|
170
|
+
* keys are rejected) and is scoped to the key's organization; the embed must
|
|
171
|
+
* belong to it. Unlike {@link search} it needs no playback session. Matching is
|
|
172
|
+
* case- and accent-insensitive.
|
|
173
|
+
*/
|
|
174
|
+
searchEmbedTranscript(embedId: string, query: string, opts?: {
|
|
175
|
+
limit?: number;
|
|
176
|
+
cursor?: number | null;
|
|
177
|
+
signal?: AbortSignal;
|
|
178
|
+
}): Promise<TranscriptSearchResult>;
|
|
106
179
|
getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo>;
|
|
107
180
|
resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string>;
|
|
108
181
|
getEventsBaseUrl(): string;
|
|
@@ -174,7 +247,7 @@ declare class TelemetryClient {
|
|
|
174
247
|
destroy(): Promise<void>;
|
|
175
248
|
}
|
|
176
249
|
|
|
177
|
-
type MoviieErrorCode =
|
|
250
|
+
type MoviieErrorCode = 'auth' | 'not_found' | 'bundle_blocked' | 'referrer_blocked' | 'direct_access_blocked' | 'subscription_inactive' | 'network' | 'rate_limit' | 'unknown';
|
|
178
251
|
declare class MoviieAuthError extends Error {
|
|
179
252
|
readonly code: MoviieErrorCode;
|
|
180
253
|
constructor(message?: string);
|
|
@@ -191,6 +264,10 @@ declare class MoviieReferrerBlockedError extends Error {
|
|
|
191
264
|
readonly code: MoviieErrorCode;
|
|
192
265
|
constructor(message?: string);
|
|
193
266
|
}
|
|
267
|
+
declare class MoviieDirectAccessBlockedError extends Error {
|
|
268
|
+
readonly code: MoviieErrorCode;
|
|
269
|
+
constructor(message?: string);
|
|
270
|
+
}
|
|
194
271
|
declare class MoviieSubscriptionInactiveError extends Error {
|
|
195
272
|
readonly code: MoviieErrorCode;
|
|
196
273
|
constructor(message?: string);
|
|
@@ -267,4 +344,4 @@ declare const MOVIIE_WATCH_BASE = "https://watch.moviie.ai";
|
|
|
267
344
|
|
|
268
345
|
declare function deriveTelemetryEventsBaseUrlFromBootstrapUrl(bootstrapUrl: string): string | null;
|
|
269
346
|
|
|
270
|
-
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, type MoviieCTA, type MoviieCaption, type MoviieChapter, MoviieClient, type MoviieClientInfo, type MoviieEndpointsConfiguration, type MoviieErrorCode, MoviieNetworkError, MoviieNotFoundError, type MoviiePlaybackControls, type MoviiePlaybackData, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, type MoviieVideo, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TelemetryClient, type ViewerTokenStore, buildClientHeaders, configureMoviieEndpoints, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
|
347
|
+
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, type MoviieCTA, type MoviieCaption, type MoviieChapter, MoviieClient, type MoviieClientInfo, MoviieDirectAccessBlockedError, type MoviieEndpointsConfiguration, type MoviieErrorCode, MoviieNetworkError, MoviieNotFoundError, type MoviiePlaybackControls, type MoviiePlaybackData, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, type MoviieVideo, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TRANSCRIPT_SEARCH_DEBOUNCE_MS, TRANSCRIPT_SEARCH_MIN_LENGTH, TelemetryClient, type TranscriptSearchController, type TranscriptSearchMatch, type TranscriptSearchResult, type ViewerTokenStore, buildClientHeaders, configureMoviieEndpoints, createTranscriptSearchController, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, fetchTranscriptSearch, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,8 @@ var SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {
|
|
|
13
13
|
};
|
|
14
14
|
var HTTP_HEADER_MOVIIE_REASON = "x-moviie-reason";
|
|
15
15
|
var MOVIIE_BLOCK_REASON = {
|
|
16
|
-
BUNDLE: "bundle"
|
|
16
|
+
BUNDLE: "bundle",
|
|
17
|
+
DIRECT_ACCESS: "direct_access_blocked"
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
// src/config/moviie-endpoints.ts
|
|
@@ -92,6 +93,13 @@ var MoviieReferrerBlockedError = class extends Error {
|
|
|
92
93
|
this.name = "MoviieReferrerBlockedError";
|
|
93
94
|
}
|
|
94
95
|
};
|
|
96
|
+
var MoviieDirectAccessBlockedError = class extends Error {
|
|
97
|
+
code = "direct_access_blocked";
|
|
98
|
+
constructor(message = "Este v\xEDdeo n\xE3o pode ser reproduzido diretamente pela URL") {
|
|
99
|
+
super(message);
|
|
100
|
+
this.name = "MoviieDirectAccessBlockedError";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
95
103
|
var MoviieSubscriptionInactiveError = class extends Error {
|
|
96
104
|
code = "subscription_inactive";
|
|
97
105
|
constructor(message = "Reprodu\xE7\xE3o temporariamente indispon\xEDvel para esta organiza\xE7\xE3o") {
|
|
@@ -253,6 +261,9 @@ async function fetchPlaybackData(params) {
|
|
|
253
261
|
if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {
|
|
254
262
|
throw new MoviieBundleBlockedError();
|
|
255
263
|
}
|
|
264
|
+
if (reason === MOVIIE_BLOCK_REASON.DIRECT_ACCESS) {
|
|
265
|
+
throw new MoviieDirectAccessBlockedError();
|
|
266
|
+
}
|
|
256
267
|
throw new MoviieReferrerBlockedError();
|
|
257
268
|
}
|
|
258
269
|
if (response.status >= 500) {
|
|
@@ -268,6 +279,102 @@ async function fetchPlaybackData(params) {
|
|
|
268
279
|
}
|
|
269
280
|
return parsed.data;
|
|
270
281
|
}
|
|
282
|
+
var matchSchema = z.object({
|
|
283
|
+
segmentIndex: z.number().int(),
|
|
284
|
+
startSeconds: z.number(),
|
|
285
|
+
endSeconds: z.number(),
|
|
286
|
+
text: z.string()
|
|
287
|
+
});
|
|
288
|
+
var resultSchema = z.object({
|
|
289
|
+
query: z.string(),
|
|
290
|
+
language: z.string().nullable(),
|
|
291
|
+
total: z.number().int(),
|
|
292
|
+
matches: z.array(matchSchema),
|
|
293
|
+
nextCursor: z.number().int().nullable()
|
|
294
|
+
});
|
|
295
|
+
var TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250;
|
|
296
|
+
var TRANSCRIPT_SEARCH_MIN_LENGTH = 2;
|
|
297
|
+
var EMPTY_RESULT = (query) => ({
|
|
298
|
+
query,
|
|
299
|
+
language: null,
|
|
300
|
+
total: 0,
|
|
301
|
+
matches: [],
|
|
302
|
+
nextCursor: null
|
|
303
|
+
});
|
|
304
|
+
async function fetchTranscriptSearch(params) {
|
|
305
|
+
const response = await fetchWithRetry(params.url, {
|
|
306
|
+
method: "GET",
|
|
307
|
+
headers: params.headers,
|
|
308
|
+
signal: params.signal
|
|
309
|
+
});
|
|
310
|
+
if (response.status === 401) throw new MoviieAuthError();
|
|
311
|
+
if (response.status === 404) throw new MoviieNotFoundError();
|
|
312
|
+
if (response.status >= 500) throw new MoviieNetworkError();
|
|
313
|
+
if (!response.ok) throw new MoviieNetworkError();
|
|
314
|
+
const json = await response.json();
|
|
315
|
+
const parsed = resultSchema.safeParse(json);
|
|
316
|
+
if (!parsed.success) {
|
|
317
|
+
throw new MoviieNetworkError("Resposta de busca inv\xE1lida");
|
|
318
|
+
}
|
|
319
|
+
return parsed.data;
|
|
320
|
+
}
|
|
321
|
+
function createTranscriptSearchController(opts) {
|
|
322
|
+
const debounceMs = opts.debounceMs ?? TRANSCRIPT_SEARCH_DEBOUNCE_MS;
|
|
323
|
+
const minLength = opts.minLength ?? TRANSCRIPT_SEARCH_MIN_LENGTH;
|
|
324
|
+
let timer = null;
|
|
325
|
+
let inFlight = null;
|
|
326
|
+
function clearTimer() {
|
|
327
|
+
if (timer !== null) {
|
|
328
|
+
clearTimeout(timer);
|
|
329
|
+
timer = null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function cancelInFlight() {
|
|
333
|
+
if (inFlight) {
|
|
334
|
+
inFlight.abort();
|
|
335
|
+
inFlight = null;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function search(rawQuery) {
|
|
339
|
+
const query = rawQuery.trim();
|
|
340
|
+
clearTimer();
|
|
341
|
+
if (query.length < minLength) {
|
|
342
|
+
cancelInFlight();
|
|
343
|
+
opts.onResult(EMPTY_RESULT(query));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
timer = setTimeout(() => {
|
|
347
|
+
timer = null;
|
|
348
|
+
cancelInFlight();
|
|
349
|
+
const controller = new AbortController();
|
|
350
|
+
inFlight = controller;
|
|
351
|
+
opts.onLoadingChange?.(true);
|
|
352
|
+
opts.fetcher(query, controller.signal).then((result) => {
|
|
353
|
+
if (!controller.signal.aborted) opts.onResult(result);
|
|
354
|
+
}).catch((error) => {
|
|
355
|
+
if (controller.signal.aborted) return;
|
|
356
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
357
|
+
opts.onError?.(error);
|
|
358
|
+
}).finally(() => {
|
|
359
|
+
if (inFlight === controller) {
|
|
360
|
+
inFlight = null;
|
|
361
|
+
opts.onLoadingChange?.(false);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}, debounceMs);
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
search,
|
|
368
|
+
cancel() {
|
|
369
|
+
clearTimer();
|
|
370
|
+
cancelInFlight();
|
|
371
|
+
},
|
|
372
|
+
destroy() {
|
|
373
|
+
clearTimer();
|
|
374
|
+
cancelInFlight();
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
271
378
|
|
|
272
379
|
// src/client/moviie-client.ts
|
|
273
380
|
var videoEmbedResponseSchema = z.object({
|
|
@@ -305,6 +412,50 @@ var MoviieClient = class {
|
|
|
305
412
|
signal
|
|
306
413
|
});
|
|
307
414
|
}
|
|
415
|
+
/**
|
|
416
|
+
* Search the spoken content of the video a playback session is playing, and
|
|
417
|
+
* return the moments where the term appears (each with a timestamp). The
|
|
418
|
+
* session scopes the search to the video it actually loaded (swap-safe) and
|
|
419
|
+
* authorizes the request — it was gated when bootstrapped. Obtain the session
|
|
420
|
+
* id from the telemetry bootstrap. Matching is case- and accent-insensitive.
|
|
421
|
+
*/
|
|
422
|
+
async search(sessionId, query, opts) {
|
|
423
|
+
const key = this.options.publishableKey?.trim();
|
|
424
|
+
if (!key) {
|
|
425
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
426
|
+
}
|
|
427
|
+
if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
428
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN);
|
|
429
|
+
}
|
|
430
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
431
|
+
const params = new URLSearchParams({ q: query });
|
|
432
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
433
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
434
|
+
const url = `${base}/sessions/${encodeURIComponent(sessionId)}/search?${params.toString()}`;
|
|
435
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Private transcript search for an embed's video (feature 183) — the
|
|
439
|
+
* authenticated twin of {@link search}. Requires a PRIVATE API key (publishable
|
|
440
|
+
* keys are rejected) and is scoped to the key's organization; the embed must
|
|
441
|
+
* belong to it. Unlike {@link search} it needs no playback session. Matching is
|
|
442
|
+
* case- and accent-insensitive.
|
|
443
|
+
*/
|
|
444
|
+
async searchEmbedTranscript(embedId, query, opts) {
|
|
445
|
+
const key = this.options.publishableKey?.trim();
|
|
446
|
+
if (!key) {
|
|
447
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
448
|
+
}
|
|
449
|
+
if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
450
|
+
throw new MoviieAuthError("A busca privada exige uma chave de API privada (n\xE3o publishable).");
|
|
451
|
+
}
|
|
452
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
453
|
+
const params = new URLSearchParams({ q: query });
|
|
454
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
455
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
456
|
+
const url = `${base}/embeds/${encodeURIComponent(embedId)}/transcript/search?${params.toString()}`;
|
|
457
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
458
|
+
}
|
|
308
459
|
async getVideo(videoId, signal) {
|
|
309
460
|
const key = this.options.publishableKey?.trim();
|
|
310
461
|
if (!key) {
|
|
@@ -730,6 +881,6 @@ function deriveTelemetryEventsBaseUrlFromBootstrapUrl(bootstrapUrl) {
|
|
|
730
881
|
}
|
|
731
882
|
}
|
|
732
883
|
|
|
733
|
-
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, MoviieClient, MoviieNetworkError, MoviieNotFoundError, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TelemetryClient, buildClientHeaders, configureMoviieEndpoints, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
|
884
|
+
export { HEARTBEAT_CONFIG, MOVIIE_CDN_BASE, MOVIIE_DEFAULT_API_BASE_URL, MOVIIE_TELEMETRY_API_PATH_PREFIX, MOVIIE_WATCH_BASE, MemoryViewerTokenStore, MoviieAuthError, MoviieBundleBlockedError, MoviieClient, MoviieDirectAccessBlockedError, MoviieNetworkError, MoviieNotFoundError, MoviieRateLimitError, MoviieReferrerBlockedError, MoviieSubscriptionInactiveError, PLAYBACK_EVENT_TYPE, SDK_PLAYBACK_AUTH_ERROR_MESSAGE, SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE, TELEMETRY_TOKEN_CONFIG, TRANSCRIPT_SEARCH_DEBOUNCE_MS, TRANSCRIPT_SEARCH_MIN_LENGTH, TelemetryClient, buildClientHeaders, configureMoviieEndpoints, createTranscriptSearchController, deriveMoviieTelemetryBaseUrlFromApiBaseUrl, deriveTelemetryEventsBaseUrlFromBootstrapUrl, fetchPlaybackData, fetchTranscriptSearch, getMoviieApiBaseUrl, getMoviieEventsBaseUrl, planRefresh, resetMoviieEndpointsConfiguration };
|
|
734
885
|
//# sourceMappingURL=index.js.map
|
|
735
886
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/config/moviie-endpoints.ts","../src/client/errors.ts","../src/client/http.ts","../src/client/client-headers.ts","../src/playback/fetch-playback.ts","../src/client/moviie-client.ts","../src/telemetry/types.ts","../src/telemetry/heartbeat-scheduler.ts","../src/telemetry/token-manager.ts","../src/telemetry/telemetry-client.ts","../src/telemetry/viewer-token-store.ts","../src/playback/playback-refresh.ts","../src/config/telemetry-bootstrap-url.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default Public REST API base URL for production clients (OpenAPI `/v1/*` paths).\n *\n * Requests use `{MOVIIE_DEFAULT_API_BASE_URL}/embeds/{embedId}/playback`, etc.\n */\nexport const MOVIIE_DEFAULT_API_BASE_URL = \"https://api.moviie.ai/v1\" as const\n\n/**\n * Path segment for telemetry on the **same origin** as the Public API (bootstrap, ingest, token refresh).\n */\nexport const MOVIIE_TELEMETRY_API_PATH_PREFIX = \"/telemetry/v1\" as const\n\nexport const SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = \"mvi_pub_\" as const\n\nexport const SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {\n KEY_REQUIRED: \"Publishable API key is required for playback.\",\n PRIVATE_KEY_FORBIDDEN:\n \"Do not use a private API key for playback; use a publishable key (mvi_pub_*).\",\n} as const\n\nexport const HTTP_HEADER_MOVIIE_REASON = \"x-moviie-reason\" as const\n\nexport const MOVIIE_BLOCK_REASON = {\n BUNDLE: \"bundle\",\n} as const\n","import {\n MOVIIE_DEFAULT_API_BASE_URL,\n MOVIIE_TELEMETRY_API_PATH_PREFIX,\n} from \"../constants\"\n\nlet configuredApiBaseUrl: string | null = null\nlet configuredEventsBaseUrl: string | null = null\n\nexport type MoviieEndpointsConfiguration = {\n /** API base URL override without trailing slash. Pass `null` or empty to clear. */\n apiBaseUrl?: string | null\n /**\n * Telemetry base (`…/telemetry/v1`) without trailing slash.\n * Pass `null` or empty to clear and derive from the API origin again.\n */\n eventsBaseUrl?: string | null\n}\n\nfunction normalizeEndpointBase(raw: string): string {\n return raw.trim().replace(/\\/+$/, \"\")\n}\n\n/**\n * Builds `{apiOrigin}/telemetry/v1` from a configured API base (e.g. `https://host/api/v1` → `https://host/telemetry/v1`).\n */\nexport function deriveMoviieTelemetryBaseUrlFromApiBaseUrl(apiBaseUrl: string): string {\n const trimmed = normalizeEndpointBase(apiBaseUrl)\n const href = trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`\n const u = new URL(href)\n return normalizeEndpointBase(`${u.origin}${MOVIIE_TELEMETRY_API_PATH_PREFIX}`)\n}\n\n/**\n * Applies global SDK endpoint configuration (e.g. Expo reads `expo.extra` at bootstrap).\n * When unset, `MoviieClient` uses `MOVIIE_DEFAULT_API_BASE_URL`.\n * Telemetry defaults to the same **origin** as the API with path `MOVIIE_TELEMETRY_API_PATH_PREFIX`.\n */\nexport function configureMoviieEndpoints(options: MoviieEndpointsConfiguration): void {\n if (options.apiBaseUrl !== undefined) {\n if (options.apiBaseUrl == null || options.apiBaseUrl.trim() === \"\") {\n configuredApiBaseUrl = null\n } else {\n configuredApiBaseUrl = normalizeEndpointBase(options.apiBaseUrl)\n }\n }\n if (options.eventsBaseUrl !== undefined) {\n if (options.eventsBaseUrl == null || options.eventsBaseUrl.trim() === \"\") {\n configuredEventsBaseUrl = null\n } else {\n configuredEventsBaseUrl = normalizeEndpointBase(options.eventsBaseUrl)\n }\n }\n}\n\n/** Clears configuration — use in tests between cases. */\nexport function resetMoviieEndpointsConfiguration(): void {\n configuredApiBaseUrl = null\n configuredEventsBaseUrl = null\n}\n\nexport function getMoviieApiBaseUrl(): string {\n return configuredApiBaseUrl ?? MOVIIE_DEFAULT_API_BASE_URL\n}\n\nexport function getMoviieEventsBaseUrl(): string {\n if (\n process.env.NODE_ENV === \"test\" &&\n process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE?.trim()\n ) {\n return normalizeEndpointBase(process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE)\n }\n if (configuredEventsBaseUrl != null) {\n return configuredEventsBaseUrl\n }\n return deriveMoviieTelemetryBaseUrlFromApiBaseUrl(getMoviieApiBaseUrl())\n}\n\nexport const MOVIIE_CDN_BASE = \"https://cdn.moviie.ai\"\n\nexport const MOVIIE_WATCH_BASE = \"https://watch.moviie.ai\"\n","export type MoviieErrorCode =\n | \"auth\"\n | \"not_found\"\n | \"bundle_blocked\"\n | \"referrer_blocked\"\n | \"subscription_inactive\"\n | \"network\"\n | \"rate_limit\"\n | \"unknown\"\n\nexport class MoviieAuthError extends Error {\n readonly code: MoviieErrorCode = \"auth\"\n\n constructor(message = \"Autenticação necessária ou chave inválida\") {\n super(message)\n this.name = \"MoviieAuthError\"\n }\n}\n\nexport class MoviieNotFoundError extends Error {\n readonly code: MoviieErrorCode = \"not_found\"\n\n constructor(message = \"Recurso não encontrado\") {\n super(message)\n this.name = \"MoviieNotFoundError\"\n }\n}\n\nexport class MoviieBundleBlockedError extends Error {\n readonly code: MoviieErrorCode = \"bundle_blocked\"\n\n constructor(message = \"Este aplicativo não está autorizado a reproduzir este vídeo\") {\n super(message)\n this.name = \"MoviieBundleBlockedError\"\n }\n}\n\nexport class MoviieReferrerBlockedError extends Error {\n readonly code: MoviieErrorCode = \"referrer_blocked\"\n\n constructor(message = \"Origem não autorizada para reprodução\") {\n super(message)\n this.name = \"MoviieReferrerBlockedError\"\n }\n}\n\nexport class MoviieSubscriptionInactiveError extends Error {\n readonly code: MoviieErrorCode = \"subscription_inactive\"\n\n constructor(message = \"Reprodução temporariamente indisponível para esta organização\") {\n super(message)\n this.name = \"MoviieSubscriptionInactiveError\"\n }\n}\n\nexport class MoviieNetworkError extends Error {\n readonly code: MoviieErrorCode = \"network\"\n\n constructor(message = \"Falha de rede. Tente novamente\") {\n super(message)\n this.name = \"MoviieNetworkError\"\n }\n}\n\nexport class MoviieRateLimitError extends Error {\n readonly code: MoviieErrorCode = \"rate_limit\"\n\n constructor(message = \"Muitas solicitações. Aguarde e tente novamente\") {\n super(message)\n this.name = \"MoviieRateLimitError\"\n }\n}\n","import {\n MoviieNetworkError,\n MoviieRateLimitError,\n} from \"./errors\"\n\nexport interface HttpRequestOptions extends RequestInit {\n timeoutMs?: number\n retries?: number\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_RETRIES = 2\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction backoffDelayMs(attempt: number): number {\n const base = 2 ** attempt * 200\n const jitter = Math.floor(Math.random() * 200)\n return base + jitter\n}\n\nfunction composeAbortSignals(\n external: AbortSignal | null | undefined,\n internal: AbortSignal\n): AbortSignal {\n if (!external) return internal\n if (external.aborted) return external\n\n const controller = new AbortController()\n const onAbort = (signal: AbortSignal) => () => {\n controller.abort(signal.reason)\n }\n external.addEventListener(\"abort\", onAbort(external), { once: true })\n internal.addEventListener(\"abort\", onAbort(internal), { once: true })\n return controller.signal\n}\n\nexport async function fetchWithRetry(\n input: string | URL,\n init: HttpRequestOptions = {}\n): Promise<Response> {\n const timeoutMs = init.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const maxRetries = init.retries ?? DEFAULT_RETRIES\n const { timeoutMs: _t, retries: _r, signal: externalSignal, ...rest } = init\n\n let lastError: unknown\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const timeoutController = new AbortController()\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs)\n const signal = composeAbortSignals(externalSignal, timeoutController.signal)\n\n try {\n const response = await fetch(input, { ...rest, signal })\n clearTimeout(timer)\n\n if (response.status === 429) {\n throw new MoviieRateLimitError()\n }\n\n if (response.status >= 500 && response.status < 600 && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n\n if (error instanceof MoviieRateLimitError) throw error\n\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const isAbort = error instanceof Error && error.name === \"AbortError\"\n if (isAbort && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n if (attempt >= maxRetries) {\n throw new MoviieNetworkError()\n }\n\n await delay(backoffDelayMs(attempt))\n }\n }\n\n throw lastError instanceof Error ? lastError : new MoviieNetworkError()\n}\n","import type { MoviieClientInfo } from \"../types\"\n\nconst SEPARATOR = \";\"\n\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[\\r\\n;]/g, \"\").trim()\n}\n\nexport function buildClientHeaders(params: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const key = params.publishableKey?.trim()\n if (key) {\n headers.Authorization = `Bearer ${key}`\n }\n\n const info = params.clientInfo\n if (info) {\n const parts: string[] = []\n if (info.bundleId) {\n parts.push(`bundle_id=${sanitizeSegment(info.bundleId)}`)\n }\n parts.push(`platform=${sanitizeSegment(info.platform)}`)\n const sdk = params.sdkVersion ?? info.sdkVersion\n if (sdk) {\n parts.push(`sdk=${sanitizeSegment(sdk)}`)\n }\n headers[\"X-Moviie-Client\"] = parts.join(SEPARATOR)\n }\n\n return headers\n}\n","import {\n HTTP_HEADER_MOVIIE_REASON,\n MOVIIE_BLOCK_REASON,\n} from \"../constants\"\nimport {\n MoviieAuthError,\n MoviieBundleBlockedError,\n MoviieNetworkError,\n MoviieNotFoundError,\n MoviieReferrerBlockedError,\n MoviieSubscriptionInactiveError,\n} from \"../client/errors\"\nimport { fetchWithRetry } from \"../client/http\"\nimport type { MoviiePlaybackData } from \"../types\"\n\nimport { z } from \"zod\"\n\nconst playbackPayloadSchema = z.object({\n uri: z.string().url(),\n contentType: z.enum([\"hls\", \"progressive\"]),\n expiresAt: z.string().nullable(),\n refreshAfter: z.string().nullable(),\n requestHeaders: z.record(z.string()).optional(),\n})\n\nexport const moviiePlaybackDataResponseSchema = z\n .object({\n embedId: z.string(),\n title: z.string(),\n smartProgressEnabled: z.boolean(),\n durationSeconds: z.number().nullable(),\n isVertical: z.boolean(),\n videoWidthPx: z.number().int().positive().nullable(),\n videoHeightPx: z.number().int().positive().nullable(),\n profile: z.string(),\n playback: playbackPayloadSchema,\n posterUrl: z.string().nullable(),\n branding: z.object({\n primaryColor: z.string().nullable(),\n showWatermark: z.boolean(),\n organizationName: z.string().nullable(),\n }),\n telemetry: z.object({\n bootstrapUrl: z.string().url(),\n }),\n })\n .passthrough()\n\nexport async function fetchPlaybackData(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<MoviiePlaybackData> {\n const response = await fetchWithRetry(params.url, {\n headers: params.headers,\n signal: params.signal,\n method: \"GET\",\n })\n\n const reason = response.headers.get(HTTP_HEADER_MOVIIE_REASON)?.toLowerCase()\n\n if (response.status === 401) {\n throw new MoviieAuthError()\n }\n\n if (response.status === 402) {\n throw new MoviieSubscriptionInactiveError()\n }\n\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n\n if (response.status === 403) {\n if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {\n throw new MoviieBundleBlockedError()\n }\n throw new MoviieReferrerBlockedError()\n }\n\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n\n if (!response.ok) {\n throw new MoviieNotFoundError(\"Não foi possível carregar a reprodução\")\n }\n\n const json: unknown = await response.json()\n const parsed = moviiePlaybackDataResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError(\"Resposta de playback inválida\")\n }\n\n return parsed.data as unknown as MoviiePlaybackData\n}\n","import { z } from \"zod\"\n\nimport {\n SDK_PLAYBACK_AUTH_ERROR_MESSAGE,\n SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE,\n} from \"../constants\"\nimport { getMoviieApiBaseUrl, getMoviieEventsBaseUrl } from \"../config/moviie-endpoints\"\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from \"./errors\"\nimport { fetchWithRetry } from \"./http\"\nimport { buildClientHeaders } from \"./client-headers\"\nimport { fetchPlaybackData } from \"../playback/fetch-playback\"\nimport type { MoviieClientInfo, MoviiePlaybackData, MoviieVideo } from \"../types\"\n\nconst videoEmbedResponseSchema = z.object({\n id: z.string().uuid(),\n embed_id: z.string().uuid(),\n})\n\nexport class MoviieClient {\n constructor(\n private readonly options: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n }\n ) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n ...buildClientHeaders({\n publishableKey: this.options.publishableKey ?? undefined,\n clientInfo: this.options.clientInfo ?? undefined,\n sdkVersion: this.options.sdkVersion,\n }),\n ...extra,\n }\n }\n\n async getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, \"\")\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/playback`\n return fetchPlaybackData({\n url,\n headers: this.headers(),\n signal,\n })\n }\n\n async getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(\"Chave de API obrigatória para buscar vídeo por ID\")\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(\"Chave publishable não pode listar vídeos administrativos\")\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, \"\")\n const url = `${base}/videos/${encodeURIComponent(videoId)}`\n const response = await fetchWithRetry(url, {\n method: \"GET\",\n headers: this.headers(),\n signal,\n })\n\n if (response.status === 401 || response.status === 403) {\n throw new MoviieAuthError()\n }\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n if (!response.ok) {\n throw new MoviieNotFoundError()\n }\n\n const json: unknown = await response.json()\n const parsed = videoEmbedResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError(\"Resposta de vídeo inválida\")\n }\n\n return {\n id: parsed.data.id,\n embedId: parsed.data.embed_id,\n }\n }\n\n async resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string> {\n const video = await this.getVideo(videoId, signal)\n if (!video.embedId) {\n throw new MoviieNotFoundError(\"Embed não encontrado para este vídeo\")\n }\n return video.embedId\n }\n\n getEventsBaseUrl(): string {\n return getMoviieEventsBaseUrl().replace(/\\/+$/, \"\")\n }\n}\n","import { z } from \"zod\"\n\nexport const PLAYBACK_EVENT_TYPE = {\n SESSION_START: \"session_start\",\n PLAY_START: \"play_start\",\n PAUSE: \"pause\",\n RESUME: \"resume\",\n HEARTBEAT: \"heartbeat\",\n ENDED: \"ended\",\n CTA_CLICK: \"cta_click\",\n ERROR: \"error\",\n} as const\n\nexport const PLAYBACK_EVENT_TYPE_VALUES = Object.values(PLAYBACK_EVENT_TYPE)\n\nexport const playbackEventTypeSchema = z.enum(\n PLAYBACK_EVENT_TYPE_VALUES as [string, ...string[]]\n)\n\nexport type PlaybackEventType = z.infer<typeof playbackEventTypeSchema>\n\nexport const TELEMETRY_TOKEN_CONFIG = {\n INGEST_TOKEN_EXPIRY_SECONDS: 600,\n REFRESH_TOKEN_EXPIRY_SECONDS: 86400,\n REFRESH_BUFFER_SECONDS: 120,\n} as const\n\nexport const HEARTBEAT_CONFIG = {\n INTERVAL_SECONDS: 10,\n WATCH_TIME_PER_HEARTBEAT_SECONDS: 10,\n} as const\n\nexport const bootstrapResponseSchema = z.object({\n sessionId: z.string().uuid(),\n eventsIngestToken: z.string(),\n eventsRefreshToken: z.string(),\n ctaId: z.string().optional(),\n})\n\nexport type BootstrapResponse = z.infer<typeof bootstrapResponseSchema>\n\nexport const tokenRefreshRequestSchema = z.object({\n sessionId: z.string().uuid(),\n eventsRefreshToken: z.string(),\n})\n\nexport const tokenRefreshResponseSchema = z.object({\n eventsIngestToken: z.string(),\n expiresInSeconds: z.number(),\n})\n\nexport type TokenRefreshResponse = z.infer<typeof tokenRefreshResponseSchema>\n\nexport const playbackEventSchema = z.object({\n eventId: z.string().uuid(),\n sessionId: z.string().uuid(),\n eventType: playbackEventTypeSchema,\n positionSeconds: z.number().int().min(0).optional(),\n ctaId: z.string().optional(),\n errorCode: z.string().max(50).optional(),\n})\n\nexport const eventIngestRequestSchema = z.object({\n events: z.array(playbackEventSchema).min(1).max(100),\n ingestToken: z.string().optional(),\n})\n\nexport type PlaybackTelemetryEvent = z.infer<typeof playbackEventSchema>\n","export class HeartbeatScheduler {\n private timer: ReturnType<typeof setInterval> | null = null\n private paused = false\n\n constructor(\n private readonly options: {\n intervalSeconds: number\n onTick: () => void\n }\n ) {}\n\n start(): void {\n if (this.timer) return\n const ms = Math.max(1_000, this.options.intervalSeconds * 1000)\n this.timer = setInterval(() => {\n if (!this.paused) {\n this.options.onTick()\n }\n }, ms)\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n pause(): void {\n this.paused = true\n }\n\n resume(): void {\n this.paused = false\n }\n\n destroy(): void {\n this.stop()\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport {\n bootstrapResponseSchema,\n TELEMETRY_TOKEN_CONFIG,\n tokenRefreshRequestSchema,\n tokenRefreshResponseSchema,\n type BootstrapResponse,\n} from \"./types\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst REFRESH_MIN_DELAY_MS = 5_000\nconst REFRESH_RETRY_BACKOFF_MS = [5_000, 15_000, 60_000]\n\nexport class TelemetryTokenManager {\n private ingestToken: string | null = null\n private refreshToken: string | null = null\n private sessionId: string | null = null\n private refreshTimer: ReturnType<typeof setTimeout> | null = null\n private refreshFailureCount = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n }\n ) {}\n\n getSessionId(): string | null {\n return this.sessionId\n }\n\n getIngestToken(): string | null {\n return this.ingestToken\n }\n\n async bootstrap(bootstrapUrl: string): Promise<BootstrapResponse> {\n const response = await fetchWithRetry(bootstrapUrl, {\n method: \"GET\",\n headers: this.options.defaultHeaders,\n })\n\n if (!response.ok) {\n throw new Error(`Bootstrap falhou: ${response.status}`)\n }\n\n const json: unknown = await response.json()\n const parsed = bootstrapResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new Error(\"Resposta de bootstrap inválida\")\n }\n\n this.sessionId = parsed.data.sessionId\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshToken = parsed.data.eventsRefreshToken\n\n const store = this.options.viewerTokenStore\n if (store && parsed.data.eventsRefreshToken) {\n await store.set(parsed.data.eventsRefreshToken, TELEMETRY_TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY_SECONDS)\n }\n\n this.refreshFailureCount = 0\n this.scheduleRefresh(TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS)\n return parsed.data\n }\n\n private scheduleRefresh(expirySeconds: number): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const delayMs =\n (expirySeconds - TELEMETRY_TOKEN_CONFIG.REFRESH_BUFFER_SECONDS) * 1000\n\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, Math.max(REFRESH_MIN_DELAY_MS, delayMs))\n }\n\n private scheduleRefreshRetry(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const index = Math.min(\n this.refreshFailureCount,\n REFRESH_RETRY_BACKOFF_MS.length - 1\n )\n const base = REFRESH_RETRY_BACKOFF_MS[index] ?? REFRESH_MIN_DELAY_MS\n const jitter = Math.floor(Math.random() * 1_000)\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, base + jitter)\n }\n\n private async refresh(refreshUrl: string): Promise<void> {\n if (!this.sessionId || !this.refreshToken) return\n\n const body = tokenRefreshRequestSchema.parse({\n sessionId: this.sessionId,\n eventsRefreshToken: this.refreshToken,\n })\n\n try {\n const response = await fetchWithRetry(refreshUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n const json: unknown = await response.json()\n const parsed = tokenRefreshResponseSchema.safeParse(json)\n if (!parsed.success) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshFailureCount = 0\n const nextExpiry =\n parsed.data.expiresInSeconds > 0\n ? parsed.data.expiresInSeconds\n : TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS\n this.scheduleRefresh(nextExpiry)\n } catch {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n }\n }\n\n destroy(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport { HEARTBEAT_CONFIG, PLAYBACK_EVENT_TYPE, type PlaybackEventType } from \"./types\"\nimport { HeartbeatScheduler } from \"./heartbeat-scheduler\"\nimport { TelemetryTokenManager } from \"./token-manager\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst BATCH_MAX = 10\nconst FLUSH_MS = 5_000\n\nfunction randomHex(length: number): string {\n let out = \"\"\n while (out.length < length) {\n out += Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, \"0\")\n }\n return out.slice(0, length)\n}\n\nfunction newEventId(): string {\n const g = globalThis as typeof globalThis & {\n crypto?: { randomUUID?: () => string }\n }\n if (typeof g.crypto?.randomUUID === \"function\") {\n return g.crypto.randomUUID()\n }\n return `${randomHex(8)}-${randomHex(4)}-4${randomHex(3)}-8${randomHex(3)}-${randomHex(12)}`\n}\n\nexport class TelemetryClient {\n private readonly tokenManager: TelemetryTokenManager\n private readonly heartbeat: HeartbeatScheduler\n private pending: Array<Record<string, unknown>> = []\n private flushTimer: ReturnType<typeof setTimeout> | null = null\n private positionSeconds = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n getPositionSeconds?: () => number\n }\n ) {\n this.tokenManager = new TelemetryTokenManager({\n eventsBaseUrl: options.eventsBaseUrl,\n defaultHeaders: options.defaultHeaders,\n viewerTokenStore: options.viewerTokenStore,\n })\n\n this.heartbeat = new HeartbeatScheduler({\n intervalSeconds: HEARTBEAT_CONFIG.INTERVAL_SECONDS,\n onTick: () => {\n const pos =\n typeof options.getPositionSeconds === \"function\"\n ? Math.floor(options.getPositionSeconds())\n : this.positionSeconds\n void this.recordEvent({\n eventType: PLAYBACK_EVENT_TYPE.HEARTBEAT,\n positionSeconds: Math.max(0, pos),\n })\n },\n })\n }\n\n async bootstrap(params: { bootstrapUrl: string }): Promise<{ sessionId: string }> {\n const res = await this.tokenManager.bootstrap(params.bootstrapUrl)\n return { sessionId: res.sessionId }\n }\n\n updatePosition(seconds: number): void {\n this.positionSeconds = Math.max(0, seconds)\n }\n\n async recordEvent(params: {\n eventType: PlaybackEventType\n positionSeconds?: number\n ctaId?: string\n errorCode?: string\n }): Promise<void> {\n const sessionId = this.tokenManager.getSessionId()\n if (!sessionId) return\n\n const payload: Record<string, unknown> = {\n eventId: newEventId(),\n sessionId,\n eventType: params.eventType,\n }\n if (params.positionSeconds !== undefined) {\n payload.positionSeconds = params.positionSeconds\n }\n if (params.ctaId !== undefined) {\n payload.ctaId = params.ctaId\n }\n if (params.errorCode !== undefined) {\n payload.errorCode = params.errorCode\n }\n\n this.pending.push(payload)\n if (this.pending.length >= BATCH_MAX) {\n await this.flush()\n } else {\n this.scheduleFlush()\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null\n void this.flush()\n }, FLUSH_MS)\n }\n\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = null\n }\n\n if (this.pending.length === 0) {\n return\n }\n\n const ingestToken = this.tokenManager.getIngestToken()\n const sessionId = this.tokenManager.getSessionId()\n if (!ingestToken || !sessionId) {\n this.scheduleFlush()\n return\n }\n\n const batch = this.pending.splice(0, BATCH_MAX)\n const eventsUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/events`\n\n try {\n const response = await fetchWithRetry(eventsUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${ingestToken}`,\n },\n body: JSON.stringify({ events: batch }),\n })\n if (!response.ok && response.status >= 500) {\n this.pending.unshift(...batch)\n }\n } catch {\n this.pending.unshift(...batch)\n }\n\n if (this.pending.length > 0) {\n this.scheduleFlush()\n }\n }\n\n startHeartbeats(): void {\n this.heartbeat.start()\n }\n\n stopHeartbeats(): void {\n this.heartbeat.stop()\n }\n\n pauseHeartbeats(): void {\n this.heartbeat.pause()\n }\n\n resumeHeartbeats(): void {\n this.heartbeat.resume()\n }\n\n async destroy(): Promise<void> {\n this.heartbeat.destroy()\n this.tokenManager.destroy()\n await this.flush()\n }\n}\n","export interface ViewerTokenStore {\n get(): Promise<string | null>\n set(token: string, ttlSec: number): Promise<void>\n}\n\nexport class MemoryViewerTokenStore implements ViewerTokenStore {\n private value: string | null = null\n\n async get(): Promise<string | null> {\n return this.value\n }\n\n async set(token: string, _ttlSec: number): Promise<void> {\n this.value = token\n }\n}\n","import type { MoviiePlaybackPayload } from \"../types\"\n\nconst REFRESH_BUFFER_MS = 60_000\n\nexport function planRefresh(params: {\n playback: Pick<MoviiePlaybackPayload, \"expiresAt\" | \"refreshAfter\">\n now: Date\n}): { delayMs: number } | null {\n const { expiresAt, refreshAfter } = params.playback\n if (!expiresAt && !refreshAfter) {\n return null\n }\n\n const anchorIso = refreshAfter ?? expiresAt\n if (!anchorIso) return null\n\n const anchor = Date.parse(anchorIso)\n if (!Number.isFinite(anchor)) return null\n\n const target = anchor - REFRESH_BUFFER_MS\n const delayMs = Math.max(0, target - params.now.getTime())\n return { delayMs }\n}\n","const BOOTSTRAP_SEGMENT_PATTERN = /\\/bootstrap\\/[^/]+\\/?$/i\n\nconst TELEMETRY_PATH_MARKER = \"/telemetry\"\n\nexport function deriveTelemetryEventsBaseUrlFromBootstrapUrl(\n bootstrapUrl: string\n): string | null {\n try {\n const u = new URL(bootstrapUrl)\n const stripped = u.pathname.replace(BOOTSTRAP_SEGMENT_PATTERN, \"\")\n if (!stripped.includes(TELEMETRY_PATH_MARKER)) {\n return null\n }\n const normalizedPath = stripped.replace(/\\/+$/, \"\") || \"/\"\n return `${u.origin}${normalizedPath}`\n } catch {\n return null\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/config/moviie-endpoints.ts","../src/client/errors.ts","../src/client/http.ts","../src/client/client-headers.ts","../src/playback/fetch-playback.ts","../src/search/transcript-search-client.ts","../src/client/moviie-client.ts","../src/telemetry/types.ts","../src/telemetry/heartbeat-scheduler.ts","../src/telemetry/token-manager.ts","../src/telemetry/telemetry-client.ts","../src/telemetry/viewer-token-store.ts","../src/playback/playback-refresh.ts","../src/config/telemetry-bootstrap-url.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Default Public REST API base URL for production clients (OpenAPI `/v1/*` paths).\n *\n * Requests use `{MOVIIE_DEFAULT_API_BASE_URL}/embeds/{embedId}/playback`, etc.\n */\nexport const MOVIIE_DEFAULT_API_BASE_URL = 'https://api.moviie.ai/v1' as const\n\n/**\n * Path segment for telemetry on the **same origin** as the Public API (bootstrap, ingest, token refresh).\n */\nexport const MOVIIE_TELEMETRY_API_PATH_PREFIX = '/telemetry/v1' as const\n\nexport const SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = 'mvi_pub_' as const\n\nexport const SDK_PLAYBACK_AUTH_ERROR_MESSAGE = {\n KEY_REQUIRED: 'Publishable API key is required for playback.',\n PRIVATE_KEY_FORBIDDEN:\n 'Do not use a private API key for playback; use a publishable key (mvi_pub_*).',\n} as const\n\nexport const HTTP_HEADER_MOVIIE_REASON = 'x-moviie-reason' as const\n\nexport const MOVIIE_BLOCK_REASON = {\n BUNDLE: 'bundle',\n DIRECT_ACCESS: 'direct_access_blocked',\n} as const\n","import {\n MOVIIE_DEFAULT_API_BASE_URL,\n MOVIIE_TELEMETRY_API_PATH_PREFIX,\n} from \"../constants\"\n\nlet configuredApiBaseUrl: string | null = null\nlet configuredEventsBaseUrl: string | null = null\n\nexport type MoviieEndpointsConfiguration = {\n /** API base URL override without trailing slash. Pass `null` or empty to clear. */\n apiBaseUrl?: string | null\n /**\n * Telemetry base (`…/telemetry/v1`) without trailing slash.\n * Pass `null` or empty to clear and derive from the API origin again.\n */\n eventsBaseUrl?: string | null\n}\n\nfunction normalizeEndpointBase(raw: string): string {\n return raw.trim().replace(/\\/+$/, \"\")\n}\n\n/**\n * Builds `{apiOrigin}/telemetry/v1` from a configured API base (e.g. `https://host/api/v1` → `https://host/telemetry/v1`).\n */\nexport function deriveMoviieTelemetryBaseUrlFromApiBaseUrl(apiBaseUrl: string): string {\n const trimmed = normalizeEndpointBase(apiBaseUrl)\n const href = trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`\n const u = new URL(href)\n return normalizeEndpointBase(`${u.origin}${MOVIIE_TELEMETRY_API_PATH_PREFIX}`)\n}\n\n/**\n * Applies global SDK endpoint configuration (e.g. Expo reads `expo.extra` at bootstrap).\n * When unset, `MoviieClient` uses `MOVIIE_DEFAULT_API_BASE_URL`.\n * Telemetry defaults to the same **origin** as the API with path `MOVIIE_TELEMETRY_API_PATH_PREFIX`.\n */\nexport function configureMoviieEndpoints(options: MoviieEndpointsConfiguration): void {\n if (options.apiBaseUrl !== undefined) {\n if (options.apiBaseUrl == null || options.apiBaseUrl.trim() === \"\") {\n configuredApiBaseUrl = null\n } else {\n configuredApiBaseUrl = normalizeEndpointBase(options.apiBaseUrl)\n }\n }\n if (options.eventsBaseUrl !== undefined) {\n if (options.eventsBaseUrl == null || options.eventsBaseUrl.trim() === \"\") {\n configuredEventsBaseUrl = null\n } else {\n configuredEventsBaseUrl = normalizeEndpointBase(options.eventsBaseUrl)\n }\n }\n}\n\n/** Clears configuration — use in tests between cases. */\nexport function resetMoviieEndpointsConfiguration(): void {\n configuredApiBaseUrl = null\n configuredEventsBaseUrl = null\n}\n\nexport function getMoviieApiBaseUrl(): string {\n return configuredApiBaseUrl ?? MOVIIE_DEFAULT_API_BASE_URL\n}\n\nexport function getMoviieEventsBaseUrl(): string {\n if (\n process.env.NODE_ENV === \"test\" &&\n process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE?.trim()\n ) {\n return normalizeEndpointBase(process.env.MOVIIE_PLAYER_SDK_TEST_EVENTS_BASE)\n }\n if (configuredEventsBaseUrl != null) {\n return configuredEventsBaseUrl\n }\n return deriveMoviieTelemetryBaseUrlFromApiBaseUrl(getMoviieApiBaseUrl())\n}\n\nexport const MOVIIE_CDN_BASE = \"https://cdn.moviie.ai\"\n\nexport const MOVIIE_WATCH_BASE = \"https://watch.moviie.ai\"\n","export type MoviieErrorCode =\n | 'auth'\n | 'not_found'\n | 'bundle_blocked'\n | 'referrer_blocked'\n | 'direct_access_blocked'\n | 'subscription_inactive'\n | 'network'\n | 'rate_limit'\n | 'unknown'\n\nexport class MoviieAuthError extends Error {\n readonly code: MoviieErrorCode = 'auth'\n\n constructor(message = 'Autenticação necessária ou chave inválida') {\n super(message)\n this.name = 'MoviieAuthError'\n }\n}\n\nexport class MoviieNotFoundError extends Error {\n readonly code: MoviieErrorCode = 'not_found'\n\n constructor(message = 'Recurso não encontrado') {\n super(message)\n this.name = 'MoviieNotFoundError'\n }\n}\n\nexport class MoviieBundleBlockedError extends Error {\n readonly code: MoviieErrorCode = 'bundle_blocked'\n\n constructor(message = 'Este aplicativo não está autorizado a reproduzir este vídeo') {\n super(message)\n this.name = 'MoviieBundleBlockedError'\n }\n}\n\nexport class MoviieReferrerBlockedError extends Error {\n readonly code: MoviieErrorCode = 'referrer_blocked'\n\n constructor(message = 'Origem não autorizada para reprodução') {\n super(message)\n this.name = 'MoviieReferrerBlockedError'\n }\n}\n\nexport class MoviieDirectAccessBlockedError extends Error {\n readonly code: MoviieErrorCode = 'direct_access_blocked'\n\n constructor(message = 'Este vídeo não pode ser reproduzido diretamente pela URL') {\n super(message)\n this.name = 'MoviieDirectAccessBlockedError'\n }\n}\n\nexport class MoviieSubscriptionInactiveError extends Error {\n readonly code: MoviieErrorCode = 'subscription_inactive'\n\n constructor(message = 'Reprodução temporariamente indisponível para esta organização') {\n super(message)\n this.name = 'MoviieSubscriptionInactiveError'\n }\n}\n\nexport class MoviieNetworkError extends Error {\n readonly code: MoviieErrorCode = 'network'\n\n constructor(message = 'Falha de rede. Tente novamente') {\n super(message)\n this.name = 'MoviieNetworkError'\n }\n}\n\nexport class MoviieRateLimitError extends Error {\n readonly code: MoviieErrorCode = 'rate_limit'\n\n constructor(message = 'Muitas solicitações. Aguarde e tente novamente') {\n super(message)\n this.name = 'MoviieRateLimitError'\n }\n}\n","import {\n MoviieNetworkError,\n MoviieRateLimitError,\n} from \"./errors\"\n\nexport interface HttpRequestOptions extends RequestInit {\n timeoutMs?: number\n retries?: number\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000\nconst DEFAULT_RETRIES = 2\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nfunction backoffDelayMs(attempt: number): number {\n const base = 2 ** attempt * 200\n const jitter = Math.floor(Math.random() * 200)\n return base + jitter\n}\n\nfunction composeAbortSignals(\n external: AbortSignal | null | undefined,\n internal: AbortSignal\n): AbortSignal {\n if (!external) return internal\n if (external.aborted) return external\n\n const controller = new AbortController()\n const onAbort = (signal: AbortSignal) => () => {\n controller.abort(signal.reason)\n }\n external.addEventListener(\"abort\", onAbort(external), { once: true })\n internal.addEventListener(\"abort\", onAbort(internal), { once: true })\n return controller.signal\n}\n\nexport async function fetchWithRetry(\n input: string | URL,\n init: HttpRequestOptions = {}\n): Promise<Response> {\n const timeoutMs = init.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const maxRetries = init.retries ?? DEFAULT_RETRIES\n const { timeoutMs: _t, retries: _r, signal: externalSignal, ...rest } = init\n\n let lastError: unknown\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const timeoutController = new AbortController()\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs)\n const signal = composeAbortSignals(externalSignal, timeoutController.signal)\n\n try {\n const response = await fetch(input, { ...rest, signal })\n clearTimeout(timer)\n\n if (response.status === 429) {\n throw new MoviieRateLimitError()\n }\n\n if (response.status >= 500 && response.status < 600 && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n return response\n } catch (error) {\n clearTimeout(timer)\n lastError = error\n\n if (error instanceof MoviieRateLimitError) throw error\n\n if (externalSignal?.aborted) {\n throw externalSignal.reason instanceof Error\n ? externalSignal.reason\n : new DOMException(\"Aborted\", \"AbortError\")\n }\n\n const isAbort = error instanceof Error && error.name === \"AbortError\"\n if (isAbort && attempt < maxRetries) {\n await delay(backoffDelayMs(attempt))\n continue\n }\n\n if (attempt >= maxRetries) {\n throw new MoviieNetworkError()\n }\n\n await delay(backoffDelayMs(attempt))\n }\n }\n\n throw lastError instanceof Error ? lastError : new MoviieNetworkError()\n}\n","import type { MoviieClientInfo } from \"../types\"\n\nconst SEPARATOR = \";\"\n\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[\\r\\n;]/g, \"\").trim()\n}\n\nexport function buildClientHeaders(params: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n}): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const key = params.publishableKey?.trim()\n if (key) {\n headers.Authorization = `Bearer ${key}`\n }\n\n const info = params.clientInfo\n if (info) {\n const parts: string[] = []\n if (info.bundleId) {\n parts.push(`bundle_id=${sanitizeSegment(info.bundleId)}`)\n }\n parts.push(`platform=${sanitizeSegment(info.platform)}`)\n const sdk = params.sdkVersion ?? info.sdkVersion\n if (sdk) {\n parts.push(`sdk=${sanitizeSegment(sdk)}`)\n }\n headers[\"X-Moviie-Client\"] = parts.join(SEPARATOR)\n }\n\n return headers\n}\n","import { HTTP_HEADER_MOVIIE_REASON, MOVIIE_BLOCK_REASON } from '../constants'\nimport {\n MoviieAuthError,\n MoviieBundleBlockedError,\n MoviieDirectAccessBlockedError,\n MoviieNetworkError,\n MoviieNotFoundError,\n MoviieReferrerBlockedError,\n MoviieSubscriptionInactiveError,\n} from '../client/errors'\nimport { fetchWithRetry } from '../client/http'\nimport type { MoviiePlaybackData } from '../types'\n\nimport { z } from 'zod'\n\nconst playbackPayloadSchema = z.object({\n uri: z.string().url(),\n contentType: z.enum(['hls', 'progressive']),\n expiresAt: z.string().nullable(),\n refreshAfter: z.string().nullable(),\n requestHeaders: z.record(z.string()).optional(),\n})\n\nexport const moviiePlaybackDataResponseSchema = z\n .object({\n embedId: z.string(),\n title: z.string(),\n smartProgressEnabled: z.boolean(),\n durationSeconds: z.number().nullable(),\n isVertical: z.boolean(),\n videoWidthPx: z.number().int().positive().nullable(),\n videoHeightPx: z.number().int().positive().nullable(),\n profile: z.string(),\n playback: playbackPayloadSchema,\n posterUrl: z.string().nullable(),\n branding: z.object({\n primaryColor: z.string().nullable(),\n showWatermark: z.boolean(),\n organizationName: z.string().nullable(),\n }),\n telemetry: z.object({\n bootstrapUrl: z.string().url(),\n }),\n })\n .passthrough()\n\nexport async function fetchPlaybackData(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<MoviiePlaybackData> {\n const response = await fetchWithRetry(params.url, {\n headers: params.headers,\n signal: params.signal,\n method: 'GET',\n })\n\n const reason = response.headers.get(HTTP_HEADER_MOVIIE_REASON)?.toLowerCase()\n\n if (response.status === 401) {\n throw new MoviieAuthError()\n }\n\n if (response.status === 402) {\n throw new MoviieSubscriptionInactiveError()\n }\n\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n\n if (response.status === 403) {\n if (reason === MOVIIE_BLOCK_REASON.BUNDLE) {\n throw new MoviieBundleBlockedError()\n }\n if (reason === MOVIIE_BLOCK_REASON.DIRECT_ACCESS) {\n throw new MoviieDirectAccessBlockedError()\n }\n throw new MoviieReferrerBlockedError()\n }\n\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n\n if (!response.ok) {\n throw new MoviieNotFoundError('Não foi possível carregar a reprodução')\n }\n\n const json: unknown = await response.json()\n const parsed = moviiePlaybackDataResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError('Resposta de playback inválida')\n }\n\n return parsed.data as unknown as MoviiePlaybackData\n}\n","import { z } from 'zod'\n\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from '../client/errors'\nimport { fetchWithRetry } from '../client/http'\n\n/** A single moment in the video where the term occurs. */\nexport interface TranscriptSearchMatch {\n segmentIndex: number\n startSeconds: number\n endSeconds: number\n /** The sentence/segment containing the term (length-bounded by the server). */\n text: string\n}\n\n/** Result set for one transcript search query. */\nexport interface TranscriptSearchResult {\n query: string\n language: string | null\n total: number\n matches: TranscriptSearchMatch[]\n nextCursor: number | null\n}\n\nconst matchSchema = z.object({\n segmentIndex: z.number().int(),\n startSeconds: z.number(),\n endSeconds: z.number(),\n text: z.string(),\n})\n\nconst resultSchema = z.object({\n query: z.string(),\n language: z.string().nullable(),\n total: z.number().int(),\n matches: z.array(matchSchema),\n nextCursor: z.number().int().nullable(),\n})\n\n/** Default debounce and minimum query length for the in-player search UI. */\nexport const TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250\nexport const TRANSCRIPT_SEARCH_MIN_LENGTH = 2\n\nconst EMPTY_RESULT = (query: string): TranscriptSearchResult => ({\n query,\n language: null,\n total: 0,\n matches: [],\n nextCursor: null,\n})\n\n/** Low-level fetch of the transcript search endpoint, with error mapping. */\nexport async function fetchTranscriptSearch(params: {\n url: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}): Promise<TranscriptSearchResult> {\n const response = await fetchWithRetry(params.url, {\n method: 'GET',\n headers: params.headers,\n signal: params.signal,\n })\n\n if (response.status === 401) throw new MoviieAuthError()\n // 429 is mapped to MoviieRateLimitError upstream by fetchWithRetry before a\n // Response is ever returned here, so no 429 branch is needed (or reachable).\n if (response.status === 404) throw new MoviieNotFoundError()\n if (response.status >= 500) throw new MoviieNetworkError()\n if (!response.ok) throw new MoviieNetworkError()\n\n const json: unknown = await response.json()\n const parsed = resultSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNetworkError('Resposta de busca inválida')\n }\n return parsed.data\n}\n\nexport interface TranscriptSearchController {\n /** Schedule a debounced search for the (trimmed) query. */\n search(query: string): void\n /** Cancel any pending debounce and in-flight request. */\n cancel(): void\n /** Tear down the controller. */\n destroy(): void\n}\n\n/**\n * UI controller that applies debounce + a minimum query length before calling\n * the search endpoint, and aborts any in-flight request when a newer query\n * arrives. Queries below the minimum length clear the results without hitting\n * the network — this is what keeps incomplete words from flooding the backend\n * (FR-003 / SC-002).\n */\nexport function createTranscriptSearchController(opts: {\n fetcher: (query: string, signal: AbortSignal) => Promise<TranscriptSearchResult>\n onResult: (result: TranscriptSearchResult) => void\n onError?: (error: unknown) => void\n onLoadingChange?: (loading: boolean) => void\n debounceMs?: number\n minLength?: number\n}): TranscriptSearchController {\n const debounceMs = opts.debounceMs ?? TRANSCRIPT_SEARCH_DEBOUNCE_MS\n const minLength = opts.minLength ?? TRANSCRIPT_SEARCH_MIN_LENGTH\n\n let timer: ReturnType<typeof setTimeout> | null = null\n let inFlight: AbortController | null = null\n\n function clearTimer(): void {\n if (timer !== null) {\n clearTimeout(timer)\n timer = null\n }\n }\n\n function cancelInFlight(): void {\n if (inFlight) {\n inFlight.abort()\n inFlight = null\n }\n }\n\n function search(rawQuery: string): void {\n const query = rawQuery.trim()\n clearTimer()\n\n if (query.length < minLength) {\n cancelInFlight()\n opts.onResult(EMPTY_RESULT(query))\n return\n }\n\n timer = setTimeout(() => {\n timer = null\n cancelInFlight()\n const controller = new AbortController()\n inFlight = controller\n opts.onLoadingChange?.(true)\n opts\n .fetcher(query, controller.signal)\n .then((result) => {\n if (!controller.signal.aborted) opts.onResult(result)\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted) return\n if (error instanceof Error && error.name === 'AbortError') return\n opts.onError?.(error)\n })\n .finally(() => {\n // Only the current request clears loading — a superseded/aborted\n // request must not hide the indicator belonging to a newer one.\n if (inFlight === controller) {\n inFlight = null\n opts.onLoadingChange?.(false)\n }\n })\n }, debounceMs)\n }\n\n return {\n search,\n cancel(): void {\n clearTimer()\n cancelInFlight()\n },\n destroy(): void {\n clearTimer()\n cancelInFlight()\n },\n }\n}\n","import { z } from 'zod'\n\nimport {\n SDK_PLAYBACK_AUTH_ERROR_MESSAGE,\n SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE,\n} from '../constants'\nimport { getMoviieApiBaseUrl, getMoviieEventsBaseUrl } from '../config/moviie-endpoints'\nimport { MoviieAuthError, MoviieNetworkError, MoviieNotFoundError } from './errors'\nimport { fetchWithRetry } from './http'\nimport { buildClientHeaders } from './client-headers'\nimport { fetchPlaybackData } from '../playback/fetch-playback'\nimport {\n fetchTranscriptSearch,\n type TranscriptSearchResult,\n} from '../search/transcript-search-client'\nimport type { MoviieClientInfo, MoviiePlaybackData, MoviieVideo } from '../types'\n\nconst videoEmbedResponseSchema = z.object({\n id: z.string().uuid(),\n embed_id: z.string().uuid(),\n})\n\nexport class MoviieClient {\n constructor(\n private readonly options: {\n publishableKey?: string | null\n clientInfo?: MoviieClientInfo | null\n sdkVersion?: string\n }\n ) {}\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n ...buildClientHeaders({\n publishableKey: this.options.publishableKey ?? undefined,\n clientInfo: this.options.clientInfo ?? undefined,\n sdkVersion: this.options.sdkVersion,\n }),\n ...extra,\n }\n }\n\n async getPlayback(embedId: string, signal?: AbortSignal): Promise<MoviiePlaybackData> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/playback`\n return fetchPlaybackData({\n url,\n headers: this.headers(),\n signal,\n })\n }\n\n /**\n * Search the spoken content of the video a playback session is playing, and\n * return the moments where the term appears (each with a timestamp). The\n * session scopes the search to the video it actually loaded (swap-safe) and\n * authorizes the request — it was gated when bootstrapped. Obtain the session\n * id from the telemetry bootstrap. Matching is case- and accent-insensitive.\n */\n async search(\n sessionId: string,\n query: string,\n opts?: {\n limit?: number\n cursor?: number | null\n signal?: AbortSignal\n }\n ): Promise<TranscriptSearchResult> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN)\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const params = new URLSearchParams({ q: query })\n if (opts?.limit != null) params.set('limit', String(opts.limit))\n if (opts?.cursor != null) params.set('cursor', String(opts.cursor))\n const url = `${base}/sessions/${encodeURIComponent(sessionId)}/search?${params.toString()}`\n return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal })\n }\n\n /**\n * Private transcript search for an embed's video (feature 183) — the\n * authenticated twin of {@link search}. Requires a PRIVATE API key (publishable\n * keys are rejected) and is scoped to the key's organization; the embed must\n * belong to it. Unlike {@link search} it needs no playback session. Matching is\n * case- and accent-insensitive.\n */\n async searchEmbedTranscript(\n embedId: string,\n query: string,\n opts?: {\n limit?: number\n cursor?: number | null\n signal?: AbortSignal\n }\n ): Promise<TranscriptSearchResult> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED)\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError('A busca privada exige uma chave de API privada (não publishable).')\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const params = new URLSearchParams({ q: query })\n if (opts?.limit != null) params.set('limit', String(opts.limit))\n if (opts?.cursor != null) params.set('cursor', String(opts.cursor))\n const url = `${base}/embeds/${encodeURIComponent(embedId)}/transcript/search?${params.toString()}`\n return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal })\n }\n\n async getVideo(videoId: string, signal?: AbortSignal): Promise<MoviieVideo> {\n const key = this.options.publishableKey?.trim()\n if (!key) {\n throw new MoviieAuthError('Chave de API obrigatória para buscar vídeo por ID')\n }\n if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {\n throw new MoviieAuthError('Chave publishable não pode listar vídeos administrativos')\n }\n\n const base = getMoviieApiBaseUrl().replace(/\\/+$/, '')\n const url = `${base}/videos/${encodeURIComponent(videoId)}`\n const response = await fetchWithRetry(url, {\n method: 'GET',\n headers: this.headers(),\n signal,\n })\n\n if (response.status === 401 || response.status === 403) {\n throw new MoviieAuthError()\n }\n if (response.status === 404) {\n throw new MoviieNotFoundError()\n }\n if (response.status >= 500) {\n throw new MoviieNetworkError()\n }\n if (!response.ok) {\n throw new MoviieNotFoundError()\n }\n\n const json: unknown = await response.json()\n const parsed = videoEmbedResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new MoviieNotFoundError('Resposta de vídeo inválida')\n }\n\n return {\n id: parsed.data.id,\n embedId: parsed.data.embed_id,\n }\n }\n\n async resolveEmbedIdFromVideoId(videoId: string, signal?: AbortSignal): Promise<string> {\n const video = await this.getVideo(videoId, signal)\n if (!video.embedId) {\n throw new MoviieNotFoundError('Embed não encontrado para este vídeo')\n }\n return video.embedId\n }\n\n getEventsBaseUrl(): string {\n return getMoviieEventsBaseUrl().replace(/\\/+$/, '')\n }\n}\n","import { z } from \"zod\"\n\nexport const PLAYBACK_EVENT_TYPE = {\n SESSION_START: \"session_start\",\n PLAY_START: \"play_start\",\n PAUSE: \"pause\",\n RESUME: \"resume\",\n HEARTBEAT: \"heartbeat\",\n ENDED: \"ended\",\n CTA_CLICK: \"cta_click\",\n ERROR: \"error\",\n} as const\n\nexport const PLAYBACK_EVENT_TYPE_VALUES = Object.values(PLAYBACK_EVENT_TYPE)\n\nexport const playbackEventTypeSchema = z.enum(\n PLAYBACK_EVENT_TYPE_VALUES as [string, ...string[]]\n)\n\nexport type PlaybackEventType = z.infer<typeof playbackEventTypeSchema>\n\nexport const TELEMETRY_TOKEN_CONFIG = {\n INGEST_TOKEN_EXPIRY_SECONDS: 600,\n REFRESH_TOKEN_EXPIRY_SECONDS: 86400,\n REFRESH_BUFFER_SECONDS: 120,\n} as const\n\nexport const HEARTBEAT_CONFIG = {\n INTERVAL_SECONDS: 10,\n WATCH_TIME_PER_HEARTBEAT_SECONDS: 10,\n} as const\n\nexport const bootstrapResponseSchema = z.object({\n sessionId: z.string().uuid(),\n eventsIngestToken: z.string(),\n eventsRefreshToken: z.string(),\n ctaId: z.string().optional(),\n})\n\nexport type BootstrapResponse = z.infer<typeof bootstrapResponseSchema>\n\nexport const tokenRefreshRequestSchema = z.object({\n sessionId: z.string().uuid(),\n eventsRefreshToken: z.string(),\n})\n\nexport const tokenRefreshResponseSchema = z.object({\n eventsIngestToken: z.string(),\n expiresInSeconds: z.number(),\n})\n\nexport type TokenRefreshResponse = z.infer<typeof tokenRefreshResponseSchema>\n\nexport const playbackEventSchema = z.object({\n eventId: z.string().uuid(),\n sessionId: z.string().uuid(),\n eventType: playbackEventTypeSchema,\n positionSeconds: z.number().int().min(0).optional(),\n ctaId: z.string().optional(),\n errorCode: z.string().max(50).optional(),\n})\n\nexport const eventIngestRequestSchema = z.object({\n events: z.array(playbackEventSchema).min(1).max(100),\n ingestToken: z.string().optional(),\n})\n\nexport type PlaybackTelemetryEvent = z.infer<typeof playbackEventSchema>\n","export class HeartbeatScheduler {\n private timer: ReturnType<typeof setInterval> | null = null\n private paused = false\n\n constructor(\n private readonly options: {\n intervalSeconds: number\n onTick: () => void\n }\n ) {}\n\n start(): void {\n if (this.timer) return\n const ms = Math.max(1_000, this.options.intervalSeconds * 1000)\n this.timer = setInterval(() => {\n if (!this.paused) {\n this.options.onTick()\n }\n }, ms)\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer)\n this.timer = null\n }\n }\n\n pause(): void {\n this.paused = true\n }\n\n resume(): void {\n this.paused = false\n }\n\n destroy(): void {\n this.stop()\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport {\n bootstrapResponseSchema,\n TELEMETRY_TOKEN_CONFIG,\n tokenRefreshRequestSchema,\n tokenRefreshResponseSchema,\n type BootstrapResponse,\n} from \"./types\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst REFRESH_MIN_DELAY_MS = 5_000\nconst REFRESH_RETRY_BACKOFF_MS = [5_000, 15_000, 60_000]\n\nexport class TelemetryTokenManager {\n private ingestToken: string | null = null\n private refreshToken: string | null = null\n private sessionId: string | null = null\n private refreshTimer: ReturnType<typeof setTimeout> | null = null\n private refreshFailureCount = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n }\n ) {}\n\n getSessionId(): string | null {\n return this.sessionId\n }\n\n getIngestToken(): string | null {\n return this.ingestToken\n }\n\n async bootstrap(bootstrapUrl: string): Promise<BootstrapResponse> {\n const response = await fetchWithRetry(bootstrapUrl, {\n method: \"GET\",\n headers: this.options.defaultHeaders,\n })\n\n if (!response.ok) {\n throw new Error(`Bootstrap falhou: ${response.status}`)\n }\n\n const json: unknown = await response.json()\n const parsed = bootstrapResponseSchema.safeParse(json)\n if (!parsed.success) {\n throw new Error(\"Resposta de bootstrap inválida\")\n }\n\n this.sessionId = parsed.data.sessionId\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshToken = parsed.data.eventsRefreshToken\n\n const store = this.options.viewerTokenStore\n if (store && parsed.data.eventsRefreshToken) {\n await store.set(parsed.data.eventsRefreshToken, TELEMETRY_TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY_SECONDS)\n }\n\n this.refreshFailureCount = 0\n this.scheduleRefresh(TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS)\n return parsed.data\n }\n\n private scheduleRefresh(expirySeconds: number): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const delayMs =\n (expirySeconds - TELEMETRY_TOKEN_CONFIG.REFRESH_BUFFER_SECONDS) * 1000\n\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, Math.max(REFRESH_MIN_DELAY_MS, delayMs))\n }\n\n private scheduleRefreshRetry(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n\n const refreshUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/token/refresh`\n const index = Math.min(\n this.refreshFailureCount,\n REFRESH_RETRY_BACKOFF_MS.length - 1\n )\n const base = REFRESH_RETRY_BACKOFF_MS[index] ?? REFRESH_MIN_DELAY_MS\n const jitter = Math.floor(Math.random() * 1_000)\n this.refreshTimer = setTimeout(() => {\n void this.refresh(refreshUrl)\n }, base + jitter)\n }\n\n private async refresh(refreshUrl: string): Promise<void> {\n if (!this.sessionId || !this.refreshToken) return\n\n const body = tokenRefreshRequestSchema.parse({\n sessionId: this.sessionId,\n eventsRefreshToken: this.refreshToken,\n })\n\n try {\n const response = await fetchWithRetry(refreshUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n const json: unknown = await response.json()\n const parsed = tokenRefreshResponseSchema.safeParse(json)\n if (!parsed.success) {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n return\n }\n\n this.ingestToken = parsed.data.eventsIngestToken\n this.refreshFailureCount = 0\n const nextExpiry =\n parsed.data.expiresInSeconds > 0\n ? parsed.data.expiresInSeconds\n : TELEMETRY_TOKEN_CONFIG.INGEST_TOKEN_EXPIRY_SECONDS\n this.scheduleRefresh(nextExpiry)\n } catch {\n this.refreshFailureCount += 1\n this.scheduleRefreshRetry()\n }\n }\n\n destroy(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer)\n this.refreshTimer = null\n }\n }\n}\n","import { fetchWithRetry } from \"../client/http\"\nimport { HEARTBEAT_CONFIG, PLAYBACK_EVENT_TYPE, type PlaybackEventType } from \"./types\"\nimport { HeartbeatScheduler } from \"./heartbeat-scheduler\"\nimport { TelemetryTokenManager } from \"./token-manager\"\nimport type { ViewerTokenStore } from \"./viewer-token-store\"\n\nconst BATCH_MAX = 10\nconst FLUSH_MS = 5_000\n\nfunction randomHex(length: number): string {\n let out = \"\"\n while (out.length < length) {\n out += Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, \"0\")\n }\n return out.slice(0, length)\n}\n\nfunction newEventId(): string {\n const g = globalThis as typeof globalThis & {\n crypto?: { randomUUID?: () => string }\n }\n if (typeof g.crypto?.randomUUID === \"function\") {\n return g.crypto.randomUUID()\n }\n return `${randomHex(8)}-${randomHex(4)}-4${randomHex(3)}-8${randomHex(3)}-${randomHex(12)}`\n}\n\nexport class TelemetryClient {\n private readonly tokenManager: TelemetryTokenManager\n private readonly heartbeat: HeartbeatScheduler\n private pending: Array<Record<string, unknown>> = []\n private flushTimer: ReturnType<typeof setTimeout> | null = null\n private positionSeconds = 0\n\n constructor(\n private readonly options: {\n eventsBaseUrl: string\n defaultHeaders?: Record<string, string>\n viewerTokenStore?: ViewerTokenStore\n getPositionSeconds?: () => number\n }\n ) {\n this.tokenManager = new TelemetryTokenManager({\n eventsBaseUrl: options.eventsBaseUrl,\n defaultHeaders: options.defaultHeaders,\n viewerTokenStore: options.viewerTokenStore,\n })\n\n this.heartbeat = new HeartbeatScheduler({\n intervalSeconds: HEARTBEAT_CONFIG.INTERVAL_SECONDS,\n onTick: () => {\n const pos =\n typeof options.getPositionSeconds === \"function\"\n ? Math.floor(options.getPositionSeconds())\n : this.positionSeconds\n void this.recordEvent({\n eventType: PLAYBACK_EVENT_TYPE.HEARTBEAT,\n positionSeconds: Math.max(0, pos),\n })\n },\n })\n }\n\n async bootstrap(params: { bootstrapUrl: string }): Promise<{ sessionId: string }> {\n const res = await this.tokenManager.bootstrap(params.bootstrapUrl)\n return { sessionId: res.sessionId }\n }\n\n updatePosition(seconds: number): void {\n this.positionSeconds = Math.max(0, seconds)\n }\n\n async recordEvent(params: {\n eventType: PlaybackEventType\n positionSeconds?: number\n ctaId?: string\n errorCode?: string\n }): Promise<void> {\n const sessionId = this.tokenManager.getSessionId()\n if (!sessionId) return\n\n const payload: Record<string, unknown> = {\n eventId: newEventId(),\n sessionId,\n eventType: params.eventType,\n }\n if (params.positionSeconds !== undefined) {\n payload.positionSeconds = params.positionSeconds\n }\n if (params.ctaId !== undefined) {\n payload.ctaId = params.ctaId\n }\n if (params.errorCode !== undefined) {\n payload.errorCode = params.errorCode\n }\n\n this.pending.push(payload)\n if (this.pending.length >= BATCH_MAX) {\n await this.flush()\n } else {\n this.scheduleFlush()\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null\n void this.flush()\n }, FLUSH_MS)\n }\n\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer)\n this.flushTimer = null\n }\n\n if (this.pending.length === 0) {\n return\n }\n\n const ingestToken = this.tokenManager.getIngestToken()\n const sessionId = this.tokenManager.getSessionId()\n if (!ingestToken || !sessionId) {\n this.scheduleFlush()\n return\n }\n\n const batch = this.pending.splice(0, BATCH_MAX)\n const eventsUrl = `${this.options.eventsBaseUrl.replace(/\\/+$/, \"\")}/events`\n\n try {\n const response = await fetchWithRetry(eventsUrl, {\n method: \"POST\",\n headers: {\n ...this.options.defaultHeaders,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${ingestToken}`,\n },\n body: JSON.stringify({ events: batch }),\n })\n if (!response.ok && response.status >= 500) {\n this.pending.unshift(...batch)\n }\n } catch {\n this.pending.unshift(...batch)\n }\n\n if (this.pending.length > 0) {\n this.scheduleFlush()\n }\n }\n\n startHeartbeats(): void {\n this.heartbeat.start()\n }\n\n stopHeartbeats(): void {\n this.heartbeat.stop()\n }\n\n pauseHeartbeats(): void {\n this.heartbeat.pause()\n }\n\n resumeHeartbeats(): void {\n this.heartbeat.resume()\n }\n\n async destroy(): Promise<void> {\n this.heartbeat.destroy()\n this.tokenManager.destroy()\n await this.flush()\n }\n}\n","export interface ViewerTokenStore {\n get(): Promise<string | null>\n set(token: string, ttlSec: number): Promise<void>\n}\n\nexport class MemoryViewerTokenStore implements ViewerTokenStore {\n private value: string | null = null\n\n async get(): Promise<string | null> {\n return this.value\n }\n\n async set(token: string, _ttlSec: number): Promise<void> {\n this.value = token\n }\n}\n","import type { MoviiePlaybackPayload } from \"../types\"\n\nconst REFRESH_BUFFER_MS = 60_000\n\nexport function planRefresh(params: {\n playback: Pick<MoviiePlaybackPayload, \"expiresAt\" | \"refreshAfter\">\n now: Date\n}): { delayMs: number } | null {\n const { expiresAt, refreshAfter } = params.playback\n if (!expiresAt && !refreshAfter) {\n return null\n }\n\n const anchorIso = refreshAfter ?? expiresAt\n if (!anchorIso) return null\n\n const anchor = Date.parse(anchorIso)\n if (!Number.isFinite(anchor)) return null\n\n const target = anchor - REFRESH_BUFFER_MS\n const delayMs = Math.max(0, target - params.now.getTime())\n return { delayMs }\n}\n","const BOOTSTRAP_SEGMENT_PATTERN = /\\/bootstrap\\/[^/]+\\/?$/i\n\nconst TELEMETRY_PATH_MARKER = \"/telemetry\"\n\nexport function deriveTelemetryEventsBaseUrlFromBootstrapUrl(\n bootstrapUrl: string\n): string | null {\n try {\n const u = new URL(bootstrapUrl)\n const stripped = u.pathname.replace(BOOTSTRAP_SEGMENT_PATTERN, \"\")\n if (!stripped.includes(TELEMETRY_PATH_MARKER)) {\n return null\n }\n const normalizedPath = stripped.replace(/\\/+$/, \"\") || \"/\"\n return `${u.origin}${normalizedPath}`\n } catch {\n return null\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moviie/player-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Vendor-agnostic Moviie player SDK — playback metadata, HTTP client, telemetry.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"zod": "^3.25.76",
|
|
44
|
-
"@moviie/player-types": "1.
|
|
44
|
+
"@moviie/player-types": "1.2.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^22.10.2",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"tsup": "^8.5.0",
|
|
51
51
|
"typescript": "^5.9.3",
|
|
52
52
|
"vitest": "^3.2.4",
|
|
53
|
-
"@moviie/eslint-config": "0.
|
|
53
|
+
"@moviie/eslint-config": "0.2.0",
|
|
54
54
|
"@moviie/prettier-config": "0.1.0",
|
|
55
55
|
"@moviie/tsconfig": "0.1.0"
|
|
56
56
|
},
|