@crowdedkingdoms/crowdyjs 8.19.0 → 8.20.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/README.md +16 -3
- package/dist/crowdy-client.d.ts +29 -1
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +53 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -119,6 +119,7 @@ If `managementUrl` is omitted, the SDK falls back to `httpUrl` for backwards-com
|
|
|
119
119
|
| `client.playerModel` | Player-owned flexible model containers and grid-confined automations (`containers`, `createContainer`, `setProperty`, `automations`, `createAutomation`, …). |
|
|
120
120
|
| `client.udp` | UDP proxy subscriptions + spatial mutations (`sendActorUpdate`, `sendVoxelUpdate`, `sendAudioPacket`, `sendTextPacket`, `sendClientEvent`). |
|
|
121
121
|
| `client.realtime` | Connection status, manual `connect()` / `disconnect()`, `onStatus()` listener. |
|
|
122
|
+
| `client.refreshGameplayToken()` | Safely rotates an active game client's app token: disconnects the old-token UDP proxy, refreshes/stores the token, and opens the new-token proxy while existing realtime handlers resubscribe in place. |
|
|
122
123
|
| `client.world(appId)` | Higher-level helpers for browser games (`actor.join`, `actor.sendState`, `actor.sendText`). |
|
|
123
124
|
|
|
124
125
|
`PlayerCodeBroker` is the P1 page-side browser security skeleton: it transfers
|
|
@@ -160,9 +161,16 @@ Auth, user reads, and the studio-admin / operator surfaces target `managementUrl
|
|
|
160
161
|
3. Subscribe to UDP proxy notifications with `game.udp.subscribe(handlers, appId)` — `appId` is **required** (the SDK opens the realtime socket on demand and scopes it to that app).
|
|
161
162
|
4. Join a chunk by sending an initial actor update.
|
|
162
163
|
5. Send actor, voxel, text, audio, and client-event updates through `game.udp` or the higher-level `game.world(appId)` helpers.
|
|
163
|
-
6.
|
|
164
|
+
6. Before the app token expires, call `game.refreshGameplayToken()` while gameplay is active. It closes the old-token UDP proxy before rotating the token, opens the new-token proxy, and lets the existing realtime subscription restart without adding handlers. Use `game.portal.refresh()` directly only when no UDP proxy lifecycle needs to be preserved.
|
|
164
165
|
7. Call `client.close()` (and `game.close()`) when disposing the SDK instances.
|
|
165
166
|
|
|
167
|
+
`refreshGameplayToken()` deliberately stops on the first failed stage. If the
|
|
168
|
+
old proxy cannot confirm disconnect, no refresh is attempted and the old token
|
|
169
|
+
remains active. If refresh fails, the old token is still retained (although its
|
|
170
|
+
proxy was closed and may be reopened). If the new proxy connect fails, the
|
|
171
|
+
fresh token remains stored; surface the error and retry `game.udp.connect()`
|
|
172
|
+
instead of rotating again.
|
|
173
|
+
|
|
166
174
|
## Per-app routing
|
|
167
175
|
|
|
168
176
|
When a player is about to join an app, query its routing fields on the management API first:
|
|
@@ -502,10 +510,15 @@ location.assign(await overworld.portal.handleAuthorizeRequest());
|
|
|
502
510
|
|
|
503
511
|
// Game origin, on callback boot: exchange code+verifier -> app token (stored).
|
|
504
512
|
const entered = await game.portal.completeEntry();
|
|
505
|
-
// Keep
|
|
506
|
-
await game.
|
|
513
|
+
// Keep active UDP gameplay running past expiry without orphaning the old proxy:
|
|
514
|
+
await game.refreshGameplayToken();
|
|
507
515
|
```
|
|
508
516
|
|
|
517
|
+
`portal.refresh()` remains available for clients with no active UDP lifecycle.
|
|
518
|
+
Once a proxy or realtime gameplay session is active, prefer
|
|
519
|
+
`refreshGameplayToken()` so the old Bearer closes its proxy before the token is
|
|
520
|
+
revoked.
|
|
521
|
+
|
|
509
522
|
Game-to-game routes through the Overworld for a fresh per-game token. New
|
|
510
523
|
realtime codes: `APP_TOKEN_REQUIRED`, `APP_SCOPE_MISMATCH`; new `UdpErrorCode`:
|
|
511
524
|
`TOKEN_EXPIRED`. See [MIGRATION.md](MIGRATION.md) for the full v7 breaking guide.
|
package/dist/crowdy-client.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ import { GameKitClient, type GameKitOptions } from './kit/index.js';
|
|
|
32
32
|
import { AuthAPI } from './domains/auth.js';
|
|
33
33
|
import { UsersAPI } from './domains/users.js';
|
|
34
34
|
import { AppsAPI } from './domains/apps.js';
|
|
35
|
-
import { PortalAPI, type PkceStore } from './domains/portal.js';
|
|
35
|
+
import { PortalAPI, type AppTokenResponse, type PkceStore } from './domains/portal.js';
|
|
36
36
|
import { PlatformAPI } from './domains/platform.js';
|
|
37
37
|
import { OrganizationsAPI } from './domains/organizations.js';
|
|
38
38
|
import { AppAccessAPI } from './domains/appAccess.js';
|
|
@@ -117,6 +117,7 @@ export interface CrowdyClientConfig {
|
|
|
117
117
|
lbCookieStore?: LbCookieStore;
|
|
118
118
|
}
|
|
119
119
|
export declare class CrowdyClient {
|
|
120
|
+
private gameplayTokenRefresh;
|
|
120
121
|
/** Shared token state for both game-api and management-api requests. */
|
|
121
122
|
readonly session: AuthState;
|
|
122
123
|
/** game-api HTTP client. */
|
|
@@ -213,6 +214,33 @@ export declare class CrowdyClient {
|
|
|
213
214
|
setToken(token: string | null): void;
|
|
214
215
|
/** Read the current Bearer token (null if no session). */
|
|
215
216
|
getToken(): string | null;
|
|
217
|
+
/**
|
|
218
|
+
* Rotate an active gameplay token without orphaning its old UDP proxy.
|
|
219
|
+
*
|
|
220
|
+
* This is the supported refresh path while a game client has an open UDP
|
|
221
|
+
* proxy: it disconnects that proxy while the old Bearer token is still
|
|
222
|
+
* active, calls {@link PortalAPI.refresh} to rotate and store the new token,
|
|
223
|
+
* then opens a proxy authenticated by the new token. The session token
|
|
224
|
+
* listener restarts the existing realtime subscription in place, so its
|
|
225
|
+
* registered notification handlers are retained rather than duplicated.
|
|
226
|
+
* Concurrent calls share one in-flight rotation.
|
|
227
|
+
*
|
|
228
|
+
* Failure semantics:
|
|
229
|
+
* - If the old proxy disconnect rejects or does not confirm closure, rotation
|
|
230
|
+
* is aborted and the old token remains active.
|
|
231
|
+
* - If refresh rejects, the old token remains active (the old proxy has
|
|
232
|
+
* already closed and can be opened again with {@link UdpAPI.connect}).
|
|
233
|
+
* - If opening the new proxy rejects, the fresh token remains active. Surface
|
|
234
|
+
* the error and retry {@link UdpAPI.connect}; do not repeat the rotation
|
|
235
|
+
* merely to retry that connection.
|
|
236
|
+
*
|
|
237
|
+
* @returns The fresh app-scoped token response stored on this client.
|
|
238
|
+
* @throws {CrowdyProtocolError} if the old proxy does not confirm closure.
|
|
239
|
+
* @throws Transport or GraphQL errors from the disconnect, refresh, or
|
|
240
|
+
* reconnect step, with token state preserved as described above.
|
|
241
|
+
*/
|
|
242
|
+
refreshGameplayToken(): Promise<AppTokenResponse>;
|
|
243
|
+
private performGameplayTokenRefresh;
|
|
216
244
|
/**
|
|
217
245
|
* Ergonomic, app-scoped realtime facade. `client.world(appId)` returns a
|
|
218
246
|
* {@link WorldClient} whose `actor()` and `subscribe()` helpers pass `appId`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"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"}
|
package/dist/crowdy-client.js
CHANGED
|
@@ -25,12 +25,13 @@ import { GraphQLClient } from './client.js';
|
|
|
25
25
|
import { LbCookieStore } from './lb-cookie-store.js';
|
|
26
26
|
import { RealtimeMetrics } from './metrics.js';
|
|
27
27
|
import { SubscriptionManager } from './subscriptions.js';
|
|
28
|
+
import { CrowdyProtocolError } from './errors.js';
|
|
28
29
|
import { WorldClient } from './world.js';
|
|
29
30
|
import { GameKitClient } from './kit/index.js';
|
|
30
31
|
import { AuthAPI } from './domains/auth.js';
|
|
31
32
|
import { UsersAPI } from './domains/users.js';
|
|
32
33
|
import { AppsAPI } from './domains/apps.js';
|
|
33
|
-
import { PortalAPI } from './domains/portal.js';
|
|
34
|
+
import { PortalAPI, } from './domains/portal.js';
|
|
34
35
|
import { PlatformAPI } from './domains/platform.js';
|
|
35
36
|
import { OrganizationsAPI } from './domains/organizations.js';
|
|
36
37
|
import { AppAccessAPI } from './domains/appAccess.js';
|
|
@@ -62,6 +63,7 @@ import { MarketplaceAPI } from './domains/marketplace.js';
|
|
|
62
63
|
import { PlayerModelAPI } from './domains/playerModel.js';
|
|
63
64
|
export class CrowdyClient {
|
|
64
65
|
constructor(config = {}) {
|
|
66
|
+
this.gameplayTokenRefresh = null;
|
|
65
67
|
this.session = new AuthState(config.tokenStore);
|
|
66
68
|
const lbCookieStore = config.lbCookieStore ?? new LbCookieStore();
|
|
67
69
|
this.graphql = new GraphQLClient({
|
|
@@ -146,6 +148,56 @@ export class CrowdyClient {
|
|
|
146
148
|
getToken() {
|
|
147
149
|
return this.session.getToken();
|
|
148
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Rotate an active gameplay token without orphaning its old UDP proxy.
|
|
153
|
+
*
|
|
154
|
+
* This is the supported refresh path while a game client has an open UDP
|
|
155
|
+
* proxy: it disconnects that proxy while the old Bearer token is still
|
|
156
|
+
* active, calls {@link PortalAPI.refresh} to rotate and store the new token,
|
|
157
|
+
* then opens a proxy authenticated by the new token. The session token
|
|
158
|
+
* listener restarts the existing realtime subscription in place, so its
|
|
159
|
+
* registered notification handlers are retained rather than duplicated.
|
|
160
|
+
* Concurrent calls share one in-flight rotation.
|
|
161
|
+
*
|
|
162
|
+
* Failure semantics:
|
|
163
|
+
* - If the old proxy disconnect rejects or does not confirm closure, rotation
|
|
164
|
+
* is aborted and the old token remains active.
|
|
165
|
+
* - If refresh rejects, the old token remains active (the old proxy has
|
|
166
|
+
* already closed and can be opened again with {@link UdpAPI.connect}).
|
|
167
|
+
* - If opening the new proxy rejects, the fresh token remains active. Surface
|
|
168
|
+
* the error and retry {@link UdpAPI.connect}; do not repeat the rotation
|
|
169
|
+
* merely to retry that connection.
|
|
170
|
+
*
|
|
171
|
+
* @returns The fresh app-scoped token response stored on this client.
|
|
172
|
+
* @throws {CrowdyProtocolError} if the old proxy does not confirm closure.
|
|
173
|
+
* @throws Transport or GraphQL errors from the disconnect, refresh, or
|
|
174
|
+
* reconnect step, with token state preserved as described above.
|
|
175
|
+
*/
|
|
176
|
+
async refreshGameplayToken() {
|
|
177
|
+
if (this.gameplayTokenRefresh)
|
|
178
|
+
return this.gameplayTokenRefresh;
|
|
179
|
+
const operation = this.performGameplayTokenRefresh();
|
|
180
|
+
this.gameplayTokenRefresh = operation;
|
|
181
|
+
try {
|
|
182
|
+
return await operation;
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
if (this.gameplayTokenRefresh === operation) {
|
|
186
|
+
this.gameplayTokenRefresh = null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async performGameplayTokenRefresh() {
|
|
191
|
+
const disconnected = await this.udp.disconnect();
|
|
192
|
+
if (!disconnected) {
|
|
193
|
+
throw new CrowdyProtocolError({
|
|
194
|
+
message: 'UDP proxy did not confirm disconnect; gameplay token rotation was aborted',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const token = await this.portal.refresh();
|
|
198
|
+
await this.udp.connect();
|
|
199
|
+
return token;
|
|
200
|
+
}
|
|
149
201
|
/**
|
|
150
202
|
* Ergonomic, app-scoped realtime facade. `client.world(appId)` returns a
|
|
151
203
|
* {@link WorldClient} whose `actor()` and `subscribe()` helpers pass `appId`
|
package/dist/index.d.ts
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* or internal tooling, never an untrusted browser.
|
|
46
46
|
*/
|
|
47
47
|
/** The published package version. Mirrors `package.json`. */
|
|
48
|
-
export declare const VERSION = "8.
|
|
48
|
+
export declare const VERSION = "8.20.0";
|
|
49
49
|
export { LbCookieStore } from './lb-cookie-store.js';
|
|
50
50
|
export { CrowdyClient, createCrowdyClient, type CrowdyClientConfig, } from './crowdy-client.js';
|
|
51
51
|
export { BrowserLocalStorageTokenStore, SessionStore, type SessionListener, type TokenStore, } from './session.js';
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* or internal tooling, never an untrusted browser.
|
|
46
46
|
*/
|
|
47
47
|
/** The published package version. Mirrors `package.json`. */
|
|
48
|
-
export const VERSION = '8.
|
|
48
|
+
export const VERSION = '8.20.0';
|
|
49
49
|
export { LbCookieStore } from './lb-cookie-store.js';
|
|
50
50
|
export { CrowdyClient, createCrowdyClient, } from './crowdy-client.js';
|
|
51
51
|
export { BrowserLocalStorageTokenStore, SessionStore, } from './session.js';
|