@crowdedkingdomstudios/crowdyjs 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CrowdedKingdoms
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # CrowdyJS SDK
2
+
3
+ Client SDK for Crowded Kingdoms GraphQL API with UDP proxy support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @crowdedkingdomstudios/crowdyjs
9
+ ```
10
+
11
+ For local development:
12
+ ```bash
13
+ npm link @crowdedkingdomstudios/crowdyjs
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ### Basic Setup
19
+
20
+ ```javascript
21
+ import { CrowdyClient } from '@crowdedkingdomstudios/crowdyjs';
22
+
23
+ const client = new CrowdyClient({
24
+ graphqlEndpoint: 'http://localhost:3000/graphql',
25
+ wsEndpoint: 'ws://localhost:3000/graphql',
26
+ });
27
+ ```
28
+
29
+ ### Authentication
30
+
31
+ ```javascript
32
+ // Login
33
+ const authResponse = await client.login(email, password);
34
+ console.log('Logged in as:', authResponse.user.email);
35
+
36
+ // Register
37
+ const authResponse = await client.register(email, password, gamertag);
38
+ ```
39
+
40
+ ### UDP Proxy Connection
41
+
42
+ ```javascript
43
+ // Connect to UDP proxy
44
+ const status = await client.connectUdpProxy();
45
+ console.log('Connected to server:', status.serverIp6);
46
+
47
+ // Check connection status
48
+ const status = await client.getConnectionStatus();
49
+
50
+ // Disconnect
51
+ await client.disconnectUdpProxy();
52
+ ```
53
+
54
+ ### Sending Actor Updates
55
+
56
+ ```javascript
57
+ // Create 96-byte binary state (position, rotation, velocity, etc.)
58
+ const stateBuffer = new ArrayBuffer(96);
59
+ const view = new DataView(stateBuffer);
60
+ view.setFloat32(0, x, true); // position x
61
+ view.setFloat32(4, y, true); // position y
62
+ // ... populate rest of state
63
+
64
+ // Convert to base64
65
+ const base64State = btoa(String.fromCharCode(...new Uint8Array(stateBuffer)));
66
+
67
+ // Send update
68
+ await client.sendActorUpdate({
69
+ mapId: '1',
70
+ chunk: { x: '0', y: '0', z: '0' },
71
+ uuid: 'your-32-byte-uuid',
72
+ state: base64State,
73
+ });
74
+ ```
75
+
76
+ ### Type-Specific Subscription Handlers
77
+
78
+ The SDK provides type-specific handlers so you don't need to switch on `__typename`:
79
+
80
+ ```javascript
81
+ // Actor update notifications
82
+ const unsubscribe1 = client.onActorUpdate((notification) => {
83
+ // notification is typed as ActorUpdateNotification
84
+ console.log('Actor updated:', notification.uuid);
85
+ });
86
+
87
+ // Actor update responses (from your own requests)
88
+ const unsubscribe2 = client.onActorUpdateResponse((response) => {
89
+ // response is typed as ActorUpdateResponse
90
+ if (response.errorCode === 'NO_ERROR') {
91
+ console.log('Update successful');
92
+ }
93
+ });
94
+
95
+ // Voxel updates
96
+ const unsubscribe3 = client.onVoxelUpdate((notification) => {
97
+ // notification is typed as VoxelUpdateNotification
98
+ });
99
+
100
+ // Client audio (voice chat)
101
+ const unsubscribe4 = client.onClientAudio((notification) => {
102
+ // notification is typed as ClientAudioNotification
103
+ });
104
+
105
+ // Client text (chat messages)
106
+ const unsubscribe5 = client.onClientText((notification) => {
107
+ // notification is typed as ClientTextNotification
108
+ });
109
+
110
+ // Client events
111
+ const unsubscribe6 = client.onClientEvent((notification) => {
112
+ // notification is typed as ClientEventNotification
113
+ });
114
+
115
+ // Server events
116
+ const unsubscribe7 = client.onServerEvent((notification) => {
117
+ // notification is typed as ServerEventNotification
118
+ });
119
+
120
+ // Unsubscribe when done
121
+ unsubscribe1();
122
+ unsubscribe2();
123
+ // ... etc
124
+ ```
125
+
126
+ ### Complete Example
127
+
128
+ ```javascript
129
+ import { CrowdyClient } from '@crowdedkingdomstudios/crowdyjs';
130
+
131
+ const client = new CrowdyClient({
132
+ graphqlEndpoint: 'http://localhost:3000/graphql',
133
+ wsEndpoint: 'ws://localhost:3000/graphql',
134
+ });
135
+
136
+ // Login
137
+ await client.login('user@example.com', 'password');
138
+
139
+ // Connect to UDP proxy
140
+ await client.connectUdpProxy();
141
+
142
+ // Subscribe to actor updates
143
+ const unsubscribe = client.onActorUpdate((notification) => {
144
+ console.log('Actor update:', notification.uuid);
145
+ // Handle the update...
146
+ });
147
+
148
+ // Send actor updates
149
+ setInterval(async () => {
150
+ await client.sendActorUpdate({
151
+ mapId: '1',
152
+ chunk: { x: '0', y: '0', z: '0' },
153
+ uuid: 'your-uuid',
154
+ state: 'base64-state-data',
155
+ });
156
+ }, 100);
157
+
158
+ // Cleanup
159
+ unsubscribe();
160
+ await client.disconnectUdpProxy();
161
+ client.close();
162
+ ```
163
+
164
+ ## API Reference
165
+
166
+ ### CrowdyClient
167
+
168
+ Main client class for interacting with the API.
169
+
170
+ #### Constructor
171
+
172
+ ```typescript
173
+ new CrowdyClient(config?: CrowdyClientConfig)
174
+ ```
175
+
176
+ **Config options:**
177
+ - `graphqlEndpoint?: string` - GraphQL HTTP endpoint (default: `http://localhost:3000/graphql`)
178
+ - `wsEndpoint?: string` - WebSocket endpoint (default: `ws://localhost:3000/graphql`)
179
+ - `timeout?: number` - Request timeout in ms (default: `60000`)
180
+
181
+ #### Methods
182
+
183
+ **Authentication:**
184
+ - `login(email: string, password: string): Promise<AuthResponse>`
185
+ - `register(email: string, password: string, gamertag?: string): Promise<AuthResponse>`
186
+ - `getAuthToken(): string | null`
187
+
188
+ **UDP Proxy:**
189
+ - `connectUdpProxy(): Promise<UdpProxyConnectionStatus>`
190
+ - `disconnectUdpProxy(): Promise<boolean>`
191
+ - `getConnectionStatus(): Promise<UdpProxyConnectionStatus>`
192
+
193
+ **Sending Updates:**
194
+ - `sendActorUpdate(input: ActorUpdateRequestInput): Promise<boolean>`
195
+ - `sendVoxelUpdate(input: VoxelUpdateRequestInput): Promise<boolean>`
196
+ - `sendAudioPacket(input: ClientAudioPacketInput): Promise<boolean>`
197
+ - `sendTextPacket(input: ClientTextPacketInput): Promise<boolean>`
198
+ - `sendClientEvent(input: ClientEventNotificationInput): Promise<boolean>`
199
+
200
+ **Subscriptions:**
201
+ - `onActorUpdate(handler: ActorUpdateHandler): UnsubscribeFn`
202
+ - `onActorUpdateResponse(handler: ActorUpdateResponseHandler): UnsubscribeFn`
203
+ - `onVoxelUpdate(handler: VoxelUpdateHandler): UnsubscribeFn`
204
+ - `onVoxelUpdateResponse(handler: VoxelUpdateResponseHandler): UnsubscribeFn`
205
+ - `onClientAudio(handler: ClientAudioHandler): UnsubscribeFn`
206
+ - `onClientText(handler: ClientTextHandler): UnsubscribeFn`
207
+ - `onClientEvent(handler: ClientEventHandler): UnsubscribeFn`
208
+ - `onServerEvent(handler: ServerEventHandler): UnsubscribeFn`
209
+
210
+ **Cleanup:**
211
+ - `close(): void` - Closes all subscriptions and cleans up
212
+
213
+ ## TypeScript Support
214
+
215
+ The SDK is written in TypeScript and includes full type definitions. All notification types are properly typed, so you get full IDE autocomplete and type safety.
216
+
217
+ ## License
218
+
219
+ MIT
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Core GraphQL client for HTTP queries and mutations
3
+ */
4
+ import type { AuthResponse, UdpProxyConnectionStatus, ActorUpdateRequestInput, VoxelUpdateRequestInput, ClientAudioPacketInput, ClientTextPacketInput, ClientEventNotificationInput } from './types.js';
5
+ export declare class GraphQLClient {
6
+ private token;
7
+ private graphqlEndpoint;
8
+ private timeout;
9
+ constructor(config?: {
10
+ graphqlEndpoint?: string;
11
+ timeout?: number;
12
+ });
13
+ setAuthToken(token: string | null): void;
14
+ getAuthToken(): string | null;
15
+ query<T = any>(query: string, variables?: Record<string, any>): Promise<T>;
16
+ login(email: string, password: string): Promise<AuthResponse>;
17
+ register(email: string, password: string, gamertag?: string): Promise<AuthResponse>;
18
+ connectUdpProxy(): Promise<UdpProxyConnectionStatus>;
19
+ disconnectUdpProxy(): Promise<boolean>;
20
+ getConnectionStatus(): Promise<UdpProxyConnectionStatus>;
21
+ sendActorUpdate(input: ActorUpdateRequestInput): Promise<boolean>;
22
+ sendVoxelUpdate(input: VoxelUpdateRequestInput): Promise<boolean>;
23
+ sendAudioPacket(input: ClientAudioPacketInput): Promise<boolean>;
24
+ sendTextPacket(input: ClientTextPacketInput): Promise<boolean>;
25
+ sendClientEvent(input: ClientEventNotificationInput): Promise<boolean>;
26
+ }
27
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC7B,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO;IAKvE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIxC,YAAY,IAAI,MAAM,GAAG,IAAI;IAIvB,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IA+C9E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA2B7D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA2BnF,eAAe,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAgBpD,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;IAWtC,mBAAmB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAgBxD,eAAe,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BjE,eAAe,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BjE,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BhE,cAAc,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC;IA0B9D,eAAe,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,OAAO,CAAC;CA0B7E"}
package/dist/client.js ADDED
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Core GraphQL client for HTTP queries and mutations
3
+ */
4
+ export class GraphQLClient {
5
+ constructor(config = {}) {
6
+ this.token = null;
7
+ this.graphqlEndpoint = config.graphqlEndpoint || 'http://localhost:3000/graphql';
8
+ this.timeout = config.timeout || 60000;
9
+ }
10
+ setAuthToken(token) {
11
+ this.token = token;
12
+ }
13
+ getAuthToken() {
14
+ return this.token;
15
+ }
16
+ async query(query, variables = {}) {
17
+ const controller = new AbortController();
18
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
19
+ try {
20
+ const requestBody = { query, variables };
21
+ const response = await fetch(this.graphqlEndpoint, {
22
+ method: 'POST',
23
+ headers: {
24
+ 'Content-Type': 'application/json',
25
+ ...(this.token && { Authorization: `Bearer ${this.token}` }),
26
+ },
27
+ body: JSON.stringify(requestBody),
28
+ signal: controller.signal,
29
+ });
30
+ clearTimeout(timeoutId);
31
+ if (!response.ok) {
32
+ const errorText = await response.text();
33
+ throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`);
34
+ }
35
+ const result = await response.json();
36
+ if (result.errors) {
37
+ const error = result.errors[0];
38
+ const errorMessage = Array.isArray(error.message)
39
+ ? error.message.join(', ')
40
+ : error.message;
41
+ console.error('GraphQL error:', error);
42
+ throw new Error(errorMessage);
43
+ }
44
+ return result.data;
45
+ }
46
+ catch (error) {
47
+ clearTimeout(timeoutId);
48
+ if (error instanceof Error && error.name === 'AbortError') {
49
+ throw new Error('Request timeout exceeded when trying to connect');
50
+ }
51
+ if (error instanceof Error) {
52
+ throw error;
53
+ }
54
+ throw new Error(`Network error: ${error}`);
55
+ }
56
+ }
57
+ async login(email, password) {
58
+ const data = await this.query(`
59
+ mutation Login($input: LoginUserInput!) {
60
+ login(loginUserInput: $input) {
61
+ token
62
+ gameTokenId
63
+ user {
64
+ userId
65
+ email
66
+ gamertag
67
+ }
68
+ }
69
+ }
70
+ `, {
71
+ input: { email, password },
72
+ });
73
+ if (data.login?.token) {
74
+ this.setAuthToken(data.login.token);
75
+ return data.login;
76
+ }
77
+ throw new Error('Login failed');
78
+ }
79
+ async register(email, password, gamertag) {
80
+ const data = await this.query(`
81
+ mutation Register($input: RegisterUserInput!) {
82
+ register(registerUserInput: $input) {
83
+ token
84
+ gameTokenId
85
+ user {
86
+ userId
87
+ email
88
+ gamertag
89
+ }
90
+ }
91
+ }
92
+ `, {
93
+ input: { email, password, gamertag },
94
+ });
95
+ if (data.register?.token) {
96
+ this.setAuthToken(data.register.token);
97
+ return data.register;
98
+ }
99
+ throw new Error('Registration failed');
100
+ }
101
+ async connectUdpProxy() {
102
+ const data = await this.query(`
103
+ mutation ConnectUdpProxy {
104
+ connectUdpProxy(input: { _placeholder: true }) {
105
+ connected
106
+ serverIp6
107
+ serverClientPort
108
+ lastMessageTime
109
+ }
110
+ }
111
+ `);
112
+ return data.connectUdpProxy;
113
+ }
114
+ async disconnectUdpProxy() {
115
+ const data = await this.query(`
116
+ mutation DisconnectUdpProxy {
117
+ disconnectUdpProxy
118
+ }
119
+ `);
120
+ return data.disconnectUdpProxy;
121
+ }
122
+ async getConnectionStatus() {
123
+ const data = await this.query(`
124
+ query GetConnectionStatus {
125
+ udpProxyConnectionStatus {
126
+ connected
127
+ serverIp6
128
+ serverClientPort
129
+ lastMessageTime
130
+ }
131
+ }
132
+ `);
133
+ return data.udpProxyConnectionStatus;
134
+ }
135
+ async sendActorUpdate(input) {
136
+ const normalizedInput = {
137
+ mapId: String(Number(input.mapId)),
138
+ chunk: {
139
+ x: String(Number(input.chunk.x)),
140
+ y: String(Number(input.chunk.y)),
141
+ z: String(Number(input.chunk.z)),
142
+ },
143
+ uuid: String(input.uuid),
144
+ state: String(input.state),
145
+ distance: input.distance ?? 8,
146
+ decayRate: input.decayRate ?? 1,
147
+ ...(input.sequenceNumber != null && { sequenceNumber: input.sequenceNumber }),
148
+ };
149
+ const data = await this.query(`
150
+ mutation SendActorUpdate($input: ActorUpdateRequestInput!) {
151
+ sendActorUpdate(input: $input)
152
+ }
153
+ `, { input: normalizedInput });
154
+ return data.sendActorUpdate;
155
+ }
156
+ async sendVoxelUpdate(input) {
157
+ const normalizedInput = {
158
+ mapId: String(Number(input.mapId)),
159
+ chunk: {
160
+ x: String(Number(input.chunk.x)),
161
+ y: String(Number(input.chunk.y)),
162
+ z: String(Number(input.chunk.z)),
163
+ },
164
+ uuid: String(input.uuid),
165
+ voxel: input.voxel,
166
+ voxelType: input.voxelType,
167
+ voxelState: String(input.voxelState),
168
+ distance: input.distance ?? 8,
169
+ decayRate: input.decayRate ?? 0,
170
+ ...(input.sequenceNumber != null && { sequenceNumber: input.sequenceNumber }),
171
+ };
172
+ const data = await this.query(`
173
+ mutation SendVoxelUpdate($input: VoxelUpdateRequestInput!) {
174
+ sendVoxelUpdate(input: $input)
175
+ }
176
+ `, { input: normalizedInput });
177
+ return data.sendVoxelUpdate;
178
+ }
179
+ async sendAudioPacket(input) {
180
+ const normalizedInput = {
181
+ mapId: String(Number(input.mapId)),
182
+ chunk: {
183
+ x: String(Number(input.chunk.x)),
184
+ y: String(Number(input.chunk.y)),
185
+ z: String(Number(input.chunk.z)),
186
+ },
187
+ uuid: String(input.uuid),
188
+ audioData: String(input.audioData),
189
+ distance: input.distance ?? 1,
190
+ decayRate: input.decayRate ?? 0,
191
+ ...(input.sequenceNumber != null && { sequenceNumber: input.sequenceNumber }),
192
+ };
193
+ const data = await this.query(`
194
+ mutation SendAudioPacket($input: ClientAudioPacketInput!) {
195
+ sendAudioPacket(input: $input)
196
+ }
197
+ `, { input: normalizedInput });
198
+ return data.sendAudioPacket;
199
+ }
200
+ async sendTextPacket(input) {
201
+ const normalizedInput = {
202
+ mapId: String(Number(input.mapId)),
203
+ chunk: {
204
+ x: String(Number(input.chunk.x)),
205
+ y: String(Number(input.chunk.y)),
206
+ z: String(Number(input.chunk.z)),
207
+ },
208
+ uuid: String(input.uuid),
209
+ text: String(input.text),
210
+ distance: input.distance ?? 1,
211
+ decayRate: input.decayRate ?? 0,
212
+ ...(input.sequenceNumber != null && { sequenceNumber: input.sequenceNumber }),
213
+ };
214
+ const data = await this.query(`
215
+ mutation SendTextPacket($input: ClientTextPacketInput!) {
216
+ sendTextPacket(input: $input)
217
+ }
218
+ `, { input: normalizedInput });
219
+ return data.sendTextPacket;
220
+ }
221
+ async sendClientEvent(input) {
222
+ const normalizedInput = {
223
+ mapId: String(Number(input.mapId)),
224
+ chunk: {
225
+ x: String(Number(input.chunk.x)),
226
+ y: String(Number(input.chunk.y)),
227
+ z: String(Number(input.chunk.z)),
228
+ },
229
+ uuid: String(input.uuid),
230
+ eventType: input.eventType,
231
+ state: String(input.state),
232
+ distance: input.distance ?? 8,
233
+ decayRate: input.decayRate ?? 0,
234
+ ...(input.sequenceNumber != null && { sequenceNumber: input.sequenceNumber }),
235
+ };
236
+ const data = await this.query(`
237
+ mutation SendClientEvent($input: ClientEventNotificationInput!) {
238
+ sendClientEvent(input: $input)
239
+ }
240
+ `, { input: normalizedInput });
241
+ return data.sendClientEvent;
242
+ }
243
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Main CrowdyClient class - public API for the SDK
3
+ */
4
+ import type { CrowdyClientConfig, AuthResponse, UdpProxyConnectionStatus, ActorUpdateRequestInput, VoxelUpdateRequestInput, ClientAudioPacketInput, ClientTextPacketInput, ClientEventNotificationInput, ActorUpdateHandler, ActorUpdateResponseHandler, VoxelUpdateHandler, VoxelUpdateResponseHandler, ClientAudioHandler, ClientTextHandler, ClientEventHandler, ServerEventHandler, GenericErrorHandler, UnsubscribeFn } from './types.js';
5
+ export declare class CrowdyClient {
6
+ private client;
7
+ private subscriptions;
8
+ constructor(config?: CrowdyClientConfig);
9
+ login(email: string, password: string): Promise<AuthResponse>;
10
+ register(email: string, password: string, gamertag?: string): Promise<AuthResponse>;
11
+ getAuthToken(): string | null;
12
+ connectUdpProxy(): Promise<UdpProxyConnectionStatus>;
13
+ disconnectUdpProxy(): Promise<boolean>;
14
+ getConnectionStatus(): Promise<UdpProxyConnectionStatus>;
15
+ sendActorUpdate(input: ActorUpdateRequestInput): Promise<boolean>;
16
+ sendVoxelUpdate(input: VoxelUpdateRequestInput): Promise<boolean>;
17
+ sendAudioPacket(input: ClientAudioPacketInput): Promise<boolean>;
18
+ sendTextPacket(input: ClientTextPacketInput): Promise<boolean>;
19
+ sendClientEvent(input: ClientEventNotificationInput): Promise<boolean>;
20
+ onActorUpdate(handler: ActorUpdateHandler): UnsubscribeFn;
21
+ onActorUpdateResponse(handler: ActorUpdateResponseHandler): UnsubscribeFn;
22
+ onVoxelUpdate(handler: VoxelUpdateHandler): UnsubscribeFn;
23
+ onVoxelUpdateResponse(handler: VoxelUpdateResponseHandler): UnsubscribeFn;
24
+ onClientAudio(handler: ClientAudioHandler): UnsubscribeFn;
25
+ onClientText(handler: ClientTextHandler): UnsubscribeFn;
26
+ onClientEvent(handler: ClientEventHandler): UnsubscribeFn;
27
+ onServerEvent(handler: ServerEventHandler): UnsubscribeFn;
28
+ onGenericError(handler: GenericErrorHandler): UnsubscribeFn;
29
+ close(): void;
30
+ }
31
+ //# sourceMappingURL=crowdy-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crowdy-client.d.ts","sourceRoot":"","sources":["../src/crowdy-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC5B,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,aAAa,CAAsB;gBAE/B,MAAM,GAAE,kBAAuB;IAYrC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAM7D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAMzF,YAAY,IAAI,MAAM,GAAG,IAAI;IAKvB,eAAe,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAIpD,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC;IAItC,mBAAmB,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAKxD,eAAe,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKjE,eAAe,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKjE,eAAe,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhE,cAAc,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9D,eAAe,CAAC,KAAK,EAAE,4BAA4B,GAAG,OAAO,CAAC,OAAO,CAAC;IAK5E,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa;IAIzD,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,GAAG,aAAa;IAIzE,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa;IAIzD,qBAAqB,CAAC,OAAO,EAAE,0BAA0B,GAAG,aAAa;IAIzE,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa;IAIzD,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa;IAIvD,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa;IAIzD,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,aAAa;IAIzD,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa;IAK3D,KAAK,IAAI,IAAI;CAId"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Main CrowdyClient class - public API for the SDK
3
+ */
4
+ import { GraphQLClient } from './client.js';
5
+ import { SubscriptionManager } from './subscriptions.js';
6
+ export class CrowdyClient {
7
+ constructor(config = {}) {
8
+ this.client = new GraphQLClient({
9
+ graphqlEndpoint: config.graphqlEndpoint,
10
+ timeout: config.timeout,
11
+ });
12
+ this.subscriptions = new SubscriptionManager({
13
+ wsEndpoint: config.wsEndpoint,
14
+ });
15
+ }
16
+ // Authentication
17
+ async login(email, password) {
18
+ const response = await this.client.login(email, password);
19
+ this.subscriptions.setAuthToken(response.token);
20
+ return response;
21
+ }
22
+ async register(email, password, gamertag) {
23
+ const response = await this.client.register(email, password, gamertag);
24
+ this.subscriptions.setAuthToken(response.token);
25
+ return response;
26
+ }
27
+ getAuthToken() {
28
+ return this.client.getAuthToken();
29
+ }
30
+ // UDP Proxy
31
+ async connectUdpProxy() {
32
+ return this.client.connectUdpProxy();
33
+ }
34
+ async disconnectUdpProxy() {
35
+ return this.client.disconnectUdpProxy();
36
+ }
37
+ async getConnectionStatus() {
38
+ return this.client.getConnectionStatus();
39
+ }
40
+ // Actor Updates
41
+ async sendActorUpdate(input) {
42
+ return this.client.sendActorUpdate(input);
43
+ }
44
+ // Voxel Updates
45
+ async sendVoxelUpdate(input) {
46
+ return this.client.sendVoxelUpdate(input);
47
+ }
48
+ // Client Packets
49
+ async sendAudioPacket(input) {
50
+ return this.client.sendAudioPacket(input);
51
+ }
52
+ async sendTextPacket(input) {
53
+ return this.client.sendTextPacket(input);
54
+ }
55
+ async sendClientEvent(input) {
56
+ return this.client.sendClientEvent(input);
57
+ }
58
+ // Type-specific subscription handlers
59
+ onActorUpdate(handler) {
60
+ return this.subscriptions.onActorUpdate(handler);
61
+ }
62
+ onActorUpdateResponse(handler) {
63
+ return this.subscriptions.onActorUpdateResponse(handler);
64
+ }
65
+ onVoxelUpdate(handler) {
66
+ return this.subscriptions.onVoxelUpdate(handler);
67
+ }
68
+ onVoxelUpdateResponse(handler) {
69
+ return this.subscriptions.onVoxelUpdateResponse(handler);
70
+ }
71
+ onClientAudio(handler) {
72
+ return this.subscriptions.onClientAudio(handler);
73
+ }
74
+ onClientText(handler) {
75
+ return this.subscriptions.onClientText(handler);
76
+ }
77
+ onClientEvent(handler) {
78
+ return this.subscriptions.onClientEvent(handler);
79
+ }
80
+ onServerEvent(handler) {
81
+ return this.subscriptions.onServerEvent(handler);
82
+ }
83
+ onGenericError(handler) {
84
+ return this.subscriptions.onGenericError(handler);
85
+ }
86
+ // Cleanup
87
+ close() {
88
+ this.subscriptions.close();
89
+ this.client.setAuthToken(null);
90
+ }
91
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * CrowdyJS SDK - Client SDK for Crowded Kingdoms GraphQL API
3
+ */
4
+ export { CrowdyClient } from './crowdy-client.js';
5
+ export type { CrowdyClientConfig, BigInt, ChunkCoordinates, ChunkCoordinatesInput, VoxelCoordinates, VoxelCoordinatesInput, UdpErrorCode, User, AuthResponse, UdpProxyConnectionStatus, ActorUpdateRequestInput, VoxelUpdateRequestInput, ClientAudioPacketInput, ClientTextPacketInput, ClientEventNotificationInput, ActorUpdateNotification, ActorUpdateResponse, VoxelUpdateNotification, VoxelUpdateResponse, ClientAudioNotification, ClientTextNotification, ClientEventNotification, ServerEventNotification, GenericErrorResponse, UdpNotification, ActorUpdateHandler, ActorUpdateResponseHandler, VoxelUpdateHandler, VoxelUpdateResponseHandler, ClientAudioHandler, ClientTextHandler, ClientEventHandler, ServerEventHandler, GenericErrorHandler, UnsubscribeFn, } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAEV,kBAAkB,EAElB,MAAM,EACN,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,IAAI,EACJ,YAAY,EACZ,wBAAwB,EAExB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAE5B,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EAEf,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * CrowdyJS SDK - Client SDK for Crowded Kingdoms GraphQL API
3
+ */
4
+ export { CrowdyClient } from './crowdy-client.js';