@wvdsh/sdk-js 1.3.11 → 1.3.12

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/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WavedashSDK } from './index.js';
2
- export { BackendConnectionPayload, EngineInstance, Friend, FullscreenChangedPayload, Leaderboard, LeaderboardDisplayType, LeaderboardEntries, LeaderboardSortOrder, Lobby, LobbyDataUpdatedPayload, LobbyInvite, LobbyInvitePayload, LobbyJoinResponse, LobbyJoinedPayload, LobbyKickedPayload, LobbyKickedReason, LobbyMessage, LobbyMessagePayload, LobbyUser, LobbyUserChangeType, LobbyUsersUpdatedPayload, LobbyVisibility, P2PConfig, P2PConnection, P2PConnectionEstablishedPayload, P2PConnectionFailedPayload, P2PMessage, P2PPacketDropReason, P2PPacketDroppedPayload, P2PPeer, P2PPeerDisconnectedPayload, P2PPeerReconnectedPayload, P2PPeerReconnectingPayload, RemoteFileMetadata, StatsStoredPayload, UGCType, UGCVisibility, UpsertedLeaderboardEntry, WavedashConfig, WavedashEvent, WavedashEventMap, WavedashResponse } from './index.js';
2
+ export { BackendConnectionPayload, EngineInstance, Friend, FullscreenChangedPayload, Leaderboard, LeaderboardDisplayType, LeaderboardEntries, LeaderboardSortOrder, ListUGCItemsArgs, Lobby, LobbyDataUpdatedPayload, LobbyInvite, LobbyInvitePayload, LobbyJoinResponse, LobbyJoinedPayload, LobbyKickedPayload, LobbyKickedReason, LobbyMessage, LobbyMessagePayload, LobbyUser, LobbyUserChangeType, LobbyUsersUpdatedPayload, LobbyVisibility, P2PConfig, P2PConnection, P2PConnectionEstablishedPayload, P2PConnectionFailedPayload, P2PMessage, P2PPacketDropReason, P2PPacketDroppedPayload, P2PPeer, P2PPeerDisconnectedPayload, P2PPeerReconnectedPayload, P2PPeerReconnectingPayload, PaginatedUGCItems, RemoteFileMetadata, StatsStoredPayload, UGCItem, UGCType, UGCVisibility, UpdateUGCItemArgs, UpsertedLeaderboardEntry, WavedashConfig, WavedashEvent, WavedashEventMap, WavedashResponse } from './index.js';
3
3
  export { GameLaunchParams } from '@wvdsh/api';
4
4
  export { GenericId as Id } from 'convex/values';
5
5
  import 'convex/browser';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ConvexClient } from 'convex/browser';
2
2
  import { GenericId } from 'convex/values';
3
3
  export { GenericId as Id } from 'convex/values';
4
- import { FunctionReturnType } from 'convex/server';
4
+ import { FunctionReturnType, FunctionArgs } from 'convex/server';
5
5
  import { LOBBY_VISIBILITY, api, UGC_TYPE, UGC_VISIBILITY, LEADERBOARD_SORT_ORDER, LEADERBOARD_DISPLAY_TYPE, GAME_ENGINE, SDKUser, IFrameEventPayloadMap, IFRAME_MESSAGE_TYPE, SDKConfig, GameLaunchParams } from '@wvdsh/api';
6
6
  export { GameLaunchParams } from '@wvdsh/api';
7
7
 
@@ -71,6 +71,13 @@ type LeaderboardSortOrder = (typeof LEADERBOARD_SORT_ORDER)[keyof typeof LEADERB
71
71
  type LeaderboardDisplayType = (typeof LEADERBOARD_DISPLAY_TYPE)[keyof typeof LEADERBOARD_DISPLAY_TYPE];
72
72
  type UGCType = (typeof UGC_TYPE)[keyof typeof UGC_TYPE];
73
73
  type UGCVisibility = (typeof UGC_VISIBILITY)[keyof typeof UGC_VISIBILITY];
74
+ type UpdateUGCItemArgs = Omit<FunctionArgs<typeof api.sdk.userGeneratedContent.updateUGCItem>, "ugcId" | "createPresignedUploadUrl"> & {
75
+ filePath?: string;
76
+ };
77
+ type UGCItem = FunctionReturnType<typeof api.sdk.userGeneratedContent.listUGCItems>["page"][0];
78
+ type PaginatedUGCItems = FunctionReturnType<typeof api.sdk.userGeneratedContent.listUGCItems>;
79
+ type RawListUGCItemsArgs = FunctionArgs<typeof api.sdk.userGeneratedContent.listUGCItems>;
80
+ type ListUGCItemsArgs = Omit<RawListUGCItemsArgs, "filters"> & NonNullable<RawListUGCItemsArgs["filters"]>;
74
81
  type LobbyUser = FunctionReturnType<typeof api.sdk.gameLobby.lobbyUsers>[0];
75
82
  type LobbyMessage = FunctionReturnType<typeof api.sdk.gameLobby.lobbyMessages>[0];
76
83
  type Lobby = FunctionReturnType<typeof api.sdk.gameLobby.listAvailable>[0];
@@ -429,9 +436,10 @@ declare class FileSystemManager extends WavedashManager {
429
436
  declare class UGCManager extends WavedashManager {
430
437
  constructor(sdk: WavedashSDK);
431
438
  createUGCItem(ugcType: UGCType, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
432
- updateUGCItem(ugcId: GenericId<"userGeneratedContent">, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
439
+ updateUGCItem(ugcId: GenericId<"userGeneratedContent">, updates?: UpdateUGCItemArgs): Promise<GenericId<"userGeneratedContent">>;
433
440
  deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<GenericId<"userGeneratedContent">>;
434
441
  downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<GenericId<"userGeneratedContent">>;
442
+ listUGCItems(args?: ListUGCItemsArgs): Promise<PaginatedUGCItems>;
435
443
  }
436
444
 
437
445
  /**
@@ -634,7 +642,7 @@ declare class HeartbeatManager extends WavedashManager {
634
642
  * @param data - Data to send to the backend
635
643
  * @returns true if the presence was updated successfully
636
644
  */
637
- updateUserPresence(data?: Record<string, unknown>): Promise<boolean>;
645
+ updateUserPresence(data?: Record<string, string | number | boolean | null>): Promise<boolean>;
638
646
  /**
639
647
  * Tests the connection to the backend
640
648
  */
@@ -848,7 +856,6 @@ declare class WavedashSDK extends EventTarget {
848
856
  };
849
857
  UGCVisibility: {
850
858
  readonly PUBLIC: 0;
851
- readonly FRIENDS_ONLY: 1;
852
859
  readonly PRIVATE: 2;
853
860
  };
854
861
  AvatarSize: {
@@ -998,21 +1005,19 @@ declare class WavedashSDK extends EventTarget {
998
1005
  createUGCItem(ugcType: UGCType, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
999
1006
  /**
1000
1007
  * Updates a UGC item and uploads the file to the server if a filePath is provided
1001
- * TODO: GD Script cannot call with optional arguments, convert this to accept a single dictionary of updates
1002
- * @param ugcId
1003
- * @param title
1004
- * @param description
1005
- * @param visibility
1006
- * @param filePath - optional IndexedDB key file path to upload to the server. If not provided, the UGC item will be updated but no file will be uploaded.
1008
+ * @param ugcId - The ID of the UGC item to update
1009
+ * @param updates - Object containing the fields to update. May also be passed
1010
+ * as a JSON string by engine bridges (Godot) that can't marshal a dict.
1007
1011
  * @returns ugcId
1008
1012
  */
1009
- updateUGCItem(ugcId: GenericId<"userGeneratedContent">, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
1013
+ updateUGCItem(ugcId: GenericId<"userGeneratedContent">, updates?: UpdateUGCItemArgs): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
1010
1014
  /**
1011
1015
  * Delete a UGC item: removes the row, the R2 object, and frees up the
1012
1016
  * user's storage quota by the size of the deleted upload.
1013
1017
  */
1014
1018
  deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
1015
1019
  downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
1020
+ listUGCItems(args?: ListUGCItemsArgs): Promise<WavedashResponse<PaginatedUGCItems>>;
1016
1021
  /**
1017
1022
  * Deletes a remote file from storage
1018
1023
  * @param filePath - The path of the remote file to delete
@@ -1158,11 +1163,10 @@ declare class WavedashSDK extends EventTarget {
1158
1163
  getLobbyInviteLink(copyToClipboard?: boolean): Promise<WavedashResponse<string>>;
1159
1164
  /**
1160
1165
  * Updates rich user presence so friends can see what the player is doing in game
1161
- * TODO: data param should be more strongly typed
1162
1166
  * @param data Game data to send to the backend
1163
1167
  * @returns true if the presence was updated successfully
1164
1168
  */
1165
- updateUserPresence(data?: Record<string, unknown>): Promise<WavedashResponse<boolean>>;
1169
+ updateUserPresence(data?: Record<string, string | number | boolean | null>): Promise<WavedashResponse<boolean>>;
1166
1170
  private isGodot;
1167
1171
  private formatResponse;
1168
1172
  private ensureInit;
@@ -1209,4 +1213,4 @@ declare global {
1209
1213
 
1210
1214
  declare function setupWavedashSDK(): WavedashSDK;
1211
1215
 
1212
- export { type BackendConnectionPayload, type EngineInstance, type Friend, type FullscreenChangedPayload, type Leaderboard, type LeaderboardDisplayType, type LeaderboardEntries, type LeaderboardSortOrder, type Lobby, type LobbyDataUpdatedPayload, type LobbyInvite, type LobbyInvitePayload, type LobbyJoinResponse, type LobbyJoinedPayload, type LobbyKickedPayload, type LobbyKickedReason, type LobbyMessage, type LobbyMessagePayload, type LobbyUser, type LobbyUserChangeType, type LobbyUsersUpdatedPayload, type LobbyVisibility, type P2PConfig, type P2PConnection, type P2PConnectionEstablishedPayload, type P2PConnectionFailedPayload, type P2PMessage, type P2PPacketDropReason, type P2PPacketDroppedPayload, type P2PPeer, type P2PPeerDisconnectedPayload, type P2PPeerReconnectedPayload, type P2PPeerReconnectingPayload, type RemoteFileMetadata, type StatsStoredPayload, type UGCType, type UGCVisibility, type UpsertedLeaderboardEntry, type WavedashConfig, type WavedashEvent, type WavedashEventMap, type WavedashResponse, WavedashSDK, setupWavedashSDK };
1216
+ export { type BackendConnectionPayload, type EngineInstance, type Friend, type FullscreenChangedPayload, type Leaderboard, type LeaderboardDisplayType, type LeaderboardEntries, type LeaderboardSortOrder, type ListUGCItemsArgs, type Lobby, type LobbyDataUpdatedPayload, type LobbyInvite, type LobbyInvitePayload, type LobbyJoinResponse, type LobbyJoinedPayload, type LobbyKickedPayload, type LobbyKickedReason, type LobbyMessage, type LobbyMessagePayload, type LobbyUser, type LobbyUserChangeType, type LobbyUsersUpdatedPayload, type LobbyVisibility, type P2PConfig, type P2PConnection, type P2PConnectionEstablishedPayload, type P2PConnectionFailedPayload, type P2PMessage, type P2PPacketDropReason, type P2PPacketDroppedPayload, type P2PPeer, type P2PPeerDisconnectedPayload, type P2PPeerReconnectedPayload, type P2PPeerReconnectingPayload, type PaginatedUGCItems, type RemoteFileMetadata, type StatsStoredPayload, type UGCItem, type UGCType, type UGCVisibility, type UpdateUGCItemArgs, type UpsertedLeaderboardEntry, type WavedashConfig, type WavedashEvent, type WavedashEventMap, type WavedashResponse, WavedashSDK, setupWavedashSDK };
package/dist/index.js CHANGED
@@ -1033,7 +1033,8 @@ var UGCManager = class extends WavedashManager {
1033
1033
  }
1034
1034
  return ugcId;
1035
1035
  }
1036
- async updateUGCItem(ugcId, title, description, visibility, filePath) {
1036
+ async updateUGCItem(ugcId, updates = {}) {
1037
+ const { title, description, visibility, filePath } = updates;
1037
1038
  const { uploadUrl } = await this.sdk.convexClient.mutation(
1038
1039
  api3.sdk.userGeneratedContent.updateUGCItem,
1039
1040
  {
@@ -1079,6 +1080,18 @@ var UGCManager = class extends WavedashManager {
1079
1080
  }
1080
1081
  return ugcId;
1081
1082
  }
1083
+ async listUGCItems(args = {}) {
1084
+ const { createdBy, ugcType, titleSearch, numItems, continueCursor } = args;
1085
+ const filters = createdBy !== void 0 || ugcType !== void 0 || titleSearch !== void 0 ? { createdBy, ugcType, titleSearch } : void 0;
1086
+ return await this.sdk.convexClient.query(
1087
+ api3.sdk.userGeneratedContent.listUGCItems,
1088
+ {
1089
+ filters,
1090
+ numItems,
1091
+ continueCursor
1092
+ }
1093
+ );
1094
+ }
1082
1095
  };
1083
1096
 
1084
1097
  // src/services/leaderboards.ts
@@ -3362,11 +3375,29 @@ function vUnion(...variants) {
3362
3375
  throw new Error(`${path}: no variant matched, got ${describeValue(value)}`);
3363
3376
  };
3364
3377
  }
3378
+ function vObject(shape) {
3379
+ return (value, path) => {
3380
+ const obj = vRecord(value, path);
3381
+ for (const key of Object.keys(obj)) {
3382
+ if (!(key in shape)) {
3383
+ throw new Error(`${path}: unrecognized property "${key}"`);
3384
+ }
3385
+ }
3386
+ for (const key of Object.keys(shape)) {
3387
+ shape[key](obj[key], `${path}.${key}`);
3388
+ }
3389
+ return obj;
3390
+ };
3391
+ }
3365
3392
  function validateArgs(methodName, specs, values) {
3393
+ const shape = {};
3394
+ const obj = {};
3366
3395
  for (let i = 0; i < specs.length; i++) {
3367
3396
  const [argName, validator] = specs[i];
3368
- validator(values[i], `${methodName}.${argName}`);
3397
+ shape[argName] = validator;
3398
+ obj[argName] = values[i];
3369
3399
  }
3400
+ vObject(shape)(obj, methodName);
3370
3401
  }
3371
3402
  function describeValue(value) {
3372
3403
  if (value === void 0) return "undefined";
@@ -3817,30 +3848,45 @@ var WavedashSDK = class extends EventTarget {
3817
3848
  }
3818
3849
  /**
3819
3850
  * Updates a UGC item and uploads the file to the server if a filePath is provided
3820
- * TODO: GD Script cannot call with optional arguments, convert this to accept a single dictionary of updates
3821
- * @param ugcId
3822
- * @param title
3823
- * @param description
3824
- * @param visibility
3825
- * @param filePath - optional IndexedDB key file path to upload to the server. If not provided, the UGC item will be updated but no file will be uploaded.
3851
+ * @param ugcId - The ID of the UGC item to update
3852
+ * @param updates - Object containing the fields to update. May also be passed
3853
+ * as a JSON string by engine bridges (Godot) that can't marshal a dict.
3826
3854
  * @returns ugcId
3827
3855
  */
3828
- async updateUGCItem(ugcId, title, description, visibility, filePath) {
3856
+ async updateUGCItem(ugcId, updates = {}) {
3857
+ if (typeof updates === "string") {
3858
+ const raw = updates;
3859
+ try {
3860
+ updates = JSON.parse(raw);
3861
+ } catch (error) {
3862
+ const message = `updateUGCItem: invalid JSON: ${raw}`;
3863
+ logger.error(message, error);
3864
+ return this.formatResponse({
3865
+ success: false,
3866
+ data: null,
3867
+ message
3868
+ });
3869
+ }
3870
+ }
3829
3871
  return this.apiCall(
3830
3872
  this.ugcManager,
3831
3873
  "updateUGCItem",
3832
3874
  [
3833
3875
  ["ugcId", vId("userGeneratedContent")],
3834
- ["title", vOptional(vString)],
3835
- ["description", vOptional(vString)],
3836
- ["visibility", vOptional(vEnum(UGC_VISIBILITY, "UGCVisibility"))],
3837
- ["filePath", vOptional(vString)]
3876
+ [
3877
+ "updates",
3878
+ vOptional(
3879
+ vObject({
3880
+ title: vOptional(vString),
3881
+ description: vOptional(vString),
3882
+ visibility: vOptional(vEnum(UGC_VISIBILITY, "UGCVisibility")),
3883
+ filePath: vOptional(vString)
3884
+ })
3885
+ )
3886
+ ]
3838
3887
  ],
3839
3888
  ugcId,
3840
- title,
3841
- description,
3842
- visibility,
3843
- filePath
3889
+ updates
3844
3890
  );
3845
3891
  }
3846
3892
  /**
@@ -3867,6 +3913,47 @@ var WavedashSDK = class extends EventTarget {
3867
3913
  filePath
3868
3914
  );
3869
3915
  }
3916
+ async listUGCItems(args = {}) {
3917
+ if (typeof args === "string") {
3918
+ const raw = args;
3919
+ try {
3920
+ args = JSON.parse(raw);
3921
+ } catch (error) {
3922
+ const message = `listUGCItems: invalid JSON: ${raw}`;
3923
+ logger.error(message, error);
3924
+ return this.formatResponse({
3925
+ success: false,
3926
+ data: null,
3927
+ message
3928
+ });
3929
+ }
3930
+ }
3931
+ return this.apiCall(
3932
+ this.ugcManager,
3933
+ "listUGCItems",
3934
+ [
3935
+ [
3936
+ "args",
3937
+ vOptional((value, path) => {
3938
+ const obj = vObject({
3939
+ createdBy: vOptional(vId("users")),
3940
+ ugcType: vOptional(vEnum(UGC_TYPE, "UGCType")),
3941
+ titleSearch: vOptional(vString),
3942
+ numItems: vOptional(vNumber),
3943
+ continueCursor: vOptional(vString)
3944
+ })(value, path);
3945
+ if (obj.continueCursor !== void 0 && (obj.createdBy !== void 0 || obj.ugcType !== void 0 || obj.titleSearch !== void 0 || obj.numItems !== void 0)) {
3946
+ throw new Error(
3947
+ `${path}: continueCursor should be the only argument if present`
3948
+ );
3949
+ }
3950
+ return obj;
3951
+ })
3952
+ ]
3953
+ ],
3954
+ args
3955
+ );
3956
+ }
3870
3957
  // ================================
3871
3958
  // Save state / Remote File Storage
3872
3959
  // ================================
@@ -4282,7 +4369,6 @@ var WavedashSDK = class extends EventTarget {
4282
4369
  // ==============================
4283
4370
  /**
4284
4371
  * Updates rich user presence so friends can see what the player is doing in game
4285
- * TODO: data param should be more strongly typed
4286
4372
  * @param data Game data to send to the backend
4287
4373
  * @returns true if the presence was updated successfully
4288
4374
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wvdsh/sdk-js",
3
- "version": "1.3.11",
3
+ "version": "1.3.12",
4
4
  "type": "module",
5
5
  "description": "Wavedash JavaScript SDK",
6
6
  "main": "./dist/client.js",
@@ -49,7 +49,7 @@
49
49
  "typescript-eslint": "^8.52.0"
50
50
  },
51
51
  "dependencies": {
52
- "@wvdsh/api": "^0.1.16",
52
+ "@wvdsh/api": "^0.1.27",
53
53
  "convex": "^1.38.0",
54
54
  "lodash.throttle": "^4.1.1"
55
55
  }