@trillboards/ads-sdk 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -35,6 +35,11 @@ interface ProgrammaticSettings {
35
35
  variant_name: string | null;
36
36
  min_interval_seconds?: number;
37
37
  sources?: VastSource[];
38
+ vast_waterfall?: {
39
+ enabled: boolean;
40
+ sources: VastSource[];
41
+ total_timeout_ms: number;
42
+ };
38
43
  auction_winner?: AuctionWinner | null;
39
44
  }
40
45
  interface VastSource {
@@ -42,7 +47,7 @@ interface VastSource {
42
47
  vast_url: string;
43
48
  priority: number;
44
49
  timeout_ms: number;
45
- enabled: boolean;
50
+ enabled?: boolean;
46
51
  }
47
52
  interface AuctionWinner {
48
53
  source: string;
package/dist/index.d.ts CHANGED
@@ -35,6 +35,11 @@ interface ProgrammaticSettings {
35
35
  variant_name: string | null;
36
36
  min_interval_seconds?: number;
37
37
  sources?: VastSource[];
38
+ vast_waterfall?: {
39
+ enabled: boolean;
40
+ sources: VastSource[];
41
+ total_timeout_ms: number;
42
+ };
38
43
  auction_winner?: AuctionWinner | null;
39
44
  }
40
45
  interface VastSource {
@@ -42,7 +47,7 @@ interface VastSource {
42
47
  vast_url: string;
43
48
  priority: number;
44
49
  timeout_ms: number;
45
- enabled: boolean;
50
+ enabled?: boolean;
46
51
  }
47
52
  interface AuctionWinner {
48
53
  source: string;
package/dist/index.js CHANGED
@@ -320,10 +320,17 @@ var ApiClient = class {
320
320
  }
321
321
  const data = await response.json();
322
322
  const newEtag = response.headers.get("ETag");
323
+ const hbs = data.data?.header_bidding_settings;
323
324
  const result = {
324
325
  ads: data.data?.ads ?? [],
325
326
  settings: data.data?.settings ?? {},
326
- programmatic: data.data?.header_bidding_settings ?? null,
327
+ programmatic: hbs ? {
328
+ ...hbs,
329
+ sources: (hbs.vast_waterfall?.sources ?? []).map((s) => ({
330
+ ...s,
331
+ enabled: s.enabled !== false
332
+ }))
333
+ } : null,
327
334
  screenId: data.data?.screen_id ?? null,
328
335
  screenOrientation: data.data?.screen_orientation ?? null,
329
336
  screenDimensions: data.data?.screen_dimensions ?? null,
@@ -921,7 +928,7 @@ var WaterfallEngine = class {
921
928
  */
922
929
  getNextSource(sources) {
923
930
  if (!sources || sources.length === 0) return null;
924
- const sorted = [...sources].filter((s) => s.enabled).sort((a, b) => a.priority - b.priority || Math.random() - 0.5);
931
+ const sorted = [...sources].filter((s) => s.enabled !== false).sort((a, b) => a.priority - b.priority || Math.random() - 0.5);
925
932
  for (const source of sorted) {
926
933
  if (this.circuitBreaker.isAvailable(source.name)) {
927
934
  return { source, vastUrl: source.vast_url };
@@ -936,7 +943,7 @@ var WaterfallEngine = class {
936
943
  */
937
944
  getAvailableSources(sources) {
938
945
  if (!sources || sources.length === 0) return [];
939
- return sources.filter((s) => s.enabled && this.circuitBreaker.isAvailable(s.name)).sort((a, b) => a.priority - b.priority || Math.random() - 0.5).map((source) => ({ source, vastUrl: source.vast_url }));
946
+ return sources.filter((s) => s.enabled !== false && this.circuitBreaker.isAvailable(s.name)).sort((a, b) => a.priority - b.priority || Math.random() - 0.5).map((source) => ({ source, vastUrl: source.vast_url }));
940
947
  }
941
948
  /** Record a successful ad fill for a source. */
942
949
  recordSuccess(sourceName) {
@@ -949,7 +956,7 @@ var WaterfallEngine = class {
949
956
  };
950
957
 
951
958
  // src/player/ProgrammaticPlayer.ts
952
- var ProgrammaticPlayer = class {
959
+ var _ProgrammaticPlayer = class _ProgrammaticPlayer {
953
960
  constructor(events, timeoutMs = 12e3) {
954
961
  // ── Public state ──────────────────────────────────────────
955
962
  this.vastTagUrl = null;
@@ -1036,8 +1043,11 @@ var ProgrammaticPlayer = class {
1036
1043
  this.telemetry.recordRequest();
1037
1044
  const correlator = Date.now();
1038
1045
  const finalUrl = vastUrl.includes("correlator=") ? vastUrl.replace(/correlator=[^&]*/, `correlator=${correlator}`) : `${vastUrl}${vastUrl.includes("?") ? "&" : "?"}correlator=${correlator}`;
1039
- if (typeof google === "undefined" || !google?.ima) {
1040
- onError("Google IMA SDK not loaded");
1046
+ const imaReady = await this.ensureImaSdk();
1047
+ if (!imaReady) {
1048
+ const msg = "Google IMA SDK not loaded";
1049
+ this.events.emit("programmatic_error", { error: msg, code: void 0 });
1050
+ onError(msg);
1041
1051
  this.telemetry.recordError();
1042
1052
  this.waterfallEngine.recordFailure(sourceName);
1043
1053
  return;
@@ -1054,6 +1064,50 @@ var ProgrammaticPlayer = class {
1054
1064
  onError(err instanceof Error ? err.message : String(err));
1055
1065
  }
1056
1066
  }
1067
+ /**
1068
+ * Ensure Google IMA SDK is available. If already loaded, resolves
1069
+ * immediately. Otherwise injects the `<script>` tag and waits.
1070
+ * Matches the Lite SDK's `loadImaScript()` pattern.
1071
+ */
1072
+ async ensureImaSdk() {
1073
+ if (typeof google !== "undefined" && google?.ima) return true;
1074
+ if (typeof document === "undefined") return false;
1075
+ const existing = document.querySelector(
1076
+ `script[src="${_ProgrammaticPlayer.IMA_SDK_URL}"]`
1077
+ );
1078
+ if (existing) {
1079
+ return new Promise((resolve) => {
1080
+ const start = Date.now();
1081
+ const check = () => {
1082
+ if (typeof google !== "undefined" && google?.ima) {
1083
+ resolve(true);
1084
+ } else if (Date.now() - start > 5e3) {
1085
+ resolve(false);
1086
+ } else {
1087
+ setTimeout(check, 100);
1088
+ }
1089
+ };
1090
+ check();
1091
+ });
1092
+ }
1093
+ if (!_ProgrammaticPlayer.imaLoadPromise) {
1094
+ _ProgrammaticPlayer.imaLoadPromise = new Promise((resolve) => {
1095
+ const script = document.createElement("script");
1096
+ script.src = _ProgrammaticPlayer.IMA_SDK_URL;
1097
+ script.async = true;
1098
+ script.onload = () => {
1099
+ _ProgrammaticPlayer.imaLoadPromise = null;
1100
+ resolve(true);
1101
+ };
1102
+ script.onerror = () => {
1103
+ _ProgrammaticPlayer.imaLoadPromise = null;
1104
+ resolve(false);
1105
+ };
1106
+ document.head.appendChild(script);
1107
+ });
1108
+ }
1109
+ return _ProgrammaticPlayer.imaLoadPromise;
1110
+ }
1057
1111
  // ── IMA request / playback lifecycle ──────────────────────
1058
1112
  async requestAdsViaIMA(vastUrl, onComplete, onError) {
1059
1113
  return new Promise((resolve) => {
@@ -1255,6 +1309,12 @@ var ProgrammaticPlayer = class {
1255
1309
  this.telemetry.reset();
1256
1310
  }
1257
1311
  };
1312
+ // ── IMA SDK loader ──────────────────────────────────────────
1313
+ /** IMA script URL */
1314
+ _ProgrammaticPlayer.IMA_SDK_URL = "https://imasdk.googleapis.com/js/sdkloader/ima3.js";
1315
+ /** Singleton load promise so concurrent calls don't insert multiple scripts. */
1316
+ _ProgrammaticPlayer.imaLoadPromise = null;
1317
+ var ProgrammaticPlayer = _ProgrammaticPlayer;
1258
1318
 
1259
1319
  // src/player/Player.ts
1260
1320
  var MAX_AD_DURATION_SECONDS = 300;