@wvdsh/sdk-js 1.3.27 → 1.3.29

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 CHANGED
@@ -84,6 +84,56 @@ var WavedashEvents = {
84
84
  // src/services/audio.ts
85
85
  import { IFRAME_MESSAGE_TYPE } from "@wvdsh/api";
86
86
 
87
+ // src/utils/logger.ts
88
+ var LOG_LEVEL = {
89
+ DEBUG: 0,
90
+ // Most verbose
91
+ INFO: 1,
92
+ WARN: 2,
93
+ ERROR: 3
94
+ };
95
+ var WavedashLogger = class {
96
+ constructor(logLevel = LOG_LEVEL.WARN) {
97
+ this.logLevel = logLevel;
98
+ }
99
+ setLogLevel(level) {
100
+ this.logLevel = level;
101
+ }
102
+ debug(message, ...args) {
103
+ if (this.logLevel <= LOG_LEVEL.DEBUG) {
104
+ console.log(`[WavedashJS] ${message}`, ...args);
105
+ }
106
+ }
107
+ info(message, ...args) {
108
+ if (this.logLevel <= LOG_LEVEL.INFO) {
109
+ console.log(`[WavedashJS] ${message}`, ...args);
110
+ }
111
+ }
112
+ warn(message, ...args) {
113
+ if (this.logLevel <= LOG_LEVEL.WARN) {
114
+ console.warn(`[WavedashJS] ${message}`, ...args);
115
+ }
116
+ }
117
+ error(message, ...args) {
118
+ if (this.logLevel <= LOG_LEVEL.ERROR) {
119
+ console.error(`[WavedashJS] ${message}`, ...args);
120
+ }
121
+ }
122
+ };
123
+ var logger = new WavedashLogger();
124
+
125
+ // src/utils/parentOrigin.ts
126
+ var _parentOrigin = "";
127
+ function setParentOrigin(origin) {
128
+ _parentOrigin = origin;
129
+ }
130
+ function getParentOrigin() {
131
+ return _parentOrigin;
132
+ }
133
+ function hasParentFrame() {
134
+ return _parentOrigin !== "";
135
+ }
136
+
87
137
  // src/services/manager.ts
88
138
  var WavedashManager = class {
89
139
  constructor(sdk) {
@@ -134,6 +184,12 @@ var AudioManager = class extends WavedashManager {
134
184
  * MUTE_CHANGED broadcast, so `isMuted()` updates independently of this result.
135
185
  */
136
186
  async requestMute(muted) {
187
+ if (!hasParentFrame()) {
188
+ logger.debug(
189
+ "requestMute() is disabled outside a Wavedash parent frame (e.g. `wavedash dev`)"
190
+ );
191
+ return false;
192
+ }
137
193
  const response = await this.sdk.iframeMessenger.requestFromParent(
138
194
  IFRAME_MESSAGE_TYPE.SET_MUTE,
139
195
  { muted }
@@ -146,6 +202,12 @@ var AudioManager = class extends WavedashManager {
146
202
  * host applied the change.
147
203
  */
148
204
  async toggleMute() {
205
+ if (!hasParentFrame()) {
206
+ logger.debug(
207
+ "toggleMute() is disabled outside a Wavedash parent frame (e.g. `wavedash dev`)"
208
+ );
209
+ return false;
210
+ }
149
211
  const response = await this.sdk.iframeMessenger.requestFromParent(
150
212
  IFRAME_MESSAGE_TYPE.TOGGLE_MUTE
151
213
  );
@@ -645,44 +707,6 @@ function toBlobFromIndexedDBValue(value) {
645
707
  throw new Error("Unrecognized value shape from IndexedDB");
646
708
  }
647
709
 
648
- // src/utils/logger.ts
649
- var LOG_LEVEL = {
650
- DEBUG: 0,
651
- // Most verbose
652
- INFO: 1,
653
- WARN: 2,
654
- ERROR: 3
655
- };
656
- var WavedashLogger = class {
657
- constructor(logLevel = LOG_LEVEL.WARN) {
658
- this.logLevel = logLevel;
659
- }
660
- setLogLevel(level) {
661
- this.logLevel = level;
662
- }
663
- debug(message, ...args) {
664
- if (this.logLevel <= LOG_LEVEL.DEBUG) {
665
- console.log(`[WavedashJS] ${message}`, ...args);
666
- }
667
- }
668
- info(message, ...args) {
669
- if (this.logLevel <= LOG_LEVEL.INFO) {
670
- console.log(`[WavedashJS] ${message}`, ...args);
671
- }
672
- }
673
- warn(message, ...args) {
674
- if (this.logLevel <= LOG_LEVEL.WARN) {
675
- console.warn(`[WavedashJS] ${message}`, ...args);
676
- }
677
- }
678
- error(message, ...args) {
679
- if (this.logLevel <= LOG_LEVEL.ERROR) {
680
- console.error(`[WavedashJS] ${message}`, ...args);
681
- }
682
- }
683
- };
684
- var logger = new WavedashLogger();
685
-
686
710
  // src/services/fileSystem.ts
687
711
  import { api } from "@wvdsh/api";
688
712
  var REMOTE_STORAGE_FOLDER = "userfs";
@@ -1129,6 +1153,7 @@ var FullscreenManager = class extends WavedashManager {
1129
1153
  super(sdk);
1130
1154
  this._isFullscreen = false;
1131
1155
  this.listeners = /* @__PURE__ */ new Set();
1156
+ if (!hasParentFrame()) return;
1132
1157
  this.sdk.iframeMessenger.addEventListener(
1133
1158
  IFRAME_MESSAGE_TYPE2.FULLSCREEN_CHANGED,
1134
1159
  (data) => {
@@ -1150,6 +1175,12 @@ var FullscreenManager = class extends WavedashManager {
1150
1175
  * (e.g. browser rejected for lack of user activation).
1151
1176
  */
1152
1177
  async requestFullscreen(fullscreen) {
1178
+ if (!hasParentFrame()) {
1179
+ logger.debug(
1180
+ "requestFullscreen() is disabled outside a Wavedash parent frame (e.g. `wavedash dev`)"
1181
+ );
1182
+ return false;
1183
+ }
1153
1184
  const response = await this.sdk.iframeMessenger.requestFromParent(
1154
1185
  IFRAME_MESSAGE_TYPE2.SET_FULLSCREEN,
1155
1186
  { fullscreen }
@@ -1157,6 +1188,12 @@ var FullscreenManager = class extends WavedashManager {
1157
1188
  return response.success;
1158
1189
  }
1159
1190
  async toggleFullscreen() {
1191
+ if (!hasParentFrame()) {
1192
+ logger.debug(
1193
+ "toggleFullscreen() is disabled outside a Wavedash parent frame (e.g. `wavedash dev`)"
1194
+ );
1195
+ return false;
1196
+ }
1160
1197
  const response = await this.sdk.iframeMessenger.requestFromParent(
1161
1198
  IFRAME_MESSAGE_TYPE2.TOGGLE_FULLSCREEN
1162
1199
  );
@@ -1319,7 +1356,7 @@ var HeartbeatManager = class extends WavedashManager {
1319
1356
  this.gamepadPollInterval = setInterval(() => {
1320
1357
  this.pollGamepads();
1321
1358
  }, this.GAMEPAD_POLL_INTERVAL_MS);
1322
- this.deviceFingerprintReady = this.sdk.iframeMessenger.requestFromParent(IFRAME_MESSAGE_TYPE3.GET_DEVICE_FINGERPRINT).then((fingerprint) => {
1359
+ this.deviceFingerprintReady = !hasParentFrame() ? Promise.resolve() : this.sdk.iframeMessenger.requestFromParent(IFRAME_MESSAGE_TYPE3.GET_DEVICE_FINGERPRINT).then((fingerprint) => {
1323
1360
  this.deviceFingerprint = fingerprint;
1324
1361
  }).catch(() => {
1325
1362
  });
@@ -1868,6 +1905,11 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
1868
1905
  if (!this.lobbyId) {
1869
1906
  throw new Error("User is not in a lobby");
1870
1907
  }
1908
+ if (!hasParentFrame()) {
1909
+ throw new Error(
1910
+ "Lobby invite links are not available outside a Wavedash parent frame (e.g. `wavedash dev`)"
1911
+ );
1912
+ }
1871
1913
  const inviteLink = await this.sdk.iframeMessenger.requestFromParent(
1872
1914
  IFRAME_MESSAGE_TYPE4.GET_LOBBY_INVITE_LINK,
1873
1915
  { lobbyId: this.lobbyId, copyToClipboard }
@@ -2133,6 +2175,7 @@ var OverlayManager = class extends WavedashManager {
2133
2175
  this.toggleOverlay();
2134
2176
  }
2135
2177
  };
2178
+ if (!hasParentFrame()) return;
2136
2179
  this.sdk.iframeMessenger.addEventListener(
2137
2180
  IFRAME_MESSAGE_TYPE5.TAKE_FOCUS,
2138
2181
  takeFocus
@@ -3463,7 +3506,76 @@ _P2PManager.MEMORY_WARNING_THRESHOLD_BYTES = 128 * 1024 * 1024;
3463
3506
  var P2PManager = _P2PManager;
3464
3507
 
3465
3508
  // src/services/paidContent.ts
3466
- import { IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE6 } from "@wvdsh/api";
3509
+ import { api as api7, IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE6 } from "@wvdsh/api";
3510
+
3511
+ // src/utils/devPaywall.ts
3512
+ var Z_INDEX = 2147483647;
3513
+ function showDevPaywall(contentIdentifier) {
3514
+ if (typeof document === "undefined") return Promise.resolve(false);
3515
+ return new Promise((resolve) => {
3516
+ const overlay = document.createElement("div");
3517
+ overlay.style.cssText = "position:fixed;inset:0;z-index:" + Z_INDEX + ";display:flex;align-items:center;justify-content:center;background:rgba(8,10,18,0.72);font:14px ui-sans-serif,system-ui,sans-serif;color:#e2e8f0";
3518
+ const card = document.createElement("div");
3519
+ card.style.cssText = "max-width:420px;width:calc(100% - 48px);background:#11151f;border:1px solid #2a3344;border-radius:12px;padding:24px;box-shadow:0 20px 60px rgba(0,0,0,0.5);box-sizing:border-box";
3520
+ const badge = document.createElement("p");
3521
+ badge.textContent = "wavedash dev \u2014 simulated purchase";
3522
+ badge.style.cssText = "margin:0 0 12px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:#7c8aa5";
3523
+ const title = document.createElement("p");
3524
+ title.textContent = "Unlock paid content?";
3525
+ title.style.cssText = "margin:0 0 8px;font-size:18px;font-weight:600;color:#f1f5f9";
3526
+ const body = document.createElement("p");
3527
+ body.style.cssText = "margin:0 0 20px;line-height:1.5;color:#cbd5e1";
3528
+ body.append(
3529
+ document.createTextNode("This game is requesting purchase of \u201C")
3530
+ );
3531
+ const id = document.createElement("code");
3532
+ id.textContent = contentIdentifier;
3533
+ id.style.cssText = "background:#1c2433;border-radius:4px;padding:1px 6px;color:#93c5fd";
3534
+ body.append(
3535
+ id,
3536
+ document.createTextNode(
3537
+ "\u201D. No real payment happens in dev \u2014 simulate the outcome to test your flow."
3538
+ )
3539
+ );
3540
+ const buttons = document.createElement("div");
3541
+ buttons.style.cssText = "display:flex;gap:12px;justify-content:flex-end";
3542
+ const baseBtn = "border-radius:8px;padding:9px 18px;font-size:14px;font-weight:600;cursor:pointer;border:1px solid transparent";
3543
+ const cancel = document.createElement("button");
3544
+ cancel.type = "button";
3545
+ cancel.textContent = "Cancel";
3546
+ cancel.style.cssText = baseBtn + ";background:transparent;border-color:#374151;color:#cbd5e1";
3547
+ const buy = document.createElement("button");
3548
+ buy.type = "button";
3549
+ buy.textContent = "Simulate purchase";
3550
+ buy.style.cssText = baseBtn + ";background:#2563eb;color:#fff";
3551
+ buttons.append(cancel, buy);
3552
+ card.append(badge, title, body, buttons);
3553
+ overlay.append(card);
3554
+ let settled = false;
3555
+ const finish = (purchased) => {
3556
+ if (settled) return;
3557
+ settled = true;
3558
+ document.removeEventListener("keydown", onKeyDown, true);
3559
+ overlay.remove();
3560
+ resolve(purchased);
3561
+ };
3562
+ const onKeyDown = (event) => {
3563
+ if (event.key === "Escape") {
3564
+ event.preventDefault();
3565
+ finish(false);
3566
+ }
3567
+ };
3568
+ cancel.addEventListener("click", () => finish(false));
3569
+ buy.addEventListener("click", () => finish(true));
3570
+ overlay.addEventListener("click", (event) => {
3571
+ if (event.target === overlay) finish(false);
3572
+ });
3573
+ document.addEventListener("keydown", onKeyDown, true);
3574
+ document.body.append(overlay);
3575
+ });
3576
+ }
3577
+
3578
+ // src/services/paidContent.ts
3467
3579
  var PAYWALL_TIMEOUT_MS = 10 * 60 * 1e3;
3468
3580
  function decodeJwtPayload(jwt) {
3469
3581
  try {
@@ -3505,6 +3617,22 @@ var PaidContentManager = class extends WavedashManager {
3505
3617
  }
3506
3618
  this.paywallOpen = true;
3507
3619
  this.restorePointerLock = suspendPointerLock();
3620
+ if (!hasParentFrame()) {
3621
+ let purchased;
3622
+ try {
3623
+ purchased = await showDevPaywall(contentIdentifier);
3624
+ } finally {
3625
+ this.restorePointerLock?.();
3626
+ this.restorePointerLock = void 0;
3627
+ this.paywallOpen = false;
3628
+ }
3629
+ if (!purchased) return false;
3630
+ await this.sdk.convexClient.mutation(api7.sdk.paidContent.mockPurchase, {
3631
+ contentIdentifier
3632
+ });
3633
+ await this.sdk.ensureGameplayJwt(true);
3634
+ return true;
3635
+ }
3508
3636
  let response;
3509
3637
  try {
3510
3638
  response = await this.sdk.iframeMessenger.requestFromParent(
@@ -3531,7 +3659,7 @@ var PaidContentManager = class extends WavedashManager {
3531
3659
  };
3532
3660
 
3533
3661
  // src/services/stats.ts
3534
- import { api as api7 } from "@wvdsh/api";
3662
+ import { api as api8 } from "@wvdsh/api";
3535
3663
  import throttle2 from "lodash.throttle";
3536
3664
  var STORE_THROTTLE_MS = 1e3;
3537
3665
  var StatsManager = class extends WavedashManager {
@@ -3589,7 +3717,7 @@ var StatsManager = class extends WavedashManager {
3589
3717
  subscribe() {
3590
3718
  this.subscriptions.push(
3591
3719
  this.sdk.convexClient.onUpdate(
3592
- api7.sdk.gameAchievements.listStatIdentifiers,
3720
+ api8.sdk.gameAchievements.listStatIdentifiers,
3593
3721
  {},
3594
3722
  (ids) => {
3595
3723
  this.knownStatIds = new Set(ids);
@@ -3599,7 +3727,7 @@ var StatsManager = class extends WavedashManager {
3599
3727
  }
3600
3728
  ),
3601
3729
  this.sdk.convexClient.onUpdate(
3602
- api7.sdk.gameAchievements.listAchievementIdentifiers,
3730
+ api8.sdk.gameAchievements.listAchievementIdentifiers,
3603
3731
  {},
3604
3732
  (ids) => {
3605
3733
  this.knownAchievementIds = new Set(ids);
@@ -3609,7 +3737,7 @@ var StatsManager = class extends WavedashManager {
3609
3737
  }
3610
3738
  ),
3611
3739
  this.sdk.convexClient.onUpdate(
3612
- api7.sdk.gameAchievements.getMyAchievementsForGame,
3740
+ api8.sdk.gameAchievements.getMyAchievementsForGame,
3613
3741
  {},
3614
3742
  (achievements) => {
3615
3743
  this.loaded.achievements = true;
@@ -3625,7 +3753,7 @@ var StatsManager = class extends WavedashManager {
3625
3753
  }
3626
3754
  async requestStats() {
3627
3755
  const newStats = await this.sdk.convexClient.query(
3628
- api7.sdk.gameAchievements.getMyStatsForGame,
3756
+ api8.sdk.gameAchievements.getMyStatsForGame,
3629
3757
  {}
3630
3758
  );
3631
3759
  this.loaded.stats = true;
@@ -3656,11 +3784,11 @@ var StatsManager = class extends WavedashManager {
3656
3784
  if (!pending) return;
3657
3785
  this.inFlightPersist = Promise.all([
3658
3786
  pending.stats.length > 0 ? this.sdk.convexClient.mutation(
3659
- api7.sdk.gameAchievements.setUserGameStats,
3787
+ api8.sdk.gameAchievements.setUserGameStats,
3660
3788
  { stats: pending.stats }
3661
3789
  ) : Promise.resolve(),
3662
3790
  pending.achievements.length > 0 ? this.sdk.convexClient.mutation(
3663
- api7.sdk.gameAchievements.setUserGameAchievements,
3791
+ api8.sdk.gameAchievements.setUserGameAchievements,
3664
3792
  { achievements: pending.achievements }
3665
3793
  ) : Promise.resolve()
3666
3794
  ]).then(() => {
@@ -3737,14 +3865,14 @@ var StatsManager = class extends WavedashManager {
3737
3865
  };
3738
3866
 
3739
3867
  // src/services/ugc.ts
3740
- import { api as api8 } from "@wvdsh/api";
3868
+ import { api as api9 } from "@wvdsh/api";
3741
3869
  var UGCManager = class extends WavedashManager {
3742
3870
  constructor(sdk) {
3743
3871
  super(sdk);
3744
3872
  }
3745
3873
  async createUGCItem(ugcType, title, description, visibility, filePath) {
3746
3874
  const { ugcId, uploadUrl } = await this.sdk.convexClient.mutation(
3747
- api8.sdk.userGeneratedContent.createUGCItem,
3875
+ api9.sdk.userGeneratedContent.createUGCItem,
3748
3876
  {
3749
3877
  ugcType,
3750
3878
  title,
@@ -3771,7 +3899,7 @@ var UGCManager = class extends WavedashManager {
3771
3899
  async updateUGCItem(ugcId, updates = {}) {
3772
3900
  const { title, description, visibility, filePath } = updates;
3773
3901
  const { uploadUrl } = await this.sdk.convexClient.mutation(
3774
- api8.sdk.userGeneratedContent.updateUGCItem,
3902
+ api9.sdk.userGeneratedContent.updateUGCItem,
3775
3903
  {
3776
3904
  ugcId,
3777
3905
  title,
@@ -3797,14 +3925,14 @@ var UGCManager = class extends WavedashManager {
3797
3925
  }
3798
3926
  async deleteUGCItem(ugcId) {
3799
3927
  await this.sdk.convexClient.mutation(
3800
- api8.sdk.userGeneratedContent.deleteUGCItem,
3928
+ api9.sdk.userGeneratedContent.deleteUGCItem,
3801
3929
  { ugcId }
3802
3930
  );
3803
3931
  return ugcId;
3804
3932
  }
3805
3933
  async downloadUGCItem(ugcId, filePath) {
3806
3934
  const downloadUrl = await this.sdk.convexClient.query(
3807
- api8.sdk.userGeneratedContent.getUGCItemDownloadUrl,
3935
+ api9.sdk.userGeneratedContent.getUGCItemDownloadUrl,
3808
3936
  { ugcId }
3809
3937
  );
3810
3938
  try {
@@ -3819,7 +3947,7 @@ var UGCManager = class extends WavedashManager {
3819
3947
  const { createdBy, ugcType, titleSearch, numItems, continueCursor } = args;
3820
3948
  const filters = createdBy !== void 0 || ugcType !== void 0 || titleSearch !== void 0 ? { createdBy, ugcType, titleSearch } : void 0;
3821
3949
  return await this.sdk.convexClient.query(
3822
- api8.sdk.userGeneratedContent.listUGCItems,
3950
+ api9.sdk.userGeneratedContent.listUGCItems,
3823
3951
  {
3824
3952
  filters,
3825
3953
  numItems,
@@ -3829,15 +3957,6 @@ var UGCManager = class extends WavedashManager {
3829
3957
  }
3830
3958
  };
3831
3959
 
3832
- // src/utils/parentOrigin.ts
3833
- var _parentOrigin = "";
3834
- function setParentOrigin(origin) {
3835
- _parentOrigin = origin;
3836
- }
3837
- function getParentOrigin() {
3838
- return _parentOrigin;
3839
- }
3840
-
3841
3960
  // src/utils/iframeMessenger.ts
3842
3961
  var RESPONSE_TIMEOUT_MS = 15e3;
3843
3962
  var IFrameMessenger = class {
@@ -5281,6 +5400,7 @@ var WavedashSDK = class extends EventTarget {
5281
5400
  const refreshQuery = new URLSearchParams({
5282
5401
  [UrlParams.Caller]: PlayRouteCaller.Wavedash
5283
5402
  });
5403
+ if (forceRefresh) refreshQuery.set("fresh", "1");
5284
5404
  const refreshPath = `/auth/refresh?${refreshQuery.toString()}`;
5285
5405
  const response = await fetch(refreshPath, {
5286
5406
  method: "POST",