@colyseus/schema 3.0.0-alpha.9 → 3.0.1
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 +148 -62
- package/bin/schema-debug +94 -0
- package/build/cjs/index.js +2222 -1513
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2223 -1516
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2225 -1516
- package/lib/Metadata.d.ts +21 -9
- package/lib/Metadata.js +169 -32
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +19 -4
- package/lib/Reflection.js +66 -31
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +12 -5
- package/lib/Schema.js +57 -56
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +31 -34
- package/lib/annotations.js +110 -160
- package/lib/annotations.js.map +1 -1
- package/lib/codegen/api.js +1 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/languages/cpp.js +1 -2
- package/lib/codegen/languages/cpp.js.map +1 -1
- package/lib/codegen/languages/csharp.js +9 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +4 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +23 -25
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +85 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +6 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.d.ts +3 -4
- package/lib/decoder/DecodeOperation.js +35 -17
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +5 -6
- package/lib/decoder/Decoder.js +10 -10
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +4 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +74 -64
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +28 -20
- package/lib/encoder/ChangeTree.js +242 -188
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +3 -6
- package/lib/encoder/EncodeOperation.js +51 -65
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +8 -7
- package/lib/encoder/Encoder.js +128 -79
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +22 -0
- package/lib/encoder/Root.js +81 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +7 -7
- package/lib/encoder/StateView.js +72 -74
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +7 -6
- package/lib/encoding/assert.js +13 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.d.ts +36 -19
- package/lib/encoding/decode.js +54 -84
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -18
- package/lib/encoding/encode.js +61 -48
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +4 -5
- package/lib/encoding/spec.js +1 -2
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +10 -9
- package/lib/index.js +24 -17
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +34 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/TypeContext.d.ts +29 -0
- package/lib/types/TypeContext.js +151 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +33 -22
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -2
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +18 -16
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -2
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.d.ts +8 -1
- package/lib/types/registry.js +23 -6
- package/lib/types/registry.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -5
- package/lib/types/symbols.js +9 -6
- package/lib/types/symbols.js.map +1 -1
- package/lib/types/utils.js +1 -2
- package/lib/types/utils.js.map +1 -1
- package/lib/utils.js +9 -7
- package/lib/utils.js.map +1 -1
- package/package.json +19 -18
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +76 -38
- package/src/Schema.ts +72 -70
- package/src/annotations.ts +156 -202
- package/src/codegen/languages/csharp.ts +8 -47
- package/src/codegen/languages/haxe.ts +4 -0
- package/src/codegen/languages/lua.ts +19 -27
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/decoder/DecodeOperation.ts +43 -15
- package/src/decoder/Decoder.ts +12 -10
- package/src/decoder/ReferenceTracker.ts +5 -3
- package/src/decoder/strategy/StateCallbacks.ts +152 -81
- package/src/encoder/ChangeTree.ts +282 -209
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +152 -88
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +80 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +73 -93
- package/src/encoding/encode.ts +76 -45
- package/src/encoding/spec.ts +3 -5
- package/src/index.ts +12 -20
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +175 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +30 -17
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/registry.ts +22 -3
- package/src/types/symbols.ts +10 -7
- package/src/utils.ts +7 -3
- package/lib/Decoder.d.ts +0 -16
- package/lib/Decoder.js +0 -182
- package/lib/Decoder.js.map +0 -1
- package/lib/Encoder.d.ts +0 -13
- package/lib/Encoder.js +0 -79
- package/lib/Encoder.js.map +0 -1
- package/lib/changes/ChangeSet.d.ts +0 -12
- package/lib/changes/ChangeSet.js +0 -35
- package/lib/changes/ChangeSet.js.map +0 -1
- package/lib/changes/ChangeTree.d.ts +0 -53
- package/lib/changes/ChangeTree.js +0 -202
- package/lib/changes/ChangeTree.js.map +0 -1
- package/lib/changes/DecodeOperation.d.ts +0 -15
- package/lib/changes/DecodeOperation.js +0 -186
- package/lib/changes/DecodeOperation.js.map +0 -1
- package/lib/changes/EncodeOperation.d.ts +0 -18
- package/lib/changes/EncodeOperation.js +0 -130
- package/lib/changes/EncodeOperation.js.map +0 -1
- package/lib/changes/ReferenceTracker.d.ts +0 -14
- package/lib/changes/ReferenceTracker.js +0 -83
- package/lib/changes/ReferenceTracker.js.map +0 -1
- package/lib/changes/consts.d.ts +0 -14
- package/lib/changes/consts.js +0 -18
- package/lib/changes/consts.js.map +0 -1
- package/lib/decoding/decode.d.ts +0 -48
- package/lib/decoding/decode.js +0 -267
- package/lib/decoding/decode.js.map +0 -1
- package/lib/ecs.d.ts +0 -11
- package/lib/ecs.js +0 -160
- package/lib/ecs.js.map +0 -1
- package/lib/filters/index.d.ts +0 -8
- package/lib/filters/index.js +0 -24
- package/lib/filters/index.js.map +0 -1
- package/lib/spec.d.ts +0 -13
- package/lib/spec.js +0 -42
- package/lib/spec.js.map +0 -1
- package/lib/types/ArraySchema.d.ts +0 -238
- package/lib/types/ArraySchema.js +0 -555
- package/lib/types/ArraySchema.js.map +0 -1
- package/lib/types/CollectionSchema.d.ts +0 -35
- package/lib/types/CollectionSchema.js +0 -150
- package/lib/types/CollectionSchema.js.map +0 -1
- package/lib/types/MapSchema.d.ts +0 -38
- package/lib/types/MapSchema.js +0 -215
- package/lib/types/MapSchema.js.map +0 -1
- package/lib/types/SetSchema.d.ts +0 -32
- package/lib/types/SetSchema.js +0 -162
- package/lib/types/SetSchema.js.map +0 -1
- package/lib/types/typeRegistry.d.ts +0 -5
- package/lib/types/typeRegistry.js +0 -13
- package/lib/types/typeRegistry.js.map +0 -1
- package/lib/usage.d.ts +0 -1
- package/lib/usage.js +0 -22
- package/lib/usage.js.map +0 -1
- package/lib/v3.d.ts +0 -1
- package/lib/v3.js +0 -427
- package/lib/v3.js.map +0 -1
- package/lib/v3_experiment.d.ts +0 -1
- package/lib/v3_experiment.js +0 -407
- package/lib/v3_experiment.js.map +0 -1
|
@@ -4,9 +4,9 @@ import { Ref } from "../../encoder/ChangeTree";
|
|
|
4
4
|
import { Decoder } from "../Decoder";
|
|
5
5
|
import { DataChange } from "../DecodeOperation";
|
|
6
6
|
import { OPERATION } from "../../encoding/spec";
|
|
7
|
-
import { DefinitionType } from "../../annotations";
|
|
8
7
|
import { Schema } from "../../Schema";
|
|
9
|
-
import type {
|
|
8
|
+
import type { DefinitionType } from "../../annotations";
|
|
9
|
+
import type { CollectionSchema } from "../../types/custom/CollectionSchema";
|
|
10
10
|
|
|
11
11
|
//
|
|
12
12
|
// Discussion: https://github.com/colyseus/schema/issues/155
|
|
@@ -17,27 +17,74 @@ import type { ArraySchema } from "../../types/custom/ArraySchema";
|
|
|
17
17
|
// - Avoid closures by allowing to pass a context. (https://github.com/colyseus/schema/issues/155#issuecomment-1804694081)
|
|
18
18
|
//
|
|
19
19
|
|
|
20
|
-
type
|
|
20
|
+
export type GetCallbackProxy = (<T extends Schema>(instance: T) => CallbackProxy<T>);
|
|
21
|
+
|
|
22
|
+
export type CallbackProxy<T> = unknown extends T // is "any"?
|
|
21
23
|
? InstanceCallback<T> & CollectionCallback<any, any>
|
|
22
24
|
: T extends Collection<infer K, infer V, infer _>
|
|
23
25
|
? CollectionCallback<K, V>
|
|
24
|
-
: InstanceCallback<T
|
|
26
|
+
: InstanceCallback<T>;
|
|
25
27
|
|
|
26
28
|
type InstanceCallback<T> = {
|
|
29
|
+
/**
|
|
30
|
+
* Trigger callback when value of a property changes.
|
|
31
|
+
*
|
|
32
|
+
* @param prop name of the property
|
|
33
|
+
* @param callback callback to be triggered on property change
|
|
34
|
+
* @param immediate trigger immediatelly if property has been already set.
|
|
35
|
+
* @return callback to detach the listener
|
|
36
|
+
*/
|
|
27
37
|
listen<K extends NonFunctionPropNames<T>>(
|
|
28
38
|
prop: K,
|
|
29
39
|
callback: (value: T[K], previousValue: T[K]) => void,
|
|
30
40
|
immediate?: boolean,
|
|
31
|
-
)
|
|
32
|
-
|
|
41
|
+
): () => void;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Trigger callback whenever any property changed within this instance.
|
|
45
|
+
*
|
|
46
|
+
* @param prop name of the property
|
|
47
|
+
* @param callback callback to be triggered on property change
|
|
48
|
+
* @param immediate trigger immediatelly if property has been already set.
|
|
49
|
+
* @return callback to detach the listener
|
|
50
|
+
*/
|
|
51
|
+
onChange(callback: () => void): () => void;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Bind properties to another object. Changes on the properties will be reflected on the target object.
|
|
55
|
+
*
|
|
56
|
+
* @param targetObject object to bind properties to
|
|
57
|
+
* @param properties list of properties to bind. If not provided, all properties will be bound.
|
|
58
|
+
*/
|
|
33
59
|
bindTo(targetObject: any, properties?: Array<NonFunctionPropNames<T>>): void;
|
|
34
60
|
} & {
|
|
35
|
-
[K in NonFunctionNonPrimitivePropNames<T>]:
|
|
61
|
+
[K in NonFunctionNonPrimitivePropNames<T>]: CallbackProxy<T[K]>;
|
|
36
62
|
}
|
|
37
63
|
|
|
38
64
|
type CollectionCallback<K, V> = {
|
|
39
|
-
|
|
40
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Trigger callback when an item has been added to the collection.
|
|
67
|
+
*
|
|
68
|
+
* @param callback
|
|
69
|
+
* @param immediate
|
|
70
|
+
* @return callback to detach the onAdd listener
|
|
71
|
+
*/
|
|
72
|
+
onAdd(callback: (item: V, index: K) => void, immediate?: boolean): () => void;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Trigger callback when an item has been removed to the collection.
|
|
76
|
+
*
|
|
77
|
+
* @param callback
|
|
78
|
+
* @return callback to detach the onRemove listener
|
|
79
|
+
*/
|
|
80
|
+
onRemove(callback: (item: V, index: K) => void): () => void;
|
|
81
|
+
|
|
82
|
+
// /**
|
|
83
|
+
// * Trigger callback when an item has been removed to the collection.
|
|
84
|
+
// *
|
|
85
|
+
// * @param callback
|
|
86
|
+
// */
|
|
87
|
+
// onChange(callback: (item: V, index: K) => void): void;
|
|
41
88
|
};
|
|
42
89
|
|
|
43
90
|
type OnInstanceAvailableCallback = (callback: (ref: Ref, existing: boolean) => void) => void;
|
|
@@ -48,11 +95,13 @@ type CallContext = {
|
|
|
48
95
|
onInstanceAvailable?: OnInstanceAvailableCallback,
|
|
49
96
|
}
|
|
50
97
|
|
|
51
|
-
|
|
98
|
+
|
|
99
|
+
export function getDecoderStateCallbacks<T extends Schema>(decoder: Decoder<T>): GetCallbackProxy {
|
|
52
100
|
const $root = decoder.root;
|
|
53
101
|
const callbacks = $root.callbacks;
|
|
54
102
|
|
|
55
|
-
|
|
103
|
+
const onAddCalls: WeakMap<Function, boolean> = new WeakMap();
|
|
104
|
+
let currentOnAddCallback: Function | undefined;
|
|
56
105
|
|
|
57
106
|
decoder.triggerChanges = function (allChanges: DataChange[]) {
|
|
58
107
|
const uniqueRefIds = new Set<number>();
|
|
@@ -76,8 +125,6 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
76
125
|
for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
|
|
77
126
|
deleteCallbacks[i]();
|
|
78
127
|
}
|
|
79
|
-
// callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE]?.forEach(callback =>
|
|
80
|
-
// callback());
|
|
81
128
|
}
|
|
82
129
|
|
|
83
130
|
if (ref instanceof Schema) {
|
|
@@ -86,47 +133,35 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
86
133
|
//
|
|
87
134
|
|
|
88
135
|
if (!uniqueRefIds.has(refId)) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
console.error(e);
|
|
136
|
+
// trigger onChange
|
|
137
|
+
const replaceCallbacks = $callbacks?.[OPERATION.REPLACE];
|
|
138
|
+
for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
|
|
139
|
+
replaceCallbacks[i]();
|
|
140
|
+
// try {
|
|
141
|
+
// } catch (e) {
|
|
142
|
+
// console.error(e);
|
|
143
|
+
// }
|
|
98
144
|
}
|
|
99
145
|
}
|
|
100
146
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
147
|
+
if ($callbacks.hasOwnProperty(change.field)) {
|
|
148
|
+
const fieldCallbacks = $callbacks[change.field];
|
|
149
|
+
for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
|
|
150
|
+
fieldCallbacks[i](change.value, change.previousValue);
|
|
151
|
+
// try {
|
|
152
|
+
// } catch (e) {
|
|
153
|
+
// console.error(e);
|
|
154
|
+
// }
|
|
107
155
|
}
|
|
108
|
-
|
|
109
|
-
} catch (e) {
|
|
110
|
-
//
|
|
111
|
-
console.error(e);
|
|
112
156
|
}
|
|
113
157
|
|
|
158
|
+
|
|
114
159
|
} else {
|
|
115
160
|
//
|
|
116
161
|
// Handle collection of items
|
|
117
162
|
//
|
|
118
163
|
|
|
119
|
-
if (change.op
|
|
120
|
-
// triger onAdd
|
|
121
|
-
|
|
122
|
-
isTriggeringOnAdd = true;
|
|
123
|
-
const addCallbacks = $callbacks[OPERATION.ADD];
|
|
124
|
-
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
125
|
-
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
126
|
-
}
|
|
127
|
-
isTriggeringOnAdd = false;
|
|
128
|
-
|
|
129
|
-
} else if ((change.op & OPERATION.DELETE) === OPERATION.DELETE) {
|
|
164
|
+
if ((change.op & OPERATION.DELETE) === OPERATION.DELETE) {
|
|
130
165
|
//
|
|
131
166
|
// FIXME: `previousValue` should always be available.
|
|
132
167
|
//
|
|
@@ -139,13 +174,19 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
139
174
|
}
|
|
140
175
|
|
|
141
176
|
// Handle DELETE_AND_ADD operations
|
|
142
|
-
// FIXME: should we set "isTriggeringOnAdd" here?
|
|
143
177
|
if ((change.op & OPERATION.ADD) === OPERATION.ADD) {
|
|
144
178
|
const addCallbacks = $callbacks[OPERATION.ADD];
|
|
145
179
|
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
146
180
|
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
147
181
|
}
|
|
148
182
|
}
|
|
183
|
+
|
|
184
|
+
} else if ((change.op & OPERATION.ADD) === OPERATION.ADD && change.previousValue === undefined) {
|
|
185
|
+
// triger onAdd
|
|
186
|
+
const addCallbacks = $callbacks[OPERATION.ADD];
|
|
187
|
+
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
188
|
+
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
189
|
+
}
|
|
149
190
|
}
|
|
150
191
|
|
|
151
192
|
// trigger onChange
|
|
@@ -161,7 +202,10 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
161
202
|
}
|
|
162
203
|
};
|
|
163
204
|
|
|
164
|
-
function getProxy(
|
|
205
|
+
function getProxy(
|
|
206
|
+
metadataOrType: Metadata | DefinitionType,
|
|
207
|
+
context: CallContext
|
|
208
|
+
) {
|
|
165
209
|
let metadata: Metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;
|
|
166
210
|
let isCollection = (
|
|
167
211
|
(context.instance && typeof (context.instance['forEach']) === "function") ||
|
|
@@ -170,7 +214,7 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
170
214
|
|
|
171
215
|
if (metadata && !isCollection) {
|
|
172
216
|
|
|
173
|
-
const
|
|
217
|
+
const onAddListen = function (
|
|
174
218
|
ref: Ref,
|
|
175
219
|
prop: string,
|
|
176
220
|
callback: (value: any, previousValue: any) => void, immediate: boolean
|
|
@@ -179,7 +223,7 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
179
223
|
if (
|
|
180
224
|
immediate &&
|
|
181
225
|
context.instance[prop] !== undefined &&
|
|
182
|
-
!
|
|
226
|
+
!onAddCalls.has(currentOnAddCallback) // Workaround for https://github.com/colyseus/schema/issues/147
|
|
183
227
|
) {
|
|
184
228
|
callback(context.instance[prop], undefined);
|
|
185
229
|
}
|
|
@@ -192,28 +236,49 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
192
236
|
return new Proxy({
|
|
193
237
|
listen: function listen(prop: string, callback: (value: any, previousValue: any) => void, immediate: boolean = true) {
|
|
194
238
|
if (context.instance) {
|
|
195
|
-
return
|
|
239
|
+
return onAddListen(context.instance, prop, callback, immediate);
|
|
196
240
|
|
|
197
241
|
} else {
|
|
198
242
|
// collection instance not received yet
|
|
199
|
-
|
|
200
|
-
|
|
243
|
+
let detachCallback = () => {};
|
|
244
|
+
|
|
245
|
+
context.onInstanceAvailable((ref: Ref, existing: boolean) => {
|
|
246
|
+
detachCallback = onAddListen(ref, prop, callback, immediate && existing && !onAddCalls.has(currentOnAddCallback))
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return () => detachCallback();
|
|
201
250
|
}
|
|
202
251
|
},
|
|
252
|
+
|
|
203
253
|
onChange: function onChange(callback: () => void) {
|
|
204
254
|
return $root.addCallback(
|
|
205
255
|
$root.refIds.get(context.instance),
|
|
206
256
|
OPERATION.REPLACE,
|
|
207
257
|
callback
|
|
208
258
|
);
|
|
209
|
-
|
|
210
259
|
},
|
|
260
|
+
|
|
261
|
+
//
|
|
262
|
+
// TODO: refactor `bindTo()` implementation.
|
|
263
|
+
// There is room for improvement.
|
|
264
|
+
//
|
|
211
265
|
bindTo: function bindTo(targetObject: any, properties?: string[]) {
|
|
212
|
-
|
|
266
|
+
if (!properties) {
|
|
267
|
+
properties = Object.keys(metadata).map((index) => metadata[index as any as number].name);
|
|
268
|
+
}
|
|
269
|
+
return $root.addCallback(
|
|
270
|
+
$root.refIds.get(context.instance),
|
|
271
|
+
OPERATION.REPLACE,
|
|
272
|
+
() => {
|
|
273
|
+
properties.forEach((prop) =>
|
|
274
|
+
targetObject[prop] = context.instance[prop])
|
|
275
|
+
}
|
|
276
|
+
);
|
|
213
277
|
}
|
|
214
278
|
}, {
|
|
215
279
|
get(target, prop: string) {
|
|
216
|
-
|
|
280
|
+
const metadataField = metadata[metadata[prop]];
|
|
281
|
+
if (metadataField) {
|
|
217
282
|
const instance = context.instance?.[prop];
|
|
218
283
|
const onInstanceAvailable: OnInstanceAvailableCallback = (
|
|
219
284
|
(callback: (ref: Ref, existing: boolean) => void) => {
|
|
@@ -233,8 +298,9 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
233
298
|
}
|
|
234
299
|
}
|
|
235
300
|
);
|
|
236
|
-
return getProxy(
|
|
237
|
-
instance
|
|
301
|
+
return getProxy(metadataField.type, {
|
|
302
|
+
// make sure refId is available, otherwise need to wait for the instance to be available.
|
|
303
|
+
instance: ($root.refIds.get(instance) && instance),
|
|
238
304
|
parentInstance: context.instance,
|
|
239
305
|
onInstanceAvailable,
|
|
240
306
|
});
|
|
@@ -257,9 +323,16 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
257
323
|
const onAdd = function (ref: Ref, callback: (value: any, key: any) => void, immediate: boolean) {
|
|
258
324
|
// Trigger callback on existing items
|
|
259
325
|
if (immediate) {
|
|
260
|
-
(ref as
|
|
326
|
+
(ref as CollectionSchema).forEach((v, k) => callback(v, k));
|
|
261
327
|
}
|
|
262
|
-
|
|
328
|
+
|
|
329
|
+
return $root.addCallback($root.refIds.get(ref), OPERATION.ADD, (value, key) => {
|
|
330
|
+
onAddCalls.set(callback, true);
|
|
331
|
+
currentOnAddCallback = callback;
|
|
332
|
+
callback(value, key);
|
|
333
|
+
onAddCalls.delete(callback)
|
|
334
|
+
currentOnAddCallback = undefined;
|
|
335
|
+
});
|
|
263
336
|
};
|
|
264
337
|
|
|
265
338
|
const onRemove = function (ref: Ref, callback: (value: any, key: any) => void) {
|
|
@@ -272,25 +345,34 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
272
345
|
// https://github.com/colyseus/schema/issues/147
|
|
273
346
|
// If parent instance has "onAdd" registered, avoid triggering immediate callback.
|
|
274
347
|
//
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
348
|
+
|
|
349
|
+
if (context.instance) {
|
|
350
|
+
return onAdd(context.instance, callback, immediate && !onAddCalls.has(currentOnAddCallback));
|
|
351
|
+
|
|
352
|
+
} else if (context.onInstanceAvailable) {
|
|
278
353
|
// collection instance not received yet
|
|
279
|
-
|
|
280
|
-
onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));
|
|
354
|
+
let detachCallback = () => {};
|
|
281
355
|
|
|
282
|
-
|
|
283
|
-
|
|
356
|
+
context.onInstanceAvailable((ref: Ref, existing: boolean) => {
|
|
357
|
+
detachCallback = onAdd(ref, callback, immediate && existing && !onAddCalls.has(currentOnAddCallback));
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
return () => detachCallback();
|
|
284
361
|
}
|
|
285
362
|
},
|
|
286
363
|
onRemove: function(callback: (value, key) => void) {
|
|
287
364
|
if (context.onInstanceAvailable) {
|
|
288
365
|
// collection instance not received yet
|
|
289
|
-
|
|
290
|
-
|
|
366
|
+
let detachCallback = () => {};
|
|
367
|
+
|
|
368
|
+
context.onInstanceAvailable((ref: Ref) => {
|
|
369
|
+
detachCallback = onRemove(ref, callback)
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return () => detachCallback();
|
|
291
373
|
|
|
292
374
|
} else if (context.instance) {
|
|
293
|
-
onRemove(context.instance, callback);
|
|
375
|
+
return onRemove(context.instance, callback);
|
|
294
376
|
}
|
|
295
377
|
},
|
|
296
378
|
}, {
|
|
@@ -307,20 +389,9 @@ export function getStateCallbacks(decoder: Decoder) {
|
|
|
307
389
|
}
|
|
308
390
|
}
|
|
309
391
|
|
|
310
|
-
function $<T>(instance: T):
|
|
311
|
-
return getProxy(undefined, { instance }) as
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return {
|
|
315
|
-
$,
|
|
316
|
-
trigger: function trigger(changes: DataChange[]) {
|
|
317
|
-
for (let i = 0, l = changes.length; i < l; i++) {
|
|
318
|
-
const change = changes[i];
|
|
319
|
-
|
|
320
|
-
change.op
|
|
321
|
-
change.ref
|
|
322
|
-
}
|
|
323
|
-
}
|
|
392
|
+
function $<T>(instance: T): CallbackProxy<T> {
|
|
393
|
+
return getProxy(undefined, { instance }) as CallbackProxy<T>;
|
|
324
394
|
}
|
|
325
395
|
|
|
396
|
+
return $;
|
|
326
397
|
}
|