@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/subscriptions.js
CHANGED
|
@@ -1,192 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* WebSocket subscription manager for the udpNotifications stream.
|
|
3
|
-
*
|
|
4
|
-
* Owns one shared `graphql-transport-ws` socket and dispatches incoming
|
|
5
|
-
* `udpNotifications` payloads to per-typename handler arrays. Reads its
|
|
6
|
-
* bearer token from `AuthState` so HTTP and WS auth can never drift.
|
|
7
|
-
*
|
|
8
|
-
* Public API is now `subscribe(handlers)` which returns an unsubscribe
|
|
9
|
-
* function; the per-handler `onActorUpdate` etc. shims are gone.
|
|
10
|
-
*/
|
|
11
|
-
export class SubscriptionManager {
|
|
12
|
-
constructor(config = {}, authState) {
|
|
13
|
-
this.wsClient = null;
|
|
14
|
-
this.wsUnsubscribe = null;
|
|
15
|
-
this.subscriptionId = null;
|
|
16
|
-
this.subscribers = new Map();
|
|
17
|
-
this.nextSubscriberId = 1;
|
|
18
|
-
this.wsEndpoint = config.wsEndpoint || 'ws://localhost:3000/graphql';
|
|
19
|
-
this.authState = authState;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Register handlers for the udpNotifications stream. The first call opens
|
|
23
|
-
* the shared socket (provided we have a token); subsequent calls reuse it.
|
|
24
|
-
* The returned function detaches just this set of handlers and closes the
|
|
25
|
-
* socket once the last subscriber leaves.
|
|
26
|
-
*/
|
|
27
|
-
subscribe(handlers) {
|
|
28
|
-
const id = `s${this.nextSubscriberId++}`;
|
|
29
|
-
this.subscribers.set(id, { id, handlers });
|
|
30
|
-
this.ensureSubscription();
|
|
31
|
-
return () => {
|
|
32
|
-
this.subscribers.delete(id);
|
|
33
|
-
this.checkIfShouldUnsubscribe();
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
ensureSubscription() {
|
|
37
|
-
if (!this.wsClient ||
|
|
38
|
-
(this.wsClient.readyState !== WebSocket.OPEN &&
|
|
39
|
-
this.wsClient.readyState !== WebSocket.CONNECTING)) {
|
|
40
|
-
this.startSubscription();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
startSubscription() {
|
|
44
|
-
const token = this.authState.getToken();
|
|
45
|
-
if (!token) {
|
|
46
|
-
throw new Error('Must be authenticated to subscribe');
|
|
47
|
-
}
|
|
48
|
-
this.subscriptionId = `udp-notifications-${Date.now()}`;
|
|
49
|
-
const ws = new WebSocket(this.wsEndpoint, 'graphql-transport-ws');
|
|
50
|
-
this.wsClient = ws;
|
|
51
|
-
ws.onopen = () => {
|
|
52
|
-
ws.send(JSON.stringify({
|
|
53
|
-
type: 'connection_init',
|
|
54
|
-
payload: {
|
|
55
|
-
Authorization: `Bearer ${token}`,
|
|
56
|
-
},
|
|
57
|
-
}));
|
|
58
|
-
};
|
|
59
|
-
ws.onmessage = (event) => {
|
|
60
|
-
try {
|
|
61
|
-
const message = JSON.parse(typeof event.data === 'string' ? event.data : '');
|
|
62
|
-
if (message.type === 'connection_ack') {
|
|
63
|
-
ws.send(JSON.stringify({
|
|
64
|
-
id: this.subscriptionId,
|
|
65
|
-
type: 'subscribe',
|
|
66
|
-
payload: { query: UDP_NOTIFICATIONS_QUERY },
|
|
67
|
-
}));
|
|
68
|
-
}
|
|
69
|
-
else if (message.type === 'next') {
|
|
70
|
-
if (message.payload?.data?.udpNotifications === null)
|
|
71
|
-
return;
|
|
72
|
-
const notification = message.payload?.data
|
|
73
|
-
?.udpNotifications;
|
|
74
|
-
if (notification) {
|
|
75
|
-
this.dispatch(notification);
|
|
76
|
-
}
|
|
77
|
-
else if (message.payload?.errors) {
|
|
78
|
-
console.error('Subscription errors:', message.payload.errors);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
else if (message.type === 'error') {
|
|
82
|
-
console.error('Subscription error:', message.payload);
|
|
83
|
-
}
|
|
84
|
-
else if (message.type === 'complete') {
|
|
85
|
-
if (this.wsClient === ws)
|
|
86
|
-
this.wsClient = null;
|
|
87
|
-
}
|
|
88
|
-
else if (message.type === 'ping') {
|
|
89
|
-
ws.send(JSON.stringify({ type: 'pong' }));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
catch (error) {
|
|
93
|
-
console.error('Error parsing WebSocket message:', error);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
ws.onerror = (error) => {
|
|
97
|
-
console.error('WebSocket error:', error);
|
|
98
|
-
};
|
|
99
|
-
ws.onclose = (event) => {
|
|
100
|
-
if (event.code !== 1000) {
|
|
101
|
-
console.warn(`WebSocket closed unexpectedly: ${event.reason || event.code}`);
|
|
102
|
-
}
|
|
103
|
-
if (this.wsClient === ws)
|
|
104
|
-
this.wsClient = null;
|
|
105
|
-
};
|
|
106
|
-
this.wsUnsubscribe = () => {
|
|
107
|
-
if (ws.readyState === WebSocket.OPEN) {
|
|
108
|
-
if (this.subscriptionId) {
|
|
109
|
-
ws.send(JSON.stringify({
|
|
110
|
-
id: this.subscriptionId,
|
|
111
|
-
type: 'complete',
|
|
112
|
-
}));
|
|
113
|
-
}
|
|
114
|
-
ws.close();
|
|
115
|
-
}
|
|
116
|
-
if (this.wsClient === ws)
|
|
117
|
-
this.wsClient = null;
|
|
118
|
-
this.wsUnsubscribe = null;
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
dispatch(notification) {
|
|
122
|
-
const type = notification.__typename;
|
|
123
|
-
if (!type) {
|
|
124
|
-
console.warn('Received notification without __typename:', notification);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
// Snapshot the subscribers list so handlers that mutate the registry
|
|
128
|
-
// (e.g. by calling close()) don't affect this dispatch loop.
|
|
129
|
-
for (const sub of [...this.subscribers.values()]) {
|
|
130
|
-
try {
|
|
131
|
-
switch (type) {
|
|
132
|
-
case 'ActorUpdateNotification':
|
|
133
|
-
sub.handlers.onActorUpdate?.(notification);
|
|
134
|
-
break;
|
|
135
|
-
case 'ActorUpdateResponse':
|
|
136
|
-
sub.handlers.onActorUpdateResponse?.(notification);
|
|
137
|
-
break;
|
|
138
|
-
case 'VoxelUpdateNotification':
|
|
139
|
-
sub.handlers.onVoxelUpdate?.(notification);
|
|
140
|
-
break;
|
|
141
|
-
case 'VoxelUpdateResponse':
|
|
142
|
-
sub.handlers.onVoxelUpdateResponse?.(notification);
|
|
143
|
-
break;
|
|
144
|
-
case 'ClientAudioNotification':
|
|
145
|
-
sub.handlers.onClientAudio?.(notification);
|
|
146
|
-
break;
|
|
147
|
-
case 'ClientTextNotification':
|
|
148
|
-
sub.handlers.onClientText?.(notification);
|
|
149
|
-
break;
|
|
150
|
-
case 'ClientEventNotification':
|
|
151
|
-
sub.handlers.onClientEvent?.(notification);
|
|
152
|
-
break;
|
|
153
|
-
case 'ServerEventNotification':
|
|
154
|
-
sub.handlers.onServerEvent?.(notification);
|
|
155
|
-
break;
|
|
156
|
-
case 'GenericErrorResponse':
|
|
157
|
-
sub.handlers.onGenericError?.(notification);
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
console.error(`Handler for ${type} threw:`, error);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
checkIfShouldUnsubscribe() {
|
|
167
|
-
if (this.subscribers.size === 0 && this.wsUnsubscribe) {
|
|
168
|
-
this.wsUnsubscribe();
|
|
169
|
-
this.wsUnsubscribe = null;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
close() {
|
|
173
|
-
this.subscribers.clear();
|
|
174
|
-
if (this.wsUnsubscribe) {
|
|
175
|
-
this.wsUnsubscribe();
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
const UDP_NOTIFICATIONS_QUERY = `subscription {
|
|
180
|
-
udpNotifications {
|
|
181
|
-
__typename
|
|
182
|
-
... on ActorUpdateNotification { appId chunkX chunkY chunkZ distance decayRate uuid state sequenceNumber epochMillis }
|
|
183
|
-
... on VoxelUpdateNotification { appId chunkX chunkY chunkZ distance decayRate uuid voxelX voxelY voxelZ voxelType voxelState sequenceNumber epochMillis }
|
|
184
|
-
... on GenericErrorResponse { sequenceNumber errorCode }
|
|
185
|
-
... on ActorUpdateResponse { appId chunkX chunkY chunkZ distance decayRate uuid sequenceNumber epochMillis }
|
|
186
|
-
... on VoxelUpdateResponse { appId chunkX chunkY chunkZ distance decayRate uuid sequenceNumber epochMillis }
|
|
187
|
-
... on ClientAudioNotification { appId chunkX chunkY chunkZ distance decayRate uuid audioData sequenceNumber epochMillis }
|
|
188
|
-
... on ClientTextNotification { appId chunkX chunkY chunkZ distance decayRate uuid text sequenceNumber epochMillis }
|
|
189
|
-
... on ClientEventNotification { appId chunkX chunkY chunkZ distance decayRate uuid eventType state sequenceNumber epochMillis }
|
|
190
|
-
... on ServerEventNotification { appId chunkX chunkY chunkZ distance decayRate uuid eventType state sequenceNumber epochMillis }
|
|
191
|
-
}
|
|
192
|
-
}`;
|
|
1
|
+
export { RealtimeClient as SubscriptionManager, } from './realtime.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -22,37 +22,8 @@ export interface VoxelCoordinatesInput {
|
|
|
22
22
|
y: number;
|
|
23
23
|
z: number;
|
|
24
24
|
}
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
UNKNOWN_ERROR = "UNKNOWN_ERROR",
|
|
28
|
-
EMAIL_NOT_FOUND = "EMAIL_NOT_FOUND",
|
|
29
|
-
BAD_PASSWORD = "BAD_PASSWORD",
|
|
30
|
-
EMAIL_ALREADY_EXISTS = "EMAIL_ALREADY_EXISTS",
|
|
31
|
-
INVALID_TOKEN = "INVALID_TOKEN",
|
|
32
|
-
APP_NOT_FOUND = "APP_NOT_FOUND",
|
|
33
|
-
UNAUTHORIZED = "UNAUTHORIZED",
|
|
34
|
-
APP_NOT_LOADED = "APP_NOT_LOADED",
|
|
35
|
-
EMAIL_TOO_SHORT = "EMAIL_TOO_SHORT",
|
|
36
|
-
EMAIL_TOO_LONG = "EMAIL_TOO_LONG",
|
|
37
|
-
PASSWORD_TOO_SHORT = "PASSWORD_TOO_SHORT",
|
|
38
|
-
PASSWORD_TOO_LONG = "PASSWORD_TOO_LONG",
|
|
39
|
-
GAME_TOKEN_WRONG_SIZE = "GAME_TOKEN_WRONG_SIZE",
|
|
40
|
-
NAME_TOO_LONG = "NAME_TOO_LONG",
|
|
41
|
-
INVALID_REQUEST = "INVALID_REQUEST",
|
|
42
|
-
EMAIL_INVALID = "EMAIL_INVALID",
|
|
43
|
-
INVALID_TOKEN_LENGTH = "INVALID_TOKEN_LENGTH",
|
|
44
|
-
INVALID_APP_ID = "INVALID_APP_ID",
|
|
45
|
-
CHUNK_NOT_FOUND = "CHUNK_NOT_FOUND",
|
|
46
|
-
USER_NOT_AUTHENTICATED = "USER_NOT_AUTHENTICATED",
|
|
47
|
-
INVALID_STATE_DATA = "INVALID_STATE_DATA",
|
|
48
|
-
USER_NOT_APP_ADMIN = "USER_NOT_APP_ADMIN",
|
|
49
|
-
GRID_OUTSIDE_ASSIGNMENT = "GRID_OUTSIDE_ASSIGNMENT",
|
|
50
|
-
NO_MATCHING_GRID_ASSIGNMENT = "NO_MATCHING_GRID_ASSIGNMENT",
|
|
51
|
-
INVALID_GRID_COORDINATES = "INVALID_GRID_COORDINATES",
|
|
52
|
-
GRID_ALREADY_EXISTS = "GRID_ALREADY_EXISTS",
|
|
53
|
-
GRID_OVERLAPS_EXISTING = "GRID_OVERLAPS_EXISTING",
|
|
54
|
-
GAMERTAG_ALREADY_EXISTS = "GAMERTAG_ALREADY_EXISTS"
|
|
55
|
-
}
|
|
25
|
+
export { UdpErrorCode } from './generated/graphql.js';
|
|
26
|
+
import type { UdpErrorCode } from './generated/graphql.js';
|
|
56
27
|
export interface User {
|
|
57
28
|
userId: BigInt;
|
|
58
29
|
email?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAG5B,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAGD,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAG5B,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAGD,MAAM,WAAW,gBAAgB;IAC/B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,qBAAqB;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAMD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,wBAAwB,EAAE,OAAO,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC;CACZ;AAGD,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,qBAAqB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAQD,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,yBAAyB,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,yBAAyB,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,yBAAyB,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,wBAAwB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,yBAAyB,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,yBAAyB,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,sBAAsB,CAAC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;CACzB;AAGD,MAAM,MAAM,eAAe,GACvB,uBAAuB,GACvB,mBAAmB,GACnB,uBAAuB,GACvB,mBAAmB,GACnB,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,uBAAuB,GACvB,oBAAoB,CAAC;AAGzB,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,uBAAuB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,uBAAuB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,uBAAuB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAAC,YAAY,EAAE,sBAAsB,KAAK,IAAI,CAAC;AAC/E,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,uBAAuB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,uBAAuB,KAAK,IAAI,CAAC;AACjF,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAG3E,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC"}
|
package/dist/types.js
CHANGED
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for Crowded Kingdoms SDK
|
|
3
3
|
*/
|
|
4
|
-
// Error codes
|
|
5
|
-
|
|
6
|
-
(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
UdpErrorCode["EMAIL_NOT_FOUND"] = "EMAIL_NOT_FOUND";
|
|
10
|
-
UdpErrorCode["BAD_PASSWORD"] = "BAD_PASSWORD";
|
|
11
|
-
UdpErrorCode["EMAIL_ALREADY_EXISTS"] = "EMAIL_ALREADY_EXISTS";
|
|
12
|
-
UdpErrorCode["INVALID_TOKEN"] = "INVALID_TOKEN";
|
|
13
|
-
UdpErrorCode["APP_NOT_FOUND"] = "APP_NOT_FOUND";
|
|
14
|
-
UdpErrorCode["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
15
|
-
UdpErrorCode["APP_NOT_LOADED"] = "APP_NOT_LOADED";
|
|
16
|
-
UdpErrorCode["EMAIL_TOO_SHORT"] = "EMAIL_TOO_SHORT";
|
|
17
|
-
UdpErrorCode["EMAIL_TOO_LONG"] = "EMAIL_TOO_LONG";
|
|
18
|
-
UdpErrorCode["PASSWORD_TOO_SHORT"] = "PASSWORD_TOO_SHORT";
|
|
19
|
-
UdpErrorCode["PASSWORD_TOO_LONG"] = "PASSWORD_TOO_LONG";
|
|
20
|
-
UdpErrorCode["GAME_TOKEN_WRONG_SIZE"] = "GAME_TOKEN_WRONG_SIZE";
|
|
21
|
-
UdpErrorCode["NAME_TOO_LONG"] = "NAME_TOO_LONG";
|
|
22
|
-
UdpErrorCode["INVALID_REQUEST"] = "INVALID_REQUEST";
|
|
23
|
-
UdpErrorCode["EMAIL_INVALID"] = "EMAIL_INVALID";
|
|
24
|
-
UdpErrorCode["INVALID_TOKEN_LENGTH"] = "INVALID_TOKEN_LENGTH";
|
|
25
|
-
UdpErrorCode["INVALID_APP_ID"] = "INVALID_APP_ID";
|
|
26
|
-
UdpErrorCode["CHUNK_NOT_FOUND"] = "CHUNK_NOT_FOUND";
|
|
27
|
-
UdpErrorCode["USER_NOT_AUTHENTICATED"] = "USER_NOT_AUTHENTICATED";
|
|
28
|
-
UdpErrorCode["INVALID_STATE_DATA"] = "INVALID_STATE_DATA";
|
|
29
|
-
UdpErrorCode["USER_NOT_APP_ADMIN"] = "USER_NOT_APP_ADMIN";
|
|
30
|
-
UdpErrorCode["GRID_OUTSIDE_ASSIGNMENT"] = "GRID_OUTSIDE_ASSIGNMENT";
|
|
31
|
-
UdpErrorCode["NO_MATCHING_GRID_ASSIGNMENT"] = "NO_MATCHING_GRID_ASSIGNMENT";
|
|
32
|
-
UdpErrorCode["INVALID_GRID_COORDINATES"] = "INVALID_GRID_COORDINATES";
|
|
33
|
-
UdpErrorCode["GRID_ALREADY_EXISTS"] = "GRID_ALREADY_EXISTS";
|
|
34
|
-
UdpErrorCode["GRID_OVERLAPS_EXISTING"] = "GRID_OVERLAPS_EXISTING";
|
|
35
|
-
UdpErrorCode["GAMERTAG_ALREADY_EXISTS"] = "GAMERTAG_ALREADY_EXISTS";
|
|
36
|
-
})(UdpErrorCode || (UdpErrorCode = {}));
|
|
4
|
+
// Error codes - re-exported from the codegen-derived enum so the SDK has
|
|
5
|
+
// exactly one canonical UdpErrorCode shape. The hand-written enum that
|
|
6
|
+
// used to live here drifted from the schema (`AppNotFound` etc.); see
|
|
7
|
+
// generated/graphql.ts for the source of truth.
|
|
8
|
+
export { UdpErrorCode } from './generated/graphql.js';
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChunkCoordinatesInput } from './generated/graphql.js';
|
|
2
|
+
export declare class SequenceAllocator {
|
|
3
|
+
private nextValue;
|
|
4
|
+
constructor(seed?: number);
|
|
5
|
+
next(): number;
|
|
6
|
+
}
|
|
7
|
+
export declare function generateCrowdyUuid(): string;
|
|
8
|
+
export declare function validateCrowdyUuid(uuid: string): void;
|
|
9
|
+
export declare function encodeBase64(bytes: Uint8Array): string;
|
|
10
|
+
export declare function decodeBase64(value: string): Uint8Array;
|
|
11
|
+
export declare function validateChunkCoordinates(chunk: ChunkCoordinatesInput): void;
|
|
12
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAW,MAAM,wBAAwB,CAAC;AAE7E,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,IAAI,SAAI;IAIpB,IAAI,IAAI,MAAM;CAKf;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMrD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAOtD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAS3E"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CrowdyProtocolError } from './errors.js';
|
|
2
|
+
export class SequenceAllocator {
|
|
3
|
+
constructor(seed = 1) {
|
|
4
|
+
this.nextValue = seed & 0xff;
|
|
5
|
+
}
|
|
6
|
+
next() {
|
|
7
|
+
const value = this.nextValue;
|
|
8
|
+
this.nextValue = (this.nextValue + 1) & 0xff;
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function generateCrowdyUuid() {
|
|
13
|
+
const bytes = new Uint8Array(16);
|
|
14
|
+
crypto.getRandomValues(bytes);
|
|
15
|
+
return Array.from(bytes)
|
|
16
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
17
|
+
.join('');
|
|
18
|
+
}
|
|
19
|
+
export function validateCrowdyUuid(uuid) {
|
|
20
|
+
if (new TextEncoder().encode(uuid).length !== 32) {
|
|
21
|
+
throw new CrowdyProtocolError({
|
|
22
|
+
message: 'Crowdy UUID must be exactly 32 bytes when UTF-8 encoded',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function encodeBase64(bytes) {
|
|
27
|
+
let binary = '';
|
|
28
|
+
for (const byte of bytes) {
|
|
29
|
+
binary += String.fromCharCode(byte);
|
|
30
|
+
}
|
|
31
|
+
return btoa(binary);
|
|
32
|
+
}
|
|
33
|
+
export function decodeBase64(value) {
|
|
34
|
+
const binary = atob(value);
|
|
35
|
+
const bytes = new Uint8Array(binary.length);
|
|
36
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
37
|
+
bytes[index] = binary.charCodeAt(index);
|
|
38
|
+
}
|
|
39
|
+
return bytes;
|
|
40
|
+
}
|
|
41
|
+
export function validateChunkCoordinates(chunk) {
|
|
42
|
+
for (const axis of ['x', 'y', 'z']) {
|
|
43
|
+
const value = BigInt(chunk[axis]);
|
|
44
|
+
if (value < -9223372036854775808n || value > 9223372036854775807n) {
|
|
45
|
+
throw new CrowdyProtocolError({
|
|
46
|
+
message: `Chunk coordinate ${axis} is outside signed int64 range`,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/world.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { UdpAPI } from './domains/udp.js';
|
|
2
|
+
import type { ActorUpdateRequestInput, ChunkCoordinatesInput, ClientEventNotificationInput, ClientTextPacketInput, Scalars, VoxelUpdateRequestInput } from './generated/graphql.js';
|
|
3
|
+
import type { SpatialNotification, UdpNotificationHandlers } from './realtime.js';
|
|
4
|
+
export interface ActorOptions {
|
|
5
|
+
uuid?: string;
|
|
6
|
+
defaultDistance?: number;
|
|
7
|
+
defaultDecayRate?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class WorldClient {
|
|
10
|
+
private readonly appId;
|
|
11
|
+
private readonly udp;
|
|
12
|
+
constructor(appId: Scalars['BigInt']['input'], udp: UdpAPI);
|
|
13
|
+
actor(options?: ActorOptions): ActorClient;
|
|
14
|
+
subscribe(handlers: UdpNotificationHandlers): () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare class ActorClient {
|
|
17
|
+
private readonly appId;
|
|
18
|
+
private readonly udp;
|
|
19
|
+
private readonly options;
|
|
20
|
+
readonly uuid: string;
|
|
21
|
+
private chunk;
|
|
22
|
+
constructor(appId: Scalars['BigInt']['input'], udp: UdpAPI, options: Required<Pick<ActorOptions, 'uuid'>> & Pick<ActorOptions, 'defaultDistance' | 'defaultDecayRate'>);
|
|
23
|
+
join(chunk: ChunkCoordinatesInput, state?: string): Promise<SpatialNotification>;
|
|
24
|
+
sendState(state: string, options?: Partial<Pick<ActorUpdateRequestInput, 'chunk' | 'distance' | 'decayRate'>>): Promise<SpatialNotification>;
|
|
25
|
+
sendVoxelUpdate(input: Omit<VoxelUpdateRequestInput, 'appId' | 'uuid' | 'chunk'> & {
|
|
26
|
+
chunk?: ChunkCoordinatesInput;
|
|
27
|
+
}): Promise<SpatialNotification>;
|
|
28
|
+
sendText(text: string, input?: Partial<Omit<ClientTextPacketInput, 'appId' | 'uuid' | 'text' | 'chunk'>> & {
|
|
29
|
+
chunk?: ChunkCoordinatesInput;
|
|
30
|
+
}): Promise<SpatialNotification>;
|
|
31
|
+
sendEvent(eventType: number, state: string, input?: Partial<Omit<ClientEventNotificationInput, 'appId' | 'uuid' | 'eventType' | 'state' | 'chunk'>> & {
|
|
32
|
+
chunk?: ChunkCoordinatesInput;
|
|
33
|
+
}): Promise<SpatialNotification>;
|
|
34
|
+
/**
|
|
35
|
+
* Send a direct message to a single other actor, identified by its UUID and
|
|
36
|
+
* the chunk it currently occupies (the sender must know the target's chunk).
|
|
37
|
+
* Only that one actor receives it. Fire-and-forget: there is no echo to the
|
|
38
|
+
* sender, so this resolves to the send acknowledgement, not a notification.
|
|
39
|
+
*/
|
|
40
|
+
sendToActor(targetUuid: string, payload: string, targetChunk: ChunkCoordinatesInput, options?: {
|
|
41
|
+
sequenceNumber?: number;
|
|
42
|
+
}): Promise<boolean>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=world.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,4BAA4B,EAC5B,qBAAqB,EACrB,OAAO,EACP,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGlF,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADH,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,GAAG,EAAE,MAAM;IAG9B,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,WAAW;IAQ9C,SAAS,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,IAAI;CAGzD;AAED,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,KAAK,CAAsC;gBAGhC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,GAC5D,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAMxD,IAAI,CACR,KAAK,EAAE,qBAAqB,EAC5B,KAAK,SAAS,GACb,OAAO,CAAC,mBAAmB,CAAC;IAKzB,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC,CAAM,GACvF,OAAO,CAAC,mBAAmB,CAAC;IAgBzB,eAAe,CACnB,KAAK,EAAE,IAAI,CAAC,uBAAuB,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;QACjE,KAAK,CAAC,EAAE,qBAAqB,CAAC;KAC/B,GACA,OAAO,CAAC,mBAAmB,CAAC;IAczB,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG;QACjF,KAAK,CAAC,EAAE,qBAAqB,CAAC;KAC1B,GACL,OAAO,CAAC,mBAAmB,CAAC;IAezB,SAAS,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC,GAAG;QACvG,KAAK,CAAC,EAAE,qBAAqB,CAAC;KAC1B,GACL,OAAO,CAAC,mBAAmB,CAAC;IAgB/B;;;;;OAKG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,qBAAqB,EAClC,OAAO,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAO,GACxC,OAAO,CAAC,OAAO,CAAC;CAWpB"}
|
package/dist/world.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { generateCrowdyUuid, validateChunkCoordinates, validateCrowdyUuid } from './utils.js';
|
|
2
|
+
export class WorldClient {
|
|
3
|
+
constructor(appId, udp) {
|
|
4
|
+
this.appId = appId;
|
|
5
|
+
this.udp = udp;
|
|
6
|
+
}
|
|
7
|
+
actor(options = {}) {
|
|
8
|
+
return new ActorClient(this.appId, this.udp, {
|
|
9
|
+
uuid: options.uuid ?? generateCrowdyUuid(),
|
|
10
|
+
defaultDistance: options.defaultDistance,
|
|
11
|
+
defaultDecayRate: options.defaultDecayRate,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
subscribe(handlers) {
|
|
15
|
+
return this.udp.subscribe(handlers);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class ActorClient {
|
|
19
|
+
constructor(appId, udp, options) {
|
|
20
|
+
this.appId = appId;
|
|
21
|
+
this.udp = udp;
|
|
22
|
+
this.options = options;
|
|
23
|
+
this.chunk = null;
|
|
24
|
+
validateCrowdyUuid(options.uuid);
|
|
25
|
+
this.uuid = options.uuid;
|
|
26
|
+
}
|
|
27
|
+
async join(chunk, state = 'AA==') {
|
|
28
|
+
this.chunk = chunk;
|
|
29
|
+
return this.sendState(state, { chunk });
|
|
30
|
+
}
|
|
31
|
+
async sendState(state, options = {}) {
|
|
32
|
+
const chunk = options.chunk ?? this.chunk;
|
|
33
|
+
if (!chunk) {
|
|
34
|
+
throw new Error('Actor must join a chunk before sending state');
|
|
35
|
+
}
|
|
36
|
+
validateChunkCoordinates(chunk);
|
|
37
|
+
return this.udp.sendActorUpdateAndWait({
|
|
38
|
+
appId: this.appId,
|
|
39
|
+
chunk,
|
|
40
|
+
uuid: this.uuid,
|
|
41
|
+
state,
|
|
42
|
+
distance: options.distance ?? this.options.defaultDistance,
|
|
43
|
+
decayRate: options.decayRate ?? this.options.defaultDecayRate,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async sendVoxelUpdate(input) {
|
|
47
|
+
const chunk = input.chunk ?? this.chunk;
|
|
48
|
+
if (!chunk) {
|
|
49
|
+
throw new Error('Actor must join a chunk before sending voxel updates');
|
|
50
|
+
}
|
|
51
|
+
validateChunkCoordinates(chunk);
|
|
52
|
+
return this.udp.sendVoxelUpdateAndWait({
|
|
53
|
+
...input,
|
|
54
|
+
appId: this.appId,
|
|
55
|
+
chunk,
|
|
56
|
+
uuid: this.uuid,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async sendText(text, input = {}) {
|
|
60
|
+
const chunk = input.chunk ?? this.chunk;
|
|
61
|
+
if (!chunk) {
|
|
62
|
+
throw new Error('Actor must join a chunk before sending text');
|
|
63
|
+
}
|
|
64
|
+
validateChunkCoordinates(chunk);
|
|
65
|
+
return this.udp.sendTextPacketAndWait({
|
|
66
|
+
...input,
|
|
67
|
+
appId: this.appId,
|
|
68
|
+
chunk,
|
|
69
|
+
uuid: this.uuid,
|
|
70
|
+
text,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async sendEvent(eventType, state, input = {}) {
|
|
74
|
+
const chunk = input.chunk ?? this.chunk;
|
|
75
|
+
if (!chunk) {
|
|
76
|
+
throw new Error('Actor must join a chunk before sending events');
|
|
77
|
+
}
|
|
78
|
+
validateChunkCoordinates(chunk);
|
|
79
|
+
return this.udp.sendClientEventAndWait({
|
|
80
|
+
...input,
|
|
81
|
+
appId: this.appId,
|
|
82
|
+
chunk,
|
|
83
|
+
uuid: this.uuid,
|
|
84
|
+
eventType,
|
|
85
|
+
state,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Send a direct message to a single other actor, identified by its UUID and
|
|
90
|
+
* the chunk it currently occupies (the sender must know the target's chunk).
|
|
91
|
+
* Only that one actor receives it. Fire-and-forget: there is no echo to the
|
|
92
|
+
* sender, so this resolves to the send acknowledgement, not a notification.
|
|
93
|
+
*/
|
|
94
|
+
async sendToActor(targetUuid, payload, targetChunk, options = {}) {
|
|
95
|
+
validateCrowdyUuid(targetUuid);
|
|
96
|
+
validateChunkCoordinates(targetChunk);
|
|
97
|
+
return this.udp.sendSingleActorMessage({
|
|
98
|
+
appId: this.appId,
|
|
99
|
+
chunk: targetChunk,
|
|
100
|
+
targetUuid,
|
|
101
|
+
payload,
|
|
102
|
+
sequenceNumber: options.sequenceNumber,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdedkingdomstudios/crowdyjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,19 +9,26 @@
|
|
|
9
9
|
".": {
|
|
10
10
|
"import": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./generated": {
|
|
14
|
+
"import": "./dist/generated/graphql.js",
|
|
15
|
+
"types": "./dist/generated/graphql.d.ts"
|
|
12
16
|
}
|
|
13
17
|
},
|
|
14
18
|
"files": [
|
|
15
19
|
"dist",
|
|
16
|
-
"README.md"
|
|
20
|
+
"README.md",
|
|
21
|
+
"MIGRATION.md"
|
|
17
22
|
],
|
|
18
23
|
"scripts": {
|
|
19
24
|
"sync-schema": "node scripts/sync-schema.mjs",
|
|
20
25
|
"precodegen": "npm run sync-schema",
|
|
21
26
|
"codegen": "graphql-codegen --config codegen.ts",
|
|
27
|
+
"check:schema": "npm run codegen && git diff --exit-code schema.gql src/generated/graphql.ts",
|
|
22
28
|
"codegen:watch": "graphql-codegen --config codegen.ts --watch",
|
|
23
29
|
"prebuild": "npm run codegen",
|
|
24
30
|
"build": "tsc",
|
|
31
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
25
32
|
"watch": "tsc --watch",
|
|
26
33
|
"clean": "rm -rf dist",
|
|
27
34
|
"prepublishOnly": "npm run clean && npm run build"
|
|
@@ -52,11 +59,13 @@
|
|
|
52
59
|
"@graphql-codegen/typescript": "^5.0.10",
|
|
53
60
|
"@graphql-codegen/typescript-operations": "^5.1.0",
|
|
54
61
|
"@types/node": "^22.10.7",
|
|
62
|
+
"pg": "^8.21.0",
|
|
55
63
|
"typescript": "^5.7.3",
|
|
56
64
|
"ws": "^8.20.0"
|
|
57
65
|
},
|
|
58
66
|
"dependencies": {
|
|
59
67
|
"@graphql-typed-document-node/core": "^3.2.0",
|
|
60
|
-
"graphql": "^16.13.2"
|
|
68
|
+
"graphql": "^16.13.2",
|
|
69
|
+
"graphql-ws": "^6.0.8"
|
|
61
70
|
}
|
|
62
71
|
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { GraphQLClient } from '../client.js';
|
|
2
|
-
import { type AppAccessTiersQuery, type AppAccessTiersQueryVariables, type MyAppAccessQuery, type MyAppAccessQueryVariables, type AppUserAccessByAppQuery, type AppUserAccessByAppQueryVariables, type CreateAccessTierMutation, type CreateAccessTierMutationVariables, type UpdateAccessTierMutation, type UpdateAccessTierMutationVariables, type ArchiveAccessTierMutationVariables, type GrantAppAccessMutation, type GrantAppAccessMutationVariables, type RevokeAppAccessMutation, type RevokeAppAccessMutationVariables } from '../generated/graphql.js';
|
|
3
|
-
/**
|
|
4
|
-
* App access tiers + per-user app access management. Exposed as
|
|
5
|
-
* `client.appAccess`.
|
|
6
|
-
*/
|
|
7
|
-
export declare class AppAccessAPI {
|
|
8
|
-
private gql;
|
|
9
|
-
constructor(gql: GraphQLClient);
|
|
10
|
-
listTiers(appId: AppAccessTiersQueryVariables['appId']): Promise<AppAccessTiersQuery['appAccessTiers']>;
|
|
11
|
-
myAccess(appId: MyAppAccessQueryVariables['appId']): Promise<MyAppAccessQuery['myAppAccess']>;
|
|
12
|
-
listAccess(args: AppUserAccessByAppQueryVariables): Promise<AppUserAccessByAppQuery['appUserAccessByApp']>;
|
|
13
|
-
createTier(input: CreateAccessTierMutationVariables['input']): Promise<CreateAccessTierMutation['createAccessTier']>;
|
|
14
|
-
updateTier(args: UpdateAccessTierMutationVariables): Promise<UpdateAccessTierMutation['updateAccessTier']>;
|
|
15
|
-
archiveTier(tierId: ArchiveAccessTierMutationVariables['tierId']): Promise<{
|
|
16
|
-
tierId: any;
|
|
17
|
-
status: string;
|
|
18
|
-
updatedAt: any;
|
|
19
|
-
}>;
|
|
20
|
-
grant(input: GrantAppAccessMutationVariables['input']): Promise<GrantAppAccessMutation['grantAppAccess']>;
|
|
21
|
-
revoke(args: RevokeAppAccessMutationVariables): Promise<RevokeAppAccessMutation['revokeAppAccess']>;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=appAccess.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appAccess.d.ts","sourceRoot":"","sources":["../../src/domains/appAccess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,4BAA4B,EAEjC,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,EAE9B,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EAErC,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EAEtC,KAAK,kCAAkC,EAEvC,KAAK,sBAAsB,EAC3B,KAAK,+BAA+B,EAEpC,KAAK,uBAAuB,EAC5B,KAAK,gCAAgC,EACtC,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAEhC,SAAS,CACb,KAAK,EAAE,4BAA4B,CAAC,OAAO,CAAC,GAC3C,OAAO,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAK3C,QAAQ,CACZ,KAAK,EAAE,yBAAyB,CAAC,OAAO,CAAC,GACxC,OAAO,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAKrC,UAAU,CACd,IAAI,EAAE,gCAAgC,GACrC,OAAO,CAAC,uBAAuB,CAAC,oBAAoB,CAAC,CAAC;IAKnD,UAAU,CACd,KAAK,EAAE,iCAAiC,CAAC,OAAO,CAAC,GAChD,OAAO,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;IAKlD,UAAU,CACd,IAAI,EAAE,iCAAiC,GACtC,OAAO,CAAC,wBAAwB,CAAC,kBAAkB,CAAC,CAAC;IAKlD,WAAW,CACf,MAAM,EAAE,kCAAkC,CAAC,QAAQ,CAAC,GACnD,OAAO,CAAC;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,GAAG,CAAA;KAAE,CAAC;IAKrD,KAAK,CACT,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAC9C,OAAO,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IAK9C,MAAM,CACV,IAAI,EAAE,gCAAgC,GACrC,OAAO,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CAIvD"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { AppAccessTiersDocument, MyAppAccessDocument, AppUserAccessByAppDocument, CreateAccessTierDocument, UpdateAccessTierDocument, ArchiveAccessTierDocument, GrantAppAccessDocument, RevokeAppAccessDocument, } from '../generated/graphql.js';
|
|
2
|
-
/**
|
|
3
|
-
* App access tiers + per-user app access management. Exposed as
|
|
4
|
-
* `client.appAccess`.
|
|
5
|
-
*/
|
|
6
|
-
export class AppAccessAPI {
|
|
7
|
-
constructor(gql) {
|
|
8
|
-
this.gql = gql;
|
|
9
|
-
}
|
|
10
|
-
async listTiers(appId) {
|
|
11
|
-
const data = await this.gql.request(AppAccessTiersDocument, { appId });
|
|
12
|
-
return data.appAccessTiers;
|
|
13
|
-
}
|
|
14
|
-
async myAccess(appId) {
|
|
15
|
-
const data = await this.gql.request(MyAppAccessDocument, { appId });
|
|
16
|
-
return data.myAppAccess;
|
|
17
|
-
}
|
|
18
|
-
async listAccess(args) {
|
|
19
|
-
const data = await this.gql.request(AppUserAccessByAppDocument, args);
|
|
20
|
-
return data.appUserAccessByApp;
|
|
21
|
-
}
|
|
22
|
-
async createTier(input) {
|
|
23
|
-
const data = await this.gql.request(CreateAccessTierDocument, { input });
|
|
24
|
-
return data.createAccessTier;
|
|
25
|
-
}
|
|
26
|
-
async updateTier(args) {
|
|
27
|
-
const data = await this.gql.request(UpdateAccessTierDocument, args);
|
|
28
|
-
return data.updateAccessTier;
|
|
29
|
-
}
|
|
30
|
-
async archiveTier(tierId) {
|
|
31
|
-
const data = await this.gql.request(ArchiveAccessTierDocument, { tierId });
|
|
32
|
-
return data.archiveAccessTier;
|
|
33
|
-
}
|
|
34
|
-
async grant(input) {
|
|
35
|
-
const data = await this.gql.request(GrantAppAccessDocument, { input });
|
|
36
|
-
return data.grantAppAccess;
|
|
37
|
-
}
|
|
38
|
-
async revoke(args) {
|
|
39
|
-
const data = await this.gql.request(RevokeAppAccessDocument, args);
|
|
40
|
-
return data.revokeAppAccess;
|
|
41
|
-
}
|
|
42
|
-
}
|