@streamlayer/feature-advertisement 1.0.0 → 1.1.1-rc.10.p6eb7304a

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.
Files changed (105) hide show
  1. package/classic/package.json +5 -0
  2. package/lib/advertisement.d.ts +6 -6
  3. package/lib/advertisement.js +32 -17
  4. package/lib/cjs/advertisement.d.ts +64 -0
  5. package/lib/cjs/advertisement.js +322 -0
  6. package/lib/cjs/index.d.ts +21 -0
  7. package/lib/cjs/index.js +41 -0
  8. package/lib/cjs/package.json +1 -0
  9. package/lib/cjs/units/ad-macros.d.ts +7 -0
  10. package/lib/cjs/units/ad-macros.js +91 -0
  11. package/lib/cjs/units/external-ad.d.ts +127 -0
  12. package/lib/cjs/units/external-ad.js +421 -0
  13. package/lib/cjs/units/external-pause-ad.d.ts +50 -0
  14. package/lib/cjs/units/external-pause-ad.js +259 -0
  15. package/lib/cjs/units/gam.d.ts +26 -0
  16. package/lib/cjs/units/gam.js +152 -0
  17. package/lib/cjs/units/parse-vast-extensions.d.ts +26 -0
  18. package/lib/cjs/units/parse-vast-extensions.js +56 -0
  19. package/lib/cjs/units/pause-ad-card.d.ts +49 -0
  20. package/lib/cjs/units/pause-ad-card.js +136 -0
  21. package/lib/cjs/units/pause-ad.d.ts +16 -0
  22. package/lib/cjs/units/pause-ad.js +52 -0
  23. package/lib/cjs/units/sponsor-logo.d.ts +78 -0
  24. package/lib/cjs/units/sponsor-logo.js +194 -0
  25. package/lib/cjs/units/ssai-ad-break.d.ts +21 -0
  26. package/lib/cjs/units/ssai-ad-break.js +11 -0
  27. package/lib/cjs/units/ssai-creative.d.ts +89 -0
  28. package/lib/cjs/units/ssai-creative.js +136 -0
  29. package/lib/cjs/units/ssai-detector.d.ts +180 -0
  30. package/lib/cjs/units/ssai-detector.js +1172 -0
  31. package/lib/cjs/units/ssai-log.d.ts +16 -0
  32. package/lib/cjs/units/ssai-log.js +23 -0
  33. package/lib/cjs/units/ssai-preload.d.ts +20 -0
  34. package/lib/cjs/units/ssai-preload.js +62 -0
  35. package/lib/cjs/units/ssai-providers.d.ts +117 -0
  36. package/lib/cjs/units/ssai-providers.js +300 -0
  37. package/lib/cjs/units/vast-tracker.d.ts +45 -0
  38. package/lib/cjs/units/vast-tracker.js +64 -0
  39. package/lib/classic/_virtual/_rollupPluginBabelHelpers.js +71 -0
  40. package/lib/classic/advertisement.js +348 -0
  41. package/lib/classic/cjs/_virtual/_rollupPluginBabelHelpers.js +77 -0
  42. package/lib/classic/cjs/advertisement.js +350 -0
  43. package/lib/classic/cjs/index.js +49 -0
  44. package/lib/classic/cjs/package.json +1 -0
  45. package/lib/classic/cjs/units/ad-macros.js +115 -0
  46. package/lib/classic/cjs/units/external-ad.js +500 -0
  47. package/lib/classic/cjs/units/external-pause-ad.js +278 -0
  48. package/lib/classic/cjs/units/gam.js +173 -0
  49. package/lib/classic/cjs/units/parse-vast-extensions.js +60 -0
  50. package/lib/classic/cjs/units/pause-ad-card.js +134 -0
  51. package/lib/classic/cjs/units/pause-ad.js +72 -0
  52. package/lib/classic/cjs/units/sponsor-logo.js +201 -0
  53. package/lib/classic/cjs/units/ssai-ad-break.js +11 -0
  54. package/lib/classic/cjs/units/ssai-creative.js +142 -0
  55. package/lib/classic/cjs/units/ssai-detector.js +1195 -0
  56. package/lib/classic/cjs/units/ssai-log.js +23 -0
  57. package/lib/classic/cjs/units/ssai-preload.js +72 -0
  58. package/lib/classic/cjs/units/ssai-providers.js +361 -0
  59. package/lib/classic/cjs/units/vast-tracker.js +81 -0
  60. package/lib/classic/index.js +29 -0
  61. package/lib/classic/units/ad-macros.js +113 -0
  62. package/lib/classic/units/external-ad.js +491 -0
  63. package/lib/classic/units/external-pause-ad.js +275 -0
  64. package/lib/classic/units/gam.js +171 -0
  65. package/lib/classic/units/parse-vast-extensions.js +58 -0
  66. package/lib/classic/units/pause-ad-card.js +131 -0
  67. package/lib/classic/units/pause-ad.js +70 -0
  68. package/lib/classic/units/sponsor-logo.js +197 -0
  69. package/lib/classic/units/ssai-ad-break.js +9 -0
  70. package/lib/classic/units/ssai-creative.js +140 -0
  71. package/lib/classic/units/ssai-detector.js +1192 -0
  72. package/lib/classic/units/ssai-log.js +21 -0
  73. package/lib/classic/units/ssai-preload.js +68 -0
  74. package/lib/classic/units/ssai-providers.js +351 -0
  75. package/lib/classic/units/vast-tracker.js +77 -0
  76. package/lib/index.d.ts +15 -12
  77. package/lib/index.js +14 -7
  78. package/lib/units/ad-macros.d.ts +7 -0
  79. package/lib/units/ad-macros.js +87 -0
  80. package/lib/units/external-ad.d.ts +71 -2
  81. package/lib/units/external-ad.js +94 -66
  82. package/lib/units/external-pause-ad.js +7 -1
  83. package/lib/units/gam.d.ts +11 -1
  84. package/lib/units/gam.js +65 -17
  85. package/lib/units/parse-vast-extensions.d.ts +10 -1
  86. package/lib/units/parse-vast-extensions.js +5 -1
  87. package/lib/units/pause-ad-card.d.ts +49 -0
  88. package/lib/units/pause-ad-card.js +130 -0
  89. package/lib/units/pause-ad.d.ts +1 -18
  90. package/lib/units/pause-ad.js +2 -49
  91. package/lib/units/sponsor-logo.d.ts +78 -0
  92. package/lib/units/sponsor-logo.js +188 -0
  93. package/lib/units/ssai-ad-break.d.ts +1 -1
  94. package/lib/units/ssai-creative.d.ts +1 -1
  95. package/lib/units/ssai-creative.js +1 -1
  96. package/lib/units/ssai-detector.d.ts +1 -1
  97. package/lib/units/ssai-detector.js +27 -11
  98. package/lib/units/ssai-log.d.ts +16 -0
  99. package/lib/units/ssai-log.js +18 -0
  100. package/lib/units/ssai-preload.d.ts +1 -1
  101. package/lib/units/ssai-providers.d.ts +1 -1
  102. package/lib/units/ssai-providers.js +48 -11
  103. package/lib/units/vast-tracker.d.ts +1 -1
  104. package/lib/vast-client.d.ts +9 -0
  105. package/package.json +43 -10
@@ -0,0 +1,350 @@
1
+ 'use strict';
2
+
3
+ var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
4
+ require('core-js/modules/es.array.iterator.js');
5
+ require('core-js/modules/esnext.iterator.constructor.js');
6
+ require('core-js/modules/esnext.iterator.find.js');
7
+ require('core-js/modules/esnext.iterator.for-each.js');
8
+ require('core-js/modules/esnext.set.difference.v2.js');
9
+ require('core-js/modules/esnext.set.intersection.v2.js');
10
+ require('core-js/modules/esnext.set.is-disjoint-from.v2.js');
11
+ require('core-js/modules/esnext.set.is-subset-of.v2.js');
12
+ require('core-js/modules/esnext.set.is-superset-of.v2.js');
13
+ require('core-js/modules/esnext.set.symmetric-difference.v2.js');
14
+ require('core-js/modules/esnext.set.union.v2.js');
15
+ require('core-js/modules/web.dom-collections.for-each.js');
16
+ require('core-js/modules/web.dom-collections.iterator.js');
17
+ var classic = require('@streamlayer/sdk-web-interfaces/classic');
18
+ var classic$1 = require('@streamlayer/sdk-web-logger/classic');
19
+ var externalAd = require('./units/external-ad.js');
20
+ var externalPauseAd = require('./units/external-pause-ad.js');
21
+ var pauseAd = require('./units/pause-ad.js');
22
+ var ssaiCreative = require('./units/ssai-creative.js');
23
+ var ssaiProviders = require('./units/ssai-providers.js');
24
+ var ssaiDetector = require('./units/ssai-detector.js');
25
+ var ssaiAdBreak = require('./units/ssai-ad-break.js');
26
+ var ssaiLog = require('./units/ssai-log.js');
27
+ var ssaiPreload = require('./units/ssai-preload.js');
28
+
29
+ class Advertisement extends classic.AbstractFeatureUnit {
30
+ constructor(instance) {
31
+ super();
32
+ _rollupPluginBabelHelpers.defineProperty(this, "getExternalAd", void 0);
33
+ _rollupPluginBabelHelpers.defineProperty(this, "getExternalPauseAd", void 0);
34
+ _rollupPluginBabelHelpers.defineProperty(this, "getPauseAdList", void 0);
35
+ _rollupPluginBabelHelpers.defineProperty(this, "ssaiAdBreak", ssaiAdBreak.createSsaiAdBreakStore());
36
+ _rollupPluginBabelHelpers.defineProperty(this, "startSsaiMonitoring", void 0);
37
+ _rollupPluginBabelHelpers.defineProperty(this, "stopSsaiMonitoring", void 0);
38
+ /**
39
+ * Fire the impression tracking pixel for a creative. Called by the UI the
40
+ * moment the bar actually renders the creative, so "impression" means the
41
+ * viewer saw it (not merely that metadata resolved).
42
+ */
43
+ _rollupPluginBabelHelpers.defineProperty(this, "fireSsaiImpression", void 0);
44
+ /**
45
+ * Fire a named tracking beacon for a creative (`clickThrough`, or any event
46
+ * the creative carries). Lifecycle beacons — `start`, the quartiles and
47
+ * `complete` — are fired automatically by the detector as playback crosses
48
+ * them; this is for the ones only the UI knows about.
49
+ */
50
+ _rollupPluginBabelHelpers.defineProperty(this, "fireSsaiTracking", void 0);
51
+ /**
52
+ * Fire the companion's `clickTracking` beacons. Exposed for hosts that render
53
+ * the companion banner themselves — the TV overlay has no companion surface,
54
+ * so nothing in this SDK calls it.
55
+ */
56
+ _rollupPluginBabelHelpers.defineProperty(this, "fireSsaiCompanionClick", void 0);
57
+ /**
58
+ * User-dismissed the current break: hide the bar now and keep it hidden for
59
+ * the rest of this break (a later break/creative shows again).
60
+ */
61
+ _rollupPluginBabelHelpers.defineProperty(this, "dismissSsaiBreak", void 0);
62
+ /**
63
+ * Read-only timing introspection of the running SSAI monitor (null while no
64
+ * monitor runs). Feeds the demo app's SSAI debug window; safe to poll.
65
+ */
66
+ _rollupPluginBabelHelpers.defineProperty(this, "getSsaiDebugSnapshot", void 0);
67
+ _rollupPluginBabelHelpers.defineProperty(this, "externalAdStores", new Map());
68
+ _rollupPluginBabelHelpers.defineProperty(this, "externalPauseAdStores", new Map());
69
+ _rollupPluginBabelHelpers.defineProperty(this, "externalPauseAdEnabled", new Map());
70
+ _rollupPluginBabelHelpers.defineProperty(this, "pauseAdStore", null);
71
+ _rollupPluginBabelHelpers.defineProperty(this, "pauseAdEnabled", null);
72
+ _rollupPluginBabelHelpers.defineProperty(this, "ssaiDetector", null);
73
+ _rollupPluginBabelHelpers.defineProperty(this, "ssaiCache", null);
74
+ _rollupPluginBabelHelpers.defineProperty(this, "log", void 0);
75
+ _rollupPluginBabelHelpers.defineProperty(this, "connect", () => {
76
+ this.log.debug('connect');
77
+ });
78
+ _rollupPluginBabelHelpers.defineProperty(this, "disconnect", () => {
79
+ this.log.debug('disconnect');
80
+ this.stopSsaiMonitoring();
81
+ this.externalAdStores.forEach(store => {
82
+ store.off();
83
+ });
84
+ this.externalAdStores.clear();
85
+ this.externalPauseAdStores.forEach(store => {
86
+ store.off();
87
+ });
88
+ this.externalPauseAdEnabled.forEach(enabled => {
89
+ enabled.off();
90
+ });
91
+ this.externalPauseAdEnabled.clear();
92
+ this.externalPauseAdStores.clear();
93
+ if (this.pauseAdStore) {
94
+ var _this$pauseAdEnabled;
95
+ this.pauseAdStore.$list.off();
96
+ this.pauseAdStore.$index.off();
97
+ (_this$pauseAdEnabled = this.pauseAdEnabled) === null || _this$pauseAdEnabled === void 0 || _this$pauseAdEnabled.off();
98
+ this.pauseAdStore = null;
99
+ this.pauseAdEnabled = null;
100
+ }
101
+ });
102
+ this.log = classic$1.createLogger('advertisement');
103
+ const externalAdGenerator = externalAd.externalAd(instance);
104
+ const externalPauseAdGenerator = externalPauseAd.externalPauseAd(instance);
105
+ const pauseAdGenerator = pauseAd.pauseAdListStore(instance);
106
+ this.fireSsaiImpression = () => undefined;
107
+ this.fireSsaiTracking = () => undefined;
108
+ this.fireSsaiCompanionClick = () => undefined;
109
+ this.dismissSsaiBreak = () => undefined;
110
+ // Stable across start/stop cycles — always answers from the CURRENT detector.
111
+ this.getSsaiDebugSnapshot = () => {
112
+ var _this$ssaiDetector$ge, _this$ssaiDetector;
113
+ return (_this$ssaiDetector$ge = (_this$ssaiDetector = this.ssaiDetector) === null || _this$ssaiDetector === void 0 ? void 0 : _this$ssaiDetector.getDebugSnapshot()) !== null && _this$ssaiDetector$ge !== void 0 ? _this$ssaiDetector$ge : null;
114
+ };
115
+ this.getPauseAdList = options => {
116
+ if (this.pauseAdStore) {
117
+ const $enabled = this.pauseAdEnabled;
118
+ const wasDisabled = $enabled.get() === false;
119
+ $enabled.set(options.$enabled);
120
+ if (wasDisabled && options.$enabled) {
121
+ window.requestAnimationFrame(() => {
122
+ if (this.pauseAdStore) this.pauseAdStore.$list.revalidate();
123
+ });
124
+ }
125
+ return this.pauseAdStore;
126
+ }
127
+ const $enabled = classic.createSingleStore(options.$enabled);
128
+ this.pauseAdEnabled = $enabled;
129
+ this.pauseAdStore = pauseAdGenerator($enabled, options);
130
+ return this.pauseAdStore;
131
+ };
132
+ this.getExternalAd = (adUrl = '') => {
133
+ if (this.externalAdStores.has(adUrl)) {
134
+ const $store = this.externalAdStores.get(adUrl);
135
+ return [$store, adUrl];
136
+ }
137
+ const store = externalAdGenerator(adUrl);
138
+ this.externalAdStores.set(adUrl, store);
139
+ return [store, adUrl];
140
+ };
141
+ this.getExternalPauseAd = (adUrl, options) => {
142
+ var _options$template;
143
+ // Store identity is (template, url): the template selects a DIFFERENT creative
144
+ // from the SAME tag, so the two must not share a store. Required because the
145
+ // cache-hit branch below applies only `$enabled` and drops the rest of `options`.
146
+ const storeKey = `${(_options$template = options.template) !== null && _options$template !== void 0 ? _options$template : 'default'}::${adUrl}`;
147
+ if (this.externalPauseAdStores.has(storeKey)) {
148
+ const $enabled = this.externalPauseAdEnabled.get(storeKey);
149
+ const $store = this.externalPauseAdStores.get(storeKey);
150
+ const shouldRevalidate = $enabled.get() === false && options.$enabled === true;
151
+ $enabled.set(options.$enabled);
152
+ if (shouldRevalidate) {
153
+ window.requestAnimationFrame(() => {
154
+ $store.revalidate();
155
+ });
156
+ }
157
+ // The 2nd element MUST stay the BARE url — `ExposedPauseAd` compares it to
158
+ // `vastUrlRef.current` (index.tsx:121) to scope store errors to the selected tag.
159
+ return [$store, adUrl];
160
+ }
161
+ const $enabled = classic.createSingleStore(options.$enabled);
162
+ const store = externalPauseAdGenerator(adUrl, $enabled, options);
163
+ this.externalPauseAdEnabled.set(storeKey, $enabled);
164
+ this.externalPauseAdStores.set(storeKey, store);
165
+ return [store, adUrl];
166
+ };
167
+ this.startSsaiMonitoring = options => {
168
+ this.stopSsaiMonitoring();
169
+ const provider = ssaiProviders.resolveProvider(options.provider);
170
+ const cache = new ssaiCreative.SsaiCreativeCache(provider);
171
+ this.ssaiCache = cache;
172
+ /**
173
+ * Every beacon the SDK fires gets a line, with the URL it was fired at.
174
+ * The narrative log is read as a live trace of one ad, and "we called the
175
+ * ad server's own tracking URL" is as much of the story as the request
176
+ * that fetched the creative in the first place.
177
+ */
178
+ const logBeacon = (creativeId, event) => {
179
+ var _cache$peek;
180
+ const url = (_cache$peek = cache.peek(creativeId)) === null || _cache$peek === void 0 || (_cache$peek = _cache$peek.trackingEvents) === null || _cache$peek === void 0 || (_cache$peek = _cache$peek.find(entry => entry.event === event)) === null || _cache$peek === void 0 ? void 0 : _cache$peek.url;
181
+ ssaiLog.ssaiq.info({
182
+ creativeId,
183
+ event,
184
+ url
185
+ }, `[beacon] ${event} fired — ${creativeId}`);
186
+ };
187
+ this.fireSsaiImpression = creativeId => {
188
+ var _cache$peek2;
189
+ // The UI only calls this once the bar is actually rendered, so this is
190
+ // the moment the viewer saw the ad — not the moment it resolved.
191
+ ssaiLog.ssaiq.info({
192
+ creativeId
193
+ }, `[ad] ad on screen — ${((_cache$peek2 = cache.peek(creativeId)) === null || _cache$peek2 === void 0 ? void 0 : _cache$peek2.advertiser) || creativeId}`);
194
+ logBeacon(creativeId, 'impression');
195
+ cache.fireImpressionById(creativeId);
196
+ };
197
+ this.fireSsaiTracking = (creativeId, event) => {
198
+ logBeacon(creativeId, event);
199
+ cache.fireTrackingById(creativeId, event);
200
+ };
201
+ this.fireSsaiCompanionClick = creativeId => {
202
+ cache.fireCompanionClickById(creativeId);
203
+ };
204
+ // Creative ids whose artwork preload has completed. Tracked apart from the
205
+ // cache: `peek` alone would let the bar show with a logo still in flight.
206
+ const preloadedIds = new Set();
207
+ /**
208
+ * Resolve + warm a creative the moment its id shows up in the manifest —
209
+ * typically seconds before its break starts, since the playhead trails the
210
+ * live edge. By break start the sync fast-path in `loadCreative` then flips
211
+ * the store straight to 'ready'. Failure here is only a debug note: the
212
+ * break may still be minutes away, and `loadCreative` retries (and warns)
213
+ * when the ad actually starts.
214
+ */
215
+ const prefetchCreative = creativeId => {
216
+ cache.resolve(creativeId).then(creative => ssaiPreload.preloadCreativeAssets(creative).then(() => creative)).then(creative => {
217
+ preloadedIds.add(creativeId);
218
+ ssaiLog.ssaiq.info({
219
+ creativeId
220
+ }, `[ad] creative ready — ${creative.advertiser} (artwork preloaded)`);
221
+ }).catch(() => {
222
+ // Already on `ssaiq` from the provider; the break may still be
223
+ // minutes away, and `loadCreative` retries when it actually starts.
224
+ });
225
+ };
226
+ const publishReady = (range, creative) => {
227
+ this.ssaiAdBreak.set({
228
+ creativeId: range.creativeId,
229
+ creative,
230
+ status: 'ready',
231
+ startMs: range.startMs,
232
+ durationSec: range.durationSec
233
+ });
234
+ // "loaded" = metadata resolved. Impression (eventBus + pixel) fires
235
+ // from the UI when the bar is actually rendered, not here.
236
+ classic.eventBus.emit('ssaiAdBreak', {
237
+ action: 'vastLoaded',
238
+ payload: {
239
+ creativeId: creative.creativeId,
240
+ advertiser: creative.advertiser,
241
+ clickThroughUrl: creative.clickThroughUrl
242
+ }
243
+ });
244
+ };
245
+ const loadCreative = range => {
246
+ // Fast path: prefetched at discovery, artwork warm — go straight to
247
+ // 'ready'. Skipping the 'detecting' hop matters for pods in particular:
248
+ // it momentarily empties the store, which the UI renders as the bar
249
+ // starting to close between two back-to-back ads.
250
+ const prefetched = cache.peek(range.creativeId);
251
+ if (prefetched && preloadedIds.has(range.creativeId)) {
252
+ publishReady(range, prefetched);
253
+ return;
254
+ }
255
+ this.ssaiAdBreak.set({
256
+ creativeId: range.creativeId,
257
+ status: 'detecting',
258
+ startMs: range.startMs,
259
+ durationSec: range.durationSec
260
+ });
261
+ cache.resolve(range.creativeId)
262
+ // Warm the artwork BEFORE flipping to 'ready', so the bar fades in with
263
+ // its logo already decoded instead of popping it in mid-animation. Capped
264
+ // internally, so a slow image host delays nothing.
265
+ .then(creative => ssaiPreload.preloadCreativeAssets(creative).then(() => {
266
+ preloadedIds.add(range.creativeId);
267
+ return creative;
268
+ })).then(creative => {
269
+ const current = this.ssaiAdBreak.get();
270
+ // Re-checked after the preload as well as the fetch: the break can end
271
+ // while either is in flight.
272
+ if (!current || current.creativeId !== range.creativeId) {
273
+ return;
274
+ }
275
+ publishReady(range, creative);
276
+ }).catch(error => {
277
+ this.log.warn(error, 'ssai creative resolution failed');
278
+ });
279
+ };
280
+ this.ssaiDetector = ssaiDetector.createSsaiDetector({
281
+ player: options.player,
282
+ videoRef: options.videoRef,
283
+ manifestUrl: options.manifestUrl,
284
+ onAdDiscovered: creativeId => {
285
+ prefetchCreative(creativeId);
286
+ },
287
+ onBreakStart: range => {
288
+ classic.eventBus.emit('ssaiAdBreak', {
289
+ action: 'breakStart',
290
+ payload: {
291
+ creativeId: range.creativeId
292
+ }
293
+ });
294
+ loadCreative(range);
295
+ },
296
+ onCreativeChange: range => {
297
+ loadCreative(range);
298
+ },
299
+ onAdEnding: range => {
300
+ const current = this.ssaiAdBreak.get();
301
+ // Only a bar currently showing this creative has anything to wind
302
+ // down — a dismissed or still-resolving break stays as it is.
303
+ if (!current || current.creativeId !== range.creativeId || current.status !== 'ready') {
304
+ return;
305
+ }
306
+ this.ssaiAdBreak.set(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, current), {}, {
307
+ status: 'ending'
308
+ }));
309
+ },
310
+ onProgress: (range, event) => {
311
+ // Logged by the detector as `progress:<event>` at the moment playback
312
+ // crosses the marker; nothing to add here.
313
+ cache.fireTrackingById(range.creativeId, event);
314
+ },
315
+ onBreakEnd: () => {
316
+ const current = this.ssaiAdBreak.get();
317
+ classic.eventBus.emit('ssaiAdBreak', {
318
+ action: 'breakEnd',
319
+ payload: {
320
+ creativeId: current === null || current === void 0 ? void 0 : current.creativeId
321
+ }
322
+ });
323
+ this.ssaiAdBreak.set(null);
324
+ }
325
+ });
326
+ this.dismissSsaiBreak = () => {
327
+ var _this$ssaiDetector2;
328
+ (_this$ssaiDetector2 = this.ssaiDetector) === null || _this$ssaiDetector2 === void 0 || _this$ssaiDetector2.dismissActiveBreak();
329
+ this.ssaiAdBreak.set(null);
330
+ };
331
+ };
332
+ this.stopSsaiMonitoring = () => {
333
+ if (this.ssaiDetector) {
334
+ this.ssaiDetector.destroy();
335
+ this.ssaiDetector = null;
336
+ }
337
+ if (this.ssaiCache) {
338
+ this.ssaiCache.destroy();
339
+ this.ssaiCache = null;
340
+ }
341
+ this.fireSsaiImpression = () => undefined;
342
+ this.fireSsaiTracking = () => undefined;
343
+ this.fireSsaiCompanionClick = () => undefined;
344
+ this.dismissSsaiBreak = () => undefined;
345
+ this.ssaiAdBreak.set(null);
346
+ };
347
+ }
348
+ }
349
+
350
+ exports.Advertisement = Advertisement;
@@ -0,0 +1,49 @@
1
+ 'use strict';
2
+
3
+ var advertisement$1 = require('./advertisement.js');
4
+ var externalPauseAd = require('./units/external-pause-ad.js');
5
+ var pauseAdCard = require('./units/pause-ad-card.js');
6
+ var sponsorLogo = require('./units/sponsor-logo.js');
7
+ var gam = require('./units/gam.js');
8
+ var vastTracker = require('./units/vast-tracker.js');
9
+ require('core-js/modules/es.array.iterator.js');
10
+ require('core-js/modules/es.promise.js');
11
+ require('core-js/modules/esnext.iterator.constructor.js');
12
+ require('core-js/modules/esnext.iterator.for-each.js');
13
+ require('core-js/modules/web.dom-collections.for-each.js');
14
+ require('core-js/modules/web.dom-collections.iterator.js');
15
+ var ssaiProviders = require('./units/ssai-providers.js');
16
+ var ssaiPreload = require('./units/ssai-preload.js');
17
+
18
+ const advertisement = (instance, _opts, done) => {
19
+ instance.sdk.advertisement = new advertisement$1.Advertisement(instance);
20
+ instance.sdk.onMount({
21
+ name: 'advertisement'
22
+ }, () => {
23
+ instance.sdk.advertisement.connect();
24
+ return () => {
25
+ instance.sdk.advertisement.disconnect();
26
+ };
27
+ });
28
+ done();
29
+ };
30
+
31
+ exports.isFullbleedVideoTemplate = externalPauseAd.isFullbleedVideoTemplate;
32
+ exports.INSIGHT_BODY_MAX_LENGTH = pauseAdCard.INSIGHT_BODY_MAX_LENGTH;
33
+ exports.selectSponsorLogo = sponsorLogo.selectSponsorLogo;
34
+ exports.gam = gam.gam;
35
+ exports.createCompanionTracker = vastTracker.createCompanionTracker;
36
+ exports.createVastTracker = vastTracker.createVastTracker;
37
+ exports.resolveVastTrackerTarget = vastTracker.resolveVastTrackerTarget;
38
+ exports.BUILTIN_PROVIDERS = ssaiProviders.BUILTIN_PROVIDERS;
39
+ exports.DEFAULT_CREATIVE_API_BASE = ssaiProviders.DEFAULT_CREATIVE_API_BASE;
40
+ exports.createQuortexProvider = ssaiProviders.createQuortexProvider;
41
+ exports.createStreamLayerProvider = ssaiProviders.createStreamLayerProvider;
42
+ exports.createVastProvider = ssaiProviders.createVastProvider;
43
+ exports.fireBeacon = ssaiProviders.fireBeacon;
44
+ exports.fireTrackingEvents = ssaiProviders.fireTrackingEvents;
45
+ exports.resolveProvider = ssaiProviders.resolveProvider;
46
+ exports.DEFAULT_PRELOAD_TIMEOUT_MS = ssaiPreload.DEFAULT_PRELOAD_TIMEOUT_MS;
47
+ exports.preloadCreativeAssets = ssaiPreload.preloadCreativeAssets;
48
+ exports.preloadImages = ssaiPreload.preloadImages;
49
+ exports.advertisement = advertisement;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ require('core-js/modules/es.regexp.exec.js');
4
+ require('core-js/modules/es.string.replace.js');
5
+
6
+ /**
7
+ * Ad-tag macro substitution, for every ad server — not just GAM.
8
+ *
9
+ * Studio stores a programmatic tag verbatim (`gamRawUrl`, returned untouched by
10
+ * `processGamAdvertisement`), so whatever macros the ad server's own tag builder emitted reach the
11
+ * SDK literal. `gam()` used to fill only the GAM `[placeholder]` token, and only for
12
+ * `pubads.g.doubleclick.net` — every other vendor's tag went out with its macros unexpanded.
13
+ *
14
+ * That is not inert. Measured against the ADITION tag on event 11089
15
+ * (`…/banner?…&ts=[timestamp]&clickurl=[clickmacro]`): ADITION prepends the value of `clickurl` to
16
+ * its own redi URL, so a literal `[clickmacro]` came back inside `<CompanionClickThrough>` as
17
+ * `[clickmacro]https%3A%2F%2Fad1…` — a broken click-through. Sending `clickurl=` empty answers with
18
+ * a valid redi URL.
19
+ *
20
+ * **Two sources.** The cache buster is the SDK's own. The consent family — `${GDPR}` and
21
+ * `${GDPR_CONSENT_<gvlid>}`, IAB TCF, where the id is the vendor's Global Vendor List entry (39 is
22
+ * ADITION / Virtual Minds) — and the click macro come from the host app (`AdTagParams`, set through
23
+ * the `adTagParams` option or `sdk.setAdTagParams`). The SDK never reads a CMP and never guesses
24
+ * consent: a value the host did not pass goes out EMPTY, which ad servers read as "unknown" — never
25
+ * as `gdpr=0`. Empty rather than literal because a literal is not inert either: ADITION copied
26
+ * `${GDPR}` into its own redirect URL (`gdpr%3D%24%7BGDPR%7D`). See
27
+ * `docs/wiki/programmatic-ads-macros.md`.
28
+ *
29
+ * An unknown macro is left exactly as configured, which is what keeps the GAM `[placeholder]`
30
+ * tokens for the PAL path (`gam.ts` fills those per parameter, not per token).
31
+ */
32
+ /**
33
+ * All three spellings in the wild — `[NAME]` (IAB / SpotX), `${NAME}` (Google) and bare `{NAME}` —
34
+ * each with its delimiters either literal or PERCENT-ENCODED.
35
+ *
36
+ * Neither half of that is theoretical. ADITION emitted `[timestamp]` / `[clickmacro]` for the
37
+ * campaign on event 11089 and `{CACHEBUSTER}` / `{GDPR}` for the one on 6203 — same ad server, same
38
+ * advertiser, different tag builder. And Studio stores the 6203 tag as `ts=%7BCACHEBUSTER%7D`, so
39
+ * matching only literal braces made the whole substitution a silent no-op on it: an unexpanded
40
+ * macro raises no error and the ad server still answers 200. `searchParams.get()` decodes on read,
41
+ * which is what hides the encoding from anyone inspecting the parsed URL.
42
+ *
43
+ * The `$` is optional rather than a fourth branch — an unowned `${NAME}` still returns its full
44
+ * matched text, `$` included, so the brace forms cannot corrupt each other.
45
+ */
46
+ const MACRO_PATTERN = /(?:\[|%5B)([a-z0-9_]+)(?:\]|%5D)|(?:\$|%24)?(?:\{|%7B)([a-z0-9_]+)(?:\}|%7D)/gi;
47
+ /**
48
+ * Every host value lands inside a query-string VALUE, so it is encoded exactly once. That matters
49
+ * most for the click URL, which carries its own `?`/`&`: sent raw it re-opens the tag's query, the
50
+ * way the malformed 6203 tag did (`clickurl` truncated, every following parameter duplicated).
51
+ */
52
+ const hostValue = value => value ? encodeURIComponent(value) : '';
53
+ const gdprConsent = ({
54
+ params
55
+ }) => hostValue(params === null || params === void 0 ? void 0 : params.tcString);
56
+ /**
57
+ * Macro name (lower-cased) → the value this SDK sends for it.
58
+ *
59
+ * `clickurl` / `clickmacro` take the host's click tracker, which the ad server PREPENDS to its own
60
+ * redirect — so the viewer's click passes host tracker → vendor redirect → landing page. The SDK
61
+ * does not fire that tracker itself; it would count the click twice. Without one it is empty, the
62
+ * documented "no player tracker" value. VAST click beacons are reported separately by
63
+ * `useSidebarVastTracker`.
64
+ */
65
+ const MACRO_VALUES = {
66
+ // One family, one value: every name here means "make this request unique so nothing caches it".
67
+ // Epoch milliseconds satisfies that for all of them, and keeps the value already shipped for
68
+ // `timestamp` unchanged. (IAB defines `[CACHEBUSTING]` as a random 8-digit number and
69
+ // `[TIMESTAMP]` as ISO-8601, but those describe VAST *tracking* URLs; this substitution only
70
+ // ever touches the ad REQUEST url, where every ad server documents the parameter as a number.)
71
+ timestamp: ({
72
+ now
73
+ }) => String(now),
74
+ cachebuster: ({
75
+ now
76
+ }) => String(now),
77
+ cachebusting: ({
78
+ now
79
+ }) => String(now),
80
+ clickmacro: ({
81
+ params
82
+ }) => hostValue(params === null || params === void 0 ? void 0 : params.clickUrl),
83
+ clickurl: ({
84
+ params
85
+ }) => hostValue(params === null || params === void 0 ? void 0 : params.clickUrl),
86
+ // `1` / `0` only from an explicit boolean — an absent value is unknown, not "does not apply".
87
+ gdpr: ({
88
+ params
89
+ }) => (params === null || params === void 0 ? void 0 : params.gdprApplies) === undefined ? '' : params.gdprApplies ? '1' : '0',
90
+ gdpr_consent: gdprConsent
91
+ };
92
+ /** `GDPR_CONSENT_<gvlid>`: the vendor id names whose tag this is; the value is the same TC string. */
93
+ const GDPR_CONSENT_FOR_VENDOR = /^gdpr_consent_\d+$/;
94
+ const resolveMacro = name => {
95
+ var _MACRO_VALUES$name;
96
+ return (_MACRO_VALUES$name = MACRO_VALUES[name]) !== null && _MACRO_VALUES$name !== void 0 ? _MACRO_VALUES$name : GDPR_CONSENT_FOR_VENDOR.test(name) ? gdprConsent : undefined;
97
+ };
98
+ /**
99
+ * Fill the macros this SDK knows in an ad-tag URL. One timestamp per call, so a tag naming the macro
100
+ * twice stays self-consistent. `params` is read as given — the caller passes the host's CURRENT
101
+ * values at request time.
102
+ */
103
+ const substituteAdTagMacros = (url, params) => {
104
+ const now = Date.now();
105
+ return url.replace(MACRO_PATTERN, (match, bracketed, braced) => {
106
+ var _ref;
107
+ const value = resolveMacro(((_ref = bracketed !== null && bracketed !== void 0 ? bracketed : braced) !== null && _ref !== void 0 ? _ref : '').toLowerCase());
108
+ return value ? value({
109
+ now,
110
+ params
111
+ }) : match;
112
+ });
113
+ };
114
+
115
+ exports.substituteAdTagMacros = substituteAdTagMacros;