@oasiz/sdk 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/index.cjs +112 -31
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +111 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -219,6 +219,8 @@ Registers a callback for platform back actions. While at least one back listener
|
|
|
219
219
|
|
|
220
220
|
Use this for pause menus, in-game overlays, or custom back-stack behavior.
|
|
221
221
|
|
|
222
|
+
If your callback throws, Oasiz falls back to closing the game and returning the player to Oasiz home before rethrowing the error for debugging/reporting.
|
|
223
|
+
|
|
222
224
|
```ts
|
|
223
225
|
const offBack = oasiz.onBackButton(() => {
|
|
224
226
|
if (this.isPauseMenuOpen) {
|
|
@@ -242,6 +244,17 @@ quitButton.addEventListener("click", () => {
|
|
|
242
244
|
});
|
|
243
245
|
```
|
|
244
246
|
|
|
247
|
+
### `oasiz.share(options: { text?: string; score?: number; image?: string }): Promise<void>`
|
|
248
|
+
|
|
249
|
+
Ask the host to open the same share flow Oasiz already uses today. Use `text` to customize the share message, `score` to trigger a challenge-style share, and `image` to share an `http(s)` URL or `data:image/...` payload.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
await oasiz.share({
|
|
253
|
+
text: "I made it to level 9!",
|
|
254
|
+
score: 4200,
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
245
258
|
### `oasiz.onLeaveGame(callback: () => void): Unsubscribe`
|
|
246
259
|
|
|
247
260
|
Registers a callback fired when the host initiates closing the game (for example, close button, gesture, or host navigation). Use this for lightweight cleanup.
|
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
onResume: () => onResume,
|
|
44
44
|
purchase: () => purchase,
|
|
45
45
|
saveGameState: () => saveGameState,
|
|
46
|
+
share: () => share,
|
|
46
47
|
shareRoomCode: () => shareRoomCode,
|
|
47
48
|
submitScore: () => submitScore,
|
|
48
49
|
syncProducts: () => syncProducts,
|
|
@@ -156,7 +157,7 @@ function emitScoreConfig(config) {
|
|
|
156
157
|
warnMissingBridge("emitScoreConfig");
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
// src/
|
|
160
|
+
// src/share.ts
|
|
160
161
|
function isDevelopment4() {
|
|
161
162
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
162
163
|
return nodeEnv !== "production";
|
|
@@ -167,6 +168,69 @@ function getBridgeWindow4() {
|
|
|
167
168
|
}
|
|
168
169
|
return window;
|
|
169
170
|
}
|
|
171
|
+
function warnMissingBridge2(methodName) {
|
|
172
|
+
if (isDevelopment4()) {
|
|
173
|
+
console.warn(
|
|
174
|
+
"[oasiz/sdk] " + methodName + " share bridge is unavailable. This is expected in local development."
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function isValidImageReference(image) {
|
|
179
|
+
if (/^data:image\/[a-zA-Z0-9.+-]+;base64,/.test(image)) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
const parsed = new URL(image);
|
|
184
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
185
|
+
} catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function validateRequest(options) {
|
|
190
|
+
const text = typeof options.text === "string" ? options.text.trim() : "";
|
|
191
|
+
const hasText = text.length > 0;
|
|
192
|
+
const hasScore = options.score !== void 0;
|
|
193
|
+
const hasImage = typeof options.image === "string" && options.image.length > 0;
|
|
194
|
+
if (!hasText && !hasScore && !hasImage) {
|
|
195
|
+
throw new Error("Share request requires text, score, or image.");
|
|
196
|
+
}
|
|
197
|
+
if (hasScore) {
|
|
198
|
+
if (typeof options.score !== "number" || !Number.isInteger(options.score) || options.score < 0) {
|
|
199
|
+
throw new Error("Share score must be a non-negative integer.");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (hasImage && !isValidImageReference(options.image)) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
"Share image must be an http(s) URL or a data:image/... base64 string."
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
...hasText ? { text } : {},
|
|
209
|
+
...hasScore ? { score: options.score } : {},
|
|
210
|
+
...hasImage ? { image: options.image } : {}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async function share(options) {
|
|
214
|
+
const request = validateRequest(options);
|
|
215
|
+
const bridge = getBridgeWindow4();
|
|
216
|
+
if (typeof bridge?.__oasizShareRequest !== "function") {
|
|
217
|
+
warnMissingBridge2("__oasizShareRequest");
|
|
218
|
+
throw new Error("Share bridge unavailable");
|
|
219
|
+
}
|
|
220
|
+
await bridge.__oasizShareRequest(request);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/state.ts
|
|
224
|
+
function isDevelopment5() {
|
|
225
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
226
|
+
return nodeEnv !== "production";
|
|
227
|
+
}
|
|
228
|
+
function getBridgeWindow5() {
|
|
229
|
+
if (typeof window === "undefined") {
|
|
230
|
+
return void 0;
|
|
231
|
+
}
|
|
232
|
+
return window;
|
|
233
|
+
}
|
|
170
234
|
function isPlainObject(value) {
|
|
171
235
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
172
236
|
return false;
|
|
@@ -174,22 +238,22 @@ function isPlainObject(value) {
|
|
|
174
238
|
const proto = Object.getPrototypeOf(value);
|
|
175
239
|
return proto === Object.prototype || proto === null;
|
|
176
240
|
}
|
|
177
|
-
function
|
|
178
|
-
if (
|
|
241
|
+
function warnMissingBridge3(methodName) {
|
|
242
|
+
if (isDevelopment5()) {
|
|
179
243
|
console.warn(
|
|
180
244
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
181
245
|
);
|
|
182
246
|
}
|
|
183
247
|
}
|
|
184
248
|
function loadGameState() {
|
|
185
|
-
const bridge =
|
|
249
|
+
const bridge = getBridgeWindow5();
|
|
186
250
|
if (typeof bridge?.loadGameState !== "function") {
|
|
187
|
-
|
|
251
|
+
warnMissingBridge3("loadGameState");
|
|
188
252
|
return {};
|
|
189
253
|
}
|
|
190
254
|
const state = bridge.loadGameState();
|
|
191
255
|
if (!isPlainObject(state)) {
|
|
192
|
-
if (
|
|
256
|
+
if (isDevelopment5()) {
|
|
193
257
|
console.warn(
|
|
194
258
|
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
195
259
|
);
|
|
@@ -200,35 +264,35 @@ function loadGameState() {
|
|
|
200
264
|
}
|
|
201
265
|
function saveGameState(state) {
|
|
202
266
|
if (!isPlainObject(state)) {
|
|
203
|
-
if (
|
|
267
|
+
if (isDevelopment5()) {
|
|
204
268
|
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
205
269
|
}
|
|
206
270
|
return;
|
|
207
271
|
}
|
|
208
|
-
const bridge =
|
|
272
|
+
const bridge = getBridgeWindow5();
|
|
209
273
|
if (typeof bridge?.saveGameState === "function") {
|
|
210
274
|
bridge.saveGameState(state);
|
|
211
275
|
return;
|
|
212
276
|
}
|
|
213
|
-
|
|
277
|
+
warnMissingBridge3("saveGameState");
|
|
214
278
|
}
|
|
215
279
|
function flushGameState() {
|
|
216
|
-
const bridge =
|
|
280
|
+
const bridge = getBridgeWindow5();
|
|
217
281
|
if (typeof bridge?.flushGameState === "function") {
|
|
218
282
|
bridge.flushGameState();
|
|
219
283
|
return;
|
|
220
284
|
}
|
|
221
|
-
|
|
285
|
+
warnMissingBridge3("flushGameState");
|
|
222
286
|
}
|
|
223
287
|
|
|
224
288
|
// src/lifecycle.ts
|
|
225
|
-
function
|
|
289
|
+
function isDevelopment6() {
|
|
226
290
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
227
291
|
return nodeEnv !== "production";
|
|
228
292
|
}
|
|
229
293
|
function addLifecycleListener(eventName, callback) {
|
|
230
294
|
if (typeof window === "undefined") {
|
|
231
|
-
if (
|
|
295
|
+
if (isDevelopment6()) {
|
|
232
296
|
console.warn(
|
|
233
297
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
234
298
|
);
|
|
@@ -249,26 +313,34 @@ function onResume(callback) {
|
|
|
249
313
|
|
|
250
314
|
// src/navigation.ts
|
|
251
315
|
var activeBackListeners = 0;
|
|
252
|
-
function
|
|
316
|
+
function isDevelopment7() {
|
|
253
317
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
254
318
|
return nodeEnv !== "production";
|
|
255
319
|
}
|
|
256
|
-
function
|
|
320
|
+
function getBridgeWindow6() {
|
|
257
321
|
if (typeof window === "undefined") {
|
|
258
322
|
return void 0;
|
|
259
323
|
}
|
|
260
324
|
return window;
|
|
261
325
|
}
|
|
262
|
-
function
|
|
263
|
-
if (
|
|
326
|
+
function warnMissingBridge4(methodName) {
|
|
327
|
+
if (isDevelopment7()) {
|
|
264
328
|
console.warn(
|
|
265
329
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
266
330
|
);
|
|
267
331
|
}
|
|
268
332
|
}
|
|
333
|
+
function normalizeNavigationError(error) {
|
|
334
|
+
if (error instanceof Error) {
|
|
335
|
+
return error;
|
|
336
|
+
}
|
|
337
|
+
return new Error(
|
|
338
|
+
typeof error === "string" ? error : "Back button callback failed."
|
|
339
|
+
);
|
|
340
|
+
}
|
|
269
341
|
function addNavigationListener(eventName, callback) {
|
|
270
342
|
if (typeof window === "undefined") {
|
|
271
|
-
if (
|
|
343
|
+
if (isDevelopment7()) {
|
|
272
344
|
console.warn(
|
|
273
345
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
274
346
|
);
|
|
@@ -281,25 +353,32 @@ function addNavigationListener(eventName, callback) {
|
|
|
281
353
|
return () => window.removeEventListener(eventName, handler);
|
|
282
354
|
}
|
|
283
355
|
function onBackButton(callback) {
|
|
284
|
-
const off = addNavigationListener("oasiz:back",
|
|
285
|
-
|
|
356
|
+
const off = addNavigationListener("oasiz:back", () => {
|
|
357
|
+
try {
|
|
358
|
+
callback();
|
|
359
|
+
} catch (error) {
|
|
360
|
+
leaveGame();
|
|
361
|
+
throw normalizeNavigationError(error);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
const bridge = getBridgeWindow6();
|
|
286
365
|
activeBackListeners += 1;
|
|
287
366
|
if (activeBackListeners === 1) {
|
|
288
367
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
289
368
|
bridge.__oasizSetBackOverride(true);
|
|
290
369
|
} else {
|
|
291
|
-
|
|
370
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
292
371
|
}
|
|
293
372
|
}
|
|
294
373
|
return () => {
|
|
295
374
|
off();
|
|
296
375
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
297
376
|
if (activeBackListeners === 0) {
|
|
298
|
-
const currentBridge =
|
|
377
|
+
const currentBridge = getBridgeWindow6();
|
|
299
378
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
300
379
|
currentBridge.__oasizSetBackOverride(false);
|
|
301
380
|
} else {
|
|
302
|
-
|
|
381
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
303
382
|
}
|
|
304
383
|
}
|
|
305
384
|
};
|
|
@@ -308,36 +387,36 @@ function onLeaveGame(callback) {
|
|
|
308
387
|
return addNavigationListener("oasiz:leave", callback);
|
|
309
388
|
}
|
|
310
389
|
function leaveGame() {
|
|
311
|
-
const bridge =
|
|
390
|
+
const bridge = getBridgeWindow6();
|
|
312
391
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
313
392
|
bridge.__oasizLeaveGame();
|
|
314
393
|
return;
|
|
315
394
|
}
|
|
316
|
-
|
|
395
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
317
396
|
}
|
|
318
397
|
|
|
319
398
|
// src/store.ts
|
|
320
|
-
function
|
|
399
|
+
function isDevelopment8() {
|
|
321
400
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
322
401
|
return nodeEnv !== "production";
|
|
323
402
|
}
|
|
324
|
-
function
|
|
403
|
+
function getBridgeWindow7() {
|
|
325
404
|
if (typeof window === "undefined") {
|
|
326
405
|
return void 0;
|
|
327
406
|
}
|
|
328
407
|
return window;
|
|
329
408
|
}
|
|
330
|
-
function
|
|
331
|
-
if (
|
|
409
|
+
function warnMissingBridge5(methodName) {
|
|
410
|
+
if (isDevelopment8()) {
|
|
332
411
|
console.warn(
|
|
333
412
|
"[oasiz/sdk] " + methodName + " store bridge is unavailable. This is expected in local development."
|
|
334
413
|
);
|
|
335
414
|
}
|
|
336
415
|
}
|
|
337
416
|
async function requestStoreBridge(action, payload) {
|
|
338
|
-
const bridge =
|
|
417
|
+
const bridge = getBridgeWindow7();
|
|
339
418
|
if (typeof bridge?.__oasizStoreBridgeRequest !== "function") {
|
|
340
|
-
|
|
419
|
+
warnMissingBridge5(action);
|
|
341
420
|
throw new Error("Store bridge unavailable");
|
|
342
421
|
}
|
|
343
422
|
return await bridge.__oasizStoreBridgeRequest({
|
|
@@ -415,6 +494,7 @@ function onJemBalanceChanged(callback) {
|
|
|
415
494
|
var oasiz = {
|
|
416
495
|
submitScore,
|
|
417
496
|
emitScoreConfig,
|
|
497
|
+
share,
|
|
418
498
|
triggerHaptic,
|
|
419
499
|
loadGameState,
|
|
420
500
|
saveGameState,
|
|
@@ -475,6 +555,7 @@ var oasiz = {
|
|
|
475
555
|
onResume,
|
|
476
556
|
purchase,
|
|
477
557
|
saveGameState,
|
|
558
|
+
share,
|
|
478
559
|
shareRoomCode,
|
|
479
560
|
submitScore,
|
|
480
561
|
syncProducts,
|
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,11 @@ interface ScoreConfig {
|
|
|
7
7
|
anchors: [ScoreAnchor, ScoreAnchor, ScoreAnchor, ScoreAnchor];
|
|
8
8
|
}
|
|
9
9
|
type GameState = Record<string, unknown>;
|
|
10
|
+
interface ShareRequest {
|
|
11
|
+
image?: string;
|
|
12
|
+
score?: number;
|
|
13
|
+
text?: string;
|
|
14
|
+
}
|
|
10
15
|
type StoreProductType = "non-consumable" | "consumable";
|
|
11
16
|
type StoreProductStatus = "active" | "disabled" | "archived";
|
|
12
17
|
type StoreEntitlementStatus = "active" | "consumed" | "revoked" | "refunded";
|
|
@@ -90,6 +95,8 @@ declare function getPlayerAvatar(): string | undefined;
|
|
|
90
95
|
declare function submitScore(score: number): void;
|
|
91
96
|
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
92
97
|
|
|
98
|
+
declare function share(options: ShareRequest): Promise<void>;
|
|
99
|
+
|
|
93
100
|
declare function loadGameState(): GameState;
|
|
94
101
|
declare function saveGameState(state: GameState): void;
|
|
95
102
|
declare function flushGameState(): void;
|
|
@@ -116,6 +123,7 @@ declare function onJemBalanceChanged(callback: (jemBalance: number) => void): ()
|
|
|
116
123
|
declare const oasiz: {
|
|
117
124
|
submitScore: typeof submitScore;
|
|
118
125
|
emitScoreConfig: typeof emitScoreConfig;
|
|
126
|
+
share: typeof share;
|
|
119
127
|
triggerHaptic: typeof triggerHaptic;
|
|
120
128
|
loadGameState: typeof loadGameState;
|
|
121
129
|
saveGameState: typeof saveGameState;
|
|
@@ -144,4 +152,4 @@ declare const oasiz: {
|
|
|
144
152
|
readonly playerAvatar: string | undefined;
|
|
145
153
|
};
|
|
146
154
|
|
|
147
|
-
export { type GameState, type HapticType, type ScoreAnchor, type ScoreConfig, type StoreConsumeFailure, type StoreConsumeResult, type StoreConsumeSuccess, type StoreEntitlement, type StoreEntitlementStatus, type StoreManifestProduct, type StoreProduct, type StoreProductStatus, type StoreProductType, type StorePurchaseFailure, type StorePurchaseResult, type StorePurchaseSuccess, type StoreStateSnapshot, type Unsubscribe, consume, emitScoreConfig, flushGameState, getEntitlements, getGameId, getJemBalance, getPlayerAvatar, getPlayerName, getProducts, getQuantity, getRoomCode, hasEntitlement, leaveGame, loadGameState, oasiz, onBackButton, onEntitlementsChanged, onJemBalanceChanged, onLeaveGame, onPause, onResume, purchase, saveGameState, shareRoomCode, submitScore, syncProducts, triggerHaptic };
|
|
155
|
+
export { type GameState, type HapticType, type ScoreAnchor, type ScoreConfig, type ShareRequest, type StoreConsumeFailure, type StoreConsumeResult, type StoreConsumeSuccess, type StoreEntitlement, type StoreEntitlementStatus, type StoreManifestProduct, type StoreProduct, type StoreProductStatus, type StoreProductType, type StorePurchaseFailure, type StorePurchaseResult, type StorePurchaseSuccess, type StoreStateSnapshot, type Unsubscribe, consume, emitScoreConfig, flushGameState, getEntitlements, getGameId, getJemBalance, getPlayerAvatar, getPlayerName, getProducts, getQuantity, getRoomCode, hasEntitlement, leaveGame, loadGameState, oasiz, onBackButton, onEntitlementsChanged, onJemBalanceChanged, onLeaveGame, onPause, onResume, purchase, saveGameState, share, shareRoomCode, submitScore, syncProducts, triggerHaptic };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,11 @@ interface ScoreConfig {
|
|
|
7
7
|
anchors: [ScoreAnchor, ScoreAnchor, ScoreAnchor, ScoreAnchor];
|
|
8
8
|
}
|
|
9
9
|
type GameState = Record<string, unknown>;
|
|
10
|
+
interface ShareRequest {
|
|
11
|
+
image?: string;
|
|
12
|
+
score?: number;
|
|
13
|
+
text?: string;
|
|
14
|
+
}
|
|
10
15
|
type StoreProductType = "non-consumable" | "consumable";
|
|
11
16
|
type StoreProductStatus = "active" | "disabled" | "archived";
|
|
12
17
|
type StoreEntitlementStatus = "active" | "consumed" | "revoked" | "refunded";
|
|
@@ -90,6 +95,8 @@ declare function getPlayerAvatar(): string | undefined;
|
|
|
90
95
|
declare function submitScore(score: number): void;
|
|
91
96
|
declare function emitScoreConfig(config: ScoreConfig): void;
|
|
92
97
|
|
|
98
|
+
declare function share(options: ShareRequest): Promise<void>;
|
|
99
|
+
|
|
93
100
|
declare function loadGameState(): GameState;
|
|
94
101
|
declare function saveGameState(state: GameState): void;
|
|
95
102
|
declare function flushGameState(): void;
|
|
@@ -116,6 +123,7 @@ declare function onJemBalanceChanged(callback: (jemBalance: number) => void): ()
|
|
|
116
123
|
declare const oasiz: {
|
|
117
124
|
submitScore: typeof submitScore;
|
|
118
125
|
emitScoreConfig: typeof emitScoreConfig;
|
|
126
|
+
share: typeof share;
|
|
119
127
|
triggerHaptic: typeof triggerHaptic;
|
|
120
128
|
loadGameState: typeof loadGameState;
|
|
121
129
|
saveGameState: typeof saveGameState;
|
|
@@ -144,4 +152,4 @@ declare const oasiz: {
|
|
|
144
152
|
readonly playerAvatar: string | undefined;
|
|
145
153
|
};
|
|
146
154
|
|
|
147
|
-
export { type GameState, type HapticType, type ScoreAnchor, type ScoreConfig, type StoreConsumeFailure, type StoreConsumeResult, type StoreConsumeSuccess, type StoreEntitlement, type StoreEntitlementStatus, type StoreManifestProduct, type StoreProduct, type StoreProductStatus, type StoreProductType, type StorePurchaseFailure, type StorePurchaseResult, type StorePurchaseSuccess, type StoreStateSnapshot, type Unsubscribe, consume, emitScoreConfig, flushGameState, getEntitlements, getGameId, getJemBalance, getPlayerAvatar, getPlayerName, getProducts, getQuantity, getRoomCode, hasEntitlement, leaveGame, loadGameState, oasiz, onBackButton, onEntitlementsChanged, onJemBalanceChanged, onLeaveGame, onPause, onResume, purchase, saveGameState, shareRoomCode, submitScore, syncProducts, triggerHaptic };
|
|
155
|
+
export { type GameState, type HapticType, type ScoreAnchor, type ScoreConfig, type ShareRequest, type StoreConsumeFailure, type StoreConsumeResult, type StoreConsumeSuccess, type StoreEntitlement, type StoreEntitlementStatus, type StoreManifestProduct, type StoreProduct, type StoreProductStatus, type StoreProductType, type StorePurchaseFailure, type StorePurchaseResult, type StorePurchaseSuccess, type StoreStateSnapshot, type Unsubscribe, consume, emitScoreConfig, flushGameState, getEntitlements, getGameId, getJemBalance, getPlayerAvatar, getPlayerName, getProducts, getQuantity, getRoomCode, hasEntitlement, leaveGame, loadGameState, oasiz, onBackButton, onEntitlementsChanged, onJemBalanceChanged, onLeaveGame, onPause, onResume, purchase, saveGameState, share, shareRoomCode, submitScore, syncProducts, triggerHaptic };
|
package/dist/index.js
CHANGED
|
@@ -104,7 +104,7 @@ function emitScoreConfig(config) {
|
|
|
104
104
|
warnMissingBridge("emitScoreConfig");
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
// src/
|
|
107
|
+
// src/share.ts
|
|
108
108
|
function isDevelopment4() {
|
|
109
109
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
110
110
|
return nodeEnv !== "production";
|
|
@@ -115,6 +115,69 @@ function getBridgeWindow4() {
|
|
|
115
115
|
}
|
|
116
116
|
return window;
|
|
117
117
|
}
|
|
118
|
+
function warnMissingBridge2(methodName) {
|
|
119
|
+
if (isDevelopment4()) {
|
|
120
|
+
console.warn(
|
|
121
|
+
"[oasiz/sdk] " + methodName + " share bridge is unavailable. This is expected in local development."
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function isValidImageReference(image) {
|
|
126
|
+
if (/^data:image\/[a-zA-Z0-9.+-]+;base64,/.test(image)) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const parsed = new URL(image);
|
|
131
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
132
|
+
} catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function validateRequest(options) {
|
|
137
|
+
const text = typeof options.text === "string" ? options.text.trim() : "";
|
|
138
|
+
const hasText = text.length > 0;
|
|
139
|
+
const hasScore = options.score !== void 0;
|
|
140
|
+
const hasImage = typeof options.image === "string" && options.image.length > 0;
|
|
141
|
+
if (!hasText && !hasScore && !hasImage) {
|
|
142
|
+
throw new Error("Share request requires text, score, or image.");
|
|
143
|
+
}
|
|
144
|
+
if (hasScore) {
|
|
145
|
+
if (typeof options.score !== "number" || !Number.isInteger(options.score) || options.score < 0) {
|
|
146
|
+
throw new Error("Share score must be a non-negative integer.");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (hasImage && !isValidImageReference(options.image)) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
"Share image must be an http(s) URL or a data:image/... base64 string."
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
...hasText ? { text } : {},
|
|
156
|
+
...hasScore ? { score: options.score } : {},
|
|
157
|
+
...hasImage ? { image: options.image } : {}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async function share(options) {
|
|
161
|
+
const request = validateRequest(options);
|
|
162
|
+
const bridge = getBridgeWindow4();
|
|
163
|
+
if (typeof bridge?.__oasizShareRequest !== "function") {
|
|
164
|
+
warnMissingBridge2("__oasizShareRequest");
|
|
165
|
+
throw new Error("Share bridge unavailable");
|
|
166
|
+
}
|
|
167
|
+
await bridge.__oasizShareRequest(request);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/state.ts
|
|
171
|
+
function isDevelopment5() {
|
|
172
|
+
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
173
|
+
return nodeEnv !== "production";
|
|
174
|
+
}
|
|
175
|
+
function getBridgeWindow5() {
|
|
176
|
+
if (typeof window === "undefined") {
|
|
177
|
+
return void 0;
|
|
178
|
+
}
|
|
179
|
+
return window;
|
|
180
|
+
}
|
|
118
181
|
function isPlainObject(value) {
|
|
119
182
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
120
183
|
return false;
|
|
@@ -122,22 +185,22 @@ function isPlainObject(value) {
|
|
|
122
185
|
const proto = Object.getPrototypeOf(value);
|
|
123
186
|
return proto === Object.prototype || proto === null;
|
|
124
187
|
}
|
|
125
|
-
function
|
|
126
|
-
if (
|
|
188
|
+
function warnMissingBridge3(methodName) {
|
|
189
|
+
if (isDevelopment5()) {
|
|
127
190
|
console.warn(
|
|
128
191
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
129
192
|
);
|
|
130
193
|
}
|
|
131
194
|
}
|
|
132
195
|
function loadGameState() {
|
|
133
|
-
const bridge =
|
|
196
|
+
const bridge = getBridgeWindow5();
|
|
134
197
|
if (typeof bridge?.loadGameState !== "function") {
|
|
135
|
-
|
|
198
|
+
warnMissingBridge3("loadGameState");
|
|
136
199
|
return {};
|
|
137
200
|
}
|
|
138
201
|
const state = bridge.loadGameState();
|
|
139
202
|
if (!isPlainObject(state)) {
|
|
140
|
-
if (
|
|
203
|
+
if (isDevelopment5()) {
|
|
141
204
|
console.warn(
|
|
142
205
|
"[oasiz/sdk] loadGameState returned invalid data. Falling back to empty object."
|
|
143
206
|
);
|
|
@@ -148,35 +211,35 @@ function loadGameState() {
|
|
|
148
211
|
}
|
|
149
212
|
function saveGameState(state) {
|
|
150
213
|
if (!isPlainObject(state)) {
|
|
151
|
-
if (
|
|
214
|
+
if (isDevelopment5()) {
|
|
152
215
|
console.warn("[oasiz/sdk] saveGameState expected a plain object:", state);
|
|
153
216
|
}
|
|
154
217
|
return;
|
|
155
218
|
}
|
|
156
|
-
const bridge =
|
|
219
|
+
const bridge = getBridgeWindow5();
|
|
157
220
|
if (typeof bridge?.saveGameState === "function") {
|
|
158
221
|
bridge.saveGameState(state);
|
|
159
222
|
return;
|
|
160
223
|
}
|
|
161
|
-
|
|
224
|
+
warnMissingBridge3("saveGameState");
|
|
162
225
|
}
|
|
163
226
|
function flushGameState() {
|
|
164
|
-
const bridge =
|
|
227
|
+
const bridge = getBridgeWindow5();
|
|
165
228
|
if (typeof bridge?.flushGameState === "function") {
|
|
166
229
|
bridge.flushGameState();
|
|
167
230
|
return;
|
|
168
231
|
}
|
|
169
|
-
|
|
232
|
+
warnMissingBridge3("flushGameState");
|
|
170
233
|
}
|
|
171
234
|
|
|
172
235
|
// src/lifecycle.ts
|
|
173
|
-
function
|
|
236
|
+
function isDevelopment6() {
|
|
174
237
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
175
238
|
return nodeEnv !== "production";
|
|
176
239
|
}
|
|
177
240
|
function addLifecycleListener(eventName, callback) {
|
|
178
241
|
if (typeof window === "undefined") {
|
|
179
|
-
if (
|
|
242
|
+
if (isDevelopment6()) {
|
|
180
243
|
console.warn(
|
|
181
244
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
182
245
|
);
|
|
@@ -197,26 +260,34 @@ function onResume(callback) {
|
|
|
197
260
|
|
|
198
261
|
// src/navigation.ts
|
|
199
262
|
var activeBackListeners = 0;
|
|
200
|
-
function
|
|
263
|
+
function isDevelopment7() {
|
|
201
264
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
202
265
|
return nodeEnv !== "production";
|
|
203
266
|
}
|
|
204
|
-
function
|
|
267
|
+
function getBridgeWindow6() {
|
|
205
268
|
if (typeof window === "undefined") {
|
|
206
269
|
return void 0;
|
|
207
270
|
}
|
|
208
271
|
return window;
|
|
209
272
|
}
|
|
210
|
-
function
|
|
211
|
-
if (
|
|
273
|
+
function warnMissingBridge4(methodName) {
|
|
274
|
+
if (isDevelopment7()) {
|
|
212
275
|
console.warn(
|
|
213
276
|
"[oasiz/sdk] " + methodName + " bridge is unavailable. This is expected in local development."
|
|
214
277
|
);
|
|
215
278
|
}
|
|
216
279
|
}
|
|
280
|
+
function normalizeNavigationError(error) {
|
|
281
|
+
if (error instanceof Error) {
|
|
282
|
+
return error;
|
|
283
|
+
}
|
|
284
|
+
return new Error(
|
|
285
|
+
typeof error === "string" ? error : "Back button callback failed."
|
|
286
|
+
);
|
|
287
|
+
}
|
|
217
288
|
function addNavigationListener(eventName, callback) {
|
|
218
289
|
if (typeof window === "undefined") {
|
|
219
|
-
if (
|
|
290
|
+
if (isDevelopment7()) {
|
|
220
291
|
console.warn(
|
|
221
292
|
"[oasiz/sdk] " + eventName + " listener registered without a browser window. This is expected in local development."
|
|
222
293
|
);
|
|
@@ -229,25 +300,32 @@ function addNavigationListener(eventName, callback) {
|
|
|
229
300
|
return () => window.removeEventListener(eventName, handler);
|
|
230
301
|
}
|
|
231
302
|
function onBackButton(callback) {
|
|
232
|
-
const off = addNavigationListener("oasiz:back",
|
|
233
|
-
|
|
303
|
+
const off = addNavigationListener("oasiz:back", () => {
|
|
304
|
+
try {
|
|
305
|
+
callback();
|
|
306
|
+
} catch (error) {
|
|
307
|
+
leaveGame();
|
|
308
|
+
throw normalizeNavigationError(error);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
const bridge = getBridgeWindow6();
|
|
234
312
|
activeBackListeners += 1;
|
|
235
313
|
if (activeBackListeners === 1) {
|
|
236
314
|
if (typeof bridge?.__oasizSetBackOverride === "function") {
|
|
237
315
|
bridge.__oasizSetBackOverride(true);
|
|
238
316
|
} else {
|
|
239
|
-
|
|
317
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
240
318
|
}
|
|
241
319
|
}
|
|
242
320
|
return () => {
|
|
243
321
|
off();
|
|
244
322
|
activeBackListeners = Math.max(0, activeBackListeners - 1);
|
|
245
323
|
if (activeBackListeners === 0) {
|
|
246
|
-
const currentBridge =
|
|
324
|
+
const currentBridge = getBridgeWindow6();
|
|
247
325
|
if (typeof currentBridge?.__oasizSetBackOverride === "function") {
|
|
248
326
|
currentBridge.__oasizSetBackOverride(false);
|
|
249
327
|
} else {
|
|
250
|
-
|
|
328
|
+
warnMissingBridge4("__oasizSetBackOverride");
|
|
251
329
|
}
|
|
252
330
|
}
|
|
253
331
|
};
|
|
@@ -256,36 +334,36 @@ function onLeaveGame(callback) {
|
|
|
256
334
|
return addNavigationListener("oasiz:leave", callback);
|
|
257
335
|
}
|
|
258
336
|
function leaveGame() {
|
|
259
|
-
const bridge =
|
|
337
|
+
const bridge = getBridgeWindow6();
|
|
260
338
|
if (typeof bridge?.__oasizLeaveGame === "function") {
|
|
261
339
|
bridge.__oasizLeaveGame();
|
|
262
340
|
return;
|
|
263
341
|
}
|
|
264
|
-
|
|
342
|
+
warnMissingBridge4("__oasizLeaveGame");
|
|
265
343
|
}
|
|
266
344
|
|
|
267
345
|
// src/store.ts
|
|
268
|
-
function
|
|
346
|
+
function isDevelopment8() {
|
|
269
347
|
const nodeEnv = globalThis.process?.env?.NODE_ENV;
|
|
270
348
|
return nodeEnv !== "production";
|
|
271
349
|
}
|
|
272
|
-
function
|
|
350
|
+
function getBridgeWindow7() {
|
|
273
351
|
if (typeof window === "undefined") {
|
|
274
352
|
return void 0;
|
|
275
353
|
}
|
|
276
354
|
return window;
|
|
277
355
|
}
|
|
278
|
-
function
|
|
279
|
-
if (
|
|
356
|
+
function warnMissingBridge5(methodName) {
|
|
357
|
+
if (isDevelopment8()) {
|
|
280
358
|
console.warn(
|
|
281
359
|
"[oasiz/sdk] " + methodName + " store bridge is unavailable. This is expected in local development."
|
|
282
360
|
);
|
|
283
361
|
}
|
|
284
362
|
}
|
|
285
363
|
async function requestStoreBridge(action, payload) {
|
|
286
|
-
const bridge =
|
|
364
|
+
const bridge = getBridgeWindow7();
|
|
287
365
|
if (typeof bridge?.__oasizStoreBridgeRequest !== "function") {
|
|
288
|
-
|
|
366
|
+
warnMissingBridge5(action);
|
|
289
367
|
throw new Error("Store bridge unavailable");
|
|
290
368
|
}
|
|
291
369
|
return await bridge.__oasizStoreBridgeRequest({
|
|
@@ -363,6 +441,7 @@ function onJemBalanceChanged(callback) {
|
|
|
363
441
|
var oasiz = {
|
|
364
442
|
submitScore,
|
|
365
443
|
emitScoreConfig,
|
|
444
|
+
share,
|
|
366
445
|
triggerHaptic,
|
|
367
446
|
loadGameState,
|
|
368
447
|
saveGameState,
|
|
@@ -422,6 +501,7 @@ export {
|
|
|
422
501
|
onResume,
|
|
423
502
|
purchase,
|
|
424
503
|
saveGameState,
|
|
504
|
+
share,
|
|
425
505
|
shareRoomCode,
|
|
426
506
|
submitScore,
|
|
427
507
|
syncProducts,
|