@aippy/runtime 0.2.1 → 0.2.3-dev.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.
@@ -1,4 +1,4 @@
1
- import { c as i, a as t, i as d, b as o, p as s, u as n } from "../useAudioContext-DaLkaQ8P.js";
1
+ import { c as i, a as t, i as d, b as o, p as s, u as n } from "../useAudioContext-BKgy28A1.js";
2
2
  export {
3
3
  i as createHiddenMediaElement,
4
4
  t as createHiddenVideoElement,
@@ -1,4 +1,4 @@
1
- import { A as d, E as v, c as _ } from "../errors-CDEBaBxB.js";
1
+ import { A as f, E as v, c as _ } from "../errors-CDEBaBxB.js";
2
2
  const o = {
3
3
  mode: "development",
4
4
  debug: !1,
@@ -22,7 +22,7 @@ function a(e) {
22
22
  }
23
23
  };
24
24
  }
25
- const s = "0.2.1", t = {
25
+ const s = "0.2.3-dev.0", t = {
26
26
  version: s
27
27
  }, i = t.version, c = "@aippy/runtime";
28
28
  function p() {
@@ -33,7 +33,7 @@ function p() {
33
33
  };
34
34
  }
35
35
  export {
36
- d as AippyRuntimeError,
36
+ f as AippyRuntimeError,
37
37
  o as DEFAULT_CONFIG,
38
38
  v as ERROR_CODES,
39
39
  c as SDK_NAME,
@@ -1,40 +1,73 @@
1
- import { DEFAULT_CONFIG as o, SDK_NAME as r, VERSION as t, getConfigFromEnv as s, getVersionInfo as i, mergeConfig as m } from "../core/index.js";
2
- import { A as p, E as c, c as f } from "../errors-CDEBaBxB.js";
3
- import { CameraAPI as A, FileSystemAPI as E, GeolocationAPI as l, SensorsAPI as S, camera as u, fileSystem as x, geolocation as I, sensors as P, vibrate as C } from "../device/index.js";
4
- import { c as R, a as y, P as D, b as M, p as O, d as b } from "../pwa-DPd78fwK.js";
5
- import { a as v, b as w } from "../useTweaks-Bc26i-fJ.js";
6
- import { c as T, a as V, i as _, b as k, p as G, u as H } from "../useAudioContext-DaLkaQ8P.js";
1
+ import { DEFAULT_CONFIG as p, SDK_NAME as d, VERSION as m, getConfigFromEnv as c, getVersionInfo as f, mergeConfig as l } from "../core/index.js";
2
+ import { A as g, E as w, c as A } from "../errors-CDEBaBxB.js";
3
+ import { CameraAPI as u, FileSystemAPI as S, GeolocationAPI as x, SensorsAPI as b, camera as I, fileSystem as P, geolocation as v, sensors as C, vibrate as M } from "../device/index.js";
4
+ import { c as O, a as R, P as D, b as F, p as _, d as G } from "../pwa-8DGmPqLV.js";
5
+ import { a as k, b as H } from "../useTweaks-QxMRmg7i.js";
6
+ import { c as h, a as T, i as U, b as $, p as J, u as K } from "../useAudioContext-BKgy28A1.js";
7
+ function r(e) {
8
+ try {
9
+ if (window.parent && window.parent !== window) {
10
+ const a = {
11
+ __aippyGame: !0,
12
+ payload: e
13
+ };
14
+ window.parent.postMessage(a, "*");
15
+ }
16
+ const o = window.webkit?.messageHandlers?.aippyListener;
17
+ o && o.postMessage({
18
+ command: "game.event",
19
+ parameters: JSON.stringify(e)
20
+ });
21
+ } catch (o) {
22
+ console.warn("[Aippy Leaderboard] Failed to send game event:", o);
23
+ }
24
+ }
25
+ function t(e) {
26
+ r({
27
+ type: "score",
28
+ score: e
29
+ }), console.log(`[Aippy Leaderboard] Score reported: ${e}`);
30
+ }
31
+ function s(e, o) {
32
+ const a = {
33
+ type: e,
34
+ ...o
35
+ };
36
+ r(a), console.log(`[Aippy Leaderboard] Event sent: ${e}`, o);
37
+ }
7
38
  export {
8
- p as AippyRuntimeError,
9
- A as CameraAPI,
10
- o as DEFAULT_CONFIG,
11
- c as ERROR_CODES,
12
- E as FileSystemAPI,
13
- l as GeolocationAPI,
14
- R as PWAUtils,
15
- y as PerformanceMonitor,
39
+ g as AippyRuntimeError,
40
+ u as CameraAPI,
41
+ p as DEFAULT_CONFIG,
42
+ w as ERROR_CODES,
43
+ S as FileSystemAPI,
44
+ x as GeolocationAPI,
45
+ O as PWAUtils,
46
+ R as PerformanceMonitor,
16
47
  D as PlatformDetector,
17
- r as SDK_NAME,
18
- S as SensorsAPI,
19
- t as VERSION,
20
- v as aippyTweaks,
21
- w as aippyTweaksRuntime,
22
- u as camera,
23
- f as createError,
24
- T as createHiddenMediaElement,
25
- V as createHiddenVideoElement,
26
- x as fileSystem,
27
- I as geolocation,
28
- s as getConfigFromEnv,
29
- i as getVersionInfo,
30
- _ as isIOSDevice,
31
- k as isMediaStreamAudioSupported,
32
- m as mergeConfig,
33
- G as patchAudioContext,
34
- M as performanceMonitor,
35
- O as platform,
36
- b as pwa,
37
- P as sensors,
38
- H as useAudioContext,
39
- C as vibrate
48
+ d as SDK_NAME,
49
+ b as SensorsAPI,
50
+ m as VERSION,
51
+ k as aippyTweaks,
52
+ H as aippyTweaksRuntime,
53
+ I as camera,
54
+ A as createError,
55
+ h as createHiddenMediaElement,
56
+ T as createHiddenVideoElement,
57
+ P as fileSystem,
58
+ v as geolocation,
59
+ c as getConfigFromEnv,
60
+ f as getVersionInfo,
61
+ U as isIOSDevice,
62
+ $ as isMediaStreamAudioSupported,
63
+ l as mergeConfig,
64
+ J as patchAudioContext,
65
+ F as performanceMonitor,
66
+ _ as platform,
67
+ G as pwa,
68
+ t as reportScore,
69
+ s as sendEvent,
70
+ C as sensors,
71
+ K as useAudioContext,
72
+ M as vibrate
40
73
  };
package/dist/index.d.ts CHANGED
@@ -3,3 +3,4 @@ export * from './device';
3
3
  export * from './utils';
4
4
  export * from './tweaks';
5
5
  export * from './audio';
6
+ export * from './leaderboard';
@@ -0,0 +1,2 @@
1
+ export * from './report';
2
+ export * from './types';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Leaderboard reporting functionality for score submission and game events
3
+ */
4
+ /**
5
+ * Report game score to parent window or iOS app
6
+ * @param score - The score value to report
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * reportScore(100);
11
+ * reportScore(1500);
12
+ * ```
13
+ */
14
+ export declare function reportScore(score: number): void;
15
+ /**
16
+ * Send a custom game event
17
+ * @param eventType - The event type
18
+ * @param data - Additional event data
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * sendEvent('level-complete', { level: 5, time: 120 });
23
+ * ```
24
+ */
25
+ export declare function sendEvent(eventType: string, data?: Record<string, unknown>): void;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Leaderboard SDK type definitions
3
+ */
4
+ /**
5
+ * Score report payload
6
+ */
7
+ export interface ScorePayload {
8
+ /** Message type, fixed as 'score' */
9
+ type: 'score';
10
+ /** The score value */
11
+ score: number;
12
+ /** Score unit (e.g., 'points', 'coins') */
13
+ unit?: string;
14
+ /** Whether bigger score is better for leaderboard ranking */
15
+ 'bigger-is-better'?: boolean;
16
+ }
17
+ /**
18
+ * Generic game event payload
19
+ */
20
+ export interface GameEventPayload {
21
+ /** Event type */
22
+ type: string;
23
+ /** Additional event data */
24
+ [key: string]: unknown;
25
+ }
26
+ /**
27
+ * Message format for postMessage communication
28
+ */
29
+ export interface AippyGameMessage {
30
+ /** Message identifier */
31
+ __aippyGame: true;
32
+ /** Event payload */
33
+ payload: ScorePayload | GameEventPayload;
34
+ }
@@ -1,6 +1,6 @@
1
1
  var u = Object.defineProperty;
2
- var f = (o, e, r) => e in o ? u(o, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : o[e] = r;
3
- var l = (o, e, r) => f(o, typeof e != "symbol" ? e + "" : e, r);
2
+ var f = (n, e, r) => e in n ? u(n, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : n[e] = r;
3
+ var l = (n, e, r) => f(n, typeof e != "symbol" ? e + "" : e, r);
4
4
  import { UAParser as m } from "ua-parser-js";
5
5
  class p {
6
6
  constructor() {
@@ -11,14 +11,14 @@ class p {
11
11
  * Get platform information
12
12
  */
13
13
  getPlatformInfo() {
14
- const e = this.parser.getResult(), r = this.normalizePlatformName(e.os.name), t = this.normalizeBrowserName(e.browser.name), n = this.isMobileDevice(), i = !n;
14
+ const e = this.parser.getResult(), r = this.normalizePlatformName(e.os.name), t = this.normalizeBrowserName(e.browser.name), o = this.isMobileDevice(), a = !o;
15
15
  return {
16
16
  name: r,
17
17
  version: e.os.version,
18
18
  browser: t,
19
19
  browserVersion: e.browser.version,
20
- isMobile: n,
21
- isDesktop: i
20
+ isMobile: o,
21
+ isDesktop: a
22
22
  };
23
23
  }
24
24
  /**
@@ -99,25 +99,25 @@ class w {
99
99
  r && (e.fcp = r.startTime);
100
100
  const t = performance.getEntriesByType("largest-contentful-paint");
101
101
  if (t.length > 0) {
102
- const s = t[t.length - 1];
103
- e.lcp = s.startTime;
102
+ const i = t[t.length - 1];
103
+ e.lcp = i.startTime;
104
104
  }
105
- const n = performance.getEntriesByType("first-input");
106
- if (n.length > 0) {
107
- const s = n[0];
108
- e.fid = s.processingStart - s.startTime;
105
+ const o = performance.getEntriesByType("first-input");
106
+ if (o.length > 0) {
107
+ const i = o[0];
108
+ e.fid = i.processingStart - i.startTime;
109
109
  }
110
- const i = performance.getEntriesByType("layout-shift");
111
- if (i.length > 0) {
112
- let s = 0;
113
- for (const d of i) {
110
+ const a = performance.getEntriesByType("layout-shift");
111
+ if (a.length > 0) {
112
+ let i = 0;
113
+ for (const d of a) {
114
114
  const c = d;
115
- c.hadRecentInput || (s += c.value);
115
+ c.hadRecentInput || (i += c.value);
116
116
  }
117
- e.cls = s;
117
+ e.cls = i;
118
118
  }
119
- const a = this.calculateTTI();
120
- a && (e.tti = a);
119
+ const s = this.calculateTTI();
120
+ s && (e.tti = s);
121
121
  } catch (r) {
122
122
  console.warn("Failed to get Core Web Vitals:", r);
123
123
  }
@@ -158,15 +158,15 @@ class w {
158
158
  * Measure function execution time
159
159
  */
160
160
  measureFunction(e, r) {
161
- const t = performance.now(), n = e(), i = performance.now();
162
- return r && (performance.mark(`${r}-start`), performance.mark(`${r}-end`), performance.measure(r, `${r}-start`, `${r}-end`)), console.log(`Function ${r || "anonymous"} took ${i - t} milliseconds`), n;
161
+ const t = e();
162
+ return r && (performance.mark(`${r}-start`), performance.mark(`${r}-end`), performance.measure(r, `${r}-start`, `${r}-end`)), t;
163
163
  }
164
164
  /**
165
165
  * Measure async function execution time
166
166
  */
167
167
  async measureAsyncFunction(e, r) {
168
- const t = performance.now(), n = await e(), i = performance.now();
169
- return r && (performance.mark(`${r}-start`), performance.mark(`${r}-end`), performance.measure(r, `${r}-start`, `${r}-end`)), console.log(`Async function ${r || "anonymous"} took ${i - t} milliseconds`), n;
168
+ const t = await e();
169
+ return r && (performance.mark(`${r}-start`), performance.mark(`${r}-end`), performance.measure(r, `${r}-start`, `${r}-end`)), t;
170
170
  }
171
171
  /**
172
172
  * Get memory usage (if available)
@@ -240,8 +240,7 @@ class g {
240
240
  if (!("serviceWorker" in navigator))
241
241
  return console.warn("Service Worker not supported"), null;
242
242
  try {
243
- const r = await navigator.serviceWorker.register(e);
244
- return console.log("Service Worker registered:", r), r;
243
+ return await navigator.serviceWorker.register(e);
245
244
  } catch (r) {
246
245
  return console.error("Service Worker registration failed:", r), null;
247
246
  }
@@ -1,4 +1,4 @@
1
- import { a as e, b as s } from "../useTweaks-Bc26i-fJ.js";
1
+ import { a as e, b as s } from "../useTweaks-QxMRmg7i.js";
2
2
  export {
3
3
  e as aippyTweaks,
4
4
  s as aippyTweaksRuntime
@@ -1,8 +1,8 @@
1
- var v = Object.defineProperty;
2
- var S = (e, t, n) => t in e ? v(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var s = (e, t, n) => S(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { useState as k, useRef as w, useEffect as p } from "react";
5
- function T() {
1
+ var b = Object.defineProperty;
2
+ var w = (e, t, n) => t in e ? b(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var s = (e, t, n) => w(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import { useState as k, useRef as T, useEffect as p } from "react";
5
+ function E() {
6
6
  const e = navigator.userAgent;
7
7
  return !!(/iPad|iPhone|iPod/.test(e) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
8
8
  }
@@ -16,15 +16,15 @@ function P() {
16
16
  return !1;
17
17
  }
18
18
  }
19
- function D(e = "video", t = !1) {
19
+ function v(e = "video", t = !1) {
20
20
  const n = document.createElement(e);
21
21
  return n.muted = !1, n.autoplay = !0, e === "video" && (n.playsInline = !0), t ? n.style.cssText = "position:fixed;bottom:10px;right:10px;width:200px;background:#ff0000;z-index:9999;" : n.style.cssText = "position:fixed;width:1px;height:1px;opacity:0;pointer-events:none;", n;
22
22
  }
23
- function M(e = !1) {
24
- return D("video", e);
23
+ function C(e = !1) {
24
+ return v("video", e);
25
25
  }
26
- class E {
27
- constructor(t, n, i, a = !1) {
26
+ class I {
27
+ constructor(t, n, i, o = !1) {
28
28
  s(this, "analyser");
29
29
  s(this, "dataArray");
30
30
  s(this, "rafId", null);
@@ -42,7 +42,7 @@ class E {
42
42
  const t = performance.now();
43
43
  t - this.lastCheckTime >= this.checkInterval && (this.lastCheckTime = t, this.getAudioLevel() < this.silenceThreshold ? this.silenceStartTime === 0 ? this.silenceStartTime = t : t - this.silenceStartTime >= this.silenceDuration && !this.isPaused && this.pauseMedia() : (this.silenceStartTime = 0, this.isPaused && this.resumeMedia())), this.rafId = requestAnimationFrame(this.check);
44
44
  });
45
- this.audioContext = t, this.mediaElement = n, this.silenceThreshold = i.silenceThreshold, this.silenceDuration = i.silenceDuration, this.checkInterval = i.checkInterval, this.debug = a, this.analyser = t.createAnalyser(), this.analyser.fftSize = 512, this.analyser.smoothingTimeConstant = 0.3, this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
45
+ this.audioContext = t, this.mediaElement = n, this.silenceThreshold = i.silenceThreshold, this.silenceDuration = i.silenceDuration, this.checkInterval = i.checkInterval, this.debug = o, this.analyser = t.createAnalyser(), this.analyser.fftSize = 512, this.analyser.smoothingTimeConstant = 0.3, this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
46
46
  }
47
47
  /**
48
48
  * Connect the detector to the audio stream
@@ -54,13 +54,13 @@ class E {
54
54
  * Start monitoring audio levels
55
55
  */
56
56
  start() {
57
- this.rafId === null && (this.lastCheckTime = performance.now(), this.check(), this.debug && console.log("[AudioSilenceDetector] Started monitoring"));
57
+ this.rafId === null && (this.lastCheckTime = performance.now(), this.check());
58
58
  }
59
59
  /**
60
60
  * Stop monitoring
61
61
  */
62
62
  stop() {
63
- this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null), this.debug && console.log("[AudioSilenceDetector] Stopped monitoring");
63
+ this.rafId !== null && (cancelAnimationFrame(this.rafId), this.rafId = null);
64
64
  }
65
65
  /**
66
66
  * Cleanup resources
@@ -85,7 +85,7 @@ class E {
85
85
  */
86
86
  pauseMedia() {
87
87
  try {
88
- this.mediaElement.pause(), this.isPaused = !0, this.debug && console.log("[AudioSilenceDetector] Paused media element (silence detected)");
88
+ this.mediaElement.pause(), this.isPaused = !0;
89
89
  } catch (t) {
90
90
  console.error("[AudioSilenceDetector] Failed to pause:", t);
91
91
  }
@@ -97,17 +97,17 @@ class E {
97
97
  try {
98
98
  this.audioContext.state === "running" && this.mediaElement.play().catch((t) => {
99
99
  this.debug && console.warn("[AudioSilenceDetector] Failed to resume:", t);
100
- }), this.isPaused = !1, this.debug && console.log("[AudioSilenceDetector] Resumed media element (audio detected)");
100
+ }), this.isPaused = !1;
101
101
  } catch (t) {
102
102
  console.error("[AudioSilenceDetector] Failed to resume:", t);
103
103
  }
104
104
  }
105
105
  }
106
- function x(e, t = {}) {
106
+ function S(e, t = {}) {
107
107
  const {
108
108
  forceEnable: n = !1,
109
109
  autoCleanup: i = !0,
110
- debug: a = !1,
110
+ debug: o = !1,
111
111
  mediaElementType: m = "video",
112
112
  autoPause: d = {}
113
113
  } = t, h = {
@@ -116,7 +116,7 @@ function x(e, t = {}) {
116
116
  silenceDuration: d.silenceDuration ?? 50,
117
117
  checkInterval: d.checkInterval ?? 16
118
118
  };
119
- if (!(n || T()))
119
+ if (!(n || E()))
120
120
  return Object.assign(e, {
121
121
  unlock: async () => {
122
122
  e.state === "suspended" && await e.resume();
@@ -136,16 +136,16 @@ function x(e, t = {}) {
136
136
  isPatched: !1,
137
137
  originalDestination: e.destination
138
138
  });
139
- const c = e.destination, g = e.createMediaStreamDestination(), f = e.createGain();
140
- f.gain.value = 1, f.connect(g);
141
- const l = D(m, a);
142
- l.srcObject = g.stream, document.body.appendChild(l);
139
+ const c = e.destination, y = e.createMediaStreamDestination(), f = e.createGain();
140
+ f.gain.value = 1, f.connect(y);
141
+ const l = v(m, o);
142
+ l.srcObject = y.stream, document.body.appendChild(l);
143
143
  let u = null;
144
- h.enabled && (u = new E(
144
+ h.enabled && (u = new I(
145
145
  e,
146
146
  l,
147
147
  h,
148
- a
148
+ o
149
149
  ), u.connect(f)), Object.defineProperty(e, "destination", {
150
150
  get: () => f,
151
151
  enumerable: !0,
@@ -154,37 +154,37 @@ function x(e, t = {}) {
154
154
  get: () => c.maxChannelCount,
155
155
  enumerable: !0
156
156
  });
157
- let y = !1;
158
- const b = async () => {
159
- if (!y)
157
+ let g = !1;
158
+ const D = async () => {
159
+ if (!g)
160
160
  try {
161
- await l.play(), e.state === "suspended" && await e.resume(), u && u.start(), y = !0, a && console.log("[AudioContext] iOS unlock successful");
162
- } catch (o) {
163
- throw o instanceof DOMException && o.name === "NotAllowedError" ? (a && console.log("[AudioContext] Unlock requires user interaction"), o) : (console.error("[AudioContext] Unlock failed:", o), o);
161
+ await l.play(), e.state === "suspended" && await e.resume(), u && u.start(), g = !0;
162
+ } catch (a) {
163
+ throw a instanceof DOMException && a.name === "NotAllowedError" || console.error("[AudioContext] Unlock failed:", a), a;
164
164
  }
165
165
  }, A = () => {
166
166
  try {
167
- u && (u.dispose(), u = null), l.pause(), l.srcObject = null, l.remove(), a && console.log("[AudioContext] Cleanup completed");
168
- } catch (o) {
169
- console.error("[AudioContext] Cleanup error:", o);
167
+ u && (u.dispose(), u = null), l.pause(), l.srcObject = null, l.remove();
168
+ } catch (a) {
169
+ console.error("[AudioContext] Cleanup error:", a);
170
170
  }
171
171
  };
172
172
  if (i) {
173
- const o = e.close.bind(e);
174
- e.close = async () => (A(), o());
173
+ const a = e.close.bind(e);
174
+ e.close = async () => (A(), a());
175
175
  }
176
176
  return Object.assign(e, {
177
- unlock: b,
177
+ unlock: D,
178
178
  cleanup: A,
179
179
  isPatched: !0,
180
180
  originalDestination: c
181
181
  });
182
182
  }
183
183
  function O(e = {}) {
184
- const { autoUnlock: t = !0, ...n } = e, [i, a] = k(null), [m, d] = k(!1), h = w(null);
184
+ const { autoUnlock: t = !0, ...n } = e, [i, o] = k(null), [m, d] = k(!1), h = T(null);
185
185
  return p(() => {
186
- const r = new AudioContext(), c = x(r, n);
187
- return a(c), () => {
186
+ const r = new AudioContext(), c = S(r, n);
187
+ return o(c), () => {
188
188
  c.cleanup(), c.close();
189
189
  };
190
190
  }, []), p(() => {
@@ -214,10 +214,10 @@ function O(e = {}) {
214
214
  };
215
215
  }
216
216
  export {
217
- M as a,
217
+ C as a,
218
218
  P as b,
219
- D as c,
220
- T as i,
221
- x as p,
219
+ v as c,
220
+ E as i,
221
+ S as p,
222
222
  O as u
223
223
  };
@@ -0,0 +1,182 @@
1
+ var b = Object.defineProperty;
2
+ var g = (n, e, t) => e in n ? b(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
+ var r = (n, e, t) => g(n, typeof e != "symbol" ? e + "" : e, t);
4
+ import { useReducer as v, useEffect as m } from "react";
5
+ class T {
6
+ constructor(e) {
7
+ r(this, "cancelled", !1);
8
+ this.cancelFn = e;
9
+ }
10
+ cancel() {
11
+ this.cancelled || (this.cancelled = !0, this.cancelFn?.());
12
+ }
13
+ get isCancelled() {
14
+ return this.cancelled;
15
+ }
16
+ }
17
+ class k {
18
+ constructor() {
19
+ r(this, "listeners", []);
20
+ }
21
+ send(e) {
22
+ this.listeners.forEach((t) => t(e));
23
+ }
24
+ subscribe(e) {
25
+ return this.listeners.push(e), new T(() => {
26
+ const t = this.listeners.indexOf(e);
27
+ t > -1 && this.listeners.splice(t, 1);
28
+ });
29
+ }
30
+ }
31
+ class C {
32
+ constructor(e, t) {
33
+ r(this, "values", {});
34
+ r(this, "subject", new k());
35
+ r(this, "observable");
36
+ this.observable = e;
37
+ for (const [i, a] of Object.entries(t))
38
+ this.values[i] = a.value;
39
+ this.observable.subscribe((i) => {
40
+ if (i && i.values)
41
+ for (const [a, s] of Object.entries(i.values)) {
42
+ let o = s;
43
+ if (this.values[a] !== void 0) {
44
+ const c = typeof this.values[a];
45
+ c === "number" && typeof s == "string" ? o = parseFloat(s) : c === "boolean" && typeof s != "boolean" && (o = s === "true" || s === !0);
46
+ }
47
+ this.values[a] !== o && (this.values[a] = o, this.subject.send(a));
48
+ }
49
+ });
50
+ }
51
+ getValue(e) {
52
+ const t = this.values[e];
53
+ if (t === void 0)
54
+ throw new Error(`Tweak key not found in values: ${e}`);
55
+ return t;
56
+ }
57
+ // React Hook integration
58
+ useState(e) {
59
+ const [t, i] = v(() => this.getValue(e), this.getValue(e));
60
+ return m(() => {
61
+ const a = this.subject.subscribe((s) => {
62
+ s === e && i();
63
+ });
64
+ return () => {
65
+ a.cancel();
66
+ };
67
+ }, [e]), t;
68
+ }
69
+ }
70
+ class I {
71
+ constructor() {
72
+ r(this, "tweaksInstance", null);
73
+ r(this, "tweaksDidWarn", !1);
74
+ r(this, "updateCallback");
75
+ // Store update callback function
76
+ r(this, "originalConfig");
77
+ }
78
+ // Store original config for merging
79
+ tweaks(e) {
80
+ if (this.tweaksInstance)
81
+ return this.tweaksDidWarn || (this.tweaksDidWarn = !0, console.warn("⚠️ [Aippy Tweaks] tweaks() is expected to only be called once, returning previous value")), this.tweaksInstance;
82
+ this.originalConfig = { ...e };
83
+ const t = new k(), i = new C(t, e), a = {};
84
+ for (const s of Object.keys(e))
85
+ a[s] = {
86
+ useState: () => i.useState(s)
87
+ };
88
+ return this.tweaksInstance = a, typeof window < "u" && window.aippyTweaksRuntime && (window.aippyTweaksRuntime.tweaksInstance = a), this.initializeExternalCommunication(e, (s) => {
89
+ t.send(s);
90
+ }), a;
91
+ }
92
+ initializeExternalCommunication(e, t) {
93
+ this.updateCallback = t;
94
+ const i = window.webkit?.messageHandlers?.aippyListener;
95
+ if (i)
96
+ try {
97
+ const s = {
98
+ command: "tweaks.initialize",
99
+ parameters: JSON.stringify(e)
100
+ };
101
+ i.postMessage(s);
102
+ } catch (s) {
103
+ console.warn("❌ [Aippy Tweaks] Failed to send tweaks config to iOS app:", s);
104
+ }
105
+ if (window.parent && window.parent !== window)
106
+ try {
107
+ const s = {
108
+ type: "tweaks-initialize",
109
+ config: JSON.stringify(e)
110
+ };
111
+ window.parent.postMessage(s, "*");
112
+ const o = {
113
+ type: "aippy-tweaks-ready",
114
+ aippyTweaksRuntime: {
115
+ tweaks: window.aippyTweaksRuntime?.tweaks,
116
+ tweaksInstance: window.aippyTweaksRuntime?.tweaksInstance
117
+ }
118
+ };
119
+ window.parent.postMessage(o, "*");
120
+ } catch (s) {
121
+ console.warn("❌ [Aippy Tweaks] Failed to send to parent window:", s);
122
+ }
123
+ const a = (s) => {
124
+ s.data && s.data.type === "tweaks-update" && t(s.data);
125
+ };
126
+ window.addEventListener("message", a);
127
+ }
128
+ // Process native data updates - Public method for external calls
129
+ processNativeData(e) {
130
+ if (!this.tweaksInstance) {
131
+ console.warn("⚠️ [Aippy Tweaks] processNativeData called but no tweaks instance exists");
132
+ return;
133
+ }
134
+ if (!this.updateCallback) {
135
+ console.warn("⚠️ [Aippy Tweaks] processNativeData called but no update callback available");
136
+ return;
137
+ }
138
+ try {
139
+ if (!e || typeof e != "object") {
140
+ console.warn("⚠️ [Aippy Tweaks] Invalid data type received from native:", typeof e);
141
+ return;
142
+ }
143
+ if (!this.originalConfig) {
144
+ console.warn("⚠️ [Aippy Tweaks] No original config available for merging");
145
+ return;
146
+ }
147
+ const t = {}, i = {};
148
+ let a = 0;
149
+ for (const [o, c] of Object.entries(e))
150
+ if (c && typeof c == "object" && "value" in c) {
151
+ const p = c, u = this.originalConfig[o];
152
+ if (!u) {
153
+ console.warn(`⚠️ [Aippy Tweaks] Key "${o}" not found in original config, skipping`);
154
+ continue;
155
+ }
156
+ const h = /* @__PURE__ */ new Set(["tweakKey", "valueBefore", "tweaksType", "editType"]), d = { ...u };
157
+ for (const [f, l] of Object.entries(p))
158
+ h.has(f) || l != null && (d[f] = l);
159
+ i[o] = d, t[o] = p.value, a++;
160
+ }
161
+ if (a === 0) {
162
+ console.warn("⚠️ [Aippy Tweaks] No valid values found in iOS data:", e);
163
+ return;
164
+ }
165
+ const s = {
166
+ type: "tweaks-update",
167
+ values: t
168
+ };
169
+ this.updateCallback(s);
170
+ } catch (t) {
171
+ console.error("❌ [Aippy Tweaks] Error processing native data:", t);
172
+ }
173
+ }
174
+ }
175
+ const w = new I(), y = {
176
+ tweaks: (n) => w.tweaks(n)
177
+ }, N = y.tweaks;
178
+ typeof window < "u" && (window.aippyTweaksRuntime = y, window.processNativeData = w.processNativeData.bind(w));
179
+ export {
180
+ N as a,
181
+ y as b
182
+ };
@@ -1,4 +1,4 @@
1
- import { c as r, a as t, P as e, b as s, p as f, d as m } from "../pwa-DPd78fwK.js";
1
+ import { c as r, a as t, P as e, b as s, p as f, d as m } from "../pwa-8DGmPqLV.js";
2
2
  export {
3
3
  r as PWAUtils,
4
4
  t as PerformanceMonitor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aippy/runtime",
3
- "version": "0.2.1",
3
+ "version": "0.2.3-dev.0",
4
4
  "description": "Aippy Runtime SDK - Runtime SDK for Aippy projects",
5
5
  "private": false,
6
6
  "type": "module",
@@ -31,6 +31,10 @@
31
31
  "./audio": {
32
32
  "import": "./dist/audio/index.js",
33
33
  "types": "./dist/audio/index.d.ts"
34
+ },
35
+ "./leaderboard": {
36
+ "import": "./dist/leaderboard/index.js",
37
+ "types": "./dist/leaderboard/index.d.ts"
34
38
  }
35
39
  },
36
40
  "files": [
@@ -88,13 +92,13 @@
88
92
  "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
89
93
  "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
90
94
  "clean": "rm -rf dist",
91
- "publish:patch": "pnpm version patch && pnpm publish --no-git-checks",
92
- "publish:minor": "pnpm version minor && pnpm publish --no-git-checks",
93
- "publish:major": "pnpm version major && pnpm publish --no-git-checks",
94
- "publish:alpha": "pnpm version prerelease --preid=alpha && pnpm publish --tag alpha --no-git-checks",
95
- "publish:beta": "pnpm version prerelease --preid=beta && pnpm publish --tag beta --no-git-checks",
96
- "publish:rc": "pnpm version prerelease --preid=rc && pnpm publish --tag rc --no-git-checks",
97
- "publish:dev": "pnpm version prerelease --preid=dev && pnpm publish --tag dev --no-git-checks",
95
+ "publish:patch": "pnpm prepublishOnly && pnpm version patch && pnpm publish --no-git-checks",
96
+ "publish:minor": "pnpm prepublishOnly && pnpm version minor && pnpm publish --no-git-checks",
97
+ "publish:major": "pnpm prepublishOnly && pnpm version major && pnpm publish --no-git-checks",
98
+ "publish:alpha": "pnpm prepublishOnly && pnpm version prerelease --preid=alpha && pnpm publish --tag alpha --no-git-checks",
99
+ "publish:beta": "pnpm prepublishOnly && pnpm version prerelease --preid=beta && pnpm publish --tag beta --no-git-checks",
100
+ "publish:rc": "pnpm prepublishOnly && pnpm version prerelease --preid=rc && pnpm publish --tag rc --no-git-checks",
101
+ "publish:dev": "pnpm prepublishOnly && pnpm version prerelease --preid=dev && pnpm publish --tag dev --no-git-checks",
98
102
  "audit": "pnpm audit --audit-level moderate",
99
103
  "audit:fix": "pnpm audit --fix",
100
104
  "security:check": "pnpm audit && pnpm outdated",
@@ -1,195 +0,0 @@
1
- var h = Object.defineProperty;
2
- var b = (l, e, t) => e in l ? h(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
- var c = (l, e, t) => b(l, typeof e != "symbol" ? e + "" : e, t);
4
- import { useReducer as v, useEffect as T } from "react";
5
- class m {
6
- constructor(e) {
7
- c(this, "cancelled", !1);
8
- this.cancelFn = e;
9
- }
10
- cancel() {
11
- this.cancelled || (this.cancelled = !0, this.cancelFn?.());
12
- }
13
- get isCancelled() {
14
- return this.cancelled;
15
- }
16
- }
17
- class y {
18
- constructor() {
19
- c(this, "listeners", []);
20
- }
21
- send(e) {
22
- this.listeners.forEach((t) => t(e));
23
- }
24
- subscribe(e) {
25
- return this.listeners.push(e), new m(() => {
26
- const t = this.listeners.indexOf(e);
27
- t > -1 && this.listeners.splice(t, 1);
28
- });
29
- }
30
- }
31
- class A {
32
- constructor(e, t) {
33
- c(this, "values", {});
34
- c(this, "subject", new y());
35
- c(this, "observable");
36
- this.observable = e;
37
- for (const [n, a] of Object.entries(t))
38
- this.values[n] = a.value;
39
- this.observable.subscribe((n) => {
40
- if (n && n.values) {
41
- console.log("🔄 [Aippy Tweaks] Processing external update:", n.values);
42
- const a = [];
43
- for (const [s, i] of Object.entries(n.values)) {
44
- let o = i;
45
- if (this.values[s] !== void 0) {
46
- const r = typeof this.values[s];
47
- r === "number" && typeof i == "string" ? o = parseFloat(i) : r === "boolean" && typeof i != "boolean" && (o = i === "true" || i === !0);
48
- }
49
- if (this.values[s] !== o) {
50
- const r = this.values[s];
51
- this.values[s] = o, this.subject.send(s), a.push(s), console.log(`📝 [Aippy Tweaks] Updated ${s}: ${r} → ${o} (type: ${typeof o})`);
52
- }
53
- }
54
- a.length > 0 ? console.log(`✨ [Aippy Tweaks] Successfully updated ${a.length} tweak(s):`, a) : console.log("💡 [Aippy Tweaks] No values changed in this update");
55
- }
56
- });
57
- }
58
- getValue(e) {
59
- const t = this.values[e];
60
- if (t === void 0)
61
- throw new Error(`Tweak key not found in values: ${e}`);
62
- return t;
63
- }
64
- // React Hook integration
65
- useState(e) {
66
- const [t, n] = v(() => this.getValue(e), this.getValue(e));
67
- return T(() => {
68
- const a = this.subject.subscribe((s) => {
69
- s === e && n();
70
- });
71
- return () => {
72
- a.cancel();
73
- };
74
- }, [e]), t;
75
- }
76
- }
77
- class S {
78
- constructor() {
79
- c(this, "tweaksInstance", null);
80
- c(this, "tweaksDidWarn", !1);
81
- c(this, "updateCallback");
82
- // Store update callback function
83
- c(this, "originalConfig");
84
- }
85
- // Store original config for merging
86
- tweaks(e) {
87
- if (this.tweaksInstance)
88
- return this.tweaksDidWarn || (this.tweaksDidWarn = !0, console.warn("⚠️ [Aippy Tweaks] tweaks() is expected to only be called once, returning previous value")), this.tweaksInstance;
89
- console.log("🚀 [Aippy Tweaks] Creating new tweaks runtime instance"), this.originalConfig = { ...e };
90
- const t = new y(), n = new A(t, e), a = {};
91
- for (const s of Object.keys(e))
92
- a[s] = {
93
- useState: () => n.useState(s)
94
- };
95
- return this.tweaksInstance = a, console.log("📋 [Aippy Tweaks] Created tweaks instance with keys:", Object.keys(e)), typeof window < "u" && window.aippyTweaksRuntime && (window.aippyTweaksRuntime.tweaksInstance = a, console.log("🌐 [Aippy Tweaks] Exposed tweaksInstance to window.aippyTweaksRuntime.tweaksInstance")), this.initializeExternalCommunication(e, (s) => {
96
- t.send(s);
97
- }), a;
98
- }
99
- initializeExternalCommunication(e, t) {
100
- this.updateCallback = t, console.log("🎛️ [Aippy Tweaks] Initializing tweaks with config:", e), console.log("🎛️ [Aippy Tweaks] Total tweaks count:", Object.keys(e).length);
101
- const n = window.webkit?.messageHandlers?.aippyListener;
102
- if (n)
103
- try {
104
- const s = {
105
- command: "tweaks.initialize",
106
- parameters: JSON.stringify(e)
107
- };
108
- n.postMessage(s), console.log("✅ [Aippy Tweaks] Successfully sent tweaks config to iOS app via aippyListener"), console.log("📤 [Aippy Tweaks] Sent data:", s);
109
- } catch (s) {
110
- console.warn("❌ [Aippy Tweaks] Failed to send tweaks config to iOS app:", s);
111
- }
112
- else
113
- console.warn("⚠️ [Aippy Tweaks] webkit.messageHandlers.aippyListener not available"), console.log(
114
- "🔍 [Aippy Tweaks] Available webkit handlers:",
115
- window.webkit?.messageHandlers ? Object.keys(window.webkit.messageHandlers) : "none"
116
- );
117
- if (window.parent && window.parent !== window)
118
- try {
119
- const s = {
120
- type: "tweaks-initialize",
121
- config: JSON.stringify(e)
122
- };
123
- window.parent.postMessage(s, "*"), console.log("📡 [Aippy Tweaks] Sent tweaks config to parent window:", s);
124
- const i = {
125
- type: "aippy-tweaks-ready",
126
- aippyTweaksRuntime: {
127
- tweaks: window.aippyTweaksRuntime?.tweaks,
128
- tweaksInstance: window.aippyTweaksRuntime?.tweaksInstance
129
- }
130
- };
131
- window.parent.postMessage(i, "*"), console.log("📡 [Aippy Tweaks] Sent aippyTweaksRuntime to parent window:", i);
132
- } catch (s) {
133
- console.warn("❌ [Aippy Tweaks] Failed to send to parent window:", s);
134
- }
135
- const a = (s) => {
136
- s.data && s.data.type === "tweaks-update" && (console.log("📥 [Aippy Tweaks] Received tweaks update:", s.data), t(s.data));
137
- };
138
- window.addEventListener("message", a), console.log("👂 [Aippy Tweaks] Listening for tweaks updates via window.postMessage");
139
- }
140
- // Process native data updates - Public method for external calls
141
- processNativeData(e) {
142
- if (!this.tweaksInstance) {
143
- console.warn("⚠️ [Aippy Tweaks] processNativeData called but no tweaks instance exists");
144
- return;
145
- }
146
- if (!this.updateCallback) {
147
- console.warn("⚠️ [Aippy Tweaks] processNativeData called but no update callback available");
148
- return;
149
- }
150
- try {
151
- if (!e || typeof e != "object") {
152
- console.warn("⚠️ [Aippy Tweaks] Invalid data type received from native:", typeof e);
153
- return;
154
- }
155
- if (!this.originalConfig) {
156
- console.warn("⚠️ [Aippy Tweaks] No original config available for merging");
157
- return;
158
- }
159
- const t = {}, n = {};
160
- let a = 0;
161
- console.log("📱 [DEBUG] Starting to process iOS data and merge with original config...");
162
- for (const [i, o] of Object.entries(e))
163
- if (console.log(`📱 [DEBUG] Processing key: ${i}`, o), o && typeof o == "object" && "value" in o) {
164
- const r = o, u = this.originalConfig[i];
165
- if (!u) {
166
- console.warn(`⚠️ [Aippy Tweaks] Key "${i}" not found in original config, skipping`);
167
- continue;
168
- }
169
- const f = /* @__PURE__ */ new Set(["tweakKey", "valueBefore", "tweaksType", "editType"]), d = { ...u };
170
- for (const [k, p] of Object.entries(r))
171
- f.has(k) || p != null && (d[k] = p);
172
- n[i] = d, t[i] = r.value, a++;
173
- }
174
- if (a === 0) {
175
- console.warn("⚠️ [Aippy Tweaks] No valid values found in iOS data:", e);
176
- return;
177
- }
178
- const s = {
179
- type: "tweaks-update",
180
- values: t
181
- };
182
- this.updateCallback(s);
183
- } catch (t) {
184
- console.error("❌ [Aippy Tweaks] Error processing native data:", t);
185
- }
186
- }
187
- }
188
- const w = new S(), g = {
189
- tweaks: (l) => w.tweaks(l)
190
- }, j = g.tweaks;
191
- typeof window < "u" && (window.aippyTweaksRuntime = g, window.processNativeData = w.processNativeData.bind(w), console.log("🌐 [Aippy Tweaks] Exposed processNativeData to window.processNativeData"));
192
- export {
193
- j as a,
194
- g as b
195
- };