@oasiz/sdk 1.0.0 → 1.0.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/README.md +33 -124
- package/dist/index.cjs +3 -14
- package/dist/index.d.cts +221 -11
- package/dist/index.d.ts +221 -11
- package/dist/index.global.js +252 -0
- package/dist/index.js +2 -12
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @oasiz/sdk
|
|
2
2
|
|
|
3
|
-
Typed SDK for integrating games with the Oasiz platform. Handles score submission, haptic feedback, cross-session state persistence, multiplayer room codes, and app lifecycle events
|
|
3
|
+
Typed SDK for integrating games with the Oasiz platform. Handles score submission, haptic feedback, cross-session state persistence, multiplayer room codes, and app lifecycle events.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install @oasiz/sdk
|
|
8
|
+
npm install @oasiz/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick start
|
|
@@ -13,27 +13,17 @@ npm install @oasiz/sdk@^0.1.0
|
|
|
13
13
|
```ts
|
|
14
14
|
import { oasiz } from "@oasiz/sdk";
|
|
15
15
|
|
|
16
|
-
// 1.
|
|
17
|
-
oasiz.emitScoreConfig({
|
|
18
|
-
anchors: [
|
|
19
|
-
{ raw: 30, normalized: 100 },
|
|
20
|
-
{ raw: 60, normalized: 300 },
|
|
21
|
-
{ raw: 120, normalized: 600 },
|
|
22
|
-
{ raw: 300, normalized: 950 },
|
|
23
|
-
],
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// 2. Load persisted state at the start of each session
|
|
16
|
+
// 1. Load persisted state at the start of each session
|
|
27
17
|
const state = oasiz.loadGameState();
|
|
28
18
|
let level = typeof state.level === "number" ? state.level : 1;
|
|
29
19
|
|
|
30
|
-
//
|
|
20
|
+
// 2. Save state at checkpoints
|
|
31
21
|
oasiz.saveGameState({ level, coins: 42 });
|
|
32
22
|
|
|
33
|
-
//
|
|
23
|
+
// 3. Trigger haptics on key events
|
|
34
24
|
oasiz.triggerHaptic("medium");
|
|
35
25
|
|
|
36
|
-
//
|
|
26
|
+
// 4. Submit score when the game ends
|
|
37
27
|
oasiz.submitScore(score);
|
|
38
28
|
```
|
|
39
29
|
|
|
@@ -43,44 +33,14 @@ oasiz.submitScore(score);
|
|
|
43
33
|
|
|
44
34
|
### `oasiz.submitScore(score: number)`
|
|
45
35
|
|
|
46
|
-
Submit the player's
|
|
36
|
+
Submit the player's score. The platform handles leaderboard persistence — do not track high scores locally.
|
|
47
37
|
|
|
48
38
|
```ts
|
|
49
|
-
|
|
50
|
-
oasiz.submitScore(Math.floor(this.score));
|
|
51
|
-
}
|
|
39
|
+
oasiz.submitScore(this.score);
|
|
52
40
|
```
|
|
53
41
|
|
|
54
42
|
- `score` must be a non-negative integer. Floats are floored automatically.
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
### `oasiz.emitScoreConfig(config)`
|
|
60
|
-
|
|
61
|
-
Maps raw score values to the platform's normalized 0–1000 scale. Call once during initialization, not every frame.
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
oasiz.emitScoreConfig({
|
|
65
|
-
anchors: [
|
|
66
|
-
{ raw: 10, normalized: 100 }, // beginner
|
|
67
|
-
{ raw: 30, normalized: 300 }, // good
|
|
68
|
-
{ raw: 75, normalized: 600 }, // great
|
|
69
|
-
{ raw: 200, normalized: 950 }, // godlike
|
|
70
|
-
],
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**Anchor rules:**
|
|
75
|
-
- Exactly 4 anchors required.
|
|
76
|
-
- `raw` values must be strictly increasing.
|
|
77
|
-
- `normalized` values must end at exactly `950`.
|
|
78
|
-
- Choose thresholds based on realistic player skill bands.
|
|
79
|
-
|
|
80
|
-
**Practical guidance by game type:**
|
|
81
|
-
- Survival / time games → use seconds survived as `raw`
|
|
82
|
-
- Score accumulation games → use points as `raw`
|
|
83
|
-
- Puzzle games → use level reached or stars earned as `raw`
|
|
43
|
+
- When and how often you call this depends on your game type (once at game over, end of each level, or throttled for long sessions).
|
|
84
44
|
|
|
85
45
|
---
|
|
86
46
|
|
|
@@ -99,23 +59,14 @@ type HapticType = "light" | "medium" | "heavy" | "success" | "error";
|
|
|
99
59
|
| `"light"` | UI button taps, menu navigation, D-pad press |
|
|
100
60
|
| `"medium"` | Collecting items, standard collisions, scoring |
|
|
101
61
|
| `"heavy"` | Explosions, major impacts, screen shake |
|
|
102
|
-
| `"success"` | Level complete,
|
|
62
|
+
| `"success"` | Level complete, achievement unlocked |
|
|
103
63
|
| `"error"` | Damage taken, game over, invalid action |
|
|
104
64
|
|
|
105
65
|
```ts
|
|
106
|
-
// UI buttons — always light
|
|
107
66
|
button.addEventListener("click", () => {
|
|
108
67
|
oasiz.triggerHaptic("light");
|
|
109
68
|
});
|
|
110
69
|
|
|
111
|
-
// Tiered hit feedback
|
|
112
|
-
private onBallHit(zone: "center" | "edge"): void {
|
|
113
|
-
if (this.settings.haptics) {
|
|
114
|
-
oasiz.triggerHaptic(zone === "center" ? "success" : "medium");
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Game over
|
|
119
70
|
private onGameOver(): void {
|
|
120
71
|
oasiz.submitScore(this.score);
|
|
121
72
|
if (this.settings.haptics) {
|
|
@@ -124,75 +75,54 @@ private onGameOver(): void {
|
|
|
124
75
|
}
|
|
125
76
|
```
|
|
126
77
|
|
|
127
|
-
Haptics are throttled internally (50ms cooldown) to prevent spam.
|
|
128
|
-
|
|
129
78
|
---
|
|
130
79
|
|
|
131
80
|
## Game state persistence
|
|
132
81
|
|
|
133
|
-
Persist cross-session data such as unlocked levels, inventory, or lifetime stats.
|
|
82
|
+
Persist cross-session data such as unlocked levels, inventory, or lifetime stats. Available across devices and app reinstalls.
|
|
134
83
|
|
|
135
84
|
### `oasiz.loadGameState(): Record<string, unknown>`
|
|
136
85
|
|
|
137
|
-
Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet.
|
|
86
|
+
Returns the player's saved state synchronously. Returns `{}` if no state has been saved yet.
|
|
138
87
|
|
|
139
88
|
```ts
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
this.level = typeof state.level === "number" ? state.level : 1;
|
|
143
|
-
this.lifetimeHits = typeof state.lifetimeHits === "number" ? state.lifetimeHits : 0;
|
|
144
|
-
this.unlockedSkins = Array.isArray(state.unlockedSkins) ? state.unlockedSkins : [];
|
|
145
|
-
}
|
|
89
|
+
const state = oasiz.loadGameState();
|
|
90
|
+
this.level = typeof state.level === "number" ? state.level : 1;
|
|
146
91
|
```
|
|
147
92
|
|
|
148
|
-
Always validate the shape of loaded data — it may be `{}` on first play.
|
|
149
|
-
|
|
150
93
|
### `oasiz.saveGameState(state: Record<string, unknown>)`
|
|
151
94
|
|
|
152
|
-
Queues a debounced save.
|
|
95
|
+
Queues a debounced save. Call freely at checkpoints.
|
|
153
96
|
|
|
154
97
|
```ts
|
|
155
|
-
|
|
156
|
-
private onLevelComplete(): void {
|
|
157
|
-
this.level += 1;
|
|
158
|
-
oasiz.saveGameState({
|
|
159
|
-
level: this.level,
|
|
160
|
-
lifetimeHits: this.lifetimeHits,
|
|
161
|
-
unlockedSkins: this.unlockedSkins,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
98
|
+
oasiz.saveGameState({ level: this.level, unlockedSkins: this.unlockedSkins });
|
|
164
99
|
```
|
|
165
100
|
|
|
166
|
-
**Rules:**
|
|
167
101
|
- State must be a plain JSON object (not an array or primitive).
|
|
168
|
-
-
|
|
169
|
-
- Do not store scores here —
|
|
102
|
+
- Use `saveGameState` instead of `localStorage` for cross-session progress.
|
|
103
|
+
- Do not store scores here — use `submitScore`.
|
|
170
104
|
|
|
171
105
|
### `oasiz.flushGameState()`
|
|
172
106
|
|
|
173
|
-
Forces an immediate write, bypassing the debounce. Use at
|
|
107
|
+
Forces an immediate write, bypassing the debounce. Use at game over or before page unload.
|
|
174
108
|
|
|
175
109
|
```ts
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
oasiz.submitScore(this.score);
|
|
180
|
-
}
|
|
110
|
+
oasiz.saveGameState({ level: this.level });
|
|
111
|
+
oasiz.flushGameState();
|
|
112
|
+
oasiz.submitScore(this.score);
|
|
181
113
|
```
|
|
182
114
|
|
|
183
115
|
---
|
|
184
116
|
|
|
185
117
|
## Lifecycle
|
|
186
118
|
|
|
187
|
-
The platform dispatches lifecycle events when the app goes to the background or returns to the foreground. Subscribe to pause game loops and audio accordingly.
|
|
188
|
-
|
|
189
119
|
### `oasiz.onPause(callback: () => void): Unsubscribe`
|
|
190
120
|
### `oasiz.onResume(callback: () => void): Unsubscribe`
|
|
191
121
|
|
|
192
122
|
Both return an unsubscribe function.
|
|
193
123
|
|
|
194
124
|
```ts
|
|
195
|
-
const offPause
|
|
125
|
+
const offPause = oasiz.onPause(() => {
|
|
196
126
|
this.gameLoop.stop();
|
|
197
127
|
this.bgMusic.pause();
|
|
198
128
|
});
|
|
@@ -202,7 +132,6 @@ const offResume = oasiz.onResume(() => {
|
|
|
202
132
|
this.bgMusic.play();
|
|
203
133
|
});
|
|
204
134
|
|
|
205
|
-
// Clean up when the game is destroyed
|
|
206
135
|
offPause();
|
|
207
136
|
offResume();
|
|
208
137
|
```
|
|
@@ -213,47 +142,29 @@ offResume();
|
|
|
213
142
|
|
|
214
143
|
### `oasiz.shareRoomCode(code: string | null)`
|
|
215
144
|
|
|
216
|
-
Notify the platform of the active multiplayer room
|
|
145
|
+
Notify the platform of the active multiplayer room. Pass `null` when leaving.
|
|
217
146
|
|
|
218
147
|
```ts
|
|
219
|
-
import { insertCoin, getRoomCode } from "playroomkit";
|
|
220
|
-
import { oasiz } from "@oasiz/sdk";
|
|
221
|
-
|
|
222
|
-
await insertCoin({ skipLobby: true });
|
|
223
148
|
oasiz.shareRoomCode(getRoomCode());
|
|
224
|
-
|
|
225
|
-
// On disconnect
|
|
226
149
|
oasiz.shareRoomCode(null);
|
|
227
150
|
```
|
|
228
151
|
|
|
229
|
-
### Read-only
|
|
230
|
-
|
|
231
|
-
These are populated by the platform before the game loads. Always check for `undefined` before using.
|
|
152
|
+
### Read-only properties
|
|
232
153
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
await connectToRoom(oasiz.roomCode);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Player identity for multiplayer games
|
|
243
|
-
const name = oasiz.playerName;
|
|
244
|
-
const avatar = oasiz.playerAvatar;
|
|
245
|
-
```
|
|
154
|
+
| Property | Type | Description |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| `oasiz.gameId` | string \| undefined | The platform's game ID |
|
|
157
|
+
| `oasiz.roomCode` | string \| undefined | Pre-filled room code from invite |
|
|
158
|
+
| `oasiz.playerName` | string \| undefined | Player's display name |
|
|
159
|
+
| `oasiz.playerAvatar` | string \| undefined | Player's profile picture URL |
|
|
246
160
|
|
|
247
161
|
---
|
|
248
162
|
|
|
249
163
|
## Named exports
|
|
250
164
|
|
|
251
|
-
All methods are also available as named exports if you prefer not to use the `oasiz` namespace object:
|
|
252
|
-
|
|
253
165
|
```ts
|
|
254
166
|
import {
|
|
255
167
|
submitScore,
|
|
256
|
-
emitScoreConfig,
|
|
257
168
|
triggerHaptic,
|
|
258
169
|
loadGameState,
|
|
259
170
|
saveGameState,
|
|
@@ -273,17 +184,15 @@ import {
|
|
|
273
184
|
## TypeScript types
|
|
274
185
|
|
|
275
186
|
```ts
|
|
276
|
-
import type { HapticType,
|
|
187
|
+
import type { HapticType, GameState } from "@oasiz/sdk";
|
|
277
188
|
```
|
|
278
189
|
|
|
279
190
|
---
|
|
280
191
|
|
|
281
192
|
## Local development
|
|
282
193
|
|
|
283
|
-
All methods safely no-op when the platform bridges are not injected. In development mode a console warning is logged
|
|
194
|
+
All methods safely no-op when the platform bridges are not injected. In development mode a console warning is logged:
|
|
284
195
|
|
|
285
196
|
```
|
|
286
197
|
[oasiz/sdk] submitScore bridge is unavailable. This is expected in local development.
|
|
287
198
|
```
|
|
288
|
-
|
|
289
|
-
No crashes, no special setup required for local dev.
|
package/dist/index.cjs
CHANGED
|
@@ -20,14 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
emitScoreConfig: () => emitScoreConfig,
|
|
24
23
|
flushGameState: () => flushGameState,
|
|
25
24
|
getGameId: () => getGameId,
|
|
26
25
|
getPlayerAvatar: () => getPlayerAvatar,
|
|
27
26
|
getPlayerName: () => getPlayerName,
|
|
28
27
|
getRoomCode: () => getRoomCode,
|
|
29
28
|
loadGameState: () => loadGameState,
|
|
30
|
-
|
|
29
|
+
oasiz: () => oasiz,
|
|
31
30
|
onPause: () => onPause,
|
|
32
31
|
onResume: () => onResume,
|
|
33
32
|
saveGameState: () => saveGameState,
|
|
@@ -134,14 +133,6 @@ function submitScore(score) {
|
|
|
134
133
|
}
|
|
135
134
|
warnMissingBridge("submitScore");
|
|
136
135
|
}
|
|
137
|
-
function emitScoreConfig(config) {
|
|
138
|
-
const bridge = getBridgeWindow3();
|
|
139
|
-
if (typeof bridge?.emitScoreConfig === "function") {
|
|
140
|
-
bridge.emitScoreConfig(config);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
warnMissingBridge("emitScoreConfig");
|
|
144
|
-
}
|
|
145
136
|
|
|
146
137
|
// src/state.ts
|
|
147
138
|
function isDevelopment4() {
|
|
@@ -235,9 +226,8 @@ function onResume(callback) {
|
|
|
235
226
|
}
|
|
236
227
|
|
|
237
228
|
// src/index.ts
|
|
238
|
-
var
|
|
229
|
+
var oasiz = {
|
|
239
230
|
submitScore,
|
|
240
|
-
emitScoreConfig,
|
|
241
231
|
triggerHaptic,
|
|
242
232
|
loadGameState,
|
|
243
233
|
saveGameState,
|
|
@@ -260,14 +250,13 @@ var oasis = {
|
|
|
260
250
|
};
|
|
261
251
|
// Annotate the CommonJS export names for ESM import in node:
|
|
262
252
|
0 && (module.exports = {
|
|
263
|
-
emitScoreConfig,
|
|
264
253
|
flushGameState,
|
|
265
254
|
getGameId,
|
|
266
255
|
getPlayerAvatar,
|
|
267
256
|
getPlayerName,
|
|
268
257
|
getRoomCode,
|
|
269
258
|
loadGameState,
|
|
270
|
-
|
|
259
|
+
oasiz,
|
|
271
260
|
onPause,
|
|
272
261
|
onResume,
|
|
273
262
|
saveGameState,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,35 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intensity level for native haptic feedback.
|
|
3
|
+
*
|
|
4
|
+
* | Type | Use case |
|
|
5
|
+
* |-------------|-------------------------------------------------|
|
|
6
|
+
* | `"light"` | UI button taps, menu navigation, D-pad press |
|
|
7
|
+
* | `"medium"` | Collecting items, standard collisions, scoring |
|
|
8
|
+
* | `"heavy"` | Explosions, major impacts, screen shake |
|
|
9
|
+
* | `"success"` | Level complete, achievement unlocked |
|
|
10
|
+
* | `"error"` | Damage taken, game over, invalid action |
|
|
11
|
+
*
|
|
12
|
+
* @category Haptics
|
|
13
|
+
*/
|
|
1
14
|
type HapticType = "light" | "medium" | "heavy" | "success" | "error";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* A plain JSON-serializable object used for cross-session game state
|
|
17
|
+
* persistence.
|
|
18
|
+
*
|
|
19
|
+
* @category State
|
|
20
|
+
*/
|
|
9
21
|
type GameState = Record<string, unknown>;
|
|
10
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Trigger native haptic feedback on the player's device.
|
|
25
|
+
*
|
|
26
|
+
* Always guard calls with the user's haptics preference toggle.
|
|
27
|
+
* The bridge is a no-op in local development (a console warning is logged).
|
|
28
|
+
*
|
|
29
|
+
* @param type - The haptic intensity level.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // UI button tap
|
|
34
|
+
* oasiz.triggerHaptic("light");
|
|
35
|
+
*
|
|
36
|
+
* // Tiered hit feedback
|
|
37
|
+
* oasiz.triggerHaptic(isPerfectHit ? "success" : "medium");
|
|
38
|
+
*
|
|
39
|
+
* // Game over
|
|
40
|
+
* oasiz.triggerHaptic("error");
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @category Haptics
|
|
44
|
+
*/
|
|
11
45
|
declare function triggerHaptic(type: HapticType): void;
|
|
12
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Notify the platform of the active multiplayer room so friends can join
|
|
49
|
+
* via the invite system. Pass `null` when leaving a room.
|
|
50
|
+
*
|
|
51
|
+
* @param roomCode - The room code string, or `null` to clear.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { insertCoin, getRoomCode } from "playroomkit";
|
|
56
|
+
*
|
|
57
|
+
* await insertCoin({ skipLobby: true });
|
|
58
|
+
* oasiz.shareRoomCode(getRoomCode());
|
|
59
|
+
*
|
|
60
|
+
* // On disconnect
|
|
61
|
+
* oasiz.shareRoomCode(null);
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @category Multiplayer
|
|
65
|
+
*/
|
|
13
66
|
declare function shareRoomCode(roomCode: string | null): void;
|
|
67
|
+
/**
|
|
68
|
+
* Get the platform's internal game ID, injected before the game loads.
|
|
69
|
+
*
|
|
70
|
+
* @returns The game ID string, or `undefined` if not yet injected.
|
|
71
|
+
*
|
|
72
|
+
* @category Multiplayer
|
|
73
|
+
*/
|
|
14
74
|
declare function getGameId(): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get the pre-filled room code for auto-joining a friend's multiplayer session.
|
|
77
|
+
*
|
|
78
|
+
* @returns The room code string, or `undefined` if not in a multiplayer context.
|
|
79
|
+
*
|
|
80
|
+
* @category Multiplayer
|
|
81
|
+
*/
|
|
15
82
|
declare function getRoomCode(): string | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get the current player's display name, injected by the platform.
|
|
85
|
+
*
|
|
86
|
+
* @returns The player name, or `undefined` if not available.
|
|
87
|
+
*
|
|
88
|
+
* @category Multiplayer
|
|
89
|
+
*/
|
|
16
90
|
declare function getPlayerName(): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current player's avatar URL, injected by the platform.
|
|
93
|
+
*
|
|
94
|
+
* @returns The avatar URL string, or `undefined` if not available.
|
|
95
|
+
*
|
|
96
|
+
* @category Multiplayer
|
|
97
|
+
*/
|
|
17
98
|
declare function getPlayerAvatar(): string | undefined;
|
|
18
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Submit the player's score.
|
|
102
|
+
*
|
|
103
|
+
* The platform handles leaderboard persistence — do not track high scores locally.
|
|
104
|
+
*
|
|
105
|
+
* - `score` must be a finite number. Floats are floored, negatives are clamped to 0.
|
|
106
|
+
* - In development mode a console warning is logged when the bridge is unavailable.
|
|
107
|
+
*
|
|
108
|
+
* @param score - The player's score (non-negative integer).
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* oasiz.submitScore(Math.floor(this.score));
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @category Score
|
|
116
|
+
*/
|
|
19
117
|
declare function submitScore(score: number): void;
|
|
20
|
-
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
21
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Load the player's persisted game state.
|
|
121
|
+
*
|
|
122
|
+
* Returns the saved state synchronously. Returns `{}` if no state has been
|
|
123
|
+
* saved yet or if the bridge is unavailable. Always validate the shape of
|
|
124
|
+
* the returned data — it may be empty on first play.
|
|
125
|
+
*
|
|
126
|
+
* Call once at the start of the game.
|
|
127
|
+
*
|
|
128
|
+
* @returns The player's saved {@link GameState}, or an empty object.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const state = oasiz.loadGameState();
|
|
133
|
+
* this.level = typeof state.level === "number" ? state.level : 1;
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @category State
|
|
137
|
+
*/
|
|
22
138
|
declare function loadGameState(): GameState;
|
|
139
|
+
/**
|
|
140
|
+
* Queue a debounced save of the player's game state.
|
|
141
|
+
*
|
|
142
|
+
* Saves are batched automatically — call freely at checkpoints without
|
|
143
|
+
* worrying about request spam. State must be a plain JSON-serializable object.
|
|
144
|
+
*
|
|
145
|
+
* @param state - A plain object to persist. Do not pass arrays or primitives.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* oasiz.saveGameState({
|
|
150
|
+
* level: this.level,
|
|
151
|
+
* lifetimeHits: this.lifetimeHits,
|
|
152
|
+
* unlockedSkins: this.unlockedSkins,
|
|
153
|
+
* });
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @category State
|
|
157
|
+
*/
|
|
23
158
|
declare function saveGameState(state: GameState): void;
|
|
159
|
+
/**
|
|
160
|
+
* Force an immediate write of the pending game state, bypassing the debounce.
|
|
161
|
+
*
|
|
162
|
+
* Use at critical checkpoints like game over or before the page unloads
|
|
163
|
+
* to ensure data is persisted.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* oasiz.saveGameState({ level: this.level });
|
|
168
|
+
* oasiz.flushGameState(); // ensure it lands before the page closes
|
|
169
|
+
* oasiz.submitScore(this.score);
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @category State
|
|
173
|
+
*/
|
|
24
174
|
declare function flushGameState(): void;
|
|
25
175
|
|
|
176
|
+
/**
|
|
177
|
+
* A function that removes an event listener when called.
|
|
178
|
+
* Returned by {@link onPause} and {@link onResume}.
|
|
179
|
+
*
|
|
180
|
+
* @category Lifecycle
|
|
181
|
+
*/
|
|
26
182
|
type Unsubscribe = () => void;
|
|
183
|
+
/**
|
|
184
|
+
* Register a callback that fires when the app goes to the background.
|
|
185
|
+
*
|
|
186
|
+
* Use this to pause game loops, audio, and animations so the game
|
|
187
|
+
* doesn't continue running while the player is away.
|
|
188
|
+
*
|
|
189
|
+
* @param callback - Invoked when the platform dispatches `oasiz:pause`.
|
|
190
|
+
* @returns An {@link Unsubscribe} function that removes the listener.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* const off = oasiz.onPause(() => {
|
|
195
|
+
* this.gameLoop.stop();
|
|
196
|
+
* this.bgMusic.pause();
|
|
197
|
+
* });
|
|
198
|
+
*
|
|
199
|
+
* // Later, clean up:
|
|
200
|
+
* off();
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* @category Lifecycle
|
|
204
|
+
*/
|
|
27
205
|
declare function onPause(callback: () => void): Unsubscribe;
|
|
206
|
+
/**
|
|
207
|
+
* Register a callback that fires when the app returns to the foreground.
|
|
208
|
+
*
|
|
209
|
+
* Use this to resume game loops, audio, and animations after a pause.
|
|
210
|
+
*
|
|
211
|
+
* @param callback - Invoked when the platform dispatches `oasiz:resume`.
|
|
212
|
+
* @returns An {@link Unsubscribe} function that removes the listener.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* const off = oasiz.onResume(() => {
|
|
217
|
+
* this.gameLoop.start();
|
|
218
|
+
* this.bgMusic.play();
|
|
219
|
+
* });
|
|
220
|
+
*
|
|
221
|
+
* // Later, clean up:
|
|
222
|
+
* off();
|
|
223
|
+
* ```
|
|
224
|
+
*
|
|
225
|
+
* @category Lifecycle
|
|
226
|
+
*/
|
|
28
227
|
declare function onResume(callback: () => void): Unsubscribe;
|
|
29
228
|
|
|
30
|
-
|
|
229
|
+
/**
|
|
230
|
+
* The main SDK namespace object. Provides convenient access to all
|
|
231
|
+
* platform bridge APIs as a single import.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* import { oasiz } from "@oasiz/sdk";
|
|
236
|
+
*
|
|
237
|
+
* oasiz.triggerHaptic("medium");
|
|
238
|
+
* oasiz.submitScore(score);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
declare const oasiz: {
|
|
31
242
|
submitScore: typeof submitScore;
|
|
32
|
-
emitScoreConfig: typeof emitScoreConfig;
|
|
33
243
|
triggerHaptic: typeof triggerHaptic;
|
|
34
244
|
loadGameState: typeof loadGameState;
|
|
35
245
|
saveGameState: typeof saveGameState;
|
|
@@ -43,4 +253,4 @@ declare const oasis: {
|
|
|
43
253
|
readonly playerAvatar: string | undefined;
|
|
44
254
|
};
|
|
45
255
|
|
|
46
|
-
export { type GameState, type HapticType, type
|
|
256
|
+
export { type GameState, type HapticType, type Unsubscribe, flushGameState, getGameId, getPlayerAvatar, getPlayerName, getRoomCode, loadGameState, oasiz, onPause, onResume, saveGameState, shareRoomCode, submitScore, triggerHaptic };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,35 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intensity level for native haptic feedback.
|
|
3
|
+
*
|
|
4
|
+
* | Type | Use case |
|
|
5
|
+
* |-------------|-------------------------------------------------|
|
|
6
|
+
* | `"light"` | UI button taps, menu navigation, D-pad press |
|
|
7
|
+
* | `"medium"` | Collecting items, standard collisions, scoring |
|
|
8
|
+
* | `"heavy"` | Explosions, major impacts, screen shake |
|
|
9
|
+
* | `"success"` | Level complete, achievement unlocked |
|
|
10
|
+
* | `"error"` | Damage taken, game over, invalid action |
|
|
11
|
+
*
|
|
12
|
+
* @category Haptics
|
|
13
|
+
*/
|
|
1
14
|
type HapticType = "light" | "medium" | "heavy" | "success" | "error";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* A plain JSON-serializable object used for cross-session game state
|
|
17
|
+
* persistence.
|
|
18
|
+
*
|
|
19
|
+
* @category State
|
|
20
|
+
*/
|
|
9
21
|
type GameState = Record<string, unknown>;
|
|
10
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Trigger native haptic feedback on the player's device.
|
|
25
|
+
*
|
|
26
|
+
* Always guard calls with the user's haptics preference toggle.
|
|
27
|
+
* The bridge is a no-op in local development (a console warning is logged).
|
|
28
|
+
*
|
|
29
|
+
* @param type - The haptic intensity level.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // UI button tap
|
|
34
|
+
* oasiz.triggerHaptic("light");
|
|
35
|
+
*
|
|
36
|
+
* // Tiered hit feedback
|
|
37
|
+
* oasiz.triggerHaptic(isPerfectHit ? "success" : "medium");
|
|
38
|
+
*
|
|
39
|
+
* // Game over
|
|
40
|
+
* oasiz.triggerHaptic("error");
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @category Haptics
|
|
44
|
+
*/
|
|
11
45
|
declare function triggerHaptic(type: HapticType): void;
|
|
12
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Notify the platform of the active multiplayer room so friends can join
|
|
49
|
+
* via the invite system. Pass `null` when leaving a room.
|
|
50
|
+
*
|
|
51
|
+
* @param roomCode - The room code string, or `null` to clear.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { insertCoin, getRoomCode } from "playroomkit";
|
|
56
|
+
*
|
|
57
|
+
* await insertCoin({ skipLobby: true });
|
|
58
|
+
* oasiz.shareRoomCode(getRoomCode());
|
|
59
|
+
*
|
|
60
|
+
* // On disconnect
|
|
61
|
+
* oasiz.shareRoomCode(null);
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @category Multiplayer
|
|
65
|
+
*/
|
|
13
66
|
declare function shareRoomCode(roomCode: string | null): void;
|
|
67
|
+
/**
|
|
68
|
+
* Get the platform's internal game ID, injected before the game loads.
|
|
69
|
+
*
|
|
70
|
+
* @returns The game ID string, or `undefined` if not yet injected.
|
|
71
|
+
*
|
|
72
|
+
* @category Multiplayer
|
|
73
|
+
*/
|
|
14
74
|
declare function getGameId(): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get the pre-filled room code for auto-joining a friend's multiplayer session.
|
|
77
|
+
*
|
|
78
|
+
* @returns The room code string, or `undefined` if not in a multiplayer context.
|
|
79
|
+
*
|
|
80
|
+
* @category Multiplayer
|
|
81
|
+
*/
|
|
15
82
|
declare function getRoomCode(): string | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Get the current player's display name, injected by the platform.
|
|
85
|
+
*
|
|
86
|
+
* @returns The player name, or `undefined` if not available.
|
|
87
|
+
*
|
|
88
|
+
* @category Multiplayer
|
|
89
|
+
*/
|
|
16
90
|
declare function getPlayerName(): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current player's avatar URL, injected by the platform.
|
|
93
|
+
*
|
|
94
|
+
* @returns The avatar URL string, or `undefined` if not available.
|
|
95
|
+
*
|
|
96
|
+
* @category Multiplayer
|
|
97
|
+
*/
|
|
17
98
|
declare function getPlayerAvatar(): string | undefined;
|
|
18
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Submit the player's score.
|
|
102
|
+
*
|
|
103
|
+
* The platform handles leaderboard persistence — do not track high scores locally.
|
|
104
|
+
*
|
|
105
|
+
* - `score` must be a finite number. Floats are floored, negatives are clamped to 0.
|
|
106
|
+
* - In development mode a console warning is logged when the bridge is unavailable.
|
|
107
|
+
*
|
|
108
|
+
* @param score - The player's score (non-negative integer).
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* oasiz.submitScore(Math.floor(this.score));
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @category Score
|
|
116
|
+
*/
|
|
19
117
|
declare function submitScore(score: number): void;
|
|
20
|
-
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
21
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Load the player's persisted game state.
|
|
121
|
+
*
|
|
122
|
+
* Returns the saved state synchronously. Returns `{}` if no state has been
|
|
123
|
+
* saved yet or if the bridge is unavailable. Always validate the shape of
|
|
124
|
+
* the returned data — it may be empty on first play.
|
|
125
|
+
*
|
|
126
|
+
* Call once at the start of the game.
|
|
127
|
+
*
|
|
128
|
+
* @returns The player's saved {@link GameState}, or an empty object.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* const state = oasiz.loadGameState();
|
|
133
|
+
* this.level = typeof state.level === "number" ? state.level : 1;
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @category State
|
|
137
|
+
*/
|
|
22
138
|
declare function loadGameState(): GameState;
|
|
139
|
+
/**
|
|
140
|
+
* Queue a debounced save of the player's game state.
|
|
141
|
+
*
|
|
142
|
+
* Saves are batched automatically — call freely at checkpoints without
|
|
143
|
+
* worrying about request spam. State must be a plain JSON-serializable object.
|
|
144
|
+
*
|
|
145
|
+
* @param state - A plain object to persist. Do not pass arrays or primitives.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* oasiz.saveGameState({
|
|
150
|
+
* level: this.level,
|
|
151
|
+
* lifetimeHits: this.lifetimeHits,
|
|
152
|
+
* unlockedSkins: this.unlockedSkins,
|
|
153
|
+
* });
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @category State
|
|
157
|
+
*/
|
|
23
158
|
declare function saveGameState(state: GameState): void;
|
|
159
|
+
/**
|
|
160
|
+
* Force an immediate write of the pending game state, bypassing the debounce.
|
|
161
|
+
*
|
|
162
|
+
* Use at critical checkpoints like game over or before the page unloads
|
|
163
|
+
* to ensure data is persisted.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* oasiz.saveGameState({ level: this.level });
|
|
168
|
+
* oasiz.flushGameState(); // ensure it lands before the page closes
|
|
169
|
+
* oasiz.submitScore(this.score);
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @category State
|
|
173
|
+
*/
|
|
24
174
|
declare function flushGameState(): void;
|
|
25
175
|
|
|
176
|
+
/**
|
|
177
|
+
* A function that removes an event listener when called.
|
|
178
|
+
* Returned by {@link onPause} and {@link onResume}.
|
|
179
|
+
*
|
|
180
|
+
* @category Lifecycle
|
|
181
|
+
*/
|
|
26
182
|
type Unsubscribe = () => void;
|
|
183
|
+
/**
|
|
184
|
+
* Register a callback that fires when the app goes to the background.
|
|
185
|
+
*
|
|
186
|
+
* Use this to pause game loops, audio, and animations so the game
|
|
187
|
+
* doesn't continue running while the player is away.
|
|
188
|
+
*
|
|
189
|
+
* @param callback - Invoked when the platform dispatches `oasiz:pause`.
|
|
190
|
+
* @returns An {@link Unsubscribe} function that removes the listener.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* const off = oasiz.onPause(() => {
|
|
195
|
+
* this.gameLoop.stop();
|
|
196
|
+
* this.bgMusic.pause();
|
|
197
|
+
* });
|
|
198
|
+
*
|
|
199
|
+
* // Later, clean up:
|
|
200
|
+
* off();
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* @category Lifecycle
|
|
204
|
+
*/
|
|
27
205
|
declare function onPause(callback: () => void): Unsubscribe;
|
|
206
|
+
/**
|
|
207
|
+
* Register a callback that fires when the app returns to the foreground.
|
|
208
|
+
*
|
|
209
|
+
* Use this to resume game loops, audio, and animations after a pause.
|
|
210
|
+
*
|
|
211
|
+
* @param callback - Invoked when the platform dispatches `oasiz:resume`.
|
|
212
|
+
* @returns An {@link Unsubscribe} function that removes the listener.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* const off = oasiz.onResume(() => {
|
|
217
|
+
* this.gameLoop.start();
|
|
218
|
+
* this.bgMusic.play();
|
|
219
|
+
* });
|
|
220
|
+
*
|
|
221
|
+
* // Later, clean up:
|
|
222
|
+
* off();
|
|
223
|
+
* ```
|
|
224
|
+
*
|
|
225
|
+
* @category Lifecycle
|
|
226
|
+
*/
|
|
28
227
|
declare function onResume(callback: () => void): Unsubscribe;
|
|
29
228
|
|
|
30
|
-
|
|
229
|
+
/**
|
|
230
|
+
* The main SDK namespace object. Provides convenient access to all
|
|
231
|
+
* platform bridge APIs as a single import.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* import { oasiz } from "@oasiz/sdk";
|
|
236
|
+
*
|
|
237
|
+
* oasiz.triggerHaptic("medium");
|
|
238
|
+
* oasiz.submitScore(score);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
declare const oasiz: {
|
|
31
242
|
submitScore: typeof submitScore;
|
|
32
|
-
emitScoreConfig: typeof emitScoreConfig;
|
|
33
243
|
triggerHaptic: typeof triggerHaptic;
|
|
34
244
|
loadGameState: typeof loadGameState;
|
|
35
245
|
saveGameState: typeof saveGameState;
|
|
@@ -43,4 +253,4 @@ declare const oasis: {
|
|
|
43
253
|
readonly playerAvatar: string | undefined;
|
|
44
254
|
};
|
|
45
255
|
|
|
46
|
-
export { type GameState, type HapticType, type
|
|
256
|
+
export { type GameState, type HapticType, type Unsubscribe, flushGameState, getGameId, getPlayerAvatar, getPlayerName, getRoomCode, loadGameState, oasiz, onPause, onResume, saveGameState, shareRoomCode, submitScore, triggerHaptic };
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var oasiz = (() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
flushGameState: () => flushGameState,
|
|
25
|
+
getGameId: () => getGameId,
|
|
26
|
+
getPlayerAvatar: () => getPlayerAvatar,
|
|
27
|
+
getPlayerName: () => getPlayerName,
|
|
28
|
+
getRoomCode: () => getRoomCode,
|
|
29
|
+
loadGameState: () => loadGameState,
|
|
30
|
+
oasiz: () => oasiz,
|
|
31
|
+
onPause: () => onPause,
|
|
32
|
+
onResume: () => onResume,
|
|
33
|
+
saveGameState: () => saveGameState,
|
|
34
|
+
shareRoomCode: () => shareRoomCode,
|
|
35
|
+
submitScore: () => submitScore,
|
|
36
|
+
triggerHaptic: () => triggerHaptic
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// src/haptics.ts
|
|
40
|
+
function isDevelopment() {
|
|
41
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
42
|
+
return nodeEnv !== "production";
|
|
43
|
+
}
|
|
44
|
+
function getBridgeWindow() {
|
|
45
|
+
if (typeof window === "undefined") {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
return window;
|
|
49
|
+
}
|
|
50
|
+
function triggerHaptic(type) {
|
|
51
|
+
const bridge = getBridgeWindow();
|
|
52
|
+
if (typeof bridge?.triggerHaptic === "function") {
|
|
53
|
+
bridge.triggerHaptic(type);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (isDevelopment()) {
|
|
57
|
+
console.warn(
|
|
58
|
+
"[oasiz/sdk] triggerHaptic bridge is unavailable. This is expected in local development."
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/multiplayer.ts
|
|
64
|
+
function isDevelopment2() {
|
|
65
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
66
|
+
return nodeEnv !== "production";
|
|
67
|
+
}
|
|
68
|
+
function getBridgeWindow2() {
|
|
69
|
+
if (typeof window === "undefined") {
|
|
70
|
+
return void 0;
|
|
71
|
+
}
|
|
72
|
+
return window;
|
|
73
|
+
}
|
|
74
|
+
function shareRoomCode(roomCode) {
|
|
75
|
+
const bridge = getBridgeWindow2();
|
|
76
|
+
if (typeof bridge?.shareRoomCode === "function") {
|
|
77
|
+
bridge.shareRoomCode(roomCode);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (isDevelopment2()) {
|
|
81
|
+
console.warn(
|
|
82
|
+
"[oasiz/sdk] shareRoomCode bridge is unavailable. This is expected in local development."
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function getGameId() {
|
|
87
|
+
const bridge = getBridgeWindow2();
|
|
88
|
+
return bridge?.__GAME_ID__;
|
|
89
|
+
}
|
|
90
|
+
function getRoomCode() {
|
|
91
|
+
const bridge = getBridgeWindow2();
|
|
92
|
+
return bridge?.__ROOM_CODE__;
|
|
93
|
+
}
|
|
94
|
+
function getPlayerName() {
|
|
95
|
+
const bridge = getBridgeWindow2();
|
|
96
|
+
return bridge?.__PLAYER_NAME__;
|
|
97
|
+
}
|
|
98
|
+
function getPlayerAvatar() {
|
|
99
|
+
const bridge = getBridgeWindow2();
|
|
100
|
+
return bridge?.__PLAYER_AVATAR__;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/score.ts
|
|
104
|
+
function isDevelopment3() {
|
|
105
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
106
|
+
return nodeEnv !== "production";
|
|
107
|
+
}
|
|
108
|
+
function warnMissingBridge(methodName) {
|
|
109
|
+
if (isDevelopment3()) {
|
|
110
|
+
console.warn(
|
|
111
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function getBridgeWindow3() {
|
|
116
|
+
if (typeof window === "undefined") {
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
return window;
|
|
120
|
+
}
|
|
121
|
+
function submitScore(score) {
|
|
122
|
+
if (!Number.isFinite(score)) {
|
|
123
|
+
if (isDevelopment3()) {
|
|
124
|
+
console.warn("[oasiz/sdk] submitScore expected a finite number:", score);
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const bridge = getBridgeWindow3();
|
|
129
|
+
const normalizedScore = Math.max(0, Math.floor(score));
|
|
130
|
+
if (typeof bridge?.submitScore === "function") {
|
|
131
|
+
bridge.submitScore(normalizedScore);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
warnMissingBridge("submitScore");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/state.ts
|
|
138
|
+
function isDevelopment4() {
|
|
139
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
140
|
+
return nodeEnv !== "production";
|
|
141
|
+
}
|
|
142
|
+
function getBridgeWindow4() {
|
|
143
|
+
if (typeof window === "undefined") {
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
return window;
|
|
147
|
+
}
|
|
148
|
+
function isPlainObject(value) {
|
|
149
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
const proto = Object.getPrototypeOf(value);
|
|
153
|
+
return proto === Object.prototype || proto === null;
|
|
154
|
+
}
|
|
155
|
+
function warnMissingBridge2(methodName) {
|
|
156
|
+
if (isDevelopment4()) {
|
|
157
|
+
console.warn(
|
|
158
|
+
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function loadGameState() {
|
|
163
|
+
const bridge = getBridgeWindow4();
|
|
164
|
+
if (typeof bridge?.loadGameState !== "function") {
|
|
165
|
+
warnMissingBridge2("loadGameState");
|
|
166
|
+
return {};
|
|
167
|
+
}
|
|
168
|
+
const state = bridge.loadGameState();
|
|
169
|
+
if (!isPlainObject(state)) {
|
|
170
|
+
if (isDevelopment4()) {
|
|
171
|
+
console.warn(
|
|
172
|
+
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
return {};
|
|
176
|
+
}
|
|
177
|
+
return state;
|
|
178
|
+
}
|
|
179
|
+
function saveGameState(state) {
|
|
180
|
+
if (!isPlainObject(state)) {
|
|
181
|
+
if (isDevelopment4()) {
|
|
182
|
+
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const bridge = getBridgeWindow4();
|
|
187
|
+
if (typeof bridge?.saveGameState === "function") {
|
|
188
|
+
bridge.saveGameState(state);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
warnMissingBridge2("saveGameState");
|
|
192
|
+
}
|
|
193
|
+
function flushGameState() {
|
|
194
|
+
const bridge = getBridgeWindow4();
|
|
195
|
+
if (typeof bridge?.flushGameState === "function") {
|
|
196
|
+
bridge.flushGameState();
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
warnMissingBridge2("flushGameState");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/lifecycle.ts
|
|
203
|
+
function isDevelopment5() {
|
|
204
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
205
|
+
return nodeEnv !== "production";
|
|
206
|
+
}
|
|
207
|
+
function addLifecycleListener(eventName, callback) {
|
|
208
|
+
if (typeof window === "undefined") {
|
|
209
|
+
if (isDevelopment5()) {
|
|
210
|
+
console.warn(
|
|
211
|
+
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
return () => {
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const handler = () => callback();
|
|
218
|
+
window.addEventListener(eventName, handler);
|
|
219
|
+
return () => window.removeEventListener(eventName, handler);
|
|
220
|
+
}
|
|
221
|
+
function onPause(callback) {
|
|
222
|
+
return addLifecycleListener("oasiz:pause", callback);
|
|
223
|
+
}
|
|
224
|
+
function onResume(callback) {
|
|
225
|
+
return addLifecycleListener("oasiz:resume", callback);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/index.ts
|
|
229
|
+
var oasiz = {
|
|
230
|
+
submitScore,
|
|
231
|
+
triggerHaptic,
|
|
232
|
+
loadGameState,
|
|
233
|
+
saveGameState,
|
|
234
|
+
flushGameState,
|
|
235
|
+
shareRoomCode,
|
|
236
|
+
onPause,
|
|
237
|
+
onResume,
|
|
238
|
+
get gameId() {
|
|
239
|
+
return getGameId();
|
|
240
|
+
},
|
|
241
|
+
get roomCode() {
|
|
242
|
+
return getRoomCode();
|
|
243
|
+
},
|
|
244
|
+
get playerName() {
|
|
245
|
+
return getPlayerName();
|
|
246
|
+
},
|
|
247
|
+
get playerAvatar() {
|
|
248
|
+
return getPlayerAvatar();
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
return __toCommonJS(index_exports);
|
|
252
|
+
})();
|
package/dist/index.js
CHANGED
|
@@ -95,14 +95,6 @@ function submitScore(score) {
|
|
|
95
95
|
}
|
|
96
96
|
warnMissingBridge("submitScore");
|
|
97
97
|
}
|
|
98
|
-
function emitScoreConfig(config) {
|
|
99
|
-
const bridge = getBridgeWindow3();
|
|
100
|
-
if (typeof bridge?.emitScoreConfig === "function") {
|
|
101
|
-
bridge.emitScoreConfig(config);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
warnMissingBridge("emitScoreConfig");
|
|
105
|
-
}
|
|
106
98
|
|
|
107
99
|
// src/state.ts
|
|
108
100
|
function isDevelopment4() {
|
|
@@ -196,9 +188,8 @@ function onResume(callback) {
|
|
|
196
188
|
}
|
|
197
189
|
|
|
198
190
|
// src/index.ts
|
|
199
|
-
var
|
|
191
|
+
var oasiz = {
|
|
200
192
|
submitScore,
|
|
201
|
-
emitScoreConfig,
|
|
202
193
|
triggerHaptic,
|
|
203
194
|
loadGameState,
|
|
204
195
|
saveGameState,
|
|
@@ -220,14 +211,13 @@ var oasis = {
|
|
|
220
211
|
}
|
|
221
212
|
};
|
|
222
213
|
export {
|
|
223
|
-
emitScoreConfig,
|
|
224
214
|
flushGameState,
|
|
225
215
|
getGameId,
|
|
226
216
|
getPlayerAvatar,
|
|
227
217
|
getPlayerName,
|
|
228
218
|
getRoomCode,
|
|
229
219
|
loadGameState,
|
|
230
|
-
|
|
220
|
+
oasiz,
|
|
231
221
|
onPause,
|
|
232
222
|
onResume,
|
|
233
223
|
saveGameState,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oasiz/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Typed SDK for Oasiz game platform bridge APIs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
|
-
"require": "./dist/index.cjs"
|
|
13
|
+
"require": "./dist/index.cjs",
|
|
14
|
+
"script": "./dist/index.global.js"
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
@@ -18,9 +19,11 @@
|
|
|
18
19
|
],
|
|
19
20
|
"sideEffects": false,
|
|
20
21
|
"scripts": {
|
|
21
|
-
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
22
|
+
"build": "tsup src/index.ts --format esm,cjs,iife --global-name oasiz --dts",
|
|
22
23
|
"prepack": "bun run build",
|
|
23
|
-
"test": "node --experimental-strip-types --test ./tests/**/*.test.ts"
|
|
24
|
+
"test": "node --experimental-strip-types --test ./tests/**/*.test.ts",
|
|
25
|
+
"docs": "typedoc",
|
|
26
|
+
"docs:watch": "typedoc --watch"
|
|
24
27
|
},
|
|
25
28
|
"publishConfig": {
|
|
26
29
|
"access": "public"
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"@types/node": "^25.3.0",
|
|
48
51
|
"semantic-release": "^25.0.3",
|
|
49
52
|
"tsup": "^8.5.1",
|
|
53
|
+
"typedoc": "^0.28.17",
|
|
50
54
|
"typescript": "^5.9.3"
|
|
51
55
|
}
|
|
52
56
|
}
|