@colyseus/schema 3.0.0-alpha.11 → 3.0.0-alpha.13
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 +131 -61
- package/build/cjs/index.js +238 -5
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +237 -6
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +238 -5
- package/lib/decoder/strategy/StateCallbacks.d.ts +4 -7
- package/lib/decoder/strategy/StateCallbacks.js +6 -12
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +1 -1
- package/lib/encoder/Encoder.js +4 -5
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/decoder/strategy/StateCallbacks.ts +11 -20
- package/src/encoder/Encoder.ts +5 -5
- package/src/index.ts +3 -0
package/build/esm/index.mjs
CHANGED
|
@@ -3393,9 +3393,8 @@ class Encoder {
|
|
|
3393
3393
|
this.state = state;
|
|
3394
3394
|
state[$changes].setRoot(this.root);
|
|
3395
3395
|
}
|
|
3396
|
-
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
|
|
3396
|
+
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
|
|
3397
3397
|
const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
|
|
3398
|
-
const isEncodeAll = this.root.allChanges === changeTrees;
|
|
3399
3398
|
const hasView = (view !== undefined);
|
|
3400
3399
|
const rootChangeTree = this.state[$changes];
|
|
3401
3400
|
const changeTreesIterator = changeTrees.entries();
|
|
@@ -3463,7 +3462,7 @@ class Encoder {
|
|
|
3463
3462
|
if (buffer === this.sharedBuffer) {
|
|
3464
3463
|
this.sharedBuffer = buffer;
|
|
3465
3464
|
}
|
|
3466
|
-
return this.encode({ offset: initialOffset }, view, buffer);
|
|
3465
|
+
return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);
|
|
3467
3466
|
}
|
|
3468
3467
|
else {
|
|
3469
3468
|
//
|
|
@@ -3483,14 +3482,14 @@ class Encoder {
|
|
|
3483
3482
|
// Array.from(this.root.allChanges.entries()).map((item) => {
|
|
3484
3483
|
// console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
|
|
3485
3484
|
// });
|
|
3486
|
-
return this.encode(it, undefined, buffer, this.root.allChanges);
|
|
3485
|
+
return this.encode(it, undefined, buffer, this.root.allChanges, true);
|
|
3487
3486
|
}
|
|
3488
3487
|
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3489
3488
|
const viewOffset = it.offset;
|
|
3490
3489
|
// console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
|
|
3491
3490
|
// this.debugAllFilteredChanges();
|
|
3492
3491
|
// try to encode "filtered" changes
|
|
3493
|
-
this.encode(it, view, bytes, this.root.allFilteredChanges);
|
|
3492
|
+
this.encode(it, view, bytes, this.root.allFilteredChanges, true);
|
|
3494
3493
|
return Buffer.concat([
|
|
3495
3494
|
bytes.subarray(0, sharedOffset),
|
|
3496
3495
|
bytes.subarray(viewOffset, it.offset)
|
|
@@ -3960,6 +3959,238 @@ __decorate([
|
|
|
3960
3959
|
type([ReflectionType])
|
|
3961
3960
|
], Reflection.prototype, "types", void 0);
|
|
3962
3961
|
|
|
3962
|
+
function getStateCallbacks(decoder) {
|
|
3963
|
+
const $root = decoder.root;
|
|
3964
|
+
const callbacks = $root.callbacks;
|
|
3965
|
+
let isTriggeringOnAdd = false;
|
|
3966
|
+
decoder.triggerChanges = function (allChanges) {
|
|
3967
|
+
const uniqueRefIds = new Set();
|
|
3968
|
+
for (let i = 0, l = allChanges.length; i < l; i++) {
|
|
3969
|
+
const change = allChanges[i];
|
|
3970
|
+
const refId = change.refId;
|
|
3971
|
+
const ref = change.ref;
|
|
3972
|
+
const $callbacks = callbacks[refId];
|
|
3973
|
+
if (!$callbacks) {
|
|
3974
|
+
continue;
|
|
3975
|
+
}
|
|
3976
|
+
//
|
|
3977
|
+
// trigger onRemove on child structure.
|
|
3978
|
+
//
|
|
3979
|
+
if ((change.op & OPERATION.DELETE) === OPERATION.DELETE &&
|
|
3980
|
+
change.previousValue instanceof Schema) {
|
|
3981
|
+
const deleteCallbacks = callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE];
|
|
3982
|
+
for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
|
|
3983
|
+
deleteCallbacks[i]();
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
if (ref instanceof Schema) {
|
|
3987
|
+
//
|
|
3988
|
+
// Handle schema instance
|
|
3989
|
+
//
|
|
3990
|
+
if (!uniqueRefIds.has(refId)) {
|
|
3991
|
+
try {
|
|
3992
|
+
// trigger onChange
|
|
3993
|
+
const replaceCallbacks = $callbacks?.[OPERATION.REPLACE];
|
|
3994
|
+
for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
|
|
3995
|
+
replaceCallbacks[i]();
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
catch (e) {
|
|
3999
|
+
console.error(e);
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
try {
|
|
4003
|
+
if ($callbacks.hasOwnProperty(change.field)) {
|
|
4004
|
+
const fieldCallbacks = $callbacks[change.field];
|
|
4005
|
+
for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
|
|
4006
|
+
fieldCallbacks[i](change.value, change.previousValue);
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
catch (e) {
|
|
4011
|
+
//
|
|
4012
|
+
console.error(e);
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
4015
|
+
else {
|
|
4016
|
+
//
|
|
4017
|
+
// Handle collection of items
|
|
4018
|
+
//
|
|
4019
|
+
if (change.op === OPERATION.ADD && change.previousValue === undefined) {
|
|
4020
|
+
// triger onAdd
|
|
4021
|
+
isTriggeringOnAdd = true;
|
|
4022
|
+
const addCallbacks = $callbacks[OPERATION.ADD];
|
|
4023
|
+
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
4024
|
+
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
4025
|
+
}
|
|
4026
|
+
isTriggeringOnAdd = false;
|
|
4027
|
+
}
|
|
4028
|
+
else if ((change.op & OPERATION.DELETE) === OPERATION.DELETE) {
|
|
4029
|
+
//
|
|
4030
|
+
// FIXME: `previousValue` should always be available.
|
|
4031
|
+
//
|
|
4032
|
+
if (change.previousValue !== undefined) {
|
|
4033
|
+
// triger onRemove
|
|
4034
|
+
const deleteCallbacks = $callbacks[OPERATION.DELETE];
|
|
4035
|
+
for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
|
|
4036
|
+
deleteCallbacks[i](change.previousValue, change.dynamicIndex ?? change.field);
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4039
|
+
// Handle DELETE_AND_ADD operations
|
|
4040
|
+
// FIXME: should we set "isTriggeringOnAdd" here?
|
|
4041
|
+
if ((change.op & OPERATION.ADD) === OPERATION.ADD) {
|
|
4042
|
+
const addCallbacks = $callbacks[OPERATION.ADD];
|
|
4043
|
+
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
4044
|
+
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
// trigger onChange
|
|
4049
|
+
if (change.value !== change.previousValue) {
|
|
4050
|
+
const replaceCallbacks = $callbacks[OPERATION.REPLACE];
|
|
4051
|
+
for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
|
|
4052
|
+
replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
uniqueRefIds.add(refId);
|
|
4057
|
+
}
|
|
4058
|
+
};
|
|
4059
|
+
function getProxy(metadataOrType, context) {
|
|
4060
|
+
let metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;
|
|
4061
|
+
let isCollection = ((context.instance && typeof (context.instance['forEach']) === "function") ||
|
|
4062
|
+
(metadataOrType && typeof (metadataOrType[Symbol.metadata]) === "undefined"));
|
|
4063
|
+
if (metadata && !isCollection) {
|
|
4064
|
+
const onAdd = function (ref, prop, callback, immediate) {
|
|
4065
|
+
// immediate trigger
|
|
4066
|
+
if (immediate &&
|
|
4067
|
+
context.instance[prop] !== undefined &&
|
|
4068
|
+
!isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)
|
|
4069
|
+
) {
|
|
4070
|
+
callback(context.instance[prop], undefined);
|
|
4071
|
+
}
|
|
4072
|
+
return $root.addCallback($root.refIds.get(ref), prop, callback);
|
|
4073
|
+
};
|
|
4074
|
+
/**
|
|
4075
|
+
* Schema instances
|
|
4076
|
+
*/
|
|
4077
|
+
return new Proxy({
|
|
4078
|
+
listen: function listen(prop, callback, immediate = true) {
|
|
4079
|
+
if (context.instance) {
|
|
4080
|
+
return onAdd(context.instance, prop, callback, immediate);
|
|
4081
|
+
}
|
|
4082
|
+
else {
|
|
4083
|
+
// collection instance not received yet
|
|
4084
|
+
context.onInstanceAvailable((ref, existing) => onAdd(ref, prop, callback, immediate && existing));
|
|
4085
|
+
}
|
|
4086
|
+
},
|
|
4087
|
+
onChange: function onChange(callback) {
|
|
4088
|
+
return $root.addCallback($root.refIds.get(context.instance), OPERATION.REPLACE, callback);
|
|
4089
|
+
},
|
|
4090
|
+
bindTo: function bindTo(targetObject, properties) {
|
|
4091
|
+
// return $root.addCallback(
|
|
4092
|
+
// $root.refIds.get(context.instance),
|
|
4093
|
+
// OPERATION.BIND,
|
|
4094
|
+
// callback
|
|
4095
|
+
// );
|
|
4096
|
+
console.log("bindTo", targetObject, properties);
|
|
4097
|
+
}
|
|
4098
|
+
}, {
|
|
4099
|
+
get(target, prop) {
|
|
4100
|
+
if (metadata[prop]) {
|
|
4101
|
+
const instance = context.instance?.[prop];
|
|
4102
|
+
const onInstanceAvailable = ((callback) => {
|
|
4103
|
+
const unbind = $(context.instance).listen(prop, (value, _) => {
|
|
4104
|
+
callback(value, false);
|
|
4105
|
+
// FIXME: by "unbinding" the callback here,
|
|
4106
|
+
// it will not support when the server
|
|
4107
|
+
// re-instantiates the instance.
|
|
4108
|
+
//
|
|
4109
|
+
unbind?.();
|
|
4110
|
+
}, false);
|
|
4111
|
+
// has existing value
|
|
4112
|
+
if ($root.refIds.get(instance) !== undefined) {
|
|
4113
|
+
callback(instance, true);
|
|
4114
|
+
}
|
|
4115
|
+
});
|
|
4116
|
+
return getProxy(metadata[prop].type, {
|
|
4117
|
+
instance,
|
|
4118
|
+
parentInstance: context.instance,
|
|
4119
|
+
onInstanceAvailable,
|
|
4120
|
+
});
|
|
4121
|
+
}
|
|
4122
|
+
else {
|
|
4123
|
+
// accessing the function
|
|
4124
|
+
return target[prop];
|
|
4125
|
+
}
|
|
4126
|
+
},
|
|
4127
|
+
has(target, prop) { return metadata[prop] !== undefined; },
|
|
4128
|
+
set(_, _1, _2) { throw new Error("not allowed"); },
|
|
4129
|
+
deleteProperty(_, _1) { throw new Error("not allowed"); },
|
|
4130
|
+
});
|
|
4131
|
+
}
|
|
4132
|
+
else {
|
|
4133
|
+
/**
|
|
4134
|
+
* Collection instances
|
|
4135
|
+
*/
|
|
4136
|
+
const onAdd = function (ref, callback, immediate) {
|
|
4137
|
+
// Trigger callback on existing items
|
|
4138
|
+
if (immediate) {
|
|
4139
|
+
ref.forEach((v, k) => callback(v, k));
|
|
4140
|
+
}
|
|
4141
|
+
return $root.addCallback($root.refIds.get(ref), OPERATION.ADD, callback);
|
|
4142
|
+
};
|
|
4143
|
+
const onRemove = function (ref, callback) {
|
|
4144
|
+
return $root.addCallback($root.refIds.get(ref), OPERATION.DELETE, callback);
|
|
4145
|
+
};
|
|
4146
|
+
return new Proxy({
|
|
4147
|
+
onAdd: function (callback, immediate = true) {
|
|
4148
|
+
//
|
|
4149
|
+
// https://github.com/colyseus/schema/issues/147
|
|
4150
|
+
// If parent instance has "onAdd" registered, avoid triggering immediate callback.
|
|
4151
|
+
//
|
|
4152
|
+
// FIXME: "isTriggeringOnAdd" is a workaround. We should find a better way to handle this.
|
|
4153
|
+
//
|
|
4154
|
+
if (context.onInstanceAvailable) {
|
|
4155
|
+
// collection instance not received yet
|
|
4156
|
+
context.onInstanceAvailable((ref, existing) => onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));
|
|
4157
|
+
}
|
|
4158
|
+
else if (context.instance) {
|
|
4159
|
+
onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);
|
|
4160
|
+
}
|
|
4161
|
+
},
|
|
4162
|
+
onRemove: function (callback) {
|
|
4163
|
+
if (context.onInstanceAvailable) {
|
|
4164
|
+
// collection instance not received yet
|
|
4165
|
+
context.onInstanceAvailable((ref) => onRemove(ref, callback));
|
|
4166
|
+
}
|
|
4167
|
+
else if (context.instance) {
|
|
4168
|
+
onRemove(context.instance, callback);
|
|
4169
|
+
}
|
|
4170
|
+
},
|
|
4171
|
+
}, {
|
|
4172
|
+
get(target, prop) {
|
|
4173
|
+
if (!target[prop]) {
|
|
4174
|
+
throw new Error(`Can't access '${prop}' through callback proxy. access the instance directly.`);
|
|
4175
|
+
}
|
|
4176
|
+
return target[prop];
|
|
4177
|
+
},
|
|
4178
|
+
has(target, prop) { return target[prop] !== undefined; },
|
|
4179
|
+
set(_, _1, _2) { throw new Error("not allowed"); },
|
|
4180
|
+
deleteProperty(_, _1) { throw new Error("not allowed"); },
|
|
4181
|
+
});
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
function $(instance) {
|
|
4185
|
+
return getProxy(undefined, { instance });
|
|
4186
|
+
}
|
|
4187
|
+
return $(decoder.state);
|
|
4188
|
+
}
|
|
4189
|
+
|
|
4190
|
+
function getRawChangesCallback(decoder, callback) {
|
|
4191
|
+
decoder.triggerChanges = callback;
|
|
4192
|
+
}
|
|
4193
|
+
|
|
3963
4194
|
class StateView {
|
|
3964
4195
|
constructor() {
|
|
3965
4196
|
/**
|
|
@@ -4153,5 +4384,5 @@ registerType("array", { constructor: ArraySchema });
|
|
|
4153
4384
|
registerType("set", { constructor: SetSchema });
|
|
4154
4385
|
registerType("collection", { constructor: CollectionSchema, });
|
|
4155
4386
|
|
|
4156
|
-
export { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track, ArraySchema, ChangeTree, CollectionSchema, Decoder, Encoder, MapSchema, Metadata, OPERATION, Reflection, ReflectionField, ReflectionType, Schema, SetSchema, StateView, TypeContext, decode, decodeKeyValueOperation, decodeSchemaOperation, defineTypes, deprecated, dumpChanges, encode, encodeArray as encodeKeyValueOperation, encodeSchemaOperation, registerType, type, view };
|
|
4387
|
+
export { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track, ArraySchema, ChangeTree, CollectionSchema, Decoder, Encoder, MapSchema, Metadata, OPERATION, Reflection, ReflectionField, ReflectionType, Schema, SetSchema, StateView, TypeContext, decode, decodeKeyValueOperation, decodeSchemaOperation, defineTypes, deprecated, dumpChanges, encode, encodeArray as encodeKeyValueOperation, encodeSchemaOperation, getRawChangesCallback, getStateCallbacks, registerType, type, view };
|
|
4157
4388
|
//# sourceMappingURL=index.mjs.map
|