@hyve-sdk/js 1.3.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,11 +36,9 @@ Main client class for SDK operations including authentication, telemetry, and AP
36
36
  ```typescript
37
37
  import { HyveClient } from "@hyve-sdk/js";
38
38
 
39
- // Initialize with optional configuration
40
- const client = new HyveClient({
41
- isDev: true, // Development mode (default: true)
42
- apiBaseUrl: 'https://...' // Optional custom API URL
43
- });
39
+ // Initialize client
40
+ // Environment (dev/prod) is automatically detected from the parent page URL
41
+ const client = new HyveClient();
44
42
 
45
43
  // Authenticate from URL parameters
46
44
  // Extracts: hyve-token/signature, hyve-access (JWT), game-id
@@ -53,6 +51,20 @@ if (authenticated) {
53
51
  }
54
52
  ```
55
53
 
54
+ **Environment Detection:**
55
+ The SDK automatically detects whether to use dev or prod environment by checking the parent page URL:
56
+ - **Dev**: `marvin.dev.hyve.gg` or `dev.hyve.gg`
57
+ - **Prod**: `marvin.hyve.gg` or `hyve.gg`
58
+
59
+ You can optionally override this for testing:
60
+ ```typescript
61
+ // Only use for local testing - NOT for production code
62
+ const client = new HyveClient({
63
+ isDev: true, // Force dev mode for testing
64
+ apiBaseUrl: 'https://...' // Optional custom API URL
65
+ });
66
+ ```
67
+
56
68
  ### Authentication Utilities
57
69
 
58
70
  #### Parse URL Parameters
@@ -292,7 +304,6 @@ import { HyveClient } from "@hyve-sdk/js";
292
304
 
293
305
  // Enable ads in initial config
294
306
  const client = new HyveClient({
295
- isDev: true,
296
307
  ads: {
297
308
  enabled: true, // Must be set to true
298
309
  sound: 'on',
@@ -390,7 +401,6 @@ import { HyveClient } from "@hyve-sdk/js";
390
401
 
391
402
  // Enable billing in initial config
392
403
  const client = new HyveClient({
393
- isDev: true,
394
404
  billing: {
395
405
  stripePublishableKey: 'pk_test_...',
396
406
  checkoutUrl: 'https://your-api.com',
@@ -534,7 +544,6 @@ interface PurchaseResult {
534
544
 
535
545
  ```typescript
536
546
  const client = new HyveClient({
537
- isDev: true,
538
547
  billing: {
539
548
  stripePublishableKey: process.env.VITE_STRIPE_KEY,
540
549
  checkoutUrl: process.env.VITE_CHECKOUT_URL,
package/dist/index.d.mts CHANGED
@@ -2,7 +2,11 @@
2
2
  * Telemetry configuration options
3
3
  */
4
4
  interface TelemetryConfig {
5
- /** Environment: true for dev, false for prod. Defaults to true (dev) */
5
+ /**
6
+ * Environment: true for dev, false for prod.
7
+ * AUTO-DETECTED from parent page URL by default - only set for local testing.
8
+ * Use this ONLY for testing, NOT in production code.
9
+ */
6
10
  isDev?: boolean;
7
11
  /** Base API URL for all API calls (telemetry and external). Can be set via env. If not provided, defaults based on isDev */
8
12
  apiBaseUrl?: string;
@@ -79,6 +83,43 @@ interface AdConfig$1 {
79
83
  /** Callback when user earns a reward (rewarded ads only) */
80
84
  onRewardEarned?: () => void;
81
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
+ }
82
123
 
83
124
  /**
84
125
  * Ads Service for Hyve SDK
@@ -388,6 +429,8 @@ interface HyveClientConfig extends TelemetryConfig {
388
429
  ads?: AdConfig$1;
389
430
  /** Billing configuration (disabled by default) */
390
431
  billing?: BillingConfig;
432
+ /** Storage mode for persistent game data - 'cloud' (default) or 'local' */
433
+ storageMode?: 'cloud' | 'local';
391
434
  }
392
435
  /**
393
436
  * HyveClient provides telemetry and authentication functionality for Hyve games
@@ -403,6 +446,9 @@ declare class HyveClient {
403
446
  private billingService;
404
447
  private billingConfig;
405
448
  private billingCallbacks;
449
+ private storageMode;
450
+ private cloudStorageAdapter;
451
+ private localStorageAdapter;
406
452
  /**
407
453
  * Creates a new HyveClient instance
408
454
  * @param config Optional configuration including telemetry and ads
@@ -493,6 +539,64 @@ declare class HyveClient {
493
539
  * Resets the client state
494
540
  */
495
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';
496
600
  /**
497
601
  * Configure ads service
498
602
  * @param config Ads configuration
@@ -570,6 +674,47 @@ declare class HyveClient {
570
674
  onBillingLog(callback: (level: "info" | "warn" | "error", message: string, data?: any) => void): void;
571
675
  }
572
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
+
573
718
  /**
574
719
  * Logger utility for the Hyve SDK
575
720
  * Automatically enabled in development (NODE_ENV !== 'production')
@@ -843,4 +988,4 @@ declare class NativeBridge {
843
988
  */
844
989
  declare function generateUUID(): string;
845
990
 
846
- 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
@@ -2,7 +2,11 @@
2
2
  * Telemetry configuration options
3
3
  */
4
4
  interface TelemetryConfig {
5
- /** Environment: true for dev, false for prod. Defaults to true (dev) */
5
+ /**
6
+ * Environment: true for dev, false for prod.
7
+ * AUTO-DETECTED from parent page URL by default - only set for local testing.
8
+ * Use this ONLY for testing, NOT in production code.
9
+ */
6
10
  isDev?: boolean;
7
11
  /** Base API URL for all API calls (telemetry and external). Can be set via env. If not provided, defaults based on isDev */
8
12
  apiBaseUrl?: string;
@@ -79,6 +83,43 @@ interface AdConfig$1 {
79
83
  /** Callback when user earns a reward (rewarded ads only) */
80
84
  onRewardEarned?: () => void;
81
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
+ }
82
123
 
83
124
  /**
84
125
  * Ads Service for Hyve SDK
@@ -388,6 +429,8 @@ interface HyveClientConfig extends TelemetryConfig {
388
429
  ads?: AdConfig$1;
389
430
  /** Billing configuration (disabled by default) */
390
431
  billing?: BillingConfig;
432
+ /** Storage mode for persistent game data - 'cloud' (default) or 'local' */
433
+ storageMode?: 'cloud' | 'local';
391
434
  }
392
435
  /**
393
436
  * HyveClient provides telemetry and authentication functionality for Hyve games
@@ -403,6 +446,9 @@ declare class HyveClient {
403
446
  private billingService;
404
447
  private billingConfig;
405
448
  private billingCallbacks;
449
+ private storageMode;
450
+ private cloudStorageAdapter;
451
+ private localStorageAdapter;
406
452
  /**
407
453
  * Creates a new HyveClient instance
408
454
  * @param config Optional configuration including telemetry and ads
@@ -493,6 +539,64 @@ declare class HyveClient {
493
539
  * Resets the client state
494
540
  */
495
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';
496
600
  /**
497
601
  * Configure ads service
498
602
  * @param config Ads configuration
@@ -570,6 +674,47 @@ declare class HyveClient {
570
674
  onBillingLog(callback: (level: "info" | "warn" | "error", message: string, data?: any) => void): void;
571
675
  }
572
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
+
573
718
  /**
574
719
  * Logger utility for the Hyve SDK
575
720
  * Automatically enabled in development (NODE_ENV !== 'production')
@@ -843,4 +988,4 @@ declare class NativeBridge {
843
988
  */
844
989
  declare function generateUUID(): string;
845
990
 
846
- 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,
@@ -1330,6 +1332,133 @@ var BillingService = class {
1330
1332
  }
1331
1333
  };
1332
1334
 
1335
+ // src/services/storage.ts
1336
+ var CloudStorageAdapter = class {
1337
+ constructor(callApi) {
1338
+ this.callApi = callApi;
1339
+ }
1340
+ async saveGameData(gameId, key, value) {
1341
+ return this.callApi("/api/v1/persistent-game-data", {
1342
+ method: "POST",
1343
+ headers: {
1344
+ "Content-Type": "application/json"
1345
+ },
1346
+ body: JSON.stringify({ game_id: gameId, key, value })
1347
+ });
1348
+ }
1349
+ async batchSaveGameData(gameId, items) {
1350
+ return this.callApi(
1351
+ "/api/v1/persistent-game-data/batch",
1352
+ {
1353
+ method: "POST",
1354
+ headers: {
1355
+ "Content-Type": "application/json"
1356
+ },
1357
+ body: JSON.stringify({ game_id: gameId, items })
1358
+ }
1359
+ );
1360
+ }
1361
+ async getGameData(gameId, key) {
1362
+ try {
1363
+ const params = new URLSearchParams({ game_id: gameId, key });
1364
+ const response = await this.callApi(
1365
+ `/api/v1/persistent-game-data?${params}`
1366
+ );
1367
+ return response.data;
1368
+ } catch (error) {
1369
+ if (error instanceof Error && error.message.includes("404")) {
1370
+ return null;
1371
+ }
1372
+ throw error;
1373
+ }
1374
+ }
1375
+ async getMultipleGameData(gameId, keys) {
1376
+ const params = new URLSearchParams({ game_id: gameId });
1377
+ keys.forEach((key) => params.append("keys", key));
1378
+ const response = await this.callApi(
1379
+ `/api/v1/persistent-game-data?${params}`
1380
+ );
1381
+ return response.data;
1382
+ }
1383
+ async deleteGameData(gameId, key) {
1384
+ try {
1385
+ const params = new URLSearchParams({ game_id: gameId, key });
1386
+ const response = await this.callApi(
1387
+ `/api/v1/persistent-game-data?${params}`,
1388
+ { method: "DELETE" }
1389
+ );
1390
+ return response.success && response.deleted_count > 0;
1391
+ } catch (error) {
1392
+ if (error instanceof Error && error.message.includes("404")) {
1393
+ return false;
1394
+ }
1395
+ throw error;
1396
+ }
1397
+ }
1398
+ async deleteMultipleGameData(gameId, keys) {
1399
+ const params = new URLSearchParams({ game_id: gameId });
1400
+ keys.forEach((key) => params.append("keys", key));
1401
+ const response = await this.callApi(
1402
+ `/api/v1/persistent-game-data?${params}`,
1403
+ { method: "DELETE" }
1404
+ );
1405
+ return response.deleted_count;
1406
+ }
1407
+ };
1408
+ var LocalStorageAdapter = class {
1409
+ constructor(getUserId) {
1410
+ this.getUserId = getUserId;
1411
+ }
1412
+ storagePrefix = "hyve_game_data";
1413
+ getStorageKey(gameId, key) {
1414
+ return `${this.storagePrefix}:${gameId}:${key}`;
1415
+ }
1416
+ async saveGameData(gameId, key, value) {
1417
+ try {
1418
+ const storageKey = this.getStorageKey(gameId, key);
1419
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1420
+ const existing = localStorage.getItem(storageKey);
1421
+ const createdAt = existing ? JSON.parse(existing).created_at || now : now;
1422
+ const item = { key, value, created_at: createdAt, updated_at: now };
1423
+ localStorage.setItem(storageKey, JSON.stringify(item));
1424
+ return { success: true, message: "Data saved successfully" };
1425
+ } catch (error) {
1426
+ throw new Error(`Failed to save: ${error instanceof Error ? error.message : "Unknown"}`);
1427
+ }
1428
+ }
1429
+ async batchSaveGameData(gameId, items) {
1430
+ for (const item of items) {
1431
+ await this.saveGameData(gameId, item.key, item.value);
1432
+ }
1433
+ return { success: true, message: `${items.length} items saved` };
1434
+ }
1435
+ async getGameData(gameId, key) {
1436
+ const data = localStorage.getItem(this.getStorageKey(gameId, key));
1437
+ return data ? JSON.parse(data) : null;
1438
+ }
1439
+ async getMultipleGameData(gameId, keys) {
1440
+ const items = [];
1441
+ for (const key of keys) {
1442
+ const item = await this.getGameData(gameId, key);
1443
+ if (item) items.push(item);
1444
+ }
1445
+ return items;
1446
+ }
1447
+ async deleteGameData(gameId, key) {
1448
+ const storageKey = this.getStorageKey(gameId, key);
1449
+ const exists = localStorage.getItem(storageKey) !== null;
1450
+ if (exists) localStorage.removeItem(storageKey);
1451
+ return exists;
1452
+ }
1453
+ async deleteMultipleGameData(gameId, keys) {
1454
+ let count = 0;
1455
+ for (const key of keys) {
1456
+ if (await this.deleteGameData(gameId, key)) count++;
1457
+ }
1458
+ return count;
1459
+ }
1460
+ };
1461
+
1333
1462
  // src/core/client.ts
1334
1463
  function determineEnvironmentFromParentUrl() {
1335
1464
  try {
@@ -1371,6 +1500,9 @@ var HyveClient = class {
1371
1500
  billingConfig;
1372
1501
  // Store callbacks to preserve them when recreating BillingService
1373
1502
  billingCallbacks = {};
1503
+ storageMode;
1504
+ cloudStorageAdapter;
1505
+ localStorageAdapter;
1374
1506
  /**
1375
1507
  * Creates a new HyveClient instance
1376
1508
  * @param config Optional configuration including telemetry and ads
@@ -1393,6 +1525,11 @@ var HyveClient = class {
1393
1525
  }
1394
1526
  this.billingConfig = config?.billing || {};
1395
1527
  this.billingService = new BillingService(this.billingConfig);
1528
+ this.storageMode = config?.storageMode || "cloud";
1529
+ this.cloudStorageAdapter = new CloudStorageAdapter(
1530
+ (endpoint, options) => this.callApi(endpoint, options)
1531
+ );
1532
+ this.localStorageAdapter = new LocalStorageAdapter(() => this.getUserId());
1396
1533
  const envSource = config?.isDev !== void 0 ? "explicit config" : "auto-detected from parent URL";
1397
1534
  logger.info("==========================================");
1398
1535
  logger.info("HyveClient Initialized");
@@ -1409,11 +1546,13 @@ var HyveClient = class {
1409
1546
  "Billing configured:",
1410
1547
  Object.keys(this.billingConfig).length > 0
1411
1548
  );
1549
+ logger.info("Storage mode:", this.storageMode);
1412
1550
  logger.debug("Config:", {
1413
1551
  isDev: this.telemetryConfig.isDev,
1414
1552
  hasCustomApiUrl: !!config?.apiBaseUrl,
1415
1553
  adsEnabled: config?.ads?.enabled || false,
1416
- billingConfigured: Object.keys(this.billingConfig).length > 0
1554
+ billingConfigured: Object.keys(this.billingConfig).length > 0,
1555
+ storageMode: this.storageMode
1417
1556
  });
1418
1557
  logger.info("==========================================");
1419
1558
  }
@@ -1678,6 +1817,146 @@ var HyveClient = class {
1678
1817
  this.sessionId = generateUUID();
1679
1818
  logger.info("Client reset with new sessionId:", this.sessionId);
1680
1819
  }
1820
+ /**
1821
+ * Get the storage adapter based on mode
1822
+ * @param mode Storage mode override (cloud or local)
1823
+ */
1824
+ getStorageAdapter(mode) {
1825
+ const storageMode = mode || this.storageMode;
1826
+ return storageMode === "local" ? this.localStorageAdapter : this.cloudStorageAdapter;
1827
+ }
1828
+ /**
1829
+ * Save persistent game data
1830
+ * @param key Data key
1831
+ * @param value Data value (any JSON-serializable value)
1832
+ * @param storage Storage mode override ('cloud' or 'local')
1833
+ * @returns Promise resolving to save response
1834
+ */
1835
+ async saveGameData(key, value, storage) {
1836
+ const gameId = this.getGameId();
1837
+ if (!gameId) {
1838
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1839
+ }
1840
+ const storageMode = storage || this.storageMode;
1841
+ logger.debug(`Saving game data to ${storageMode}: ${gameId}/${key}`);
1842
+ const adapter = this.getStorageAdapter(storage);
1843
+ const response = await adapter.saveGameData(gameId, key, value);
1844
+ logger.info(`Game data saved successfully to ${storageMode}: ${gameId}/${key}`);
1845
+ return response;
1846
+ }
1847
+ /**
1848
+ * Batch save persistent game data
1849
+ * @param items Array of key-value pairs to save
1850
+ * @param storage Storage mode override ('cloud' or 'local')
1851
+ * @returns Promise resolving to save response
1852
+ */
1853
+ async batchSaveGameData(items, storage) {
1854
+ const gameId = this.getGameId();
1855
+ if (!gameId) {
1856
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1857
+ }
1858
+ const storageMode = storage || this.storageMode;
1859
+ logger.debug(`Batch saving ${items.length} game data entries to ${storageMode} for game: ${gameId}`);
1860
+ const adapter = this.getStorageAdapter(storage);
1861
+ const response = await adapter.batchSaveGameData(gameId, items);
1862
+ logger.info(`Batch saved ${items.length} game data entries successfully to ${storageMode}`);
1863
+ return response;
1864
+ }
1865
+ /**
1866
+ * Get persistent game data
1867
+ * @param key Data key
1868
+ * @param storage Storage mode override ('cloud' or 'local')
1869
+ * @returns Promise resolving to game data item or null if not found
1870
+ */
1871
+ async getGameData(key, storage) {
1872
+ const gameId = this.getGameId();
1873
+ if (!gameId) {
1874
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1875
+ }
1876
+ const storageMode = storage || this.storageMode;
1877
+ logger.debug(`Getting game data from ${storageMode}: ${gameId}/${key}`);
1878
+ const adapter = this.getStorageAdapter(storage);
1879
+ const data = await adapter.getGameData(gameId, key);
1880
+ if (data) {
1881
+ logger.info(`Game data retrieved successfully from ${storageMode}: ${gameId}/${key}`);
1882
+ } else {
1883
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1884
+ }
1885
+ return data;
1886
+ }
1887
+ /**
1888
+ * Get multiple persistent game data entries
1889
+ * @param keys Array of data keys
1890
+ * @param storage Storage mode override ('cloud' or 'local')
1891
+ * @returns Promise resolving to array of game data items
1892
+ */
1893
+ async getMultipleGameData(keys, storage) {
1894
+ const gameId = this.getGameId();
1895
+ if (!gameId) {
1896
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1897
+ }
1898
+ const storageMode = storage || this.storageMode;
1899
+ logger.debug(`Getting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1900
+ const adapter = this.getStorageAdapter(storage);
1901
+ const data = await adapter.getMultipleGameData(gameId, keys);
1902
+ logger.info(`Retrieved ${data.length} game data entries from ${storageMode}`);
1903
+ return data;
1904
+ }
1905
+ /**
1906
+ * Delete persistent game data
1907
+ * @param key Data key
1908
+ * @param storage Storage mode override ('cloud' or 'local')
1909
+ * @returns Promise resolving to boolean indicating if data was deleted
1910
+ */
1911
+ async deleteGameData(key, storage) {
1912
+ const gameId = this.getGameId();
1913
+ if (!gameId) {
1914
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1915
+ }
1916
+ const storageMode = storage || this.storageMode;
1917
+ logger.debug(`Deleting game data from ${storageMode}: ${gameId}/${key}`);
1918
+ const adapter = this.getStorageAdapter(storage);
1919
+ const deleted = await adapter.deleteGameData(gameId, key);
1920
+ if (deleted) {
1921
+ logger.info(`Game data deleted successfully from ${storageMode}: ${gameId}/${key}`);
1922
+ } else {
1923
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1924
+ }
1925
+ return deleted;
1926
+ }
1927
+ /**
1928
+ * Delete multiple persistent game data entries
1929
+ * @param keys Array of data keys
1930
+ * @param storage Storage mode override ('cloud' or 'local')
1931
+ * @returns Promise resolving to number of entries deleted
1932
+ */
1933
+ async deleteMultipleGameData(keys, storage) {
1934
+ const gameId = this.getGameId();
1935
+ if (!gameId) {
1936
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1937
+ }
1938
+ const storageMode = storage || this.storageMode;
1939
+ logger.debug(`Deleting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1940
+ const adapter = this.getStorageAdapter(storage);
1941
+ const deletedCount = await adapter.deleteMultipleGameData(gameId, keys);
1942
+ logger.info(`Deleted ${deletedCount} game data entries from ${storageMode}`);
1943
+ return deletedCount;
1944
+ }
1945
+ /**
1946
+ * Configure storage mode
1947
+ * @param mode Storage mode ('cloud' or 'local')
1948
+ */
1949
+ configureStorage(mode) {
1950
+ this.storageMode = mode;
1951
+ logger.info("Storage mode updated to:", mode);
1952
+ }
1953
+ /**
1954
+ * Get current storage mode
1955
+ * @returns Current storage mode
1956
+ */
1957
+ getStorageMode() {
1958
+ return this.storageMode;
1959
+ }
1681
1960
  /**
1682
1961
  * Configure ads service
1683
1962
  * @param config Ads configuration
@@ -1815,7 +2094,9 @@ var HyveClient = class {
1815
2094
  AdsService,
1816
2095
  BillingPlatform,
1817
2096
  BillingService,
2097
+ CloudStorageAdapter,
1818
2098
  HyveClient,
2099
+ LocalStorageAdapter,
1819
2100
  Logger,
1820
2101
  NativeBridge,
1821
2102
  NativeMessageType,
package/dist/index.mjs CHANGED
@@ -1290,6 +1290,133 @@ var BillingService = class {
1290
1290
  }
1291
1291
  };
1292
1292
 
1293
+ // src/services/storage.ts
1294
+ var CloudStorageAdapter = class {
1295
+ constructor(callApi) {
1296
+ this.callApi = callApi;
1297
+ }
1298
+ async saveGameData(gameId, key, value) {
1299
+ return this.callApi("/api/v1/persistent-game-data", {
1300
+ method: "POST",
1301
+ headers: {
1302
+ "Content-Type": "application/json"
1303
+ },
1304
+ body: JSON.stringify({ game_id: gameId, key, value })
1305
+ });
1306
+ }
1307
+ async batchSaveGameData(gameId, items) {
1308
+ return this.callApi(
1309
+ "/api/v1/persistent-game-data/batch",
1310
+ {
1311
+ method: "POST",
1312
+ headers: {
1313
+ "Content-Type": "application/json"
1314
+ },
1315
+ body: JSON.stringify({ game_id: gameId, items })
1316
+ }
1317
+ );
1318
+ }
1319
+ async getGameData(gameId, key) {
1320
+ try {
1321
+ const params = new URLSearchParams({ game_id: gameId, key });
1322
+ const response = await this.callApi(
1323
+ `/api/v1/persistent-game-data?${params}`
1324
+ );
1325
+ return response.data;
1326
+ } catch (error) {
1327
+ if (error instanceof Error && error.message.includes("404")) {
1328
+ return null;
1329
+ }
1330
+ throw error;
1331
+ }
1332
+ }
1333
+ async getMultipleGameData(gameId, keys) {
1334
+ const params = new URLSearchParams({ game_id: gameId });
1335
+ keys.forEach((key) => params.append("keys", key));
1336
+ const response = await this.callApi(
1337
+ `/api/v1/persistent-game-data?${params}`
1338
+ );
1339
+ return response.data;
1340
+ }
1341
+ async deleteGameData(gameId, key) {
1342
+ try {
1343
+ const params = new URLSearchParams({ game_id: gameId, key });
1344
+ const response = await this.callApi(
1345
+ `/api/v1/persistent-game-data?${params}`,
1346
+ { method: "DELETE" }
1347
+ );
1348
+ return response.success && response.deleted_count > 0;
1349
+ } catch (error) {
1350
+ if (error instanceof Error && error.message.includes("404")) {
1351
+ return false;
1352
+ }
1353
+ throw error;
1354
+ }
1355
+ }
1356
+ async deleteMultipleGameData(gameId, keys) {
1357
+ const params = new URLSearchParams({ game_id: gameId });
1358
+ keys.forEach((key) => params.append("keys", key));
1359
+ const response = await this.callApi(
1360
+ `/api/v1/persistent-game-data?${params}`,
1361
+ { method: "DELETE" }
1362
+ );
1363
+ return response.deleted_count;
1364
+ }
1365
+ };
1366
+ var LocalStorageAdapter = class {
1367
+ constructor(getUserId) {
1368
+ this.getUserId = getUserId;
1369
+ }
1370
+ storagePrefix = "hyve_game_data";
1371
+ getStorageKey(gameId, key) {
1372
+ return `${this.storagePrefix}:${gameId}:${key}`;
1373
+ }
1374
+ async saveGameData(gameId, key, value) {
1375
+ try {
1376
+ const storageKey = this.getStorageKey(gameId, key);
1377
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1378
+ const existing = localStorage.getItem(storageKey);
1379
+ const createdAt = existing ? JSON.parse(existing).created_at || now : now;
1380
+ const item = { key, value, created_at: createdAt, updated_at: now };
1381
+ localStorage.setItem(storageKey, JSON.stringify(item));
1382
+ return { success: true, message: "Data saved successfully" };
1383
+ } catch (error) {
1384
+ throw new Error(`Failed to save: ${error instanceof Error ? error.message : "Unknown"}`);
1385
+ }
1386
+ }
1387
+ async batchSaveGameData(gameId, items) {
1388
+ for (const item of items) {
1389
+ await this.saveGameData(gameId, item.key, item.value);
1390
+ }
1391
+ return { success: true, message: `${items.length} items saved` };
1392
+ }
1393
+ async getGameData(gameId, key) {
1394
+ const data = localStorage.getItem(this.getStorageKey(gameId, key));
1395
+ return data ? JSON.parse(data) : null;
1396
+ }
1397
+ async getMultipleGameData(gameId, keys) {
1398
+ const items = [];
1399
+ for (const key of keys) {
1400
+ const item = await this.getGameData(gameId, key);
1401
+ if (item) items.push(item);
1402
+ }
1403
+ return items;
1404
+ }
1405
+ async deleteGameData(gameId, key) {
1406
+ const storageKey = this.getStorageKey(gameId, key);
1407
+ const exists = localStorage.getItem(storageKey) !== null;
1408
+ if (exists) localStorage.removeItem(storageKey);
1409
+ return exists;
1410
+ }
1411
+ async deleteMultipleGameData(gameId, keys) {
1412
+ let count = 0;
1413
+ for (const key of keys) {
1414
+ if (await this.deleteGameData(gameId, key)) count++;
1415
+ }
1416
+ return count;
1417
+ }
1418
+ };
1419
+
1293
1420
  // src/core/client.ts
1294
1421
  function determineEnvironmentFromParentUrl() {
1295
1422
  try {
@@ -1331,6 +1458,9 @@ var HyveClient = class {
1331
1458
  billingConfig;
1332
1459
  // Store callbacks to preserve them when recreating BillingService
1333
1460
  billingCallbacks = {};
1461
+ storageMode;
1462
+ cloudStorageAdapter;
1463
+ localStorageAdapter;
1334
1464
  /**
1335
1465
  * Creates a new HyveClient instance
1336
1466
  * @param config Optional configuration including telemetry and ads
@@ -1353,6 +1483,11 @@ var HyveClient = class {
1353
1483
  }
1354
1484
  this.billingConfig = config?.billing || {};
1355
1485
  this.billingService = new BillingService(this.billingConfig);
1486
+ this.storageMode = config?.storageMode || "cloud";
1487
+ this.cloudStorageAdapter = new CloudStorageAdapter(
1488
+ (endpoint, options) => this.callApi(endpoint, options)
1489
+ );
1490
+ this.localStorageAdapter = new LocalStorageAdapter(() => this.getUserId());
1356
1491
  const envSource = config?.isDev !== void 0 ? "explicit config" : "auto-detected from parent URL";
1357
1492
  logger.info("==========================================");
1358
1493
  logger.info("HyveClient Initialized");
@@ -1369,11 +1504,13 @@ var HyveClient = class {
1369
1504
  "Billing configured:",
1370
1505
  Object.keys(this.billingConfig).length > 0
1371
1506
  );
1507
+ logger.info("Storage mode:", this.storageMode);
1372
1508
  logger.debug("Config:", {
1373
1509
  isDev: this.telemetryConfig.isDev,
1374
1510
  hasCustomApiUrl: !!config?.apiBaseUrl,
1375
1511
  adsEnabled: config?.ads?.enabled || false,
1376
- billingConfigured: Object.keys(this.billingConfig).length > 0
1512
+ billingConfigured: Object.keys(this.billingConfig).length > 0,
1513
+ storageMode: this.storageMode
1377
1514
  });
1378
1515
  logger.info("==========================================");
1379
1516
  }
@@ -1638,6 +1775,146 @@ var HyveClient = class {
1638
1775
  this.sessionId = generateUUID();
1639
1776
  logger.info("Client reset with new sessionId:", this.sessionId);
1640
1777
  }
1778
+ /**
1779
+ * Get the storage adapter based on mode
1780
+ * @param mode Storage mode override (cloud or local)
1781
+ */
1782
+ getStorageAdapter(mode) {
1783
+ const storageMode = mode || this.storageMode;
1784
+ return storageMode === "local" ? this.localStorageAdapter : this.cloudStorageAdapter;
1785
+ }
1786
+ /**
1787
+ * Save persistent game data
1788
+ * @param key Data key
1789
+ * @param value Data value (any JSON-serializable value)
1790
+ * @param storage Storage mode override ('cloud' or 'local')
1791
+ * @returns Promise resolving to save response
1792
+ */
1793
+ async saveGameData(key, value, storage) {
1794
+ const gameId = this.getGameId();
1795
+ if (!gameId) {
1796
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1797
+ }
1798
+ const storageMode = storage || this.storageMode;
1799
+ logger.debug(`Saving game data to ${storageMode}: ${gameId}/${key}`);
1800
+ const adapter = this.getStorageAdapter(storage);
1801
+ const response = await adapter.saveGameData(gameId, key, value);
1802
+ logger.info(`Game data saved successfully to ${storageMode}: ${gameId}/${key}`);
1803
+ return response;
1804
+ }
1805
+ /**
1806
+ * Batch save persistent game data
1807
+ * @param items Array of key-value pairs to save
1808
+ * @param storage Storage mode override ('cloud' or 'local')
1809
+ * @returns Promise resolving to save response
1810
+ */
1811
+ async batchSaveGameData(items, storage) {
1812
+ const gameId = this.getGameId();
1813
+ if (!gameId) {
1814
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1815
+ }
1816
+ const storageMode = storage || this.storageMode;
1817
+ logger.debug(`Batch saving ${items.length} game data entries to ${storageMode} for game: ${gameId}`);
1818
+ const adapter = this.getStorageAdapter(storage);
1819
+ const response = await adapter.batchSaveGameData(gameId, items);
1820
+ logger.info(`Batch saved ${items.length} game data entries successfully to ${storageMode}`);
1821
+ return response;
1822
+ }
1823
+ /**
1824
+ * Get persistent game data
1825
+ * @param key Data key
1826
+ * @param storage Storage mode override ('cloud' or 'local')
1827
+ * @returns Promise resolving to game data item or null if not found
1828
+ */
1829
+ async getGameData(key, storage) {
1830
+ const gameId = this.getGameId();
1831
+ if (!gameId) {
1832
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1833
+ }
1834
+ const storageMode = storage || this.storageMode;
1835
+ logger.debug(`Getting game data from ${storageMode}: ${gameId}/${key}`);
1836
+ const adapter = this.getStorageAdapter(storage);
1837
+ const data = await adapter.getGameData(gameId, key);
1838
+ if (data) {
1839
+ logger.info(`Game data retrieved successfully from ${storageMode}: ${gameId}/${key}`);
1840
+ } else {
1841
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1842
+ }
1843
+ return data;
1844
+ }
1845
+ /**
1846
+ * Get multiple persistent game data entries
1847
+ * @param keys Array of data keys
1848
+ * @param storage Storage mode override ('cloud' or 'local')
1849
+ * @returns Promise resolving to array of game data items
1850
+ */
1851
+ async getMultipleGameData(keys, storage) {
1852
+ const gameId = this.getGameId();
1853
+ if (!gameId) {
1854
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1855
+ }
1856
+ const storageMode = storage || this.storageMode;
1857
+ logger.debug(`Getting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1858
+ const adapter = this.getStorageAdapter(storage);
1859
+ const data = await adapter.getMultipleGameData(gameId, keys);
1860
+ logger.info(`Retrieved ${data.length} game data entries from ${storageMode}`);
1861
+ return data;
1862
+ }
1863
+ /**
1864
+ * Delete persistent game data
1865
+ * @param key Data key
1866
+ * @param storage Storage mode override ('cloud' or 'local')
1867
+ * @returns Promise resolving to boolean indicating if data was deleted
1868
+ */
1869
+ async deleteGameData(key, storage) {
1870
+ const gameId = this.getGameId();
1871
+ if (!gameId) {
1872
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1873
+ }
1874
+ const storageMode = storage || this.storageMode;
1875
+ logger.debug(`Deleting game data from ${storageMode}: ${gameId}/${key}`);
1876
+ const adapter = this.getStorageAdapter(storage);
1877
+ const deleted = await adapter.deleteGameData(gameId, key);
1878
+ if (deleted) {
1879
+ logger.info(`Game data deleted successfully from ${storageMode}: ${gameId}/${key}`);
1880
+ } else {
1881
+ logger.debug(`Game data not found in ${storageMode}: ${key}`);
1882
+ }
1883
+ return deleted;
1884
+ }
1885
+ /**
1886
+ * Delete multiple persistent game data entries
1887
+ * @param keys Array of data keys
1888
+ * @param storage Storage mode override ('cloud' or 'local')
1889
+ * @returns Promise resolving to number of entries deleted
1890
+ */
1891
+ async deleteMultipleGameData(keys, storage) {
1892
+ const gameId = this.getGameId();
1893
+ if (!gameId) {
1894
+ throw new Error("game-id is required for persistent storage. Call authenticateFromUrl first.");
1895
+ }
1896
+ const storageMode = storage || this.storageMode;
1897
+ logger.debug(`Deleting ${keys.length} game data entries from ${storageMode} for game: ${gameId}`);
1898
+ const adapter = this.getStorageAdapter(storage);
1899
+ const deletedCount = await adapter.deleteMultipleGameData(gameId, keys);
1900
+ logger.info(`Deleted ${deletedCount} game data entries from ${storageMode}`);
1901
+ return deletedCount;
1902
+ }
1903
+ /**
1904
+ * Configure storage mode
1905
+ * @param mode Storage mode ('cloud' or 'local')
1906
+ */
1907
+ configureStorage(mode) {
1908
+ this.storageMode = mode;
1909
+ logger.info("Storage mode updated to:", mode);
1910
+ }
1911
+ /**
1912
+ * Get current storage mode
1913
+ * @returns Current storage mode
1914
+ */
1915
+ getStorageMode() {
1916
+ return this.storageMode;
1917
+ }
1641
1918
  /**
1642
1919
  * Configure ads service
1643
1920
  * @param config Ads configuration
@@ -1774,7 +2051,9 @@ export {
1774
2051
  AdsService,
1775
2052
  BillingPlatform,
1776
2053
  BillingService,
2054
+ CloudStorageAdapter,
1777
2055
  HyveClient,
2056
+ LocalStorageAdapter,
1778
2057
  Logger,
1779
2058
  NativeBridge,
1780
2059
  NativeMessageType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyve-sdk/js",
3
- "version": "1.3.5",
3
+ "version": "1.4.0",
4
4
  "description": "Hyve SDK - TypeScript wrapper for Hyve game server integration",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -15,14 +15,6 @@
15
15
  "README.md",
16
16
  "LICENSE"
17
17
  ],
18
- "scripts": {
19
- "lint": "eslint . --max-warnings 0",
20
- "check-types": "tsc --noEmit",
21
- "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
- "prepublishOnly": "pnpm run build && pnpm run check-types",
23
- "publish:npm": "pnpm publish --access public",
24
- "publish:dry-run": "pnpm publish --dry-run --access public --no-git-checks"
25
- },
26
18
  "keywords": [
27
19
  "hyve",
28
20
  "game",
@@ -56,11 +48,18 @@
56
48
  }
57
49
  },
58
50
  "devDependencies": {
59
- "@repo/eslint-config": "workspace:*",
60
- "@repo/typescript-config": "workspace:*",
61
51
  "@types/minimatch": "^5.1.2",
62
52
  "@types/uuid": "^10.0.0",
63
53
  "tsup": "^8.4.0",
64
- "typescript": "^5.3.3"
54
+ "typescript": "^5.3.3",
55
+ "@repo/eslint-config": "0.0.0",
56
+ "@repo/typescript-config": "0.0.0"
57
+ },
58
+ "scripts": {
59
+ "lint": "eslint . --max-warnings 0",
60
+ "check-types": "tsc --noEmit",
61
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
62
+ "publish:npm": "pnpm publish --access public",
63
+ "publish:dry-run": "pnpm publish --dry-run --access public --no-git-checks"
65
64
  }
66
- }
65
+ }