@rtsdk/topia 0.19.0 → 0.19.2

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
@@ -40683,6 +40683,32 @@ class DroppedAsset extends Asset {
40683
40683
  }
40684
40684
  });
40685
40685
  }
40686
+ /**
40687
+ * Checks if this dropped asset exists with the current app's public key installed.
40688
+ *
40689
+ * @keywords check, exists, verify, validate, lookup
40690
+ *
40691
+ * @example
40692
+ * ```ts
40693
+ * const { exists } = await droppedAsset.checkExists();
40694
+ * ```
40695
+ *
40696
+ * @returns {Promise<{ exists: boolean }>} Returns whether the asset exists with the app's public key.
40697
+ */
40698
+ checkExists() {
40699
+ return __awaiter(this, void 0, void 0, function* () {
40700
+ try {
40701
+ const response = yield this.topiaPublicApi().get(`/world/${this.urlSlug}/dropped-asset/${this.id}/exists`, this.requestOptions);
40702
+ return response.data;
40703
+ }
40704
+ catch (error) {
40705
+ throw this.errorHandler({
40706
+ error,
40707
+ sdkMethod: "DroppedAsset.checkExists",
40708
+ });
40709
+ }
40710
+ });
40711
+ }
40686
40712
  /**
40687
40713
  * Retrieve analytics for a dropped asset by day, week, month, quarter, or year
40688
40714
  *
@@ -41013,7 +41039,7 @@ class UserInventoryItem extends InventoryItem {
41013
41039
  super(topia, item_id, { attributes: options.attributes, credentials: options.credentials });
41014
41040
  Object.assign(this, options.attributes);
41015
41041
  this.userItemId = id;
41016
- const { user_id = "", quantity = 0, grant_source = "unknown", type = "unknown", metadata = {}, created_at = new Date(), updated_at = new Date(), } = options.attributes;
41042
+ const { user_id = "", quantity = 0, grant_source = "unknown", type = "unknown", metadata = {}, created_at = new Date(), updated_at = new Date(), profile_id = null, } = options.attributes;
41017
41043
  this.item_id = item_id;
41018
41044
  this.quantity = quantity;
41019
41045
  this.grant_source = grant_source;
@@ -41022,6 +41048,7 @@ class UserInventoryItem extends InventoryItem {
41022
41048
  this.metadata = metadata;
41023
41049
  this.created_at = created_at;
41024
41050
  this.updated_at = updated_at;
41051
+ this.profile_id = profile_id;
41025
41052
  }
41026
41053
  /**
41027
41054
  * Fetches the user inventory item details from the platform and assigns them to this instance.
@@ -41490,8 +41517,16 @@ class World extends SDKController {
41490
41517
  fetchDroppedAssetsBySceneDropId({ sceneDropId, uniqueName, }) {
41491
41518
  return __awaiter(this, void 0, void 0, function* () {
41492
41519
  try {
41493
- if (!sceneDropId)
41494
- throw this.errorHandler({ message: "A sceneDropId is required." });
41520
+ // Validate sceneDropId to prevent dangerous queries that could match unintended assets
41521
+ if (!sceneDropId ||
41522
+ typeof sceneDropId !== "string" ||
41523
+ sceneDropId.trim() === "" ||
41524
+ sceneDropId === "undefined" ||
41525
+ sceneDropId === "null") {
41526
+ throw this.errorHandler({
41527
+ message: "A valid sceneDropId is required. Received an empty, undefined, or invalid sceneDropId which could match unintended assets.",
41528
+ });
41529
+ }
41495
41530
  const response = yield this.topiaPublicApi().get(`/world/${this.urlSlug}/assets-with-scene-drop-id/${sceneDropId}${uniqueName ? `?uniqueName=${uniqueName}` : ""}`, this.requestOptions);
41496
41531
  // create temp map and then update private property only once
41497
41532
  const droppedAssets = [];
@@ -43456,27 +43491,31 @@ class Visitor extends User {
43456
43491
  }
43457
43492
  /**
43458
43493
  * Modifies the quantity of an inventory item in this visitor's inventory.
43494
+ * Supports upsert behavior - if the visitor doesn't own the item yet, it will be granted first.
43459
43495
  *
43460
- * @param item The UserInventoryItem to modify.
43461
- * @param quantity The new quantity to set.
43496
+ * @param item Either a UserInventoryItem (for owned items) or an InventoryItem (for upsert).
43497
+ * @param quantity The quantity delta to apply (positive to add, negative to subtract).
43462
43498
  *
43463
43499
  * @example
43464
43500
  * ```ts
43465
- * await visitor.modifyInventoryItemQuantity("item-id-123", 5);
43501
+ * // Modify an existing user inventory item
43502
+ * await visitor.modifyInventoryItemQuantity(userItem, 5);
43503
+ *
43504
+ * // Upsert: grant if not owned, or modify if already owned
43505
+ * await visitor.modifyInventoryItemQuantity(inventoryItem, 1);
43466
43506
  * ```
43467
43507
  *
43468
43508
  * @returns {Promise<UserInventoryItem>} Returns the updated inventory item or a response object.
43469
43509
  */
43470
43510
  modifyInventoryItemQuantity(item, quantity) {
43471
- var _a;
43472
43511
  return __awaiter(this, void 0, void 0, function* () {
43473
- // Check for existence in #visitorInventoryItems
43474
- const found = (_a = __classPrivateFieldGet(this, _Visitor_visitorInventoryItems, "f")) === null || _a === void 0 ? void 0 : _a.some((visitorItem) => visitorItem.id === item.userItemId);
43475
- if (!found) {
43476
- throw new Error(`Inventory item with id '${item.userItemId}' does not exist in visitorInventoryItems.`);
43477
- }
43478
43512
  try {
43479
- const response = yield this.topiaPublicApi().put(`/world/${this.urlSlug}/visitors/${this.id}/update-visitor-inventory-item-quantity`, { userItemId: item.id, itemId: item.item_id, quantity }, this.requestOptions);
43513
+ // Determine if item is a UserInventoryItem (has userItemId) or InventoryItem (only has id)
43514
+ const isUserItem = "userItemId" in item && item.userItemId;
43515
+ const body = isUserItem
43516
+ ? { userItemId: item.userItemId, itemId: item.item_id, quantity }
43517
+ : { itemId: item.id, quantity };
43518
+ const response = yield this.topiaPublicApi().put(`/world/${this.urlSlug}/visitors/${this.id}/update-visitor-inventory-item-quantity`, body, this.requestOptions);
43480
43519
  const userInventoryItemFactory = new UserInventoryItemFactory(this.topia);
43481
43520
  const { inventoryItem, user_id, quantity: newQuantity } = response.data;
43482
43521
  return userInventoryItemFactory.create(inventoryItem, user_id, newQuantity, {
package/dist/index.d.ts CHANGED
@@ -74,7 +74,7 @@ type DroppedAssetLinkType = {
74
74
  linkSamlQueryParams?: string;
75
75
  };
76
76
 
77
- type InteractiveCredentials$1 = {
77
+ type InteractiveCredentials = {
78
78
  apiKey?: string;
79
79
  assetId?: string;
80
80
  interactiveNonce?: string;
@@ -88,22 +88,22 @@ type InteractiveCredentials$1 = {
88
88
 
89
89
  type AssetOptions = {
90
90
  attributes?: AssetInterface | undefined;
91
- credentials?: InteractiveCredentials$1 | undefined;
91
+ credentials?: InteractiveCredentials | undefined;
92
92
  };
93
93
  type DroppedAssetOptions = {
94
94
  attributes?: DroppedAssetInterface | undefined;
95
- credentials?: InteractiveCredentials$1 | undefined;
95
+ credentials?: InteractiveCredentials | undefined;
96
96
  };
97
97
  type UserOptions = {
98
- credentials?: InteractiveCredentials$1 | undefined;
98
+ credentials?: InteractiveCredentials | undefined;
99
99
  };
100
100
  type VisitorOptions = {
101
101
  attributes?: VisitorInterface | undefined;
102
- credentials?: InteractiveCredentials$1 | undefined;
102
+ credentials?: InteractiveCredentials | undefined;
103
103
  };
104
104
  type WorldOptions = {
105
105
  attributes?: WorldDetailsInterface | undefined;
106
- credentials?: InteractiveCredentials$1 | undefined;
106
+ credentials?: InteractiveCredentials | undefined;
107
107
  };
108
108
 
109
109
  type ResponseType$1 = {
@@ -651,6 +651,21 @@ declare class DroppedAsset extends Asset implements DroppedAssetInterface {
651
651
  isInteractive?: boolean;
652
652
  interactivePublicKey: string;
653
653
  }): Promise<void | ResponseType$1>;
654
+ /**
655
+ * Checks if this dropped asset exists with the current app's public key installed.
656
+ *
657
+ * @keywords check, exists, verify, validate, lookup
658
+ *
659
+ * @example
660
+ * ```ts
661
+ * const { exists } = await droppedAsset.checkExists();
662
+ * ```
663
+ *
664
+ * @returns {Promise<{ exists: boolean }>} Returns whether the asset exists with the app's public key.
665
+ */
666
+ checkExists(): Promise<{
667
+ exists: boolean;
668
+ }>;
654
669
  /**
655
670
  * Retrieve analytics for a dropped asset by day, week, month, quarter, or year
656
671
  *
@@ -1190,6 +1205,7 @@ declare class UserInventoryItem extends InventoryItem implements UserInventoryIt
1190
1205
  metadata?: object | null;
1191
1206
  grant_source: string;
1192
1207
  type: string;
1208
+ profile_id?: string | null;
1193
1209
  constructor(topia: Topia, id: string, options?: UserInventoryItemOptionalInterface);
1194
1210
  /**
1195
1211
  * Fetches the user inventory item details from the platform and assigns them to this instance.
@@ -2143,18 +2159,23 @@ declare class Visitor extends User implements VisitorInterface {
2143
2159
  grantInventoryItem(item: InventoryItem, quantity?: number): Promise<UserInventoryItem>;
2144
2160
  /**
2145
2161
  * Modifies the quantity of an inventory item in this visitor's inventory.
2162
+ * Supports upsert behavior - if the visitor doesn't own the item yet, it will be granted first.
2146
2163
  *
2147
- * @param item The UserInventoryItem to modify.
2148
- * @param quantity The new quantity to set.
2164
+ * @param item Either a UserInventoryItem (for owned items) or an InventoryItem (for upsert).
2165
+ * @param quantity The quantity delta to apply (positive to add, negative to subtract).
2149
2166
  *
2150
2167
  * @example
2151
2168
  * ```ts
2152
- * await visitor.modifyInventoryItemQuantity("item-id-123", 5);
2169
+ * // Modify an existing user inventory item
2170
+ * await visitor.modifyInventoryItemQuantity(userItem, 5);
2171
+ *
2172
+ * // Upsert: grant if not owned, or modify if already owned
2173
+ * await visitor.modifyInventoryItemQuantity(inventoryItem, 1);
2153
2174
  * ```
2154
2175
  *
2155
2176
  * @returns {Promise<UserInventoryItem>} Returns the updated inventory item or a response object.
2156
2177
  */
2157
- modifyInventoryItemQuantity(item: UserInventoryItem, quantity: number): Promise<UserInventoryItem>;
2178
+ modifyInventoryItemQuantity(item: UserInventoryItem | InventoryItem, quantity: number): Promise<UserInventoryItem>;
2158
2179
  }
2159
2180
 
2160
2181
  type VisitorType = {
@@ -2197,7 +2218,7 @@ declare enum WorldActivityType {
2197
2218
  }
2198
2219
 
2199
2220
  interface SDKInterface {
2200
- credentials?: InteractiveCredentials$1;
2221
+ credentials?: InteractiveCredentials;
2201
2222
  jwt?: string;
2202
2223
  requestOptions: object;
2203
2224
  topia: Topia;
@@ -2234,7 +2255,7 @@ interface AssetInterface extends SDKInterface {
2234
2255
  }
2235
2256
  type AssetOptionalInterface = {
2236
2257
  attributes?: AssetInterface | object;
2237
- credentials?: InteractiveCredentials$1;
2258
+ credentials?: InteractiveCredentials;
2238
2259
  };
2239
2260
 
2240
2261
  interface DroppedAssetInterface extends AssetInterface {
@@ -2356,7 +2377,7 @@ interface DroppedAssetOptionalInterface {
2356
2377
  text?: string;
2357
2378
  urlSlug?: string;
2358
2379
  };
2359
- credentials?: InteractiveCredentials$1 | object;
2380
+ credentials?: InteractiveCredentials | object;
2360
2381
  }
2361
2382
  interface UpdateBroadcastInterface {
2362
2383
  assetBroadcast?: boolean;
@@ -2448,7 +2469,7 @@ interface EcosystemInterface {
2448
2469
  incrementDataObjectValue(path: string, amount: number, options: object): Promise<void | ResponseType$1>;
2449
2470
  }
2450
2471
  interface EcosystemOptionalInterface {
2451
- credentials?: InteractiveCredentials$1;
2472
+ credentials?: InteractiveCredentials;
2452
2473
  }
2453
2474
 
2454
2475
  interface SceneInterface {
@@ -2476,7 +2497,7 @@ interface SceneInterface {
2476
2497
  }
2477
2498
  type SceneOptionalInterface = {
2478
2499
  attributes?: SceneInterface | object;
2479
- credentials?: InteractiveCredentials$1;
2500
+ credentials?: InteractiveCredentials;
2480
2501
  };
2481
2502
 
2482
2503
  interface FireToastInterface {
@@ -2524,7 +2545,7 @@ interface UserInterface {
2524
2545
  dataObject?: object | null;
2525
2546
  }
2526
2547
  interface UserOptionalInterface {
2527
- credentials?: InteractiveCredentials$1;
2548
+ credentials?: InteractiveCredentials;
2528
2549
  profileId?: string | null;
2529
2550
  visitorId?: number | null;
2530
2551
  urlSlug?: string;
@@ -2600,7 +2621,7 @@ interface VisitorInterface extends SDKInterface {
2600
2621
  }
2601
2622
  interface VisitorOptionalInterface {
2602
2623
  attributes?: VisitorInterface | object;
2603
- credentials?: InteractiveCredentials$1;
2624
+ credentials?: InteractiveCredentials;
2604
2625
  }
2605
2626
  interface MoveVisitorInterface {
2606
2627
  shouldTeleportVisitor: boolean;
@@ -2633,12 +2654,12 @@ interface WebRTCConnectorInterface {
2633
2654
  getTwilioConfig(): Promise<void | ResponseType$1>;
2634
2655
  }
2635
2656
  interface WebRTCConnectorOptionalInterface {
2636
- credentials?: InteractiveCredentials$1;
2657
+ credentials?: InteractiveCredentials;
2637
2658
  twilioConfig?: object;
2638
2659
  }
2639
2660
 
2640
2661
  interface WorldActivityOptionalInterface {
2641
- credentials?: InteractiveCredentials$1;
2662
+ credentials?: InteractiveCredentials;
2642
2663
  }
2643
2664
  interface MoveAllVisitorsInterface {
2644
2665
  shouldFetchVisitors?: boolean;
@@ -2728,13 +2749,13 @@ interface WorldInterface extends SDKInterface, WorldDetailsInterface {
2728
2749
  }
2729
2750
  interface WorldOptionalInterface {
2730
2751
  attributes?: WorldDetailsInterface | object;
2731
- credentials?: InteractiveCredentials$1;
2752
+ credentials?: InteractiveCredentials;
2732
2753
  }
2733
2754
  interface WorldWebhooksInterface {
2734
2755
  webhooks: Array<WebhookInterface>;
2735
2756
  }
2736
2757
 
2737
- type InteractiveCredentials = {
2758
+ type InteractiveCredentials$1 = {
2738
2759
  apiKey?: string;
2739
2760
  assetId?: string;
2740
2761
  interactiveNonce?: string;
@@ -2763,7 +2784,7 @@ interface InventoryItemInterface extends SDKInterface {
2763
2784
  }
2764
2785
  type InventoryItemOptionalInterface = {
2765
2786
  attributes?: InventoryItemInterface | object;
2766
- credentials?: InteractiveCredentials;
2787
+ credentials?: InteractiveCredentials$1;
2767
2788
  };
2768
2789
 
2769
2790
  /**
@@ -2778,10 +2799,11 @@ interface UserInventoryItemInterface extends InventoryItemInterface {
2778
2799
  updated_at?: Date;
2779
2800
  metadata?: object | null;
2780
2801
  grant_source: string;
2802
+ profile_id?: string | null;
2781
2803
  }
2782
2804
  type UserInventoryItemOptionalInterface = {
2783
2805
  attributes?: UserInventoryItemInterface | object;
2784
- credentials?: InteractiveCredentials;
2806
+ credentials?: InteractiveCredentials$1;
2785
2807
  };
2786
2808
 
2787
2809
  /**
@@ -2837,11 +2859,11 @@ declare class Topia implements TopiaInterface {
2837
2859
  * ```
2838
2860
  */
2839
2861
  declare abstract class SDKController implements SDKInterface {
2840
- credentials: InteractiveCredentials$1 | undefined;
2862
+ credentials: InteractiveCredentials | undefined;
2841
2863
  jwt?: string;
2842
2864
  requestOptions: object;
2843
2865
  topia: Topia;
2844
- constructor(topia: Topia, credentials?: InteractiveCredentials$1);
2866
+ constructor(topia: Topia, credentials?: InteractiveCredentials);
2845
2867
  topiaPublicApi(): axios.AxiosInstance;
2846
2868
  errorHandler({ error, message, params, sdkMethod, }: {
2847
2869
  error?: Error | AxiosError | unknown;
@@ -3421,7 +3443,7 @@ declare class DroppedAssetFactory extends SDKController {
3421
3443
  *
3422
3444
  * @returns {Promise<DroppedAsset>} Returns a new DroppedAsset object with all properties already fetched.
3423
3445
  */
3424
- getWithUniqueName(uniqueName: string, urlSlug: string, interactiveSecret: string, credentials: InteractiveCredentials$1): Promise<DroppedAsset>;
3446
+ getWithUniqueName(uniqueName: string, urlSlug: string, interactiveSecret: string, credentials: InteractiveCredentials): Promise<DroppedAsset>;
3425
3447
  /**
3426
3448
  * Drops an asset in a world and returns a new instance of DroppedAsset class with all properties.
3427
3449
  *
@@ -4003,4 +4025,4 @@ declare class WorldFactory extends SDKController {
4003
4025
  }>;
4004
4026
  }
4005
4027
 
4006
- export { AnalyticType, AnimationMetaType, Asset, AssetFactory, AssetInterface, AssetOptionalInterface, AssetOptions, AssetType, DroppedAsset, DroppedAssetClickType, DroppedAssetFactory, DroppedAssetInterface, DroppedAssetLinkType, DroppedAssetMediaType, DroppedAssetMediaVolumeRadius, DroppedAssetOptionalInterface, DroppedAssetOptions, Ecosystem, EcosystemFactory, EcosystemInterface, EcosystemOptionalInterface, FireToastInterface, FrameType, InteractiveCredentials$1 as InteractiveCredentials, InventoryItemInterface, InventoryItemOptionalInterface, MoveAllVisitorsInterface, MoveVisitorInterface, OpenIframeInterface, RemoveClickableLinkInterface, ResponseType$1 as ResponseType, SDKController, SDKInterface, Scene, SceneFactory, SceneInterface, SceneOptionalInterface, SetClickableLinkMultiInterface, Topia, TopiaInterface, UpdateBroadcastInterface, UpdateClickTypeInterface, UpdateClickableLinkMultiInterface, UpdateDroppedAssetInterface, UpdateMediaTypeInterface, UpdatePrivateZoneInterface, User, UserFactory, UserInterface, UserInventoryItemInterface, UserInventoryItemOptionalInterface, UserOptionalInterface, UserOptions, Visitor, VisitorFactory, VisitorInterface, VisitorOptionalInterface, VisitorOptions, VisitorType, VisitorsToMoveArrayType, VisitorsToMoveType, WebRTCConnector, WebRTCConnectorFactory, WebRTCConnectorInterface, WebRTCConnectorOptionalInterface, WebhookInterface, World, WorldActivity, WorldActivityFactory, WorldActivityOptionalInterface, WorldActivityType, WorldDetailsInterface, WorldFactory, WorldInterface, WorldOptionalInterface, WorldOptions, WorldWebhooksInterface };
4028
+ export { AnalyticType, AnimationMetaType, Asset, AssetFactory, AssetInterface, AssetOptionalInterface, AssetOptions, AssetType, DroppedAsset, DroppedAssetClickType, DroppedAssetFactory, DroppedAssetInterface, DroppedAssetLinkType, DroppedAssetMediaType, DroppedAssetMediaVolumeRadius, DroppedAssetOptionalInterface, DroppedAssetOptions, Ecosystem, EcosystemFactory, EcosystemInterface, EcosystemOptionalInterface, FireToastInterface, FrameType, InteractiveCredentials, InventoryItemInterface, InventoryItemOptionalInterface, MoveAllVisitorsInterface, MoveVisitorInterface, OpenIframeInterface, RemoveClickableLinkInterface, ResponseType$1 as ResponseType, SDKController, SDKInterface, Scene, SceneFactory, SceneInterface, SceneOptionalInterface, SetClickableLinkMultiInterface, Topia, TopiaInterface, UpdateBroadcastInterface, UpdateClickTypeInterface, UpdateClickableLinkMultiInterface, UpdateDroppedAssetInterface, UpdateMediaTypeInterface, UpdatePrivateZoneInterface, User, UserFactory, UserInterface, UserInventoryItemInterface, UserInventoryItemOptionalInterface, UserOptionalInterface, UserOptions, Visitor, VisitorFactory, VisitorInterface, VisitorOptionalInterface, VisitorOptions, VisitorType, VisitorsToMoveArrayType, VisitorsToMoveType, WebRTCConnector, WebRTCConnectorFactory, WebRTCConnectorInterface, WebRTCConnectorOptionalInterface, WebhookInterface, World, WorldActivity, WorldActivityFactory, WorldActivityOptionalInterface, WorldActivityType, WorldDetailsInterface, WorldFactory, WorldInterface, WorldOptionalInterface, WorldOptions, WorldWebhooksInterface };
package/dist/index.js CHANGED
@@ -40681,6 +40681,32 @@ class DroppedAsset extends Asset {
40681
40681
  }
40682
40682
  });
40683
40683
  }
40684
+ /**
40685
+ * Checks if this dropped asset exists with the current app's public key installed.
40686
+ *
40687
+ * @keywords check, exists, verify, validate, lookup
40688
+ *
40689
+ * @example
40690
+ * ```ts
40691
+ * const { exists } = await droppedAsset.checkExists();
40692
+ * ```
40693
+ *
40694
+ * @returns {Promise<{ exists: boolean }>} Returns whether the asset exists with the app's public key.
40695
+ */
40696
+ checkExists() {
40697
+ return __awaiter(this, void 0, void 0, function* () {
40698
+ try {
40699
+ const response = yield this.topiaPublicApi().get(`/world/${this.urlSlug}/dropped-asset/${this.id}/exists`, this.requestOptions);
40700
+ return response.data;
40701
+ }
40702
+ catch (error) {
40703
+ throw this.errorHandler({
40704
+ error,
40705
+ sdkMethod: "DroppedAsset.checkExists",
40706
+ });
40707
+ }
40708
+ });
40709
+ }
40684
40710
  /**
40685
40711
  * Retrieve analytics for a dropped asset by day, week, month, quarter, or year
40686
40712
  *
@@ -41011,7 +41037,7 @@ class UserInventoryItem extends InventoryItem {
41011
41037
  super(topia, item_id, { attributes: options.attributes, credentials: options.credentials });
41012
41038
  Object.assign(this, options.attributes);
41013
41039
  this.userItemId = id;
41014
- const { user_id = "", quantity = 0, grant_source = "unknown", type = "unknown", metadata = {}, created_at = new Date(), updated_at = new Date(), } = options.attributes;
41040
+ const { user_id = "", quantity = 0, grant_source = "unknown", type = "unknown", metadata = {}, created_at = new Date(), updated_at = new Date(), profile_id = null, } = options.attributes;
41015
41041
  this.item_id = item_id;
41016
41042
  this.quantity = quantity;
41017
41043
  this.grant_source = grant_source;
@@ -41020,6 +41046,7 @@ class UserInventoryItem extends InventoryItem {
41020
41046
  this.metadata = metadata;
41021
41047
  this.created_at = created_at;
41022
41048
  this.updated_at = updated_at;
41049
+ this.profile_id = profile_id;
41023
41050
  }
41024
41051
  /**
41025
41052
  * Fetches the user inventory item details from the platform and assigns them to this instance.
@@ -41488,8 +41515,16 @@ class World extends SDKController {
41488
41515
  fetchDroppedAssetsBySceneDropId({ sceneDropId, uniqueName, }) {
41489
41516
  return __awaiter(this, void 0, void 0, function* () {
41490
41517
  try {
41491
- if (!sceneDropId)
41492
- throw this.errorHandler({ message: "A sceneDropId is required." });
41518
+ // Validate sceneDropId to prevent dangerous queries that could match unintended assets
41519
+ if (!sceneDropId ||
41520
+ typeof sceneDropId !== "string" ||
41521
+ sceneDropId.trim() === "" ||
41522
+ sceneDropId === "undefined" ||
41523
+ sceneDropId === "null") {
41524
+ throw this.errorHandler({
41525
+ message: "A valid sceneDropId is required. Received an empty, undefined, or invalid sceneDropId which could match unintended assets.",
41526
+ });
41527
+ }
41493
41528
  const response = yield this.topiaPublicApi().get(`/world/${this.urlSlug}/assets-with-scene-drop-id/${sceneDropId}${uniqueName ? `?uniqueName=${uniqueName}` : ""}`, this.requestOptions);
41494
41529
  // create temp map and then update private property only once
41495
41530
  const droppedAssets = [];
@@ -43454,27 +43489,31 @@ class Visitor extends User {
43454
43489
  }
43455
43490
  /**
43456
43491
  * Modifies the quantity of an inventory item in this visitor's inventory.
43492
+ * Supports upsert behavior - if the visitor doesn't own the item yet, it will be granted first.
43457
43493
  *
43458
- * @param item The UserInventoryItem to modify.
43459
- * @param quantity The new quantity to set.
43494
+ * @param item Either a UserInventoryItem (for owned items) or an InventoryItem (for upsert).
43495
+ * @param quantity The quantity delta to apply (positive to add, negative to subtract).
43460
43496
  *
43461
43497
  * @example
43462
43498
  * ```ts
43463
- * await visitor.modifyInventoryItemQuantity("item-id-123", 5);
43499
+ * // Modify an existing user inventory item
43500
+ * await visitor.modifyInventoryItemQuantity(userItem, 5);
43501
+ *
43502
+ * // Upsert: grant if not owned, or modify if already owned
43503
+ * await visitor.modifyInventoryItemQuantity(inventoryItem, 1);
43464
43504
  * ```
43465
43505
  *
43466
43506
  * @returns {Promise<UserInventoryItem>} Returns the updated inventory item or a response object.
43467
43507
  */
43468
43508
  modifyInventoryItemQuantity(item, quantity) {
43469
- var _a;
43470
43509
  return __awaiter(this, void 0, void 0, function* () {
43471
- // Check for existence in #visitorInventoryItems
43472
- const found = (_a = __classPrivateFieldGet(this, _Visitor_visitorInventoryItems, "f")) === null || _a === void 0 ? void 0 : _a.some((visitorItem) => visitorItem.id === item.userItemId);
43473
- if (!found) {
43474
- throw new Error(`Inventory item with id '${item.userItemId}' does not exist in visitorInventoryItems.`);
43475
- }
43476
43510
  try {
43477
- const response = yield this.topiaPublicApi().put(`/world/${this.urlSlug}/visitors/${this.id}/update-visitor-inventory-item-quantity`, { userItemId: item.id, itemId: item.item_id, quantity }, this.requestOptions);
43511
+ // Determine if item is a UserInventoryItem (has userItemId) or InventoryItem (only has id)
43512
+ const isUserItem = "userItemId" in item && item.userItemId;
43513
+ const body = isUserItem
43514
+ ? { userItemId: item.userItemId, itemId: item.item_id, quantity }
43515
+ : { itemId: item.id, quantity };
43516
+ const response = yield this.topiaPublicApi().put(`/world/${this.urlSlug}/visitors/${this.id}/update-visitor-inventory-item-quantity`, body, this.requestOptions);
43478
43517
  const userInventoryItemFactory = new UserInventoryItemFactory(this.topia);
43479
43518
  const { inventoryItem, user_id, quantity: newQuantity } = response.data;
43480
43519
  return userInventoryItemFactory.create(inventoryItem, user_id, newQuantity, {
package/package.json CHANGED
@@ -61,5 +61,5 @@
61
61
  "yalc-push": "yarn build && yalc publish --push --dev --no-scripts"
62
62
  },
63
63
  "type": "module",
64
- "version": "0.19.00"
64
+ "version": "0.19.02"
65
65
  }