@colyseus/schema 4.0.4 → 4.0.6
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 +7 -0
- package/build/decoder/DecodeOperation.d.ts +3 -3
- package/build/decoder/Decoder.d.ts +3 -3
- package/build/decoder/ReferenceTracker.d.ts +3 -3
- package/build/decoder/strategy/Callbacks.d.ts +5 -5
- package/build/index.cjs +51 -9
- package/build/index.cjs.map +1 -1
- package/build/index.js +51 -9
- package/build/index.mjs +51 -9
- package/build/index.mjs.map +1 -1
- package/build/types/HelperTypes.d.ts +5 -1
- package/package.json +1 -1
- package/src/Metadata.ts +5 -1
- package/src/Schema.ts +10 -0
- package/src/annotations.ts +34 -5
- package/src/decoder/DecodeOperation.ts +3 -5
- package/src/decoder/Decoder.ts +3 -3
- package/src/decoder/ReferenceTracker.ts +4 -4
- package/src/decoder/strategy/Callbacks.ts +7 -7
- package/src/decoder/strategy/getDecoderStateCallbacks.ts +2 -2
- package/src/types/HelperTypes.ts +2 -0
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
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { OPERATION } from "../encoding/spec.js";
|
|
2
2
|
import { Schema } from "../Schema.js";
|
|
3
|
-
import type { Ref } from "../encoder/ChangeTree.js";
|
|
3
|
+
import type { IRef, Ref } from "../encoder/ChangeTree.js";
|
|
4
4
|
import type { Decoder } from "./Decoder.js";
|
|
5
5
|
import { Iterator } from "../encoding/decode.js";
|
|
6
6
|
export interface DataChange<T = any, F = string> {
|
|
7
|
-
ref:
|
|
7
|
+
ref: IRef;
|
|
8
8
|
refId: number;
|
|
9
9
|
op: OPERATION;
|
|
10
10
|
field: F;
|
|
@@ -13,7 +13,7 @@ export interface DataChange<T = any, F = string> {
|
|
|
13
13
|
previousValue: T;
|
|
14
14
|
}
|
|
15
15
|
export declare const DEFINITION_MISMATCH = -1;
|
|
16
|
-
export type DecodeOperation<T extends Schema = any> = (decoder: Decoder<T>, bytes: Uint8Array, it: Iterator, ref:
|
|
16
|
+
export type DecodeOperation<T extends Schema = any> = (decoder: Decoder<T>, bytes: Uint8Array, it: Iterator, ref: IRef, allChanges: DataChange[]) => number | void;
|
|
17
17
|
export declare function decodeValue<T extends Ref>(decoder: Decoder, operation: OPERATION, ref: T, index: number, type: any, bytes: Uint8Array, it: Iterator, allChanges: DataChange[]): {
|
|
18
18
|
value: any;
|
|
19
19
|
previousValue: T;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TypeContext } from "../types/TypeContext.js";
|
|
2
2
|
import { Schema } from "../Schema.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { IRef } from "../encoder/ChangeTree.js";
|
|
4
4
|
import type { Iterator } from "../encoding/decode.js";
|
|
5
5
|
import { ReferenceTracker } from "./ReferenceTracker.js";
|
|
6
6
|
import { type DataChange } from "./DecodeOperation.js";
|
|
7
7
|
import { Collection } from "../types/HelperTypes.js";
|
|
8
|
-
export declare class Decoder<T extends
|
|
8
|
+
export declare class Decoder<T extends IRef = any> {
|
|
9
9
|
context: TypeContext;
|
|
10
10
|
state: T;
|
|
11
11
|
root: ReferenceTracker;
|
|
@@ -13,7 +13,7 @@ export declare class Decoder<T extends Schema = any> {
|
|
|
13
13
|
triggerChanges?: (allChanges: DataChange[]) => void;
|
|
14
14
|
constructor(root: T, context?: TypeContext);
|
|
15
15
|
protected setState(root: T): void;
|
|
16
|
-
decode(bytes: Uint8Array, it?: Iterator, ref?:
|
|
16
|
+
decode(bytes: Uint8Array, it?: Iterator, ref?: IRef): DataChange<any, string>[];
|
|
17
17
|
skipCurrentStructure(bytes: Uint8Array, it: Iterator, totalBytes: number): void;
|
|
18
18
|
getInstanceType(bytes: Uint8Array, it: Iterator, defaultType: typeof Schema): typeof Schema;
|
|
19
19
|
createInstanceOfType(type: typeof Schema): Schema;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IRef } from "../encoder/ChangeTree.js";
|
|
2
2
|
/**
|
|
3
3
|
* Used for decoding only.
|
|
4
4
|
*/
|
|
@@ -6,7 +6,7 @@ export type SchemaCallbacks = {
|
|
|
6
6
|
[field: string | number]: Function[];
|
|
7
7
|
};
|
|
8
8
|
export declare class ReferenceTracker {
|
|
9
|
-
refs: Map<number,
|
|
9
|
+
refs: Map<number, IRef>;
|
|
10
10
|
refCount: {
|
|
11
11
|
[refId: number]: number;
|
|
12
12
|
};
|
|
@@ -16,7 +16,7 @@ export declare class ReferenceTracker {
|
|
|
16
16
|
};
|
|
17
17
|
protected nextUniqueId: number;
|
|
18
18
|
getNextUniqueId(): number;
|
|
19
|
-
addRef(refId: number, ref:
|
|
19
|
+
addRef(refId: number, ref: IRef, incrementCount?: boolean): void;
|
|
20
20
|
removeRef(refId: number): void;
|
|
21
21
|
clearRefs(): void;
|
|
22
22
|
garbageCollectDeletedRefs(): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Collection, NonFunctionPropNames } from "../../types/HelperTypes.js";
|
|
2
|
-
import { Ref } from "../../encoder/ChangeTree.js";
|
|
2
|
+
import type { IRef, Ref } from "../../encoder/ChangeTree.js";
|
|
3
3
|
import { Decoder } from "../Decoder.js";
|
|
4
4
|
import { DataChange } from "../DecodeOperation.js";
|
|
5
5
|
import { OPERATION } from "../../encoding/spec.js";
|
|
@@ -18,7 +18,7 @@ type CollectionPropNames<T> = Exclude<{
|
|
|
18
18
|
}[keyof T] & string, typeof $refId>;
|
|
19
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;
|
|
20
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;
|
|
21
|
-
export declare class StateCallbackStrategy<TState extends
|
|
21
|
+
export declare class StateCallbackStrategy<TState extends IRef> {
|
|
22
22
|
protected decoder: Decoder<TState>;
|
|
23
23
|
protected uniqueRefIds: Set<number>;
|
|
24
24
|
protected isTriggering: boolean;
|
|
@@ -28,7 +28,7 @@ export declare class StateCallbackStrategy<TState extends Schema> {
|
|
|
28
28
|
};
|
|
29
29
|
protected get state(): TState;
|
|
30
30
|
protected addCallback(refId: number, operationOrProperty: OPERATION | string, handler: Function): () => void;
|
|
31
|
-
protected addCallbackOrWaitCollectionAvailable<TInstance extends
|
|
31
|
+
protected addCallbackOrWaitCollectionAvailable<TInstance extends IRef, TReturn extends Ref>(instance: TInstance, propertyName: string, operation: OPERATION, handler: Function, immediate?: boolean): () => void;
|
|
32
32
|
/**
|
|
33
33
|
* Listen to property changes on the root state.
|
|
34
34
|
*/
|
|
@@ -37,7 +37,7 @@ export declare class StateCallbackStrategy<TState extends Schema> {
|
|
|
37
37
|
* Listen to property changes on a nested instance.
|
|
38
38
|
*/
|
|
39
39
|
listen<TInstance extends Schema, K extends PublicPropNames<TInstance>>(instance: TInstance, property: K, handler: PropertyChangeCallback<TInstance[K]>, immediate?: boolean): () => void;
|
|
40
|
-
protected listenInstance<TInstance extends
|
|
40
|
+
protected listenInstance<TInstance extends IRef>(instance: TInstance, propertyName: string, handler: PropertyChangeCallback<any>, immediate?: boolean): () => void;
|
|
41
41
|
/**
|
|
42
42
|
* Listen to any property change on an instance.
|
|
43
43
|
*/
|
|
@@ -106,7 +106,7 @@ export declare const Callbacks: {
|
|
|
106
106
|
* @param roomOrDecoder - Room or Decoder instance to get the callbacks for.
|
|
107
107
|
* @returns the new callbacks standard API.
|
|
108
108
|
*/
|
|
109
|
-
get<T extends
|
|
109
|
+
get<T extends IRef>(roomOrDecoder: Decoder<T> | {
|
|
110
110
|
serializer: {
|
|
111
111
|
decoder: Decoder<T>;
|
|
112
112
|
};
|
package/build/index.cjs
CHANGED
|
@@ -929,7 +929,11 @@ const Metadata = {
|
|
|
929
929
|
});
|
|
930
930
|
}
|
|
931
931
|
}
|
|
932
|
-
constructor
|
|
932
|
+
Object.defineProperty(constructor, Symbol.metadata, {
|
|
933
|
+
value: metadata,
|
|
934
|
+
writable: false,
|
|
935
|
+
configurable: true
|
|
936
|
+
});
|
|
933
937
|
return metadata;
|
|
934
938
|
},
|
|
935
939
|
isValidInstance(klass) {
|
|
@@ -3551,7 +3555,12 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
3551
3555
|
}
|
|
3552
3556
|
else if (value['type'] !== undefined && Schema.is(value['type'])) {
|
|
3553
3557
|
// Direct Schema type: Type → new Type()
|
|
3554
|
-
|
|
3558
|
+
if (!value['type'].prototype.initialize || value['type'].prototype.initialize.length === 0) {
|
|
3559
|
+
// only auto-initialize Schema instances if:
|
|
3560
|
+
// - they don't have an initialize method
|
|
3561
|
+
// - or initialize method doesn't accept any parameters
|
|
3562
|
+
defaultValues[fieldName] = new value['type']();
|
|
3563
|
+
}
|
|
3555
3564
|
}
|
|
3556
3565
|
}
|
|
3557
3566
|
else {
|
|
@@ -3561,7 +3570,12 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
3561
3570
|
else if (typeof (value) === "function") {
|
|
3562
3571
|
if (Schema.is(value)) {
|
|
3563
3572
|
// Direct Schema type: Type → new Type()
|
|
3564
|
-
|
|
3573
|
+
if (!value.prototype.initialize || value.prototype.initialize.length === 0) {
|
|
3574
|
+
// only auto-initialize Schema instances if:
|
|
3575
|
+
// - they don't have an initialize method
|
|
3576
|
+
// - or initialize method doesn't accept any parameters
|
|
3577
|
+
defaultValues[fieldName] = new value();
|
|
3578
|
+
}
|
|
3565
3579
|
fields[fieldName] = getNormalizedType(value);
|
|
3566
3580
|
}
|
|
3567
3581
|
else {
|
|
@@ -3588,13 +3602,32 @@ function schema(fieldsAndMethods, name, inherits = Schema) {
|
|
|
3588
3602
|
}
|
|
3589
3603
|
return defaults;
|
|
3590
3604
|
};
|
|
3605
|
+
const getParentProps = (props) => {
|
|
3606
|
+
const fieldNames = Object.keys(fields);
|
|
3607
|
+
const parentProps = {};
|
|
3608
|
+
for (const key in props) {
|
|
3609
|
+
if (!fieldNames.includes(key)) {
|
|
3610
|
+
parentProps[key] = props[key];
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3613
|
+
return parentProps;
|
|
3614
|
+
};
|
|
3591
3615
|
/** @codegen-ignore */
|
|
3592
3616
|
const klass = Metadata.setFields(class extends inherits {
|
|
3593
3617
|
constructor(...args) {
|
|
3594
|
-
super(Object.assign({}, getDefaultValues(), args[0] || {}));
|
|
3595
3618
|
// call initialize method
|
|
3596
3619
|
if (methods.initialize && typeof methods.initialize === 'function') {
|
|
3597
|
-
|
|
3620
|
+
super(Object.assign({}, getDefaultValues(), getParentProps(args[0] || {})));
|
|
3621
|
+
/**
|
|
3622
|
+
* only call initialize() in the current class, not the parent ones.
|
|
3623
|
+
* see "should not call initialize automatically when creating an instance of inherited Schema"
|
|
3624
|
+
*/
|
|
3625
|
+
if (new.target === klass) {
|
|
3626
|
+
methods.initialize.apply(this, args);
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
else {
|
|
3630
|
+
super(Object.assign({}, getDefaultValues(), args[0] || {}));
|
|
3598
3631
|
}
|
|
3599
3632
|
}
|
|
3600
3633
|
}, fields);
|
|
@@ -3668,6 +3701,15 @@ class Schema {
|
|
|
3668
3701
|
static is(type) {
|
|
3669
3702
|
return typeof (type[Symbol.metadata]) === "object";
|
|
3670
3703
|
}
|
|
3704
|
+
/**
|
|
3705
|
+
* Check if a value is an instance of Schema.
|
|
3706
|
+
* This method uses duck-typing to avoid issues with multiple @colyseus/schema versions.
|
|
3707
|
+
* @param obj Value to check
|
|
3708
|
+
* @returns true if the value is a Schema instance
|
|
3709
|
+
*/
|
|
3710
|
+
static isSchema(obj) {
|
|
3711
|
+
return typeof obj?.assign === "function";
|
|
3712
|
+
}
|
|
3671
3713
|
/**
|
|
3672
3714
|
* Track property changes
|
|
3673
3715
|
*/
|
|
@@ -4872,13 +4914,13 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4872
4914
|
// trigger onRemove on child structure.
|
|
4873
4915
|
//
|
|
4874
4916
|
if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
|
|
4875
|
-
change.previousValue
|
|
4917
|
+
Schema.isSchema(change.previousValue)) {
|
|
4876
4918
|
const deleteCallbacks = callbacks[change.previousValue[$refId]]?.[exports.OPERATION.DELETE];
|
|
4877
4919
|
for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
|
|
4878
4920
|
deleteCallbacks[i]();
|
|
4879
4921
|
}
|
|
4880
4922
|
}
|
|
4881
|
-
if (ref
|
|
4923
|
+
if (Schema.isSchema(ref)) {
|
|
4882
4924
|
//
|
|
4883
4925
|
// Handle schema instance
|
|
4884
4926
|
//
|
|
@@ -5262,7 +5304,7 @@ class StateCallbackStrategy {
|
|
|
5262
5304
|
// trigger onRemove on child structure.
|
|
5263
5305
|
//
|
|
5264
5306
|
if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
|
|
5265
|
-
change.previousValue
|
|
5307
|
+
Schema.isSchema(change.previousValue)) {
|
|
5266
5308
|
const childRefId = change.previousValue[$refId];
|
|
5267
5309
|
const deleteCallbacks = this.callbacks[childRefId]?.[exports.OPERATION.DELETE];
|
|
5268
5310
|
if (deleteCallbacks) {
|
|
@@ -5271,7 +5313,7 @@ class StateCallbackStrategy {
|
|
|
5271
5313
|
}
|
|
5272
5314
|
}
|
|
5273
5315
|
}
|
|
5274
|
-
if (ref
|
|
5316
|
+
if (Schema.isSchema(ref)) {
|
|
5275
5317
|
//
|
|
5276
5318
|
// Handle Schema instance
|
|
5277
5319
|
//
|