@oasiz/sdk 1.2.1 → 1.4.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.cjs CHANGED
@@ -20,24 +20,32 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ consume: () => consume,
23
24
  emitScoreConfig: () => emitScoreConfig,
24
- enableLogOverlay: () => enableLogOverlay,
25
25
  flushGameState: () => flushGameState,
26
+ getEntitlements: () => getEntitlements,
26
27
  getGameId: () => getGameId,
28
+ getJemBalance: () => getJemBalance,
27
29
  getPlayerAvatar: () => getPlayerAvatar,
28
30
  getPlayerName: () => getPlayerName,
31
+ getProducts: () => getProducts,
32
+ getQuantity: () => getQuantity,
29
33
  getRoomCode: () => getRoomCode,
34
+ hasEntitlement: () => hasEntitlement,
30
35
  leaveGame: () => leaveGame,
31
36
  loadGameState: () => loadGameState,
32
37
  oasiz: () => oasiz,
33
38
  onBackButton: () => onBackButton,
39
+ onEntitlementsChanged: () => onEntitlementsChanged,
40
+ onJemBalanceChanged: () => onJemBalanceChanged,
34
41
  onLeaveGame: () => onLeaveGame,
35
42
  onPause: () => onPause,
36
43
  onResume: () => onResume,
37
- openInviteModal: () => openInviteModal,
44
+ purchase: () => purchase,
38
45
  saveGameState: () => saveGameState,
39
46
  shareRoomCode: () => shareRoomCode,
40
47
  submitScore: () => submitScore,
48
+ syncProducts: () => syncProducts,
41
49
  triggerHaptic: () => triggerHaptic
42
50
  });
43
51
  module.exports = __toCommonJS(index_exports);
@@ -66,897 +74,6 @@ function triggerHaptic(type) {
66
74
  }
67
75
  }
68
76
 
69
- // src/log-overlay.ts
70
- var CONSOLE_METHODS = [
71
- "debug",
72
- "log",
73
- "info",
74
- "warn",
75
- "error"
76
- ];
77
- var DEFAULT_MAX_ENTRIES = 200;
78
- var DEFAULT_TITLE = "SDK Logs";
79
- var OVERLAY_MARGIN = 12;
80
- var DEFAULT_COLLAPSED_WIDTH = 156;
81
- var DEFAULT_COLLAPSED_HEIGHT = 52;
82
- var DEFAULT_EXPANDED_WIDTH = 565;
83
- var DEFAULT_EXPANDED_HEIGHT = 372;
84
- var DRAG_THRESHOLD_PX = 6;
85
- var MIN_EXPANDED_WIDTH = 160;
86
- var MIN_EXPANDED_HEIGHT = 110;
87
- var RESIZE_HOTSPOT_PX = 28;
88
- var TOP_DRAG_ZONE_PX = 44;
89
- var NOOP_HANDLE = {
90
- clear() {
91
- },
92
- destroy() {
93
- },
94
- hide() {
95
- },
96
- isVisible() {
97
- return false;
98
- },
99
- show() {
100
- }
101
- };
102
- function getBrowserWindow() {
103
- if (typeof window === "undefined") {
104
- return void 0;
105
- }
106
- return window;
107
- }
108
- function getDocument() {
109
- if (typeof document === "undefined") {
110
- return void 0;
111
- }
112
- return document;
113
- }
114
- function clampMaxEntries(value) {
115
- if (!Number.isFinite(value)) {
116
- return DEFAULT_MAX_ENTRIES;
117
- }
118
- return Math.max(10, Math.floor(value));
119
- }
120
- function createConsoleSnapshot() {
121
- const fallback = console.log.bind(console);
122
- return {
123
- debug: typeof console.debug === "function" ? console.debug.bind(console) : fallback,
124
- log: fallback,
125
- info: typeof console.info === "function" ? console.info.bind(console) : fallback,
126
- warn: typeof console.warn === "function" ? console.warn.bind(console) : fallback,
127
- error: typeof console.error === "function" ? console.error.bind(console) : fallback
128
- };
129
- }
130
- function formatTimestamp(timestamp) {
131
- const date = new Date(timestamp);
132
- const hours = String(date.getHours()).padStart(2, "0");
133
- const minutes = String(date.getMinutes()).padStart(2, "0");
134
- const seconds = String(date.getSeconds()).padStart(2, "0");
135
- const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
136
- return "[" + hours + ":" + minutes + ":" + seconds + "." + milliseconds + "]";
137
- }
138
- function safeStringify(value) {
139
- const seen = /* @__PURE__ */ new WeakSet();
140
- try {
141
- return JSON.stringify(
142
- value,
143
- (_key, candidate) => {
144
- if (typeof candidate === "bigint") {
145
- return candidate.toString() + "n";
146
- }
147
- if (typeof candidate === "object" && candidate !== null) {
148
- if (seen.has(candidate)) {
149
- return "[Circular]";
150
- }
151
- seen.add(candidate);
152
- }
153
- return candidate;
154
- },
155
- 2
156
- ) ?? String(value);
157
- } catch {
158
- return String(value);
159
- }
160
- }
161
- function formatArg(value) {
162
- if (typeof value === "string") {
163
- return value;
164
- }
165
- if (value instanceof Error) {
166
- if (value.stack) {
167
- return value.stack;
168
- }
169
- return value.name + ": " + value.message;
170
- }
171
- if (typeof value === "undefined") {
172
- return "undefined";
173
- }
174
- if (typeof value === "function") {
175
- return "[Function " + (value.name || "anonymous") + "]";
176
- }
177
- return safeStringify(value);
178
- }
179
- function formatEntryMessage(args) {
180
- const message = args.map(formatArg).join(" ");
181
- if (message.length <= 4e3) {
182
- return message;
183
- }
184
- return message.slice(0, 3997) + "...";
185
- }
186
- function createEntry(level, args, id) {
187
- return {
188
- id,
189
- level,
190
- message: formatEntryMessage(args),
191
- timestamp: Date.now()
192
- };
193
- }
194
- function createButton(label) {
195
- const button = document.createElement("button");
196
- button.type = "button";
197
- button.textContent = label;
198
- button.style.cssText = [
199
- "appearance:none",
200
- "border:1px solid rgba(255,255,255,0.18)",
201
- "background:rgba(255,255,255,0.06)",
202
- "color:#f8fafc",
203
- "border-radius:999px",
204
- "padding:6px 10px",
205
- "font:600 12px/1.1 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
206
- "cursor:pointer"
207
- ].join(";");
208
- return button;
209
- }
210
- function getLevelAccent(level) {
211
- if (level === "error") {
212
- return {
213
- lineBackground: "rgba(255, 109, 122, 0.08)"
214
- };
215
- }
216
- if (level === "warn") {
217
- return {
218
- lineBackground: "rgba(255, 196, 94, 0.07)"
219
- };
220
- }
221
- if (level === "info") {
222
- return {
223
- lineBackground: "rgba(82, 187, 255, 0.07)"
224
- };
225
- }
226
- if (level === "debug") {
227
- return {
228
- lineBackground: "rgba(166, 137, 255, 0.07)"
229
- };
230
- }
231
- return {
232
- lineBackground: "rgba(117, 235, 191, 0.06)"
233
- };
234
- }
235
- function getViewportSize() {
236
- const browserWindow = getBrowserWindow();
237
- return {
238
- width: Math.max(320, browserWindow?.innerWidth ?? 1280),
239
- height: Math.max(240, browserWindow?.innerHeight ?? 720)
240
- };
241
- }
242
- function clampPanelSize(size) {
243
- const viewport = getViewportSize();
244
- const maxWidth = Math.max(MIN_EXPANDED_WIDTH, viewport.width - OVERLAY_MARGIN * 2);
245
- const maxHeight = Math.max(
246
- MIN_EXPANDED_HEIGHT,
247
- viewport.height - OVERLAY_MARGIN * 2
248
- );
249
- return {
250
- width: Math.min(maxWidth, Math.max(MIN_EXPANDED_WIDTH, size.width)),
251
- height: Math.min(maxHeight, Math.max(MIN_EXPANDED_HEIGHT, size.height))
252
- };
253
- }
254
- function getOverlaySize(state) {
255
- if (state.expanded && state.panelSize) {
256
- return state.panelSize;
257
- }
258
- const rect = state.ui?.root && typeof state.ui.root.getBoundingClientRect === "function" ? state.ui.root.getBoundingClientRect() : null;
259
- if (rect && Number.isFinite(rect.width) && Number.isFinite(rect.height)) {
260
- return {
261
- width: Math.max(1, rect.width),
262
- height: Math.max(1, rect.height)
263
- };
264
- }
265
- return state.expanded ? clampPanelSize({
266
- width: DEFAULT_EXPANDED_WIDTH,
267
- height: DEFAULT_EXPANDED_HEIGHT
268
- }) : { width: DEFAULT_COLLAPSED_WIDTH, height: DEFAULT_COLLAPSED_HEIGHT };
269
- }
270
- function applyPanelSize(state) {
271
- if (!state.ui) {
272
- return;
273
- }
274
- if (!state.expanded) {
275
- state.ui.root.style.width = "auto";
276
- state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
277
- state.ui.panel.style.height = "auto";
278
- state.ui.entries.style.maxHeight = "min(36vh, 280px)";
279
- return;
280
- }
281
- if (!state.panelSize) {
282
- state.ui.root.style.width = "min(565px, calc(100vw - 24px))";
283
- state.ui.panel.style.width = "min(565px, calc(100vw - 24px))";
284
- state.ui.panel.style.height = "auto";
285
- state.ui.entries.style.maxHeight = "min(36vh, 280px)";
286
- return;
287
- }
288
- const nextSize = clampPanelSize(
289
- state.panelSize
290
- );
291
- state.panelSize = nextSize;
292
- state.ui.root.style.width = nextSize.width + "px";
293
- state.ui.panel.style.width = "100%";
294
- state.ui.panel.style.height = nextSize.height + "px";
295
- state.ui.entries.style.maxHeight = Math.max(72, nextSize.height - 88) + "px";
296
- }
297
- function clampPosition(point, state) {
298
- const viewport = getViewportSize();
299
- const size = getOverlaySize(state);
300
- const maxX = Math.max(OVERLAY_MARGIN, viewport.width - size.width - OVERLAY_MARGIN);
301
- const maxY = Math.max(
302
- OVERLAY_MARGIN,
303
- viewport.height - size.height - OVERLAY_MARGIN
304
- );
305
- return {
306
- x: Math.min(maxX, Math.max(OVERLAY_MARGIN, point.x)),
307
- y: Math.min(maxY, Math.max(OVERLAY_MARGIN, point.y))
308
- };
309
- }
310
- function applyOverlayPosition(state) {
311
- if (!state.ui) {
312
- return;
313
- }
314
- if (!state.position) {
315
- const viewport = getViewportSize();
316
- const size = getOverlaySize(state);
317
- state.position = clampPosition(
318
- {
319
- x: viewport.width - size.width - OVERLAY_MARGIN,
320
- y: viewport.height - size.height - OVERLAY_MARGIN
321
- },
322
- state
323
- );
324
- } else {
325
- state.position = clampPosition(state.position, state);
326
- }
327
- state.ui.root.style.left = state.position.x + "px";
328
- state.ui.root.style.top = state.position.y + "px";
329
- }
330
- function getPointFromMouseEvent(event) {
331
- return { x: event.clientX, y: event.clientY };
332
- }
333
- function getPointFromTouchEvent(event) {
334
- const touch = event.touches[0] ?? event.changedTouches[0];
335
- if (!touch) {
336
- return null;
337
- }
338
- return { x: touch.clientX, y: touch.clientY };
339
- }
340
- function stopDragging(state) {
341
- if (state.isDragging || state.isResizing) {
342
- state.suppressToggleClickUntil = Date.now() + 180;
343
- }
344
- state.isDragging = false;
345
- state.dragStartPoint = null;
346
- state.lastDragPoint = null;
347
- state.removeDragListeners?.();
348
- state.removeDragListeners = null;
349
- if (state.ui) {
350
- state.ui.panel.style.cursor = "default";
351
- state.ui.dragZone.style.cursor = "grab";
352
- state.ui.toggleButton.style.cursor = "grab";
353
- }
354
- }
355
- function stopResizing(state) {
356
- if (state.isResizing) {
357
- state.suppressToggleClickUntil = Date.now() + 180;
358
- }
359
- state.isResizing = false;
360
- state.resizeStartPoint = null;
361
- state.resizeStartSize = null;
362
- state.removeResizeListeners?.();
363
- state.removeResizeListeners = null;
364
- }
365
- function beginDragTracking(state, startPoint) {
366
- const doc = getDocument();
367
- if (!doc) {
368
- return;
369
- }
370
- stopResizing(state);
371
- stopDragging(state);
372
- state.dragMoved = false;
373
- state.dragStartPoint = startPoint;
374
- state.lastDragPoint = startPoint;
375
- const handlePointerMove = (nextPoint) => {
376
- if (!state.dragStartPoint || !state.lastDragPoint || !nextPoint) {
377
- return;
378
- }
379
- if (!state.isDragging) {
380
- const deltaFromStartX = nextPoint.x - state.dragStartPoint.x;
381
- const deltaFromStartY = nextPoint.y - state.dragStartPoint.y;
382
- const distance = Math.sqrt(
383
- deltaFromStartX * deltaFromStartX + deltaFromStartY * deltaFromStartY
384
- );
385
- if (distance < DRAG_THRESHOLD_PX) {
386
- return;
387
- }
388
- state.isDragging = true;
389
- state.dragMoved = true;
390
- if (state.ui) {
391
- state.ui.panel.style.cursor = "grabbing";
392
- state.ui.dragZone.style.cursor = "grabbing";
393
- state.ui.toggleButton.style.cursor = "grabbing";
394
- }
395
- }
396
- const currentPosition = state.position ?? { x: OVERLAY_MARGIN, y: OVERLAY_MARGIN };
397
- state.position = clampPosition(
398
- {
399
- x: currentPosition.x + (nextPoint.x - state.lastDragPoint.x),
400
- y: currentPosition.y + (nextPoint.y - state.lastDragPoint.y)
401
- },
402
- state
403
- );
404
- state.lastDragPoint = nextPoint;
405
- applyOverlayPosition(state);
406
- };
407
- const handleMouseMove = (event) => {
408
- handlePointerMove(getPointFromMouseEvent(event));
409
- };
410
- const handleTouchMove = (event) => {
411
- handlePointerMove(getPointFromTouchEvent(event));
412
- };
413
- const handleMouseUp = () => {
414
- stopDragging(state);
415
- };
416
- const handleTouchEnd = () => {
417
- stopDragging(state);
418
- };
419
- doc.addEventListener("mousemove", handleMouseMove);
420
- doc.addEventListener("mouseup", handleMouseUp);
421
- doc.addEventListener("touchmove", handleTouchMove, { passive: true });
422
- doc.addEventListener("touchend", handleTouchEnd);
423
- doc.addEventListener("touchcancel", handleTouchEnd);
424
- state.removeDragListeners = () => {
425
- doc.removeEventListener("mousemove", handleMouseMove);
426
- doc.removeEventListener("mouseup", handleMouseUp);
427
- doc.removeEventListener("touchmove", handleTouchMove);
428
- doc.removeEventListener("touchend", handleTouchEnd);
429
- doc.removeEventListener("touchcancel", handleTouchEnd);
430
- };
431
- }
432
- function startResizing(state, startPoint) {
433
- const doc = getDocument();
434
- if (!doc) {
435
- return;
436
- }
437
- stopDragging(state);
438
- stopResizing(state);
439
- state.isResizing = true;
440
- state.resizeStartPoint = startPoint;
441
- state.resizeStartSize = state.panelSize ?? clampPanelSize({ width: DEFAULT_EXPANDED_WIDTH, height: DEFAULT_EXPANDED_HEIGHT });
442
- const handleResizeMove = (nextPoint) => {
443
- if (!state.isResizing || !state.resizeStartPoint || !state.resizeStartSize || !nextPoint) {
444
- return;
445
- }
446
- state.panelSize = clampPanelSize({
447
- width: state.resizeStartSize.width + (nextPoint.x - state.resizeStartPoint.x),
448
- height: state.resizeStartSize.height + (nextPoint.y - state.resizeStartPoint.y)
449
- });
450
- applyPanelSize(state);
451
- applyOverlayPosition(state);
452
- };
453
- const handleMouseMove = (event) => {
454
- handleResizeMove(getPointFromMouseEvent(event));
455
- };
456
- const handleTouchMove = (event) => {
457
- handleResizeMove(getPointFromTouchEvent(event));
458
- };
459
- const handleFinish = () => {
460
- stopResizing(state);
461
- };
462
- doc.addEventListener("mousemove", handleMouseMove);
463
- doc.addEventListener("mouseup", handleFinish);
464
- doc.addEventListener("touchmove", handleTouchMove, { passive: true });
465
- doc.addEventListener("touchend", handleFinish);
466
- doc.addEventListener("touchcancel", handleFinish);
467
- state.removeResizeListeners = () => {
468
- doc.removeEventListener("mousemove", handleMouseMove);
469
- doc.removeEventListener("mouseup", handleFinish);
470
- doc.removeEventListener("touchmove", handleTouchMove);
471
- doc.removeEventListener("touchend", handleFinish);
472
- doc.removeEventListener("touchcancel", handleFinish);
473
- };
474
- }
475
- function isInBottomRightResizeZone(element, point) {
476
- const rect = element.getBoundingClientRect();
477
- return point.x >= rect.right - RESIZE_HOTSPOT_PX && point.x <= rect.right && point.y >= rect.bottom - RESIZE_HOTSPOT_PX && point.y <= rect.bottom;
478
- }
479
- function canStartDragFromTarget(target) {
480
- if (!(target instanceof Element)) {
481
- return true;
482
- }
483
- if (target.closest("button") || target.closest("a") || target.closest("input") || target.closest("textarea") || target.closest("select")) {
484
- return false;
485
- }
486
- return true;
487
- }
488
- function isInTopDragZone(element, point, zoneHeight) {
489
- const rect = element.getBoundingClientRect();
490
- return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.top + zoneHeight;
491
- }
492
- function attachDragStartListeners(element, state, options = {}) {
493
- element.addEventListener("mousedown", (event) => {
494
- if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
495
- return;
496
- }
497
- const point = getPointFromMouseEvent(event);
498
- if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
499
- return;
500
- }
501
- beginDragTracking(state, point);
502
- });
503
- element.addEventListener("touchstart", (event) => {
504
- if (!options.allowInteractiveTarget && !canStartDragFromTarget(event.target)) {
505
- return;
506
- }
507
- const point = getPointFromTouchEvent(event);
508
- if (!point) {
509
- return;
510
- }
511
- if (typeof options.topZoneHeight === "number" && !isInTopDragZone(element, point, options.topZoneHeight)) {
512
- return;
513
- }
514
- beginDragTracking(state, point);
515
- });
516
- }
517
- function attachCollapsedToggleListeners(element, state) {
518
- const startToggleInteraction = (startPoint) => {
519
- const doc = getDocument();
520
- if (!doc) {
521
- return;
522
- }
523
- beginDragTracking(state, startPoint);
524
- const finishInteraction = () => {
525
- releaseListeners();
526
- if (state.dragMoved || Date.now() < state.suppressToggleClickUntil) {
527
- return;
528
- }
529
- state.expanded = true;
530
- state.unreadCount = 0;
531
- renderOverlay(state);
532
- };
533
- const releaseListeners = () => {
534
- doc.removeEventListener("mouseup", finishInteraction);
535
- doc.removeEventListener("touchend", finishInteraction);
536
- doc.removeEventListener("touchcancel", finishInteraction);
537
- };
538
- doc.addEventListener("mouseup", finishInteraction);
539
- doc.addEventListener("touchend", finishInteraction);
540
- doc.addEventListener("touchcancel", finishInteraction);
541
- };
542
- element.addEventListener("mousedown", (event) => {
543
- event.preventDefault();
544
- startToggleInteraction(getPointFromMouseEvent(event));
545
- });
546
- element.addEventListener("touchstart", (event) => {
547
- const point = getPointFromTouchEvent(event);
548
- if (!point) {
549
- return;
550
- }
551
- event.preventDefault();
552
- startToggleInteraction(point);
553
- });
554
- }
555
- function attachPanelResizeListeners(element, state) {
556
- element.addEventListener("mousedown", (event) => {
557
- if (!state.expanded || !canStartDragFromTarget(event.target)) {
558
- return;
559
- }
560
- const point = getPointFromMouseEvent(event);
561
- if (!isInBottomRightResizeZone(element, point)) {
562
- return;
563
- }
564
- event.preventDefault();
565
- event.stopPropagation();
566
- startResizing(state, point);
567
- });
568
- element.addEventListener("touchstart", (event) => {
569
- if (!state.expanded || !canStartDragFromTarget(event.target)) {
570
- return;
571
- }
572
- const point = getPointFromTouchEvent(event);
573
- if (!point || !isInBottomRightResizeZone(element, point)) {
574
- return;
575
- }
576
- event.preventDefault();
577
- event.stopPropagation();
578
- startResizing(state, point);
579
- });
580
- }
581
- function createOverlayUi(state) {
582
- const root = document.createElement("div");
583
- root.style.cssText = [
584
- "position:fixed",
585
- "left:12px",
586
- "top:12px",
587
- "z-index:2147483647",
588
- "display:flex",
589
- "flex-direction:column",
590
- "align-items:stretch",
591
- "gap:8px",
592
- "width:min(565px, calc(100vw - 24px))",
593
- "pointer-events:none"
594
- ].join(";");
595
- const toggleButton = createButton("Logs");
596
- toggleButton.style.pointerEvents = "auto";
597
- toggleButton.style.alignSelf = "flex-end";
598
- toggleButton.style.display = "inline-flex";
599
- toggleButton.style.alignItems = "center";
600
- toggleButton.style.justifyContent = "center";
601
- toggleButton.style.minHeight = "40px";
602
- toggleButton.style.minWidth = "76px";
603
- toggleButton.style.padding = "8px 14px";
604
- toggleButton.style.textAlign = "center";
605
- toggleButton.style.border = "1px solid rgba(122, 212, 255, 0.22)";
606
- toggleButton.style.background = "linear-gradient(180deg, rgba(13,31,54,0.98), rgba(8,19,37,0.98))";
607
- toggleButton.style.boxShadow = "0 18px 40px rgba(4,12,24,0.34)";
608
- toggleButton.style.cursor = "grab";
609
- toggleButton.style.touchAction = "none";
610
- const panel = document.createElement("div");
611
- panel.style.cssText = [
612
- "position:relative",
613
- "display:flex",
614
- "flex-direction:column",
615
- "width:min(565px, calc(100vw - 24px))",
616
- "max-height:min(48vh, 372px)",
617
- "border-radius:18px",
618
- "border:1px solid rgba(116,167,255,0.16)",
619
- "background:linear-gradient(180deg, rgba(9,19,37,0.98), rgba(5,12,24,0.98))",
620
- "box-shadow:0 28px 64px rgba(2,8,18,0.46)",
621
- "backdrop-filter:blur(16px)",
622
- "overflow:hidden",
623
- "cursor:default",
624
- "pointer-events:auto"
625
- ].join(";");
626
- const dragZone = document.createElement("div");
627
- dragZone.style.cssText = [
628
- "position:absolute",
629
- "top:0",
630
- "left:0",
631
- "right:0",
632
- "height:" + String(TOP_DRAG_ZONE_PX) + "px",
633
- "z-index:1",
634
- "cursor:grab",
635
- "background:transparent",
636
- "pointer-events:auto"
637
- ].join(";");
638
- const controls = document.createElement("div");
639
- controls.style.cssText = [
640
- "position:absolute",
641
- "top:22px",
642
- "right:22px",
643
- "z-index:2",
644
- "display:flex",
645
- "align-items:center",
646
- "gap:8px",
647
- "pointer-events:auto"
648
- ].join(";");
649
- const clearButton = createButton("Clear");
650
- clearButton.style.background = "rgba(255,255,255,0.1)";
651
- clearButton.style.border = "1px solid rgba(255,255,255,0.16)";
652
- clearButton.style.color = "#eef6ff";
653
- clearButton.style.minHeight = "30px";
654
- clearButton.style.padding = "4px 9px";
655
- clearButton.style.fontSize = "11px";
656
- clearButton.style.backdropFilter = "blur(8px)";
657
- const collapseButton = createButton("Hide");
658
- collapseButton.style.background = "rgba(113, 171, 255, 0.12)";
659
- collapseButton.style.border = "1px solid rgba(113, 171, 255, 0.2)";
660
- collapseButton.style.color = "#d9ebff";
661
- collapseButton.style.minHeight = "30px";
662
- collapseButton.style.padding = "4px 9px";
663
- collapseButton.style.fontSize = "11px";
664
- collapseButton.style.backdropFilter = "blur(8px)";
665
- const body = document.createElement("div");
666
- body.style.cssText = [
667
- "position:relative",
668
- "display:flex",
669
- "flex-direction:column",
670
- "padding:12px",
671
- "background:linear-gradient(180deg, rgba(4,10,20,0.88), rgba(3,8,18,0.98))",
672
- "flex:1 1 auto",
673
- "min-height:0"
674
- ].join(";");
675
- const entries = document.createElement("div");
676
- entries.style.cssText = [
677
- "display:flex",
678
- "flex-direction:column",
679
- "gap:0",
680
- "overflow:auto",
681
- "flex:1 1 auto",
682
- "min-height:96px",
683
- "max-height:min(36vh, 280px)",
684
- "padding:0",
685
- "border:1px solid rgba(115,153,212,0.14)",
686
- "border-radius:12px",
687
- "background:rgba(4,10,20,0.82)"
688
- ].join(";");
689
- const emptyState = document.createElement("div");
690
- emptyState.style.cssText = [
691
- "display:flex",
692
- "align-items:center",
693
- "justify-content:center",
694
- "flex:1 1 auto",
695
- "min-height:96px",
696
- "color:rgba(204,222,250,0.6)",
697
- "font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
698
- "text-align:center",
699
- "padding:18px"
700
- ].join(";");
701
- emptyState.textContent = "Console output will appear here.";
702
- collapseButton.addEventListener("click", (event) => {
703
- event.stopPropagation();
704
- state.expanded = false;
705
- renderOverlay(state);
706
- });
707
- clearButton.addEventListener("click", (event) => {
708
- event.stopPropagation();
709
- state.entries = [];
710
- state.unreadCount = 0;
711
- renderOverlay(state);
712
- });
713
- controls.appendChild(clearButton);
714
- controls.appendChild(collapseButton);
715
- entries.appendChild(emptyState);
716
- body.appendChild(entries);
717
- body.appendChild(controls);
718
- panel.appendChild(dragZone);
719
- panel.appendChild(body);
720
- attachDragStartListeners(dragZone, state);
721
- attachPanelResizeListeners(panel, state);
722
- attachCollapsedToggleListeners(toggleButton, state);
723
- root.appendChild(panel);
724
- root.appendChild(toggleButton);
725
- return {
726
- body,
727
- clearButton,
728
- collapseButton,
729
- controls,
730
- dragZone,
731
- emptyState,
732
- entries,
733
- panel,
734
- root,
735
- toggleButton
736
- };
737
- }
738
- function renderOverlay(state) {
739
- if (!state.ui) {
740
- return;
741
- }
742
- state.ui.panel.style.display = state.expanded ? "flex" : "none";
743
- state.ui.toggleButton.style.display = state.expanded ? "none" : "inline-flex";
744
- state.ui.toggleButton.textContent = "Logs";
745
- if (state.entries.length === 0) {
746
- state.ui.entries.style.display = "flex";
747
- state.ui.emptyState.style.display = "flex";
748
- state.ui.entries.replaceChildren(state.ui.emptyState);
749
- applyPanelSize(state);
750
- applyOverlayPosition(state);
751
- return;
752
- }
753
- state.ui.entries.style.display = "flex";
754
- state.ui.emptyState.style.display = "none";
755
- const nextChildren = state.entries.map((entry) => {
756
- const accent = getLevelAccent(entry.level);
757
- const row = document.createElement("div");
758
- row.style.cssText = [
759
- "display:flex",
760
- "align-items:flex-start",
761
- "gap:0",
762
- "padding:4px 12px",
763
- "background:" + accent.lineBackground
764
- ].join(";");
765
- const line = document.createElement("div");
766
- line.textContent = formatTimestamp(entry.timestamp) + " " + entry.level.toUpperCase() + " " + entry.message;
767
- line.style.cssText = [
768
- "color:#ecf4ff",
769
- "font:500 12px/1.5 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace",
770
- "white-space:pre-wrap",
771
- "word-break:break-word",
772
- "flex:1 1 auto"
773
- ].join(";");
774
- row.appendChild(line);
775
- return row;
776
- });
777
- state.ui.entries.replaceChildren(...nextChildren);
778
- state.ui.entries.scrollTop = state.ui.entries.scrollHeight;
779
- applyPanelSize(state);
780
- applyOverlayPosition(state);
781
- }
782
- function mountOverlay(state) {
783
- const doc = getDocument();
784
- if (!doc?.body || state.ui) {
785
- return;
786
- }
787
- state.ui = createOverlayUi(state);
788
- doc.body.appendChild(state.ui.root);
789
- applyPanelSize(state);
790
- applyOverlayPosition(state);
791
- renderOverlay(state);
792
- }
793
- function enqueueEntry(state, level, args) {
794
- state.entries.push(createEntry(level, args, state.nextEntryId));
795
- state.nextEntryId += 1;
796
- if (state.entries.length > state.maxEntries) {
797
- state.entries.splice(0, state.entries.length - state.maxEntries);
798
- }
799
- if (!state.expanded) {
800
- state.unreadCount += 1;
801
- }
802
- renderOverlay(state);
803
- }
804
- function restoreConsole(snapshot) {
805
- for (const method of CONSOLE_METHODS) {
806
- console[method] = snapshot[method];
807
- }
808
- }
809
- function patchConsole(state) {
810
- for (const method of CONSOLE_METHODS) {
811
- const original = state.originalConsole[method];
812
- console[method] = (...args) => {
813
- enqueueEntry(state, method, args);
814
- original(...args);
815
- };
816
- }
817
- }
818
- function cleanupOverlay(browserWindow, state) {
819
- restoreConsole(state.originalConsole);
820
- stopResizing(state);
821
- stopDragging(state);
822
- if (state.domReadyHandler) {
823
- getDocument()?.removeEventListener("DOMContentLoaded", state.domReadyHandler);
824
- state.domReadyHandler = void 0;
825
- }
826
- if (state.resizeHandler && typeof browserWindow.removeEventListener === "function") {
827
- browserWindow.removeEventListener("resize", state.resizeHandler);
828
- state.resizeHandler = void 0;
829
- }
830
- state.ui?.root.remove();
831
- state.ui = null;
832
- delete browserWindow.__oasizLogOverlayController__;
833
- delete browserWindow.__oasizLogOverlayState__;
834
- }
835
- function createController(browserWindow, state) {
836
- return {
837
- retain() {
838
- state.refCount += 1;
839
- this.ensureMounted();
840
- },
841
- ensureMounted() {
842
- const doc = getDocument();
843
- if (!doc) {
844
- return;
845
- }
846
- if (doc.body) {
847
- mountOverlay(state);
848
- applyOverlayPosition(state);
849
- return;
850
- }
851
- if (!state.domReadyHandler) {
852
- state.domReadyHandler = () => {
853
- mountOverlay(state);
854
- state.domReadyHandler = void 0;
855
- };
856
- doc.addEventListener("DOMContentLoaded", state.domReadyHandler, {
857
- once: true
858
- });
859
- }
860
- },
861
- clear() {
862
- state.entries = [];
863
- state.unreadCount = 0;
864
- renderOverlay(state);
865
- },
866
- show() {
867
- state.expanded = true;
868
- state.unreadCount = 0;
869
- renderOverlay(state);
870
- },
871
- hide() {
872
- state.expanded = false;
873
- renderOverlay(state);
874
- },
875
- isVisible() {
876
- return state.expanded;
877
- },
878
- destroy() {
879
- state.refCount = Math.max(0, state.refCount - 1);
880
- if (state.refCount === 0) {
881
- cleanupOverlay(browserWindow, state);
882
- }
883
- }
884
- };
885
- }
886
- function enableLogOverlay(options = {}) {
887
- if (options.enabled === false) {
888
- return NOOP_HANDLE;
889
- }
890
- const browserWindow = getBrowserWindow();
891
- const doc = getDocument();
892
- if (!browserWindow || !doc) {
893
- return NOOP_HANDLE;
894
- }
895
- const existingController = browserWindow.__oasizLogOverlayController__;
896
- const existingState = browserWindow.__oasizLogOverlayState__;
897
- if (existingController && existingState) {
898
- existingController.retain();
899
- if (typeof options.maxEntries === "number") {
900
- existingState.maxEntries = clampMaxEntries(options.maxEntries);
901
- if (existingState.entries.length > existingState.maxEntries) {
902
- existingState.entries.splice(
903
- 0,
904
- existingState.entries.length - existingState.maxEntries
905
- );
906
- }
907
- }
908
- if (typeof options.collapsed === "boolean") {
909
- existingState.expanded = !options.collapsed;
910
- applyPanelSize(existingState);
911
- if (existingState.expanded) {
912
- existingState.unreadCount = 0;
913
- }
914
- }
915
- if (typeof options.title === "string" && options.title.trim().length > 0) {
916
- existingState.title = options.title.trim();
917
- }
918
- existingController.ensureMounted();
919
- renderOverlay(existingState);
920
- return existingController;
921
- }
922
- const state = {
923
- dragMoved: false,
924
- dragStartPoint: null,
925
- entries: [],
926
- expanded: options.collapsed !== true,
927
- isDragging: false,
928
- isResizing: false,
929
- lastDragPoint: null,
930
- maxEntries: clampMaxEntries(options.maxEntries),
931
- nextEntryId: 1,
932
- originalConsole: createConsoleSnapshot(),
933
- panelSize: null,
934
- position: null,
935
- refCount: 1,
936
- removeDragListeners: null,
937
- removeResizeListeners: null,
938
- resizeStartPoint: null,
939
- resizeStartSize: null,
940
- suppressToggleClickUntil: 0,
941
- title: typeof options.title === "string" && options.title.trim().length > 0 ? options.title.trim() : DEFAULT_TITLE,
942
- resizeHandler: void 0,
943
- ui: null,
944
- unreadCount: 0
945
- };
946
- const controller = createController(browserWindow, state);
947
- browserWindow.__oasizLogOverlayState__ = state;
948
- browserWindow.__oasizLogOverlayController__ = controller;
949
- patchConsole(state);
950
- if (typeof browserWindow.addEventListener === "function") {
951
- state.resizeHandler = () => {
952
- applyOverlayPosition(state);
953
- };
954
- browserWindow.addEventListener("resize", state.resizeHandler);
955
- }
956
- controller.ensureMounted();
957
- return controller;
958
- }
959
-
960
77
  // src/multiplayer.ts
961
78
  function isDevelopment2() {
962
79
  const nodeEnv = globalThis.process?.env?.NODE_ENV;
@@ -968,10 +85,10 @@ function getBridgeWindow2() {
968
85
  }
969
86
  return window;
970
87
  }
971
- function shareRoomCode(roomCode, options) {
88
+ function shareRoomCode(roomCode) {
972
89
  const bridge = getBridgeWindow2();
973
90
  if (typeof bridge?.shareRoomCode === "function") {
974
- bridge.shareRoomCode(roomCode, options);
91
+ bridge.shareRoomCode(roomCode);
975
92
  return;
976
93
  }
977
94
  if (isDevelopment2()) {
@@ -980,18 +97,6 @@ function shareRoomCode(roomCode, options) {
980
97
  );
981
98
  }
982
99
  }
983
- function openInviteModal() {
984
- const bridge = getBridgeWindow2();
985
- if (typeof bridge?.openInviteModal === "function") {
986
- bridge.openInviteModal();
987
- return;
988
- }
989
- if (isDevelopment2()) {
990
- console.warn(
991
- "[oasiz/sdk] openInviteModal bridge is unavailable. This is expected in local development."
992
- );
993
- }
994
- }
995
100
  function getGameId() {
996
101
  const bridge = getBridgeWindow2();
997
102
  return bridge?.__GAME_ID__;
@@ -1211,22 +316,127 @@ function leaveGame() {
1211
316
  warnMissingBridge3("__oasizLeaveGame");
1212
317
  }
1213
318
 
319
+ // src/store.ts
320
+ function isDevelopment7() {
321
+ const nodeEnv = globalThis.process?.env?.NODE_ENV;
322
+ return nodeEnv !== "production";
323
+ }
324
+ function getBridgeWindow6() {
325
+ if (typeof window === "undefined") {
326
+ return void 0;
327
+ }
328
+ return window;
329
+ }
330
+ function warnMissingBridge4(methodName) {
331
+ if (isDevelopment7()) {
332
+ console.warn(
333
+ "[oasiz/sdk] " + methodName + " store bridge is unavailable. This is expected in local development."
334
+ );
335
+ }
336
+ }
337
+ async function requestStoreBridge(action, payload) {
338
+ const bridge = getBridgeWindow6();
339
+ if (typeof bridge?.__oasizStoreBridgeRequest !== "function") {
340
+ warnMissingBridge4(action);
341
+ throw new Error("Store bridge unavailable");
342
+ }
343
+ return await bridge.__oasizStoreBridgeRequest({
344
+ action,
345
+ payload
346
+ });
347
+ }
348
+ async function getFreshState() {
349
+ return await requestStoreBridge("getStoreState");
350
+ }
351
+ function subscribeToStoreEvent(eventName, callback) {
352
+ if (typeof window === "undefined") {
353
+ return () => {
354
+ };
355
+ }
356
+ const handler = (event) => {
357
+ const customEvent = event;
358
+ callback(customEvent.detail);
359
+ };
360
+ window.addEventListener(eventName, handler);
361
+ return () => {
362
+ window.removeEventListener(eventName, handler);
363
+ };
364
+ }
365
+ async function syncProducts(products, expectedVersion) {
366
+ return await requestStoreBridge("syncProducts", {
367
+ expectedVersion: expectedVersion ?? null,
368
+ products
369
+ });
370
+ }
371
+ async function getProducts() {
372
+ const state = await getFreshState();
373
+ return state.products;
374
+ }
375
+ async function getEntitlements() {
376
+ const state = await getFreshState();
377
+ return state.entitlements;
378
+ }
379
+ async function hasEntitlement(productId) {
380
+ const state = await getFreshState();
381
+ return state.entitlements.find((item) => item.productId === productId)?.owned === true;
382
+ }
383
+ async function getQuantity(productId) {
384
+ const state = await getFreshState();
385
+ return state.entitlements.find((item) => item.productId === productId)?.quantity ?? 0;
386
+ }
387
+ async function purchase(productId, quantity = 1) {
388
+ return await requestStoreBridge("purchaseProduct", {
389
+ productId,
390
+ quantity
391
+ });
392
+ }
393
+ async function consume(productId, quantity = 1) {
394
+ return await requestStoreBridge("consumeProduct", {
395
+ productId,
396
+ quantity
397
+ });
398
+ }
399
+ async function getJemBalance() {
400
+ const state = await getFreshState();
401
+ return state.jemBalance;
402
+ }
403
+ function onEntitlementsChanged(callback) {
404
+ return subscribeToStoreEvent("oasiz:entitlements-changed", (state) => {
405
+ callback(state.entitlements);
406
+ });
407
+ }
408
+ function onJemBalanceChanged(callback) {
409
+ return subscribeToStoreEvent("oasiz:jem-balance-changed", (state) => {
410
+ callback(state.jemBalance);
411
+ });
412
+ }
413
+
1214
414
  // src/index.ts
1215
415
  var oasiz = {
1216
416
  submitScore,
1217
417
  emitScoreConfig,
1218
418
  triggerHaptic,
1219
- enableLogOverlay,
1220
419
  loadGameState,
1221
420
  saveGameState,
1222
421
  flushGameState,
1223
422
  shareRoomCode,
1224
- openInviteModal,
1225
423
  onPause,
1226
424
  onResume,
1227
425
  onBackButton,
1228
426
  onLeaveGame,
1229
427
  leaveGame,
428
+ store: {
429
+ syncProducts,
430
+ getProducts,
431
+ getEntitlements,
432
+ hasEntitlement,
433
+ getQuantity,
434
+ purchase,
435
+ consume,
436
+ getJemBalance,
437
+ onEntitlementsChanged,
438
+ onJemBalanceChanged
439
+ },
1230
440
  get gameId() {
1231
441
  return getGameId();
1232
442
  },
@@ -1242,23 +452,31 @@ var oasiz = {
1242
452
  };
1243
453
  // Annotate the CommonJS export names for ESM import in node:
1244
454
  0 && (module.exports = {
455
+ consume,
1245
456
  emitScoreConfig,
1246
- enableLogOverlay,
1247
457
  flushGameState,
458
+ getEntitlements,
1248
459
  getGameId,
460
+ getJemBalance,
1249
461
  getPlayerAvatar,
1250
462
  getPlayerName,
463
+ getProducts,
464
+ getQuantity,
1251
465
  getRoomCode,
466
+ hasEntitlement,
1252
467
  leaveGame,
1253
468
  loadGameState,
1254
469
  oasiz,
1255
470
  onBackButton,
471
+ onEntitlementsChanged,
472
+ onJemBalanceChanged,
1256
473
  onLeaveGame,
1257
474
  onPause,
1258
475
  onResume,
1259
- openInviteModal,
476
+ purchase,
1260
477
  saveGameState,
1261
478
  shareRoomCode,
1262
479
  submitScore,
480
+ syncProducts,
1263
481
  triggerHaptic
1264
482
  });