@momo-cloud/gami-sdk 0.0.93 → 0.0.97

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
@@ -82,21 +82,25 @@ Then rely on runtime properties:
82
82
  await GamiSDK.startGame();
83
83
  ```
84
84
 
85
- Typical game loop calls:
85
+ > `startGame()` / `endGame()` bracket a **gameplay session**, not a single spin. Call `startGame()` once when entering the game and `endGame()` once when leaving — many `spin()` calls happen in between.
86
86
 
87
- - `getConfig()`
88
- - `getBalance({ balanceId })`
87
+ Typical game loop calls (signatures match `IGameApi`):
88
+
89
+ - `getConfig({ ext? })`
90
+ - `getBalance({ balanceId? })`
89
91
  - `getBalanceConfig()`
90
- - `spin()`
92
+ - `spin({ checkCounter?, giftCate?, isBonus? })`
91
93
  - `shake()`
92
94
  - `getCoinBalance()`
93
- - `getCoinExchangeInfo()`
94
- - `coinExchange({ amount })`
95
+ - `getCoinExchangeInfo({ actionId? })`
96
+ - `coinExchange({ amount, actionId? })`
95
97
  - `getMission({ viewId? })`
96
- - `getLeaderboard({ boardId, group?, limit?, page? })`
98
+ - `postSuccessMission({ eventName, serviceId? })`
99
+ - `getLeaderboard({ type })`
97
100
  - `submitLeaderboard({ boardName, score, periodType?, delta? })`
98
101
  - `getHistory({ page, limit })`
99
102
  - `getEvent({ eventId })`
103
+ - `customGameRequest({ path, method, subDomain?, body?, extraHeader?, mockData? })`
100
104
 
101
105
  ### Phase C - Close or Navigate
102
106
 
@@ -134,28 +138,91 @@ GamiSDK.screenTracking({
134
138
  });
135
139
  ```
136
140
 
137
- ## 6) Shared Utilities
141
+ ## 6) Shared Utilities (Named Exports)
142
+
143
+ Alongside the default `GamiSDK`, the package exposes these named exports:
144
+
145
+ ```ts
146
+ import GamiSDK, { Storage, Calendar, AudioPlayer, GameEvent, Utils } from '@momo-cloud/gami-sdk';
147
+ ```
138
148
 
139
- Named exports are available for common integration helpers:
149
+ | Export | What it is |
150
+ | --- | --- |
151
+ | `GamiSDK` (default) | Composed game + platform API object |
152
+ | `Storage` | Persistent key/value + file cache (see §6.1) |
153
+ | `Calendar` | Device calendar helper |
154
+ | `AudioPlayer` | Music / SFX playback (see §6.2) |
155
+ | `GameEvent` | In-app event bus (`eventemitter3`) |
156
+ | `Utils` | Misc helpers (name/phone formatting, etc.) |
157
+ | Types | Domain DTOs (`TSpin`, `TLeaderboard`, `THistory`, …) |
140
158
 
141
- - Storage: `saveItem`, `getItem`, `cacheFile`
142
- - Calendar wrapper: `addCalendar`
143
- - Time sync: `setServerTime`, `getServerTime`
144
- - Event bus: `GameEvent`
145
- - SSE support: from `features/sse/*`
146
- - Types: from `features/types/*`
159
+ > `getServerTime()` / `setServerTime()` live on the `GamiSDK` object, not as standalone named exports — call `GamiSDK.getServerTime()`. It is **synchronous** (returns `number`, ms epoch) — do **not** `await` it. Use it for any countdown, expiry, or campaign window instead of `Date.now()` to avoid client-clock skew.
160
+ >
161
+ > ```ts
162
+ > const now = GamiSDK.getServerTime(); // ✅ synchronous
163
+ > const remaining = campaignEndAt - now; // never Date.now()
164
+ > ```
147
165
 
148
- Example:
166
+ ### 6.1) Storage
167
+
168
+ **Use `Storage` for all persistence — not `localStorage` / `sessionStorage`.** Browser storage is unreliable inside the MoMo WebView. All keys are automatically namespaced with the current `gameId` (e.g. `wheel_fpt_progress`).
169
+
170
+ ```ts
171
+ import { Storage } from '@momo-cloud/gami-sdk';
172
+
173
+ // Writes are fire-and-forget (synchronous, return void)
174
+ Storage.cacheJson('progress', { level: 3, stars: 15 });
175
+ Storage.cacheValue('lastSeen', Date.now());
176
+
177
+ // Reads are async
178
+ const progress = await Storage.getJson('progress', /* default */ {});
179
+ const lastSeen = await Storage.getValue('lastSeen');
180
+
181
+ // CDN file caching → returns a usable (possibly object) URL
182
+ const localUrl = await Storage.cacheFile('https://cdn.example.com/img/wheel.png');
183
+ ```
184
+
185
+ | Method | Returns | Notes |
186
+ | --- | --- | --- |
187
+ | `cacheJson(key, obj)` | `void` | Persist an object (fire-and-forget) |
188
+ | `cacheValue(key, val)` | `void` | Persist a primitive |
189
+ | `getJson(key, default?)` | `Promise<any>` | Read object; falls back to `default` |
190
+ | `getValue(key, default?)` | `Promise<any>` | Read primitive |
191
+ | `cacheFile(url)` | `Promise<string>` | Cache a remote file, returns local URL |
192
+ | `getInCache(url)` | `string \| undefined` | Synchronous lookup of an already-cached file |
193
+
194
+ ### 6.2) AudioPlayer
149
195
 
150
196
  ```ts
151
- import { saveItem, getItem, GameEvent } from '@momo-cloud/gami-sdk';
197
+ import { AudioPlayer } from '@momo-cloud/gami-sdk';
198
+
199
+ // If sound names are short keys (e.g. 'bg', 'btn-click'), set a base URL first.
200
+ // Skip this if every name you pass is already a full https URL.
201
+ AudioPlayer.init({ baseURL: 'https://cdn.example.com/sounds/' });
202
+
203
+ AudioPlayer.play('btn-click'); // one-shot SFX
204
+ AudioPlayer.play('btn-click', { volume: 0.5 }); // with options
205
+ AudioPlayer.playMusic('bg', { loop: true, volume: 1 }); // looping background music
206
+
207
+ AudioPlayer.pause(); // pause all (no arg) — call synchronously on app blur
208
+ AudioPlayer.resume(); // resume all — on app focus, wrap in setTimeout(…, 1000) on iOS WebView
209
+ AudioPlayer.stop('bg');
210
+ AudioPlayer.enable = false; // mute everything (respect user setting)
211
+ AudioPlayer.musicVolume = 0.3; // 0..1
212
+ ```
213
+
214
+ > `playMusic`'s second argument is an **options object** (`{ loop, volume, onComplete }`) — not a boolean. `init` takes `{ baseURL }` (capital `URL`).
215
+
216
+ ### 6.3) Event bus
152
217
 
153
- await saveItem('progress', { level: 3, stars: 15 });
154
- const progress = await getItem('progress');
218
+ ```ts
219
+ import { GameEvent } from '@momo-cloud/gami-sdk';
155
220
 
156
221
  GameEvent.on('GAME_ON_BACK', () => {
157
222
  // route back to your home screen
158
223
  });
224
+ GameEvent.emit('GAME_ON_BACK');
225
+ GameEvent.off('GAME_ON_BACK', handler);
159
226
  ```
160
227
 
161
228
  ## 7) Error Handling Pattern
@@ -180,14 +247,11 @@ if (res?.response_info?.error_code !== 0) {
180
247
  ### Read leaderboard
181
248
 
182
249
  ```ts
183
- const lb = await GamiSDK.getLeaderboard({
184
- boardId: 'win',
185
- group: 'global', // 'global' | 'friend'
186
- limit: 50,
187
- page: 0,
188
- });
250
+ const lb = await GamiSDK.getLeaderboard({ type: 'win' });
189
251
  ```
190
252
 
253
+ - `type` — the leaderboard identifier (e.g. `'win'`).
254
+
191
255
  ### Submit a score
192
256
 
193
257
  ```ts
@@ -4,6 +4,29 @@ export declare const GameEvent: EventEmitter<string | symbol, any>;
4
4
  export declare const GamiSDK: Record<string, any>;
5
5
  export default GamiSDK;
6
6
 
7
+ export declare const AudioPlayer: {
8
+ init(options: { baseURL: string }): void;
9
+ play(name: string, options?: { loop?: boolean; volume?: number }): Promise<any>;
10
+ playMusic(name: string, options?: { loop?: boolean; volume?: number; onComplete?: () => void }): Promise<any>;
11
+ stop(name: string): void;
12
+ pause(name?: string): void;
13
+ resume(name?: string): void;
14
+ setVolume(name: string, value: number): void;
15
+ setMute(name: string, value: boolean): void;
16
+ musicVolume: number;
17
+ enableSfx: boolean;
18
+ enable: boolean;
19
+ };
20
+
21
+ export declare const Storage: {
22
+ cacheJson(key: string, value: object): void;
23
+ cacheValue(key: string, value: string): void;
24
+ getJson<T = any>(key: string, defaultVal?: T): Promise<T>;
25
+ getValue(key: string, defaultVal?: string): Promise<string | undefined>;
26
+ cacheFile(url: string): Promise<string>;
27
+ getInCache(url: string): string | undefined;
28
+ };
29
+
7
30
  export type IUserInfo = {
8
31
  id: string;
9
32
  name?: string;