@adhese/sdk 0.3.0 → 0.5.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/dist/es/index.js CHANGED
@@ -1,12 +1,7 @@
1
- var __defProp = Object.defineProperty;
2
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField = (obj, key, value) => {
4
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
- return value;
6
- };
7
1
  import { createDevtools } from "@adhese/sdk-devtools";
8
- import { debounce, uniqueId, random, round } from "lodash-es";
9
- import { union, coerce, literal, object, string, unknown, lazy } from "zod";
2
+ import { effectScope, shallowReactive, watchEffect, watch, reactive, ref, computed, toValue } from "@vue/runtime-core";
3
+ import { debounce, uniqueId, random, round, isEqual } from "lodash-es";
4
+ import { union, coerce, literal, number, string, ZodIssueCode, NEVER, object, unknown, lazy } from "zod";
10
5
  async function waitForDomLoad() {
11
6
  return new Promise((resolve) => {
12
7
  function onDomLoad() {
@@ -66,91 +61,132 @@ function createEvent() {
66
61
  removeListener
67
62
  };
68
63
  }
64
+ function renderIframe(ad, element) {
65
+ const iframe = document.createElement("iframe");
66
+ iframe.srcdoc = `
67
+ <!DOCTYPE html>
68
+ <html>
69
+ <head>
70
+ <style>
71
+ body {
72
+ margin: 0;
73
+ padding: 0;
74
+ overflow: hidden;
75
+ }
76
+ </style>
77
+ </head>
78
+ <body>
79
+ ${String(ad.tag)}
80
+ </body>
81
+ `.replaceAll(/\s+/g, " ").trim();
82
+ iframe.style.border = "none";
83
+ iframe.style.width = ad.width ?? "auto";
84
+ iframe.style.height = ad.height ?? "auto";
85
+ element.replaceChildren(iframe);
86
+ }
87
+ function renderInline(ad, element) {
88
+ element.style.width = ad.width ?? "auto";
89
+ element.style.height = ad.height ?? "auto";
90
+ element.innerHTML = String(ad.tag);
91
+ }
92
+ function generateName(location, format, slot) {
93
+ return `${location}${slot ? `${slot}` : ""}-${format}`;
94
+ }
69
95
  async function findDomSlots(context) {
70
96
  await waitForDomLoad();
71
- return (await Promise.all(Array.from(document.querySelectorAll(".adunit")).filter((element) => Boolean(element.dataset.format)).map((element) => createSlot({
97
+ return Array.from(document.querySelectorAll(".adunit")).filter((element) => {
98
+ var _a;
99
+ if (!element.dataset.format)
100
+ return false;
101
+ const name = generateName(
102
+ context.location,
103
+ element.dataset.format,
104
+ element.dataset.slot
105
+ );
106
+ return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === name));
107
+ }).map((element) => createSlot({
72
108
  format: element.dataset.format,
73
109
  containingElement: element,
74
110
  slot: element.dataset.slot,
75
111
  context
76
- })))).filter((slot) => {
112
+ })).filter((slot) => {
77
113
  var _a;
78
- return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.getName() === slot.getName()));
114
+ return !((_a = context.getAll) == null ? void 0 : _a.call(context).some((activeSlot) => activeSlot.name.value === slot.name.value));
79
115
  });
80
116
  }
81
- async function createSlotManager({
117
+ function createSlotManager({
82
118
  initialSlots = [],
83
119
  context
84
120
  }) {
85
- const slots = /* @__PURE__ */ new Map();
86
- await Promise.allSettled(initialSlots.map(async (slot) => add({
87
- ...slot,
88
- lazyLoading: false
89
- })));
90
- function getAll() {
91
- return Array.from(slots).map(([, slot]) => slot);
92
- }
93
- async function add(options) {
94
- var _a, _b;
95
- const slot = await createSlot({
96
- ...options,
97
- onDispose,
98
- onNameChange,
99
- context
121
+ const scope = effectScope();
122
+ return scope.run(() => {
123
+ const slots = shallowReactive(/* @__PURE__ */ new Map());
124
+ watchEffect(() => {
125
+ var _a;
126
+ (_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
100
127
  });
101
- function onDispose() {
102
- var _a2, _b2;
103
- slots.delete(slot.getName());
104
- logger.debug("Slot removed", {
128
+ function getAll() {
129
+ return Array.from(slots).map(([, slot]) => slot);
130
+ }
131
+ function add(options) {
132
+ var _a;
133
+ const slot = createSlot({
134
+ ...options,
135
+ onDispose,
136
+ context
137
+ });
138
+ function onDispose() {
139
+ var _a2;
140
+ slots.delete(slot.name.value);
141
+ logger.debug("Slot removed", {
142
+ slot,
143
+ slots: Array.from(slots)
144
+ });
145
+ (_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
146
+ }
147
+ slots.set(slot.name.value, slot);
148
+ watch(slot.name, (newName, previousName) => {
149
+ slots.set(newName, slot);
150
+ slots.delete(previousName);
151
+ });
152
+ logger.debug("Slot added", {
105
153
  slot,
106
- slots: Array.from(slots)
154
+ slots: Array.from(slots.values())
107
155
  });
108
- (_a2 = context.events) == null ? void 0 : _a2.removeSlot.dispatch(slot);
109
- (_b2 = context.events) == null ? void 0 : _b2.changeSlots.dispatch(Array.from(slots.values()));
156
+ (_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
157
+ return slot;
110
158
  }
111
- slots.set(slot.getName(), slot);
112
- function onNameChange(newName, previousName) {
113
- var _a2;
114
- slots.set(newName, slot);
115
- slots.delete(previousName);
116
- (_a2 = context.events) == null ? void 0 : _a2.changeSlots.dispatch(Array.from(slots.values()));
159
+ async function findDomSlots$1() {
160
+ const domSlots = await findDomSlots(
161
+ context
162
+ );
163
+ for (const slot of domSlots)
164
+ slots.set(slot.name.value, slot);
165
+ return domSlots;
117
166
  }
118
- logger.debug("Slot added", {
119
- slot,
120
- slots: Array.from(slots.values())
121
- });
122
- (_a = context.events) == null ? void 0 : _a.addSlot.dispatch(slot);
123
- (_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(slots.values()));
124
- return slot;
125
- }
126
- async function findDomSlots$1() {
127
- var _a;
128
- const domSlots = await findDomSlots(
129
- context
130
- );
131
- for (const slot of domSlots) {
132
- slots.set(slot.getName(), slot);
133
- (_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
167
+ function get(name) {
168
+ return slots.get(name);
134
169
  }
135
- return domSlots;
136
- }
137
- function get(name) {
138
- return slots.get(name);
139
- }
140
- function dispose() {
141
- var _a;
142
- for (const slot of slots.values())
143
- slot.dispose();
144
- slots.clear();
145
- (_a = context.events) == null ? void 0 : _a.changeSlots.dispatch(Array.from(slots.values()));
146
- }
147
- return {
148
- getAll,
149
- add,
150
- findDomSlots: findDomSlots$1,
151
- get,
152
- dispose
153
- };
170
+ function dispose() {
171
+ for (const slot of slots.values())
172
+ slot.dispose();
173
+ slots.clear();
174
+ scope.stop();
175
+ }
176
+ for (const options of initialSlots) {
177
+ add({
178
+ ...options,
179
+ lazyLoading: false
180
+ });
181
+ }
182
+ return {
183
+ getAll,
184
+ add,
185
+ findDomSlots: findDomSlots$1,
186
+ get,
187
+ dispose
188
+ };
189
+ });
154
190
  }
155
191
  function onTcfConsentChange(callback) {
156
192
  var _a;
@@ -270,7 +306,7 @@ const logger = createLogger({
270
306
  scope: "Adhese SDK"
271
307
  });
272
308
  function createParameters(options, queryDetector) {
273
- const parameters = new MapWithEvents();
309
+ const parameters = /* @__PURE__ */ new Map();
274
310
  if (options.logReferrer)
275
311
  parameters.set("re", btoa(document.referrer));
276
312
  if (options.logUrl)
@@ -297,230 +333,231 @@ function setupLogging(mergedOptions) {
297
333
  function isPreviewMode() {
298
334
  return window.location.search.includes("adhesePreviewCreativeId");
299
335
  }
300
- class MapWithEvents extends Map {
301
- constructor() {
302
- super(...arguments);
303
- __publicField(this, "listeners", /* @__PURE__ */ new Set());
336
+ function createHook({
337
+ onRun,
338
+ onAdd
339
+ }) {
340
+ const callbacks = /* @__PURE__ */ new Set();
341
+ function run() {
342
+ for (const callback of callbacks)
343
+ callback();
344
+ onRun == null ? void 0 : onRun();
304
345
  }
305
- addEventListener(listener) {
306
- this.listeners.add(listener);
346
+ function add(callback) {
347
+ callbacks.add(callback);
348
+ onAdd == null ? void 0 : onAdd();
307
349
  }
308
- removeEventListener(listener) {
309
- this.listeners.delete(listener);
350
+ return [run, add];
351
+ }
352
+ let resolveOnInitPromise = () => {
353
+ };
354
+ let isInit = false;
355
+ new Promise((resolve) => {
356
+ resolveOnInitPromise = resolve;
357
+ });
358
+ const [runOnInit, onInit] = createHook({
359
+ onRun() {
360
+ isInit = true;
361
+ resolveOnInitPromise();
362
+ logger.debug("Initialization completed");
363
+ },
364
+ onAdd() {
365
+ if (isInit)
366
+ runOnInit();
310
367
  }
311
- set(key, value) {
312
- const set = super.set(key, value);
313
- this.listeners.forEach((listener) => {
314
- listener();
368
+ });
369
+ function createAdhese(options) {
370
+ const scope = effectScope();
371
+ return scope.run(() => {
372
+ const mergedOptions = {
373
+ host: `https://ads-${options.account}.adhese.com`,
374
+ poolHost: `https://pool-${options.account}.adhese.com`,
375
+ location: "homepage",
376
+ requestType: "POST",
377
+ debug: false,
378
+ initialSlots: [],
379
+ findDomSlotsOnLoad: false,
380
+ consent: false,
381
+ logReferrer: true,
382
+ logUrl: true,
383
+ eagerRendering: false,
384
+ viewabilityTracking: true,
385
+ ...options
386
+ };
387
+ setupLogging(mergedOptions);
388
+ const context = reactive({
389
+ location: mergedOptions.location,
390
+ consent: mergedOptions.consent,
391
+ debug: mergedOptions.debug,
392
+ getAll,
393
+ get,
394
+ options: mergedOptions,
395
+ logger
315
396
  });
316
- return set;
317
- }
318
- clear() {
319
- super.clear();
320
- this.listeners.forEach((listener) => {
321
- listener();
397
+ context.events = createEventManager();
398
+ function getLocation() {
399
+ return context.location;
400
+ }
401
+ function setLocation(newLocation) {
402
+ var _a;
403
+ context.location = newLocation;
404
+ (_a = context.events) == null ? void 0 : _a.locationChange.dispatch(newLocation);
405
+ }
406
+ const queryDetector = createQueryDetector({
407
+ onChange: onQueryChange,
408
+ queries: mergedOptions.queries
322
409
  });
323
- }
324
- delete(key) {
325
- const deleted = super.delete(key);
326
- this.listeners.forEach((listener) => {
327
- listener();
410
+ context.parameters = createParameters(mergedOptions, queryDetector);
411
+ watch(
412
+ context.parameters,
413
+ onParametersChange,
414
+ {
415
+ deep: true,
416
+ immediate: true
417
+ }
418
+ );
419
+ function onParametersChange() {
420
+ var _a;
421
+ if (context.parameters)
422
+ (_a = context.events) == null ? void 0 : _a.parametersChange.dispatch(context.parameters);
423
+ }
424
+ async function onQueryChange() {
425
+ var _a, _b;
426
+ const query = queryDetector.getQuery();
427
+ (_a = context.parameters) == null ? void 0 : _a.set("dt", query);
428
+ (_b = context.parameters) == null ? void 0 : _b.set("br", query);
429
+ await fetchAndRenderAllSlots();
430
+ }
431
+ function getConsent() {
432
+ return context.consent;
433
+ }
434
+ function setConsent(newConsent) {
435
+ var _a, _b;
436
+ (_a = context.parameters) == null ? void 0 : _a.set("tl", newConsent ? "all" : "none");
437
+ context.consent = newConsent;
438
+ (_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
439
+ }
440
+ const slotManager = createSlotManager({
441
+ initialSlots: mergedOptions.initialSlots,
442
+ context
328
443
  });
329
- return deleted;
330
- }
331
- /**
332
- * Remove all listeners and clear the map.
333
- */
334
- dispose() {
335
- this.listeners.clear();
336
- super.clear();
337
- }
338
- }
339
- async function createAdhese(options) {
340
- var _a;
341
- const mergedOptions = {
342
- host: `https://ads-${options.account}.adhese.com`,
343
- poolHost: `https://pool-${options.account}.adhese.com`,
344
- location: "homepage",
345
- requestType: "POST",
346
- debug: false,
347
- initialSlots: [],
348
- findDomSlotsOnLoad: false,
349
- consent: false,
350
- logReferrer: true,
351
- logUrl: true,
352
- eagerRendering: false,
353
- viewabilityTracking: true,
354
- ...options
355
- };
356
- setupLogging(mergedOptions);
357
- const context = new Proxy({
358
- location: mergedOptions.location,
359
- consent: mergedOptions.consent,
360
- debug: mergedOptions.debug,
361
- getAll,
362
- get,
363
- options: mergedOptions,
364
- logger
365
- }, {});
366
- context.events = createEventManager();
367
- function getLocation() {
368
- return context.location;
369
- }
370
- function setLocation(newLocation) {
371
- var _a2;
372
- context.location = newLocation;
373
- (_a2 = context.events) == null ? void 0 : _a2.locationChange.dispatch(newLocation);
374
- }
375
- const queryDetector = createQueryDetector({
376
- onChange: onQueryChange,
377
- queries: mergedOptions.queries
378
- });
379
- context.parameters = createParameters(mergedOptions, queryDetector);
380
- context.parameters.addEventListener(onParametersChange);
381
- let unmountDevtools;
382
- if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
383
- unmountDevtools = await createDevtools(context);
384
- (_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
385
- }
386
- function onParametersChange() {
387
- var _a2;
388
- if (context.parameters)
389
- (_a2 = context.events) == null ? void 0 : _a2.parametersChange.dispatch(context.parameters);
390
- }
391
- async function onQueryChange() {
392
- var _a2, _b;
393
- const query = queryDetector.getQuery();
394
- (_a2 = context.parameters) == null ? void 0 : _a2.set("dt", query);
395
- (_b = context.parameters) == null ? void 0 : _b.set("br", query);
396
- await fetchAndRenderAllSlots();
397
- }
398
- function getConsent() {
399
- return context.consent;
400
- }
401
- function setConsent(newConsent) {
402
- var _a2, _b;
403
- (_a2 = context.parameters) == null ? void 0 : _a2.set("tl", newConsent ? "all" : "none");
404
- context.consent = newConsent;
405
- (_b = context.events) == null ? void 0 : _b.consentChange.dispatch(newConsent);
406
- }
407
- const slotManager = await createSlotManager({
408
- initialSlots: mergedOptions.initialSlots,
409
- context
410
- });
411
- function getAll() {
412
- return slotManager.getAll();
413
- }
414
- function get(name) {
415
- return slotManager.get(name);
416
- }
417
- async function addSlot(slotOptions) {
418
- const slot = await slotManager.add(slotOptions);
419
- if (!slot.lazyLoading) {
420
- const ad = await requestAd({
421
- slot,
422
- host: mergedOptions.host,
423
- parameters: context.parameters,
424
- account: mergedOptions.account,
444
+ function getAll() {
445
+ return slotManager.getAll() ?? [];
446
+ }
447
+ function get(name) {
448
+ return slotManager.get(name);
449
+ }
450
+ async function addSlot(slotOptions) {
451
+ if (!slotManager)
452
+ throw new Error("Slot manager not initialized");
453
+ const slot = slotManager.add(slotOptions);
454
+ if (!slot.lazyLoading) {
455
+ slot.ad.value = await requestAd({
456
+ slot,
457
+ context
458
+ });
459
+ }
460
+ return slot;
461
+ }
462
+ async function findDomSlots2() {
463
+ const domSlots = (await slotManager.findDomSlots() ?? []).filter((slot) => !slot.lazyLoading);
464
+ if (domSlots.length <= 0)
465
+ return [];
466
+ const ads = await requestAds({
467
+ slots: domSlots,
425
468
  context
426
469
  });
427
- await slot.setAd(ad);
470
+ for (const ad of ads) {
471
+ const slot = slotManager.get(ad.slotName);
472
+ if (slot)
473
+ slot.ad.value = ad;
474
+ }
475
+ return domSlots;
428
476
  }
429
- return slot;
430
- }
431
- async function findDomSlots2() {
432
- const domSlots = (await slotManager.findDomSlots()).filter((slot) => !slot.lazyLoading);
433
- const ads = await requestAds({
434
- host: mergedOptions.host,
435
- slots: domSlots,
436
- method: mergedOptions.requestType,
437
- account: mergedOptions.account,
438
- parameters: context.parameters,
439
- context
477
+ let unmountDevtools;
478
+ async function toggleDebug() {
479
+ var _a, _b;
480
+ context.debug = !context.debug;
481
+ if (context.debug && !unmountDevtools) {
482
+ unmountDevtools = await createDevtools(context);
483
+ logger.setMinLogLevelThreshold("debug");
484
+ logger.debug("Debug mode enabled");
485
+ (_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
486
+ } else {
487
+ logger.debug("Debug mode disabled");
488
+ unmountDevtools == null ? void 0 : unmountDevtools();
489
+ unmountDevtools = void 0;
490
+ logger.setMinLogLevelThreshold("info");
491
+ (_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
492
+ }
493
+ return context.debug;
494
+ }
495
+ async function fetchAndRenderAllSlots() {
496
+ const slots = (slotManager.getAll() ?? []).filter((slot) => !slot.lazyLoading);
497
+ if (slots.length === 0)
498
+ return;
499
+ const ads = await requestAds({
500
+ slots,
501
+ context
502
+ });
503
+ for (const ad of ads) {
504
+ const slot = slotManager.get(ad.slotName);
505
+ if (slot)
506
+ slot.ad.value = ad;
507
+ }
508
+ }
509
+ const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
510
+ var _a, _b;
511
+ if (!data.tcString)
512
+ return;
513
+ logger.debug("TCF v2 consent data received", {
514
+ data
515
+ });
516
+ (_a = context.parameters) == null ? void 0 : _a.set("xt", data.tcString);
517
+ (_b = context.parameters) == null ? void 0 : _b.delete("tl");
518
+ await fetchAndRenderAllSlots();
440
519
  });
441
- await Promise.allSettled(ads.map((ad) => {
442
- var _a2;
443
- return (_a2 = slotManager.get(ad.slotName)) == null ? void 0 : _a2.setAd(ad);
444
- }));
445
- return domSlots;
446
- }
447
- async function toggleDebug() {
448
- var _a2, _b;
449
- context.debug = !context.debug;
450
- if (context.debug && !unmountDevtools) {
451
- unmountDevtools = await createDevtools(context);
452
- logger.setMinLogLevelThreshold("debug");
453
- logger.debug("Debug mode enabled");
454
- (_a2 = context.events) == null ? void 0 : _a2.debugChange.dispatch(true);
455
- } else {
456
- logger.debug("Debug mode disabled");
520
+ function dispose() {
521
+ var _a, _b;
457
522
  unmountDevtools == null ? void 0 : unmountDevtools();
458
- unmountDevtools = void 0;
459
- logger.setMinLogLevelThreshold("info");
460
- (_b = context.events) == null ? void 0 : _b.debugChange.dispatch(false);
523
+ queryDetector.dispose();
524
+ slotManager.dispose();
525
+ queryDetector.dispose();
526
+ disposeOnTcfConsentChange();
527
+ (_a = context.parameters) == null ? void 0 : _a.clear();
528
+ logger.resetLogs();
529
+ (_b = context.events) == null ? void 0 : _b.dispose();
530
+ logger.info("Adhese instance disposed");
531
+ scope.stop();
461
532
  }
462
- return context.debug;
463
- }
464
- async function fetchAndRenderAllSlots() {
465
- const slots = slotManager.getAll().filter((slot) => !slot.lazyLoading);
466
- if (slots.length === 0)
467
- return;
468
- const ads = await requestAds({
469
- host: mergedOptions.host,
470
- slots,
471
- method: mergedOptions.requestType,
472
- account: mergedOptions.account,
533
+ onInit(async () => {
534
+ var _a;
535
+ if ((slotManager.getAll().length ?? 0) > 0)
536
+ await fetchAndRenderAllSlots().catch(logger.error);
537
+ if (mergedOptions.findDomSlotsOnLoad)
538
+ await findDomSlots2();
539
+ if (mergedOptions.debug || window.location.search.includes("adhese_debug=true") || isPreviewMode()) {
540
+ unmountDevtools = await createDevtools(context);
541
+ (_a = context.events) == null ? void 0 : _a.debugChange.dispatch(true);
542
+ }
543
+ });
544
+ runOnInit();
545
+ return {
546
+ ...mergedOptions,
547
+ ...slotManager,
473
548
  parameters: context.parameters,
549
+ events: context.events,
550
+ getLocation,
551
+ setLocation,
552
+ getConsent,
553
+ setConsent,
554
+ addSlot,
555
+ findDomSlots: findDomSlots2,
556
+ dispose,
557
+ toggleDebug,
474
558
  context
475
- });
476
- await Promise.allSettled(ads.map((ad) => {
477
- var _a2;
478
- return (_a2 = slotManager.get(ad.slotName)) == null ? void 0 : _a2.setAd(ad);
479
- }));
480
- }
481
- const disposeOnTcfConsentChange = onTcfConsentChange(async (data) => {
482
- var _a2, _b;
483
- if (!data.tcString)
484
- return;
485
- logger.debug("TCF v2 consent data received", {
486
- data
487
- });
488
- (_a2 = context.parameters) == null ? void 0 : _a2.set("xt", data.tcString);
489
- (_b = context.parameters) == null ? void 0 : _b.delete("tl");
490
- await fetchAndRenderAllSlots();
559
+ };
491
560
  });
492
- if (slotManager.getAll().length > 0)
493
- await fetchAndRenderAllSlots().catch(logger.error);
494
- function dispose() {
495
- var _a2, _b, _c;
496
- queryDetector.dispose();
497
- slotManager.dispose();
498
- queryDetector.dispose();
499
- disposeOnTcfConsentChange();
500
- (_a2 = context.parameters) == null ? void 0 : _a2.dispose();
501
- (_b = context.parameters) == null ? void 0 : _b.clear();
502
- logger.resetLogs();
503
- (_c = context.events) == null ? void 0 : _c.dispose();
504
- unmountDevtools == null ? void 0 : unmountDevtools();
505
- logger.info("Adhese instance disposed");
506
- }
507
- if (mergedOptions.findDomSlotsOnLoad)
508
- await slotManager.findDomSlots();
509
- return {
510
- ...mergedOptions,
511
- ...slotManager,
512
- parameters: context.parameters,
513
- events: context.events,
514
- getLocation,
515
- setLocation,
516
- getConsent,
517
- setConsent,
518
- addSlot,
519
- findDomSlots: findDomSlots2,
520
- dispose,
521
- toggleDebug,
522
- context
523
- };
524
561
  }
525
562
  function addTrackingPixel(url) {
526
563
  const img = document.createElement("img");
@@ -533,118 +570,7 @@ function addTrackingPixel(url) {
533
570
  img.style.top = "0";
534
571
  return document.body.appendChild(img);
535
572
  }
536
- function renderIframe(ad, element) {
537
- const iframe = document.createElement("iframe");
538
- iframe.srcdoc = `
539
- <!DOCTYPE html>
540
- <html>
541
- <head>
542
- <style>
543
- body {
544
- margin: 0;
545
- padding: 0;
546
- overflow: hidden;
547
- }
548
- </style>
549
- </head>
550
- <body>
551
- ${ad.tag}
552
- </body>
553
- `.replaceAll(/\s+/g, " ").trim();
554
- iframe.style.border = "none";
555
- iframe.style.width = ad.width ? `${ad.width}px` : "100%";
556
- iframe.style.height = ad.height ? `${ad.height}px` : "100%";
557
- element.replaceChildren(iframe);
558
- }
559
- function renderInline(ad, element) {
560
- element.style.width = ad.width ? `${ad.width}px` : "100%";
561
- element.style.height = ad.height ? `${ad.height}px` : "100%";
562
- element.innerHTML = ad.tag;
563
- }
564
- const renderFunctions = {
565
- iframe: renderIframe,
566
- inline: renderInline
567
- };
568
- async function createSlot(options) {
569
- var _a;
570
- const {
571
- containingElement,
572
- slot,
573
- context,
574
- renderMode = "iframe"
575
- } = options;
576
- await waitForDomLoad();
577
- const parameters = new Map(Object.entries(options.parameters ?? {}));
578
- let format;
579
- let queryDetector = null;
580
- if (typeof options.format === "string") {
581
- format = options.format;
582
- } else {
583
- queryDetector = createQueryDetector({
584
- onChange: setFormat,
585
- queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
586
- });
587
- format = queryDetector.getQuery();
588
- }
589
- async function setFormat(newFormat) {
590
- var _a2;
591
- const oldName = getName();
592
- format = newFormat;
593
- (_a2 = options.onNameChange) == null ? void 0 : _a2.call(options, getName(), oldName);
594
- const newAd = await requestAd({
595
- slot: {
596
- getName,
597
- parameters
598
- },
599
- account: context.options.account,
600
- host: context.options.host,
601
- parameters: context.parameters,
602
- context
603
- });
604
- cleanElement();
605
- await setAd(newAd);
606
- }
607
- function getFormat() {
608
- return format;
609
- }
610
- let element = typeof containingElement === "string" || !containingElement ? document.querySelector(`.adunit[data-format="${format}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`) : containingElement;
611
- function getElement() {
612
- if (renderMode === "iframe")
613
- return (element == null ? void 0 : element.querySelector("iframe")) ?? null;
614
- return (element == null ? void 0 : element.innerHTML) ? element.firstElementChild : null;
615
- }
616
- let impressionTrackingPixelElement = null;
617
- let viewabilityTrackingPixelElement = null;
618
- let isInViewport = false;
619
- let ad = null;
620
- function getAd() {
621
- return ad;
622
- }
623
- async function setAd(newAd) {
624
- var _a2, _b;
625
- ad = newAd;
626
- if (isInViewport || context.options.eagerRendering)
627
- await render(ad);
628
- if (element) {
629
- element.style.width = `${ad.width}px`;
630
- element.style.height = `${ad.height}px`;
631
- }
632
- await ((_b = context.events) == null ? void 0 : _b.changeSlots.dispatchAsync(Array.from(((_a2 = context.getAll) == null ? void 0 : _a2.call(context)) ?? [])));
633
- }
634
- const renderIntersectionObserver = new IntersectionObserver((entries) => {
635
- isInViewport = entries.some((entry) => entry.isIntersecting);
636
- if (isInViewport) {
637
- (async () => {
638
- if (!ad && options.lazyLoading)
639
- await render();
640
- else if (ad)
641
- await render(ad);
642
- })().catch(logger.error);
643
- }
644
- }, {
645
- rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
646
- threshold: 0
647
- });
573
+ function useViewabilityObserver({ context, ad, name, element }) {
648
574
  let timeoutId = null;
649
575
  const {
650
576
  threshold,
@@ -656,17 +582,19 @@ async function createSlot(options) {
656
582
  rootMargin: "0px",
657
583
  ...context.options.viewabilityTrackingOptions
658
584
  };
585
+ const trackingPixel = ref(null);
586
+ const isTracked = computed(() => Boolean(trackingPixel.value));
659
587
  const viewabilityObserver = new IntersectionObserver(([entry]) => {
660
- if (context.options.viewabilityTracking && !viewabilityTrackingPixelElement && ad) {
588
+ if (context.options.viewabilityTracking && !trackingPixel.value && ad) {
661
589
  const ratio = round(entry.intersectionRatio, 1);
662
590
  if (ratio >= threshold && !timeoutId) {
663
591
  timeoutId = setTimeout(() => {
664
- var _a2, _b;
592
+ var _a, _b, _c;
665
593
  timeoutId = null;
666
- if (ad == null ? void 0 : ad.viewableImpressionCounter) {
667
- viewabilityTrackingPixelElement = addTrackingPixel(ad.viewableImpressionCounter);
668
- logger.debug(`Viewability tracking pixel fired for ${getName()}`);
669
- (_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(((_a2 = context.getAll) == null ? void 0 : _a2.call(context)) ?? []));
594
+ if ((_a = ad.value) == null ? void 0 : _a.viewableImpressionCounter) {
595
+ trackingPixel.value = addTrackingPixel(ad.value.viewableImpressionCounter);
596
+ logger.debug(`Viewability tracking pixel fired for ${name.value}`);
597
+ (_c = context.events) == null ? void 0 : _c.changeSlots.dispatch(Array.from(((_b = context.getAll) == null ? void 0 : _b.call(context)) ?? []));
670
598
  }
671
599
  }, duration);
672
600
  } else if (ratio < threshold && timeoutId) {
@@ -678,90 +606,218 @@ async function createSlot(options) {
678
606
  rootMargin,
679
607
  threshold: Array.from({ length: 11 }, (_, i) => i * 0.1)
680
608
  });
681
- if (element && context.options.viewabilityTracking)
682
- viewabilityObserver.observe(element);
683
- if (element)
684
- renderIntersectionObserver.observe(element);
685
- async function render(adToRender) {
686
- var _a2, _b;
687
- await waitForDomLoad();
688
- ad = adToRender ?? ad ?? await requestAd({
689
- slot: {
690
- getName,
691
- parameters
692
- },
693
- account: context.options.account,
694
- host: context.options.host,
695
- parameters: context.parameters,
696
- context
697
- });
698
- if (!element) {
699
- const error = `Could not create slot for format ${format}. No element found.`;
700
- logger.error(error, options);
701
- throw new Error(error);
702
- }
703
- if (context.debug)
704
- element.style.position = "relative";
705
- renderFunctions[renderMode](ad, element);
706
- if ((ad == null ? void 0 : ad.impressionCounter) && !impressionTrackingPixelElement) {
707
- impressionTrackingPixelElement = addTrackingPixel(ad.impressionCounter);
708
- logger.debug(`Impression tracking pixel fired for ${getName()}`);
709
- }
710
- logger.debug("Slot rendered", {
711
- renderedElement: element,
712
- location: context.location,
713
- format,
714
- containingElement
715
- });
716
- renderIntersectionObserver.disconnect();
717
- await ((_b = context.events) == null ? void 0 : _b.changeSlots.dispatchAsync(Array.from(((_a2 = context.getAll) == null ? void 0 : _a2.call(context)) ?? [])));
718
- return element;
719
- }
720
- function cleanElement() {
721
- if (!element)
722
- return;
723
- element.innerHTML = "";
724
- element.style.position = "";
725
- element.style.width = "";
726
- element.style.height = "";
727
- }
728
- function getName() {
729
- return `${context.location}${slot ? `${slot}` : ""}-${format}`;
609
+ function observe(newElement, oldElement) {
610
+ if (oldElement)
611
+ viewabilityObserver.unobserve(oldElement);
612
+ if (newElement && context.options.viewabilityTracking)
613
+ viewabilityObserver.observe(newElement);
614
+ return () => {
615
+ if (newElement)
616
+ viewabilityObserver.unobserve(newElement);
617
+ };
730
618
  }
731
- function dispose() {
732
- var _a2;
733
- cleanElement();
734
- impressionTrackingPixelElement == null ? void 0 : impressionTrackingPixelElement.remove();
735
- viewabilityTrackingPixelElement == null ? void 0 : viewabilityTrackingPixelElement.remove();
736
- element = null;
737
- ad = null;
738
- renderIntersectionObserver.disconnect();
619
+ watch(element, observe);
620
+ observe(element.value);
621
+ return [isTracked, () => {
622
+ var _a;
623
+ (_a = trackingPixel.value) == null ? void 0 : _a.remove();
739
624
  viewabilityObserver.disconnect();
740
- (_a2 = options.onDispose) == null ? void 0 : _a2.call(options);
741
- queryDetector == null ? void 0 : queryDetector.dispose();
742
- }
743
- function isViewabilityTracked() {
744
- return Boolean(viewabilityTrackingPixelElement);
745
- }
746
- function isImpressionTracked() {
747
- return Boolean(impressionTrackingPixelElement);
625
+ }];
626
+ }
627
+ function useRenderIntersectionObserver({ ad, options, element, render }) {
628
+ var _a;
629
+ const isInViewport = ref(false);
630
+ const renderIntersectionObserver = new IntersectionObserver((entries) => {
631
+ isInViewport.value = entries.some((entry) => entry.isIntersecting);
632
+ if (isInViewport.value) {
633
+ (async () => {
634
+ if (!ad.value && options.lazyLoading)
635
+ await render();
636
+ await render(ad.value ?? void 0);
637
+ })().catch(logger.error);
638
+ }
639
+ }, {
640
+ rootMargin: ((_a = options.lazyLoadingOptions) == null ? void 0 : _a.rootMargin) ?? "200px",
641
+ threshold: 0
642
+ });
643
+ function observe(newElement, oldElement) {
644
+ if (oldElement)
645
+ renderIntersectionObserver.unobserve(oldElement);
646
+ if (newElement)
647
+ renderIntersectionObserver.observe(newElement);
648
+ return () => {
649
+ if (newElement)
650
+ renderIntersectionObserver.unobserve(newElement);
651
+ };
748
652
  }
749
- return {
750
- location: context.location,
751
- lazyLoading: options.lazyLoading ?? false,
752
- slot,
753
- parameters,
754
- setFormat,
755
- getFormat,
756
- render,
757
- getElement,
758
- getName,
759
- getAd,
760
- setAd,
761
- isViewabilityTracked,
762
- isImpressionTracked,
763
- dispose
764
- };
653
+ watch(element, observe);
654
+ observe(element.value);
655
+ return [isInViewport, () => {
656
+ renderIntersectionObserver.disconnect();
657
+ }];
658
+ }
659
+ const renderFunctions = {
660
+ iframe: renderIframe,
661
+ inline: renderInline
662
+ };
663
+ function createSlot(options) {
664
+ const scope = effectScope();
665
+ return scope.run(() => {
666
+ const {
667
+ containingElement,
668
+ slot,
669
+ context,
670
+ renderMode = "iframe"
671
+ } = options;
672
+ const parameters = reactive(new Map(Object.entries(options.parameters ?? {})));
673
+ let queryDetector = null;
674
+ if (typeof options.format !== "string") {
675
+ queryDetector = createQueryDetector({
676
+ onChange: onQueryChange,
677
+ queries: Object.fromEntries(options.format.map((item) => [item.format, item.query]))
678
+ });
679
+ }
680
+ const format = ref(queryDetector ? queryDetector.getQuery() : options.format);
681
+ function onQueryChange(newFormat) {
682
+ format.value = newFormat;
683
+ }
684
+ const ad = ref(null);
685
+ const name = computed(() => generateName(context.location, format.value, slot));
686
+ watch(name, async (newName, oldName) => {
687
+ var _a;
688
+ if (newName === oldName)
689
+ return;
690
+ (_a = options.onNameChange) == null ? void 0 : _a.call(options, newName, oldName);
691
+ const newAd = await requestAd({
692
+ slot: {
693
+ name: newName,
694
+ parameters
695
+ },
696
+ context
697
+ });
698
+ cleanElement();
699
+ ad.value = newAd;
700
+ });
701
+ const isDomLoaded = useDomLoaded();
702
+ const element = computed(
703
+ () => {
704
+ if (!(typeof containingElement === "string" || !containingElement))
705
+ return containingElement;
706
+ if (!isDomLoaded.value)
707
+ return null;
708
+ return document.querySelector(`.adunit[data-format="${format.value}"]#${containingElement}${slot ? `[data-slot="${slot}"]` : ""}`);
709
+ }
710
+ );
711
+ function getElement() {
712
+ var _a, _b;
713
+ if (renderMode === "iframe")
714
+ return ((_a = element.value) == null ? void 0 : _a.querySelector("iframe")) ?? null;
715
+ return ((_b = element.value) == null ? void 0 : _b.innerHTML) ? element.value.firstElementChild : null;
716
+ }
717
+ const [isInViewport, disposeRenderIntersectionObserver] = useRenderIntersectionObserver({
718
+ ad,
719
+ options,
720
+ element,
721
+ render
722
+ });
723
+ watch([ad, isInViewport], async ([newAd, newIsInViewport], [oldAd]) => {
724
+ var _a, _b;
725
+ if (!newAd || isEqual(newAd, oldAd))
726
+ return;
727
+ if (newIsInViewport || context.options.eagerRendering)
728
+ await render(newAd);
729
+ if (element.value) {
730
+ element.value.style.width = `${newAd.width}px`;
731
+ element.value.style.height = `${newAd.height}px`;
732
+ }
733
+ (_b = context.events) == null ? void 0 : _b.changeSlots.dispatch(Array.from(((_a = context.getAll) == null ? void 0 : _a.call(context)) ?? []));
734
+ });
735
+ const [
736
+ isViewabilityTracked,
737
+ disposeViewabilityObserver
738
+ ] = useViewabilityObserver({
739
+ context,
740
+ ad,
741
+ name,
742
+ element
743
+ });
744
+ const impressionTrackingPixelElement = ref(null);
745
+ const isImpressionTracked = computed(() => Boolean(impressionTrackingPixelElement.value));
746
+ async function render(adToRender) {
747
+ var _a, _b, _c, _d;
748
+ await waitForDomLoad();
749
+ ad.value = adToRender ?? ad.value ?? await requestAd({
750
+ slot: {
751
+ name,
752
+ parameters
753
+ },
754
+ context
755
+ });
756
+ ad.value = ((_a = options.onBeforeRender) == null ? void 0 : _a.call(options, ad.value)) ?? ad.value;
757
+ if (!element.value) {
758
+ const error = `Could not create slot for format ${format.value}. No element found.`;
759
+ logger.error(error, options);
760
+ throw new Error(error);
761
+ }
762
+ if (context.debug)
763
+ element.value.style.position = "relative";
764
+ renderFunctions[renderMode](ad.value, element.value);
765
+ if (((_b = ad.value) == null ? void 0 : _b.impressionCounter) && !impressionTrackingPixelElement.value) {
766
+ impressionTrackingPixelElement.value = addTrackingPixel((_c = ad.value) == null ? void 0 : _c.impressionCounter);
767
+ logger.debug(`Impression tracking pixel fired for ${name.value}`);
768
+ }
769
+ logger.debug("Slot rendered", {
770
+ renderedElement: element,
771
+ location: context.location,
772
+ format,
773
+ containingElement
774
+ });
775
+ (_d = options.onRender) == null ? void 0 : _d.call(options, element.value);
776
+ disposeRenderIntersectionObserver();
777
+ return element.value;
778
+ }
779
+ function cleanElement() {
780
+ if (!element.value)
781
+ return;
782
+ element.value.innerHTML = "";
783
+ element.value.style.position = "";
784
+ element.value.style.width = "";
785
+ element.value.style.height = "";
786
+ }
787
+ function dispose() {
788
+ var _a, _b;
789
+ cleanElement();
790
+ (_a = impressionTrackingPixelElement.value) == null ? void 0 : _a.remove();
791
+ ad.value = null;
792
+ disposeRenderIntersectionObserver();
793
+ disposeViewabilityObserver();
794
+ (_b = options.onDispose) == null ? void 0 : _b.call(options);
795
+ queryDetector == null ? void 0 : queryDetector.dispose();
796
+ scope.stop();
797
+ }
798
+ return {
799
+ location: context.location,
800
+ lazyLoading: options.lazyLoading ?? false,
801
+ slot,
802
+ parameters,
803
+ format,
804
+ name,
805
+ ad,
806
+ isViewabilityTracked,
807
+ isImpressionTracked,
808
+ render,
809
+ getElement,
810
+ dispose
811
+ };
812
+ });
813
+ }
814
+ function useDomLoaded() {
815
+ const isDomLoaded = ref(false);
816
+ onInit(async () => {
817
+ await waitForDomLoad();
818
+ isDomLoaded.value = true;
819
+ });
820
+ return isDomLoaded;
765
821
  }
766
822
  const numberLike = union([coerce.string().regex(/^\d+$/), literal("")]).transform((value) => value === "" ? void 0 : Number(value));
767
823
  const booleanLike = union([coerce.boolean(), literal("")]);
@@ -780,13 +836,48 @@ const dateLike = union([coerce.string(), literal("")]).transform((value) => {
780
836
  return void 0;
781
837
  return date;
782
838
  });
783
- const baseAdResponseScheme = object({
839
+ const cssValueLike = union([coerce.string(), literal(""), number()]).transform((value) => {
840
+ if (value === "" || value === 0 || value === "0")
841
+ return void 0;
842
+ if (numberLike.parse(value))
843
+ return `${numberLike.parse(value)}px`;
844
+ return String(value);
845
+ });
846
+ const isJson = string().transform((value, { addIssue }) => {
847
+ try {
848
+ return JSON.parse(value.replaceAll("'", '"'));
849
+ } catch (error) {
850
+ addIssue({
851
+ code: ZodIssueCode.custom,
852
+ message: `Invalid JSON: ${error.message}`
853
+ });
854
+ return NEVER;
855
+ }
856
+ });
857
+ const isHtmlString = string().transform((value, { addIssue }) => {
858
+ var _a;
859
+ const htmlParser = new DOMParser();
860
+ try {
861
+ const html = htmlParser.parseFromString(value, "text/html");
862
+ if (((_a = html.body) == null ? void 0 : _a.children.length) === 0)
863
+ throw new Error("Invalid HTML");
864
+ return value;
865
+ } catch (error) {
866
+ addIssue({
867
+ code: ZodIssueCode.custom,
868
+ message: error.message
869
+ });
870
+ return NEVER;
871
+ }
872
+ });
873
+ const isJsonOrHtmlString = union([isJson, isHtmlString]);
874
+ const isJsonOrHtmlOptionalString = union([coerce.string(), isJsonOrHtmlString]).transform((value) => {
875
+ if (value === "")
876
+ return void 0;
877
+ return value;
878
+ }).optional();
879
+ const baseSchema = object({
784
880
  adDuration: numberLike.optional(),
785
- adDuration2nd: numberLike.optional(),
786
- adDuration3rd: numberLike.optional(),
787
- adDuration4th: numberLike.optional(),
788
- adDuration5th: numberLike.optional(),
789
- adDuration6th: numberLike.optional(),
790
881
  adFormat: string().optional(),
791
882
  adType: string(),
792
883
  additionalCreativeTracker: urlLike.optional(),
@@ -798,34 +889,27 @@ const baseAdResponseScheme = object({
798
889
  advertiserId: string().optional(),
799
890
  altText: string().optional(),
800
891
  auctionable: booleanLike.optional(),
801
- body: string().optional(),
892
+ body: isJsonOrHtmlOptionalString,
802
893
  clickTag: urlLike.optional(),
803
894
  comment: string().optional(),
804
895
  creativeName: string().optional(),
805
896
  deliveryGroupId: string().optional(),
806
897
  deliveryMultiples: string().optional(),
807
- dm: string().optional(),
808
898
  ext: string().optional(),
809
899
  extension: object({
810
900
  mediaType: string(),
811
901
  prebid: unknown().optional()
812
902
  }).optional(),
813
- extraField1: string().optional(),
814
- extraField2: string().optional(),
815
- height: numberLike.optional(),
816
- height3rd: numberLike.optional(),
817
- height4th: numberLike.optional(),
818
- height5th: numberLike.optional(),
819
- height6th: numberLike.optional(),
820
- heightLarge: numberLike.optional(),
903
+ height: cssValueLike.optional(),
821
904
  id: string().optional(),
822
905
  impressionCounter: urlLike.optional(),
823
906
  libId: string().optional(),
824
907
  orderId: string().optional(),
825
908
  orderName: string().optional(),
826
909
  orderProperty: string().optional(),
827
- origin: string().optional(),
910
+ origin: union([literal("JERLICIA"), literal("DALE")]),
828
911
  originData: unknown().optional(),
912
+ originInstance: string().optional(),
829
913
  poolPath: urlLike.optional(),
830
914
  preview: booleanLike.optional(),
831
915
  priority: numberLike.optional(),
@@ -834,12 +918,7 @@ const baseAdResponseScheme = object({
834
918
  slotID: string(),
835
919
  slotName: string(),
836
920
  swfSrc: urlLike.optional(),
837
- swfSrc2nd: string().optional(),
838
- swfSrc3rd: string().optional(),
839
- swfSrc4th: string().optional(),
840
- swfSrc5th: string().optional(),
841
- swfSrc6th: string().optional(),
842
- tag: string(),
921
+ tag: isJsonOrHtmlOptionalString,
843
922
  tagUrl: urlLike.optional(),
844
923
  timeStamp: dateLike.optional(),
845
924
  trackedImpressionCounter: urlLike.optional(),
@@ -847,14 +926,21 @@ const baseAdResponseScheme = object({
847
926
  trackingUrl: urlLike.optional(),
848
927
  url: urlLike.optional(),
849
928
  viewableImpressionCounter: urlLike.optional(),
850
- width: numberLike.optional(),
851
- width3rd: numberLike.optional(),
852
- width4th: numberLike.optional(),
853
- width5th: numberLike.optional(),
854
- width6th: numberLike.optional(),
855
- widthLarge: numberLike.optional()
929
+ width: cssValueLike.optional(),
930
+ widthLarge: cssValueLike.optional()
856
931
  });
857
- const adResponseSchema = baseAdResponseScheme.extend({
932
+ const jerliciaSchema = object({
933
+ origin: literal("JERLICIA"),
934
+ tag: isJsonOrHtmlString
935
+ }).passthrough();
936
+ const daleSchema = object({
937
+ origin: literal("DALE"),
938
+ body: isJsonOrHtmlString
939
+ }).passthrough().transform(({ body, ...data }) => ({
940
+ ...data,
941
+ tag: body
942
+ }));
943
+ const adResponseSchema = baseSchema.extend({
858
944
  additionalCreatives: lazy(() => union([adResponseSchema.array(), string()]).optional())
859
945
  });
860
946
  const adSchema = adResponseSchema.transform(({
@@ -869,6 +955,21 @@ const adSchema = adResponseSchema.transform(({
869
955
  additionalCreatives: Array.isArray(additionalCreatives) ? additionalCreatives.map((creative) => adSchema.parse(creative)) : additionalCreatives
870
956
  };
871
957
  });
958
+ function parseResponse(response) {
959
+ const schemaMap = {
960
+ /* eslint-disable ts/naming-convention */
961
+ JERLICIA: jerliciaSchema,
962
+ DALE: daleSchema
963
+ /* eslint-enable ts/naming-convention */
964
+ };
965
+ const preParsed = adResponseSchema.array().parse(response);
966
+ return preParsed.map((item) => {
967
+ const schema = schemaMap[item.origin];
968
+ if (!schema)
969
+ return adSchema.parse(item);
970
+ return schema.parse(item);
971
+ });
972
+ }
872
973
  async function requestPreviews(account) {
873
974
  const previewObjects = getPreviewObjects();
874
975
  const list = (await Promise.allSettled(previewObjects.filter((previewObject) => "adhesePreviewCreativeId" in previewObject).map(async (previewObject) => {
@@ -914,16 +1015,16 @@ function getPreviewObjects() {
914
1015
  return previewObjects;
915
1016
  }
916
1017
  function requestWithPost({
917
- host,
1018
+ context: { options: { host }, parameters },
918
1019
  ...options
919
1020
  }) {
920
1021
  const payload = {
921
1022
  ...options,
922
1023
  slots: options.slots.map((slot) => ({
923
- slotname: slot.getName(),
1024
+ slotname: toValue(slot.name),
924
1025
  parameters: parseParameters(slot.parameters)
925
1026
  })),
926
- parameters: options.parameters && parseParameters(options.parameters)
1027
+ parameters: parameters && parseParameters(parameters)
927
1028
  };
928
1029
  return fetch(`${new URL(host).href}json`, {
929
1030
  method: "POST",
@@ -934,8 +1035,8 @@ function requestWithPost({
934
1035
  }
935
1036
  });
936
1037
  }
937
- async function requestWithGet(options) {
938
- return fetch(new URL(`${options.host}/json/sl${options.slots.map((slot) => slot.getName()).join("/sl")}`), {
1038
+ async function requestWithGet({ context, slots }) {
1039
+ return fetch(new URL(`${context.options.host}/json/sl${slots.map((slot) => toValue(slot.name)).join("/sl")}`), {
939
1040
  method: "GET",
940
1041
  headers: {
941
1042
  // eslint-disable-next-line ts/naming-convention
@@ -951,23 +1052,19 @@ function parseParameters(parameters) {
951
1052
  return false;
952
1053
  }));
953
1054
  }
954
- async function requestAds({
955
- method = "POST",
956
- context,
957
- ...options
958
- }) {
959
- var _a, _b, _c, _d;
1055
+ async function requestAds(options) {
1056
+ var _a, _b, _c, _d, _e;
1057
+ const { context } = options;
960
1058
  try {
961
1059
  (_a = context.events) == null ? void 0 : _a.requestAd.dispatch({
962
1060
  ...options,
963
- context,
964
- method
1061
+ context
965
1062
  });
966
- const [response, previews] = await Promise.all([(method == null ? void 0 : method.toUpperCase()) === "POST" ? requestWithPost(options) : requestWithGet(options), requestPreviews(options.account)]);
1063
+ const [response, previews] = await Promise.all([((_b = context.options.requestType) == null ? void 0 : _b.toUpperCase()) === "POST" ? requestWithPost(options) : requestWithGet(options), requestPreviews(context.options.account)]);
967
1064
  logger.debug("Received response", response);
968
1065
  if (!response.ok)
969
1066
  throw new Error(`Failed to request ad: ${response.status} ${response.statusText}`);
970
- const result = adSchema.array().parse(await response.json());
1067
+ const result = parseResponse(await response.json());
971
1068
  logger.debug("Parsed ad", result);
972
1069
  if (previews.length > 0)
973
1070
  logger.info(`Found ${previews.length} ${previews.length === 1 ? "preview" : "previews"}. Replacing ads in response with preview items`, previews);
@@ -979,18 +1076,18 @@ async function requestAds({
979
1076
  };
980
1077
  });
981
1078
  if (matchedPreviews.length > 0)
982
- (_b = context.events) == null ? void 0 : _b.previewReceived.dispatch(matchedPreviews);
1079
+ (_c = context.events) == null ? void 0 : _c.previewReceived.dispatch(matchedPreviews);
983
1080
  const mergedResult = [
984
1081
  ...result.filter((ad) => !previews.some((preview) => preview.libId === ad.libId)),
985
1082
  ...matchedPreviews
986
1083
  ];
987
1084
  if (mergedResult.length === 0)
988
1085
  throw new Error("No ads found");
989
- (_c = context.events) == null ? void 0 : _c.responseReceived.dispatch(mergedResult);
1086
+ (_d = context.events) == null ? void 0 : _d.responseReceived.dispatch(mergedResult);
990
1087
  return mergedResult;
991
1088
  } catch (error) {
992
1089
  logger.error(String(error));
993
- (_d = context.events) == null ? void 0 : _d.requestError.dispatch(error);
1090
+ (_e = context.events) == null ? void 0 : _e.requestError.dispatch(error);
994
1091
  throw error;
995
1092
  }
996
1093
  }