@crowdedkingdomstudios/crowdyjs 5.2.0 → 5.2.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/MIGRATION.md +22 -0
- package/dist/client.d.ts +98 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +74 -5
- package/dist/crowdy-client.d.ts +31 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +8 -0
- package/dist/domains/actors.d.ts +87 -4
- package/dist/domains/actors.d.ts.map +1 -1
- package/dist/domains/actors.js +87 -4
- package/dist/domains/apps.d.ts +95 -41
- package/dist/domains/apps.d.ts.map +1 -1
- package/dist/domains/apps.js +80 -33
- package/dist/domains/auth.d.ts +139 -19
- package/dist/domains/auth.d.ts.map +1 -1
- package/dist/domains/auth.js +137 -17
- package/dist/domains/channels.d.ts +264 -5
- package/dist/domains/channels.d.ts.map +1 -1
- package/dist/domains/channels.js +264 -5
- package/dist/domains/chunks.d.ts +116 -3
- package/dist/domains/chunks.d.ts.map +1 -1
- package/dist/domains/chunks.js +116 -3
- package/dist/domains/gameModel.d.ts +412 -6
- package/dist/domains/gameModel.d.ts.map +1 -1
- package/dist/domains/gameModel.js +412 -6
- package/dist/domains/platform.d.ts +36 -20
- package/dist/domains/platform.d.ts.map +1 -1
- package/dist/domains/platform.js +29 -18
- package/dist/domains/serverStatus.d.ts +74 -6
- package/dist/domains/serverStatus.d.ts.map +1 -1
- package/dist/domains/serverStatus.js +74 -6
- package/dist/domains/state.d.ts +50 -2
- package/dist/domains/state.d.ts.map +1 -1
- package/dist/domains/state.js +50 -2
- package/dist/domains/teams.d.ts +263 -5
- package/dist/domains/teams.d.ts.map +1 -1
- package/dist/domains/teams.js +263 -5
- package/dist/domains/teleport.d.ts +30 -2
- package/dist/domains/teleport.d.ts.map +1 -1
- package/dist/domains/teleport.js +30 -2
- package/dist/domains/udp.d.ts +341 -5
- package/dist/domains/udp.d.ts.map +1 -1
- package/dist/domains/udp.js +341 -5
- package/dist/domains/users.d.ts +42 -11
- package/dist/domains/users.d.ts.map +1 -1
- package/dist/domains/users.js +41 -10
- package/dist/domains/voxels.d.ts +107 -2
- package/dist/domains/voxels.d.ts.map +1 -1
- package/dist/domains/voxels.js +107 -2
- package/dist/errors.d.ts +116 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +100 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/realtime.d.ts +226 -0
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +90 -0
- package/dist/session.d.ts +46 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +35 -0
- package/dist/types.d.ts +429 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +53 -0
- package/dist/utils.d.ts +86 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +86 -0
- package/dist/world.d.ts +192 -0
- package/dist/world.d.ts.map +1 -1
- package/dist/world.js +170 -0
- package/package.json +1 -1
package/dist/domains/channels.js
CHANGED
|
@@ -1,92 +1,351 @@
|
|
|
1
1
|
import { MyChannelsDocument, ChannelsDocument, ChannelDocument, ChannelMembersDocument, ChannelRolesDocument, ChannelPolicyDocument, SetChannelPolicyDocument, CreateChannelDocument, UpdateChannelDocument, DeleteChannelDocument, JoinChannelDocument, RequestToJoinChannelDocument, LeaveChannelDocument, AddChannelMemberDocument, RemoveChannelMemberDocument, SetChannelMemberRolesDocument, CreateChannelRoleDocument, UpdateChannelRoleDocument, DeleteChannelRoleDocument, } from '../generated/graphql.js';
|
|
2
2
|
/**
|
|
3
|
-
* Channels: app-scoped
|
|
4
|
-
*
|
|
5
|
-
* CRUD/membership runs over the game-api GraphQL endpoint; publishing and
|
|
6
|
-
* receiving channel messages happens over the realtime UDP path (`client.udp`).
|
|
3
|
+
* Channels: app-scoped, location-independent pub/sub messaging groups on the
|
|
4
|
+
* **game-api**. Exposed as `client.channels`.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
6
|
+
* A channel is a named subscriber set with role-gated messaging, built on the
|
|
7
|
+
* same generic groups subsystem as Teams (`group_type='channel'`). The methods
|
|
8
|
+
* here manage a channel's lifecycle and configuration — creating channels,
|
|
9
|
+
* listing/fetching them, managing membership (join/leave/add/remove), roles,
|
|
10
|
+
* and the per-app channel policy — all over the game-api GraphQL endpoint.
|
|
11
|
+
*
|
|
12
|
+
* Realtime message delivery is a **separate** path: publish to a channel with
|
|
13
|
+
* `client.udp.sendChannelMessage(...)` over UDP. That call requires the
|
|
14
|
+
* channel's `send_messages` permission and fans the payload out to every
|
|
15
|
+
* active member (as a `ChannelMessageNotification` on `client.udp`
|
|
16
|
+
* notifications) rather than chunk-routing it. The methods on this class never
|
|
17
|
+
* carry message payloads — they only manage who belongs to a channel and what
|
|
18
|
+
* each member may do.
|
|
19
|
+
*
|
|
20
|
+
* `BigInt` ids (`appId`, `groupId`, `userId`, `groupRoleId`) are sent and
|
|
21
|
+
* received as decimal strings.
|
|
22
|
+
*
|
|
23
|
+
* Every method requires an authenticated session (a Bearer token set via
|
|
24
|
+
* `client.auth.login()` or `client.setToken()`) and the caller must be
|
|
25
|
+
* entitled to the target app; membership/role/policy mutations additionally
|
|
26
|
+
* require a specific channel permission (e.g. `manage_group`, `manage_members`,
|
|
27
|
+
* `manage_roles`) or app-admin (`manage_apps`). Failures throw
|
|
28
|
+
* {@link CrowdyGraphQLError} carrying a stable `extensions.code` such as
|
|
29
|
+
* `UNAUTHENTICATED`, `SCOPE_MISSING`, or `FORBIDDEN`.
|
|
9
30
|
*/
|
|
10
31
|
export class ChannelsAPI {
|
|
11
32
|
constructor(gql) {
|
|
12
33
|
this.gql = gql;
|
|
13
34
|
}
|
|
14
35
|
// -- Queries --------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* List the caller's own channels in an app, each with the caller's roles and
|
|
38
|
+
* effective channel permissions (e.g. whether they hold `send_messages`). Use
|
|
39
|
+
* this to discover which channels the current user can read and post in.
|
|
40
|
+
*
|
|
41
|
+
* @param appId - The app (tenant) to list the caller's channels within, as a
|
|
42
|
+
* decimal `BigInt` string.
|
|
43
|
+
* @returns One {@link GroupMembership} per channel the caller belongs to
|
|
44
|
+
* (the channel {@link Group}, the caller's {@link GroupRole}s, their
|
|
45
|
+
* effective permission keys, and the join time).
|
|
46
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` if there is no valid token,
|
|
47
|
+
* or `SCOPE_MISSING` / `FORBIDDEN` if the caller isn't entitled to the app.
|
|
48
|
+
*/
|
|
15
49
|
async mine(appId) {
|
|
16
50
|
const data = await this.gql.request(MyChannelsDocument, { appId });
|
|
17
51
|
return data.myChannels;
|
|
18
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* List all active channels in an app — not just the caller's. Use
|
|
55
|
+
* {@link mine} instead when you only want the channels the caller belongs to.
|
|
56
|
+
*
|
|
57
|
+
* @param appId - The app (tenant) whose channels to list, as a decimal
|
|
58
|
+
* `BigInt` string.
|
|
59
|
+
* @returns Every active channel in the app as {@link Group} records.
|
|
60
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED`, or `SCOPE_MISSING` /
|
|
61
|
+
* `FORBIDDEN` if the caller isn't entitled to the app.
|
|
62
|
+
*/
|
|
19
63
|
async list(appId) {
|
|
20
64
|
const data = await this.gql.request(ChannelsDocument, { appId });
|
|
21
65
|
return data.channels;
|
|
22
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Fetch a single channel by its group id.
|
|
69
|
+
*
|
|
70
|
+
* @param groupId - The channel's group id, as a decimal `BigInt` string.
|
|
71
|
+
* @returns The channel as a {@link Group}.
|
|
72
|
+
* @throws {CrowdyGraphQLError} if the id does not resolve to a channel (e.g.
|
|
73
|
+
* it is a team, or does not exist), or `UNAUTHENTICATED` / `FORBIDDEN` if
|
|
74
|
+
* the caller isn't entitled to the app.
|
|
75
|
+
*/
|
|
23
76
|
async get(groupId) {
|
|
24
77
|
const data = await this.gql.request(ChannelDocument, { groupId });
|
|
25
78
|
return data.channel;
|
|
26
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* List a channel's members — its subscriber set, including pending join
|
|
82
|
+
* requests — each with their membership status and roles.
|
|
83
|
+
*
|
|
84
|
+
* @param groupId - The channel whose members to list, as a decimal `BigInt`
|
|
85
|
+
* string.
|
|
86
|
+
* @returns The channel's members as {@link GroupMember} records.
|
|
87
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN` if the caller
|
|
88
|
+
* isn't entitled to the channel's app.
|
|
89
|
+
*/
|
|
27
90
|
async members(groupId) {
|
|
28
91
|
const data = await this.gql.request(ChannelMembersDocument, { groupId });
|
|
29
92
|
return data.channelMembers;
|
|
30
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* List a channel's roles, including the system `leader` role and any default
|
|
96
|
+
* `member` role (which typically grants `send_messages`).
|
|
97
|
+
*
|
|
98
|
+
* @param groupId - The channel whose roles to list, as a decimal `BigInt`
|
|
99
|
+
* string.
|
|
100
|
+
* @returns The channel's roles as {@link GroupRole} records, each with its
|
|
101
|
+
* granted permission keys.
|
|
102
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN` if the caller
|
|
103
|
+
* isn't entitled to the channel's app.
|
|
104
|
+
*/
|
|
31
105
|
async roles(groupId) {
|
|
32
106
|
const data = await this.gql.request(ChannelRolesDocument, { groupId });
|
|
33
107
|
return data.channelRoles;
|
|
34
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Read an app's current channel policy: who may create channels and the
|
|
111
|
+
* default membership policy applied to new channels. Falls back to app
|
|
112
|
+
* defaults when unset.
|
|
113
|
+
*
|
|
114
|
+
* @param appId - The app (tenant) whose channel policy to read, as a decimal
|
|
115
|
+
* `BigInt` string.
|
|
116
|
+
* @returns The effective {@link AppGroupPolicy} for channels in the app
|
|
117
|
+
* (creation policy, default membership policy, and any member/group caps).
|
|
118
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN` if the caller
|
|
119
|
+
* isn't entitled to the app.
|
|
120
|
+
*/
|
|
35
121
|
async policy(appId) {
|
|
36
122
|
const data = await this.gql.request(ChannelPolicyDocument, { appId });
|
|
37
123
|
return data.channelPolicy;
|
|
38
124
|
}
|
|
39
125
|
// -- Channel mutations ----------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Create a channel in an app. Whether the caller may create one is governed
|
|
128
|
+
* by the per-app channel creation policy (`admin` | `member` | `anyone`).
|
|
129
|
+
* The caller becomes the owner with a system `leader` role. When
|
|
130
|
+
* `input.membersCanSend` is true (the default) a default `member` role
|
|
131
|
+
* granting `send_messages` is created and auto-assigned to joiners (an open
|
|
132
|
+
* chat channel); when false, only roles you explicitly grant may post (an
|
|
133
|
+
* announce / read-only channel).
|
|
134
|
+
*
|
|
135
|
+
* @param input - {@link CreateChannelInput}: the owning `appId`, the channel
|
|
136
|
+
* `name` (max 128 chars, unique per app + type), and optional
|
|
137
|
+
* `description`, `membershipPolicy` (`open` | `request` | `invite` |
|
|
138
|
+
* `admin`; defaults to the app policy), and `membersCanSend` flag.
|
|
139
|
+
* @returns The newly created channel as a {@link Group}.
|
|
140
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` (e.g. name too long or a
|
|
141
|
+
* duplicate name), `FORBIDDEN` if the channel policy disallows creation, or
|
|
142
|
+
* `UNAUTHENTICATED`.
|
|
143
|
+
*/
|
|
40
144
|
async create(input) {
|
|
41
145
|
const data = await this.gql.request(CreateChannelDocument, { input });
|
|
42
146
|
return data.createChannel;
|
|
43
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Update a channel's name, description, and/or membership policy. Only the
|
|
150
|
+
* fields present on `input` change; omitted fields are left as-is. Requires
|
|
151
|
+
* the `manage_group` channel permission (app admins bypass).
|
|
152
|
+
*
|
|
153
|
+
* @param input - {@link UpdateChannelInput}: the `groupId` plus the fields to
|
|
154
|
+
* change — `name` (max 128 chars), `description`, and/or `membershipPolicy`
|
|
155
|
+
* (`open` | `request` | `invite` | `admin`).
|
|
156
|
+
* @returns The updated channel as a {@link Group}.
|
|
157
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
158
|
+
* lacks `manage_group`, `BAD_USER_INPUT` on a validation failure, or
|
|
159
|
+
* `UNAUTHENTICATED`.
|
|
160
|
+
*/
|
|
44
161
|
async update(input) {
|
|
45
162
|
const data = await this.gql.request(UpdateChannelDocument, { input });
|
|
46
163
|
return data.updateChannel;
|
|
47
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Delete a channel. Requires the `manage_group` channel permission (app
|
|
167
|
+
* admins bypass). **Destructive**: cascades to the channel's members and
|
|
168
|
+
* roles and notifies Buddy servers to tear down message routing for the
|
|
169
|
+
* channel.
|
|
170
|
+
*
|
|
171
|
+
* @param groupId - The channel to delete, as a decimal `BigInt` string.
|
|
172
|
+
* @returns `true` on success.
|
|
173
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
174
|
+
* lacks `manage_group`, or `UNAUTHENTICATED`.
|
|
175
|
+
*/
|
|
48
176
|
async remove(groupId) {
|
|
49
177
|
const data = await this.gql.request(DeleteChannelDocument, { groupId });
|
|
50
178
|
return data.deleteChannel;
|
|
51
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Set who may create channels in an app and the default membership policy
|
|
182
|
+
* for new channels. Requires app-admin (`manage_apps`). Affects future
|
|
183
|
+
* channel creation only — existing channels are unchanged.
|
|
184
|
+
*
|
|
185
|
+
* @param input - {@link SetChannelPolicyInput}: the `appId`, the
|
|
186
|
+
* `creationPolicy` (`admin` | `member` | `anyone`), the
|
|
187
|
+
* `defaultMembershipPolicy` (`open` | `request` | `invite` | `admin`), and
|
|
188
|
+
* optional `maxMembers` / `maxGroupsPerUser` caps (`null` = unlimited).
|
|
189
|
+
* @returns The updated {@link AppGroupPolicy}.
|
|
190
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
191
|
+
* isn't app-admin, `BAD_USER_INPUT` on an invalid policy value, or
|
|
192
|
+
* `UNAUTHENTICATED`.
|
|
193
|
+
*/
|
|
52
194
|
async setPolicy(input) {
|
|
53
195
|
const data = await this.gql.request(SetChannelPolicyDocument, { input });
|
|
54
196
|
return data.setChannelPolicy;
|
|
55
197
|
}
|
|
56
198
|
// -- Membership mutations -------------------------------------------------
|
|
199
|
+
/**
|
|
200
|
+
* Join a channel as the caller (subscribe to it). Honors the channel's
|
|
201
|
+
* membership policy: `open` → active immediately; `request` → pending until
|
|
202
|
+
* a manager approves; `invite` / `admin` → rejected. On becoming active,
|
|
203
|
+
* Buddy is notified with the caller's effective send permission so message
|
|
204
|
+
* routing starts.
|
|
205
|
+
*
|
|
206
|
+
* @param groupId - The channel to join, as a decimal `BigInt` string.
|
|
207
|
+
* @returns The caller's {@link GroupMember} record; its `status` reflects
|
|
208
|
+
* `active` vs. `pending`.
|
|
209
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` if the membership policy rejects
|
|
210
|
+
* the join, or `UNAUTHENTICATED`.
|
|
211
|
+
*/
|
|
57
212
|
async join(groupId) {
|
|
58
213
|
const data = await this.gql.request(JoinChannelDocument, { groupId });
|
|
59
214
|
return data.joinChannel;
|
|
60
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Request to join a request-only channel, creating a pending membership a
|
|
218
|
+
* manager can later approve via {@link addMember}. Behaves identically to
|
|
219
|
+
* {@link join}; it exists as a clearer name for request-policy UIs.
|
|
220
|
+
*
|
|
221
|
+
* @param groupId - The request-only channel to request to join, as a decimal
|
|
222
|
+
* `BigInt` string.
|
|
223
|
+
* @returns The caller's pending {@link GroupMember} record.
|
|
224
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` if the membership policy rejects
|
|
225
|
+
* the request, or `UNAUTHENTICATED`.
|
|
226
|
+
*/
|
|
61
227
|
async requestToJoin(groupId) {
|
|
62
228
|
const data = await this.gql.request(RequestToJoinChannelDocument, { groupId });
|
|
63
229
|
return data.requestToJoinChannel;
|
|
64
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Leave a channel (unsubscribe the caller). Notifies Buddy to stop routing
|
|
233
|
+
* messages to the caller.
|
|
234
|
+
*
|
|
235
|
+
* @param groupId - The channel to leave, as a decimal `BigInt` string.
|
|
236
|
+
* @returns `true` if a membership was removed (`false` if the caller wasn't
|
|
237
|
+
* a member).
|
|
238
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED`.
|
|
239
|
+
*/
|
|
65
240
|
async leave(groupId) {
|
|
66
241
|
const data = await this.gql.request(LeaveChannelDocument, { groupId });
|
|
67
242
|
return data.leaveChannel;
|
|
68
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Add a user to a channel, or approve their pending join request (upserts
|
|
246
|
+
* the membership to `active`). Requires the `manage_members` channel
|
|
247
|
+
* permission (app admins bypass). Auto-assigns the channel's default role if
|
|
248
|
+
* configured and notifies Buddy with the member's effective send permission.
|
|
249
|
+
*
|
|
250
|
+
* @param groupId - The channel to add the user to, as a decimal `BigInt`
|
|
251
|
+
* string.
|
|
252
|
+
* @param userId - The user to add or approve, as a decimal `BigInt` string.
|
|
253
|
+
* @returns The added/approved {@link GroupMember} record.
|
|
254
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
255
|
+
* lacks `manage_members`, or `UNAUTHENTICATED`.
|
|
256
|
+
*/
|
|
69
257
|
async addMember(groupId, userId) {
|
|
70
258
|
const data = await this.gql.request(AddChannelMemberDocument, { groupId, userId });
|
|
71
259
|
return data.addChannelMember;
|
|
72
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Remove a member from a channel. Requires the `manage_members` channel
|
|
263
|
+
* permission, except that any member may remove themselves (pass their own
|
|
264
|
+
* `userId`). Notifies Buddy to stop routing messages to the removed member.
|
|
265
|
+
*
|
|
266
|
+
* @param groupId - The channel to remove the user from, as a decimal
|
|
267
|
+
* `BigInt` string.
|
|
268
|
+
* @param userId - The user to remove; may be the caller's own id to
|
|
269
|
+
* self-remove. Decimal `BigInt` string.
|
|
270
|
+
* @returns `true` if a membership was removed.
|
|
271
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` when removing
|
|
272
|
+
* another member without `manage_members`, or `UNAUTHENTICATED`.
|
|
273
|
+
*/
|
|
73
274
|
async removeMember(groupId, userId) {
|
|
74
275
|
const data = await this.gql.request(RemoveChannelMemberDocument, { groupId, userId });
|
|
75
276
|
return data.removeChannelMember;
|
|
76
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* Replace a member's channel roles with the given set. This is **not
|
|
280
|
+
* additive** — roles not listed are removed. Requires the `manage_roles`
|
|
281
|
+
* channel permission (app admins bypass). Re-pushes the member's effective
|
|
282
|
+
* send permission to Buddy so their ability to post updates immediately.
|
|
283
|
+
*
|
|
284
|
+
* @param input - {@link SetMemberRolesInput}: the `groupId`, the target
|
|
285
|
+
* `userId`, and `roleIds` — the complete set of channel role ids the member
|
|
286
|
+
* should have (ids that are unknown or belong to another group are
|
|
287
|
+
* ignored).
|
|
288
|
+
* @returns The updated {@link GroupMember} record with its new roles.
|
|
289
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
290
|
+
* lacks `manage_roles`, or `UNAUTHENTICATED`.
|
|
291
|
+
*/
|
|
77
292
|
async setMemberRoles(input) {
|
|
78
293
|
const data = await this.gql.request(SetChannelMemberRolesDocument, { input });
|
|
79
294
|
return data.setChannelMemberRoles;
|
|
80
295
|
}
|
|
81
296
|
// -- Role mutations -------------------------------------------------------
|
|
297
|
+
/**
|
|
298
|
+
* Create a custom (non-system) channel role granting the given channel
|
|
299
|
+
* permission keys (e.g. `send_messages` for posting rights). Requires the
|
|
300
|
+
* `manage_roles` channel permission (app admins bypass).
|
|
301
|
+
*
|
|
302
|
+
* @param input - {@link CreateGroupRoleInput}: the `groupId`, the `roleName`
|
|
303
|
+
* (max 128 chars, unique within the channel), the `permissions` keys to
|
|
304
|
+
* grant (e.g. `send_messages`, `manage_members`; each max 64 chars,
|
|
305
|
+
* defaults to none), and an optional `rank` (higher = more senior;
|
|
306
|
+
* defaults to 0).
|
|
307
|
+
* @returns The created {@link GroupRole}.
|
|
308
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` on an invalid/duplicate name
|
|
309
|
+
* or unknown permission key, `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
310
|
+
* lacks `manage_roles`, or `UNAUTHENTICATED`.
|
|
311
|
+
*/
|
|
82
312
|
async createRole(input) {
|
|
83
313
|
const data = await this.gql.request(CreateChannelRoleDocument, { input });
|
|
84
314
|
return data.createChannelRole;
|
|
85
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Update a channel role's name, rank, and/or permission keys (system roles
|
|
318
|
+
* cannot be renamed or re-ranked). When `input.permissions` is supplied it
|
|
319
|
+
* **replaces** the role's existing keys. Requires the `manage_roles` channel
|
|
320
|
+
* permission (app admins bypass).
|
|
321
|
+
*
|
|
322
|
+
* Note: changing `send_messages` here does not re-push to Buddy until each
|
|
323
|
+
* affected member's roles are re-applied via {@link setMemberRoles}.
|
|
324
|
+
*
|
|
325
|
+
* @param input - {@link UpdateGroupRoleInput}: the `groupRoleId` plus the
|
|
326
|
+
* fields to change (`roleName`, `permissions`, `rank`); omitted fields are
|
|
327
|
+
* left unchanged.
|
|
328
|
+
* @returns The updated {@link GroupRole}.
|
|
329
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` on a validation failure,
|
|
330
|
+
* `FORBIDDEN` / `SCOPE_MISSING` if the caller lacks `manage_roles`, or
|
|
331
|
+
* `UNAUTHENTICATED`.
|
|
332
|
+
*/
|
|
86
333
|
async updateRole(input) {
|
|
87
334
|
const data = await this.gql.request(UpdateChannelRoleDocument, { input });
|
|
88
335
|
return data.updateChannelRole;
|
|
89
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Delete a non-system channel role. Requires the `manage_roles` channel
|
|
339
|
+
* permission (app admins bypass). The system `leader` role cannot be
|
|
340
|
+
* deleted. **Destructive**: removes the role from any members that held it.
|
|
341
|
+
*
|
|
342
|
+
* @param groupRoleId - The channel role to delete (must be a non-system
|
|
343
|
+
* role), as a decimal `BigInt` string.
|
|
344
|
+
* @returns `true` if a role was deleted.
|
|
345
|
+
* @throws {CrowdyGraphQLError} `FORBIDDEN` / `SCOPE_MISSING` if the caller
|
|
346
|
+
* lacks `manage_roles`, `BAD_USER_INPUT` if targeting a system role, or
|
|
347
|
+
* `UNAUTHENTICATED`.
|
|
348
|
+
*/
|
|
90
349
|
async deleteRole(groupRoleId) {
|
|
91
350
|
const data = await this.gql.request(DeleteChannelRoleDocument, { groupRoleId });
|
|
92
351
|
return data.deleteChannelRole;
|
package/dist/domains/chunks.d.ts
CHANGED
|
@@ -1,20 +1,133 @@
|
|
|
1
1
|
import type { GraphQLClient } from '../client.js';
|
|
2
2
|
import { type GetChunkQuery, type GetChunkQueryVariables, type GetChunkLodsQuery, type GetChunkLodsQueryVariables, type GetChunksByDistanceQuery, type GetChunksByDistanceQueryVariables, type GetVoxelListQuery, type GetVoxelListQueryVariables, type UpdateChunkMutation, type UpdateChunkMutationVariables, type UpdateChunkStateMutation, type UpdateChunkStateMutationVariables, type UpdateChunkLodsMutation, type UpdateChunkLodsMutationVariables } from '../generated/graphql.js';
|
|
3
3
|
/**
|
|
4
|
-
* Chunk-level
|
|
5
|
-
* voxel lists, and chunk state/LOD updates.
|
|
6
|
-
*
|
|
4
|
+
* Chunk-level reads and writes for an app's voxel world on the **game-api**.
|
|
7
5
|
* Exposed as `client.chunks`.
|
|
6
|
+
*
|
|
7
|
+
* A "chunk" is a persisted 16×16×16-voxel cube (4096 voxels) of an app's world.
|
|
8
|
+
* It holds the packed voxel-type grid (`voxels`), sparse per-voxel state
|
|
9
|
+
* overrides (`voxelStates`), an optional opaque chunk-level state blob
|
|
10
|
+
* (`chunkState`), and level-of-detail meshes (`lods`). Use this API for
|
|
11
|
+
* authoritative world persistence and bulk region loads; for high-frequency,
|
|
12
|
+
* per-voxel realtime edits prefer the UDP path
|
|
13
|
+
* (`client.udp.sendVoxelUpdate(...)`), which is far cheaper per update.
|
|
14
|
+
*
|
|
15
|
+
* Coordinate & encoding conventions used throughout:
|
|
16
|
+
* - **Chunk coordinates** (`coordinates.x/y/z`) are int64 **decimal strings**;
|
|
17
|
+
* `+1` on an axis is one chunk (16 voxels) further along it.
|
|
18
|
+
* - **Voxel positions** (`location` / `voxelCoord`) are signed 16-bit ints,
|
|
19
|
+
* `0-15` per axis for in-bounds voxels.
|
|
20
|
+
* - Binary blobs — the dense `voxels` grid (exactly 4096 bytes once decoded),
|
|
21
|
+
* per-voxel `state`, `chunkState`, and LOD `data` — are **base64-encoded**.
|
|
22
|
+
* - `appId` is a `BigInt` sent and received as a decimal string.
|
|
23
|
+
*
|
|
24
|
+
* Every method requires an authenticated session (a Bearer token set via
|
|
25
|
+
* `client.auth.login()` or `client.setToken()`); an app-scoped token may only
|
|
26
|
+
* touch its own app, otherwise {@link CrowdyGraphQLError} is thrown
|
|
27
|
+
* (`UNAUTHENTICATED` / `FORBIDDEN`). The two privileged writes
|
|
28
|
+
* ({@link ChunksAPI.updateState}, {@link ChunksAPI.updateLods}) additionally
|
|
29
|
+
* require the `manage_apps` permission on the owning org
|
|
30
|
+
* (`SCOPE_MISSING` / `FORBIDDEN`).
|
|
8
31
|
*/
|
|
9
32
|
export declare class ChunksAPI {
|
|
10
33
|
private gql;
|
|
11
34
|
constructor(gql: GraphQLClient);
|
|
35
|
+
/**
|
|
36
|
+
* Fetch a single chunk — its base64 voxel grid, per-voxel states, chunk-level
|
|
37
|
+
* state and LODs — by app id and chunk coordinates. Read-only. Use the input's
|
|
38
|
+
* LOD options (`requestedLodLevels` / `includeAllLods`) to limit which LODs
|
|
39
|
+
* come back.
|
|
40
|
+
*
|
|
41
|
+
* @param input - {@link GetChunkInput}: `appId` (decimal string), chunk
|
|
42
|
+
* `coordinates` (int64 decimal strings), and optional LOD filtering.
|
|
43
|
+
* @returns The {@link Chunk}, or `null` if no chunk exists at those
|
|
44
|
+
* coordinates. Binary fields (`voxels`, `chunkState`, per-voxel/LOD `data`)
|
|
45
|
+
* are base64-encoded.
|
|
46
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED`, or `FORBIDDEN` if an
|
|
47
|
+
* app-scoped token is used against a different app.
|
|
48
|
+
*/
|
|
12
49
|
get(input: GetChunkQueryVariables['input']): Promise<GetChunkQuery['getChunk']>;
|
|
50
|
+
/**
|
|
51
|
+
* Fetch only the requested level-of-detail (LOD) meshes for one chunk —
|
|
52
|
+
* cheaper than {@link ChunksAPI.get} when you only need LODs. Read-only.
|
|
53
|
+
*
|
|
54
|
+
* @param input - {@link GetChunkLodsInput}: `appId`, chunk `coordinates`, and
|
|
55
|
+
* `lodLevels` (the LOD levels to return; each `>= 0`, where `0` is finest).
|
|
56
|
+
* @returns A {@link ChunkLodsResponse} (chunk identity plus the matching
|
|
57
|
+
* `lods`, each carrying base64 `data`), or `null` if the chunk does not
|
|
58
|
+
* exist.
|
|
59
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
60
|
+
*/
|
|
13
61
|
getLods(input: GetChunkLodsQueryVariables['input']): Promise<GetChunkLodsQuery['getChunkLods']>;
|
|
62
|
+
/**
|
|
63
|
+
* Return all chunks for an app within a cubic (Chebyshev-distance) radius of a
|
|
64
|
+
* center chunk, paginated — the cube spans center ± `maxDistance` chunks on
|
|
65
|
+
* each axis (a `(2·maxDistance+1)³` cube). Use this for bulk region loads; use
|
|
66
|
+
* {@link ChunksAPI.get} for a single chunk. Read-only.
|
|
67
|
+
*
|
|
68
|
+
* @param input - {@link GetChunksByDistanceInput}: `appId`, `centerCoordinate`
|
|
69
|
+
* (int64 decimal strings), `maxDistance` (in chunk units, integer `1-8`),
|
|
70
|
+
* and optional `limit` (max chunks, default 1000) / `skip` (default 0)
|
|
71
|
+
* pagination.
|
|
72
|
+
* @returns A {@link ChunksByDistanceResponse}: the matching `chunks` plus an
|
|
73
|
+
* echo of the applied `limit`/`skip`.
|
|
74
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` (e.g. `maxDistance` outside
|
|
75
|
+
* `1-8`), `UNAUTHENTICATED`, or `FORBIDDEN`.
|
|
76
|
+
*/
|
|
14
77
|
byDistance(input: GetChunksByDistanceQueryVariables['input']): Promise<GetChunksByDistanceQuery['getChunksByDistance']>;
|
|
78
|
+
/**
|
|
79
|
+
* List every recorded voxel edit (the `voxel_updates` log) for a single chunk,
|
|
80
|
+
* newest first. Use {@link ChunksAPI.get} instead when you want the packed
|
|
81
|
+
* voxel grid rather than the individual edit log. Read-only.
|
|
82
|
+
*
|
|
83
|
+
* @param input - {@link GetVoxelListInput}: `appId` and chunk `coordinates`.
|
|
84
|
+
* @returns A {@link ChunkVoxelResponse}: the chunk address plus its
|
|
85
|
+
* {@link Voxel} edits (each `state` blob base64-encoded), newest first.
|
|
86
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
87
|
+
*/
|
|
15
88
|
voxelList(input: GetVoxelListQueryVariables['input']): Promise<GetVoxelListQuery['getVoxelList']>;
|
|
89
|
+
/**
|
|
90
|
+
* Create or replace a chunk's dense voxel grid and/or per-voxel states for the
|
|
91
|
+
* given app and coordinates, recording each provided voxel state as an
|
|
92
|
+
* individual voxel update and asynchronously uploading the chunk to the CDN.
|
|
93
|
+
* **Writes world state.** Leaves `chunkState` and LODs untouched.
|
|
94
|
+
*
|
|
95
|
+
* @param input - {@link ChunkUpdateInput}: `appId`, `coordinates`, an optional
|
|
96
|
+
* base64 `voxels` grid (the decoded buffer must be exactly 4096 bytes — one
|
|
97
|
+
* voxel-type byte `0-255` per voxel, indexed `x + y*16 + z*256`), and
|
|
98
|
+
* optional `voxelStates` overrides.
|
|
99
|
+
* @returns The updated {@link Chunk}.
|
|
100
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` (e.g. a `voxels` buffer that
|
|
101
|
+
* isn't 4096 bytes), `UNAUTHENTICATED`, or `FORBIDDEN` if an app-scoped token
|
|
102
|
+
* targets another app.
|
|
103
|
+
*/
|
|
16
104
|
update(input: UpdateChunkMutationVariables['input']): Promise<UpdateChunkMutation['updateChunk']>;
|
|
105
|
+
/**
|
|
106
|
+
* Upsert **only** the opaque base64 chunk-level state blob for a chunk,
|
|
107
|
+
* preserving its voxels, per-voxel states and LODs. **Writes world state.**
|
|
108
|
+
* Privileged: requires the `manage_apps` permission on the org that owns
|
|
109
|
+
* `input.appId` (super admins bypass).
|
|
110
|
+
*
|
|
111
|
+
* @param input - {@link UpdateChunkStateInput}: `appId`, `coordinates`, and the
|
|
112
|
+
* base64-encoded `chunkState` blob (omit/null to store none).
|
|
113
|
+
* @returns The updated {@link Chunk}, or `null` if it could not be written.
|
|
114
|
+
* @throws {CrowdyGraphQLError} `SCOPE_MISSING` / `FORBIDDEN` (missing
|
|
115
|
+
* `manage_apps`), or `UNAUTHENTICATED`.
|
|
116
|
+
*/
|
|
17
117
|
updateState(input: UpdateChunkStateMutationVariables['input']): Promise<UpdateChunkStateMutation['updateChunkState']>;
|
|
118
|
+
/**
|
|
119
|
+
* Replace the entire level-of-detail (LOD) set for a chunk, preserving its
|
|
120
|
+
* voxels, per-voxel states, chunk state and owner. **Writes world state.**
|
|
121
|
+
* Privileged: requires the `manage_apps` permission on the org that owns
|
|
122
|
+
* `input.appId` (super admins bypass).
|
|
123
|
+
*
|
|
124
|
+
* @param input - {@link UpdateChunkLodsInput}: `appId`, `coordinates`, and the
|
|
125
|
+
* full `lods` set (each entry a `level` `>= 0` plus base64 `data`); this
|
|
126
|
+
* REPLACES any existing LODs.
|
|
127
|
+
* @returns The updated {@link Chunk}, or `null` if it could not be written.
|
|
128
|
+
* @throws {CrowdyGraphQLError} `SCOPE_MISSING` / `FORBIDDEN` (missing
|
|
129
|
+
* `manage_apps`), or `UNAUTHENTICATED`.
|
|
130
|
+
*/
|
|
18
131
|
updateLods(input: UpdateChunkLodsMutationVariables['input']): Promise<UpdateChunkLodsMutation['updateChunkLods']>;
|
|
19
132
|
}
|
|
20
133
|
//# sourceMappingURL=chunks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/domains/chunks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAE/B,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EAEjC,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EACtC,MAAM,yBAAyB,CAAC;AAEjC
|
|
1
|
+
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/domains/chunks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAE3B,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAE/B,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EAEjC,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EACtC,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEtC;;;;;;;;;;;;;OAaG;IACG,GAAG,CACP,KAAK,EAAE,sBAAsB,CAAC,OAAO,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAKrC;;;;;;;;;;OAUG;IACG,OAAO,CACX,KAAK,EAAE,0BAA0B,CAAC,OAAO,CAAC,GACzC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAK7C;;;;;;;;;;;;;;OAcG;IACG,UAAU,CACd,KAAK,EAAE,iCAAiC,CAAC,OAAO,CAAC,GAChD,OAAO,CAAC,wBAAwB,CAAC,qBAAqB,CAAC,CAAC;IAK3D;;;;;;;;;OASG;IACG,SAAS,CACb,KAAK,EAAE,0BAA0B,CAAC,OAAO,CAAC,GACzC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAK7C;;;;;;;;;;;;;;OAcG;IACG,MAAM,CACV,KAAK,EAAE,4BAA4B,CAAC,OAAO,CAAC,GAC3C,OAAO,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAK9C;;;;;;;;;;;OAWG;IACG,WAAW,CACf,KAAK,EAAE,iCAAiC,CAAC,OAAO,CAAC,GAChD,OAAO,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;IAKxD;;;;;;;;;;;;OAYG;IACG,UAAU,CACd,KAAK,EAAE,gCAAgC,CAAC,OAAO,CAAC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CAIvD"}
|
package/dist/domains/chunks.js
CHANGED
|
@@ -1,38 +1,151 @@
|
|
|
1
1
|
import { GetChunkDocument, GetChunkLodsDocument, GetChunksByDistanceDocument, GetVoxelListDocument, UpdateChunkDocument, UpdateChunkStateDocument, UpdateChunkLodsDocument, } from '../generated/graphql.js';
|
|
2
2
|
/**
|
|
3
|
-
* Chunk-level
|
|
4
|
-
* voxel lists, and chunk state/LOD updates.
|
|
5
|
-
*
|
|
3
|
+
* Chunk-level reads and writes for an app's voxel world on the **game-api**.
|
|
6
4
|
* Exposed as `client.chunks`.
|
|
5
|
+
*
|
|
6
|
+
* A "chunk" is a persisted 16×16×16-voxel cube (4096 voxels) of an app's world.
|
|
7
|
+
* It holds the packed voxel-type grid (`voxels`), sparse per-voxel state
|
|
8
|
+
* overrides (`voxelStates`), an optional opaque chunk-level state blob
|
|
9
|
+
* (`chunkState`), and level-of-detail meshes (`lods`). Use this API for
|
|
10
|
+
* authoritative world persistence and bulk region loads; for high-frequency,
|
|
11
|
+
* per-voxel realtime edits prefer the UDP path
|
|
12
|
+
* (`client.udp.sendVoxelUpdate(...)`), which is far cheaper per update.
|
|
13
|
+
*
|
|
14
|
+
* Coordinate & encoding conventions used throughout:
|
|
15
|
+
* - **Chunk coordinates** (`coordinates.x/y/z`) are int64 **decimal strings**;
|
|
16
|
+
* `+1` on an axis is one chunk (16 voxels) further along it.
|
|
17
|
+
* - **Voxel positions** (`location` / `voxelCoord`) are signed 16-bit ints,
|
|
18
|
+
* `0-15` per axis for in-bounds voxels.
|
|
19
|
+
* - Binary blobs — the dense `voxels` grid (exactly 4096 bytes once decoded),
|
|
20
|
+
* per-voxel `state`, `chunkState`, and LOD `data` — are **base64-encoded**.
|
|
21
|
+
* - `appId` is a `BigInt` sent and received as a decimal string.
|
|
22
|
+
*
|
|
23
|
+
* Every method requires an authenticated session (a Bearer token set via
|
|
24
|
+
* `client.auth.login()` or `client.setToken()`); an app-scoped token may only
|
|
25
|
+
* touch its own app, otherwise {@link CrowdyGraphQLError} is thrown
|
|
26
|
+
* (`UNAUTHENTICATED` / `FORBIDDEN`). The two privileged writes
|
|
27
|
+
* ({@link ChunksAPI.updateState}, {@link ChunksAPI.updateLods}) additionally
|
|
28
|
+
* require the `manage_apps` permission on the owning org
|
|
29
|
+
* (`SCOPE_MISSING` / `FORBIDDEN`).
|
|
7
30
|
*/
|
|
8
31
|
export class ChunksAPI {
|
|
9
32
|
constructor(gql) {
|
|
10
33
|
this.gql = gql;
|
|
11
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Fetch a single chunk — its base64 voxel grid, per-voxel states, chunk-level
|
|
37
|
+
* state and LODs — by app id and chunk coordinates. Read-only. Use the input's
|
|
38
|
+
* LOD options (`requestedLodLevels` / `includeAllLods`) to limit which LODs
|
|
39
|
+
* come back.
|
|
40
|
+
*
|
|
41
|
+
* @param input - {@link GetChunkInput}: `appId` (decimal string), chunk
|
|
42
|
+
* `coordinates` (int64 decimal strings), and optional LOD filtering.
|
|
43
|
+
* @returns The {@link Chunk}, or `null` if no chunk exists at those
|
|
44
|
+
* coordinates. Binary fields (`voxels`, `chunkState`, per-voxel/LOD `data`)
|
|
45
|
+
* are base64-encoded.
|
|
46
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED`, or `FORBIDDEN` if an
|
|
47
|
+
* app-scoped token is used against a different app.
|
|
48
|
+
*/
|
|
12
49
|
async get(input) {
|
|
13
50
|
const data = await this.gql.request(GetChunkDocument, { input });
|
|
14
51
|
return data.getChunk;
|
|
15
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Fetch only the requested level-of-detail (LOD) meshes for one chunk —
|
|
55
|
+
* cheaper than {@link ChunksAPI.get} when you only need LODs. Read-only.
|
|
56
|
+
*
|
|
57
|
+
* @param input - {@link GetChunkLodsInput}: `appId`, chunk `coordinates`, and
|
|
58
|
+
* `lodLevels` (the LOD levels to return; each `>= 0`, where `0` is finest).
|
|
59
|
+
* @returns A {@link ChunkLodsResponse} (chunk identity plus the matching
|
|
60
|
+
* `lods`, each carrying base64 `data`), or `null` if the chunk does not
|
|
61
|
+
* exist.
|
|
62
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
63
|
+
*/
|
|
16
64
|
async getLods(input) {
|
|
17
65
|
const data = await this.gql.request(GetChunkLodsDocument, { input });
|
|
18
66
|
return data.getChunkLods;
|
|
19
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Return all chunks for an app within a cubic (Chebyshev-distance) radius of a
|
|
70
|
+
* center chunk, paginated — the cube spans center ± `maxDistance` chunks on
|
|
71
|
+
* each axis (a `(2·maxDistance+1)³` cube). Use this for bulk region loads; use
|
|
72
|
+
* {@link ChunksAPI.get} for a single chunk. Read-only.
|
|
73
|
+
*
|
|
74
|
+
* @param input - {@link GetChunksByDistanceInput}: `appId`, `centerCoordinate`
|
|
75
|
+
* (int64 decimal strings), `maxDistance` (in chunk units, integer `1-8`),
|
|
76
|
+
* and optional `limit` (max chunks, default 1000) / `skip` (default 0)
|
|
77
|
+
* pagination.
|
|
78
|
+
* @returns A {@link ChunksByDistanceResponse}: the matching `chunks` plus an
|
|
79
|
+
* echo of the applied `limit`/`skip`.
|
|
80
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` (e.g. `maxDistance` outside
|
|
81
|
+
* `1-8`), `UNAUTHENTICATED`, or `FORBIDDEN`.
|
|
82
|
+
*/
|
|
20
83
|
async byDistance(input) {
|
|
21
84
|
const data = await this.gql.request(GetChunksByDistanceDocument, { input });
|
|
22
85
|
return data.getChunksByDistance;
|
|
23
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* List every recorded voxel edit (the `voxel_updates` log) for a single chunk,
|
|
89
|
+
* newest first. Use {@link ChunksAPI.get} instead when you want the packed
|
|
90
|
+
* voxel grid rather than the individual edit log. Read-only.
|
|
91
|
+
*
|
|
92
|
+
* @param input - {@link GetVoxelListInput}: `appId` and chunk `coordinates`.
|
|
93
|
+
* @returns A {@link ChunkVoxelResponse}: the chunk address plus its
|
|
94
|
+
* {@link Voxel} edits (each `state` blob base64-encoded), newest first.
|
|
95
|
+
* @throws {CrowdyGraphQLError} `UNAUTHENTICATED` / `FORBIDDEN`.
|
|
96
|
+
*/
|
|
24
97
|
async voxelList(input) {
|
|
25
98
|
const data = await this.gql.request(GetVoxelListDocument, { input });
|
|
26
99
|
return data.getVoxelList;
|
|
27
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Create or replace a chunk's dense voxel grid and/or per-voxel states for the
|
|
103
|
+
* given app and coordinates, recording each provided voxel state as an
|
|
104
|
+
* individual voxel update and asynchronously uploading the chunk to the CDN.
|
|
105
|
+
* **Writes world state.** Leaves `chunkState` and LODs untouched.
|
|
106
|
+
*
|
|
107
|
+
* @param input - {@link ChunkUpdateInput}: `appId`, `coordinates`, an optional
|
|
108
|
+
* base64 `voxels` grid (the decoded buffer must be exactly 4096 bytes — one
|
|
109
|
+
* voxel-type byte `0-255` per voxel, indexed `x + y*16 + z*256`), and
|
|
110
|
+
* optional `voxelStates` overrides.
|
|
111
|
+
* @returns The updated {@link Chunk}.
|
|
112
|
+
* @throws {CrowdyGraphQLError} `BAD_USER_INPUT` (e.g. a `voxels` buffer that
|
|
113
|
+
* isn't 4096 bytes), `UNAUTHENTICATED`, or `FORBIDDEN` if an app-scoped token
|
|
114
|
+
* targets another app.
|
|
115
|
+
*/
|
|
28
116
|
async update(input) {
|
|
29
117
|
const data = await this.gql.request(UpdateChunkDocument, { input });
|
|
30
118
|
return data.updateChunk;
|
|
31
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Upsert **only** the opaque base64 chunk-level state blob for a chunk,
|
|
122
|
+
* preserving its voxels, per-voxel states and LODs. **Writes world state.**
|
|
123
|
+
* Privileged: requires the `manage_apps` permission on the org that owns
|
|
124
|
+
* `input.appId` (super admins bypass).
|
|
125
|
+
*
|
|
126
|
+
* @param input - {@link UpdateChunkStateInput}: `appId`, `coordinates`, and the
|
|
127
|
+
* base64-encoded `chunkState` blob (omit/null to store none).
|
|
128
|
+
* @returns The updated {@link Chunk}, or `null` if it could not be written.
|
|
129
|
+
* @throws {CrowdyGraphQLError} `SCOPE_MISSING` / `FORBIDDEN` (missing
|
|
130
|
+
* `manage_apps`), or `UNAUTHENTICATED`.
|
|
131
|
+
*/
|
|
32
132
|
async updateState(input) {
|
|
33
133
|
const data = await this.gql.request(UpdateChunkStateDocument, { input });
|
|
34
134
|
return data.updateChunkState;
|
|
35
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Replace the entire level-of-detail (LOD) set for a chunk, preserving its
|
|
138
|
+
* voxels, per-voxel states, chunk state and owner. **Writes world state.**
|
|
139
|
+
* Privileged: requires the `manage_apps` permission on the org that owns
|
|
140
|
+
* `input.appId` (super admins bypass).
|
|
141
|
+
*
|
|
142
|
+
* @param input - {@link UpdateChunkLodsInput}: `appId`, `coordinates`, and the
|
|
143
|
+
* full `lods` set (each entry a `level` `>= 0` plus base64 `data`); this
|
|
144
|
+
* REPLACES any existing LODs.
|
|
145
|
+
* @returns The updated {@link Chunk}, or `null` if it could not be written.
|
|
146
|
+
* @throws {CrowdyGraphQLError} `SCOPE_MISSING` / `FORBIDDEN` (missing
|
|
147
|
+
* `manage_apps`), or `UNAUTHENTICATED`.
|
|
148
|
+
*/
|
|
36
149
|
async updateLods(input) {
|
|
37
150
|
const data = await this.gql.request(UpdateChunkLodsDocument, { input });
|
|
38
151
|
return data.updateChunkLods;
|