@crowdedkingdoms/crowdyjs 7.1.1 → 8.0.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 (45) hide show
  1. package/MIGRATION.md +46 -0
  2. package/README.md +51 -14
  3. package/dist/client.d.ts +8 -0
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +5 -0
  6. package/dist/crowdy-client.d.ts +7 -0
  7. package/dist/crowdy-client.d.ts.map +1 -1
  8. package/dist/crowdy-client.js +4 -0
  9. package/dist/domains/auth.d.ts +77 -140
  10. package/dist/domains/auth.d.ts.map +1 -1
  11. package/dist/domains/auth.js +81 -178
  12. package/dist/domains/gameModel.d.ts +54 -3
  13. package/dist/domains/gameModel.d.ts.map +1 -1
  14. package/dist/domains/gameModel.js +67 -4
  15. package/dist/domains/host.d.ts +14 -3
  16. package/dist/domains/host.d.ts.map +1 -1
  17. package/dist/domains/host.js +17 -3
  18. package/dist/domains/organizations.d.ts +3 -3
  19. package/dist/domains/organizations.js +3 -3
  20. package/dist/domains/portal.d.ts +43 -1
  21. package/dist/domains/portal.d.ts.map +1 -1
  22. package/dist/domains/portal.js +59 -1
  23. package/dist/domains/quotas.d.ts +1 -1
  24. package/dist/domains/quotas.js +1 -1
  25. package/dist/domains/udp.d.ts +28 -17
  26. package/dist/domains/udp.d.ts.map +1 -1
  27. package/dist/domains/udp.js +28 -17
  28. package/dist/generated/graphql.d.ts +420 -106
  29. package/dist/generated/graphql.d.ts.map +1 -1
  30. package/dist/generated/graphql.js +6 -8
  31. package/dist/index.d.ts +14 -9
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -8
  34. package/dist/lb-cookie-store.d.ts +20 -0
  35. package/dist/lb-cookie-store.d.ts.map +1 -0
  36. package/dist/lb-cookie-store.js +73 -0
  37. package/dist/realtime.d.ts +20 -5
  38. package/dist/realtime.d.ts.map +1 -1
  39. package/dist/realtime.js +38 -0
  40. package/dist/types.d.ts +22 -6
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/world.d.ts +13 -8
  43. package/dist/world.d.ts.map +1 -1
  44. package/dist/world.js +13 -8
  45. package/package.json +6 -4
@@ -101,13 +101,13 @@ export declare class OrganizationsAPI {
101
101
  * Mint a new org API token (for server-side studio backends). Requires the
102
102
  * `manage_tokens` org permission. The plaintext secret is returned **once**.
103
103
  *
104
- * @param input - {@link CreateOrgTokenInput}: `orgId`, `name`, optional
105
- * `permissions` and `expiresAt`.
104
+ * @param input - {@link CreateOrgTokenInput}: `orgId`, optional `label` and
105
+ * `expiresAt`.
106
106
  * @returns The created token including its one-time plaintext secret.
107
107
  */
108
108
  createToken(input: CreateOrgTokenInput): Promise<CreateOrgTokenMutation['createOrgToken']>;
109
109
  /**
110
- * Update an org token's metadata (name / permissions / expiry). Requires the
110
+ * Update an org token's metadata (label / active flag / expiry). Requires the
111
111
  * `manage_tokens` org permission.
112
112
  *
113
113
  * @param orgTokenId - Numeric token id.
@@ -142,8 +142,8 @@ export class OrganizationsAPI {
142
142
  * Mint a new org API token (for server-side studio backends). Requires the
143
143
  * `manage_tokens` org permission. The plaintext secret is returned **once**.
144
144
  *
145
- * @param input - {@link CreateOrgTokenInput}: `orgId`, `name`, optional
146
- * `permissions` and `expiresAt`.
145
+ * @param input - {@link CreateOrgTokenInput}: `orgId`, optional `label` and
146
+ * `expiresAt`.
147
147
  * @returns The created token including its one-time plaintext secret.
148
148
  */
149
149
  async createToken(input) {
@@ -153,7 +153,7 @@ export class OrganizationsAPI {
153
153
  return data.createOrgToken;
154
154
  }
155
155
  /**
156
- * Update an org token's metadata (name / permissions / expiry). Requires the
156
+ * Update an org token's metadata (label / active flag / expiry). Requires the
157
157
  * `manage_tokens` org permission.
158
158
  *
159
159
  * @param orgTokenId - Numeric token id.
@@ -60,6 +60,30 @@ export declare class BrowserSessionPkceStore implements PkceStore {
60
60
  set(state: string, verifier: string): void;
61
61
  remove(state: string): void;
62
62
  }
63
+ export interface PortalConsentState {
64
+ appId: string;
65
+ appName: string | null;
66
+ /** True for first-party/trusted apps (consent always skipped). */
67
+ trusted: boolean;
68
+ alreadyGranted: boolean;
69
+ /** True if the Overworld must show a consent screen before minting a code. */
70
+ consentRequired: boolean;
71
+ }
72
+ export interface AppAuthorizationGrant {
73
+ grantId: string;
74
+ appId: string;
75
+ appName: string | null;
76
+ scopes: string[];
77
+ status: string;
78
+ grantedAt: string;
79
+ revokedAt: string | null;
80
+ }
81
+ /** Thrown by {@link PortalAPI.handleAuthorizeRequest} when the user must consent. */
82
+ export declare class PortalConsentRequiredError extends Error {
83
+ readonly appId: string;
84
+ readonly appName: string | null;
85
+ constructor(appId: string, appName: string | null);
86
+ }
63
87
  export interface BeginEntryParams {
64
88
  /** Target app id (decimal string). */
65
89
  appId: string;
@@ -105,6 +129,21 @@ export declare class PortalAPI {
105
129
  * through the Overworld. Requires the current app token on this session.
106
130
  */
107
131
  refresh(): Promise<AppTokenResponse>;
132
+ /** Whether portaling into an app needs a consent prompt (Overworld side). */
133
+ getConsent(appId: string): Promise<PortalConsentState>;
134
+ /** Record the user's consent for an app (call from the consent screen). */
135
+ authorizeApp(appId: string, scopes?: string[]): Promise<AppAuthorizationGrant>;
136
+ /** Revoke a prior authorization; also revokes the user's live tokens for it. */
137
+ revokeAppAuthorization(appId: string): Promise<boolean>;
138
+ /** The user's active app authorizations ("connected apps"). */
139
+ myAuthorizedApps(): Promise<AppAuthorizationGrant[]>;
140
+ /** Register/update an app's portal client settings (requires manage_apps). */
141
+ setAppClientSettings(input: {
142
+ appId: string;
143
+ redirectUris?: string[];
144
+ clientType?: string;
145
+ launchUrl?: string;
146
+ }): Promise<PortalConsentState>;
108
147
  /**
109
148
  * Destination-game side, step 1: generate a PKCE pair, persist the verifier,
110
149
  * and return the Overworld authorize URL to navigate to. The caller does
@@ -116,7 +155,10 @@ export declare class PortalAPI {
116
155
  * game's params from the URL, mints a code with the session token, and returns
117
156
  * the URL to redirect the player back to (carrying `code` + `state`).
118
157
  */
119
- handleAuthorizeRequest(search?: string): Promise<string>;
158
+ handleAuthorizeRequest(search?: string, options?: {
159
+ grantConsent?: boolean;
160
+ scopes?: string[];
161
+ }): Promise<string>;
120
162
  /**
121
163
  * Destination-game side, step 3: read `code` + `state` from the callback URL,
122
164
  * load the stored verifier, exchange for an app token, and store it. Returns
@@ -1 +1 @@
1
- {"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/domains/portal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../src/domains/portal.ts"],"names":[],"mappings":"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"}
@@ -48,6 +48,20 @@ const MintAppTokenDocument = parse(`mutation MintAppToken($input: MintAppTokenIn
48
48
  const CreatePortalAuthorizationCodeDocument = parse(`mutation CreatePortalAuthorizationCode($input: CreatePortalAuthorizationCodeInput!) { createPortalAuthorizationCode(input: $input) { code redirectUri expiresAt } }`);
49
49
  const ExchangePortalCodeDocument = parse(`mutation ExchangePortalCode($input: ExchangePortalCodeInput!) { exchangePortalCode(input: $input) { ${APP_TOKEN_FIELDS} } }`);
50
50
  const RefreshAppTokenDocument = parse(`mutation RefreshAppToken { refreshAppToken { ${APP_TOKEN_FIELDS} } }`);
51
+ /** Thrown by {@link PortalAPI.handleAuthorizeRequest} when the user must consent. */
52
+ export class PortalConsentRequiredError extends Error {
53
+ constructor(appId, appName) {
54
+ super(`Consent required for app ${appId}`);
55
+ this.appId = appId;
56
+ this.appName = appName;
57
+ this.name = 'PortalConsentRequiredError';
58
+ }
59
+ }
60
+ const PortalConsentDocument = parse(`query PortalConsent($appId: BigInt!) { portalConsent(appId: $appId) { appId appName trusted alreadyGranted consentRequired } }`);
61
+ const AuthorizeAppDocument = parse(`mutation AuthorizeApp($input: AuthorizeAppInput!) { authorizeApp(input: $input) { grantId appId status scopes } }`);
62
+ const RevokeAppAuthorizationDocument = parse(`mutation RevokeAppAuthorization($appId: BigInt!) { revokeAppAuthorization(appId: $appId) }`);
63
+ const MyAuthorizedAppsDocument = parse(`query MyAuthorizedApps { myAuthorizedApps { grantId appId appName scopes status grantedAt revokedAt } }`);
64
+ const SetAppClientSettingsDocument = parse(`mutation SetAppClientSettings($input: SetAppClientSettingsInput!) { setAppClientSettings(input: $input) { appId appName trusted consentRequired } }`);
51
65
  export class PortalAPI {
52
66
  constructor(management, session, pkceStore = new BrowserSessionPkceStore()) {
53
67
  this.management = management;
@@ -97,6 +111,38 @@ export class PortalAPI {
97
111
  this.session.setToken(data.refreshAppToken.token);
98
112
  return data.refreshAppToken;
99
113
  }
114
+ // ----- Consent + connected apps ------------------------------------------
115
+ /** Whether portaling into an app needs a consent prompt (Overworld side). */
116
+ async getConsent(appId) {
117
+ const data = await this.management.request(PortalConsentDocument, { appId });
118
+ return data.portalConsent;
119
+ }
120
+ /** Record the user's consent for an app (call from the consent screen). */
121
+ async authorizeApp(appId, scopes) {
122
+ const data = await this.management.request(AuthorizeAppDocument, {
123
+ input: { appId, scopes },
124
+ });
125
+ return data.authorizeApp;
126
+ }
127
+ /** Revoke a prior authorization; also revokes the user's live tokens for it. */
128
+ async revokeAppAuthorization(appId) {
129
+ const data = await this.management.request(RevokeAppAuthorizationDocument, {
130
+ appId,
131
+ });
132
+ return data.revokeAppAuthorization;
133
+ }
134
+ /** The user's active app authorizations ("connected apps"). */
135
+ async myAuthorizedApps() {
136
+ const data = await this.management.request(MyAuthorizedAppsDocument);
137
+ return data.myAuthorizedApps;
138
+ }
139
+ /** Register/update an app's portal client settings (requires manage_apps). */
140
+ async setAppClientSettings(input) {
141
+ const data = await this.management.request(SetAppClientSettingsDocument, {
142
+ input,
143
+ });
144
+ return data.setAppClientSettings;
145
+ }
100
146
  // ----- Browser PKCE redirect helpers -------------------------------------
101
147
  /**
102
148
  * Destination-game side, step 1: generate a PKCE pair, persist the verifier,
@@ -120,7 +166,7 @@ export class PortalAPI {
120
166
  * game's params from the URL, mints a code with the session token, and returns
121
167
  * the URL to redirect the player back to (carrying `code` + `state`).
122
168
  */
123
- async handleAuthorizeRequest(search) {
169
+ async handleAuthorizeRequest(search, options) {
124
170
  const params = new URLSearchParams(search ?? defaultSearch());
125
171
  const appId = params.get('app_id');
126
172
  const codeChallenge = params.get('code_challenge');
@@ -130,6 +176,18 @@ export class PortalAPI {
130
176
  if (!appId || !codeChallenge || !redirectUri) {
131
177
  throw new Error('authorize request missing app_id, code_challenge, or redirect_uri');
132
178
  }
179
+ // Consent gate: trusted apps + already-granted apps proceed silently. For an
180
+ // untrusted, not-yet-granted app, either record consent (when the user
181
+ // approved on the consent screen) or signal the caller to show one.
182
+ const consent = await this.getConsent(appId);
183
+ if (consent.consentRequired) {
184
+ if (options?.grantConsent) {
185
+ await this.authorizeApp(appId, options.scopes);
186
+ }
187
+ else {
188
+ throw new PortalConsentRequiredError(appId, consent.appName);
189
+ }
190
+ }
133
191
  const result = await this.createAuthorizationCode({
134
192
  appId,
135
193
  codeChallenge,
@@ -47,7 +47,7 @@ export declare class QuotasAPI {
47
47
  * Create or update a quota at an org or app scope. Requires `manage_quotas`
48
48
  * (super-admin for platform-global quotas).
49
49
  *
50
- * @param input - {@link SetQuotaInput}: scope ids, `metric`, and `limit`.
50
+ * @param input - {@link SetQuotaInput}: scope ids, `metric`, and `limitValue`.
51
51
  * @returns The created/updated quota.
52
52
  */
53
53
  set(input: SetQuotaInput): Promise<SetQuotaMutation['setQuota']>;
@@ -57,7 +57,7 @@ export class QuotasAPI {
57
57
  * Create or update a quota at an org or app scope. Requires `manage_quotas`
58
58
  * (super-admin for platform-global quotas).
59
59
  *
60
- * @param input - {@link SetQuotaInput}: scope ids, `metric`, and `limit`.
60
+ * @param input - {@link SetQuotaInput}: scope ids, `metric`, and `limitValue`.
61
61
  * @returns The created/updated quota.
62
62
  */
63
63
  async set(input) {
@@ -77,10 +77,13 @@ export declare class UdpAPI {
77
77
  /**
78
78
  * Send an actor (player/NPC) state update for spatial replication to nearby
79
79
  * chunks. Fire-and-forget; opens a UDP proxy session automatically if none
80
- * exists. The applied echo (`ActorUpdateResponse`) and any failure
81
- * (`GenericErrorResponse`) arrive asynchronously on {@link subscribe},
82
- * correlated by `sequenceNumber`; use {@link sendActorUpdateAndWait} to await
83
- * that echo inline.
80
+ * exists. There is no separate per-request response: the server fans the
81
+ * update out to every client in the target chunk **including the sender**, so
82
+ * your own applied update comes back as an `ActorUpdateNotification` carrying
83
+ * the same `sequenceNumber` (the legacy `ActorUpdateResponse` type is never
84
+ * emitted). Failures arrive as a `GenericErrorResponse`; both are delivered
85
+ * asynchronously on {@link subscribe} and correlated by `sequenceNumber`. Use
86
+ * {@link sendActorUpdateAndWait} to await that self-notification inline.
84
87
  *
85
88
  * @param input - {@link ActorUpdateRequestInput}:
86
89
  * - `appId` — owning app id (`BigInt` as a decimal string).
@@ -106,17 +109,19 @@ export declare class UdpAPI {
106
109
  /**
107
110
  * Send an actor update and wait for the server's applied echo. Allocates a
108
111
  * `sequenceNumber` when `input.sequenceNumber` is omitted, registers the wait
109
- * *before* sending, then resolves with the matching `ActorUpdateResponse`.
110
- * Requires an active {@link subscribe} so the echo can be delivered over the
111
- * shared WebSocket.
112
+ * *before* sending, then resolves with the matching notification. Because the
113
+ * server includes the sender in the chunk fan-out, the echo is your own
114
+ * `ActorUpdateNotification` with the same `sequenceNumber` (there is no
115
+ * `ActorUpdateResponse` on the wire). Requires an active {@link subscribe} so
116
+ * the self-notification can be delivered over the shared WebSocket.
112
117
  *
113
118
  * @param input - {@link ActorUpdateRequestInput} (see {@link sendActorUpdate}
114
119
  * for field units/encoding). Omit `sequenceNumber` to let the SDK allocate
115
120
  * one.
116
121
  * @param options - `timeoutMs`: how long to wait for the echo, in
117
122
  * milliseconds; defaults to the client's realtime `waitTimeoutMs` (5000).
118
- * @returns The correlated {@link SpatialNotification} (the `ActorUpdateResponse`
119
- * echo).
123
+ * @returns The correlated {@link SpatialNotification} (your own
124
+ * `ActorUpdateNotification` self-echo).
120
125
  * @throws {CrowdyGraphQLError} if the underlying send is rejected.
121
126
  * @throws {CrowdyTimeoutError} if the HTTP send leg exceeds the client's
122
127
  * request timeout.
@@ -141,10 +146,13 @@ export declare class UdpAPI {
141
146
  }): Promise<SpatialNotification>;
142
147
  /**
143
148
  * Send a single voxel (block) update for spatial replication to nearby
144
- * chunks. Fire-and-forget; opens a UDP proxy session automatically. The
145
- * applied echo (`VoxelUpdateResponse`) and failures (`GenericErrorResponse`)
146
- * arrive asynchronously on {@link subscribe}; use
147
- * {@link sendVoxelUpdateAndWait} to await the echo inline.
149
+ * chunks. Fire-and-forget; opens a UDP proxy session automatically. There is
150
+ * no separate per-request response: the change fans out to nearby clients
151
+ * **including the sender** as a `VoxelUpdateNotification` carrying the same
152
+ * `sequenceNumber` (the legacy `VoxelUpdateResponse` type is never emitted).
153
+ * Failures arrive as a `GenericErrorResponse`; both are delivered
154
+ * asynchronously on {@link subscribe}. Use {@link sendVoxelUpdateAndWait} to
155
+ * await the self-notification inline.
148
156
  *
149
157
  * @param input - {@link VoxelUpdateRequestInput}:
150
158
  * - `appId` — owning app id (`BigInt` as a decimal string).
@@ -166,15 +174,18 @@ export declare class UdpAPI {
166
174
  */
167
175
  sendVoxelUpdate(input: SendVoxelUpdateMutationVariables['input']): Promise<boolean>;
168
176
  /**
169
- * Send a voxel update and wait for the server's applied `VoxelUpdateResponse`
170
- * echo. Allocates a `sequenceNumber` when omitted and requires an active
171
- * {@link subscribe}.
177
+ * Send a voxel update and wait for the server's applied echo. Allocates a
178
+ * `sequenceNumber` when omitted and requires an active {@link subscribe}.
179
+ * Because the server includes the sender in the chunk fan-out, the echo is
180
+ * your own `VoxelUpdateNotification` with the same `sequenceNumber` (there is
181
+ * no `VoxelUpdateResponse` on the wire).
172
182
  *
173
183
  * @param input - {@link VoxelUpdateRequestInput} (see {@link sendVoxelUpdate}
174
184
  * for field units/encoding).
175
185
  * @param options - `timeoutMs`: echo wait in milliseconds; defaults to the
176
186
  * client's realtime `waitTimeoutMs` (5000).
177
- * @returns The correlated {@link SpatialNotification} (`VoxelUpdateResponse`).
187
+ * @returns The correlated {@link SpatialNotification} (your own
188
+ * `VoxelUpdateNotification` self-echo).
178
189
  * @throws {CrowdyGraphQLError} if the underlying send is rejected.
179
190
  * @throws {CrowdyTimeoutError} if the HTTP send leg times out.
180
191
  * @throws {CrowdyRealtimeError} on echo timeout
@@ -1 +1 @@
1
- {"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../../src/domains/udp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"udp.d.ts","sourceRoot":"","sources":["../../src/domains/udp.ts"],"names":[],"mappings":"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"}
@@ -85,10 +85,13 @@ export class UdpAPI {
85
85
  /**
86
86
  * Send an actor (player/NPC) state update for spatial replication to nearby
87
87
  * chunks. Fire-and-forget; opens a UDP proxy session automatically if none
88
- * exists. The applied echo (`ActorUpdateResponse`) and any failure
89
- * (`GenericErrorResponse`) arrive asynchronously on {@link subscribe},
90
- * correlated by `sequenceNumber`; use {@link sendActorUpdateAndWait} to await
91
- * that echo inline.
88
+ * exists. There is no separate per-request response: the server fans the
89
+ * update out to every client in the target chunk **including the sender**, so
90
+ * your own applied update comes back as an `ActorUpdateNotification` carrying
91
+ * the same `sequenceNumber` (the legacy `ActorUpdateResponse` type is never
92
+ * emitted). Failures arrive as a `GenericErrorResponse`; both are delivered
93
+ * asynchronously on {@link subscribe} and correlated by `sequenceNumber`. Use
94
+ * {@link sendActorUpdateAndWait} to await that self-notification inline.
92
95
  *
93
96
  * @param input - {@link ActorUpdateRequestInput}:
94
97
  * - `appId` — owning app id (`BigInt` as a decimal string).
@@ -117,17 +120,19 @@ export class UdpAPI {
117
120
  /**
118
121
  * Send an actor update and wait for the server's applied echo. Allocates a
119
122
  * `sequenceNumber` when `input.sequenceNumber` is omitted, registers the wait
120
- * *before* sending, then resolves with the matching `ActorUpdateResponse`.
121
- * Requires an active {@link subscribe} so the echo can be delivered over the
122
- * shared WebSocket.
123
+ * *before* sending, then resolves with the matching notification. Because the
124
+ * server includes the sender in the chunk fan-out, the echo is your own
125
+ * `ActorUpdateNotification` with the same `sequenceNumber` (there is no
126
+ * `ActorUpdateResponse` on the wire). Requires an active {@link subscribe} so
127
+ * the self-notification can be delivered over the shared WebSocket.
123
128
  *
124
129
  * @param input - {@link ActorUpdateRequestInput} (see {@link sendActorUpdate}
125
130
  * for field units/encoding). Omit `sequenceNumber` to let the SDK allocate
126
131
  * one.
127
132
  * @param options - `timeoutMs`: how long to wait for the echo, in
128
133
  * milliseconds; defaults to the client's realtime `waitTimeoutMs` (5000).
129
- * @returns The correlated {@link SpatialNotification} (the `ActorUpdateResponse`
130
- * echo).
134
+ * @returns The correlated {@link SpatialNotification} (your own
135
+ * `ActorUpdateNotification` self-echo).
131
136
  * @throws {CrowdyGraphQLError} if the underlying send is rejected.
132
137
  * @throws {CrowdyTimeoutError} if the HTTP send leg exceeds the client's
133
138
  * request timeout.
@@ -155,10 +160,13 @@ export class UdpAPI {
155
160
  }
156
161
  /**
157
162
  * Send a single voxel (block) update for spatial replication to nearby
158
- * chunks. Fire-and-forget; opens a UDP proxy session automatically. The
159
- * applied echo (`VoxelUpdateResponse`) and failures (`GenericErrorResponse`)
160
- * arrive asynchronously on {@link subscribe}; use
161
- * {@link sendVoxelUpdateAndWait} to await the echo inline.
163
+ * chunks. Fire-and-forget; opens a UDP proxy session automatically. There is
164
+ * no separate per-request response: the change fans out to nearby clients
165
+ * **including the sender** as a `VoxelUpdateNotification` carrying the same
166
+ * `sequenceNumber` (the legacy `VoxelUpdateResponse` type is never emitted).
167
+ * Failures arrive as a `GenericErrorResponse`; both are delivered
168
+ * asynchronously on {@link subscribe}. Use {@link sendVoxelUpdateAndWait} to
169
+ * await the self-notification inline.
162
170
  *
163
171
  * @param input - {@link VoxelUpdateRequestInput}:
164
172
  * - `appId` — owning app id (`BigInt` as a decimal string).
@@ -183,15 +191,18 @@ export class UdpAPI {
183
191
  return data.sendVoxelUpdate;
184
192
  }
185
193
  /**
186
- * Send a voxel update and wait for the server's applied `VoxelUpdateResponse`
187
- * echo. Allocates a `sequenceNumber` when omitted and requires an active
188
- * {@link subscribe}.
194
+ * Send a voxel update and wait for the server's applied echo. Allocates a
195
+ * `sequenceNumber` when omitted and requires an active {@link subscribe}.
196
+ * Because the server includes the sender in the chunk fan-out, the echo is
197
+ * your own `VoxelUpdateNotification` with the same `sequenceNumber` (there is
198
+ * no `VoxelUpdateResponse` on the wire).
189
199
  *
190
200
  * @param input - {@link VoxelUpdateRequestInput} (see {@link sendVoxelUpdate}
191
201
  * for field units/encoding).
192
202
  * @param options - `timeoutMs`: echo wait in milliseconds; defaults to the
193
203
  * client's realtime `waitTimeoutMs` (5000).
194
- * @returns The correlated {@link SpatialNotification} (`VoxelUpdateResponse`).
204
+ * @returns The correlated {@link SpatialNotification} (your own
205
+ * `VoxelUpdateNotification` self-echo).
195
206
  * @throws {CrowdyGraphQLError} if the underlying send is rejected.
196
207
  * @throws {CrowdyTimeoutError} if the HTTP send leg times out.
197
208
  * @throws {CrowdyRealtimeError} on echo timeout