@hyve-sdk/js 1.3.6 → 1.4.1

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.d.mts CHANGED
@@ -83,6 +83,43 @@ interface AdConfig$1 {
83
83
  /** Callback when user earns a reward (rewarded ads only) */
84
84
  onRewardEarned?: () => void;
85
85
  }
86
+ /**
87
+ * Persistent Game Data Types
88
+ */
89
+ /** Generic value type for game data storage - can be any JSON-serializable value */
90
+ type GameDataValue = string | number | boolean | null | GameDataValue[] | {
91
+ [key: string]: GameDataValue;
92
+ };
93
+ /** Single game data item with metadata */
94
+ interface GameDataItem {
95
+ key: string;
96
+ value: GameDataValue;
97
+ created_at: string;
98
+ updated_at: string;
99
+ }
100
+ /** Response from save operations */
101
+ interface SaveGameDataResponse {
102
+ success: boolean;
103
+ message: string;
104
+ }
105
+ /** Response when getting a single game data entry */
106
+ interface GetGameDataResponse {
107
+ data: GameDataItem;
108
+ }
109
+ /** Response when getting multiple game data entries */
110
+ interface GetGameDataBatchResponse {
111
+ data: GameDataItem[];
112
+ }
113
+ /** Response after deleting game data */
114
+ interface DeleteGameDataResponse {
115
+ success: boolean;
116
+ deleted_count: number;
117
+ }
118
+ /** Batch item for saving multiple entries */
119
+ interface GameDataBatchItem {
120
+ key: string;
121
+ value: GameDataValue;
122
+ }
86
123
 
87
124
  /**
88
125
  * Ads Service for Hyve SDK
@@ -392,6 +429,8 @@ interface HyveClientConfig extends TelemetryConfig {
392
429
  ads?: AdConfig$1;
393
430
  /** Billing configuration (disabled by default) */
394
431
  billing?: BillingConfig;
432
+ /** Storage mode for persistent game data - 'cloud' (default) or 'local' */
433
+ storageMode?: 'cloud' | 'local';
395
434
  }
396
435
  /**
397
436
  * HyveClient provides telemetry and authentication functionality for Hyve games
@@ -407,6 +446,9 @@ declare class HyveClient {
407
446
  private billingService;
408
447
  private billingConfig;
409
448
  private billingCallbacks;
449
+ private storageMode;
450
+ private cloudStorageAdapter;
451
+ private localStorageAdapter;
410
452
  /**
411
453
  * Creates a new HyveClient instance
412
454
  * @param config Optional configuration including telemetry and ads
@@ -497,6 +539,64 @@ declare class HyveClient {
497
539
  * Resets the client state
498
540
  */
499
541
  reset(): void;
542
+ /**
543
+ * Get the storage adapter based on mode
544
+ * @param mode Storage mode override (cloud or local)
545
+ */
546
+ private getStorageAdapter;
547
+ /**
548
+ * Save persistent game data
549
+ * @param key Data key
550
+ * @param value Data value (any JSON-serializable value)
551
+ * @param storage Storage mode override ('cloud' or 'local')
552
+ * @returns Promise resolving to save response
553
+ */
554
+ saveGameData(key: string, value: GameDataValue, storage?: 'cloud' | 'local'): Promise<SaveGameDataResponse>;
555
+ /**
556
+ * Batch save persistent game data
557
+ * @param items Array of key-value pairs to save
558
+ * @param storage Storage mode override ('cloud' or 'local')
559
+ * @returns Promise resolving to save response
560
+ */
561
+ batchSaveGameData(items: GameDataBatchItem[], storage?: 'cloud' | 'local'): Promise<SaveGameDataResponse>;
562
+ /**
563
+ * Get persistent game data
564
+ * @param key Data key
565
+ * @param storage Storage mode override ('cloud' or 'local')
566
+ * @returns Promise resolving to game data item or null if not found
567
+ */
568
+ getGameData(key: string, storage?: 'cloud' | 'local'): Promise<GameDataItem | null>;
569
+ /**
570
+ * Get multiple persistent game data entries
571
+ * @param keys Array of data keys
572
+ * @param storage Storage mode override ('cloud' or 'local')
573
+ * @returns Promise resolving to array of game data items
574
+ */
575
+ getMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise<GameDataItem[]>;
576
+ /**
577
+ * Delete persistent game data
578
+ * @param key Data key
579
+ * @param storage Storage mode override ('cloud' or 'local')
580
+ * @returns Promise resolving to boolean indicating if data was deleted
581
+ */
582
+ deleteGameData(key: string, storage?: 'cloud' | 'local'): Promise<boolean>;
583
+ /**
584
+ * Delete multiple persistent game data entries
585
+ * @param keys Array of data keys
586
+ * @param storage Storage mode override ('cloud' or 'local')
587
+ * @returns Promise resolving to number of entries deleted
588
+ */
589
+ deleteMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise<number>;
590
+ /**
591
+ * Configure storage mode
592
+ * @param mode Storage mode ('cloud' or 'local')
593
+ */
594
+ configureStorage(mode: 'cloud' | 'local'): void;
595
+ /**
596
+ * Get current storage mode
597
+ * @returns Current storage mode
598
+ */
599
+ getStorageMode(): 'cloud' | 'local';
500
600
  /**
501
601
  * Configure ads service
502
602
  * @param config Ads configuration
@@ -574,6 +674,47 @@ declare class HyveClient {
574
674
  onBillingLog(callback: (level: "info" | "warn" | "error", message: string, data?: any) => void): void;
575
675
  }
576
676
 
677
+ /**
678
+ * Storage adapter interface - supports cloud and local implementations
679
+ */
680
+ interface StorageAdapter {
681
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
682
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
683
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
684
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
685
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
686
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
687
+ }
688
+ /**
689
+ * Cloud storage adapter - stores data via API calls to backend
690
+ */
691
+ declare class CloudStorageAdapter implements StorageAdapter {
692
+ private callApi;
693
+ constructor(callApi: <T = any>(endpoint: string, options?: RequestInit) => Promise<T>);
694
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
695
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
696
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
697
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
698
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
699
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
700
+ }
701
+ /**
702
+ * Local storage adapter - stores data in browser's localStorage
703
+ * Namespaced by game_id only (device-specific storage)
704
+ */
705
+ declare class LocalStorageAdapter implements StorageAdapter {
706
+ private getUserId;
707
+ private readonly storagePrefix;
708
+ constructor(getUserId: () => string | null);
709
+ private getStorageKey;
710
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
711
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
712
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
713
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
714
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
715
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
716
+ }
717
+
577
718
  /**
578
719
  * Logger utility for the Hyve SDK
579
720
  * Automatically enabled in development (NODE_ENV !== 'production')
@@ -847,4 +988,4 @@ declare class NativeBridge {
847
988
  */
848
989
  declare function generateUUID(): string;
849
990
 
850
- export { type AdConfig$1 as AdConfig, type AdResult, type AdType, AdsService, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, type PurchaseResult, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, logger, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
991
+ export { type AdConfig$1 as AdConfig, type AdResult, type AdType, AdsService, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, logger, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
package/dist/index.d.ts CHANGED
@@ -83,6 +83,43 @@ interface AdConfig$1 {
83
83
  /** Callback when user earns a reward (rewarded ads only) */
84
84
  onRewardEarned?: () => void;
85
85
  }
86
+ /**
87
+ * Persistent Game Data Types
88
+ */
89
+ /** Generic value type for game data storage - can be any JSON-serializable value */
90
+ type GameDataValue = string | number | boolean | null | GameDataValue[] | {
91
+ [key: string]: GameDataValue;
92
+ };
93
+ /** Single game data item with metadata */
94
+ interface GameDataItem {
95
+ key: string;
96
+ value: GameDataValue;
97
+ created_at: string;
98
+ updated_at: string;
99
+ }
100
+ /** Response from save operations */
101
+ interface SaveGameDataResponse {
102
+ success: boolean;
103
+ message: string;
104
+ }
105
+ /** Response when getting a single game data entry */
106
+ interface GetGameDataResponse {
107
+ data: GameDataItem;
108
+ }
109
+ /** Response when getting multiple game data entries */
110
+ interface GetGameDataBatchResponse {
111
+ data: GameDataItem[];
112
+ }
113
+ /** Response after deleting game data */
114
+ interface DeleteGameDataResponse {
115
+ success: boolean;
116
+ deleted_count: number;
117
+ }
118
+ /** Batch item for saving multiple entries */
119
+ interface GameDataBatchItem {
120
+ key: string;
121
+ value: GameDataValue;
122
+ }
86
123
 
87
124
  /**
88
125
  * Ads Service for Hyve SDK
@@ -392,6 +429,8 @@ interface HyveClientConfig extends TelemetryConfig {
392
429
  ads?: AdConfig$1;
393
430
  /** Billing configuration (disabled by default) */
394
431
  billing?: BillingConfig;
432
+ /** Storage mode for persistent game data - 'cloud' (default) or 'local' */
433
+ storageMode?: 'cloud' | 'local';
395
434
  }
396
435
  /**
397
436
  * HyveClient provides telemetry and authentication functionality for Hyve games
@@ -407,6 +446,9 @@ declare class HyveClient {
407
446
  private billingService;
408
447
  private billingConfig;
409
448
  private billingCallbacks;
449
+ private storageMode;
450
+ private cloudStorageAdapter;
451
+ private localStorageAdapter;
410
452
  /**
411
453
  * Creates a new HyveClient instance
412
454
  * @param config Optional configuration including telemetry and ads
@@ -497,6 +539,64 @@ declare class HyveClient {
497
539
  * Resets the client state
498
540
  */
499
541
  reset(): void;
542
+ /**
543
+ * Get the storage adapter based on mode
544
+ * @param mode Storage mode override (cloud or local)
545
+ */
546
+ private getStorageAdapter;
547
+ /**
548
+ * Save persistent game data
549
+ * @param key Data key
550
+ * @param value Data value (any JSON-serializable value)
551
+ * @param storage Storage mode override ('cloud' or 'local')
552
+ * @returns Promise resolving to save response
553
+ */
554
+ saveGameData(key: string, value: GameDataValue, storage?: 'cloud' | 'local'): Promise<SaveGameDataResponse>;
555
+ /**
556
+ * Batch save persistent game data
557
+ * @param items Array of key-value pairs to save
558
+ * @param storage Storage mode override ('cloud' or 'local')
559
+ * @returns Promise resolving to save response
560
+ */
561
+ batchSaveGameData(items: GameDataBatchItem[], storage?: 'cloud' | 'local'): Promise<SaveGameDataResponse>;
562
+ /**
563
+ * Get persistent game data
564
+ * @param key Data key
565
+ * @param storage Storage mode override ('cloud' or 'local')
566
+ * @returns Promise resolving to game data item or null if not found
567
+ */
568
+ getGameData(key: string, storage?: 'cloud' | 'local'): Promise<GameDataItem | null>;
569
+ /**
570
+ * Get multiple persistent game data entries
571
+ * @param keys Array of data keys
572
+ * @param storage Storage mode override ('cloud' or 'local')
573
+ * @returns Promise resolving to array of game data items
574
+ */
575
+ getMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise<GameDataItem[]>;
576
+ /**
577
+ * Delete persistent game data
578
+ * @param key Data key
579
+ * @param storage Storage mode override ('cloud' or 'local')
580
+ * @returns Promise resolving to boolean indicating if data was deleted
581
+ */
582
+ deleteGameData(key: string, storage?: 'cloud' | 'local'): Promise<boolean>;
583
+ /**
584
+ * Delete multiple persistent game data entries
585
+ * @param keys Array of data keys
586
+ * @param storage Storage mode override ('cloud' or 'local')
587
+ * @returns Promise resolving to number of entries deleted
588
+ */
589
+ deleteMultipleGameData(keys: string[], storage?: 'cloud' | 'local'): Promise<number>;
590
+ /**
591
+ * Configure storage mode
592
+ * @param mode Storage mode ('cloud' or 'local')
593
+ */
594
+ configureStorage(mode: 'cloud' | 'local'): void;
595
+ /**
596
+ * Get current storage mode
597
+ * @returns Current storage mode
598
+ */
599
+ getStorageMode(): 'cloud' | 'local';
500
600
  /**
501
601
  * Configure ads service
502
602
  * @param config Ads configuration
@@ -574,6 +674,47 @@ declare class HyveClient {
574
674
  onBillingLog(callback: (level: "info" | "warn" | "error", message: string, data?: any) => void): void;
575
675
  }
576
676
 
677
+ /**
678
+ * Storage adapter interface - supports cloud and local implementations
679
+ */
680
+ interface StorageAdapter {
681
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
682
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
683
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
684
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
685
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
686
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
687
+ }
688
+ /**
689
+ * Cloud storage adapter - stores data via API calls to backend
690
+ */
691
+ declare class CloudStorageAdapter implements StorageAdapter {
692
+ private callApi;
693
+ constructor(callApi: <T = any>(endpoint: string, options?: RequestInit) => Promise<T>);
694
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
695
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
696
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
697
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
698
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
699
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
700
+ }
701
+ /**
702
+ * Local storage adapter - stores data in browser's localStorage
703
+ * Namespaced by game_id only (device-specific storage)
704
+ */
705
+ declare class LocalStorageAdapter implements StorageAdapter {
706
+ private getUserId;
707
+ private readonly storagePrefix;
708
+ constructor(getUserId: () => string | null);
709
+ private getStorageKey;
710
+ saveGameData(gameId: string, key: string, value: GameDataValue): Promise<SaveGameDataResponse>;
711
+ batchSaveGameData(gameId: string, items: GameDataBatchItem[]): Promise<SaveGameDataResponse>;
712
+ getGameData(gameId: string, key: string): Promise<GameDataItem | null>;
713
+ getMultipleGameData(gameId: string, keys: string[]): Promise<GameDataItem[]>;
714
+ deleteGameData(gameId: string, key: string): Promise<boolean>;
715
+ deleteMultipleGameData(gameId: string, keys: string[]): Promise<number>;
716
+ }
717
+
577
718
  /**
578
719
  * Logger utility for the Hyve SDK
579
720
  * Automatically enabled in development (NODE_ENV !== 'production')
@@ -847,4 +988,4 @@ declare class NativeBridge {
847
988
  */
848
989
  declare function generateUUID(): string;
849
990
 
850
- export { type AdConfig$1 as AdConfig, type AdResult, type AdType, AdsService, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, type PurchaseResult, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, logger, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
991
+ export { type AdConfig$1 as AdConfig, type AdResult, type AdType, AdsService, type BillingConfig, BillingPlatform, type BillingProduct, BillingService, CloudStorageAdapter, type DeleteGameDataResponse, type GameDataBatchItem, type GameDataItem, type GameDataValue, type GetGameDataBatchResponse, type GetGameDataResponse, HyveClient, type HyveClientConfig, type Inventory, type InventoryItem, LocalStorageAdapter, Logger, NativeBridge, type NativeMessage, type NativeMessageHandler, NativeMessageType, type PurchaseResult, type SaveGameDataResponse, type StorageAdapter, type TelemetryAdditionalData, type TelemetryConfig, type TelemetryEvent, generateUUID, handleVerifyMessage, isDomainAllowed, logger, parseUrlParams, validateSignature, verifyAuthentication, verifyHyveToken };
package/dist/index.js CHANGED
@@ -23,7 +23,9 @@ __export(index_exports, {
23
23
  AdsService: () => AdsService,
24
24
  BillingPlatform: () => BillingPlatform,
25
25
  BillingService: () => BillingService,
26
+ CloudStorageAdapter: () => CloudStorageAdapter,
26
27
  HyveClient: () => HyveClient,
28
+ LocalStorageAdapter: () => LocalStorageAdapter,
27
29
  Logger: () => Logger,
28
30
  NativeBridge: () => NativeBridge,
29
31
  NativeMessageType: () => NativeMessageType,
@@ -1249,14 +1251,21 @@ var BillingService = class {
1249
1251
  throw new Error("Stripe not initialized");
1250
1252
  }
1251
1253
  try {
1254
+ if (this.checkoutElement) {
1255
+ this.log("info", "[BillingService] Unmounting existing checkout element");
1256
+ this.unmountCheckoutElement();
1257
+ await new Promise((resolve) => setTimeout(resolve, 100));
1258
+ }
1252
1259
  const container = document.getElementById(elementId);
1253
1260
  if (!container) {
1254
1261
  throw new Error(`Element with id "${elementId}" not found in the DOM`);
1255
1262
  }
1256
1263
  container.innerHTML = "";
1264
+ this.log("info", "[BillingService] Creating new checkout instance");
1257
1265
  this.checkoutElement = await this.stripe.initEmbeddedCheckout({
1258
1266
  clientSecret
1259
1267
  });
1268
+ this.log("info", "[BillingService] Mounting checkout element to DOM");
1260
1269
  this.checkoutElement.mount(`#${elementId}`);
1261
1270
  this.setupCheckoutEventListeners();
1262
1271
  } catch (error) {
@@ -1294,7 +1303,14 @@ var BillingService = class {
1294
1303
  */
1295
1304
  unmountCheckoutElement() {
1296
1305
  if (this.checkoutElement) {
1297
- this.checkoutElement.unmount();
1306
+ try {
1307
+ this.checkoutElement.unmount();
1308
+ if (typeof this.checkoutElement.destroy === "function") {
1309
+ this.checkoutElement.destroy();
1310
+ }
1311
+ } catch (error) {
1312
+ this.log("warn", "[BillingService] Error unmounting checkout element:", error?.message);
1313
+ }
1298
1314
  this.checkoutElement = null;
1299
1315
  }
1300
1316
  }
@@ -1330,6 +1346,133 @@ var BillingService = class {
1330
1346
  }
1331
1347
  };
1332
1348
 
1349
+ // src/services/storage.ts
1350
+ var CloudStorageAdapter = class {
1351
+ constructor(callApi) {
1352
+ this.callApi = callApi;
1353
+ }
1354
+ async saveGameData(gameId, key, value) {
1355
+ return this.callApi("/api/v1/persistent-game-data", {
1356
+ method: "POST",
1357
+ headers: {
1358
+ "Content-Type": "application/json"
1359
+ },
1360
+ body: JSON.stringify({ game_id: gameId, key, value })
1361
+ });
1362
+ }
1363
+ async batchSaveGameData(gameId, items) {
1364
+ return this.callApi(
1365
+ "/api/v1/persistent-game-data/batch",
1366
+ {
1367
+ method: "POST",
1368
+ headers: {
1369
+ "Content-Type": "application/json"
1370
+ },
1371
+ body: JSON.stringify({ game_id: gameId, items })
1372
+ }
1373
+ );
1374
+ }
1375
+ async getGameData(gameId, key) {
1376
+ try {
1377
+ const params = new URLSearchParams({ game_id: gameId, key });
1378
+ const response = await this.callApi(
1379
+ `/api/v1/persistent-game-data?${params}`
1380
+ );
1381
+ return response.data;
1382
+ } catch (error) {
1383
+ if (error instanceof Error && error.message.includes("404")) {
1384
+ return null;
1385
+ }
1386
+ throw error;
1387
+ }
1388
+ }
1389
+ async getMultipleGameData(gameId, keys) {
1390
+ const params = new URLSearchParams({ game_id: gameId });
1391
+ keys.forEach((key) => params.append("keys", key));
1392
+ const response = await this.callApi(
1393
+ `/api/v1/persistent-game-data?${params}`
1394
+ );
1395
+ return response.data;
1396
+ }
1397
+ async deleteGameData(gameId, key) {
1398
+ try {
1399
+ const params = new URLSearchParams({ game_id: gameId, key });
1400
+ const response = await this.callApi(
1401
+ `/api/v1/persistent-game-data?${params}`,
1402
+ { method: "DELETE" }
1403
+ );
1404
+ return response.success && response.deleted_count > 0;
1405
+ } catch (error) {
1406
+ if (error instanceof Error && error.message.includes("404")) {
1407
+ return false;
1408
+ }
1409
+ throw error;
1410
+ }
1411
+ }
1412
+ async deleteMultipleGameData(gameId, keys) {
1413
+ const params = new URLSearchParams({ game_id: gameId });
1414
+ keys.forEach((key) => params.append("keys", key));
1415
+ const response = await this.callApi(
1416
+ `/api/v1/persistent-game-data?${params}`,
1417
+ { method: "DELETE" }
1418
+ );
1419
+ return response.deleted_count;
1420
+ }
1421
+ };
1422
+ var LocalStorageAdapter = class {
1423
+ constructor(getUserId) {
1424
+ this.getUserId = getUserId;
1425
+ }
1426
+ storagePrefix = "hyve_game_data";
1427
+ getStorageKey(gameId, key) {
1428
+ return `${this.storagePrefix}:${gameId}:${key}`;
1429
+ }
1430
+ async saveGameData(gameId, key, value) {
1431
+ try {
1432
+ const storageKey = this.getStorageKey(gameId, key);
1433
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1434
+ const existing = localStorage.getItem(storageKey);
1435
+ const createdAt = existing ? JSON.parse(existing).created_at || now : now;
1436
+ const item = { key, value, created_at: createdAt, updated_at: now };
1437
+ localStorage.setItem(storageKey, JSON.stringify(item));
1438
+ return { success: true, message: "Data saved successfully" };
1439
+ } catch (error) {
1440
+ throw new Error(`Failed to save: ${error instanceof Error ? error.message : "Unknown"}`);
1441
+ }
1442
+ }
1443
+ async batchSaveGameData(gameId, items) {
1444
+ for (const item of items) {
1445
+ await this.saveGameData(gameId, item.key, item.value);
1446
+ }
1447
+ return { success: true, message: `${items.length} items saved` };
1448
+ }
1449
+ async getGameData(gameId, key) {
1450
+ const data = localStorage.getItem(this.getStorageKey(gameId, key));
1451
+ return data ? JSON.parse(data) : null;
1452
+ }
1453
+ async getMultipleGameData(gameId, keys) {
1454
+ const items = [];
1455
+ for (const key of keys) {
1456
+ const item = await this.getGameData(gameId, key);
1457
+ if (item) items.push(item);
1458
+ }
1459
+ return items;
1460
+ }
1461
+ async deleteGameData(gameId, key) {
1462
+ const storageKey = this.getStorageKey(gameId, key);
1463
+ const exists = localStorage.getItem(storageKey) !== null;
1464
+ if (exists) localStorage.removeItem(storageKey);
1465
+ return exists;
1466
+ }
1467
+ async deleteMultipleGameData(gameId, keys) {
1468
+ let count = 0;
1469
+ for (const key of keys) {
1470
+ if (await this.deleteGameData(gameId, key)) count++;
1471
+ }
1472
+ return count;
1473
+ }
1474
+ };
1475
+
1333
1476
  // src/core/client.ts
1334
1477
  function determineEnvironmentFromParentUrl() {
1335
1478
  try {
@@ -1371,6 +1514,9 @@ var HyveClient = class {
1371
1514
  billingConfig;
1372
1515
  // Store callbacks to preserve them when recreating BillingService
1373
1516
  billingCallbacks = {};
1517
+ storageMode;
1518
+ cloudStorageAdapter;
1519
+ localStorageAdapter;
1374
1520
  /**
1375
1521
  * Creates a new HyveClient instance
1376
1522
  * @param config Optional configuration including telemetry and ads
@@ -1393,6 +1539,11 @@ var HyveClient = class {
1393
1539
  }
1394
1540
  this.billingConfig = config?.billing || {};
1395
1541
  this.billingService = new BillingService(this.billingConfig);
1542
+ this.storageMode = config?.storageMode || "cloud";
1543
+ this.cloudStorageAdapter = new CloudStorageAdapter(
1544
+ (endpoint, options) => this.callApi(endpoint, options)
1545
+ );
1546
+ this.localStorageAdapter = new LocalStorageAdapter(() => this.getUserId());
1396
1547
  const envSource = config?.isDev !== void 0 ? "explicit config" : "auto-detected from parent URL";
1397
1548
  logger.info("==========================================");
1398
1549
  logger.info("HyveClient Initialized");
@@ -1409,11 +1560,13 @@ var HyveClient = class {
1409
1560
  "Billing configured:",
1410
1561
  Object.keys(this.billingConfig).length > 0
1411
1562
  );
1563
+ logger.info("Storage mode:", this.storageMode);
1412
1564
  logger.debug("Config:", {
1413
1565
  isDev: this.telemetryConfig.isDev,
1414
1566
  hasCustomApiUrl: !!config?.apiBaseUrl,
1415
1567
  adsEnabled: config?.ads?.enabled || false,
1416
- billingConfigured: Object.keys(this.billingConfig).length > 0
1568
+ billingConfigured: Object.keys(this.billingConfig).length > 0,
1569
+ storageMode: this.storageMode
1417
1570
  });
1418
1571
  logger.info("==========================================");
1419
1572
  }
@@ -1678,6 +1831,146 @@ var HyveClient = class {
1678
1831
  this.sessionId = generateUUID();
1679
1832
  logger.info("Client reset with new sessionId:", this.sessionId);
1680
1833
  }
1834
+ /**
1835
+ * Get the storage adapter based on mode
1836
+ * @param mode Storage mode override (cloud or local)
1837
+ */
1838
+ getStorageAdapter(mode) {
1839
+ const storageMode = mode || this.storageMode;
1840
+ return storageMode === "local" ? this.localStorageAdapter : this.cloudStorageAdapter;
1841
+ }
1842
+ /**
1843
+ * Save persistent game data
1844
+ * @param key Data key
1845
+ * @param value Data value (any JSON-serializable value)
1846
+ * @param storage Storage mode override ('cloud' or 'local')
1847
+ * @returns Promise resolving to save response
1848
+ */
1849
+ async saveGameData(key, value, storage) {
1850
+ const gameId = this.getGameId();
1851
+ if (!gameId) {
1852
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1853
+ }
1854
+ const storageMode = storage || this.storageMode;
1855
+ logger.debug(`Saving game data to ${storageMode}: ${gameId}/${key}`);
1856
+ const adapter = this.getStorageAdapter(storage);
1857
+ const response = await adapter.saveGameData(gameId, key, value);
1858
+ logger.info(`Game data saved successfully to ${storageMode}: ${gameId}/${key}`);
1859
+ return response;
1860
+ }
1861
+ /**
1862
+ * Batch save persistent game data
1863
+ * @param items Array of key-value pairs to save
1864
+ * @param storage Storage mode override ('cloud' or 'local')
1865
+ * @returns Promise resolving to save response
1866
+ */
1867
+ async batchSaveGameData(items, storage) {
1868
+ const gameId = this.getGameId();
1869
+ if (!gameId) {
1870
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1871
+ }
1872
+ const storageMode = storage || this.storageMode;
1873
+ logger.debug(`Batch saving ${items.length} game data entries to ${storageMode} for game: ${gameId}`);
1874
+ const adapter = this.getStorageAdapter(storage);
1875
+ const response = await adapter.batchSaveGameData(gameId, items);
1876
+ logger.info(`Batch saved ${items.length} game data entries successfully to ${storageMode}`);
1877
+ return response;
1878
+ }
1879
+ /**
1880
+ * Get persistent game data
1881
+ * @param key Data key
1882
+ * @param storage Storage mode override ('cloud' or 'local')
1883
+ * @returns Promise resolving to game data item or null if not found
1884
+ */
1885
+ async getGameData(key, storage) {
1886
+ const gameId = this.getGameId();
1887
+ if (!gameId) {
1888
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1889
+ }
1890
+ const storageMode = storage || this.storageMode;
1891
+ logger.debug(`Getting game data from ${storageMode}: ${gameId}/${key}`);
1892
+ const adapter = this.getStorageAdapter(storage);
1893
+ const data = await adapter.getGameData(gameId, key);
1894
+ if (data) {
1895
+ logger.info(`Game data retrieved successfully from ${storageMode}: ${gameId}/${key}`);
1896
+ } else {
1897
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1898
+ }
1899
+ return data;
1900
+ }
1901
+ /**
1902
+ * Get multiple persistent game data entries
1903
+ * @param keys Array of data keys
1904
+ * @param storage Storage mode override ('cloud' or 'local')
1905
+ * @returns Promise resolving to array of game data items
1906
+ */
1907
+ async getMultipleGameData(keys, storage) {
1908
+ const gameId = this.getGameId();
1909
+ if (!gameId) {
1910
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1911
+ }
1912
+ const storageMode = storage || this.storageMode;
1913
+ logger.debug(`Getting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1914
+ const adapter = this.getStorageAdapter(storage);
1915
+ const data = await adapter.getMultipleGameData(gameId, keys);
1916
+ logger.info(`Retrieved ${data.length} game data entries from ${storageMode}`);
1917
+ return data;
1918
+ }
1919
+ /**
1920
+ * Delete persistent game data
1921
+ * @param key Data key
1922
+ * @param storage Storage mode override ('cloud' or 'local')
1923
+ * @returns Promise resolving to boolean indicating if data was deleted
1924
+ */
1925
+ async deleteGameData(key, storage) {
1926
+ const gameId = this.getGameId();
1927
+ if (!gameId) {
1928
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1929
+ }
1930
+ const storageMode = storage || this.storageMode;
1931
+ logger.debug(`Deleting game data from ${storageMode}: ${gameId}/${key}`);
1932
+ const adapter = this.getStorageAdapter(storage);
1933
+ const deleted = await adapter.deleteGameData(gameId, key);
1934
+ if (deleted) {
1935
+ logger.info(`Game data deleted successfully from ${storageMode}: ${gameId}/${key}`);
1936
+ } else {
1937
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1938
+ }
1939
+ return deleted;
1940
+ }
1941
+ /**
1942
+ * Delete multiple persistent game data entries
1943
+ * @param keys Array of data keys
1944
+ * @param storage Storage mode override ('cloud' or 'local')
1945
+ * @returns Promise resolving to number of entries deleted
1946
+ */
1947
+ async deleteMultipleGameData(keys, storage) {
1948
+ const gameId = this.getGameId();
1949
+ if (!gameId) {
1950
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1951
+ }
1952
+ const storageMode = storage || this.storageMode;
1953
+ logger.debug(`Deleting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1954
+ const adapter = this.getStorageAdapter(storage);
1955
+ const deletedCount = await adapter.deleteMultipleGameData(gameId, keys);
1956
+ logger.info(`Deleted ${deletedCount} game data entries from ${storageMode}`);
1957
+ return deletedCount;
1958
+ }
1959
+ /**
1960
+ * Configure storage mode
1961
+ * @param mode Storage mode ('cloud' or 'local')
1962
+ */
1963
+ configureStorage(mode) {
1964
+ this.storageMode = mode;
1965
+ logger.info("Storage mode updated to:", mode);
1966
+ }
1967
+ /**
1968
+ * Get current storage mode
1969
+ * @returns Current storage mode
1970
+ */
1971
+ getStorageMode() {
1972
+ return this.storageMode;
1973
+ }
1681
1974
  /**
1682
1975
  * Configure ads service
1683
1976
  * @param config Ads configuration
@@ -1815,7 +2108,9 @@ var HyveClient = class {
1815
2108
  AdsService,
1816
2109
  BillingPlatform,
1817
2110
  BillingService,
2111
+ CloudStorageAdapter,
1818
2112
  HyveClient,
2113
+ LocalStorageAdapter,
1819
2114
  Logger,
1820
2115
  NativeBridge,
1821
2116
  NativeMessageType,
package/dist/index.mjs CHANGED
@@ -1209,14 +1209,21 @@ var BillingService = class {
1209
1209
  throw new Error("Stripe not initialized");
1210
1210
  }
1211
1211
  try {
1212
+ if (this.checkoutElement) {
1213
+ this.log("info", "[BillingService] Unmounting existing checkout element");
1214
+ this.unmountCheckoutElement();
1215
+ await new Promise((resolve) => setTimeout(resolve, 100));
1216
+ }
1212
1217
  const container = document.getElementById(elementId);
1213
1218
  if (!container) {
1214
1219
  throw new Error(`Element with id "${elementId}" not found in the DOM`);
1215
1220
  }
1216
1221
  container.innerHTML = "";
1222
+ this.log("info", "[BillingService] Creating new checkout instance");
1217
1223
  this.checkoutElement = await this.stripe.initEmbeddedCheckout({
1218
1224
  clientSecret
1219
1225
  });
1226
+ this.log("info", "[BillingService] Mounting checkout element to DOM");
1220
1227
  this.checkoutElement.mount(`#${elementId}`);
1221
1228
  this.setupCheckoutEventListeners();
1222
1229
  } catch (error) {
@@ -1254,7 +1261,14 @@ var BillingService = class {
1254
1261
  */
1255
1262
  unmountCheckoutElement() {
1256
1263
  if (this.checkoutElement) {
1257
- this.checkoutElement.unmount();
1264
+ try {
1265
+ this.checkoutElement.unmount();
1266
+ if (typeof this.checkoutElement.destroy === "function") {
1267
+ this.checkoutElement.destroy();
1268
+ }
1269
+ } catch (error) {
1270
+ this.log("warn", "[BillingService] Error unmounting checkout element:", error?.message);
1271
+ }
1258
1272
  this.checkoutElement = null;
1259
1273
  }
1260
1274
  }
@@ -1290,6 +1304,133 @@ var BillingService = class {
1290
1304
  }
1291
1305
  };
1292
1306
 
1307
+ // src/services/storage.ts
1308
+ var CloudStorageAdapter = class {
1309
+ constructor(callApi) {
1310
+ this.callApi = callApi;
1311
+ }
1312
+ async saveGameData(gameId, key, value) {
1313
+ return this.callApi("/api/v1/persistent-game-data", {
1314
+ method: "POST",
1315
+ headers: {
1316
+ "Content-Type": "application/json"
1317
+ },
1318
+ body: JSON.stringify({ game_id: gameId, key, value })
1319
+ });
1320
+ }
1321
+ async batchSaveGameData(gameId, items) {
1322
+ return this.callApi(
1323
+ "/api/v1/persistent-game-data/batch",
1324
+ {
1325
+ method: "POST",
1326
+ headers: {
1327
+ "Content-Type": "application/json"
1328
+ },
1329
+ body: JSON.stringify({ game_id: gameId, items })
1330
+ }
1331
+ );
1332
+ }
1333
+ async getGameData(gameId, key) {
1334
+ try {
1335
+ const params = new URLSearchParams({ game_id: gameId, key });
1336
+ const response = await this.callApi(
1337
+ `/api/v1/persistent-game-data?${params}`
1338
+ );
1339
+ return response.data;
1340
+ } catch (error) {
1341
+ if (error instanceof Error && error.message.includes("404")) {
1342
+ return null;
1343
+ }
1344
+ throw error;
1345
+ }
1346
+ }
1347
+ async getMultipleGameData(gameId, keys) {
1348
+ const params = new URLSearchParams({ game_id: gameId });
1349
+ keys.forEach((key) => params.append("keys", key));
1350
+ const response = await this.callApi(
1351
+ `/api/v1/persistent-game-data?${params}`
1352
+ );
1353
+ return response.data;
1354
+ }
1355
+ async deleteGameData(gameId, key) {
1356
+ try {
1357
+ const params = new URLSearchParams({ game_id: gameId, key });
1358
+ const response = await this.callApi(
1359
+ `/api/v1/persistent-game-data?${params}`,
1360
+ { method: "DELETE" }
1361
+ );
1362
+ return response.success && response.deleted_count > 0;
1363
+ } catch (error) {
1364
+ if (error instanceof Error && error.message.includes("404")) {
1365
+ return false;
1366
+ }
1367
+ throw error;
1368
+ }
1369
+ }
1370
+ async deleteMultipleGameData(gameId, keys) {
1371
+ const params = new URLSearchParams({ game_id: gameId });
1372
+ keys.forEach((key) => params.append("keys", key));
1373
+ const response = await this.callApi(
1374
+ `/api/v1/persistent-game-data?${params}`,
1375
+ { method: "DELETE" }
1376
+ );
1377
+ return response.deleted_count;
1378
+ }
1379
+ };
1380
+ var LocalStorageAdapter = class {
1381
+ constructor(getUserId) {
1382
+ this.getUserId = getUserId;
1383
+ }
1384
+ storagePrefix = "hyve_game_data";
1385
+ getStorageKey(gameId, key) {
1386
+ return `${this.storagePrefix}:${gameId}:${key}`;
1387
+ }
1388
+ async saveGameData(gameId, key, value) {
1389
+ try {
1390
+ const storageKey = this.getStorageKey(gameId, key);
1391
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1392
+ const existing = localStorage.getItem(storageKey);
1393
+ const createdAt = existing ? JSON.parse(existing).created_at || now : now;
1394
+ const item = { key, value, created_at: createdAt, updated_at: now };
1395
+ localStorage.setItem(storageKey, JSON.stringify(item));
1396
+ return { success: true, message: "Data saved successfully" };
1397
+ } catch (error) {
1398
+ throw new Error(`Failed to save: ${error instanceof Error ? error.message : "Unknown"}`);
1399
+ }
1400
+ }
1401
+ async batchSaveGameData(gameId, items) {
1402
+ for (const item of items) {
1403
+ await this.saveGameData(gameId, item.key, item.value);
1404
+ }
1405
+ return { success: true, message: `${items.length} items saved` };
1406
+ }
1407
+ async getGameData(gameId, key) {
1408
+ const data = localStorage.getItem(this.getStorageKey(gameId, key));
1409
+ return data ? JSON.parse(data) : null;
1410
+ }
1411
+ async getMultipleGameData(gameId, keys) {
1412
+ const items = [];
1413
+ for (const key of keys) {
1414
+ const item = await this.getGameData(gameId, key);
1415
+ if (item) items.push(item);
1416
+ }
1417
+ return items;
1418
+ }
1419
+ async deleteGameData(gameId, key) {
1420
+ const storageKey = this.getStorageKey(gameId, key);
1421
+ const exists = localStorage.getItem(storageKey) !== null;
1422
+ if (exists) localStorage.removeItem(storageKey);
1423
+ return exists;
1424
+ }
1425
+ async deleteMultipleGameData(gameId, keys) {
1426
+ let count = 0;
1427
+ for (const key of keys) {
1428
+ if (await this.deleteGameData(gameId, key)) count++;
1429
+ }
1430
+ return count;
1431
+ }
1432
+ };
1433
+
1293
1434
  // src/core/client.ts
1294
1435
  function determineEnvironmentFromParentUrl() {
1295
1436
  try {
@@ -1331,6 +1472,9 @@ var HyveClient = class {
1331
1472
  billingConfig;
1332
1473
  // Store callbacks to preserve them when recreating BillingService
1333
1474
  billingCallbacks = {};
1475
+ storageMode;
1476
+ cloudStorageAdapter;
1477
+ localStorageAdapter;
1334
1478
  /**
1335
1479
  * Creates a new HyveClient instance
1336
1480
  * @param config Optional configuration including telemetry and ads
@@ -1353,6 +1497,11 @@ var HyveClient = class {
1353
1497
  }
1354
1498
  this.billingConfig = config?.billing || {};
1355
1499
  this.billingService = new BillingService(this.billingConfig);
1500
+ this.storageMode = config?.storageMode || "cloud";
1501
+ this.cloudStorageAdapter = new CloudStorageAdapter(
1502
+ (endpoint, options) => this.callApi(endpoint, options)
1503
+ );
1504
+ this.localStorageAdapter = new LocalStorageAdapter(() => this.getUserId());
1356
1505
  const envSource = config?.isDev !== void 0 ? "explicit config" : "auto-detected from parent URL";
1357
1506
  logger.info("==========================================");
1358
1507
  logger.info("HyveClient Initialized");
@@ -1369,11 +1518,13 @@ var HyveClient = class {
1369
1518
  "Billing configured:",
1370
1519
  Object.keys(this.billingConfig).length > 0
1371
1520
  );
1521
+ logger.info("Storage mode:", this.storageMode);
1372
1522
  logger.debug("Config:", {
1373
1523
  isDev: this.telemetryConfig.isDev,
1374
1524
  hasCustomApiUrl: !!config?.apiBaseUrl,
1375
1525
  adsEnabled: config?.ads?.enabled || false,
1376
- billingConfigured: Object.keys(this.billingConfig).length > 0
1526
+ billingConfigured: Object.keys(this.billingConfig).length > 0,
1527
+ storageMode: this.storageMode
1377
1528
  });
1378
1529
  logger.info("==========================================");
1379
1530
  }
@@ -1638,6 +1789,146 @@ var HyveClient = class {
1638
1789
  this.sessionId = generateUUID();
1639
1790
  logger.info("Client reset with new sessionId:", this.sessionId);
1640
1791
  }
1792
+ /**
1793
+ * Get the storage adapter based on mode
1794
+ * @param mode Storage mode override (cloud or local)
1795
+ */
1796
+ getStorageAdapter(mode) {
1797
+ const storageMode = mode || this.storageMode;
1798
+ return storageMode === "local" ? this.localStorageAdapter : this.cloudStorageAdapter;
1799
+ }
1800
+ /**
1801
+ * Save persistent game data
1802
+ * @param key Data key
1803
+ * @param value Data value (any JSON-serializable value)
1804
+ * @param storage Storage mode override ('cloud' or 'local')
1805
+ * @returns Promise resolving to save response
1806
+ */
1807
+ async saveGameData(key, value, storage) {
1808
+ const gameId = this.getGameId();
1809
+ if (!gameId) {
1810
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1811
+ }
1812
+ const storageMode = storage || this.storageMode;
1813
+ logger.debug(`Saving game data to ${storageMode}: ${gameId}/${key}`);
1814
+ const adapter = this.getStorageAdapter(storage);
1815
+ const response = await adapter.saveGameData(gameId, key, value);
1816
+ logger.info(`Game data saved successfully to ${storageMode}: ${gameId}/${key}`);
1817
+ return response;
1818
+ }
1819
+ /**
1820
+ * Batch save persistent game data
1821
+ * @param items Array of key-value pairs to save
1822
+ * @param storage Storage mode override ('cloud' or 'local')
1823
+ * @returns Promise resolving to save response
1824
+ */
1825
+ async batchSaveGameData(items, storage) {
1826
+ const gameId = this.getGameId();
1827
+ if (!gameId) {
1828
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1829
+ }
1830
+ const storageMode = storage || this.storageMode;
1831
+ logger.debug(`Batch saving ${items.length} game data entries to ${storageMode} for game: ${gameId}`);
1832
+ const adapter = this.getStorageAdapter(storage);
1833
+ const response = await adapter.batchSaveGameData(gameId, items);
1834
+ logger.info(`Batch saved ${items.length} game data entries successfully to ${storageMode}`);
1835
+ return response;
1836
+ }
1837
+ /**
1838
+ * Get persistent game data
1839
+ * @param key Data key
1840
+ * @param storage Storage mode override ('cloud' or 'local')
1841
+ * @returns Promise resolving to game data item or null if not found
1842
+ */
1843
+ async getGameData(key, storage) {
1844
+ const gameId = this.getGameId();
1845
+ if (!gameId) {
1846
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1847
+ }
1848
+ const storageMode = storage || this.storageMode;
1849
+ logger.debug(`Getting game data from ${storageMode}: ${gameId}/${key}`);
1850
+ const adapter = this.getStorageAdapter(storage);
1851
+ const data = await adapter.getGameData(gameId, key);
1852
+ if (data) {
1853
+ logger.info(`Game data retrieved successfully from ${storageMode}: ${gameId}/${key}`);
1854
+ } else {
1855
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1856
+ }
1857
+ return data;
1858
+ }
1859
+ /**
1860
+ * Get multiple persistent game data entries
1861
+ * @param keys Array of data keys
1862
+ * @param storage Storage mode override ('cloud' or 'local')
1863
+ * @returns Promise resolving to array of game data items
1864
+ */
1865
+ async getMultipleGameData(keys, storage) {
1866
+ const gameId = this.getGameId();
1867
+ if (!gameId) {
1868
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1869
+ }
1870
+ const storageMode = storage || this.storageMode;
1871
+ logger.debug(`Getting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1872
+ const adapter = this.getStorageAdapter(storage);
1873
+ const data = await adapter.getMultipleGameData(gameId, keys);
1874
+ logger.info(`Retrieved ${data.length} game data entries from ${storageMode}`);
1875
+ return data;
1876
+ }
1877
+ /**
1878
+ * Delete persistent game data
1879
+ * @param key Data key
1880
+ * @param storage Storage mode override ('cloud' or 'local')
1881
+ * @returns Promise resolving to boolean indicating if data was deleted
1882
+ */
1883
+ async deleteGameData(key, storage) {
1884
+ const gameId = this.getGameId();
1885
+ if (!gameId) {
1886
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1887
+ }
1888
+ const storageMode = storage || this.storageMode;
1889
+ logger.debug(`Deleting game data from ${storageMode}: ${gameId}/${key}`);
1890
+ const adapter = this.getStorageAdapter(storage);
1891
+ const deleted = await adapter.deleteGameData(gameId, key);
1892
+ if (deleted) {
1893
+ logger.info(`Game data deleted successfully from ${storageMode}: ${gameId}/${key}`);
1894
+ } else {
1895
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1896
+ }
1897
+ return deleted;
1898
+ }
1899
+ /**
1900
+ * Delete multiple persistent game data entries
1901
+ * @param keys Array of data keys
1902
+ * @param storage Storage mode override ('cloud' or 'local')
1903
+ * @returns Promise resolving to number of entries deleted
1904
+ */
1905
+ async deleteMultipleGameData(keys, storage) {
1906
+ const gameId = this.getGameId();
1907
+ if (!gameId) {
1908
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1909
+ }
1910
+ const storageMode = storage || this.storageMode;
1911
+ logger.debug(`Deleting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1912
+ const adapter = this.getStorageAdapter(storage);
1913
+ const deletedCount = await adapter.deleteMultipleGameData(gameId, keys);
1914
+ logger.info(`Deleted ${deletedCount} game data entries from ${storageMode}`);
1915
+ return deletedCount;
1916
+ }
1917
+ /**
1918
+ * Configure storage mode
1919
+ * @param mode Storage mode ('cloud' or 'local')
1920
+ */
1921
+ configureStorage(mode) {
1922
+ this.storageMode = mode;
1923
+ logger.info("Storage mode updated to:", mode);
1924
+ }
1925
+ /**
1926
+ * Get current storage mode
1927
+ * @returns Current storage mode
1928
+ */
1929
+ getStorageMode() {
1930
+ return this.storageMode;
1931
+ }
1641
1932
  /**
1642
1933
  * Configure ads service
1643
1934
  * @param config Ads configuration
@@ -1774,7 +2065,9 @@ export {
1774
2065
  AdsService,
1775
2066
  BillingPlatform,
1776
2067
  BillingService,
2068
+ CloudStorageAdapter,
1777
2069
  HyveClient,
2070
+ LocalStorageAdapter,
1778
2071
  Logger,
1779
2072
  NativeBridge,
1780
2073
  NativeMessageType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyve-sdk/js",
3
- "version": "1.3.6",
3
+ "version": "1.4.1",
4
4
  "description": "Hyve SDK - TypeScript wrapper for Hyve game server integration",
5
5
  "private": false,
6
6
  "publishConfig": {