@colyseus/schema 4.0.3 → 4.0.5

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/build/Schema.d.ts CHANGED
@@ -20,6 +20,13 @@ export declare class Schema<C = any> implements IRef {
20
20
  */
21
21
  static initialize(instance: any): void;
22
22
  static is(type: DefinitionType): boolean;
23
+ /**
24
+ * Check if a value is an instance of Schema.
25
+ * This method uses duck-typing to avoid issues with multiple @colyseus/schema versions.
26
+ * @param obj Value to check
27
+ * @returns true if the value is a Schema instance
28
+ */
29
+ static isSchema(obj: any): obj is Schema;
23
30
  /**
24
31
  * Track property changes
25
32
  */
@@ -10,6 +10,7 @@ import { ArraySchema } from "../../types/custom/ArraySchema.js";
10
10
  import { type SchemaCallbackProxy } from "./getDecoderStateCallbacks.js";
11
11
  type PropertyChangeCallback<K> = (currentValue: K, previousValue: K) => void;
12
12
  type KeyValueCallback<K, V> = (key: K, value: V) => void;
13
+ type ValueKeyCallback<V, K> = (value: V, key: K) => void;
13
14
  type InstanceChangeCallback = () => void;
14
15
  type PublicPropNames<T> = Exclude<NonFunctionPropNames<T>, typeof $refId> & string;
15
16
  type CollectionPropNames<T> = Exclude<{
@@ -17,32 +18,6 @@ type CollectionPropNames<T> = Exclude<{
17
18
  }[keyof T] & string, typeof $refId>;
18
19
  type CollectionValueType<T, K extends keyof T> = T[K] extends MapSchema<infer V, any> ? V : T[K] extends ArraySchema<infer V> ? V : T[K] extends Collection<any, infer V, any> ? V : never;
19
20
  type CollectionKeyType<T, K extends keyof T> = T[K] extends MapSchema<any, infer Key> ? Key : T[K] extends ArraySchema<any> ? number : T[K] extends Collection<infer Key, any, any> ? Key : never;
20
- /**
21
- * State Callbacks handler
22
- *
23
- * Usage:
24
- * ```ts
25
- * const $ = Callbacks.get(decoder);
26
- *
27
- * // Listen to property changes
28
- * $.listen("currentTurn", (currentValue, previousValue) => { ... });
29
- *
30
- * // Listen to collection additions
31
- * $.onAdd("entities", (sessionId, entity) => {
32
- * // Nested property listening
33
- * $.listen(entity, "hp", (currentHp, previousHp) => { ... });
34
- * });
35
- *
36
- * // Listen to collection removals
37
- * $.onRemove("entities", (sessionId, entity) => { ... });
38
- *
39
- * // Listen to any property change on an instance
40
- * $.onChange(entity, () => { ... });
41
- *
42
- * // Bind properties to another object
43
- * $.bindTo(player, playerVisual);
44
- * ```
45
- */
46
21
  export declare class StateCallbackStrategy<TState extends Schema> {
47
22
  protected decoder: Decoder<TState>;
48
23
  protected uniqueRefIds: Set<number>;
@@ -78,19 +53,19 @@ export declare class StateCallbackStrategy<TState extends Schema> {
78
53
  /**
79
54
  * Listen to items added to a collection on root state.
80
55
  */
81
- onAdd<K extends CollectionPropNames<TState>>(property: K, handler: KeyValueCallback<CollectionKeyType<TState, K>, CollectionValueType<TState, K>>, immediate?: boolean): () => void;
56
+ onAdd<K extends CollectionPropNames<TState>>(property: K, handler: ValueKeyCallback<CollectionValueType<TState, K>, CollectionKeyType<TState, K>>, immediate?: boolean): () => void;
82
57
  /**
83
58
  * Listen to items added to a nested collection.
84
59
  */
85
- onAdd<TInstance extends Schema, K extends CollectionPropNames<TInstance>>(instance: TInstance, property: K, handler: KeyValueCallback<CollectionKeyType<TInstance, K>, CollectionValueType<TInstance, K>>, immediate?: boolean): () => void;
60
+ onAdd<TInstance extends Schema, K extends CollectionPropNames<TInstance>>(instance: TInstance, property: K, handler: ValueKeyCallback<CollectionValueType<TInstance, K>, CollectionKeyType<TInstance, K>>, immediate?: boolean): () => void;
86
61
  /**
87
62
  * Listen to items removed from a collection on root state.
88
63
  */
89
- onRemove<K extends CollectionPropNames<TState>>(property: K, handler: KeyValueCallback<CollectionKeyType<TState, K>, CollectionValueType<TState, K>>): () => void;
64
+ onRemove<K extends CollectionPropNames<TState>>(property: K, handler: ValueKeyCallback<CollectionValueType<TState, K>, CollectionKeyType<TState, K>>): () => void;
90
65
  /**
91
66
  * Listen to items removed from a nested collection.
92
67
  */
93
- onRemove<TInstance extends Schema, K extends CollectionPropNames<TInstance>>(instance: TInstance, property: K, handler: KeyValueCallback<CollectionKeyType<TInstance, K>, CollectionValueType<TInstance, K>>): () => void;
68
+ onRemove<TInstance extends Schema, K extends CollectionPropNames<TInstance>>(instance: TInstance, property: K, handler: ValueKeyCallback<CollectionValueType<TInstance, K>, CollectionKeyType<TInstance, K>>): () => void;
94
69
  /**
95
70
  * Bind properties from a Schema instance to a target object.
96
71
  * Changes will be automatically reflected on the target object.
@@ -113,13 +88,13 @@ export declare const Callbacks: {
113
88
  * callbacks.listen("currentTurn", (currentValue, previousValue) => { ... });
114
89
  *
115
90
  * // Listen to collection additions
116
- * callbacks.onAdd("entities", (sessionId, entity) => {
91
+ * callbacks.onAdd("entities", (entity, sessionId) => {
117
92
  * // Nested property listening
118
93
  * callbacks.listen(entity, "hp", (currentHp, previousHp) => { ... });
119
94
  * });
120
95
  *
121
96
  * // Listen to collection removals
122
- * callbacks.onRemove("entities", (sessionId, entity) => { ... });
97
+ * callbacks.onRemove("entities", (entity, sessionId) => { ... });
123
98
  *
124
99
  * // Listen to any property change on an instance
125
100
  * callbacks.onChange(entity, () => { ... });
package/build/index.cjs CHANGED
@@ -3668,6 +3668,15 @@ class Schema {
3668
3668
  static is(type) {
3669
3669
  return typeof (type[Symbol.metadata]) === "object";
3670
3670
  }
3671
+ /**
3672
+ * Check if a value is an instance of Schema.
3673
+ * This method uses duck-typing to avoid issues with multiple @colyseus/schema versions.
3674
+ * @param obj Value to check
3675
+ * @returns true if the value is a Schema instance
3676
+ */
3677
+ static isSchema(obj) {
3678
+ return typeof obj?.assign === "function";
3679
+ }
3671
3680
  /**
3672
3681
  * Track property changes
3673
3682
  */
@@ -4872,13 +4881,13 @@ function getDecoderStateCallbacks(decoder) {
4872
4881
  // trigger onRemove on child structure.
4873
4882
  //
4874
4883
  if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
4875
- change.previousValue instanceof Schema) {
4884
+ Schema.isSchema(change.previousValue)) {
4876
4885
  const deleteCallbacks = callbacks[change.previousValue[$refId]]?.[exports.OPERATION.DELETE];
4877
4886
  for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
4878
4887
  deleteCallbacks[i]();
4879
4888
  }
4880
4889
  }
4881
- if (ref instanceof Schema) {
4890
+ if (Schema.isSchema(ref)) {
4882
4891
  //
4883
4892
  // Handle schema instance
4884
4893
  //
@@ -5122,32 +5131,6 @@ function getRawChangesCallback(decoder, callback) {
5122
5131
  decoder.triggerChanges = callback;
5123
5132
  }
5124
5133
 
5125
- /**
5126
- * State Callbacks handler
5127
- *
5128
- * Usage:
5129
- * ```ts
5130
- * const $ = Callbacks.get(decoder);
5131
- *
5132
- * // Listen to property changes
5133
- * $.listen("currentTurn", (currentValue, previousValue) => { ... });
5134
- *
5135
- * // Listen to collection additions
5136
- * $.onAdd("entities", (sessionId, entity) => {
5137
- * // Nested property listening
5138
- * $.listen(entity, "hp", (currentHp, previousHp) => { ... });
5139
- * });
5140
- *
5141
- * // Listen to collection removals
5142
- * $.onRemove("entities", (sessionId, entity) => { ... });
5143
- *
5144
- * // Listen to any property change on an instance
5145
- * $.onChange(entity, () => { ... });
5146
- *
5147
- * // Bind properties to another object
5148
- * $.bindTo(player, playerVisual);
5149
- * ```
5150
- */
5151
5134
  class StateCallbackStrategy {
5152
5135
  decoder;
5153
5136
  uniqueRefIds = new Set();
@@ -5186,7 +5169,7 @@ class StateCallbackStrategy {
5186
5169
  immediate = immediate && this.isTriggering === false;
5187
5170
  if (operation === exports.OPERATION.ADD && immediate) {
5188
5171
  collection.forEach((value, key) => {
5189
- handler(key, value);
5172
+ handler(value, key);
5190
5173
  });
5191
5174
  }
5192
5175
  return this.addCallback(collection[$refId], operation, handler);
@@ -5288,7 +5271,7 @@ class StateCallbackStrategy {
5288
5271
  // trigger onRemove on child structure.
5289
5272
  //
5290
5273
  if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
5291
- change.previousValue instanceof Schema) {
5274
+ Schema.isSchema(change.previousValue)) {
5292
5275
  const childRefId = change.previousValue[$refId];
5293
5276
  const deleteCallbacks = this.callbacks[childRefId]?.[exports.OPERATION.DELETE];
5294
5277
  if (deleteCallbacks) {
@@ -5297,7 +5280,7 @@ class StateCallbackStrategy {
5297
5280
  }
5298
5281
  }
5299
5282
  }
5300
- if (ref instanceof Schema) {
5283
+ if (Schema.isSchema(ref)) {
5301
5284
  //
5302
5285
  // Handle Schema instance
5303
5286
  //
@@ -5342,11 +5325,11 @@ class StateCallbackStrategy {
5342
5325
  // FIXME: `previousValue` should always be available.
5343
5326
  //
5344
5327
  if (change.previousValue !== undefined) {
5345
- // trigger onRemove (key, value)
5328
+ // trigger onRemove (value, key)
5346
5329
  const deleteCallbacks = $callbacks[exports.OPERATION.DELETE];
5347
5330
  if (deleteCallbacks) {
5348
5331
  for (let j = deleteCallbacks.length - 1; j >= 0; j--) {
5349
- deleteCallbacks[j](dynamicIndex, change.previousValue);
5332
+ deleteCallbacks[j](change.previousValue, dynamicIndex);
5350
5333
  }
5351
5334
  }
5352
5335
  }
@@ -5356,7 +5339,7 @@ class StateCallbackStrategy {
5356
5339
  if (addCallbacks) {
5357
5340
  this.isTriggering = true;
5358
5341
  for (let j = addCallbacks.length - 1; j >= 0; j--) {
5359
- addCallbacks[j](dynamicIndex, change.value);
5342
+ addCallbacks[j](change.value, dynamicIndex);
5360
5343
  }
5361
5344
  this.isTriggering = false;
5362
5345
  }
@@ -5364,12 +5347,12 @@ class StateCallbackStrategy {
5364
5347
  }
5365
5348
  else if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD &&
5366
5349
  change.previousValue !== change.value) {
5367
- // trigger onAdd (key, value)
5350
+ // trigger onAdd (value, key)
5368
5351
  const addCallbacks = $callbacks[exports.OPERATION.ADD];
5369
5352
  if (addCallbacks) {
5370
5353
  this.isTriggering = true;
5371
5354
  for (let j = addCallbacks.length - 1; j >= 0; j--) {
5372
- addCallbacks[j](dynamicIndex, change.value);
5355
+ addCallbacks[j](change.value, dynamicIndex);
5373
5356
  }
5374
5357
  this.isTriggering = false;
5375
5358
  }
@@ -5403,13 +5386,13 @@ const Callbacks = {
5403
5386
  * callbacks.listen("currentTurn", (currentValue, previousValue) => { ... });
5404
5387
  *
5405
5388
  * // Listen to collection additions
5406
- * callbacks.onAdd("entities", (sessionId, entity) => {
5389
+ * callbacks.onAdd("entities", (entity, sessionId) => {
5407
5390
  * // Nested property listening
5408
5391
  * callbacks.listen(entity, "hp", (currentHp, previousHp) => { ... });
5409
5392
  * });
5410
5393
  *
5411
5394
  * // Listen to collection removals
5412
- * callbacks.onRemove("entities", (sessionId, entity) => { ... });
5395
+ * callbacks.onRemove("entities", (entity, sessionId) => { ... });
5413
5396
  *
5414
5397
  * // Listen to any property change on an instance
5415
5398
  * callbacks.onChange(entity, () => { ... });