@xhub-short/adapters 1.0.0-beta.25 → 1.0.0-beta.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1672,6 +1672,14 @@ declare class BrowserVideoLoader implements IVideoLoader {
1672
1672
  * Full segment preload requires hls.js which is optional
1673
1673
  */
1674
1674
  private preloadHLS;
1675
+ /**
1676
+ * Parse M3U8 manifest and pre-fetch the first N segments into the Cache API.
1677
+ * Runs concurrently for speed; tolerates individual segment fetch failures.
1678
+ *
1679
+ * Resolves relative segment paths against the manifest URL base.
1680
+ * Only runs when a cache is available - gracefully no-ops otherwise.
1681
+ */
1682
+ private preloadHLSSegments;
1675
1683
  /**
1676
1684
  * Cancel preload
1677
1685
  */
@@ -2109,6 +2117,10 @@ declare class HttpClient {
2109
2117
  * Get base URL (for sendBeacon which needs full URL)
2110
2118
  */
2111
2119
  getBaseUrl(): string;
2120
+ /**
2121
+ * Check if access token is available
2122
+ */
2123
+ hasAccessToken(): Promise<boolean>;
2112
2124
  private isRefreshing;
2113
2125
  private refreshPromise;
2114
2126
  constructor(config: HttpClientConfig);
package/dist/index.js CHANGED
@@ -2164,6 +2164,10 @@ var RESTAnalyticsAdapter = class {
2164
2164
  const events = [...this.queue];
2165
2165
  this.queue = [];
2166
2166
  try {
2167
+ const hasToken = await this.httpClient.hasAccessToken();
2168
+ if (!hasToken) {
2169
+ return;
2170
+ }
2167
2171
  const requestBody = await this.buildRequestBody(events);
2168
2172
  if (this.trySendBeacon(requestBody)) {
2169
2173
  return;
@@ -3351,6 +3355,17 @@ var HttpClient = class {
3351
3355
  getBaseUrl() {
3352
3356
  return this.config.baseUrl;
3353
3357
  }
3358
+ /**
3359
+ * Check if access token is available
3360
+ */
3361
+ async hasAccessToken() {
3362
+ try {
3363
+ const token = await this.config.auth.getAccessToken();
3364
+ return !!token;
3365
+ } catch {
3366
+ return false;
3367
+ }
3368
+ }
3354
3369
  /**
3355
3370
  * Make HTTP request with auth and retry
3356
3371
  */
@@ -4181,11 +4196,42 @@ var BrowserVideoLoader = class {
4181
4196
  * Full segment preload requires hls.js which is optional
4182
4197
  */
4183
4198
  async preloadHLS(url, signal) {
4199
+ const _isDev = globalThis.process?.env?.NODE_ENV !== "production";
4200
+ const _t0 = _isDev ? performance.now() : 0;
4201
+ if (_isDev) {
4202
+ performance.mark("sv-preload:hls:start");
4203
+ console.debug(
4204
+ "%c\u{1F504} [HLS Preload] manifest fetch start",
4205
+ "color:#7c3aed;font-size:11px;",
4206
+ url.slice(url.lastIndexOf("/") + 1).slice(0, 60)
4207
+ );
4208
+ }
4184
4209
  const response = await fetch(url, { signal });
4185
4210
  if (!response.ok) {
4186
4211
  throw new Error(`HTTP error: ${response.status}`);
4187
4212
  }
4188
4213
  const text = await response.text();
4214
+ if (_isDev) {
4215
+ performance.mark("sv-preload:hls:done");
4216
+ try {
4217
+ performance.measure(
4218
+ "sv-preload:hls:manifest",
4219
+ "sv-preload:hls:start",
4220
+ "sv-preload:hls:done"
4221
+ );
4222
+ } catch {
4223
+ }
4224
+ const segCount = text.split("\n").filter(
4225
+ (l) => l.endsWith(".ts") || l.endsWith(".m4s") || l.includes(".ts?") || l.includes(".m4s?")
4226
+ ).length;
4227
+ console.debug(
4228
+ "%c\u2705 [HLS Preload] manifest done",
4229
+ "color:#059669;font-size:11px;",
4230
+ `+${(performance.now() - _t0).toFixed(0)}ms`,
4231
+ `${text.length} bytes`,
4232
+ `segments: ${segCount}`
4233
+ );
4234
+ }
4189
4235
  if (this.cache) {
4190
4236
  try {
4191
4237
  const cacheResponse = new Response(text, {
@@ -4197,8 +4243,50 @@ var BrowserVideoLoader = class {
4197
4243
  } catch {
4198
4244
  }
4199
4245
  }
4246
+ await this.preloadHLSSegments(url, text, signal);
4200
4247
  return text.length;
4201
4248
  }
4249
+ /**
4250
+ * Parse M3U8 manifest and pre-fetch the first N segments into the Cache API.
4251
+ * Runs concurrently for speed; tolerates individual segment fetch failures.
4252
+ *
4253
+ * Resolves relative segment paths against the manifest URL base.
4254
+ * Only runs when a cache is available - gracefully no-ops otherwise.
4255
+ */
4256
+ async preloadHLSSegments(manifestUrl, manifestText, signal, maxSegments = 3) {
4257
+ if (!this.cache) return;
4258
+ const baseUrl = manifestUrl.substring(0, manifestUrl.lastIndexOf("/") + 1);
4259
+ const segmentUrls = manifestText.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#")).slice(0, maxSegments).map((l) => l.startsWith("http") ? l : `${baseUrl}${l}`);
4260
+ if (segmentUrls.length === 0) return;
4261
+ const _isDev = globalThis.process?.env?.NODE_ENV !== "production";
4262
+ if (_isDev) {
4263
+ console.debug(
4264
+ "%c\u{1F4E6} [HLS Preload] fetching first segments",
4265
+ "color:#7c3aed;font-size:11px;",
4266
+ segmentUrls.map((u) => u.slice(u.lastIndexOf("/") + 1).slice(0, 40))
4267
+ );
4268
+ }
4269
+ const cache = this.cache;
4270
+ await Promise.allSettled(
4271
+ segmentUrls.map(async (segUrl) => {
4272
+ const existing = await cache.match(segUrl);
4273
+ if (existing) return;
4274
+ const segResponse = await fetch(segUrl, { signal });
4275
+ if (segResponse.ok) {
4276
+ await cache.put(segUrl, segResponse.clone());
4277
+ if (_isDev) {
4278
+ const size = Number(segResponse.headers.get("content-length") ?? 0);
4279
+ console.debug(
4280
+ "%c \u2713 segment cached",
4281
+ "color:#059669;font-size:11px;",
4282
+ segUrl.slice(segUrl.lastIndexOf("/") + 1).slice(0, 50),
4283
+ size ? `${(size / 1024).toFixed(0)}KB` : ""
4284
+ );
4285
+ }
4286
+ }
4287
+ })
4288
+ );
4289
+ }
4202
4290
  /**
4203
4291
  * Cancel preload
4204
4292
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xhub-short/adapters",
3
3
  "sideEffects": false,
4
- "version": "1.0.0-beta.25",
4
+ "version": "1.0.0-beta.27",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -20,7 +20,7 @@
20
20
  "dist"
21
21
  ],
22
22
  "dependencies": {
23
- "@xhub-short/contracts": "1.0.0-beta.25"
23
+ "@xhub-short/contracts": "1.0.0-beta.27"
24
24
  },
25
25
  "optionalDependencies": {
26
26
  "hls.js": "^1.5.0"
@@ -29,8 +29,8 @@
29
29
  "tsup": "^8.3.0",
30
30
  "typescript": "^5.7.0",
31
31
  "vitest": "^2.1.0",
32
- "@xhub-short/tsconfig": "0.1.0-beta.3",
33
- "@xhub-short/vitest-config": "0.1.0-beta.14"
32
+ "@xhub-short/tsconfig": "0.0.1-beta.2",
33
+ "@xhub-short/vitest-config": "0.1.0-beta.13"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsup",