@indiegems/gem-web-sdk 16.1.0 → 16.3.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.
@@ -1,6 +1,6 @@
1
1
  # The function surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/function` v16.1.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/function` v16.3.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/function` exports exactly the symbols on this page and nothing else.
6
6
 
@@ -3200,9 +3200,11 @@ readonly etag: string
3200
3200
 
3201
3201
  This save's version, which changes whenever the save does.
3202
3202
 
3203
- NOT something to pass back on a write — a write pins the version it is
3204
- replacing on its own. This is how a game holding a copy tells whether the
3205
- stored save is still the one it has.
3203
+ NOT something to pass back on a write — the SDK remembers the version of
3204
+ each slot you last loaded or wrote and sends it for you, so a write that
3205
+ would replace a save you never saw is refused as `save_conflict`. This is
3206
+ how a game holding a copy tells whether the stored save is still the one
3207
+ it has.
3206
3208
 
3207
3209
  <a id="saverecord-metadata"></a>
3208
3210
 
@@ -3295,7 +3297,7 @@ has already agreed to the write. Re-read before assuming what is stored.
3295
3297
  ## GemSaveError.reason
3296
3298
 
3297
3299
  ```ts
3298
- readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed"
3300
+ readonly reason: "upload_failed" | "download_failed" | "save_timeout" | "save_malformed" | "save_conflict" | "load_failed"
3299
3301
  ```
3300
3302
 
3301
3303
  Which part failed.
@@ -3305,15 +3307,31 @@ Which part failed.
3305
3307
  - `save_timeout` — a hop did not finish in the time the call allows.
3306
3308
  - `save_malformed` — the answer, or the stored payload, was not what it
3307
3309
  claims to be.
3310
+ - `save_conflict` — a write was refused because the stored save changed
3311
+ since this game last loaded or wrote it: another device or tab saved
3312
+ in between. Nothing was written.
3313
+ - `load_failed` — a write was refused before anything was sent, because
3314
+ the last load of this slot failed, so what the write would replace is
3315
+ unknown — it could be the player's real progress.
3308
3316
 
3309
3317
  `save_timeout`, and a one-off `upload_failed` or `download_failed`, are
3310
3318
  worth one retry. `save_malformed` is not: the same bytes will fail the
3311
3319
  same way.
3312
3320
 
3321
+ Neither is `save_conflict` or `load_failed`: resending the same write
3322
+ fails the same way. Load the slot again and decide what to write from
3323
+ what is stored — merge, or ask the player. Pass `overwrite: true` only to
3324
+ replace whatever is stored on purpose.
3325
+
3313
3326
  An `upload_failed` that repeats on EVERY save, for every player, is not
3314
3327
  transient either — it is a platform-side misconfiguration, and retrying
3315
3328
  is a loop rather than a recovery. See the saves guide.
3316
3329
 
3330
+ A RATE LIMIT IS NOT ONE OF THESE. Refused for the rate on any leg — the
3331
+ platform, the upload, the download — a save or load rejects as
3332
+ `GemApiError` reason `rate_limited`, with `retryAfterSeconds` when a wait
3333
+ was named.
3334
+
3317
3335
  <a id="putsaveoptions"></a>
3318
3336
 
3319
3337
  ## PutSaveOptions
@@ -3354,6 +3372,10 @@ Cancel the write.
3354
3372
  A save is several hops, so a cancelled write can land after the platform
3355
3373
  has already agreed to it. Re-read rather than assuming nothing was stored.
3356
3374
 
3375
+ A write that replaced earlier ones still waiting on its slot carries them,
3376
+ so cancelling it before it goes out cancels them too. Cancelling a write
3377
+ that a later one replaced rejects only this call; the later write goes on.
3378
+
3357
3379
  <a id="putsaveoptions-timeoutms"></a>
3358
3380
 
3359
3381
  ## PutSaveOptions.timeoutMs
@@ -3376,6 +3398,68 @@ to do something about it.
3376
3398
  It does not make a save faster. Three round trips plus the payload is what
3377
3399
  a save costs; this only decides when to stop waiting.
3378
3400
 
3401
+ It counts from the call, so a write waiting for the one before it on the
3402
+ same slot spends it waiting. A rate limit whose wait it will not cover
3403
+ rejects at once as `GemApiError` reason `rate_limited`, not as
3404
+ `save_timeout`.
3405
+
3406
+ It stays this call's when a later write replaces this one: running out
3407
+ rejects only this call, and the later write goes on. The write that is
3408
+ sent runs on the newest call's `timeoutMs`, and running out of that rejects
3409
+ every call it carries.
3410
+
3411
+ <a id="putsaveoptions-teardown"></a>
3412
+
3413
+ ## PutSaveOptions.teardown
3414
+
3415
+ ```ts
3416
+ readonly teardown?: boolean
3417
+ ```
3418
+
3419
+ This is the last write before the page goes away: send it without waiting
3420
+ for the spacing between writes to one slot.
3421
+
3422
+ Writes to one slot go out a few seconds apart, and a write made sooner
3423
+ waits its turn. Set this on the write you make from
3424
+ `GemTerminationNotice` or `pagehide`, with a `timeoutMs` inside the
3425
+ time you have.
3426
+
3427
+ IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
3428
+ still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
3429
+ write rejects at once as `rate_limited`, and nothing is sent. Not for
3430
+ ordinary saves — the spacing is what keeps a save loop from spending the
3431
+ rate limit.
3432
+
3433
+ A later write that replaces this one while it waits keeps it: the write
3434
+ that goes out skips the spacing when any call it carries set `teardown`.
3435
+ Not across a player change: a call replaced after the signed-in player
3436
+ changed is refused as `save_conflict`, and its `teardown` goes with it.
3437
+
3438
+ <a id="putsaveoptions-overwrite"></a>
3439
+
3440
+ ## PutSaveOptions.overwrite
3441
+
3442
+ ```ts
3443
+ readonly overwrite?: boolean
3444
+ ```
3445
+
3446
+ Write even if it replaces a save this game has not loaded.
3447
+
3448
+ Without it, a write to a slot whose last load FAILED is refused as
3449
+ `load_failed`, and a write is refused as `save_conflict` when the stored
3450
+ save changed since you last loaded or wrote it. Both refusals protect the
3451
+ player's real progress from a game that started from defaults.
3452
+
3453
+ Set it only when replacing whatever is stored is what you mean — a "new
3454
+ game" the player confirmed, or the player choosing this device's progress
3455
+ after a conflict. Never set it to get past a failed load.
3456
+
3457
+ A later write that replaces this one while it waits keeps it: the write
3458
+ that goes out overwrites when any call it carries set `overwrite`. A call
3459
+ that gives up first (its `signal` or `timeoutMs`) takes it back, and so
3460
+ does one replaced after the signed-in player changed: it is refused as
3461
+ `save_conflict`, so one player's "new game" never overwrites the next's.
3462
+
3379
3463
  <a id="putbytesoptions"></a>
3380
3464
 
3381
3465
  ## PutBytesOptions
@@ -3419,6 +3503,10 @@ Cancel the write.
3419
3503
  A save is several hops, so a cancelled write can land after the platform
3420
3504
  has already agreed to it. Re-read rather than assuming nothing was stored.
3421
3505
 
3506
+ A write that replaced earlier ones still waiting on its slot carries them,
3507
+ so cancelling it before it goes out cancels them too. Cancelling a write
3508
+ that a later one replaced rejects only this call; the later write goes on.
3509
+
3422
3510
  <a id="putbytesoptions-timeoutms"></a>
3423
3511
 
3424
3512
  ## PutBytesOptions.timeoutMs
@@ -3441,6 +3529,68 @@ to do something about it.
3441
3529
  It does not make a save faster. Three round trips plus the payload is what
3442
3530
  a save costs; this only decides when to stop waiting.
3443
3531
 
3532
+ It counts from the call, so a write waiting for the one before it on the
3533
+ same slot spends it waiting. A rate limit whose wait it will not cover
3534
+ rejects at once as `GemApiError` reason `rate_limited`, not as
3535
+ `save_timeout`.
3536
+
3537
+ It stays this call's when a later write replaces this one: running out
3538
+ rejects only this call, and the later write goes on. The write that is
3539
+ sent runs on the newest call's `timeoutMs`, and running out of that rejects
3540
+ every call it carries.
3541
+
3542
+ <a id="putbytesoptions-teardown"></a>
3543
+
3544
+ ## PutBytesOptions.teardown
3545
+
3546
+ ```ts
3547
+ readonly teardown?: boolean
3548
+ ```
3549
+
3550
+ This is the last write before the page goes away: send it without waiting
3551
+ for the spacing between writes to one slot.
3552
+
3553
+ Writes to one slot go out a few seconds apart, and a write made sooner
3554
+ waits its turn. Set this on the write you make from
3555
+ `GemTerminationNotice` or `pagehide`, with a `timeoutMs` inside the
3556
+ time you have.
3557
+
3558
+ IT STILL WAITS FOR A WRITE ALREADY IN FLIGHT to the same slot, and it
3559
+ still honours a rate-limit hold: when the hold outlasts `timeoutMs` the
3560
+ write rejects at once as `rate_limited`, and nothing is sent. Not for
3561
+ ordinary saves — the spacing is what keeps a save loop from spending the
3562
+ rate limit.
3563
+
3564
+ A later write that replaces this one while it waits keeps it: the write
3565
+ that goes out skips the spacing when any call it carries set `teardown`.
3566
+ Not across a player change: a call replaced after the signed-in player
3567
+ changed is refused as `save_conflict`, and its `teardown` goes with it.
3568
+
3569
+ <a id="putbytesoptions-overwrite"></a>
3570
+
3571
+ ## PutBytesOptions.overwrite
3572
+
3573
+ ```ts
3574
+ readonly overwrite?: boolean
3575
+ ```
3576
+
3577
+ Write even if it replaces a save this game has not loaded.
3578
+
3579
+ Without it, a write to a slot whose last load FAILED is refused as
3580
+ `load_failed`, and a write is refused as `save_conflict` when the stored
3581
+ save changed since you last loaded or wrote it. Both refusals protect the
3582
+ player's real progress from a game that started from defaults.
3583
+
3584
+ Set it only when replacing whatever is stored is what you mean — a "new
3585
+ game" the player confirmed, or the player choosing this device's progress
3586
+ after a conflict. Never set it to get past a failed load.
3587
+
3588
+ A later write that replaces this one while it waits keeps it: the write
3589
+ that goes out overwrites when any call it carries set `overwrite`. A call
3590
+ that gives up first (its `signal` or `timeoutMs`) takes it back, and so
3591
+ does one replaced after the signed-in player changed: it is refused as
3592
+ `save_conflict`, so one player's "new game" never overwrites the next's.
3593
+
3444
3594
  <a id="putbytesoptions-contenttype"></a>
3445
3595
 
3446
3596
  ## PutBytesOptions.contentType
@@ -3483,6 +3633,20 @@ await gem.me.saves.put('slot1', { level: 7, checkpoint: 'bridge' });
3483
3633
  const state = await gem.me.saves.get('slot1');
3484
3634
  ```
3485
3635
 
3636
+ LOAD BEFORE YOU SAVE. Each write carries the version of the slot your last
3637
+ load or write found, so a write that would replace a save this game has not
3638
+ seen — another device's, or the player's real progress after a load that
3639
+ failed — is refused as `save_conflict` or `load_failed` rather than stored.
3640
+ After a failed load, play on without saving and load again later; pass
3641
+ `overwrite: true` only when the player chose to start over.
3642
+
3643
+ ONE WRITE PER SLOT AT A TIME. A write made while another to the same slot is
3644
+ in flight waits for it, and a later one replaces it: the newest value is the
3645
+ one sent, and every caller it replaced resolves with it, keeping its own
3646
+ `signal`, `timeoutMs`, `teardown` and `overwrite`. Writes to one slot
3647
+ go out a few seconds apart (`teardown: true` skips that), and after a
3648
+ `rate_limited` answer none goes out until the wait it named is over.
3649
+
3486
3650
  WHAT IS DELIBERATELY NOT HERE: no autosave timer, no save format, no
3487
3651
  migration. Those are your game's, and a platform that guessed at them would
3488
3652
  guess wrong.