@trillboards/ads-sdk 2.1.0 → 2.2.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/CHANGELOG.md +18 -0
- package/README.md +9 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.mts +45 -5
- package/dist/index.d.ts +45 -5
- package/dist/index.js +128 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +128 -11
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +2 -0
- package/dist/react-native.d.ts +2 -0
- package/dist/react-native.js +1 -0
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +1 -0
- package/dist/react-native.mjs.map +1 -1
- package/dist/react.d.mts +6 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.js +130 -8
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +130 -8
- package/dist/react.mjs.map +1 -1
- package/dist/server.js +6 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +6 -2
- package/dist/server.mjs.map +1 -1
- package/dist/trillboards-lite.global.js +1 -1
- package/dist/trillboards-lite.global.js.map +1 -1
- package/package.json +19 -19
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/core/config.ts
|
|
2
|
-
var SDK_VERSION = "2.
|
|
2
|
+
var SDK_VERSION = "2.2.0";
|
|
3
3
|
var DEFAULT_CONFIG = {
|
|
4
4
|
API_BASE: "https://api.trillboards.com/v1/partner",
|
|
5
5
|
CDN_BASE: "https://cdn.trillboards.com",
|
|
@@ -58,6 +58,7 @@ var DEFAULT_PUBLIC_STATE = {
|
|
|
58
58
|
programmaticPlaying: false,
|
|
59
59
|
prefetchedReady: false,
|
|
60
60
|
waterfallMode: "programmatic_only",
|
|
61
|
+
adDeliveryProfileMode: null,
|
|
61
62
|
screenId: null,
|
|
62
63
|
deviceId: null
|
|
63
64
|
};
|
|
@@ -85,6 +86,7 @@ function createInitialState() {
|
|
|
85
86
|
programmaticRetryActive: false,
|
|
86
87
|
programmaticRetryCount: 0,
|
|
87
88
|
programmaticLastError: null,
|
|
89
|
+
adDeliveryProfile: null,
|
|
88
90
|
initialized: false,
|
|
89
91
|
screenOrientation: null,
|
|
90
92
|
screenDimensions: null,
|
|
@@ -102,6 +104,7 @@ function getPublicState(internal) {
|
|
|
102
104
|
programmaticPlaying: internal.programmaticPlaying,
|
|
103
105
|
prefetchedReady: internal.prefetchedReady ?? false,
|
|
104
106
|
waterfallMode: internal.waterfallMode,
|
|
107
|
+
adDeliveryProfileMode: internal.adDeliveryProfile?.mode ?? null,
|
|
105
108
|
screenId: internal.screenId,
|
|
106
109
|
deviceId: internal.deviceId
|
|
107
110
|
};
|
|
@@ -362,10 +365,9 @@ var ApiClient = class {
|
|
|
362
365
|
}
|
|
363
366
|
}
|
|
364
367
|
/**
|
|
365
|
-
* Ping
|
|
366
|
-
* Returns `true` on 2xx, `false` on any error.
|
|
368
|
+
* Ping heartbeat endpoint and return delivery profile + queued commands.
|
|
367
369
|
*/
|
|
368
|
-
async sendHeartbeat(deviceId, screenId) {
|
|
370
|
+
async sendHeartbeat(deviceId, screenId, payload = {}) {
|
|
369
371
|
logger.debug("Sending heartbeat", { deviceId });
|
|
370
372
|
try {
|
|
371
373
|
const response = await fetch(`${this.apiBase}/device/${deviceId}/heartbeat`, {
|
|
@@ -375,13 +377,24 @@ var ApiClient = class {
|
|
|
375
377
|
device_id: deviceId,
|
|
376
378
|
screen_id: screenId,
|
|
377
379
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
378
|
-
status: "active"
|
|
380
|
+
status: "active",
|
|
381
|
+
...payload
|
|
379
382
|
}),
|
|
380
383
|
signal: AbortSignal.timeout(5e3)
|
|
381
384
|
});
|
|
382
|
-
|
|
385
|
+
if (!response.ok) {
|
|
386
|
+
return { ok: false, data: null };
|
|
387
|
+
}
|
|
388
|
+
let data = null;
|
|
389
|
+
try {
|
|
390
|
+
const json = await response.json();
|
|
391
|
+
data = json?.data ?? null;
|
|
392
|
+
} catch {
|
|
393
|
+
data = null;
|
|
394
|
+
}
|
|
395
|
+
return { ok: true, data };
|
|
383
396
|
} catch {
|
|
384
|
-
return false;
|
|
397
|
+
return { ok: false, data: null };
|
|
385
398
|
}
|
|
386
399
|
}
|
|
387
400
|
/**
|
|
@@ -1398,6 +1411,9 @@ var _TrillboardsAds = class _TrillboardsAds {
|
|
|
1398
1411
|
this.offlineHandler = null;
|
|
1399
1412
|
this.visibilityHandler = null;
|
|
1400
1413
|
this.config = resolveConfig(config);
|
|
1414
|
+
if (this.config.debug) {
|
|
1415
|
+
setLogLevel("debug");
|
|
1416
|
+
}
|
|
1401
1417
|
this.state = createInitialState();
|
|
1402
1418
|
this.events = new EventEmitter();
|
|
1403
1419
|
this.api = new ApiClient(this.config.apiBase);
|
|
@@ -1671,11 +1687,104 @@ var _TrillboardsAds = class _TrillboardsAds {
|
|
|
1671
1687
|
}
|
|
1672
1688
|
startHeartbeatTimer() {
|
|
1673
1689
|
if (this.state.heartbeatTimer) clearInterval(this.state.heartbeatTimer);
|
|
1690
|
+
const tick = () => {
|
|
1691
|
+
this.sendHeartbeatTick().catch(() => {
|
|
1692
|
+
});
|
|
1693
|
+
};
|
|
1694
|
+
tick();
|
|
1674
1695
|
this.state.heartbeatTimer = setInterval(() => {
|
|
1675
|
-
|
|
1696
|
+
tick();
|
|
1676
1697
|
}, this.config.heartbeatInterval);
|
|
1677
1698
|
}
|
|
1699
|
+
async sendHeartbeatTick() {
|
|
1700
|
+
const result = await this.api.sendHeartbeat(
|
|
1701
|
+
this.config.deviceId,
|
|
1702
|
+
this.state.screenId,
|
|
1703
|
+
this.buildHeartbeatPayload()
|
|
1704
|
+
);
|
|
1705
|
+
if (!result.ok || !result.data) return;
|
|
1706
|
+
if (result.data.ad_delivery_profile?.mode) {
|
|
1707
|
+
this.applyAdDeliveryProfile(result.data.ad_delivery_profile);
|
|
1708
|
+
}
|
|
1709
|
+
if (Array.isArray(result.data.commands) && result.data.commands.length > 0) {
|
|
1710
|
+
this.runHeartbeatCommands(result.data.commands);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
buildHeartbeatPayload() {
|
|
1714
|
+
const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : "";
|
|
1715
|
+
const platform = typeof navigator !== "undefined" ? navigator.platform : null;
|
|
1716
|
+
const connection = typeof navigator !== "undefined" ? navigator.connection : null;
|
|
1717
|
+
const chromiumMatch = userAgent.match(/(?:Chrome|Chromium)\/(\d+)/i);
|
|
1718
|
+
const chromiumMajor = chromiumMatch ? Number(chromiumMatch[1]) : void 0;
|
|
1719
|
+
const imaSupported = typeof window !== "undefined" ? Boolean(window?.google?.ima) : null;
|
|
1720
|
+
const telemetry = {
|
|
1721
|
+
powerState: typeof document !== "undefined" && document.hidden ? "standby" : "on",
|
|
1722
|
+
agentStatus: typeof document !== "undefined" && document.hidden ? "background" : "foreground",
|
|
1723
|
+
os: platform || void 0,
|
|
1724
|
+
agentVersion: SDK_VERSION,
|
|
1725
|
+
ima_integration: "html5_webview",
|
|
1726
|
+
ima_supported: imaSupported,
|
|
1727
|
+
webview_chromium_major: Number.isFinite(chromiumMajor) ? chromiumMajor : void 0
|
|
1728
|
+
};
|
|
1729
|
+
const payload = {
|
|
1730
|
+
telemetry,
|
|
1731
|
+
sdk: {
|
|
1732
|
+
version: SDK_VERSION,
|
|
1733
|
+
ima_supported: imaSupported,
|
|
1734
|
+
ima_integration: "html5_webview",
|
|
1735
|
+
webview_chromium_major: Number.isFinite(chromiumMajor) ? chromiumMajor : void 0
|
|
1736
|
+
},
|
|
1737
|
+
device: {
|
|
1738
|
+
os: platform || void 0,
|
|
1739
|
+
model: userAgent || void 0
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
if (connection) {
|
|
1743
|
+
payload.network = {
|
|
1744
|
+
connectionType: connection.type || void 0,
|
|
1745
|
+
effectiveType: connection.effectiveType || void 0,
|
|
1746
|
+
downlinkMbps: typeof connection.downlink === "number" ? connection.downlink : void 0,
|
|
1747
|
+
bandwidthMbps: typeof connection.downlink === "number" ? connection.downlink : void 0,
|
|
1748
|
+
rtt: typeof connection.rtt === "number" ? connection.rtt : void 0,
|
|
1749
|
+
latencyRtt: typeof connection.rtt === "number" ? connection.rtt : void 0,
|
|
1750
|
+
saveData: typeof connection.saveData === "boolean" ? connection.saveData : void 0
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
return payload;
|
|
1754
|
+
}
|
|
1755
|
+
applyAdDeliveryProfile(profile) {
|
|
1756
|
+
if (!profile?.mode) return;
|
|
1757
|
+
const previousMode = this.state.adDeliveryProfile?.mode ?? null;
|
|
1758
|
+
this.state.adDeliveryProfile = profile;
|
|
1759
|
+
if (profile.mode === "vast_fallback" && this.state.programmaticPlaying) {
|
|
1760
|
+
this.programmaticPlayer.stop({ silent: true });
|
|
1761
|
+
this.state.programmaticPlaying = false;
|
|
1762
|
+
}
|
|
1763
|
+
if (previousMode !== profile.mode) {
|
|
1764
|
+
this.emitStateChanged();
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
runHeartbeatCommands(commands) {
|
|
1768
|
+
for (const command of commands) {
|
|
1769
|
+
const name = String(command?.command || "").toLowerCase();
|
|
1770
|
+
if (name === "refresh_ads") {
|
|
1771
|
+
this.refresh().catch(() => {
|
|
1772
|
+
});
|
|
1773
|
+
} else if (name === "restart") {
|
|
1774
|
+
if (typeof window !== "undefined" && typeof window.location?.reload === "function") {
|
|
1775
|
+
window.location.reload();
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
this.refresh().catch(() => {
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1678
1783
|
playNextAd() {
|
|
1784
|
+
if (this.state.adDeliveryProfile?.mode === "vast_fallback" && this.state.ads.length > 0) {
|
|
1785
|
+
this.playDirect();
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1679
1788
|
const mode = this.state.waterfallMode;
|
|
1680
1789
|
if (mode === "programmatic_only" || mode === "programmatic_then_direct") {
|
|
1681
1790
|
this.playProgrammatic();
|
|
@@ -1690,13 +1799,20 @@ var _TrillboardsAds = class _TrillboardsAds {
|
|
|
1690
1799
|
this.programmaticPlayer.play(
|
|
1691
1800
|
() => {
|
|
1692
1801
|
this.state.programmaticPlaying = false;
|
|
1802
|
+
this.resetProgrammaticBackoff();
|
|
1693
1803
|
this.emitStateChanged();
|
|
1694
1804
|
this.scheduleProgrammaticRetry();
|
|
1695
1805
|
},
|
|
1696
1806
|
(error) => {
|
|
1697
1807
|
this.state.programmaticPlaying = false;
|
|
1698
1808
|
this.state.programmaticLastError = error;
|
|
1699
|
-
|
|
1809
|
+
const normalizedError = String(error || "").toLowerCase();
|
|
1810
|
+
const isNoFillLike = normalizedError.includes("no fill") || normalizedError.includes("no ads vast response") || normalizedError.includes("waterfall_exhausted") || normalizedError === "throttled" || normalizedError === "busy";
|
|
1811
|
+
if (isNoFillLike) {
|
|
1812
|
+
this.state.programmaticRetryCount = 0;
|
|
1813
|
+
} else {
|
|
1814
|
+
this.state.programmaticRetryCount++;
|
|
1815
|
+
}
|
|
1700
1816
|
this.emitStateChanged();
|
|
1701
1817
|
if (this.state.waterfallMode === "programmatic_then_direct" && this.state.ads.length > 0) {
|
|
1702
1818
|
this.playDirect();
|
|
@@ -1806,6 +1922,7 @@ var TrillboardsAds = _TrillboardsAds;
|
|
|
1806
1922
|
var TrillboardsError = class extends Error {
|
|
1807
1923
|
constructor(message, options = {}) {
|
|
1808
1924
|
super(message);
|
|
1925
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
1809
1926
|
this.name = "TrillboardsError";
|
|
1810
1927
|
this.type = options.type ?? "api_error";
|
|
1811
1928
|
this.code = options.code ?? "unknown_error";
|
|
@@ -1817,12 +1934,12 @@ var TrillboardsError = class extends Error {
|
|
|
1817
1934
|
var TrillboardsAuthenticationError = class extends TrillboardsError {
|
|
1818
1935
|
constructor(message) {
|
|
1819
1936
|
super(
|
|
1820
|
-
message ?? "Invalid API key. Check your key at https://trillboards.com/developers",
|
|
1937
|
+
message ?? "Invalid API key. Check your key at https://trillboards.com/support/developers",
|
|
1821
1938
|
{
|
|
1822
1939
|
type: "authentication_error",
|
|
1823
1940
|
code: "invalid_api_key",
|
|
1824
1941
|
statusCode: 401,
|
|
1825
|
-
help: "https://trillboards.com/developers"
|
|
1942
|
+
help: "https://trillboards.com/support/developers"
|
|
1826
1943
|
}
|
|
1827
1944
|
);
|
|
1828
1945
|
this.name = "TrillboardsAuthenticationError";
|