@diffenderfer-games/hub 2.0.0-next.0 → 2.0.0-next.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -21
  3. package/README.md +191 -139
  4. package/dist/doctor/cli.mjs +49 -19
  5. package/dist/doctor/cli.mjs.map +1 -1
  6. package/dist/shared/client-version.gen.js +1 -1
  7. package/dist/shared/daily.js +1 -1
  8. package/dist/shared/globals.js +8 -3
  9. package/dist/shared/globals.js.map +1 -1
  10. package/dist/shared/index.d.ts +1 -1
  11. package/package.json +89 -89
  12. package/src/auto.ts +39 -39
  13. package/src/core/connection.ts +299 -299
  14. package/src/core/errors.ts +147 -147
  15. package/src/core/game-data.ts +38 -38
  16. package/src/core/hub-economy.ts +179 -179
  17. package/src/core/hub-progress.ts +205 -205
  18. package/src/core/hub.ts +131 -131
  19. package/src/core/menu-control.ts +61 -61
  20. package/src/core/offline/events.ts +50 -50
  21. package/src/core/offline/favorites.ts +21 -21
  22. package/src/core/offline/local-store.ts +261 -261
  23. package/src/core/offline/queue.ts +171 -171
  24. package/src/core/page.ts +74 -74
  25. package/src/core/rest/endpoint-types.ts +22 -22
  26. package/src/core/rest/rest-client.ts +152 -152
  27. package/src/core/storage/json-guards.ts +74 -74
  28. package/src/core/storage/key-value.ts +66 -66
  29. package/src/core/ticket.ts +43 -43
  30. package/src/core/types.ts +134 -134
  31. package/src/core/version/client-version.gen.ts +1 -1
  32. package/src/core/version/hub-version.ts +62 -62
  33. package/src/core/version/semver.ts +97 -97
  34. package/src/daily/daily-system.ts +161 -161
  35. package/src/daily/page-daily.ts +36 -36
  36. package/src/daily/types.ts +67 -67
  37. package/src/daily.ts +10 -10
  38. package/src/doctor/checks.ts +78 -76
  39. package/src/doctor/cli.ts +98 -106
  40. package/src/doctor/hub-version-fetch.ts +43 -0
  41. package/src/doctor/tsconfig.json +12 -12
  42. package/src/globals.ts +115 -110
  43. package/src/index.ts +50 -50
  44. package/src/input/device-state.ts +146 -146
  45. package/src/input/edges.ts +55 -55
  46. package/src/input/gamepad.ts +61 -61
  47. package/src/input/input-events.ts +32 -32
  48. package/src/input/input-registry.ts +164 -164
  49. package/src/input/input-system.ts +393 -393
  50. package/src/input/legacy-controls.ts +64 -64
  51. package/src/input/nav-state.ts +191 -191
  52. package/src/input/navigator.ts +171 -171
  53. package/src/input/on-screen-controls.ts +101 -101
  54. package/src/input/page-control.ts +43 -43
  55. package/src/input/page-input.ts +193 -193
  56. package/src/input/player-remaps.ts +77 -77
  57. package/src/input/source-values.ts +116 -116
  58. package/src/input/spatial.ts +47 -47
  59. package/src/input/types.ts +331 -331
  60. package/src/input/zero-config.ts +177 -177
  61. package/src/input.ts +22 -22
  62. package/src/mp.ts +10 -10
  63. package/src/overlay/controls-panel.ts +163 -163
  64. package/src/overlay/dom.ts +46 -46
  65. package/src/overlay/layout-clusters.ts +162 -162
  66. package/src/overlay/layout-geometry.ts +136 -136
  67. package/src/overlay/layout.ts +203 -203
  68. package/src/overlay/listener-scope.ts +23 -23
  69. package/src/overlay/on-screen-keyboard.ts +137 -137
  70. package/src/overlay/overlay.ts +208 -208
  71. package/src/overlay/styles.ts +9 -9
  72. package/src/overlay/virtual-controls.ts +262 -262
  73. package/src/race.ts +10 -10
  74. package/src/realtime/bridge.ts +121 -121
  75. package/src/realtime/cross-bundle.ts +29 -29
  76. package/src/realtime/fallback-notice.ts +48 -48
  77. package/src/realtime/hub-link.ts +65 -65
  78. package/src/realtime/latest-state.ts +33 -33
  79. package/src/realtime/multiplayer-forwarder.ts +28 -28
  80. package/src/realtime/multiplayer-types.ts +52 -52
  81. package/src/realtime/page-runtime.ts +60 -60
  82. package/src/realtime/race-forwarder.ts +59 -59
  83. package/src/realtime/race-types.ts +132 -132
  84. package/src/realtime/room-types.ts +125 -125
  85. package/src/realtime/rooms-forwarder.ts +79 -79
  86. package/src/realtime/runtime-api.ts +49 -49
  87. package/src/realtime/runtime-opener.ts +61 -61
  88. package/src/realtime/social-forwarder.ts +72 -72
  89. package/src/realtime/social-types.ts +78 -78
  90. package/src/realtime/types.ts +53 -53
  91. package/src/realtime/wire-types.ts +72 -72
  92. package/src/rooms.ts +10 -10
  93. package/src/social.ts +18 -18
  94. package/src/types.ts +13 -13
  95. package/src/uistack/page-stack.ts +45 -45
  96. package/src/uistack/play-suspension.ts +82 -82
  97. package/src/uistack/types.ts +76 -76
  98. package/src/uistack/ui-stack.ts +144 -144
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # @diffenderfer-games/hub
2
+
3
+ ## 2.0.0-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Follow-ups from the Bubble Pop pilot. `hub-doctor` gives up after `--timeout` ms (default 10 s) and fails with `hub unreachable at <url>` instead of hanging. A v1 vendored singleton adopted on the page is now recorded in `window.__DG__` as `{ version: 'v1' }`. The README covers exact pins for prereleases, sharing the page with the host's `/_hub/hub.js`, and testing against the hub.
8
+ - Updated dependencies
9
+ - @diffenderfer-games/hub-contract@2.0.0-next.1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Philip Diffenderfer
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Philip Diffenderfer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,139 +1,191 @@
1
- # @diffenderfer-games/hub
2
-
3
- The client library for games on [diffenderfer.games](https://diffenderfer.games):
4
- accounts, saves, stats, leaderboards, inventory and trades, daily challenges,
5
- the input system (keyboard, touch and gamepad), and the social, multiplayer,
6
- rooms and race namespaces. It is typed from the hub's wire contract
7
- (`@diffenderfer-games/hub-contract`), ships ES modules with `.d.ts` files, and
8
- carries no zod at runtime.
9
-
10
- ## Install
11
-
12
- ```sh
13
- npm install @diffenderfer-games/hub
14
- ```
15
-
16
- ESM only, for browsers (ES2020: Safari 14+, current Chrome, Edge and Firefox).
17
- Node 20+ for the `hub-doctor` command.
18
-
19
- ## Use
20
-
21
- ```ts
22
- import { hub } from '@diffenderfer-games/hub';
23
-
24
- const { user } = await hub.me();
25
- await hub.ensureGuest(); // a guest account, so progress saves without a sign-in
26
- await hub.putSave('auto', { level: 7, gold: 120 });
27
- await hub.submitScore('highscore', 9001, { title: 'High Score' });
28
- hub.recordPlay();
29
-
30
- hub.input.define({ groups: { play: { inputs: { jump: { keys: [' '], gamepad: { button: 0 } } } } } });
31
- hub.input.enable('play');
32
- hub.daily.define({ play: (challenge) => startLevel(challenge.seed) });
33
- hub.overlay.autoPause({ pause, resume });
34
- ```
35
-
36
- In a game the host serves, the slug and the API base are read from the page.
37
- For anything else, create a client yourself:
38
-
39
- ```ts
40
- import { createHub } from '@diffenderfer-games/hub';
41
-
42
- const demo = createHub({ slug: 'my-game', apiBase: '/_api', offline: 'auto' });
43
- ```
44
-
45
- A game's own JSON is typed by the game: `hub.getSave<MySave>('auto')`,
46
- `hub.putSave<MySave>('auto', save)`, `hub.getProfile<MyProfile>()`.
47
-
48
- ## Entry points
49
-
50
- | Import | What it has |
51
- |---|---|
52
- | `@diffenderfer-games/hub` | `hub`, `createHub`, `Hub`, the errors, every client type, and the input and daily exports |
53
- | `@diffenderfer-games/hub/input` | `getInput`, `InputSystem`, the on-screen control layout, `getUiStack` |
54
- | `@diffenderfer-games/hub/daily` | `getDaily`, `DailySystem` |
55
- | `@diffenderfer-games/hub/race`, `/social`, `/mp`, `/rooms` | one namespace each (`race`, `social` with `presence` and `notify`, `mp`, `rooms`) |
56
- | `@diffenderfer-games/hub/types` | type-only: every contract type (requests, replies, entities, error codes, socket ops and events, the `game.*` manifest) |
57
- | `@diffenderfer-games/hub/auto` | everything above, and it sets `window.HubSDK` (what `/_hub/hub.js` is built from) |
58
-
59
- The namespaces also hang off `hub` (`hub.input`, `hub.daily`, `hub.race`,
60
- `hub.social`, `hub.presence`, `hub.notify`, `hub.mp`, `hub.rooms`,
61
- `hub.overlay`, `hub.menu`), created on first use.
62
-
63
- ## Errors
64
-
65
- Every call rejects with a `HubError` when it fails. `status` is the HTTP
66
- status, or `undefined` when the hub could not be reached (`isOffline`).
67
- `code`, `reason`, `hint` and `retryAfterMs` come from the hub's error body.
68
-
69
- - `ContentRejectedError`: the safety filter refused some text (HTTP 422).
70
- Keep the player's draft and show `hint`.
71
- - `OfflineError`: an action that needs the hub was tried offline.
72
- - `code: 'unsupported_by_hub'`: the hub does not have this call yet (the game
73
- uses a newer client than the deployed hub). Deploy the hub first.
74
-
75
- The analytics calls (`recordPlay`, `heartbeat`, `event`) never throw.
76
-
77
- ## Offline
78
-
79
- With `offline: 'auto'` (the default), reads fall back to a cache in
80
- `localStorage` when the hub can't be reached, and writes (saves, stats,
81
- scores, profile) apply to the cache at once and are queued. The queue replays
82
- in order when the connection returns; `hub.sync()` replays it on demand,
83
- `hub.pending()` counts what waits, and `hub.onStatus(listener)` reports
84
- changes. `hub.prefetchAll()` warms the cache for every game in one request.
85
- `offline: 'always'` never touches the network (develop without a hub);
86
- `offline: 'never'` always throws instead.
87
-
88
- The cache and queue use the same `localStorage` keys as the old vendored
89
- client, so a game that switches to this package keeps its players' queued
90
- progress.
91
-
92
- ## Games without a build step
93
-
94
- Keep `import('/_hub/hub.js')` or `window.HubSDK.hub`: the host serves a
95
- bundle of this package's `./auto` entry, at the version the host was built
96
- with. Install the package as a dev dependency only if you want editor types:
97
-
98
- ```js
99
- /** @type {import('@diffenderfer-games/hub').Hub} */
100
- const hub = window.HubSDK.hub;
101
- ```
102
-
103
- ## Versions
104
-
105
- The client sends its version as `x-hub-client`. `hub.hubVersion()` reads the
106
- hub's `GET /_api/version` (`{ server, contract, supported, deprecated }`) once
107
- per page, and `hub.clientSupport()` says whether this client is `supported`,
108
- `deprecated` or `unsupported` (`unknown` on a hub from before versioning).
109
-
110
- The hub supports the current major and the previous one. Update with
111
- `npm update @diffenderfer-games/hub`.
112
-
113
- ## hub-doctor
114
-
115
- Run it in a game's folder, in CI and before pushing:
116
-
117
- ```sh
118
- npx hub-doctor # checks against https://diffenderfer.games
119
- npx hub-doctor --offline # skip the version check
120
- npx hub-doctor --hub http://localhost:8080 --dir ../my-game --json
121
- ```
122
-
123
- It fails when the installed client is outside the hub's `supported` range or
124
- the `package.json` `game.*` block does not match the manifest schema, and it
125
- warns when the client is deprecated or a vendored `src/hub/` copy (or
126
- `scripts/sync-hub.mjs`) is still around.
127
-
128
- ## Moving from the vendored copy
129
-
130
- 1. `npm install @diffenderfer-games/hub`.
131
- 2. Change `from './hub/hub'` (or `'./hub'`) to `from '@diffenderfer-games/hub'`.
132
- 3. Delete `src/hub/` and `scripts/sync-hub.mjs`.
133
- 4. Add `npx hub-doctor` to the game's CI.
134
-
135
- Every method name is unchanged.
136
-
137
- ## License
138
-
139
- MIT
1
+ # @diffenderfer-games/hub
2
+
3
+ The client library for games on [diffenderfer.games](https://diffenderfer.games):
4
+ accounts, saves, stats, leaderboards, inventory and trades, daily challenges,
5
+ the input system (keyboard, touch and gamepad), and the social, multiplayer,
6
+ rooms and race namespaces. It is typed from the hub's wire contract
7
+ (`@diffenderfer-games/hub-contract`), ships ES modules with `.d.ts` files, and
8
+ carries no zod at runtime.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ npm install @diffenderfer-games/hub
14
+ ```
15
+
16
+ **Prereleases: pin the exact version.** While the package is on `2.0.0-next.N`,
17
+ a caret range does not move between prereleases the way you might expect, so
18
+ install with `--save-exact` and bump on purpose:
19
+
20
+ ```sh
21
+ npm install --save-exact @diffenderfer-games/hub@2.0.0-next.1
22
+ ```
23
+
24
+ The `next` dist-tag always names the newest prerelease. `latest` points at the
25
+ same prerelease for now. It moves to `2.0.0` with the first stable release,
26
+ after which ordinary `^2.0.0` ranges are fine.
27
+
28
+ ESM only, for browsers (ES2020: Safari 14+, current Chrome, Edge and Firefox).
29
+ Node 20+ for the `hub-doctor` command.
30
+
31
+ ## Use
32
+
33
+ ```ts
34
+ import { hub } from '@diffenderfer-games/hub';
35
+
36
+ const { user } = await hub.me();
37
+ await hub.ensureGuest(); // a guest account, so progress saves without a sign-in
38
+ await hub.putSave('auto', { level: 7, gold: 120 });
39
+ await hub.submitScore('highscore', 9001, { title: 'High Score' });
40
+ hub.recordPlay();
41
+
42
+ hub.input.define({ groups: { play: { inputs: { jump: { keys: [' '], gamepad: { button: 0 } } } } } });
43
+ hub.input.enable('play');
44
+ hub.daily.define({ play: (challenge) => startLevel(challenge.seed) });
45
+ hub.overlay.autoPause({ pause, resume });
46
+ ```
47
+
48
+ In a game the host serves, the slug and the API base are read from the page.
49
+ For anything else, create a client yourself:
50
+
51
+ ```ts
52
+ import { createHub } from '@diffenderfer-games/hub';
53
+
54
+ const demo = createHub({ slug: 'my-game', apiBase: '/_api', offline: 'auto' });
55
+ ```
56
+
57
+ A game's own JSON is typed by the game: `hub.getSave<MySave>('auto')`,
58
+ `hub.putSave<MySave>('auto', save)`, `hub.getProfile<MyProfile>()`.
59
+
60
+ ## Entry points
61
+
62
+ | Import | What it has |
63
+ |---|---|
64
+ | `@diffenderfer-games/hub` | `hub`, `createHub`, `Hub`, the errors, every client type, and the input and daily exports |
65
+ | `@diffenderfer-games/hub/input` | `getInput`, `InputSystem`, the on-screen control layout, `getUiStack` |
66
+ | `@diffenderfer-games/hub/daily` | `getDaily`, `DailySystem` |
67
+ | `@diffenderfer-games/hub/race`, `/social`, `/mp`, `/rooms` | one namespace each (`race`, `social` with `presence` and `notify`, `mp`, `rooms`) |
68
+ | `@diffenderfer-games/hub/types` | type-only: every contract type (requests, replies, entities, error codes, socket ops and events, the `game.*` manifest) |
69
+ | `@diffenderfer-games/hub/auto` | everything above, and it sets `window.HubSDK` (what `/_hub/hub.js` is built from) |
70
+
71
+ The namespaces also hang off `hub` (`hub.input`, `hub.daily`, `hub.race`,
72
+ `hub.social`, `hub.presence`, `hub.notify`, `hub.mp`, `hub.rooms`,
73
+ `hub.overlay`, `hub.menu`), created on first use.
74
+
75
+ ## Errors
76
+
77
+ Every call rejects with a `HubError` when it fails. `status` is the HTTP
78
+ status, or `undefined` when the hub could not be reached (`isOffline`).
79
+ `code`, `reason`, `hint` and `retryAfterMs` come from the hub's error body.
80
+
81
+ - `ContentRejectedError`: the safety filter refused some text (HTTP 422).
82
+ Keep the player's draft and show `hint`.
83
+ - `OfflineError`: an action that needs the hub was tried offline.
84
+ - `code: 'unsupported_by_hub'`: the hub does not have this call yet (the game
85
+ uses a newer client than the deployed hub). Deploy the hub first.
86
+
87
+ The analytics calls (`recordPlay`, `heartbeat`, `event`) never throw.
88
+
89
+ ## Offline
90
+
91
+ With `offline: 'auto'` (the default), reads fall back to a cache in
92
+ `localStorage` when the hub can't be reached, and writes (saves, stats,
93
+ scores, profile) apply to the cache at once and are queued. The queue replays
94
+ in order when the connection returns; `hub.sync()` replays it on demand,
95
+ `hub.pending()` counts what waits, and `hub.onStatus(listener)` reports
96
+ changes. `hub.prefetchAll()` warms the cache for every game in one request.
97
+ `offline: 'always'` never touches the network (develop without a hub);
98
+ `offline: 'never'` always throws instead.
99
+
100
+ The cache and queue use the same `localStorage` keys as the old vendored
101
+ client, so a game that switches to this package keeps its players' queued
102
+ progress.
103
+
104
+ ## Games without a build step
105
+
106
+ Keep `import('/_hub/hub.js')` or `window.HubSDK.hub`: the host serves a
107
+ bundle of this package's `./auto` entry, at the version the host was built
108
+ with. Install the package as a dev dependency only if you want editor types:
109
+
110
+ ```js
111
+ /** @type {import('@diffenderfer-games/hub').Hub} */
112
+ const hub = window.HubSDK.hub;
113
+ ```
114
+
115
+ ## Sharing the page with the host's `/_hub/hub.js`
116
+
117
+ Every game page also gets the host's menu and social runtime, which use the
118
+ host's own copy of this client (`/_hub/hub.js`, built from the version the host
119
+ was deployed with). Your bundled copy and the host's cooperate. The page-wide
120
+ pieces (the input system, daily challenges, the realtime API) are registered
121
+ once on `window.__DG__`, each with the version that created it:
122
+
123
+ - **Same shape** (the usual case): the first one wins and both copies share
124
+ it, so an older patch version on either side is harmless.
125
+ - **A different shape** (a major change): your game's copy owns input and
126
+ daily; the host's runtime owns realtime. The mismatch is logged once in the
127
+ console with the fix: `npm update @diffenderfer-games/hub`.
128
+ - **A v1 vendored copy** already on the page is shared too, and recorded as
129
+ `{ version: 'v1' }`.
130
+
131
+ The v1 globals (`window.__HUB_INPUT__`, `__HUB_DAILY__`, `__HUB_RT__`) stay as
132
+ aliases. Don't create your own singletons; `hub.input`, `hub.daily` and the
133
+ forwarders always return the shared ones.
134
+
135
+ ## Versions
136
+
137
+ The client sends its version as `x-hub-client`. `hub.hubVersion()` reads the
138
+ hub's `GET /_api/version` (`{ server, contract, supported, deprecated }`) once
139
+ per page, and `hub.clientSupport()` says whether this client is `supported`,
140
+ `deprecated` or `unsupported` (`unknown` on a hub from before versioning).
141
+
142
+ The hub supports the current major and the previous one. Update with
143
+ `npm update @diffenderfer-games/hub`.
144
+
145
+ ## hub-doctor
146
+
147
+ Run it in a game's folder, in CI and before pushing:
148
+
149
+ ```sh
150
+ npx hub-doctor # checks against https://diffenderfer.games
151
+ npx hub-doctor --offline # skip the version check
152
+ npx hub-doctor --timeout 5000 # wait at most 5 s for the hub (default 10 s)
153
+ npx hub-doctor --hub http://localhost:8080 --dir ../my-game --json
154
+ ```
155
+
156
+ An unreachable or slow hub is an error (`hub unreachable at <url> (...)`) and
157
+ exits non-zero, so CI notices. Use `--offline` where CI has no network.
158
+
159
+ It fails when the installed client is outside the hub's `supported` range or
160
+ the `package.json` `game.*` block does not match the manifest schema, and it
161
+ warns when the client is deprecated or a vendored `src/hub/` copy (or
162
+ `scripts/sync-hub.mjs`) is still around.
163
+
164
+ ## Testing your game against the hub
165
+
166
+ The hub's test kit lives in the host repo (`test/helpers/`). Point your
167
+ game's tests at a checkout of it with `DG_HOST`; the default is
168
+ `../diffenderfer-games`. It boots a real hub on a free port for each test
169
+ file:
170
+
171
+ ```sh
172
+ DG_HOST=../diffenderfer-games HUB_IMPL=next npm run test:hub
173
+ ```
174
+
175
+ `HUB_IMPL=next` runs the TypeScript hub and host that production runs. Without
176
+ it, the kit boots the old hub (`src/index.js`), which is kept only as a
177
+ rollback path until it is deleted; test against `next`. The checkout needs
178
+ `npm ci` at its root and in `next/`.
179
+
180
+ ## Moving from the vendored copy
181
+
182
+ 1. `npm install @diffenderfer-games/hub`.
183
+ 2. Change `from './hub/hub'` (or `'./hub'`) to `from '@diffenderfer-games/hub'`.
184
+ 3. Delete `src/hub/` and `scripts/sync-hub.mjs`.
185
+ 4. Add `npx hub-doctor` to the game's CI.
186
+
187
+ Every method name is unchanged.
188
+
189
+ ## License
190
+
191
+ MIT
@@ -5,7 +5,7 @@ import { parseArgs } from "node:util";
5
5
  import { GamePackageJson, HubVersion } from "@diffenderfer-games/hub-contract";
6
6
  //#region src/core/version/client-version.gen.ts
7
7
  /** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
8
- const HUB_CLIENT_VERSION = "2.0.0-next.0";
8
+ const HUB_CLIENT_VERSION = "2.0.0-next.1";
9
9
  //#endregion
10
10
  //#region src/core/version/semver.ts
11
11
  const VERSION_PATTERN = /^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
@@ -81,6 +81,39 @@ function clientSupport(hubVersion, version = HUB_CLIENT_VERSION) {
81
81
  return satisfiesRange(version, hubVersion.deprecated) ? "deprecated" : "supported";
82
82
  }
83
83
  //#endregion
84
+ //#region src/doctor/hub-version-fetch.ts
85
+ /**
86
+ * Reading the hub's `GET /_api/version` for `hub-doctor`, with a timeout so a
87
+ * hung or unreachable hub fails a game's CI quickly instead of stalling it.
88
+ */
89
+ /** How long the doctor waits for the hub by default, ms. */
90
+ const DEFAULT_HUB_TIMEOUT_MS = 1e4;
91
+ /** Whether a version lookup failed. */
92
+ function isHubUnreachable(lookup) {
93
+ return lookup !== null && "unreachableUrl" in lookup;
94
+ }
95
+ /**
96
+ * The hub's version: `null` for a hub from before versioning (404), a
97
+ * {@link HubUnreachable} when it can't be read within `timeoutMs`.
98
+ */
99
+ async function fetchHubVersion(hubUrl, timeoutMs = DEFAULT_HUB_TIMEOUT_MS) {
100
+ const url = new URL("/_api/version", hubUrl).toString();
101
+ try {
102
+ const response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
103
+ if (response.status === 404) return null;
104
+ if (!response.ok) return {
105
+ unreachableUrl: url,
106
+ reason: `HTTP ${String(response.status)}`
107
+ };
108
+ return HubVersion.parse(await response.json());
109
+ } catch (failure) {
110
+ return {
111
+ unreachableUrl: url,
112
+ reason: failure instanceof Error && (failure.name === "TimeoutError" || failure.name === "AbortError") ? `timed out after ${String(timeoutMs)} ms` : failure instanceof Error ? failure.message : String(failure)
113
+ };
114
+ }
115
+ }
116
+ //#endregion
84
117
  //#region src/doctor/checks.ts
85
118
  /**
86
119
  * The checks `hub-doctor` runs on a game (plan §4.3.7). Each returns
@@ -90,14 +123,15 @@ function clientSupport(hubVersion, version = HUB_CLIENT_VERSION) {
90
123
  const UPDATE_FIX = "run `npm update @diffenderfer-games/hub`";
91
124
  /**
92
125
  * The installed client against the hub's `/_api/version`: outside
93
- * `supported` is an error, `deprecated` a warning. `null` (a hub from before
94
- * versioning) and an unreachable hub are only reported.
126
+ * `supported` is an error, `deprecated` a warning, `null` (a hub from before
127
+ * versioning) is only reported. An unreachable or slow hub is an error, so a
128
+ * game's CI notices (`--offline` skips the check).
95
129
  */
96
130
  function checkClientVersion(installedVersion, hubVersion) {
97
- if (hubVersion instanceof Error) return [{
98
- level: "warning",
131
+ if (isHubUnreachable(hubVersion)) return [{
132
+ level: "error",
99
133
  check: "version",
100
- message: `could not read the hub's version (${hubVersion.message}); the client version was not checked`
134
+ message: `hub unreachable at ${hubVersion.unreachableUrl} (${hubVersion.reason}); check --hub, or pass --offline to skip the version check`
101
135
  }];
102
136
  switch (clientSupport(hubVersion, installedVersion)) {
103
137
  case "unsupported": return [{
@@ -158,7 +192,7 @@ function checkManifest(packageJson) {
158
192
  * game's folder, in CI and before pushing:
159
193
  *
160
194
  * ```sh
161
- * npx hub-doctor [--dir <game folder>] [--hub <url>] [--offline] [--json]
195
+ * npx hub-doctor [--dir <game folder>] [--hub <url>] [--timeout <ms>] [--offline] [--json]
162
196
  * ```
163
197
  *
164
198
  * - the installed `@diffenderfer-games/hub` against the hub's
@@ -174,6 +208,7 @@ function readOptions() {
174
208
  const { values } = parseArgs({ options: {
175
209
  dir: { type: "string" },
176
210
  hub: { type: "string" },
211
+ timeout: { type: "string" },
177
212
  offline: {
178
213
  type: "boolean",
179
214
  default: false
@@ -183,9 +218,15 @@ function readOptions() {
183
218
  default: false
184
219
  }
185
220
  } });
221
+ const timeoutMs = values.timeout === void 0 ? DEFAULT_HUB_TIMEOUT_MS : Number(values.timeout);
222
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
223
+ process.stderr.write("hub-doctor: --timeout must be a positive number of milliseconds\n");
224
+ process.exit(2);
225
+ }
186
226
  return {
187
227
  gameDir: resolve(values.dir ?? "."),
188
228
  hubUrl: values.hub ?? DEFAULT_HUB_URL,
229
+ timeoutMs,
189
230
  isOffline: values.offline,
190
231
  isJson: values.json
191
232
  };
@@ -201,20 +242,9 @@ function installedClientVersion(gameDir) {
201
242
  } catch {}
202
243
  return HUB_CLIENT_VERSION;
203
244
  }
204
- /** The hub's `/_api/version`: `null` for a hub without it, an `Error` when unreachable. */
205
- async function fetchHubVersion(hubUrl) {
206
- try {
207
- const response = await fetch(new URL("/_api/version", hubUrl));
208
- if (response.status === 404) return null;
209
- if (!response.ok) return /* @__PURE__ */ new Error(`HTTP ${String(response.status)}`);
210
- return HubVersion.parse(await response.json());
211
- } catch (failure) {
212
- return failure instanceof Error ? failure : new Error(String(failure));
213
- }
214
- }
215
245
  async function runDoctor(options) {
216
246
  const findings = [];
217
- if (!options.isOffline) findings.push(...checkClientVersion(installedClientVersion(options.gameDir), await fetchHubVersion(options.hubUrl)));
247
+ if (!options.isOffline) findings.push(...checkClientVersion(installedClientVersion(options.gameDir), await fetchHubVersion(options.hubUrl, options.timeoutMs)));
218
248
  findings.push(...checkVendoredCopies(options.gameDir));
219
249
  try {
220
250
  findings.push(...checkManifest(readJsonFile(join(options.gameDir, "package.json"))));
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../../src/core/version/client-version.gen.ts","../../src/core/version/semver.ts","../../src/core/version/hub-version.ts","../../src/doctor/checks.ts","../../src/doctor/cli.ts"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../../src/core/version/client-version.gen.ts","../../src/core/version/semver.ts","../../src/core/version/hub-version.ts","../../src/doctor/hub-version-fetch.ts","../../src/doctor/checks.ts","../../src/doctor/cli.ts"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region src/core/version/client-version.gen.ts
2
2
  /** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
3
- const HUB_CLIENT_VERSION = "2.0.0-next.0";
3
+ const HUB_CLIENT_VERSION = "2.0.0-next.1";
4
4
  //#endregion
5
5
  export { HUB_CLIENT_VERSION as t };
6
6
 
@@ -178,7 +178,7 @@ let claimedDaily = null;
178
178
  function getDaily(host) {
179
179
  claimedDaily ?? (claimedDaily = claimSingleton({
180
180
  name: "daily",
181
- version: "2.0.0-next.0",
181
+ version: "2.0.0-next.1",
182
182
  api: 1,
183
183
  create: () => new DailySystem(host),
184
184
  isInstance: isDailySystem
@@ -50,8 +50,6 @@ function _defineProperty(e, r, t) {
50
50
  writable: !0
51
51
  }) : e[r] = t, e;
52
52
  }
53
- //#endregion
54
- //#region src/globals.ts
55
53
  /** The v1 window names, kept as aliases. */
56
54
  const LEGACY_GLOBAL_NAMES = {
57
55
  input: "__HUB_INPUT__",
@@ -80,7 +78,14 @@ function claimSingleton(claim) {
80
78
  if (claim.onMismatch?.(registered) !== true) return claim.create();
81
79
  } else {
82
80
  const legacy = page[LEGACY_GLOBAL_NAMES[claim.name]];
83
- if (registered === void 0 && claim.isInstance(legacy)) return legacy;
81
+ if (registered === void 0 && claim.isInstance(legacy)) {
82
+ registry[claim.name] = {
83
+ version: "v1",
84
+ api: claim.api,
85
+ instance: legacy
86
+ };
87
+ return legacy;
88
+ }
84
89
  }
85
90
  const instance = claim.create();
86
91
  registry[claim.name] = {
@@ -1 +1 @@
1
- {"version":3,"file":"globals.js","names":[],"sources":["../../src/realtime/cross-bundle.ts","../../src/globals.ts"],"mappings":";;AAWA,SAAgB,SAAS,WAAyC;CAChE,OAAO,OAAO,cAAc,YAAY,cAAc;AACxD;;AAIA,SAAgB,WAAgC,WAAoB,OAA8D;CAChI,IAAI,CAAC,SAAS,SAAS,GACrB,OAAO;CAET,OAAO,MAAM,OAAO,SAAS,QAAQ,aAAa,OAAO,QAAQ,IAAI,WAAW,IAAI,MAAM,UAAU;AACtG;;AAIA,SAAgB,UAAU,WAAoB,KAAsB;CAClE,OAAO,SAAS,SAAS,IAAI,QAAQ,IAAI,WAAW,GAAG,IAAI,KAAA;AAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACKA,MAAa,sBAAsB;CAAE,OAAO;CAAiB,OAAO;CAAiB,IAAI;AAAa;AAkCtG,MAAM,mCAAmB,IAAI,IAAmB;;AAGhD,SAAS,WAAW,MAAiD;CACnE,IAAI,SAAS,KAAA,GACX;CAEF,KAAK,WAAL,KAAK,SAAW,CAAC;CACjB,OAAO,KAAK;AACd;;AAGA,SAAgB,eAAkB,OAA6B;CAC7D,MAAM,OAAO,OAAO,WAAW,cAAc,KAAA,IAAY;CACzD,MAAM,WAAW,WAAW,IAAI;CAChC,IAAI,SAAS,KAAA,KAAa,aAAa,KAAA,GACrC,OAAO,MAAM,OAAO;CAEtB,MAAM,aAAa,SAAS,MAAM;CAClC,IAAI,eAAe,KAAA,KAAa,MAAM,WAAW,WAAW,QAAQ,GAAG;EACrE,IAAI,WAAW,QAAQ,MAAM,KAC3B,OAAO,WAAW;EAEpB,IAAI,CAAC,iBAAiB,IAAI,MAAM,IAAI,GAAG;GACrC,iBAAiB,IAAI,MAAM,IAAI;GAE/B,QAAQ,KAAK,+CAA+C,MAAM,KAAK,MAAM,WAAW,QAAQ,OAAO,OAAO,WAAW,GAAG,EAAE,KAAK,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,EAAE,2CAA2C;EACvN;EACA,IAAI,MAAM,aAAa,UAAU,MAAM,MACrC,OAAO,MAAM,OAAO;CAExB,OAAO;EACL,MAAM,SAAS,KAAK,oBAAoB,MAAM;EAC9C,IAAI,eAAe,KAAA,KAAa,MAAM,WAAW,MAAM,GAErD,OAAO;CAEX;CACA,MAAM,WAAW,MAAM,OAAO;CAC9B,SAAS,MAAM,QAAQ;EAAE,SAAS,MAAM;EAAS,KAAK,MAAM;EAAK;CAAS;CAC1E,KAAK,oBAAoB,MAAM,SAAS;CACxC,OAAO;AACT"}
1
+ {"version":3,"file":"globals.js","names":[],"sources":["../../src/realtime/cross-bundle.ts","../../src/globals.ts"],"mappings":";;AAWA,SAAgB,SAAS,WAAyC;CAChE,OAAO,OAAO,cAAc,YAAY,cAAc;AACxD;;AAIA,SAAgB,WAAgC,WAAoB,OAA8D;CAChI,IAAI,CAAC,SAAS,SAAS,GACrB,OAAO;CAET,OAAO,MAAM,OAAO,SAAS,QAAQ,aAAa,OAAO,QAAQ,IAAI,WAAW,IAAI,MAAM,UAAU;AACtG;;AAIA,SAAgB,UAAU,WAAoB,KAAsB;CAClE,OAAO,SAAS,SAAS,IAAI,QAAQ,IAAI,WAAW,GAAG,IAAI,KAAA;AAC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACQA,MAAa,sBAAsB;CAAE,OAAO;CAAiB,OAAO;CAAiB,IAAI;AAAa;AAkCtG,MAAM,mCAAmB,IAAI,IAAmB;;AAGhD,SAAS,WAAW,MAAiD;CACnE,IAAI,SAAS,KAAA,GACX;CAEF,KAAK,WAAL,KAAK,SAAW,CAAC;CACjB,OAAO,KAAK;AACd;;AAGA,SAAgB,eAAkB,OAA6B;CAC7D,MAAM,OAAO,OAAO,WAAW,cAAc,KAAA,IAAY;CACzD,MAAM,WAAW,WAAW,IAAI;CAChC,IAAI,SAAS,KAAA,KAAa,aAAa,KAAA,GACrC,OAAO,MAAM,OAAO;CAEtB,MAAM,aAAa,SAAS,MAAM;CAClC,IAAI,eAAe,KAAA,KAAa,MAAM,WAAW,WAAW,QAAQ,GAAG;EACrE,IAAI,WAAW,QAAQ,MAAM,KAC3B,OAAO,WAAW;EAEpB,IAAI,CAAC,iBAAiB,IAAI,MAAM,IAAI,GAAG;GACrC,iBAAiB,IAAI,MAAM,IAAI;GAE/B,QAAQ,KAAK,+CAA+C,MAAM,KAAK,MAAM,WAAW,QAAQ,OAAO,OAAO,WAAW,GAAG,EAAE,KAAK,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,EAAE,2CAA2C;EACvN;EACA,IAAI,MAAM,aAAa,UAAU,MAAM,MACrC,OAAO,MAAM,OAAO;CAExB,OAAO;EACL,MAAM,SAAS,KAAK,oBAAoB,MAAM;EAC9C,IAAI,eAAe,KAAA,KAAa,MAAM,WAAW,MAAM,GAAG;GAGxD,SAAS,MAAM,QAAQ;IAAE,SAAA;IAA4B,KAAK,MAAM;IAAK,UAAU;GAAO;GACtF,OAAO;EACT;CACF;CACA,MAAM,WAAW,MAAM,OAAO;CAC9B,SAAS,MAAM,QAAQ;EAAE,SAAS,MAAM;EAAS,KAAK,MAAM;EAAK;CAAS;CAC1E,KAAK,oBAAoB,MAAM,SAAS;CACxC,OAAO;AACT"}
@@ -700,7 +700,7 @@ declare class ContentRejectedError extends HubError {
700
700
  //#endregion
701
701
  //#region src/core/version/client-version.gen.d.ts
702
702
  /** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
703
- declare const HUB_CLIENT_VERSION = "2.0.0-next.0";
703
+ declare const HUB_CLIENT_VERSION = "2.0.0-next.1";
704
704
  //#endregion
705
705
  export { SubmitScoreResult as $, BoardWithTop as A, Json$1 as B, CLIENT_VERSION_HEADER as C, QueuedScoreOptions as D, QueueOpInput as E, GlobalAnalytics as F, Profile as G, LeaderboardResult as H, HubOptions as I, SaveMeta as J, ProfileSummary as K, HubStatus as L, GameInfo$1 as M, GameLeaderboards as N, BufferedEvent as O, GameRecords as P, SubmitScoreOptions as Q, Inventory as R, SyncResult as S, QueueOp as T, MeResponse as U, LeaderboardEntry as V, Metrics$1 as W, SortDir$1 as X, SnapshotResponse as Y, Stats$1 as Z, TradeNoteOptions as _, HubErrorDetails as a, StatResult as b, Hub as c, ClientSupport as d, User as et, HubMenuControl as f, TradeListOptions as g, TradeId as h, HubErrorCode as i, GamePayload as it, GameAnalytics as j, Board$1 as k, createHub as l, TradeBundle as m, ContentRejectedError as n, EndpointName as nt, OfflineError as o, GrantBundle as p, Save as q, HubError as r, EndpointReply as rt, UNSUPPORTED_BY_HUB as s, HUB_CLIENT_VERSION as t, EndpointFields as tt, hub as u, AuthResponse as v, ProfilePatch as w, SyncConflict as x, ProfileUpdate as y, InventorySnapshot as z };
706
706
  //# sourceMappingURL=index.d.ts.map