@moviie/player-sdk 0.2.0 → 0.3.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/LICENSE +21 -0
- package/README.md +70 -11
- package/dist/index.cjs +144 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -1
- package/dist/index.d.ts +74 -1
- package/dist/index.js +141 -1
- package/dist/index.js.map +1 -1
- package/package.json +26 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Moviie
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# @moviie/player-sdk
|
|
2
2
|
|
|
3
|
-
Vendor-agnostic
|
|
3
|
+
Vendor-agnostic JavaScript SDK for the [Moviie](https://moviie.ai) video platform. Fetch playback metadata, build custom player UIs, and integrate Moviie playback into any runtime — Node.js, browsers, React Native, Expo, or edge workers.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Full documentation: [docs.moviie.ai](https://docs.moviie.ai).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Prerequisites
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
You need a **[Moviie](https://moviie.ai) account** and a **publishable API key** (`mvi_pub_*`).
|
|
10
|
+
|
|
11
|
+
1. Create an account at [app.moviie.ai/signin](https://app.moviie.ai/signin).
|
|
12
|
+
2. Go to **Organization Settings → API Keys** and create a **Publishable** key.
|
|
13
|
+
3. Copy the key — it starts with `mvi_pub_`.
|
|
14
|
+
|
|
15
|
+
> **Never** use a secret key (`mvi_sec_*`) in a client app. The playback API rejects it.
|
|
10
16
|
|
|
11
17
|
## Install
|
|
12
18
|
|
|
@@ -14,17 +20,70 @@ Private/admin keys belong only on the server; they are **not** accepted by the p
|
|
|
14
20
|
pnpm add @moviie/player-sdk
|
|
15
21
|
```
|
|
16
22
|
|
|
17
|
-
##
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { MoviieClient } from "@moviie/player-sdk"
|
|
27
|
+
|
|
28
|
+
const client = new MoviieClient({
|
|
29
|
+
publishableKey: process.env.MOVIIE_PUBLISHABLE_KEY,
|
|
30
|
+
clientInfo: {
|
|
31
|
+
platform: "web",
|
|
32
|
+
sdkVersion: "1.0.0",
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const playback = await client.getPlayback("YOUR-EMBED-UUID")
|
|
37
|
+
console.log(playback.playback.uri) // HLS stream URL
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The returned `MoviiePlaybackData` includes the HLS source, poster, captions, chapters, CTAs, and per-embed control flags (Chromecast, PiP, autoplay, etc.). Wire it into any video element or player library.
|
|
41
|
+
|
|
42
|
+
## API
|
|
18
43
|
|
|
19
|
-
|
|
44
|
+
### `new MoviieClient(options)`
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
46
|
+
| Option | Type | Required | Description |
|
|
47
|
+
|--------|------|:--------:|-------------|
|
|
48
|
+
| `publishableKey` | `string` | ✓ | Publishable key (`mvi_pub_*`) from your [Moviie](https://moviie.ai) organization settings. |
|
|
49
|
+
| `clientInfo` | `MoviieClientInfo` | — | Optional bundle ID, platform, and SDK version. Sent as request headers for analytics and bundle-ID allowlisting. |
|
|
50
|
+
| `sdkVersion` | `string` | — | Optional SDK version string sent with requests. |
|
|
51
|
+
|
|
52
|
+
### `client.getPlayback(embedId)`
|
|
53
|
+
|
|
54
|
+
Fetches playback metadata for a public embed. Returns `Promise<MoviiePlaybackData>`. Throws a typed error on failure:
|
|
55
|
+
|
|
56
|
+
| Class | `.code` | Cause |
|
|
57
|
+
|-------|---------|-------|
|
|
58
|
+
| `MoviieAuthError` | `auth` | Invalid or missing publishable key. |
|
|
59
|
+
| `MoviieNotFoundError` | `not_found` | Embed UUID does not exist. |
|
|
60
|
+
| `MoviieBundleBlockedError` | `bundle_blocked` | Bundle ID not on the embed allowlist. |
|
|
61
|
+
| `MoviieReferrerBlockedError` | `referrer_blocked` | Request origin not on the embed allowlist. |
|
|
62
|
+
| `MoviieSubscriptionInactiveError` | `subscription_inactive` | Organization subscription is paused or expired. |
|
|
63
|
+
| `MoviieNetworkError` | `network` | Network request failed (timeout, unreachable). |
|
|
64
|
+
| `MoviieRateLimitError` | `rate_limit` | Too many requests in a short period. |
|
|
65
|
+
|
|
66
|
+
Detect by class or code string:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { MoviieBundleBlockedError } from "@moviie/player-sdk"
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await client.getPlayback(embedId)
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof MoviieBundleBlockedError) {
|
|
75
|
+
// ask the user to update the allowlist in the Moviie dashboard
|
|
76
|
+
}
|
|
77
|
+
if (error?.code === "network") {
|
|
78
|
+
// retry
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
23
82
|
|
|
24
|
-
|
|
83
|
+
## Looking for the React Native / Expo player?
|
|
25
84
|
|
|
26
|
-
|
|
85
|
+
If you're building a mobile app with Expo or React Native, use [`@moviie/player-expo`](https://www.npmjs.com/package/@moviie/player-expo) — it wraps this SDK with a ready-to-use video component, custom chrome, Picture-in-Picture, background audio, and optional Chromecast.
|
|
27
86
|
|
|
28
87
|
## License
|
|
29
88
|
|
|
30
|
-
|
|
89
|
+
MIT — see [`LICENSE`](./LICENSE). Copyright (c) 2026 [Moviie](https://moviie.ai).
|
package/dist/index.cjs
CHANGED
|
@@ -270,6 +270,102 @@ async function fetchPlaybackData(params) {
|
|
|
270
270
|
}
|
|
271
271
|
return parsed.data;
|
|
272
272
|
}
|
|
273
|
+
var matchSchema = zod.z.object({
|
|
274
|
+
segmentIndex: zod.z.number().int(),
|
|
275
|
+
startSeconds: zod.z.number(),
|
|
276
|
+
endSeconds: zod.z.number(),
|
|
277
|
+
text: zod.z.string()
|
|
278
|
+
});
|
|
279
|
+
var resultSchema = zod.z.object({
|
|
280
|
+
query: zod.z.string(),
|
|
281
|
+
language: zod.z.string().nullable(),
|
|
282
|
+
total: zod.z.number().int(),
|
|
283
|
+
matches: zod.z.array(matchSchema),
|
|
284
|
+
nextCursor: zod.z.number().int().nullable()
|
|
285
|
+
});
|
|
286
|
+
var TRANSCRIPT_SEARCH_DEBOUNCE_MS = 250;
|
|
287
|
+
var TRANSCRIPT_SEARCH_MIN_LENGTH = 2;
|
|
288
|
+
var EMPTY_RESULT = (query) => ({
|
|
289
|
+
query,
|
|
290
|
+
language: null,
|
|
291
|
+
total: 0,
|
|
292
|
+
matches: [],
|
|
293
|
+
nextCursor: null
|
|
294
|
+
});
|
|
295
|
+
async function fetchTranscriptSearch(params) {
|
|
296
|
+
const response = await fetchWithRetry(params.url, {
|
|
297
|
+
method: "GET",
|
|
298
|
+
headers: params.headers,
|
|
299
|
+
signal: params.signal
|
|
300
|
+
});
|
|
301
|
+
if (response.status === 401) throw new MoviieAuthError();
|
|
302
|
+
if (response.status === 404) throw new MoviieNotFoundError();
|
|
303
|
+
if (response.status >= 500) throw new MoviieNetworkError();
|
|
304
|
+
if (!response.ok) throw new MoviieNetworkError();
|
|
305
|
+
const json = await response.json();
|
|
306
|
+
const parsed = resultSchema.safeParse(json);
|
|
307
|
+
if (!parsed.success) {
|
|
308
|
+
throw new MoviieNetworkError("Resposta de busca inv\xE1lida");
|
|
309
|
+
}
|
|
310
|
+
return parsed.data;
|
|
311
|
+
}
|
|
312
|
+
function createTranscriptSearchController(opts) {
|
|
313
|
+
const debounceMs = opts.debounceMs ?? TRANSCRIPT_SEARCH_DEBOUNCE_MS;
|
|
314
|
+
const minLength = opts.minLength ?? TRANSCRIPT_SEARCH_MIN_LENGTH;
|
|
315
|
+
let timer = null;
|
|
316
|
+
let inFlight = null;
|
|
317
|
+
function clearTimer() {
|
|
318
|
+
if (timer !== null) {
|
|
319
|
+
clearTimeout(timer);
|
|
320
|
+
timer = null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function cancelInFlight() {
|
|
324
|
+
if (inFlight) {
|
|
325
|
+
inFlight.abort();
|
|
326
|
+
inFlight = null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function search(rawQuery) {
|
|
330
|
+
const query = rawQuery.trim();
|
|
331
|
+
clearTimer();
|
|
332
|
+
if (query.length < minLength) {
|
|
333
|
+
cancelInFlight();
|
|
334
|
+
opts.onResult(EMPTY_RESULT(query));
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
timer = setTimeout(() => {
|
|
338
|
+
timer = null;
|
|
339
|
+
cancelInFlight();
|
|
340
|
+
const controller = new AbortController();
|
|
341
|
+
inFlight = controller;
|
|
342
|
+
opts.onLoadingChange?.(true);
|
|
343
|
+
opts.fetcher(query, controller.signal).then((result) => {
|
|
344
|
+
if (!controller.signal.aborted) opts.onResult(result);
|
|
345
|
+
}).catch((error) => {
|
|
346
|
+
if (controller.signal.aborted) return;
|
|
347
|
+
if (error instanceof Error && error.name === "AbortError") return;
|
|
348
|
+
opts.onError?.(error);
|
|
349
|
+
}).finally(() => {
|
|
350
|
+
if (inFlight === controller) {
|
|
351
|
+
inFlight = null;
|
|
352
|
+
opts.onLoadingChange?.(false);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}, debounceMs);
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
search,
|
|
359
|
+
cancel() {
|
|
360
|
+
clearTimer();
|
|
361
|
+
cancelInFlight();
|
|
362
|
+
},
|
|
363
|
+
destroy() {
|
|
364
|
+
clearTimer();
|
|
365
|
+
cancelInFlight();
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
}
|
|
273
369
|
|
|
274
370
|
// src/client/moviie-client.ts
|
|
275
371
|
var videoEmbedResponseSchema = zod.z.object({
|
|
@@ -307,6 +403,50 @@ var MoviieClient = class {
|
|
|
307
403
|
signal
|
|
308
404
|
});
|
|
309
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Search the spoken content of the video a playback session is playing, and
|
|
408
|
+
* return the moments where the term appears (each with a timestamp). The
|
|
409
|
+
* session scopes the search to the video it actually loaded (swap-safe) and
|
|
410
|
+
* authorizes the request — it was gated when bootstrapped. Obtain the session
|
|
411
|
+
* id from the telemetry bootstrap. Matching is case- and accent-insensitive.
|
|
412
|
+
*/
|
|
413
|
+
async search(sessionId, query, opts) {
|
|
414
|
+
const key = this.options.publishableKey?.trim();
|
|
415
|
+
if (!key) {
|
|
416
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
417
|
+
}
|
|
418
|
+
if (!key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
419
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.PRIVATE_KEY_FORBIDDEN);
|
|
420
|
+
}
|
|
421
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
422
|
+
const params = new URLSearchParams({ q: query });
|
|
423
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
424
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
425
|
+
const url = `${base}/sessions/${encodeURIComponent(sessionId)}/search?${params.toString()}`;
|
|
426
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Private transcript search for an embed's video (feature 183) — the
|
|
430
|
+
* authenticated twin of {@link search}. Requires a PRIVATE API key (publishable
|
|
431
|
+
* keys are rejected) and is scoped to the key's organization; the embed must
|
|
432
|
+
* belong to it. Unlike {@link search} it needs no playback session. Matching is
|
|
433
|
+
* case- and accent-insensitive.
|
|
434
|
+
*/
|
|
435
|
+
async searchEmbedTranscript(embedId, query, opts) {
|
|
436
|
+
const key = this.options.publishableKey?.trim();
|
|
437
|
+
if (!key) {
|
|
438
|
+
throw new MoviieAuthError(SDK_PLAYBACK_AUTH_ERROR_MESSAGE.KEY_REQUIRED);
|
|
439
|
+
}
|
|
440
|
+
if (key.startsWith(SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE)) {
|
|
441
|
+
throw new MoviieAuthError("A busca privada exige uma chave de API privada (n\xE3o publishable).");
|
|
442
|
+
}
|
|
443
|
+
const base = getMoviieApiBaseUrl().replace(/\/+$/, "");
|
|
444
|
+
const params = new URLSearchParams({ q: query });
|
|
445
|
+
if (opts?.limit != null) params.set("limit", String(opts.limit));
|
|
446
|
+
if (opts?.cursor != null) params.set("cursor", String(opts.cursor));
|
|
447
|
+
const url = `${base}/embeds/${encodeURIComponent(embedId)}/transcript/search?${params.toString()}`;
|
|
448
|
+
return fetchTranscriptSearch({ url, headers: this.headers(), signal: opts?.signal });
|
|
449
|
+
}
|
|
310
450
|
async getVideo(videoId, signal) {
|
|
311
451
|
const key = this.options.publishableKey?.trim();
|
|
312
452
|
if (!key) {
|
|
@@ -754,12 +894,16 @@ exports.PLAYBACK_EVENT_TYPE = PLAYBACK_EVENT_TYPE;
|
|
|
754
894
|
exports.SDK_PLAYBACK_AUTH_ERROR_MESSAGE = SDK_PLAYBACK_AUTH_ERROR_MESSAGE;
|
|
755
895
|
exports.SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE = SDK_PUBLIC_API_KEY_PREFIX_PUBLISHABLE;
|
|
756
896
|
exports.TELEMETRY_TOKEN_CONFIG = TELEMETRY_TOKEN_CONFIG;
|
|
897
|
+
exports.TRANSCRIPT_SEARCH_DEBOUNCE_MS = TRANSCRIPT_SEARCH_DEBOUNCE_MS;
|
|
898
|
+
exports.TRANSCRIPT_SEARCH_MIN_LENGTH = TRANSCRIPT_SEARCH_MIN_LENGTH;
|
|
757
899
|
exports.TelemetryClient = TelemetryClient;
|
|
758
900
|
exports.buildClientHeaders = buildClientHeaders;
|
|
759
901
|
exports.configureMoviieEndpoints = configureMoviieEndpoints;
|
|
902
|
+
exports.createTranscriptSearchController = createTranscriptSearchController;
|
|
760
903
|
exports.deriveMoviieTelemetryBaseUrlFromApiBaseUrl = deriveMoviieTelemetryBaseUrlFromApiBaseUrl;
|
|
761
904
|
exports.deriveTelemetryEventsBaseUrlFromBootstrapUrl = deriveTelemetryEventsBaseUrlFromBootstrapUrl;
|
|
762
905
|
exports.fetchPlaybackData = fetchPlaybackData;
|
|
906
|
+
exports.fetchTranscriptSearch = fetchTranscriptSearch;
|
|
763
907
|
exports.getMoviieApiBaseUrl = getMoviieApiBaseUrl;
|
|
764
908
|
exports.getMoviieEventsBaseUrl = getMoviieEventsBaseUrl;
|
|
765
909
|
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} 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 { 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"]}
|