@crowdedkingdomstudios/crowdyjs 2.1.2 → 4.0.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/MIGRATION.md +26 -0
- package/README.md +155 -749
- package/dist/auth-state.d.ts +6 -16
- package/dist/auth-state.d.ts.map +1 -1
- package/dist/auth-state.js +9 -26
- package/dist/client.d.ts +14 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +24 -17
- package/dist/crowdy-client.d.ts +62 -16
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +70 -28
- package/dist/domains/apps.d.ts +48 -20
- package/dist/domains/apps.d.ts.map +1 -1
- package/dist/domains/apps.js +58 -35
- package/dist/domains/auth.d.ts +33 -22
- package/dist/domains/auth.d.ts.map +1 -1
- package/dist/domains/auth.js +51 -33
- package/dist/domains/serverStatus.d.ts +2 -1
- package/dist/domains/serverStatus.d.ts.map +1 -1
- package/dist/domains/serverStatus.js +5 -1
- package/dist/domains/udp.d.ts +28 -3
- package/dist/domains/udp.d.ts.map +1 -1
- package/dist/domains/udp.js +52 -1
- package/dist/domains/users.d.ts +19 -16
- package/dist/domains/users.d.ts.map +1 -1
- package/dist/domains/users.js +21 -39
- package/dist/errors.d.ts +42 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +42 -0
- package/dist/generated/graphql.d.ts +1473 -11
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +17 -8
- package/dist/index.d.ts +37 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -20
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +1 -0
- package/dist/realtime.d.ts +89 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +273 -0
- package/dist/session.d.ts +27 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +61 -0
- package/dist/subscriptions.d.ts +1 -48
- package/dist/subscriptions.d.ts.map +1 -1
- package/dist/subscriptions.js +1 -192
- package/dist/types.d.ts +2 -31
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -33
- package/dist/utils.d.ts +12 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +50 -0
- package/dist/world.d.ts +44 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +105 -0
- package/package.json +12 -3
- package/dist/domains/appAccess.d.ts +0 -23
- package/dist/domains/appAccess.d.ts.map +0 -1
- package/dist/domains/appAccess.js +0 -42
- package/dist/domains/billing.d.ts +0 -17
- package/dist/domains/billing.d.ts.map +0 -1
- package/dist/domains/billing.js +0 -31
- package/dist/domains/organizations.d.ts +0 -33
- package/dist/domains/organizations.d.ts.map +0 -1
- package/dist/domains/organizations.js +0 -90
- package/dist/domains/payments.d.ts +0 -20
- package/dist/domains/payments.d.ts.map +0 -1
- package/dist/domains/payments.js +0 -28
- package/dist/domains/quotas.d.ts +0 -20
- package/dist/domains/quotas.d.ts.map +0 -1
- package/dist/domains/quotas.js +0 -34
package/dist/auth-state.d.ts
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
|
+
import { SessionStore, type SessionListener, type TokenStore } from './session.js';
|
|
2
|
+
export type AuthStateListener = SessionListener;
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Both the HTTP client (`GraphQLClient`) and the WebSocket subscription
|
|
5
|
-
* manager observe this. Anything that mutates auth state - the typed
|
|
6
|
-
* `client.auth.login()` / `register()` / `logout()` family, or external
|
|
7
|
-
* callers - flows through `setToken()` so subscription requests can never
|
|
8
|
-
* silently fail with "Must be authenticated to subscribe".
|
|
9
|
-
*
|
|
10
|
-
* (Replaces the previous arrangement where GraphQLClient and
|
|
11
|
-
* SubscriptionManager each held their own copy of the token.)
|
|
4
|
+
* Backwards-compatible internal name for the v3 SessionStore. Public callers
|
|
5
|
+
* should use `client.session`; older domain wrappers still accept AuthState.
|
|
12
6
|
*/
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
private token;
|
|
16
|
-
private listeners;
|
|
17
|
-
getToken(): string | null;
|
|
18
|
-
setToken(token: string | null): void;
|
|
7
|
+
export declare class AuthState extends SessionStore {
|
|
8
|
+
constructor(tokenStore?: TokenStore);
|
|
19
9
|
subscribe(listener: AuthStateListener): () => void;
|
|
20
10
|
}
|
|
21
11
|
//# sourceMappingURL=auth-state.d.ts.map
|
package/dist/auth-state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-state.d.ts","sourceRoot":"","sources":["../src/auth-state.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-state.d.ts","sourceRoot":"","sources":["../src/auth-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEhD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,YAAY;gBAC7B,UAAU,CAAC,EAAE,UAAU;IAInC,SAAS,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI;CAGnD"}
|
package/dist/auth-state.js
CHANGED
|
@@ -1,30 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
setToken(token) {
|
|
10
|
-
if (token === this.token)
|
|
11
|
-
return;
|
|
12
|
-
this.token = token;
|
|
13
|
-
for (const listener of this.listeners) {
|
|
14
|
-
try {
|
|
15
|
-
listener(token);
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
console.error('AuthState listener threw:', error);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
1
|
+
import { SessionStore } from './session.js';
|
|
2
|
+
/**
|
|
3
|
+
* Backwards-compatible internal name for the v3 SessionStore. Public callers
|
|
4
|
+
* should use `client.session`; older domain wrappers still accept AuthState.
|
|
5
|
+
*/
|
|
6
|
+
export class AuthState extends SessionStore {
|
|
7
|
+
constructor(tokenStore) {
|
|
8
|
+
super(tokenStore);
|
|
21
9
|
}
|
|
22
10
|
subscribe(listener) {
|
|
23
|
-
this.
|
|
24
|
-
// Replay current value immediately so listeners initialize correctly.
|
|
25
|
-
listener(this.token);
|
|
26
|
-
return () => {
|
|
27
|
-
this.listeners.delete(listener);
|
|
28
|
-
};
|
|
11
|
+
return this.onChange(listener);
|
|
29
12
|
}
|
|
30
13
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -7,27 +7,36 @@
|
|
|
7
7
|
* `client.auth.login`, `client.udp.sendActorUpdate`).
|
|
8
8
|
*/
|
|
9
9
|
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
10
|
-
import {
|
|
10
|
+
import type { SessionStore } from './session.js';
|
|
11
|
+
import type { CrowdyLogger } from './logger.js';
|
|
11
12
|
export interface GraphQLClientConfig {
|
|
13
|
+
httpUrl?: string;
|
|
12
14
|
graphqlEndpoint?: string;
|
|
13
15
|
timeout?: number;
|
|
16
|
+
logger?: CrowdyLogger;
|
|
14
17
|
}
|
|
15
18
|
export declare class GraphQLClient {
|
|
16
19
|
private readonly graphqlEndpoint;
|
|
17
20
|
private readonly timeout;
|
|
18
|
-
private readonly
|
|
19
|
-
|
|
21
|
+
private readonly session;
|
|
22
|
+
private readonly logger;
|
|
23
|
+
constructor(config: GraphQLClientConfig | undefined, session: SessionStore);
|
|
20
24
|
getEndpoint(): string;
|
|
21
25
|
/**
|
|
22
26
|
* Execute a typed GraphQL operation produced by codegen and return the
|
|
23
27
|
* `data` payload. Throws on transport errors, GraphQL errors, or timeouts.
|
|
24
28
|
*/
|
|
25
|
-
request<TResult, TVariables>(document: TypedDocumentNode<TResult, TVariables>, variables?: TVariables
|
|
29
|
+
request<TResult, TVariables>(document: TypedDocumentNode<TResult, TVariables>, variables?: TVariables, options?: {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}): Promise<TResult>;
|
|
26
32
|
/**
|
|
27
33
|
* Internal escape hatch for raw query strings (used by hand-written
|
|
28
34
|
* adapters that haven't migrated to typed documents yet). Prefer
|
|
29
35
|
* `request()` with a `TypedDocumentNode`.
|
|
30
36
|
*/
|
|
31
|
-
query<T = any>(query: string, variables?: Record<string,
|
|
37
|
+
query<T = any>(query: string, variables?: Record<string, unknown>, options?: {
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
}): Promise<T>;
|
|
32
40
|
}
|
|
41
|
+
export { GraphQLClient as GraphQLTransport };
|
|
33
42
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAWhD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,mBAAmB,YAAK,EAAE,OAAO,EAAE,YAAY;IAUnE,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,UAAU,EAC/B,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,EAChD,SAAS,CAAC,EAAE,UAAU,EACtB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,OAAO,CAAC;IASnB;;;;OAIG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACvC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACrC,OAAO,CAAC,CAAC,CAAC;CA+Cd;AAED,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
* `client.auth.login`, `client.udp.sendActorUpdate`).
|
|
8
8
|
*/
|
|
9
9
|
import { print } from 'graphql';
|
|
10
|
+
import { silentLogger } from './logger.js';
|
|
11
|
+
import { CrowdyError, CrowdyGraphQLError, CrowdyHttpError, CrowdyNetworkError, CrowdyTimeoutError, } from './errors.js';
|
|
10
12
|
export class GraphQLClient {
|
|
11
|
-
constructor(config = {},
|
|
13
|
+
constructor(config = {}, session) {
|
|
12
14
|
this.graphqlEndpoint =
|
|
13
|
-
config.graphqlEndpoint ||
|
|
15
|
+
config.graphqlEndpoint ||
|
|
16
|
+
config.httpUrl ||
|
|
17
|
+
'http://localhost:3000/graphql';
|
|
14
18
|
this.timeout = config.timeout || 60000;
|
|
15
|
-
this.
|
|
19
|
+
this.session = session;
|
|
20
|
+
this.logger = config.logger ?? silentLogger;
|
|
16
21
|
}
|
|
17
22
|
getEndpoint() {
|
|
18
23
|
return this.graphqlEndpoint;
|
|
@@ -21,19 +26,20 @@ export class GraphQLClient {
|
|
|
21
26
|
* Execute a typed GraphQL operation produced by codegen and return the
|
|
22
27
|
* `data` payload. Throws on transport errors, GraphQL errors, or timeouts.
|
|
23
28
|
*/
|
|
24
|
-
async request(document, variables) {
|
|
29
|
+
async request(document, variables, options = {}) {
|
|
25
30
|
const queryStr = print(document);
|
|
26
|
-
return this.query(queryStr, (variables ?? {}));
|
|
31
|
+
return this.query(queryStr, (variables ?? {}), options);
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
34
|
* Internal escape hatch for raw query strings (used by hand-written
|
|
30
35
|
* adapters that haven't migrated to typed documents yet). Prefer
|
|
31
36
|
* `request()` with a `TypedDocumentNode`.
|
|
32
37
|
*/
|
|
33
|
-
async query(query, variables = {}) {
|
|
38
|
+
async query(query, variables = {}, options = {}) {
|
|
34
39
|
const controller = new AbortController();
|
|
35
40
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
36
|
-
const token = this.
|
|
41
|
+
const token = this.session.getToken();
|
|
42
|
+
const signal = options.signal ?? controller.signal;
|
|
37
43
|
try {
|
|
38
44
|
const requestBody = { query, variables };
|
|
39
45
|
const response = await fetch(this.graphqlEndpoint, {
|
|
@@ -43,32 +49,33 @@ export class GraphQLClient {
|
|
|
43
49
|
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
44
50
|
},
|
|
45
51
|
body: JSON.stringify(requestBody),
|
|
46
|
-
signal
|
|
52
|
+
signal,
|
|
47
53
|
});
|
|
48
54
|
clearTimeout(timeoutId);
|
|
49
55
|
if (!response.ok) {
|
|
50
56
|
const errorText = await response.text();
|
|
51
|
-
throw new
|
|
57
|
+
throw new CrowdyHttpError(response.status, errorText);
|
|
52
58
|
}
|
|
53
59
|
const result = await response.json();
|
|
54
60
|
if (result.errors) {
|
|
55
|
-
|
|
56
|
-
const errorMessage = Array.isArray(error.message)
|
|
57
|
-
? error.message.join(', ')
|
|
58
|
-
: error.message;
|
|
59
|
-
throw new Error(errorMessage);
|
|
61
|
+
throw new CrowdyGraphQLError(result.errors);
|
|
60
62
|
}
|
|
61
63
|
return result.data;
|
|
62
64
|
}
|
|
63
65
|
catch (error) {
|
|
64
66
|
clearTimeout(timeoutId);
|
|
65
67
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
66
|
-
throw new
|
|
68
|
+
throw new CrowdyTimeoutError(this.timeout);
|
|
67
69
|
}
|
|
68
|
-
if (error instanceof
|
|
70
|
+
if (error instanceof CrowdyError) {
|
|
69
71
|
throw error;
|
|
70
72
|
}
|
|
71
|
-
|
|
73
|
+
if (error instanceof Error) {
|
|
74
|
+
throw new CrowdyNetworkError(error);
|
|
75
|
+
}
|
|
76
|
+
this.logger.error?.('GraphQL request failed', error);
|
|
77
|
+
throw new CrowdyNetworkError(error);
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
}
|
|
81
|
+
export { GraphQLClient as GraphQLTransport };
|
package/dist/crowdy-client.d.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public surface of the SDK. Construct one `CrowdyClient` per session and
|
|
3
3
|
* access everything via the typed sub-clients (`client.auth`, `client.udp`,
|
|
4
|
-
* `client.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* `client.chunks`, ...).
|
|
5
|
+
*
|
|
6
|
+
* The management/game-api split means CrowdyJS now talks to **two** GraphQL
|
|
7
|
+
* endpoints behind the scenes:
|
|
8
|
+
*
|
|
9
|
+
* - `managementUrl` / `managementGraphqlEndpoint` -> `cks-management-api`
|
|
10
|
+
* used by `auth` (login, register, logout, password / email flows) and
|
|
11
|
+
* `users` (me, updateGamertag, deleteMyAccount). This is also where
|
|
12
|
+
* `game_tokens` are minted.
|
|
13
|
+
*
|
|
14
|
+
* - `httpUrl` / `graphqlEndpoint` -> `cks-game-api`
|
|
15
|
+
* used by every game / world / replication sub-client
|
|
16
|
+
* (`chunks`, `voxels`, `actors`, `teleport`, `state`, `serverStatus`,
|
|
17
|
+
* `udp`). WebSocket subscriptions (`wsUrl`) also target this endpoint.
|
|
18
|
+
*
|
|
19
|
+
* A single `AuthState` is shared across both clients, so once
|
|
20
|
+
* `client.auth.login()` returns, every subsequent SDK call (against either
|
|
21
|
+
* endpoint) carries the Bearer token automatically.
|
|
7
22
|
*/
|
|
23
|
+
import { AuthState } from './auth-state.js';
|
|
24
|
+
import { GraphQLClient } from './client.js';
|
|
25
|
+
import { SubscriptionManager } from './subscriptions.js';
|
|
26
|
+
import type { CrowdyLogger } from './logger.js';
|
|
27
|
+
import type { TokenStore } from './session.js';
|
|
28
|
+
import { WorldClient } from './world.js';
|
|
8
29
|
import { AuthAPI } from './domains/auth.js';
|
|
9
30
|
import { UsersAPI } from './domains/users.js';
|
|
10
|
-
import { OrganizationsAPI } from './domains/organizations.js';
|
|
11
31
|
import { AppsAPI } from './domains/apps.js';
|
|
12
|
-
import { AppAccessAPI } from './domains/appAccess.js';
|
|
13
|
-
import { BillingAPI } from './domains/billing.js';
|
|
14
|
-
import { QuotasAPI } from './domains/quotas.js';
|
|
15
|
-
import { PaymentsAPI } from './domains/payments.js';
|
|
16
32
|
import { ChunksAPI } from './domains/chunks.js';
|
|
17
33
|
import { VoxelsAPI } from './domains/voxels.js';
|
|
18
34
|
import { ActorsAPI } from './domains/actors.js';
|
|
@@ -21,22 +37,46 @@ import { StateAPI } from './domains/state.js';
|
|
|
21
37
|
import { ServerStatusAPI } from './domains/serverStatus.js';
|
|
22
38
|
import { UdpAPI } from './domains/udp.js';
|
|
23
39
|
export interface CrowdyClientConfig {
|
|
40
|
+
/** game-api HTTP root (e.g. `https://dev-game-api.crowdedkingdoms.com`). */
|
|
41
|
+
httpUrl?: string;
|
|
42
|
+
/** game-api WS root. */
|
|
43
|
+
wsUrl?: string;
|
|
44
|
+
/** game-api GraphQL endpoint. Defaults to `${httpUrl}/graphql`. */
|
|
24
45
|
graphqlEndpoint?: string;
|
|
46
|
+
/** game-api WS endpoint. Defaults to `${wsUrl}/graphql`. */
|
|
25
47
|
wsEndpoint?: string;
|
|
48
|
+
/**
|
|
49
|
+
* management-api HTTP root (e.g.
|
|
50
|
+
* `https://dev-management-api.crowdedkingdoms.com`). When set,
|
|
51
|
+
* `client.auth` and `client.users` route here. If left empty the SDK
|
|
52
|
+
* falls back to `httpUrl` for backwards-compatibility with the legacy
|
|
53
|
+
* single-endpoint deployment, but new code should set this explicitly.
|
|
54
|
+
*/
|
|
55
|
+
managementUrl?: string;
|
|
56
|
+
/** management-api GraphQL endpoint. Defaults to `${managementUrl}/graphql`. */
|
|
57
|
+
managementGraphqlEndpoint?: string;
|
|
26
58
|
timeout?: number;
|
|
59
|
+
tokenStore?: TokenStore;
|
|
60
|
+
logger?: CrowdyLogger;
|
|
61
|
+
realtime?: {
|
|
62
|
+
retryAttempts?: number;
|
|
63
|
+
retryInitialDelayMs?: number;
|
|
64
|
+
retryMaxDelayMs?: number;
|
|
65
|
+
waitTimeoutMs?: number;
|
|
66
|
+
};
|
|
27
67
|
}
|
|
28
68
|
export declare class CrowdyClient {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
69
|
+
/** Shared token state for both game-api and management-api requests. */
|
|
70
|
+
readonly session: AuthState;
|
|
71
|
+
/** game-api HTTP client. */
|
|
72
|
+
readonly graphql: GraphQLClient;
|
|
73
|
+
/** game-api WebSocket subscription manager. */
|
|
74
|
+
readonly realtime: SubscriptionManager;
|
|
75
|
+
/** management-api HTTP client. Same `AuthState` as `graphql`. */
|
|
76
|
+
readonly management: GraphQLClient;
|
|
32
77
|
readonly auth: AuthAPI;
|
|
33
78
|
readonly users: UsersAPI;
|
|
34
|
-
readonly orgs: OrganizationsAPI;
|
|
35
79
|
readonly apps: AppsAPI;
|
|
36
|
-
readonly appAccess: AppAccessAPI;
|
|
37
|
-
readonly billing: BillingAPI;
|
|
38
|
-
readonly quotas: QuotasAPI;
|
|
39
|
-
readonly payments: PaymentsAPI;
|
|
40
80
|
readonly chunks: ChunksAPI;
|
|
41
81
|
readonly voxels: VoxelsAPI;
|
|
42
82
|
readonly actors: ActorsAPI;
|
|
@@ -45,7 +85,13 @@ export declare class CrowdyClient {
|
|
|
45
85
|
readonly serverStatus: ServerStatusAPI;
|
|
46
86
|
readonly udp: UdpAPI;
|
|
47
87
|
constructor(config?: CrowdyClientConfig);
|
|
88
|
+
/** Imperatively set the Bearer token (useful for SSO / token rehydrate). */
|
|
89
|
+
setToken(token: string | null): void;
|
|
90
|
+
/** Read the current Bearer token (null if no session). */
|
|
91
|
+
getToken(): string | null;
|
|
92
|
+
world(appId: string): WorldClient;
|
|
48
93
|
/** Closes the WebSocket and clears the in-memory auth token. */
|
|
49
94
|
close(): void;
|
|
50
95
|
}
|
|
96
|
+
export declare function createCrowdyClient(config?: CrowdyClientConfig): CrowdyClient;
|
|
51
97
|
//# sourceMappingURL=crowdy-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"AAAA
|
|
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
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public surface of the SDK. Construct one `CrowdyClient` per session and
|
|
3
3
|
* access everything via the typed sub-clients (`client.auth`, `client.udp`,
|
|
4
|
-
* `client.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* `client.chunks`, ...).
|
|
5
|
+
*
|
|
6
|
+
* The management/game-api split means CrowdyJS now talks to **two** GraphQL
|
|
7
|
+
* endpoints behind the scenes:
|
|
8
|
+
*
|
|
9
|
+
* - `managementUrl` / `managementGraphqlEndpoint` -> `cks-management-api`
|
|
10
|
+
* used by `auth` (login, register, logout, password / email flows) and
|
|
11
|
+
* `users` (me, updateGamertag, deleteMyAccount). This is also where
|
|
12
|
+
* `game_tokens` are minted.
|
|
13
|
+
*
|
|
14
|
+
* - `httpUrl` / `graphqlEndpoint` -> `cks-game-api`
|
|
15
|
+
* used by every game / world / replication sub-client
|
|
16
|
+
* (`chunks`, `voxels`, `actors`, `teleport`, `state`, `serverStatus`,
|
|
17
|
+
* `udp`). WebSocket subscriptions (`wsUrl`) also target this endpoint.
|
|
18
|
+
*
|
|
19
|
+
* A single `AuthState` is shared across both clients, so once
|
|
20
|
+
* `client.auth.login()` returns, every subsequent SDK call (against either
|
|
21
|
+
* endpoint) carries the Bearer token automatically.
|
|
7
22
|
*/
|
|
8
23
|
import { AuthState } from './auth-state.js';
|
|
9
24
|
import { GraphQLClient } from './client.js';
|
|
10
25
|
import { SubscriptionManager } from './subscriptions.js';
|
|
26
|
+
import { WorldClient } from './world.js';
|
|
11
27
|
import { AuthAPI } from './domains/auth.js';
|
|
12
28
|
import { UsersAPI } from './domains/users.js';
|
|
13
|
-
import { OrganizationsAPI } from './domains/organizations.js';
|
|
14
29
|
import { AppsAPI } from './domains/apps.js';
|
|
15
|
-
import { AppAccessAPI } from './domains/appAccess.js';
|
|
16
|
-
import { BillingAPI } from './domains/billing.js';
|
|
17
|
-
import { QuotasAPI } from './domains/quotas.js';
|
|
18
|
-
import { PaymentsAPI } from './domains/payments.js';
|
|
19
30
|
import { ChunksAPI } from './domains/chunks.js';
|
|
20
31
|
import { VoxelsAPI } from './domains/voxels.js';
|
|
21
32
|
import { ActorsAPI } from './domains/actors.js';
|
|
@@ -25,28 +36,59 @@ import { ServerStatusAPI } from './domains/serverStatus.js';
|
|
|
25
36
|
import { UdpAPI } from './domains/udp.js';
|
|
26
37
|
export class CrowdyClient {
|
|
27
38
|
constructor(config = {}) {
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
this.session = new AuthState(config.tokenStore);
|
|
40
|
+
this.graphql = new GraphQLClient({
|
|
41
|
+
httpUrl: config.httpUrl,
|
|
42
|
+
graphqlEndpoint: config.graphqlEndpoint,
|
|
43
|
+
timeout: config.timeout,
|
|
44
|
+
logger: config.logger,
|
|
45
|
+
}, this.session);
|
|
46
|
+
this.realtime = new SubscriptionManager({
|
|
47
|
+
wsUrl: config.wsUrl,
|
|
48
|
+
wsEndpoint: config.wsEndpoint,
|
|
49
|
+
logger: config.logger,
|
|
50
|
+
...config.realtime,
|
|
51
|
+
}, this.session);
|
|
52
|
+
const managementGraphqlEndpoint = config.managementGraphqlEndpoint ??
|
|
53
|
+
(config.managementUrl
|
|
54
|
+
? `${config.managementUrl.replace(/\/$/, '')}/graphql`
|
|
55
|
+
: config.graphqlEndpoint);
|
|
56
|
+
// Management-api client. Falls back to game-api endpoint if the caller
|
|
57
|
+
// hasn't configured `managementUrl` yet (single-endpoint legacy mode).
|
|
58
|
+
this.management = new GraphQLClient({
|
|
59
|
+
httpUrl: config.managementUrl ?? config.httpUrl,
|
|
60
|
+
graphqlEndpoint: managementGraphqlEndpoint,
|
|
61
|
+
timeout: config.timeout,
|
|
62
|
+
logger: config.logger,
|
|
63
|
+
}, this.session);
|
|
64
|
+
this.auth = new AuthAPI(this.management, this.session);
|
|
65
|
+
this.users = new UsersAPI(this.management);
|
|
66
|
+
this.apps = new AppsAPI(this.management);
|
|
67
|
+
this.chunks = new ChunksAPI(this.graphql);
|
|
68
|
+
this.voxels = new VoxelsAPI(this.graphql);
|
|
69
|
+
this.actors = new ActorsAPI(this.graphql);
|
|
70
|
+
this.teleport = new TeleportAPI(this.graphql);
|
|
71
|
+
this.state = new StateAPI(this.graphql);
|
|
72
|
+
this.serverStatus = new ServerStatusAPI(this.graphql);
|
|
73
|
+
this.udp = new UdpAPI(this.graphql, this.realtime);
|
|
74
|
+
}
|
|
75
|
+
/** Imperatively set the Bearer token (useful for SSO / token rehydrate). */
|
|
76
|
+
setToken(token) {
|
|
77
|
+
this.session.setToken(token);
|
|
78
|
+
}
|
|
79
|
+
/** Read the current Bearer token (null if no session). */
|
|
80
|
+
getToken() {
|
|
81
|
+
return this.session.getToken();
|
|
82
|
+
}
|
|
83
|
+
world(appId) {
|
|
84
|
+
return new WorldClient(appId, this.udp);
|
|
46
85
|
}
|
|
47
86
|
/** Closes the WebSocket and clears the in-memory auth token. */
|
|
48
87
|
close() {
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
88
|
+
this.realtime.close();
|
|
89
|
+
this.session.setToken(null);
|
|
51
90
|
}
|
|
52
91
|
}
|
|
92
|
+
export function createCrowdyClient(config = {}) {
|
|
93
|
+
return new CrowdyClient(config);
|
|
94
|
+
}
|
package/dist/domains/apps.d.ts
CHANGED
|
@@ -1,27 +1,55 @@
|
|
|
1
|
-
import type { GraphQLClient } from '../client.js';
|
|
2
|
-
import { type AppQuery, type AppQueryVariables, type AppBySlugQuery, type AppBySlugQueryVariables, type MyAppsQuery, type AppsForOrgQuery, type AppsForOrgQueryVariables, type MarketplaceAppsQuery, type MarketplaceAppsQueryVariables, type CreateAppMutation, type CreateAppMutationVariables, type UpdateAppMutation, type UpdateAppMutationVariables, type ArchiveAppMutationVariables, type SetAppVisibilityMutation, type SetAppVisibilityMutationVariables } from '../generated/graphql.js';
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
2
|
+
* Apps sub-client. Targets `cks-management-api` (where the apps catalog
|
|
3
|
+
* lives). After the DB split each app may be served by its own per-tenant
|
|
4
|
+
* cks-game-api; the marketplace returns `gameApiUrl` for those rows so the
|
|
5
|
+
* caller can build a per-app `CrowdyClient` against the correct endpoint.
|
|
6
|
+
*
|
|
7
|
+
* Typical pattern:
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
+
* const baseClient = createCrowdyClient({
|
|
10
|
+
* managementUrl: 'https://api.example.com',
|
|
11
|
+
* httpUrl: 'https://legacy-game-api.example.com', // pre-split fallback
|
|
12
|
+
* });
|
|
13
|
+
* await baseClient.auth.login({ email, password });
|
|
14
|
+
*
|
|
15
|
+
* const route = await baseClient.apps.routeFor(appId);
|
|
16
|
+
* if (route.splitMode && route.gameApiUrl) {
|
|
17
|
+
* const perAppClient = createCrowdyClient({
|
|
18
|
+
* managementUrl: 'https://api.example.com',
|
|
19
|
+
* httpUrl: route.gameApiUrl,
|
|
20
|
+
* wsUrl: route.gameApiUrl.replace(/^https?/, 'wss'),
|
|
21
|
+
* tokenStore: baseClient.session.tokenStore,
|
|
22
|
+
* });
|
|
23
|
+
* // drive gameplay through perAppClient
|
|
24
|
+
* }
|
|
9
25
|
*/
|
|
26
|
+
import type { GraphQLClient } from '../client.js';
|
|
27
|
+
import { type AppQuery, type AppBySlugQuery, type MyAppsQuery } from '../generated/graphql.js';
|
|
28
|
+
/**
|
|
29
|
+
* Subset of an `App` row that the SDK exposes for routing decisions. The
|
|
30
|
+
* fields are typed loosely as `unknown` because the generated types lag
|
|
31
|
+
* behind the `splitMode` / `gameApiUrl` selection until codegen runs.
|
|
32
|
+
*/
|
|
33
|
+
export interface AppRoute {
|
|
34
|
+
appId: string;
|
|
35
|
+
splitMode: boolean;
|
|
36
|
+
gameApiUrl: string | null;
|
|
37
|
+
}
|
|
10
38
|
export declare class AppsAPI {
|
|
11
|
-
private
|
|
12
|
-
constructor(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
39
|
+
private readonly management;
|
|
40
|
+
constructor(management: GraphQLClient);
|
|
41
|
+
/** Fetch a single app by id. */
|
|
42
|
+
app(appId: string): Promise<AppQuery['app']>;
|
|
43
|
+
/** Fetch by org slug + app slug (marketplace links). */
|
|
44
|
+
appBySlug(orgSlug: string, appSlug: string): Promise<AppBySlugQuery['appBySlug']>;
|
|
45
|
+
/** Apps the caller can play (org membership OR active access). */
|
|
16
46
|
myApps(): Promise<MyAppsQuery['myApps']>;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}>;
|
|
25
|
-
setVisibility(args: SetAppVisibilityMutationVariables): Promise<SetAppVisibilityMutation['setAppVisibility']>;
|
|
47
|
+
/**
|
|
48
|
+
* Convenience: returns just the routing tuple for a given app. If the
|
|
49
|
+
* app row is missing or the API does not expose split-mode fields yet,
|
|
50
|
+
* returns `{ appId, splitMode: false, gameApiUrl: null }` so the caller
|
|
51
|
+
* keeps using the legacy single-endpoint deployment.
|
|
52
|
+
*/
|
|
53
|
+
routeFor(appId: string): Promise<AppRoute>;
|
|
26
54
|
}
|
|
27
55
|
//# sourceMappingURL=apps.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/domains/apps.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/domains/apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAIL,KAAK,QAAQ,EAEb,KAAK,cAAc,EAEnB,KAAK,WAAW,EACjB,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAcD,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,aAAa;IAEtD,gCAAgC;IAC1B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAQlD,wDAAwD;IAClD,SAAS,CACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;IAQvC,kEAAkE;IAC5D,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAQ9C;;;;;OAKG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;CAUjD"}
|