@roomkit/state 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/README.md +356 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/package.json +74 -0
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# @roomkit/state
|
|
2
|
+
|
|
3
|
+
High-performance state synchronization library inspired by Colyseus Schema.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Type-Safe**: Decorator-based schema definition with TypeScript support
|
|
8
|
+
- ⚡ **High Performance**: Binary encoding with MessagePack, <1ms for 1000 entities
|
|
9
|
+
- 📦 **Small Payloads**: 75-85% bandwidth reduction with compression
|
|
10
|
+
- 🔄 **Automatic Tracking**: Automatic change detection for all data types
|
|
11
|
+
- 🎮 **Game-Ready**: Tracked collections (Map, Array, Set) with automatic sync
|
|
12
|
+
- 📊 **Delta Updates**: JSON Patch format for incremental state changes
|
|
13
|
+
- 🧩 **Deep Nesting**: Automatic tracking of nested objects and collections
|
|
14
|
+
- 🗜️ **Smart Compression**: Adaptive compression with entropy detection
|
|
15
|
+
- 📦 **Batch Updates**: Queue system to reduce message frequency by 20x
|
|
16
|
+
- 📈 **Performance Monitoring**: Built-in statistics and benchmarking
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @roomkit/state
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Performance Benchmarks
|
|
25
|
+
|
|
26
|
+
| Scale | Players | Encoding Time | Data Size | Compression | Throughput |
|
|
27
|
+
|-------|---------|---------------|-----------|-------------|------------|
|
|
28
|
+
| Small | 10 | 0.087ms | 474 bytes | 58.1% saved | 11,504/sec |
|
|
29
|
+
| Medium| 100 | 0.210ms | 3.3 KB | 70.6% saved | 4,768/sec |
|
|
30
|
+
| Large | 1000 | 0.996ms | 32 KB | 72.5% saved | 1,004/sec |
|
|
31
|
+
|
|
32
|
+
**Delta Updates**: 0.006ms for 3 patches, 158,430 patches/sec
|
|
33
|
+
**Batch Queue**: 20x message reduction, 4.25ms for 5000 patches
|
|
34
|
+
**Change Tracking**: 0.010ms per cycle, 104,261 cycles/sec
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### Using Tracked Collections (Recommended)
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { State, Field, MapField, TrackedMap } from '@roomkit/state';
|
|
42
|
+
|
|
43
|
+
class Player {
|
|
44
|
+
@Field('string') name: string = '';
|
|
45
|
+
@Field('number') score: number = 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class GameState extends State {
|
|
49
|
+
@MapField(Player) players = new Map<string, Player>();
|
|
50
|
+
@Field('string') status: string = 'waiting';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Usage
|
|
54
|
+
const state = new GameState();
|
|
55
|
+
state.startTracking(); // Automatically converts to TrackedMap
|
|
56
|
+
|
|
57
|
+
// All modifications are automatically tracked
|
|
58
|
+
state.players.set('p1', newPlayer);
|
|
59
|
+
state.status = 'playing';
|
|
60
|
+
|
|
61
|
+
// Get changes
|
|
62
|
+
const patches = state.getPatches(); // JSON Patch format
|
|
63
|
+
const encoded = state.encode(); // Binary MessagePack
|
|
64
|
+
|
|
65
|
+
// Clear changes after sync
|
|
66
|
+
state.clearChanges();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Direct Tracked Collections Usage
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { TrackedMap, TrackedArray, TrackedSet } from '@roomkit/state';
|
|
73
|
+
|
|
74
|
+
// TrackedMap
|
|
75
|
+
const players = new TrackedMap<string, Player>();
|
|
76
|
+
players.startTracking();
|
|
77
|
+
|
|
78
|
+
players.onChange((patches) => {
|
|
79
|
+
console.log('Players changed:', patches);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
players.set('p1', new Player());
|
|
83
|
+
// Triggers onChange with patches
|
|
84
|
+
|
|
85
|
+
// TrackedArray
|
|
86
|
+
const items = new TrackedArray<string>();
|
|
87
|
+
items.startTracking();
|
|
88
|
+
items.push('item1', 'item2');
|
|
89
|
+
|
|
90
|
+
// TrackedSet
|
|
91
|
+
const tags = new TrackedSet<string>();
|
|
92
|
+
tags.startTracking();
|
|
93
|
+
tags.add('tag1');
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Client-side State Synchronization
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { StateDecoder } from '@roomkit/state/encoding';
|
|
100
|
+
|
|
101
|
+
class ClientGameState {
|
|
102
|
+
players = new Map<string, any>();
|
|
103
|
+
scores: number[] = [];
|
|
104
|
+
status: string = 'waiting';
|
|
105
|
+
round: number = 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const decoder = new StateDecoder();
|
|
109
|
+
const state = new ClientGameState();
|
|
110
|
+
|
|
111
|
+
// Full state sync
|
|
112
|
+
room.onMessage(MessageId.STATE_FULL, (message) => {
|
|
113
|
+
const decoded = decoder.decode(message.data);
|
|
114
|
+
Object.assign(state, decoded);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Delta updates
|
|
118
|
+
room.onMessage(MessageId.STATE_DELTA, (message) => {
|
|
119
|
+
decoder.applyPatches(state, message.patches);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## API Reference
|
|
124
|
+
|
|
125
|
+
### Decorators
|
|
126
|
+
|
|
127
|
+
#### `@Field(type: FieldType)`
|
|
128
|
+
Define a primitive field.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
@Field('string') name: string = '';
|
|
132
|
+
@Field('number') health: number = 100;
|
|
133
|
+
@Field('boolean') isAlive: boolean = true;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### TrackedMap
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
@MapField(Player) players = new Map<string, Player>();
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
When `startTracking()` is called, automatically converts to `TrackedMap` which:
|
|
143
|
+
- Tracks `set()`, `delete()`, `clear()` operations
|
|
144
|
+
- Emits change events via `onChange(callback)`
|
|
145
|
+
- Supports batch operations with `batch(fn)`
|
|
146
|
+
|
|
147
|
+
### TrackedArray
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
@ArrayField('number') scores: number[] = [];
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Automatically converts to `TrackedArray` which tracks:
|
|
154
|
+
- `push()`, `pop()`, `shift()`, `unshift()`
|
|
155
|
+
- `splice()`, `sort()`, `reverse()`
|
|
156
|
+
- Array element assignments
|
|
157
|
+
|
|
158
|
+
### TrackedSet
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
@SetField('string') tags = new Set<string>();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Automatically converts to `TrackedSet` which tracks:
|
|
165
|
+
- `add()`, `delete()`, `clear()`
|
|
166
|
+
- All modifications to the set
|
|
167
|
+
|
|
168
|
+
### State Class
|
|
169
|
+
|
|
170
|
+
#### `startTracking()`
|
|
171
|
+
Start tracking changes to the state.
|
|
172
|
+
|
|
173
|
+
#### `stopTracking()`
|
|
174
|
+
Stop tracking changes.
|
|
175
|
+
|
|
176
|
+
#### `getPatches(): Patch[]`
|
|
177
|
+
Get accumulated changes as JSON Patch operations.
|
|
178
|
+
|
|
179
|
+
#### `clearChanges()`
|
|
180
|
+
Clear accumulated changes.
|
|
181
|
+
|
|
182
|
+
#### `encode(full?: boolean, options?: EncodeOptions): EncodedState`
|
|
183
|
+
Encode state to binary format.
|
|
184
|
+
- `full=true`: Encode entire state
|
|
185
|
+
- `full=false`: Encode only changes (delta)
|
|
186
|
+
- Returns: `{ data, compressed, originalSize, compressedSize, compressionRatio }`
|
|
187
|
+
|
|
188
|
+
#### `clone(): this`
|
|
189
|
+
Create a deep copy of the state.
|
|
190
|
+
|
|
191
|
+
### Compression Strategy
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { CompressionStrategy, StateEncoder } from '@roomkit/state';
|
|
195
|
+
|
|
196
|
+
// Create custom compression strategy
|
|
197
|
+
const compressionStrategy = new CompressionStrategy({
|
|
198
|
+
threshold: 2048, // Only compress data > 2KB
|
|
199
|
+
minCompressionRatio: 0.7, // Skip if compression ratio > 70%
|
|
200
|
+
level: 9, // Compression level (1-9)
|
|
201
|
+
adaptive: true // Learn from compression history
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Use with encoder
|
|
205
|
+
const encoder = new StateEncoder(compressionStrategy);
|
|
206
|
+
const encoded = encoder.encodeFull(state);
|
|
207
|
+
|
|
208
|
+
// Get compression statistics
|
|
209
|
+
const stats = encoder.getCompressionStats();
|
|
210
|
+
console.log(`Compression rate: ${stats.compressionRate * 100}%`);
|
|
211
|
+
console.log(`Average saving: ${stats.averageSaving} bytes`);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Batch Update Queue
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { BatchQueue } from '@roomkit/state';
|
|
218
|
+
|
|
219
|
+
const queue = new BatchQueue({
|
|
220
|
+
maxWaitTime: 100, // Flush every 100ms
|
|
221
|
+
maxPatchCount: 50, // Or when 50 patches accumulated
|
|
222
|
+
maxBatchSize: 10240, // Or when 10KB reached
|
|
223
|
+
enablePriority: true // Enable priority queue
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
// Register flush callback
|
|
227
|
+
queue.onFlush((updates) => {
|
|
228
|
+
const patches = updates.flatMap(u => u.patches);
|
|
229
|
+
const encoded = encoder.encodeDelta(patches);
|
|
230
|
+
sendToClients(encoded.data);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Add updates to queue
|
|
234
|
+
setInterval(() => {
|
|
235
|
+
const patches = state.getPatches();
|
|
236
|
+
if (patches.length > 0) {
|
|
237
|
+
queue.enqueue(patches, priority);
|
|
238
|
+
state.clearChanges();
|
|
239
|
+
}
|
|
240
|
+
}, 16); // 60 FPS
|
|
241
|
+
|
|
242
|
+
// Force flush on important events
|
|
243
|
+
queue.forceFlush();
|
|
244
|
+
|
|
245
|
+
// Get statistics
|
|
246
|
+
const stats = queue.getStats();
|
|
247
|
+
console.log(`Batching factor: ${stats.totalEnqueued / stats.totalBatches}x`);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Complete Production Example
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import {
|
|
254
|
+
State, Field, MapField,
|
|
255
|
+
StateEncoder, StateDecoder,
|
|
256
|
+
CompressionStrategy, BatchQueue
|
|
257
|
+
} from '@roomkit/state';
|
|
258
|
+
|
|
259
|
+
class GameState extends State {
|
|
260
|
+
@MapField(Player) players = new Map();
|
|
261
|
+
@Field('number') tick = 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Server setup
|
|
265
|
+
const state = new GameState();
|
|
266
|
+
state.startTracking();
|
|
267
|
+
|
|
268
|
+
const compressionStrategy = new CompressionStrategy({ adaptive: true });
|
|
269
|
+
const encoder = new StateEncoder(compressionStrategy);
|
|
270
|
+
const queue = new BatchQueue({ maxWaitTime: 50 });
|
|
271
|
+
|
|
272
|
+
queue.onFlush((updates) => {
|
|
273
|
+
const patches = updates.flatMap(u => u.patches);
|
|
274
|
+
|
|
275
|
+
// Optimize patches (merge, deduplicate)
|
|
276
|
+
const optimized = BatchQueue.optimizePatches(patches);
|
|
277
|
+
|
|
278
|
+
// Encode with compression
|
|
279
|
+
const encoded = encoder.encodeDelta(optimized);
|
|
280
|
+
|
|
281
|
+
// Send to clients
|
|
282
|
+
broadcast({
|
|
283
|
+
type: 'state_delta',
|
|
284
|
+
data: encoded.data,
|
|
285
|
+
compressed: encoded.compressed
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Log stats
|
|
289
|
+
console.log(`Sent ${encoded.compressedSize} bytes (${optimized.length} patches)`);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Game loop
|
|
293
|
+
setInterval(() => {
|
|
294
|
+
// Update game logic
|
|
295
|
+
updateGame(state);
|
|
296
|
+
|
|
297
|
+
// Queue changes
|
|
298
|
+
const patches = state.getPatches();
|
|
299
|
+
if (patches.length > 0) {
|
|
300
|
+
queue.enqueue(patches);
|
|
301
|
+
state.clearChanges();
|
|
302
|
+
}
|
|
303
|
+
}, 16); // 60 FPS
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Performance Optimization Tips
|
|
307
|
+
|
|
308
|
+
### 1. Choose Right Compression Threshold
|
|
309
|
+
- **Small messages (< 1KB)**: Don't compress (overhead > benefit)
|
|
310
|
+
- **Medium messages (1-10KB)**: Use level 3-6
|
|
311
|
+
- **Large messages (> 10KB)**: Use level 6-9
|
|
312
|
+
|
|
313
|
+
### 2. Batch Update Strategy
|
|
314
|
+
- **Real-time games**: 50ms window, prioritize important events
|
|
315
|
+
- **Turn-based games**: 200ms window, accumulate more changes
|
|
316
|
+
- **MMO games**: 100ms window, use priority queue
|
|
317
|
+
|
|
318
|
+
### 3. Memory Management
|
|
319
|
+
- Call `resetStats()` periodically to avoid stat accumulation
|
|
320
|
+
- Use `forceFlush()` at critical moments
|
|
321
|
+
- Consider state sharding for large-scale applications
|
|
322
|
+
|
|
323
|
+
## Benchmarking
|
|
324
|
+
|
|
325
|
+
Run the built-in performance tests:
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
cd packages/state
|
|
329
|
+
pnpm benchmark
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
This will test:
|
|
333
|
+
- Full state encoding (with/without compression)
|
|
334
|
+
- Delta encoding performance
|
|
335
|
+
- Decoding performance
|
|
336
|
+
- Change tracking overhead
|
|
337
|
+
- Batch queue efficiency
|
|
338
|
+
- Compression strategy effectiveness
|
|
339
|
+
|
|
340
|
+
## Performance
|
|
341
|
+
|
|
342
|
+
- **Full state encoding**: 0.087ms (10 players) → 0.996ms (1000 players)
|
|
343
|
+
- **Delta encoding**: 0.006ms for 3 patches, 158,430 patches/sec
|
|
344
|
+
- **Compression**: 58-73% size reduction for game states
|
|
345
|
+
- **Batch queue**: 20x message frequency reduction
|
|
346
|
+
- **Bandwidth reduction**: 75-85% vs JSON
|
|
347
|
+
|
|
348
|
+
## Documentation
|
|
349
|
+
|
|
350
|
+
- [Phase 1 Summary](./docs/PHASE1_SUMMARY.md) - Core state system
|
|
351
|
+
- [Phase 2 Summary](./docs/PHASE2_SUMMARY.md) - Tracked collections
|
|
352
|
+
- [Phase 3 Summary](./docs/PHASE3_SUMMARY.md) - Compression & optimization
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @roomkit/state - High-performance state synchronization library
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { State, Field, MapField } from '@roomkit/state';
|
|
7
|
+
*
|
|
8
|
+
* class Player {
|
|
9
|
+
* @Field('string') name: string = '';
|
|
10
|
+
* @Field('number') x: number = 0;
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* class GameState extends State {
|
|
14
|
+
* @MapField(Player) players = new Map();
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* const state = new GameState();
|
|
18
|
+
* state.startTracking();
|
|
19
|
+
*
|
|
20
|
+
* // Changes are automatically tracked
|
|
21
|
+
* state.players.set('p1', new Player());
|
|
22
|
+
*
|
|
23
|
+
* // Get patches
|
|
24
|
+
* const patches = state.getPatches();
|
|
25
|
+
*
|
|
26
|
+
* // Encode to binary
|
|
27
|
+
* const encoded = state.encode(true); // full state
|
|
28
|
+
* const delta = state.encode(false); // only changes
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export * from './State.js';
|
|
32
|
+
export * from './types.js';
|
|
33
|
+
export * from './decorators/index.js';
|
|
34
|
+
export * from './tracking/ChangeTracker.js';
|
|
35
|
+
export * from './encoding/index.js';
|
|
36
|
+
export * from './collections/index.js';
|
|
37
|
+
export * from './compression/index.js';
|
|
38
|
+
export * from './optimization/index.js';
|
|
39
|
+
export type { Patch, FieldType, FieldMetadata, EncodedState, EncodeOptions, DecodeOptions, TrackingOptions, } from './types.js';
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AAGxC,YAAY,EACV,KAAK,EACL,SAAS,EACT,aAAa,EACb,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @roomkit/state - High-performance state synchronization library
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { State, Field, MapField } from '@roomkit/state';
|
|
8
|
+
*
|
|
9
|
+
* class Player {
|
|
10
|
+
* @Field('string') name: string = '';
|
|
11
|
+
* @Field('number') x: number = 0;
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* class GameState extends State {
|
|
15
|
+
* @MapField(Player) players = new Map();
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* const state = new GameState();
|
|
19
|
+
* state.startTracking();
|
|
20
|
+
*
|
|
21
|
+
* // Changes are automatically tracked
|
|
22
|
+
* state.players.set('p1', new Player());
|
|
23
|
+
*
|
|
24
|
+
* // Get patches
|
|
25
|
+
* const patches = state.getPatches();
|
|
26
|
+
*
|
|
27
|
+
* // Encode to binary
|
|
28
|
+
* const encoded = state.encode(true); // full state
|
|
29
|
+
* const delta = state.encode(false); // only changes
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
33
|
+
if (k2 === undefined) k2 = k;
|
|
34
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
35
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
36
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
37
|
+
}
|
|
38
|
+
Object.defineProperty(o, k2, desc);
|
|
39
|
+
}) : (function(o, m, k, k2) {
|
|
40
|
+
if (k2 === undefined) k2 = k;
|
|
41
|
+
o[k2] = m[k];
|
|
42
|
+
}));
|
|
43
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
44
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
__exportStar(require("./State.js"), exports);
|
|
48
|
+
__exportStar(require("./types.js"), exports);
|
|
49
|
+
__exportStar(require("./decorators/index.js"), exports);
|
|
50
|
+
__exportStar(require("./tracking/ChangeTracker.js"), exports);
|
|
51
|
+
__exportStar(require("./encoding/index.js"), exports);
|
|
52
|
+
__exportStar(require("./collections/index.js"), exports);
|
|
53
|
+
__exportStar(require("./compression/index.js"), exports);
|
|
54
|
+
__exportStar(require("./optimization/index.js"), exports);
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;;;;;;;;;;;;;;AAEH,6CAA2B;AAC3B,6CAA2B;AAC3B,wDAAsC;AACtC,8DAA4C;AAC5C,sDAAoC;AACpC,yDAAuC;AACvC,yDAAuC;AACvC,0DAAwC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@roomkit/state",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "High-performance state synchronization library inspired by Colyseus Schema",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./decorators": {
|
|
15
|
+
"types": "./dist/decorators/index.d.ts",
|
|
16
|
+
"import": "./dist/decorators/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./collections": {
|
|
19
|
+
"types": "./dist/collections/index.d.ts",
|
|
20
|
+
"import": "./dist/collections/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./encoding": {
|
|
23
|
+
"types": "./dist/encoding/index.d.ts",
|
|
24
|
+
"import": "./dist/encoding/index.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"build:examples": "tsc --project tsconfig.examples.json",
|
|
30
|
+
"dev": "tsc --watch",
|
|
31
|
+
"clean": "rm -rf dist dist-examples",
|
|
32
|
+
"benchmark": "pnpm build:examples && node dist-examples/benchmarks/performance.js",
|
|
33
|
+
"test": "jest"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"state",
|
|
37
|
+
"synchronization",
|
|
38
|
+
"schema",
|
|
39
|
+
"binary",
|
|
40
|
+
"msgpack",
|
|
41
|
+
"realtime",
|
|
42
|
+
"game"
|
|
43
|
+
],
|
|
44
|
+
"author": "",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/daxing/gateway-worker.git",
|
|
49
|
+
"directory": "packages/state"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/daxing/gateway-worker/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/daxing/gateway-worker#readme",
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"README.md",
|
|
58
|
+
"LICENSE"
|
|
59
|
+
],
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@msgpack/msgpack": "^3.0.0-beta2",
|
|
65
|
+
"fast-json-patch": "^3.1.1",
|
|
66
|
+
"pako": "^2.1.0",
|
|
67
|
+
"reflect-metadata": "^0.2.1"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/node": "^20.10.0",
|
|
71
|
+
"@types/pako": "^2.0.3",
|
|
72
|
+
"typescript": "^5.3.3"
|
|
73
|
+
}
|
|
74
|
+
}
|