@indiegems/gem-web-sdk 7.6.0 → 7.8.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 browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.6.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.8.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -6194,6 +6194,25 @@ rather than cut it, say. The arcade shows its mute button for your game
6194
6194
  either way where it shows one, so `false` is a promise that your handler goes quiet on
6195
6195
  `muted: true`, and the release checklist holds you to it.
6196
6196
 
6197
+ ## GemOptions.selectableText
6198
+
6199
+ [GemOptions.selectableText](https://gemarcade.com/developer/api/game#gemoptions-selectabletext)
6200
+
6201
+ ```ts
6202
+ readonly selectableText?: boolean
6203
+ ```
6204
+
6205
+ Leave your page's text selectable. Default `false`: the SDK stops
6206
+ accidental text selection, the long-press copy menu and the tap highlight
6207
+ across your document, because in a game every one of them is a press the
6208
+ player did not mean.
6209
+
6210
+ Your own CSS always wins — the SDK's rule has zero specificity — so to make
6211
+ one element copyable, give it `user-select: text` (and
6212
+ `-webkit-user-select: text`). Inputs, text areas and editable content stay
6213
+ typeable and selectable without anything from you. Set this to `true` only
6214
+ if your game is mostly text a player should be able to copy.
6215
+
6197
6216
  ## GemOptions.onPause
6198
6217
 
6199
6218
  [GemOptions.onPause](https://gemarcade.com/developer/api/game#gemoptions-onpause)
@@ -7991,6 +8010,43 @@ What [LeaderboardsApi.mine](https://gemarcade.com/developer/api/game#leaderboard
7991
8010
  Separate from [GetLeaderboardOptions](https://gemarcade.com/developer/api/game#getleaderboardoptions) because `limit` has no meaning
7992
8011
  there — the global board arrives whole.
7993
8012
 
8013
+ ## LeaderboardPeriod
8014
+
8015
+ [LeaderboardPeriod](https://gemarcade.com/developer/api/game#leaderboardperiod)
8016
+
8017
+ ```ts
8018
+ interface LeaderboardPeriod
8019
+ ```
8020
+
8021
+ Which period a `per_period` board's result is for.
8022
+
8023
+ A board whose config sets `per_period: true` exists once per period of the
8024
+ challenge its run type names: one board for each day of a daily challenge,
8025
+ each week of a weekly one. Present on a result exactly when the board is one
8026
+ of those; absent — not `null` — on an ordinary board.
8027
+
8028
+ ⚠️ **Players on the same date share a board, whatever their time zone.** On
8029
+ a challenge that follows each player's own time zone (the default), a date
8030
+ begins for each player at their own midnight, so one day's board is open for
8031
+ about 50 hours worldwide and the standings can still change after YOUR day
8032
+ has ended. [LeaderboardPeriod.final](https://gemarcade.com/developer/api/game#leaderboardperiod-final) says when they no longer can.
8033
+
8034
+ ## PeriodOptions
8035
+
8036
+ [PeriodOptions](https://gemarcade.com/developer/api/game#periodoptions)
8037
+
8038
+ ```ts
8039
+ interface PeriodOptions
8040
+ ```
8041
+
8042
+ Which period of a `per_period` board to read. Shared by every read.
8043
+
8044
+ Name at most one of [PeriodOptions.periodsBack](https://gemarcade.com/developer/api/game#periodoptions-periodsback) and
8045
+ [PeriodOptions.period](https://gemarcade.com/developer/api/game#periodoptions-period); with neither, the read answers for the current
8046
+ period. On a board that is not `per_period` both are refused with `invalid`
8047
+ rather than ignored — asking an all-time board for yesterday and being
8048
+ handed all time would be a different answer with nothing saying so.
8049
+
7994
8050
  ## ShowcaseApi
7995
8051
 
7996
8052
  [ShowcaseApi](https://gemarcade.com/developer/api/game#showcaseapi)
@@ -11038,6 +11094,101 @@ A unit test that constructs the SDK in a simulated DOM has to give its
11038
11094
  window a parent of its own, because a simulated top-level window is exactly
11039
11095
  what this refuses.
11040
11096
 
11097
+ ## LeaderboardPeriod.id
11098
+
11099
+ [LeaderboardPeriod.id](https://gemarcade.com/developer/api/game#leaderboardperiod-id)
11100
+
11101
+ ```ts
11102
+ readonly id: string
11103
+ ```
11104
+
11105
+ The period this board is for: the date for a daily challenge, the Monday
11106
+ for a weekly, the 1st for a monthly (`2026-10-02`), or a cron challenge's
11107
+ start as `2026-10-02T06:00:00Z`.
11108
+
11109
+ **This is the board's identity.** Pass it back as
11110
+ [GetLeaderboardOptions.period](https://gemarcade.com/developer/api/game#getleaderboardoptions-period) to read this same board again later —
11111
+ from a shared link, or a history screen — and key any cache on it.
11112
+
11113
+ ## LeaderboardPeriod.localDate
11114
+
11115
+ [LeaderboardPeriod.localDate](https://gemarcade.com/developer/api/game#leaderboardperiod-localdate)
11116
+
11117
+ ```ts
11118
+ readonly localDate?: string
11119
+ ```
11120
+
11121
+ The period's calendar date, `YYYY-MM-DD` — the same value
11122
+ `gem.challenges.list()` gives as `periodLocalDate` for the challenge, so
11123
+ the two can be compared. Absent for a cron challenge, which has no date.
11124
+
11125
+ ## LeaderboardPeriod.startAt
11126
+
11127
+ [LeaderboardPeriod.startAt](https://gemarcade.com/developer/api/game#leaderboardperiod-startat)
11128
+
11129
+ ```ts
11130
+ readonly startAt?: number
11131
+ ```
11132
+
11133
+ When this period began for the player the read answered for, in Unix
11134
+ seconds. Absent when the read answered for no player — a server or a
11135
+ function that named none — on a challenge that follows each player's own
11136
+ time zone.
11137
+
11138
+ ## LeaderboardPeriod.endsAt
11139
+
11140
+ [LeaderboardPeriod.endsAt](https://gemarcade.com/developer/api/game#leaderboardperiod-endsat)
11141
+
11142
+ ```ts
11143
+ readonly endsAt?: number
11144
+ ```
11145
+
11146
+ When this period ends for that player, in Unix seconds: their own runs stop
11147
+ counting towards this board then.
11148
+
11149
+ ⚠️ **Not when the board stops changing.** Players in later time zones are
11150
+ still on this date after it; see [LeaderboardPeriod.closesAt](https://gemarcade.com/developer/api/game#leaderboardperiod-closesat) and
11151
+ [LeaderboardPeriod.final](https://gemarcade.com/developer/api/game#leaderboardperiod-final). Absent exactly when
11152
+ [LeaderboardPeriod.startAt](https://gemarcade.com/developer/api/game#leaderboardperiod-startat) is.
11153
+
11154
+ ## LeaderboardPeriod.opensAt
11155
+
11156
+ [LeaderboardPeriod.opensAt](https://gemarcade.com/developer/api/game#leaderboardperiod-opensat)
11157
+
11158
+ ```ts
11159
+ readonly opensAt: number
11160
+ ```
11161
+
11162
+ When this board started accepting runs from anyone, in Unix seconds. `0`
11163
+ when the platform sent something this SDK could not read.
11164
+
11165
+ ## LeaderboardPeriod.closesAt
11166
+
11167
+ [LeaderboardPeriod.closesAt](https://gemarcade.com/developer/api/game#leaderboardperiod-closesat)
11168
+
11169
+ ```ts
11170
+ readonly closesAt: number
11171
+ ```
11172
+
11173
+ When this board stops accepting runs from anyone, in Unix seconds. `0`
11174
+ when the platform sent something this SDK could not read.
11175
+
11176
+ ## LeaderboardPeriod.final
11177
+
11178
+ [LeaderboardPeriod.final](https://gemarcade.com/developer/api/game#leaderboardperiod-final)
11179
+
11180
+ ```ts
11181
+ readonly final: boolean
11182
+ ```
11183
+
11184
+ `true` once no run can still arrive, so the standings will not change
11185
+ again — stop polling, and say "final" if your screen says anything.
11186
+
11187
+ While it is `false` the standings may change, **including after the
11188
+ viewer's own period has ended**: a "you finished 3rd today" shown at the
11189
+ player's midnight can be wrong an hour later. Say "so far" until this is
11190
+ `true`.
11191
+
11041
11192
  ## LeaderboardEntry.playerId
11042
11193
 
11043
11194
  [LeaderboardEntry.playerId](https://gemarcade.com/developer/api/game#leaderboardentry-playerid)
@@ -11135,6 +11286,12 @@ readonly occurredAt: number
11135
11286
 
11136
11287
  When the ranked run occurred — Unix seconds.
11137
11288
 
11289
+ ⚠️ **`0` on a `per_period` board whose challenge follows each player's own
11290
+ time zone** (the default `local` boundary). The platform serves no time
11291
+ there: beside the board's date, the time of a run would show which time
11292
+ zones its player could be in. Render no time for `0` rather than 1970.
11293
+ Ranks are unaffected — ties are still broken by the real time.
11294
+
11138
11295
  ## LeaderboardEntry.entityId
11139
11296
 
11140
11297
  [LeaderboardEntry.entityId](https://gemarcade.com/developer/api/game#leaderboardentry-entityid)
@@ -11278,6 +11435,20 @@ interval: polling faster re-downloads the same rendering.
11278
11435
  Absent if the server did not state one. Absent means *unknown*, not
11279
11436
  "refreshes constantly" — do not substitute `0` and poll on it.
11280
11437
 
11438
+ ## Leaderboard.period
11439
+
11440
+ [Leaderboard.period](https://gemarcade.com/developer/api/game#leaderboard-period)
11441
+
11442
+ ```ts
11443
+ readonly period?: LeaderboardPeriod
11444
+ ```
11445
+
11446
+ Which period this result is for, on a board whose config sets
11447
+ `per_period`. Absent on an ordinary board, which ranks every run.
11448
+
11449
+ Once `period.final` is `true` the board no longer changes and need not be
11450
+ polled.
11451
+
11281
11452
  ## RankedRow.rank
11282
11453
 
11283
11454
  [RankedRow.rank](https://gemarcade.com/developer/api/game#rankedrow-rank)
@@ -11296,7 +11467,9 @@ readonly rank: number
11296
11467
  readonly occurredAt: number
11297
11468
  ```
11298
11469
 
11299
- When the ranked run occurred — Unix seconds.
11470
+ When the ranked run occurred — Unix seconds. `0` on a `per_period` board
11471
+ whose challenge follows each player's own time zone, where the platform
11472
+ serves no time; render nothing for it.
11300
11473
 
11301
11474
  ## RankedRow.stats
11302
11475
 
@@ -11326,7 +11499,9 @@ The run's freeform properties.
11326
11499
  readonly occurredAt: number
11327
11500
  ```
11328
11501
 
11329
- When the ranked run occurred — Unix seconds.
11502
+ When the ranked run occurred — Unix seconds. `0` on a `per_period` board
11503
+ whose challenge follows each player's own time zone, where the platform
11504
+ serves no time; render nothing for it.
11330
11505
 
11331
11506
  ## EntityLeaderboardEntry.properties
11332
11507
 
@@ -11488,6 +11663,107 @@ readonly generatedAt: number
11488
11663
 
11489
11664
  When this rendering was computed — Unix seconds.
11490
11665
 
11666
+ ## EntityLeaderboard.period
11667
+
11668
+ [EntityLeaderboard.period](https://gemarcade.com/developer/api/game#entityleaderboard-period)
11669
+
11670
+ ```ts
11671
+ readonly period?: LeaderboardPeriod
11672
+ ```
11673
+
11674
+ Which period these runs are from, on a board whose config sets
11675
+ `per_period`: `entries`, `personalBest` and `totalRuns`
11676
+ are then that ONE period's, not the entity's whole history. Absent on an
11677
+ ordinary board.
11678
+
11679
+ ## PeriodOptions.periodsBack
11680
+
11681
+ [PeriodOptions.periodsBack](https://gemarcade.com/developer/api/game#periodoptions-periodsback)
11682
+
11683
+ ```ts
11684
+ readonly periodsBack?: number
11685
+ ```
11686
+
11687
+ How many periods back to read. `0` — the default — is the current period;
11688
+ `1` is yesterday's board for a daily challenge, last week's for a weekly.
11689
+
11690
+ An integer from 0 to 400. Anything else is a `TypeError` before the
11691
+ request is made.
11692
+
11693
+ ## PeriodOptions.period
11694
+
11695
+ [PeriodOptions.period](https://gemarcade.com/developer/api/game#periodoptions-period)
11696
+
11697
+ ```ts
11698
+ readonly period?: string
11699
+ ```
11700
+
11701
+ The period to read, as an earlier result's [LeaderboardPeriod.id](https://gemarcade.com/developer/api/game#leaderboardperiod-id) —
11702
+ for a board reached from a shared link or a history screen. At most 400
11703
+ periods back.
11704
+
11705
+ ⚠️ A period that has not begun for the player is refused, even when it has
11706
+ already begun for players in time zones ahead of theirs.
11707
+
11708
+ ## PeriodOptions.playerId
11709
+
11710
+ [PeriodOptions.playerId](https://gemarcade.com/developer/api/game#periodoptions-playerid)
11711
+
11712
+ ```ts
11713
+ readonly playerId?: string
11714
+ ```
11715
+
11716
+ For a serverless function or a dedicated server: the player whose period
11717
+ to answer for. Their credential names no player, so without this a
11718
+ `per_period` board on each player's own time zone is answered in UTC,
11719
+ which is not that player's day.
11720
+
11721
+ Ignored in the browser, where the read is always for the signed-in player.
11722
+
11723
+ ## EntityLeaderboardOptions.periodsBack
11724
+
11725
+ [EntityLeaderboardOptions.periodsBack](https://gemarcade.com/developer/api/game#entityleaderboardoptions-periodsback)
11726
+
11727
+ ```ts
11728
+ readonly periodsBack?: number
11729
+ ```
11730
+
11731
+ How many periods back to read. `0` — the default — is the current period;
11732
+ `1` is yesterday's board for a daily challenge, last week's for a weekly.
11733
+
11734
+ An integer from 0 to 400. Anything else is a `TypeError` before the
11735
+ request is made.
11736
+
11737
+ ## EntityLeaderboardOptions.period
11738
+
11739
+ [EntityLeaderboardOptions.period](https://gemarcade.com/developer/api/game#entityleaderboardoptions-period)
11740
+
11741
+ ```ts
11742
+ readonly period?: string
11743
+ ```
11744
+
11745
+ The period to read, as an earlier result's [LeaderboardPeriod.id](https://gemarcade.com/developer/api/game#leaderboardperiod-id) —
11746
+ for a board reached from a shared link or a history screen. At most 400
11747
+ periods back.
11748
+
11749
+ ⚠️ A period that has not begun for the player is refused, even when it has
11750
+ already begun for players in time zones ahead of theirs.
11751
+
11752
+ ## EntityLeaderboardOptions.playerId
11753
+
11754
+ [EntityLeaderboardOptions.playerId](https://gemarcade.com/developer/api/game#entityleaderboardoptions-playerid)
11755
+
11756
+ ```ts
11757
+ readonly playerId?: string
11758
+ ```
11759
+
11760
+ For a serverless function or a dedicated server: the player whose period
11761
+ to answer for. Their credential names no player, so without this a
11762
+ `per_period` board on each player's own time zone is answered in UTC,
11763
+ which is not that player's day.
11764
+
11765
+ Ignored in the browser, where the read is always for the signed-in player.
11766
+
11491
11767
  ## EntityLeaderboardOptions.bucket1
11492
11768
 
11493
11769
  [EntityLeaderboardOptions.bucket1](https://gemarcade.com/developer/api/game#entityleaderboardoptions-bucket1)
@@ -11534,6 +11810,50 @@ readonly signal?: AbortSignal
11534
11810
 
11535
11811
  Abort the read.
11536
11812
 
11813
+ ## GetLeaderboardOptions.periodsBack
11814
+
11815
+ [GetLeaderboardOptions.periodsBack](https://gemarcade.com/developer/api/game#getleaderboardoptions-periodsback)
11816
+
11817
+ ```ts
11818
+ readonly periodsBack?: number
11819
+ ```
11820
+
11821
+ How many periods back to read. `0` — the default — is the current period;
11822
+ `1` is yesterday's board for a daily challenge, last week's for a weekly.
11823
+
11824
+ An integer from 0 to 400. Anything else is a `TypeError` before the
11825
+ request is made.
11826
+
11827
+ ## GetLeaderboardOptions.period
11828
+
11829
+ [GetLeaderboardOptions.period](https://gemarcade.com/developer/api/game#getleaderboardoptions-period)
11830
+
11831
+ ```ts
11832
+ readonly period?: string
11833
+ ```
11834
+
11835
+ The period to read, as an earlier result's [LeaderboardPeriod.id](https://gemarcade.com/developer/api/game#leaderboardperiod-id) —
11836
+ for a board reached from a shared link or a history screen. At most 400
11837
+ periods back.
11838
+
11839
+ ⚠️ A period that has not begun for the player is refused, even when it has
11840
+ already begun for players in time zones ahead of theirs.
11841
+
11842
+ ## GetLeaderboardOptions.playerId
11843
+
11844
+ [GetLeaderboardOptions.playerId](https://gemarcade.com/developer/api/game#getleaderboardoptions-playerid)
11845
+
11846
+ ```ts
11847
+ readonly playerId?: string
11848
+ ```
11849
+
11850
+ For a serverless function or a dedicated server: the player whose period
11851
+ to answer for. Their credential names no player, so without this a
11852
+ `per_period` board on each player's own time zone is answered in UTC,
11853
+ which is not that player's day.
11854
+
11855
+ Ignored in the browser, where the read is always for the signed-in player.
11856
+
11537
11857
  ## GetLeaderboardOptions.bucket1
11538
11858
 
11539
11859
  [GetLeaderboardOptions.bucket1](https://gemarcade.com/developer/api/game#getleaderboardoptions-bucket1)
@@ -11581,14 +11901,28 @@ A bucketed board (config `bucket_by`) needs exactly its bucket values —
11581
11901
  faster than the result's `updateFrequencySeconds`; the server regenerates
11582
11902
  at that cadence and faster polling re-reads the same rendering.
11583
11903
 
11904
+ A `per_period` board answers for one period — the current one by default:
11905
+
11906
+ ```js
11907
+ const today = await gem.leaderboards.get('daily');
11908
+ const yesterday = await gem.leaderboards.get('daily', { periodsBack: 1 });
11909
+ label(today.period.final ? 'Final standings' : 'Standings so far');
11910
+ ```
11911
+
11584
11912
  | Parameter | Type | Description |
11585
11913
  | --- | --- | --- |
11586
11914
  | `leaderboardType` | `string` | The board's id in your game config. |
11587
11915
  | `options` | `GetLeaderboardOptions` | |
11588
11916
 
11589
- **Throws.** `not_found` when no board with this id is in the channel's active
11917
+ **Throws.** `TypeError` when `periodsBack` is not an integer from 0 to 400,
11918
+ `period` is not a period id, or both are passed — refused before the
11919
+ request.
11920
+
11921
+ `not_found` when no board with this id is in the channel's active
11590
11922
  config, `invalid` when bucket values do not match the board's
11591
- `bucket_by`.
11923
+ `bucket_by`, when a period is asked of a board that is not `per_period`
11924
+ (`code` `invalid_period`), or when the period has not begun for the
11925
+ player (`code` `period_not_begun`).
11592
11926
 
11593
11927
  ## LeaderboardsApi.friends
11594
11928
 
@@ -11619,16 +11953,20 @@ for (const row of board.entries) {
11619
11953
  }
11620
11954
  ```
11621
11955
 
11956
+ On a `per_period` board this takes the same `periodsBack` and `period` as
11957
+ `get`. A friend in another time zone who is on the same date is on
11958
+ the same board.
11959
+
11622
11960
  | Parameter | Type |
11623
11961
  | --- | --- |
11624
11962
  | `leaderboardType` | `string` |
11625
11963
  | `options` | `GetLeaderboardOptions` |
11626
11964
 
11627
11965
  **Throws.** `not_found` when no board with this id is in the channel's active
11628
- config, `invalid` when bucket values do not match the board's
11629
- `bucket_by`, and `forbidden` in a context with no player — the friend
11630
- view is a player surface, and a game server has no friends. (The global
11631
- `get` declares no such refusal: it needs no viewer.)
11966
+ config, `invalid` when bucket values or a period do not match the board
11967
+ (as on `get`), and `forbidden` in a context with no player — the
11968
+ friend view is a player surface, and a game server has no friends. (The
11969
+ global `get` declares no such refusal: it needs no viewer.)
11632
11970
 
11633
11971
  ## LeaderboardsApi.mine
11634
11972
 
@@ -11664,6 +12002,11 @@ a `200` with no entries, not an error. If it is *always* empty, see
11664
12002
  [LeaderboardsApi](https://gemarcade.com/developer/api/game#leaderboardsapi) on where runs come from: a browser cannot submit
11665
12003
  one.
11666
12004
 
12005
+ On a `per_period` board the runs, the personal best and the total are ONE
12006
+ period's — the current one unless `periodsBack` or `period` names another
12007
+ — so `personalBest` is "your best today", and an empty result at the start
12008
+ of a day is the ordinary state.
12009
+
11667
12010
  | Parameter | Type |
11668
12011
  | --- | --- |
11669
12012
  | `leaderboardType` | `string` |
@@ -14674,6 +15017,24 @@ Arcade measured for them, and a host moves it by naming another cluster on
14674
15017
  [RoomManager.startMatch](https://gemarcade.com/developer/api/game#roommanager-startmatch). Absent on a room created without one, such
14675
15018
  as by an older client or outside the Arcade.
14676
15019
 
15020
+ ## Room.selfHosted
15021
+
15022
+ [Room.selfHosted](https://gemarcade.com/developer/api/game#room-selfhosted)
15023
+
15024
+ ```ts
15025
+ readonly selfHosted: boolean
15026
+ ```
15027
+
15028
+ Whether this room's matches are served from the developer's own machine
15029
+ rather than by the platform.
15030
+
15031
+ True only inside a development tool that runs your game's server locally
15032
+ (the Gem Editor's play surface). The SDK asks for such a room on your
15033
+ behalf — there is no option for a game to set — and the platform keeps it
15034
+ to its host: no other player can join it, quick-join never matches into
15035
+ it, and the server browser never lists it. False on every room a player in
15036
+ the Arcade is in.
15037
+
14677
15038
  ## Room.matchId
14678
15039
 
14679
15040
  [Room.matchId](https://gemarcade.com/developer/api/game#room-matchid)
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v7.6.0. Every symbol below links to its page on the Gem Arcade developer site.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v7.8.0. Every symbol below links to its page on the Gem Arcade developer site.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6