@crowdedkingdoms/crowdyjs 7.1.0 → 7.1.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.
- package/README.md +27 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CrowdyJS
|
|
2
2
|
|
|
3
|
-
The official browser-first TypeScript SDK for **Crowded Kingdoms**. CrowdyJS gives you
|
|
3
|
+
The official browser-first TypeScript SDK for **Crowded Kingdoms**. CrowdyJS gives you typed clients for auth, the world/replication GraphQL API, and the UDP proxy subscription stream. As of **v7** it follows the Overworld two-token model: an identity **session token** for the Management API, and short-lived **app-scoped tokens** for gameplay via `client.portal` (see [Overworld portals & app-scoped tokens (v7)](#overworld-portals--app-scoped-tokens-v7)).
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -41,12 +41,15 @@ if (!client.session.getToken()) {
|
|
|
41
41
|
await client.auth.login({ email: 'player@example.com', password: 'secret' });
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
// `client.auth.login()` returns an identity SESSION token (Management API only).
|
|
45
|
+
// Identity reads run on it:
|
|
46
|
+
const me = await client.users.me();
|
|
47
|
+
console.log(me.email);
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
**Gameplay needs an app-scoped token, not the login token.** Mint one per app and
|
|
51
|
+
drive the Game API world/UDP surface (including `gameClientBootstrap`) from a
|
|
52
|
+
per-game client — see [Overworld portals & app-scoped tokens (v7)](#overworld-portals--app-scoped-tokens-v7).
|
|
50
53
|
|
|
51
54
|
If `managementUrl` is omitted, the SDK falls back to `httpUrl` for backwards-compat with the single-endpoint deployment.
|
|
52
55
|
|
|
@@ -90,16 +93,17 @@ If `managementUrl` is omitted, the SDK falls back to `httpUrl` for backwards-com
|
|
|
90
93
|
|---|---|
|
|
91
94
|
| `client.operator` | Control plane: cross-org environments, change orders, secrets, release management, audit. |
|
|
92
95
|
|
|
93
|
-
Auth, user reads, and the studio-admin / operator surfaces target `managementUrl
|
|
96
|
+
Auth, user reads, and the studio-admin / operator surfaces target `managementUrl` and use the **identity session token**; the game-client world/UDP surfaces target `httpUrl` / `wsUrl` and require an **app-scoped token** for that app. Use one identity client plus a per-game client (see [Overworld portals & app-scoped tokens (v7)](#overworld-portals--app-scoped-tokens-v7)); each client's `AuthState` carries its token to its own endpoints, so HTTP and WebSocket auth never drift within a client.
|
|
94
97
|
|
|
95
98
|
## Game-loop lifecycle
|
|
96
99
|
|
|
97
|
-
1. Authenticate with `client.auth.login()` or
|
|
98
|
-
2.
|
|
99
|
-
3.
|
|
100
|
-
4.
|
|
101
|
-
5.
|
|
102
|
-
6. Call `
|
|
100
|
+
1. Authenticate on the identity client with `client.auth.login()` (or `client.session.restore()`) — this yields the **session token**.
|
|
101
|
+
2. Mint an **app-scoped token** for the app (`identity.portal.mintAppToken(appId)`, or the PKCE portal flow across origins) and build a per-game client holding it (`game.setToken(token)`). The gameplay steps below run on that **game** client.
|
|
102
|
+
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).
|
|
103
|
+
4. Join a chunk by sending an initial actor update.
|
|
104
|
+
5. Send actor, voxel, text, audio, and client-event updates through `game.udp` or the higher-level `game.world(appId)` helpers.
|
|
105
|
+
6. Call `game.udp.disconnect()` when leaving the world; `game.portal.refresh()` before the token expires to keep playing.
|
|
106
|
+
7. Call `client.close()` (and `game.close()`) when disposing the SDK instances.
|
|
103
107
|
|
|
104
108
|
## Per-app routing
|
|
105
109
|
|
|
@@ -118,18 +122,21 @@ query AppForRouting($appId: BigInt!) {
|
|
|
118
122
|
|
|
119
123
|
`gameApiUrl` is populated for **both** dedicated (`splitMode`) and shared
|
|
120
124
|
(`deploymentTarget: "shared"`) apps. When it's set, build a **second**
|
|
121
|
-
`CrowdyClient` with `httpUrl: gameApiUrl` (and the matching `wsUrl`)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
`CrowdyClient` with `httpUrl: gameApiUrl` (and the matching `wsUrl`) holding that
|
|
126
|
+
app's **app-scoped token** (`identity.portal.mintAppToken(appId)` — do **not**
|
|
127
|
+
reuse the identity client's session token store), then drive gameplay through that
|
|
128
|
+
client. In practice `mintAppToken` already returns `gameApiUrl` / `gameApiWsUrl`,
|
|
129
|
+
so you rarely need this separate routing query. Apps with no `gameApiUrl` keep
|
|
130
|
+
working against the default `httpUrl` you configured.
|
|
125
131
|
|
|
126
132
|
## Realtime notifications
|
|
127
133
|
|
|
128
134
|
`subscribe` takes the handlers **and a required `appId`** (second argument). The
|
|
129
135
|
Game API scopes the realtime session to that app and rejects an app-agnostic
|
|
130
|
-
subscription with a `RealtimeConnectionEvent` (`code: 'APP_ID_REQUIRED'`).
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
subscription with a `RealtimeConnectionEvent` (`code: 'APP_ID_REQUIRED'`). It also
|
|
137
|
+
rejects an identity session token (`APP_TOKEN_REQUIRED`) or a token scoped to a
|
|
138
|
+
different app (`APP_SCOPE_MISMATCH`). Run one client per app (each holding that
|
|
139
|
+
app's app-scoped token) when a player is in multiple apps at once.
|
|
133
140
|
|
|
134
141
|
```ts
|
|
135
142
|
const appId = '1';
|
|
@@ -258,7 +265,7 @@ The key parameter is optional and trailing, so it's safe to omit. Requires a ser
|
|
|
258
265
|
|
|
259
266
|
- Use `client.auth.setToken(token)` if you need to seed a token externally (e.g. when restoring auth from a non-default storage).
|
|
260
267
|
- `client.session.restore()` reads from the configured `tokenStore`. `BrowserLocalStorageTokenStore` is provided; bring your own for SSR or Node usage.
|
|
261
|
-
-
|
|
268
|
+
- Each client's `AuthState` is observed by both its HTTP client and its realtime socket, so HTTP and WebSocket auth never drift within a client. Hold the **identity session token** on the management/identity client and an **app-scoped token** on each per-game client (`client.portal` — see the [v7 section](#overworld-portals--app-scoped-tokens-v7)).
|
|
262
269
|
|
|
263
270
|
## Overworld portals & app-scoped tokens (v7)
|
|
264
271
|
|
package/dist/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* or internal tooling, never an untrusted browser.
|
|
42
42
|
*/
|
|
43
43
|
/** The published package version. Mirrors `package.json`. */
|
|
44
|
-
export declare const VERSION = "7.1.
|
|
44
|
+
export declare const VERSION = "7.1.1";
|
|
45
45
|
export { CrowdyClient, createCrowdyClient, type CrowdyClientConfig, } from './crowdy-client.js';
|
|
46
46
|
export { BrowserLocalStorageTokenStore, SessionStore, type SessionListener, type TokenStore, } from './session.js';
|
|
47
47
|
export { GraphQLClient, GraphQLTransport, type GraphQLClientConfig, } from './client.js';
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
* or internal tooling, never an untrusted browser.
|
|
42
42
|
*/
|
|
43
43
|
/** The published package version. Mirrors `package.json`. */
|
|
44
|
-
export const VERSION = '7.1.
|
|
44
|
+
export const VERSION = '7.1.1';
|
|
45
45
|
export { CrowdyClient, createCrowdyClient, } from './crowdy-client.js';
|
|
46
46
|
export { BrowserLocalStorageTokenStore, SessionStore, } from './session.js';
|
|
47
47
|
export { GraphQLClient, GraphQLTransport, } from './client.js';
|