@smoud/playable-sdk 1.0.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/index.js ADDED
@@ -0,0 +1,631 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => sdk,
24
+ sdk: () => sdk
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/events.ts
29
+ var registeredEvents = {};
30
+ function onEvent(event, fn, context, once) {
31
+ let listeners = registeredEvents[event];
32
+ if (!listeners) {
33
+ listeners = registeredEvents[event] = {
34
+ list: []
35
+ };
36
+ }
37
+ listeners.list.push(fn, context || null, once || false);
38
+ }
39
+ function offEvent(event, fn, context) {
40
+ const listeners = registeredEvents[event];
41
+ if (!listeners) return;
42
+ var fnArray = listeners.list;
43
+ if (!fn) {
44
+ fnArray.length = 0;
45
+ } else {
46
+ let i = fnArray.length;
47
+ while (i > 0) {
48
+ i -= 3;
49
+ if (fnArray[i] == fn && (context !== void 0 || fnArray[i + 1] == context)) {
50
+ fnArray.splice(i, 3);
51
+ }
52
+ }
53
+ }
54
+ if (fnArray.length == 0) {
55
+ delete registeredEvents[event];
56
+ }
57
+ }
58
+ function emitEvent(event, a1, a2, a3) {
59
+ var listeners = registeredEvents[event];
60
+ if (!listeners) return;
61
+ const fnArray = listeners.list;
62
+ const len = arguments.length;
63
+ let fn, ctx;
64
+ for (var i = 0; i < fnArray.length; i += 3) {
65
+ fn = fnArray[i];
66
+ ctx = fnArray[i + 1];
67
+ if (fnArray[i + 2]) {
68
+ fnArray.splice(i, 3);
69
+ i -= 3;
70
+ }
71
+ if (len <= 1) fn.call(ctx);
72
+ else if (len == 2) fn.call(ctx, a1);
73
+ else if (len == 3) fn.call(ctx, a1, a2);
74
+ else fn.call(ctx, a1, a2, a3);
75
+ }
76
+ if (fnArray.length == 0) {
77
+ delete registeredEvents[event];
78
+ }
79
+ }
80
+
81
+ // src/protocols.ts
82
+ var uid = 0;
83
+ var NONE = uid++;
84
+ var MRAID = uid++;
85
+ var DAPI = uid++;
86
+ var NUCLEO = uid++;
87
+ var FACEBOOK = uid++;
88
+ var GOOGLE = uid++;
89
+ var MINTEGRAL = uid++;
90
+ var TAPJOY = uid++;
91
+ var TIKTOK = uid++;
92
+ var actualProtocol = NONE;
93
+ function isMraid() {
94
+ return actualProtocol === MRAID;
95
+ }
96
+ function isDapi() {
97
+ return actualProtocol === DAPI;
98
+ }
99
+ function isNucleo() {
100
+ return actualProtocol === NUCLEO;
101
+ }
102
+ function isFacebook() {
103
+ return actualProtocol === FACEBOOK;
104
+ }
105
+ function isGoogle() {
106
+ return actualProtocol === GOOGLE;
107
+ }
108
+ function isMintegral() {
109
+ return actualProtocol === MINTEGRAL;
110
+ }
111
+ function isTapjoy() {
112
+ return actualProtocol === TAPJOY;
113
+ }
114
+ function isTikTok() {
115
+ return actualProtocol === TIKTOK;
116
+ }
117
+ function ensureProtocol() {
118
+ if ("mraid" === AD_PROTOCOL) {
119
+ try {
120
+ mraid.getState();
121
+ actualProtocol = MRAID;
122
+ } catch (error) {
123
+ }
124
+ } else if ("dapi" === AD_PROTOCOL) {
125
+ try {
126
+ dapi.isReady();
127
+ actualProtocol = DAPI;
128
+ } catch (error) {
129
+ }
130
+ } else if ("facebook" === AD_NETWORK) {
131
+ try {
132
+ if (FbPlayableAd) actualProtocol = FACEBOOK;
133
+ } catch (error) {
134
+ }
135
+ } else if ("google" === AD_NETWORK) {
136
+ try {
137
+ if (ExitApi) actualProtocol = GOOGLE;
138
+ } catch (error) {
139
+ }
140
+ } else if ("mintegral" === AD_NETWORK) {
141
+ if (window.gameReady) actualProtocol = MINTEGRAL;
142
+ } else if ("tapjoy" === AD_NETWORK) {
143
+ if (window.TJ_API) actualProtocol = TAPJOY;
144
+ } else if ("tiktok" === AD_NETWORK) {
145
+ if (window.openAppStore) actualProtocol = TIKTOK;
146
+ }
147
+ }
148
+
149
+ // src/core.ts
150
+ var destinationUrl = /android/i.test(navigator.userAgent) ? GOOGLE_PLAY_URL : APP_STORE_URL;
151
+ var isSDKInitialized = false;
152
+ var isProtocolInitialized = false;
153
+ var isForcePaused = false;
154
+ var isInstallClicked = false;
155
+ var initCallback = () => {
156
+ };
157
+ function bootAd() {
158
+ if (sdk.isReady) return;
159
+ emitEvent("boot");
160
+ document.body.oncontextmenu = function() {
161
+ return false;
162
+ };
163
+ initCallback(sdk.maxWidth, sdk.maxHeight);
164
+ emitEvent("ready");
165
+ sdk.isReady = true;
166
+ }
167
+ function changeVolume(value) {
168
+ emitEvent("volume", value);
169
+ }
170
+ function handlePause() {
171
+ changeVolume(0);
172
+ sdk.isPaused = true;
173
+ emitEvent("pause");
174
+ }
175
+ function handleResume() {
176
+ if (isForcePaused) return;
177
+ changeVolume(sdk.volume);
178
+ sdk.isPaused = false;
179
+ emitEvent("resume");
180
+ }
181
+ function mraidIsViewable(viewable) {
182
+ if ("mraid" !== AD_PROTOCOL) return;
183
+ if (viewable) {
184
+ if (sdk.isReady) {
185
+ handleResume();
186
+ } else {
187
+ if (AD_NETWORK == "ironsource") {
188
+ const maxSize = mraid.getMaxSize();
189
+ sdk.maxWidth = Math.floor(maxSize.width);
190
+ sdk.maxHeight = Math.floor(maxSize.height);
191
+ }
192
+ bootAd();
193
+ }
194
+ } else {
195
+ handlePause();
196
+ }
197
+ }
198
+ function dapiIsViewable(event) {
199
+ if ("dapi" !== AD_PROTOCOL) return;
200
+ if (event.isViewable) {
201
+ if (sdk.isReady) {
202
+ handleResume();
203
+ } else {
204
+ var screenSize = dapi.getScreenSize();
205
+ screenSize.width = Math.floor(screenSize.width);
206
+ screenSize.height = Math.floor(screenSize.height);
207
+ bootAd();
208
+ }
209
+ } else {
210
+ handlePause();
211
+ }
212
+ }
213
+ function fireResizeEvent(width, height) {
214
+ handleResize(width, height);
215
+ }
216
+ function startMraidProtocol() {
217
+ if ("mraid" !== AD_PROTOCOL) return;
218
+ if (!isProtocolInitialized) {
219
+ mraid.removeEventListener("ready", startMraidProtocol);
220
+ mraid.addEventListener("viewableChange", function() {
221
+ var isViewable = mraid.isViewable();
222
+ mraidIsViewable(isViewable);
223
+ });
224
+ if (mraid.isViewable() || AD_NETWORK == "adcolony") {
225
+ mraidIsViewable(true);
226
+ }
227
+ mraid.addEventListener("audioVolumeChange", function(newVolume) {
228
+ if (newVolume !== null) {
229
+ if (newVolume > 0) {
230
+ changeVolume(sdk.volume);
231
+ } else {
232
+ changeVolume(0);
233
+ }
234
+ }
235
+ });
236
+ mraid.addEventListener("error", function(t, e) {
237
+ console.log("mraid error: " + t + " action: " + e);
238
+ });
239
+ mraid.addEventListener("sizeChange", function() {
240
+ var maxSize = mraid.getMaxSize();
241
+ fireResizeEvent(maxSize.width, maxSize.height);
242
+ });
243
+ isProtocolInitialized = true;
244
+ }
245
+ }
246
+ function startDapiProtocol() {
247
+ if ("dapi" !== AD_PROTOCOL) return;
248
+ if (!isProtocolInitialized) {
249
+ dapi.removeEventListener("ready", startDapiProtocol);
250
+ var isAudioEnabled = !!dapi.getAudioVolume();
251
+ dapi.addEventListener("audioVolumeChange", function(volume) {
252
+ var isAudioEnabled2 = !!volume;
253
+ if (isAudioEnabled2) {
254
+ changeVolume(sdk.volume);
255
+ } else {
256
+ changeVolume(0);
257
+ }
258
+ });
259
+ dapi.addEventListener("adResized", function(event) {
260
+ var maxSize = dapi.getScreenSize();
261
+ fireResizeEvent(event.width || maxSize.width, event.height || maxSize.height);
262
+ });
263
+ if (dapi.isViewable()) {
264
+ dapiIsViewable({ isViewable: true });
265
+ }
266
+ dapi.addEventListener("viewableChange", dapiIsViewable);
267
+ isProtocolInitialized = true;
268
+ }
269
+ }
270
+ function startDefaultProtocol() {
271
+ if ("none" !== AD_PROTOCOL) return;
272
+ if (!isProtocolInitialized) {
273
+ if ("mintegral" === AD_NETWORK) {
274
+ window.mintGameStart = function() {
275
+ handleResume();
276
+ handleResize(sdk.maxWidth, sdk.maxHeight);
277
+ };
278
+ window.mintGameClose = function() {
279
+ handlePause();
280
+ };
281
+ }
282
+ document.addEventListener("visibilitychange", () => {
283
+ if (document.visibilityState === "visible") {
284
+ if (sdk.isReady) {
285
+ handleResume();
286
+ } else {
287
+ bootAd();
288
+ }
289
+ } else {
290
+ handlePause();
291
+ }
292
+ });
293
+ if (document.readyState === "complete" || document.visibilityState === "visible") {
294
+ bootAd();
295
+ } else {
296
+ window.addEventListener("load", () => {
297
+ bootAd();
298
+ });
299
+ }
300
+ window.addEventListener("resize", function() {
301
+ handleResize();
302
+ });
303
+ if ("tapjoy" === AD_NETWORK && isTapjoy()) {
304
+ var tapjoyApi = {
305
+ skipAd: function() {
306
+ try {
307
+ sdk.finish();
308
+ } catch (e) {
309
+ console.warn("Could not skip ad! | " + e);
310
+ }
311
+ }
312
+ };
313
+ window.TJ_API.setPlayableAPI && window.TJ_API.setPlayableAPI(tapjoyApi);
314
+ }
315
+ isProtocolInitialized = true;
316
+ }
317
+ }
318
+ function finishTapjoy() {
319
+ window.TJ_API.objectiveComplete && window.TJ_API.objectiveComplete();
320
+ window.TJ_API.playableFinished && window.TJ_API.playableFinished();
321
+ window.TJ_API.gameplayFinished && window.TJ_API.gameplayFinished();
322
+ }
323
+ function handleResize(width, height) {
324
+ sdk.maxWidth = Math.floor(width || window.innerWidth);
325
+ sdk.maxHeight = Math.floor(height || window.innerHeight);
326
+ sdk.isLandscape = sdk.maxWidth > sdk.maxHeight;
327
+ emitEvent("resize", sdk.maxWidth, sdk.maxHeight);
328
+ }
329
+ var isListeningToTouchEvents = false;
330
+ var isTouchEventRegistered = false;
331
+ function onUserInteraction(event) {
332
+ if (typeof TouchEvent !== "undefined" && event instanceof TouchEvent) {
333
+ isListeningToTouchEvents = true;
334
+ }
335
+ if (isListeningToTouchEvents && event instanceof MouseEvent) return;
336
+ sdk.interactions += 1;
337
+ emitEvent("interaction", sdk.interactions);
338
+ }
339
+ function registerTouchHandlers() {
340
+ if (!isTouchEventRegistered) {
341
+ document.addEventListener("mousedown", onUserInteraction);
342
+ document.addEventListener("touchstart", onUserInteraction);
343
+ isTouchEventRegistered = true;
344
+ }
345
+ }
346
+ var _sdk = class _sdk {
347
+ /**
348
+ * Initializes the SDK and sets up protocol-specific handlers.
349
+ * This must be called as earlier as possible.
350
+ *
351
+ * @param callback Optional function called when ad container is ready
352
+ * @example
353
+ * // Basic initialization
354
+ * sdk.init();
355
+ *
356
+ * // Initialization with callback
357
+ * sdk.init((width, height) => {
358
+ * new App(width, height)
359
+ * });
360
+ *
361
+ * @fires init When initialization starts
362
+ * @fires boot When the ad begins booting
363
+ * @fires ready When Ad Network is ready and playable ad can be initialized
364
+ */
365
+ static init(callback) {
366
+ if (isSDKInitialized) return;
367
+ ensureProtocol();
368
+ if (callback) initCallback = callback;
369
+ if ("mraid" === AD_PROTOCOL && isMraid()) {
370
+ if (mraid.getState() !== "ready" && "adcolony" !== AD_NETWORK) {
371
+ mraid.addEventListener("ready", startMraidProtocol);
372
+ } else {
373
+ startMraidProtocol();
374
+ }
375
+ } else if ("dapi" === AD_PROTOCOL && isDapi()) {
376
+ window.addEventListener("load", function() {
377
+ dapi.isReady() ? startDapiProtocol() : dapi.addEventListener("ready", startDapiProtocol);
378
+ });
379
+ } else {
380
+ startDefaultProtocol();
381
+ }
382
+ emitEvent("init");
383
+ isSDKInitialized = true;
384
+ }
385
+ /**
386
+ * Starts the playable ad experience.
387
+ * Should be called after all resources are loaded and first frame is rendered.
388
+ *
389
+ * @example
390
+ * // Call just after all resources are preloaded and first frame is rendered
391
+ * sdk.start();
392
+ *
393
+ * @fires start When the playable ad starts
394
+ * @fires resize When the ad container is initially sized
395
+ */
396
+ static start() {
397
+ if (_sdk.isStarted) return;
398
+ _sdk.isStarted = true;
399
+ emitEvent("start");
400
+ registerTouchHandlers();
401
+ if ("mintegral" === AD_NETWORK && isMintegral()) {
402
+ _sdk.resize();
403
+ handlePause();
404
+ window.gameReady && window.gameReady();
405
+ } else {
406
+ if ("tapjoy" === AD_NETWORK && isTapjoy()) {
407
+ window.TJ_API.setPlayableBuild({
408
+ orientation: this.isLandscape ? "landscape" : "portrait",
409
+ buildID: __BUILD_ID__
410
+ });
411
+ }
412
+ _sdk.resize();
413
+ }
414
+ }
415
+ /**
416
+ * Marks the playable ad as finished.
417
+ * This triggers network-specific completion handlers.
418
+ *
419
+ * @example
420
+ * // Call when game/experience is complete
421
+ * sdk.finish();
422
+ *
423
+ * @fires finish When the playable ad is marked as finished
424
+ */
425
+ static finish() {
426
+ _sdk.isFinished = true;
427
+ if ("tapjoy" === AD_NETWORK && isTapjoy()) {
428
+ finishTapjoy();
429
+ } else if ("mintegral" === AD_NETWORK && isMintegral()) {
430
+ window.gameEnd && window.gameEnd();
431
+ } else if ("vungle" === AD_NETWORK) {
432
+ parent.postMessage("complete", "*");
433
+ }
434
+ emitEvent("finish");
435
+ }
436
+ /**
437
+ * Triggers a retry/restart of the playable ad.
438
+ * Behavior varies by ad network.
439
+ *
440
+ * @example
441
+ * // Allow user to try again
442
+ * retryButton.onclick = () => sdk.retry();
443
+ *
444
+ * @fires retry When a retry is triggered
445
+ */
446
+ static retry() {
447
+ if ("mintegral" === AD_NETWORK && isMintegral()) {
448
+ window.gameRetry && window.gameRetry();
449
+ } else if ("nucleo" === AD_PROTOCOL && isNucleo()) {
450
+ NUC.trigger.tryAgain();
451
+ }
452
+ emitEvent("retry");
453
+ }
454
+ /**
455
+ * Triggers the install/download action for the advertised app.
456
+ * Handles different store opening methods across ad networks.
457
+ *
458
+ * @example
459
+ * // Call when user wants to install
460
+ * installButton.onclick = () => sdk.install();
461
+ *
462
+ * @fires finish If the ad hasn't been marked as finished
463
+ * @fires install When the install action is triggered
464
+ */
465
+ static install() {
466
+ if (!_sdk.isFinished) {
467
+ _sdk.isFinished = true;
468
+ let timeout = 0;
469
+ if ("tapjoy" === AD_NETWORK && isTapjoy()) {
470
+ finishTapjoy();
471
+ timeout = 300;
472
+ }
473
+ emitEvent("finish");
474
+ setTimeout(function() {
475
+ _sdk.install();
476
+ }, timeout);
477
+ return;
478
+ }
479
+ if (isInstallClicked) return;
480
+ isInstallClicked = true;
481
+ setTimeout(function() {
482
+ isInstallClicked = false;
483
+ }, 500);
484
+ emitEvent("install");
485
+ if ("mraid" === AD_PROTOCOL && isMraid()) {
486
+ mraid.openStoreUrl ? mraid.openStoreUrl() : mraid.open(destinationUrl);
487
+ } else if ("dapi" === AD_PROTOCOL && isDapi()) {
488
+ dapi.openStoreUrl();
489
+ } else if ("nucleo" === AD_PROTOCOL && isNucleo()) {
490
+ NUC.trigger.convert(destinationUrl);
491
+ } else if ("facebook" == AD_NETWORK && isFacebook()) {
492
+ FbPlayableAd.onCTAClick();
493
+ } else if ("vungle" == AD_NETWORK) {
494
+ parent.postMessage("download", "*");
495
+ } else if ("google" == AD_NETWORK && isGoogle()) {
496
+ ExitApi.exit();
497
+ } else if ("mintegral" === AD_NETWORK && isMintegral()) {
498
+ window.install && window.install();
499
+ } else if ("tapjoy" === AD_NETWORK && isTapjoy()) {
500
+ window.TJ_API.click();
501
+ } else if ("tiktok" === AD_NETWORK && isTikTok()) {
502
+ window.openAppStore();
503
+ } else {
504
+ window.open(destinationUrl);
505
+ }
506
+ }
507
+ /**
508
+ * Trigger force resize event
509
+ * Useful when container size changes need to be manually propagated.
510
+ *
511
+ * @example
512
+ * sdk.resize();
513
+ *
514
+ * @fires resize With current maxWidth and maxHeight
515
+ */
516
+ static resize() {
517
+ handleResize(_sdk.maxWidth, _sdk.maxHeight);
518
+ }
519
+ /**
520
+ * Forces the playable ad into a paused state.
521
+ *
522
+ * @example
523
+ * // Pause the experience
524
+ * pauseButton.onclick = () => sdk.pause();
525
+ *
526
+ * @fires pause When the ad enters paused state
527
+ */
528
+ static pause() {
529
+ if (!isForcePaused) {
530
+ isForcePaused = true;
531
+ handlePause();
532
+ }
533
+ }
534
+ /**
535
+ * Resumes the playable ad from a forced pause state.
536
+ * Only works if the ad was paused via sdk.pause().
537
+ *
538
+ * @example
539
+ * // Resume from pause
540
+ * resumeButton.onclick = () => sdk.resume();
541
+ *
542
+ * @fires resume When the ad resumes from pause
543
+ */
544
+ static resume() {
545
+ if (isForcePaused) {
546
+ isForcePaused = false;
547
+ handleResume();
548
+ }
549
+ }
550
+ /**
551
+ * Registers an event listener.
552
+ *
553
+ * @param event Name of the event to listen for
554
+ * @param fn Callback function to execute when event occurs
555
+ * @param context Optional 'this' context for the callback
556
+ *
557
+ * @example
558
+ * // Listen for user interactions
559
+ * sdk.on('interaction', (count) => {
560
+ * console.log(`User interaction #${count}`);
561
+ * });
562
+ *
563
+ * // Listen for resize with context
564
+ * sdk.on('resize', function(width, height) {
565
+ * this.updateLayout(width, height);
566
+ * }, gameInstance);
567
+ */
568
+ static on(event, fn, context) {
569
+ onEvent(event, fn, context);
570
+ }
571
+ /**
572
+ * Registers a one-time event listener that removes itself after execution.
573
+ *
574
+ * @param event Name of the event to listen for
575
+ * @param fn Callback function to execute when event occurs
576
+ * @param context Optional 'this' context for the callback
577
+ *
578
+ * @example
579
+ * // Listen for first interaction only
580
+ * sdk.once('interaction', () => {
581
+ * console.log('First user interaction occurred!');
582
+ * });
583
+ */
584
+ static once(event, fn, context) {
585
+ onEvent(event, fn, context, true);
586
+ }
587
+ /**
588
+ * Removes an event listener.
589
+ *
590
+ * @param event Name of the event to stop listening for
591
+ * @param fn Optional callback function to remove (if not provided, removes all listeners for the event)
592
+ * @param context Optional 'this' context to match when removing
593
+ *
594
+ * @example
595
+ * // Remove specific listener
596
+ * const handler = () => console.log('Interaction');
597
+ * sdk.off('interaction', handler);
598
+ *
599
+ * // Remove all listeners for an event
600
+ * sdk.off('interaction');
601
+ */
602
+ static off(event, fn, context) {
603
+ offEvent(event, fn, context);
604
+ }
605
+ };
606
+ /** Current version of the SDK */
607
+ _sdk.version = "1.0.0";
608
+ /** Current maximum width of the playable ad container in pixels */
609
+ _sdk.maxWidth = Math.floor(window.innerWidth);
610
+ /** Current maximum height of the playable ad container in pixels */
611
+ _sdk.maxHeight = Math.floor(window.innerHeight);
612
+ /** Indicates if the current orientation is landscape (width > height) */
613
+ _sdk.isLandscape = window.innerWidth > window.innerHeight;
614
+ /** Indicates if the Ad Network is ready and playable ad can be initialized */
615
+ _sdk.isReady = false;
616
+ /** Indicates if all playable ad resources are loaded and gameplay has started */
617
+ _sdk.isStarted = false;
618
+ /** Indicates if the playable ad is currently paused */
619
+ _sdk.isPaused = false;
620
+ /** Indicates if the playable ad has finished */
621
+ _sdk.isFinished = false;
622
+ /** Current volume level (0-1) */
623
+ _sdk.volume = 1;
624
+ /** Number of user interactions with the playable ad */
625
+ _sdk.interactions = 0;
626
+ var sdk = _sdk;
627
+ window.PlayableSDK = sdk;
628
+ // Annotate the CommonJS export names for ESM import in node:
629
+ 0 && (module.exports = {
630
+ sdk
631
+ });
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@smoud/playable-sdk",
3
+ "version": "1.0.0",
4
+ "description": "It's unified Playable SDK that supports MRAID, Google, Facebook, Vungle, and many more Ad Networks, simplifying playable ad development with a standardized interface for seamless cross-network compatibility.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "browser": "dist/iife/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/smoudjs/playable-sdk.git"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "defines.d.ts"
21
+ ],
22
+ "scripts": {
23
+ "build": "npx tsup src/index.ts --format esm,cjs,iife --out-dir dist --legacy-output --dts --clean",
24
+ "test": "jest"
25
+ },
26
+ "author": "Smoud",
27
+ "license": "MIT",
28
+ "devDependencies": {
29
+ "@types/jest": "^29.5.14",
30
+ "jest": "^29.7.0",
31
+ "jest-environment-jsdom": "^29.7.0",
32
+ "ts-jest": "^29.2.5",
33
+ "tsup": "^8.4.0",
34
+ "typescript": "^5.7.2"
35
+ },
36
+ "bugs": {
37
+ "mail": "peter.hutsul@gmail.com",
38
+ "url": "https://github.com/smoudjs/playable-sdk/issues"
39
+ },
40
+ "homepage": "https://github.com/smoudjs/playable-sdk",
41
+ "keywords": [
42
+ "playable",
43
+ "sdk",
44
+ "playable-sdk",
45
+ "PlayableSDK",
46
+ "playable-ads",
47
+ "html5",
48
+ "html5-playable",
49
+ "playable-ad-sdk",
50
+ "playable-ads-sdk",
51
+ "html5-playable-ads",
52
+ "interactive-ads",
53
+ "ads",
54
+ "ad-sdk",
55
+ "ad-network",
56
+ "ad-monetization",
57
+ "mraid",
58
+ "mraid-sdk",
59
+ "google-ads",
60
+ "facebook-playable",
61
+ "unity-ads",
62
+ "vungle",
63
+ "ironsource",
64
+ "mintegral",
65
+ "tiktok-ads",
66
+ "pangle-sdk",
67
+ "applovin",
68
+ "chartboost",
69
+ "adcolony",
70
+ "snapchat-ads",
71
+ "appreciate-ads",
72
+ "liftoff",
73
+ "mytarget",
74
+ "javascript-sdk",
75
+ "typescript-sdk",
76
+ "game-ad-sdk",
77
+ "html5-sdk",
78
+ "interactive-ads",
79
+ "playable-ads-engine"
80
+ ]
81
+ }