@mpgd/adapter-ait 0.5.2 → 0.6.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/dist/index.d.ts +12 -1
- package/dist/index.js +136 -19
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,17 @@ import type { PlatformGateway } from '@mpgd/platform';
|
|
|
3
3
|
export interface GamePlatformBridge {
|
|
4
4
|
request(input: BridgeRequest): Promise<BridgeResponse>;
|
|
5
5
|
}
|
|
6
|
+
export interface AitSandboxStorage {
|
|
7
|
+
readonly getItem: (key: string) => string | null;
|
|
8
|
+
readonly setItem: (key: string, value: string) => void;
|
|
9
|
+
readonly removeItem?: (key: string) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface CreateAitSandboxBridgeOptions {
|
|
12
|
+
/** Persistent browser storage used by local AIT playtests. Defaults to localStorage when available. */
|
|
13
|
+
readonly storage?: AitSandboxStorage | null;
|
|
14
|
+
/** Namespace for persisted sandbox values so they cannot collide with application-owned keys. */
|
|
15
|
+
readonly storageKeyPrefix?: string;
|
|
16
|
+
}
|
|
6
17
|
export declare function createAitPlatformGateway(input: {
|
|
7
18
|
readonly appVersion: string;
|
|
8
19
|
readonly buildId: string;
|
|
@@ -10,4 +21,4 @@ export declare function createAitPlatformGateway(input: {
|
|
|
10
21
|
readonly fallbackBridge?: GamePlatformBridge;
|
|
11
22
|
}): PlatformGateway;
|
|
12
23
|
export { aitLifecyclePauseEvent, aitLifecycleResumeEvent, createAitLifecycleAdapter, dispatchAitLifecycleEvent, } from './lifecycle.js';
|
|
13
|
-
export declare function createAitSandboxBridge(): GamePlatformBridge;
|
|
24
|
+
export declare function createAitSandboxBridge(options?: CreateAitSandboxBridgeOptions): GamePlatformBridge;
|
package/dist/index.js
CHANGED
|
@@ -72,8 +72,18 @@ export { aitLifecyclePauseEvent, aitLifecycleResumeEvent, createAitLifecycleAdap
|
|
|
72
72
|
function getBridge() {
|
|
73
73
|
return globalThis.__GAME_PLATFORM_BRIDGE__;
|
|
74
74
|
}
|
|
75
|
-
export function createAitSandboxBridge() {
|
|
75
|
+
export function createAitSandboxBridge(options = {}) {
|
|
76
76
|
const storage = new Map();
|
|
77
|
+
let persistentStorage;
|
|
78
|
+
if (options.storage === undefined) {
|
|
79
|
+
persistentStorage = resolveAitSandboxBrowserStorage();
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
persistentStorage = options.storage ?? undefined;
|
|
83
|
+
}
|
|
84
|
+
// PlatformGateway storage exposes load/save only. Sandbox callers should use stable,
|
|
85
|
+
// namespaced keys whose values are overwritten instead of creating an unbounded key stream.
|
|
86
|
+
const storageKeyPrefix = options.storageKeyPrefix ?? 'mpgd:ait-sandbox:';
|
|
77
87
|
return {
|
|
78
88
|
async request(input) {
|
|
79
89
|
switch (input.method) {
|
|
@@ -167,41 +177,141 @@ export function createAitSandboxBridge() {
|
|
|
167
177
|
return ok(input, {});
|
|
168
178
|
case 'storage.load': {
|
|
169
179
|
const payload = input.payload;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
if (payload.key === undefined) {
|
|
181
|
+
return ok(input, {
|
|
182
|
+
__mpgdBridgeProtocol: bridgeStorageLoadProtocol,
|
|
183
|
+
found: false,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (storage.has(payload.key)) {
|
|
187
|
+
return ok(input, {
|
|
188
|
+
__mpgdBridgeProtocol: bridgeStorageLoadProtocol,
|
|
189
|
+
found: true,
|
|
190
|
+
value: cloneJsonValue(storage.get(payload.key)),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const persistent = loadPersistentSandboxValue(persistentStorage, `${storageKeyPrefix}${payload.key}`);
|
|
194
|
+
// Browser storage access failures commonly remain blocked for the page lifetime. The
|
|
195
|
+
// sandbox intentionally degrades once per bridge instead of retrying and logging on every
|
|
196
|
+
// load. Production AIT storage uses the host bridge and is not affected by this fallback.
|
|
197
|
+
if (!persistent.storageAvailable && persistentStorage !== undefined) {
|
|
198
|
+
console.warn('[mpgd/adapter-ait] AIT sandbox persistent storage is unavailable; subsequent saves are memory-only and will not survive reloads.');
|
|
199
|
+
persistentStorage = undefined;
|
|
200
|
+
}
|
|
201
|
+
if (persistent.found) {
|
|
202
|
+
// Keep the hydrated cache detached from the returned parsed value. Callers may mutate
|
|
203
|
+
// their result, while a later memory load must still model serialized storage.
|
|
204
|
+
storage.set(payload.key, cloneJsonValue(persistent.value));
|
|
205
|
+
return ok(input, {
|
|
206
|
+
__mpgdBridgeProtocol: bridgeStorageLoadProtocol,
|
|
207
|
+
found: true,
|
|
208
|
+
value: persistent.value,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return ok(input, {
|
|
212
|
+
__mpgdBridgeProtocol: bridgeStorageLoadProtocol,
|
|
213
|
+
found: false,
|
|
214
|
+
});
|
|
177
215
|
}
|
|
178
216
|
case 'storage.save': {
|
|
179
217
|
const payload = input.payload;
|
|
180
218
|
if (payload.key !== undefined) {
|
|
181
|
-
|
|
219
|
+
let serialized;
|
|
220
|
+
let value;
|
|
221
|
+
try {
|
|
222
|
+
serialized = serializeJsonValue(payload.value);
|
|
223
|
+
value = JSON.parse(serialized);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return createSandboxBridgeError(input, 'STORAGE_SERIALIZATION_FAILED', 'AIT sandbox storage values must be JSON-serializable.');
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
savePersistentSandboxValue(persistentStorage, `${storageKeyPrefix}${payload.key}`, serialized);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
// The helper reports the original failure and the loss of reload durability. The
|
|
233
|
+
// sandbox still honors its memory fallback so local gameplay can continue.
|
|
234
|
+
persistentStorage = undefined;
|
|
235
|
+
}
|
|
236
|
+
storage.set(payload.key, value);
|
|
182
237
|
}
|
|
183
238
|
return ok(input, {});
|
|
184
239
|
}
|
|
185
240
|
default:
|
|
186
|
-
return {
|
|
187
|
-
id: input.id,
|
|
188
|
-
ok: false,
|
|
189
|
-
error: {
|
|
190
|
-
code: 'UNSUPPORTED_METHOD',
|
|
191
|
-
message: `Unsupported AIT sandbox method: ${input.method}`,
|
|
192
|
-
retryable: false,
|
|
193
|
-
},
|
|
194
|
-
};
|
|
241
|
+
return createSandboxBridgeError(input, 'UNSUPPORTED_METHOD', `Unsupported AIT sandbox method: ${input.method}`);
|
|
195
242
|
}
|
|
196
243
|
},
|
|
197
244
|
};
|
|
198
245
|
}
|
|
246
|
+
function resolveAitSandboxBrowserStorage() {
|
|
247
|
+
try {
|
|
248
|
+
return globalThis.localStorage;
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
reportAitSandboxStorageResolutionFailure(error);
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function loadPersistentSandboxValue(storage, key) {
|
|
256
|
+
if (storage === undefined) {
|
|
257
|
+
return { found: false, storageAvailable: false };
|
|
258
|
+
}
|
|
259
|
+
let serialized;
|
|
260
|
+
try {
|
|
261
|
+
serialized = storage.getItem(key);
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
return { found: false, storageAvailable: false };
|
|
265
|
+
}
|
|
266
|
+
if (serialized === null) {
|
|
267
|
+
return { found: false, storageAvailable: true };
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
return {
|
|
271
|
+
found: true,
|
|
272
|
+
storageAvailable: true,
|
|
273
|
+
value: JSON.parse(serialized),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
console.warn(`[mpgd/adapter-ait] Removing corrupt sandbox storage value for key "${key}".`, error);
|
|
278
|
+
if (storage.removeItem === undefined) {
|
|
279
|
+
console.warn('[mpgd/adapter-ait] Corrupt sandbox storage cannot be removed; disabling persistent storage for this bridge.');
|
|
280
|
+
return { found: false, storageAvailable: false };
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
storage.removeItem(key);
|
|
284
|
+
}
|
|
285
|
+
catch (cleanupError) {
|
|
286
|
+
console.warn('[mpgd/adapter-ait] Corrupt sandbox storage cleanup failed; disabling persistent storage for this bridge.', cleanupError);
|
|
287
|
+
return { found: false, storageAvailable: false };
|
|
288
|
+
}
|
|
289
|
+
return { found: false, storageAvailable: true };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function savePersistentSandboxValue(storage, key, serialized) {
|
|
293
|
+
if (storage === undefined) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
storage.setItem(key, serialized);
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.warn('[mpgd/adapter-ait] AIT sandbox persistent storage save failed; subsequent saves are memory-only and will not survive reloads.', error);
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function reportAitSandboxStorageResolutionFailure(error) {
|
|
305
|
+
}
|
|
199
306
|
function cloneJsonValue(input) {
|
|
307
|
+
return JSON.parse(serializeJsonValue(input));
|
|
308
|
+
}
|
|
309
|
+
function serializeJsonValue(input) {
|
|
200
310
|
const serialized = JSON.stringify(input);
|
|
201
311
|
if (serialized === undefined) {
|
|
202
312
|
throw new Error('AIT sandbox storage values must be JSON-serializable.');
|
|
203
313
|
}
|
|
204
|
-
return
|
|
314
|
+
return serialized;
|
|
205
315
|
}
|
|
206
316
|
function ok(input, data) {
|
|
207
317
|
return {
|
|
@@ -210,3 +320,10 @@ function ok(input, data) {
|
|
|
210
320
|
data,
|
|
211
321
|
};
|
|
212
322
|
}
|
|
323
|
+
function createSandboxBridgeError(input, code, message, retryable = false) {
|
|
324
|
+
return {
|
|
325
|
+
id: input.id,
|
|
326
|
+
ok: false,
|
|
327
|
+
error: { code, message, retryable },
|
|
328
|
+
};
|
|
329
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpgd/adapter-ait",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Apps in Toss WebView platform adapter for mpgd games.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"dist"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@mpgd/
|
|
51
|
-
"@mpgd/
|
|
50
|
+
"@mpgd/bridge": "0.6.1",
|
|
51
|
+
"@mpgd/platform": "0.7.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@apps-in-toss/web-framework": ">=2.10.4 <3"
|