@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.
@@ -3399,9 +3399,8 @@
3399
3399
  this.state = state;
3400
3400
  state[$changes].setRoot(this.root);
3401
3401
  }
3402
- encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
3402
+ encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
3403
3403
  const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
3404
- const isEncodeAll = this.root.allChanges === changeTrees;
3405
3404
  const hasView = (view !== undefined);
3406
3405
  const rootChangeTree = this.state[$changes];
3407
3406
  const changeTreesIterator = changeTrees.entries();
@@ -3469,7 +3468,7 @@
3469
3468
  if (buffer === this.sharedBuffer) {
3470
3469
  this.sharedBuffer = buffer;
3471
3470
  }
3472
- return this.encode({ offset: initialOffset }, view, buffer);
3471
+ return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);
3473
3472
  }
3474
3473
  else {
3475
3474
  //
@@ -3489,14 +3488,14 @@
3489
3488
  // Array.from(this.root.allChanges.entries()).map((item) => {
3490
3489
  // console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
3491
3490
  // });
3492
- return this.encode(it, undefined, buffer, this.root.allChanges);
3491
+ return this.encode(it, undefined, buffer, this.root.allChanges, true);
3493
3492
  }
3494
3493
  encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
3495
3494
  const viewOffset = it.offset;
3496
3495
  // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
3497
3496
  // this.debugAllFilteredChanges();
3498
3497
  // try to encode "filtered" changes
3499
- this.encode(it, view, bytes, this.root.allFilteredChanges);
3498
+ this.encode(it, view, bytes, this.root.allFilteredChanges, true);
3500
3499
  return Buffer.concat([
3501
3500
  bytes.subarray(0, sharedOffset),
3502
3501
  bytes.subarray(viewOffset, it.offset)
@@ -3966,6 +3965,238 @@
3966
3965
  type([ReflectionType])
3967
3966
  ], Reflection.prototype, "types", void 0);
3968
3967
 
3968
+ function getStateCallbacks(decoder) {
3969
+ const $root = decoder.root;
3970
+ const callbacks = $root.callbacks;
3971
+ let isTriggeringOnAdd = false;
3972
+ decoder.triggerChanges = function (allChanges) {
3973
+ const uniqueRefIds = new Set();
3974
+ for (let i = 0, l = allChanges.length; i < l; i++) {
3975
+ const change = allChanges[i];
3976
+ const refId = change.refId;
3977
+ const ref = change.ref;
3978
+ const $callbacks = callbacks[refId];
3979
+ if (!$callbacks) {
3980
+ continue;
3981
+ }
3982
+ //
3983
+ // trigger onRemove on child structure.
3984
+ //
3985
+ if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
3986
+ change.previousValue instanceof Schema) {
3987
+ const deleteCallbacks = callbacks[$root.refIds.get(change.previousValue)]?.[exports.OPERATION.DELETE];
3988
+ for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
3989
+ deleteCallbacks[i]();
3990
+ }
3991
+ }
3992
+ if (ref instanceof Schema) {
3993
+ //
3994
+ // Handle schema instance
3995
+ //
3996
+ if (!uniqueRefIds.has(refId)) {
3997
+ try {
3998
+ // trigger onChange
3999
+ const replaceCallbacks = $callbacks?.[exports.OPERATION.REPLACE];
4000
+ for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
4001
+ replaceCallbacks[i]();
4002
+ }
4003
+ }
4004
+ catch (e) {
4005
+ console.error(e);
4006
+ }
4007
+ }
4008
+ try {
4009
+ if ($callbacks.hasOwnProperty(change.field)) {
4010
+ const fieldCallbacks = $callbacks[change.field];
4011
+ for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
4012
+ fieldCallbacks[i](change.value, change.previousValue);
4013
+ }
4014
+ }
4015
+ }
4016
+ catch (e) {
4017
+ //
4018
+ console.error(e);
4019
+ }
4020
+ }
4021
+ else {
4022
+ //
4023
+ // Handle collection of items
4024
+ //
4025
+ if (change.op === exports.OPERATION.ADD && change.previousValue === undefined) {
4026
+ // triger onAdd
4027
+ isTriggeringOnAdd = true;
4028
+ const addCallbacks = $callbacks[exports.OPERATION.ADD];
4029
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4030
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4031
+ }
4032
+ isTriggeringOnAdd = false;
4033
+ }
4034
+ else if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
4035
+ //
4036
+ // FIXME: `previousValue` should always be available.
4037
+ //
4038
+ if (change.previousValue !== undefined) {
4039
+ // triger onRemove
4040
+ const deleteCallbacks = $callbacks[exports.OPERATION.DELETE];
4041
+ for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
4042
+ deleteCallbacks[i](change.previousValue, change.dynamicIndex ?? change.field);
4043
+ }
4044
+ }
4045
+ // Handle DELETE_AND_ADD operations
4046
+ // FIXME: should we set "isTriggeringOnAdd" here?
4047
+ if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD) {
4048
+ const addCallbacks = $callbacks[exports.OPERATION.ADD];
4049
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4050
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4051
+ }
4052
+ }
4053
+ }
4054
+ // trigger onChange
4055
+ if (change.value !== change.previousValue) {
4056
+ const replaceCallbacks = $callbacks[exports.OPERATION.REPLACE];
4057
+ for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
4058
+ replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4059
+ }
4060
+ }
4061
+ }
4062
+ uniqueRefIds.add(refId);
4063
+ }
4064
+ };
4065
+ function getProxy(metadataOrType, context) {
4066
+ let metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;
4067
+ let isCollection = ((context.instance && typeof (context.instance['forEach']) === "function") ||
4068
+ (metadataOrType && typeof (metadataOrType[Symbol.metadata]) === "undefined"));
4069
+ if (metadata && !isCollection) {
4070
+ const onAdd = function (ref, prop, callback, immediate) {
4071
+ // immediate trigger
4072
+ if (immediate &&
4073
+ context.instance[prop] !== undefined &&
4074
+ !isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)
4075
+ ) {
4076
+ callback(context.instance[prop], undefined);
4077
+ }
4078
+ return $root.addCallback($root.refIds.get(ref), prop, callback);
4079
+ };
4080
+ /**
4081
+ * Schema instances
4082
+ */
4083
+ return new Proxy({
4084
+ listen: function listen(prop, callback, immediate = true) {
4085
+ if (context.instance) {
4086
+ return onAdd(context.instance, prop, callback, immediate);
4087
+ }
4088
+ else {
4089
+ // collection instance not received yet
4090
+ context.onInstanceAvailable((ref, existing) => onAdd(ref, prop, callback, immediate && existing));
4091
+ }
4092
+ },
4093
+ onChange: function onChange(callback) {
4094
+ return $root.addCallback($root.refIds.get(context.instance), exports.OPERATION.REPLACE, callback);
4095
+ },
4096
+ bindTo: function bindTo(targetObject, properties) {
4097
+ // return $root.addCallback(
4098
+ // $root.refIds.get(context.instance),
4099
+ // OPERATION.BIND,
4100
+ // callback
4101
+ // );
4102
+ console.log("bindTo", targetObject, properties);
4103
+ }
4104
+ }, {
4105
+ get(target, prop) {
4106
+ if (metadata[prop]) {
4107
+ const instance = context.instance?.[prop];
4108
+ const onInstanceAvailable = ((callback) => {
4109
+ const unbind = $(context.instance).listen(prop, (value, _) => {
4110
+ callback(value, false);
4111
+ // FIXME: by "unbinding" the callback here,
4112
+ // it will not support when the server
4113
+ // re-instantiates the instance.
4114
+ //
4115
+ unbind?.();
4116
+ }, false);
4117
+ // has existing value
4118
+ if ($root.refIds.get(instance) !== undefined) {
4119
+ callback(instance, true);
4120
+ }
4121
+ });
4122
+ return getProxy(metadata[prop].type, {
4123
+ instance,
4124
+ parentInstance: context.instance,
4125
+ onInstanceAvailable,
4126
+ });
4127
+ }
4128
+ else {
4129
+ // accessing the function
4130
+ return target[prop];
4131
+ }
4132
+ },
4133
+ has(target, prop) { return metadata[prop] !== undefined; },
4134
+ set(_, _1, _2) { throw new Error("not allowed"); },
4135
+ deleteProperty(_, _1) { throw new Error("not allowed"); },
4136
+ });
4137
+ }
4138
+ else {
4139
+ /**
4140
+ * Collection instances
4141
+ */
4142
+ const onAdd = function (ref, callback, immediate) {
4143
+ // Trigger callback on existing items
4144
+ if (immediate) {
4145
+ ref.forEach((v, k) => callback(v, k));
4146
+ }
4147
+ return $root.addCallback($root.refIds.get(ref), exports.OPERATION.ADD, callback);
4148
+ };
4149
+ const onRemove = function (ref, callback) {
4150
+ return $root.addCallback($root.refIds.get(ref), exports.OPERATION.DELETE, callback);
4151
+ };
4152
+ return new Proxy({
4153
+ onAdd: function (callback, immediate = true) {
4154
+ //
4155
+ // https://github.com/colyseus/schema/issues/147
4156
+ // If parent instance has "onAdd" registered, avoid triggering immediate callback.
4157
+ //
4158
+ // FIXME: "isTriggeringOnAdd" is a workaround. We should find a better way to handle this.
4159
+ //
4160
+ if (context.onInstanceAvailable) {
4161
+ // collection instance not received yet
4162
+ context.onInstanceAvailable((ref, existing) => onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));
4163
+ }
4164
+ else if (context.instance) {
4165
+ onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);
4166
+ }
4167
+ },
4168
+ onRemove: function (callback) {
4169
+ if (context.onInstanceAvailable) {
4170
+ // collection instance not received yet
4171
+ context.onInstanceAvailable((ref) => onRemove(ref, callback));
4172
+ }
4173
+ else if (context.instance) {
4174
+ onRemove(context.instance, callback);
4175
+ }
4176
+ },
4177
+ }, {
4178
+ get(target, prop) {
4179
+ if (!target[prop]) {
4180
+ throw new Error(`Can't access '${prop}' through callback proxy. access the instance directly.`);
4181
+ }
4182
+ return target[prop];
4183
+ },
4184
+ has(target, prop) { return target[prop] !== undefined; },
4185
+ set(_, _1, _2) { throw new Error("not allowed"); },
4186
+ deleteProperty(_, _1) { throw new Error("not allowed"); },
4187
+ });
4188
+ }
4189
+ }
4190
+ function $(instance) {
4191
+ return getProxy(undefined, { instance });
4192
+ }
4193
+ return $(decoder.state);
4194
+ }
4195
+
4196
+ function getRawChangesCallback(decoder, callback) {
4197
+ decoder.triggerChanges = callback;
4198
+ }
4199
+
3969
4200
  class StateView {
3970
4201
  constructor() {
3971
4202
  /**
@@ -4190,6 +4421,8 @@
4190
4421
  exports.encode = encode;
4191
4422
  exports.encodeKeyValueOperation = encodeArray;
4192
4423
  exports.encodeSchemaOperation = encodeSchemaOperation;
4424
+ exports.getRawChangesCallback = getRawChangesCallback;
4425
+ exports.getStateCallbacks = getStateCallbacks;
4193
4426
  exports.registerType = registerType;
4194
4427
  exports.type = type;
4195
4428
  exports.view = view;
@@ -1,20 +1,17 @@
1
1
  import { Collection, NonFunctionNonPrimitivePropNames, NonFunctionPropNames } from "../../types/HelperTypes";
2
2
  import { Decoder } from "../Decoder";
3
- import { DataChange } from "../DecodeOperation";
4
- type GetProxyType<T> = unknown extends T ? InstanceCallback<T> & CollectionCallback<any, any> : T extends Collection<infer K, infer V, infer _> ? CollectionCallback<K, V> : InstanceCallback<T>;
3
+ import { Schema } from "../../Schema";
4
+ export type CallbackProxy<T> = unknown extends T ? InstanceCallback<T> & CollectionCallback<any, any> : T extends Collection<infer K, infer V, infer _> ? CollectionCallback<K, V> : InstanceCallback<T>;
5
5
  type InstanceCallback<T> = {
6
6
  listen<K extends NonFunctionPropNames<T>>(prop: K, callback: (value: T[K], previousValue: T[K]) => void, immediate?: boolean): any;
7
7
  onChange(callback: () => void): void;
8
8
  bindTo(targetObject: any, properties?: Array<NonFunctionPropNames<T>>): void;
9
9
  } & {
10
- [K in NonFunctionNonPrimitivePropNames<T>]: GetProxyType<T[K]>;
10
+ [K in NonFunctionNonPrimitivePropNames<T>]: CallbackProxy<T[K]>;
11
11
  };
12
12
  type CollectionCallback<K, V> = {
13
13
  onAdd(callback: (item: V, index: K) => void, immediate?: boolean): void;
14
14
  onRemove(callback: (item: V, index: K) => void): void;
15
15
  };
16
- export declare function getStateCallbacks(decoder: Decoder): {
17
- $: <T>(instance: T) => GetProxyType<T>;
18
- trigger: (changes: DataChange[]) => void;
19
- };
16
+ export declare function getStateCallbacks<T extends Schema>(decoder: Decoder<T>): CallbackProxy<T>;
20
17
  export {};
@@ -26,8 +26,6 @@ function getStateCallbacks(decoder) {
26
26
  for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
27
27
  deleteCallbacks[i]();
28
28
  }
29
- // callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE]?.forEach(callback =>
30
- // callback());
31
29
  }
32
30
  if (ref instanceof Schema_1.Schema) {
33
31
  //
@@ -134,6 +132,11 @@ function getStateCallbacks(decoder) {
134
132
  return $root.addCallback($root.refIds.get(context.instance), spec_1.OPERATION.REPLACE, callback);
135
133
  },
136
134
  bindTo: function bindTo(targetObject, properties) {
135
+ // return $root.addCallback(
136
+ // $root.refIds.get(context.instance),
137
+ // OPERATION.BIND,
138
+ // callback
139
+ // );
137
140
  console.log("bindTo", targetObject, properties);
138
141
  }
139
142
  }, {
@@ -225,16 +228,7 @@ function getStateCallbacks(decoder) {
225
228
  function $(instance) {
226
229
  return getProxy(undefined, { instance });
227
230
  }
228
- return {
229
- $,
230
- trigger: function trigger(changes) {
231
- for (let i = 0, l = changes.length; i < l; i++) {
232
- const change = changes[i];
233
- change.op;
234
- change.ref;
235
- }
236
- }
237
- };
231
+ return $(decoder.state);
238
232
  }
239
233
  exports.getStateCallbacks = getStateCallbacks;
240
234
  //# sourceMappingURL=StateCallbacks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StateCallbacks.js","sourceRoot":"","sources":["../../../src/decoder/strategy/StateCallbacks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../../Metadata\";\nimport { Collection, NonFunctionNonPrimitivePropNames, NonFunctionPropNames } from \"../../types/HelperTypes\";\nimport { Ref } from \"../../encoder/ChangeTree\";\nimport { Decoder } from \"../Decoder\";\nimport { DataChange } from \"../DecodeOperation\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { DefinitionType } from \"../../annotations\";\nimport { Schema } from \"../../Schema\";\nimport type { ArraySchema } from \"../../types/custom/ArraySchema\";\n\n//\n// Discussion: https://github.com/colyseus/schema/issues/155\n//\n// Main points:\n// - Decouple structures from their callbacks.\n// - Registering deep callbacks can be confusing.\n// - Avoid closures by allowing to pass a context. (https://github.com/colyseus/schema/issues/155#issuecomment-1804694081)\n//\n\ntype GetProxyType<T> = unknown extends T // is \"any\"?\n ? InstanceCallback<T> & CollectionCallback<any, any>\n : T extends Collection<infer K, infer V, infer _>\n ? CollectionCallback<K, V>\n : InstanceCallback<T>\n\ntype InstanceCallback<T> = {\n listen<K extends NonFunctionPropNames<T>>(\n prop: K,\n callback: (value: T[K], previousValue: T[K]) => void,\n immediate?: boolean,\n )\n onChange(callback: () => void): void;\n bindTo(targetObject: any, properties?: Array<NonFunctionPropNames<T>>): void;\n} & {\n [K in NonFunctionNonPrimitivePropNames<T>]: GetProxyType<T[K]>;\n}\n\ntype CollectionCallback<K, V> = {\n onAdd(callback: (item: V, index: K) => void, immediate?: boolean): void;\n onRemove(callback: (item: V, index: K) => void): void;\n};\n\ntype OnInstanceAvailableCallback = (callback: (ref: Ref, existing: boolean) => void) => void;\n\ntype CallContext = {\n instance?: any,\n parentInstance?: any,\n onInstanceAvailable?: OnInstanceAvailableCallback,\n}\n\nexport function getStateCallbacks(decoder: Decoder) {\n const $root = decoder.root;\n const callbacks = $root.callbacks;\n\n let isTriggeringOnAdd = false;\n\n decoder.triggerChanges = function (allChanges: DataChange[]) {\n const uniqueRefIds = new Set<number>();\n\n for (let i = 0, l = allChanges.length; i < l; i++) {\n const change = allChanges[i];\n const refId = change.refId;\n const ref = change.ref;\n const $callbacks = callbacks[refId];\n\n if (!$callbacks) { continue; }\n\n //\n // trigger onRemove on child structure.\n //\n if (\n (change.op & OPERATION.DELETE) === OPERATION.DELETE &&\n change.previousValue instanceof Schema\n ) {\n const deleteCallbacks = callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE];\n for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {\n deleteCallbacks[i]();\n }\n // callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE]?.forEach(callback =>\n // callback());\n }\n\n if (ref instanceof Schema) {\n //\n // Handle schema instance\n //\n\n if (!uniqueRefIds.has(refId)) {\n try {\n // trigger onChange\n const replaceCallbacks = $callbacks?.[OPERATION.REPLACE];\n for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {\n replaceCallbacks[i]();\n }\n\n } catch (e) {\n console.error(e);\n }\n }\n\n try {\n if ($callbacks.hasOwnProperty(change.field)) {\n const fieldCallbacks = $callbacks[change.field];\n for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {\n fieldCallbacks[i](change.value, change.previousValue);\n }\n }\n\n } catch (e) {\n //\n console.error(e);\n }\n\n } else {\n //\n // Handle collection of items\n //\n\n if (change.op === OPERATION.ADD && change.previousValue === undefined) {\n // triger onAdd\n\n isTriggeringOnAdd = true;\n const addCallbacks = $callbacks[OPERATION.ADD];\n for (let i = addCallbacks?.length - 1; i >= 0; i--) {\n addCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n isTriggeringOnAdd = false;\n\n } else if ((change.op & OPERATION.DELETE) === OPERATION.DELETE) {\n //\n // FIXME: `previousValue` should always be available.\n //\n if (change.previousValue !== undefined) {\n // triger onRemove\n const deleteCallbacks = $callbacks[OPERATION.DELETE];\n for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {\n deleteCallbacks[i](change.previousValue, change.dynamicIndex ?? change.field);\n }\n }\n\n // Handle DELETE_AND_ADD operations\n // FIXME: should we set \"isTriggeringOnAdd\" here?\n if ((change.op & OPERATION.ADD) === OPERATION.ADD) {\n const addCallbacks = $callbacks[OPERATION.ADD];\n for (let i = addCallbacks?.length - 1; i >= 0; i--) {\n addCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n }\n }\n\n // trigger onChange\n if (change.value !== change.previousValue) {\n const replaceCallbacks = $callbacks[OPERATION.REPLACE];\n for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {\n replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n }\n }\n\n uniqueRefIds.add(refId);\n }\n };\n\n function getProxy(metadataOrType: Metadata | DefinitionType, context: CallContext) {\n let metadata: Metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;\n let isCollection = (\n (context.instance && typeof (context.instance['forEach']) === \"function\") ||\n (metadataOrType && typeof (metadataOrType[Symbol.metadata]) === \"undefined\")\n );\n\n if (metadata && !isCollection) {\n\n const onAdd = function (\n ref: Ref,\n prop: string,\n callback: (value: any, previousValue: any) => void, immediate: boolean\n ) {\n // immediate trigger\n if (\n immediate &&\n context.instance[prop] !== undefined &&\n !isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)\n ) {\n callback(context.instance[prop], undefined);\n }\n return $root.addCallback($root.refIds.get(ref), prop, callback);\n }\n\n /**\n * Schema instances\n */\n return new Proxy({\n listen: function listen(prop: string, callback: (value: any, previousValue: any) => void, immediate: boolean = true) {\n if (context.instance) {\n return onAdd(context.instance, prop, callback, immediate);\n\n } else {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref, existing: boolean) =>\n onAdd(ref, prop, callback, immediate && existing));\n }\n },\n onChange: function onChange(callback: () => void) {\n return $root.addCallback(\n $root.refIds.get(context.instance),\n OPERATION.REPLACE,\n callback\n );\n\n },\n bindTo: function bindTo(targetObject: any, properties?: string[]) {\n console.log(\"bindTo\", targetObject, properties);\n }\n }, {\n get(target, prop: string) {\n if (metadata[prop]) {\n const instance = context.instance?.[prop];\n const onInstanceAvailable: OnInstanceAvailableCallback = (\n (callback: (ref: Ref, existing: boolean) => void) => {\n const unbind = $(context.instance).listen(prop, (value, _) => {\n callback(value, false);\n\n // FIXME: by \"unbinding\" the callback here,\n // it will not support when the server\n // re-instantiates the instance.\n //\n unbind?.();\n }, false);\n\n // has existing value\n if ($root.refIds.get(instance) !== undefined) {\n callback(instance, true);\n }\n }\n );\n return getProxy(metadata[prop].type, {\n instance,\n parentInstance: context.instance,\n onInstanceAvailable,\n });\n\n } else {\n // accessing the function\n return target[prop];\n }\n },\n has(target, prop: string) { return metadata[prop] !== undefined; },\n set(_, _1, _2) { throw new Error(\"not allowed\"); },\n deleteProperty(_, _1) { throw new Error(\"not allowed\"); },\n });\n\n } else {\n /**\n * Collection instances\n */\n\n const onAdd = function (ref: Ref, callback: (value: any, key: any) => void, immediate: boolean) {\n // Trigger callback on existing items\n if (immediate) {\n (ref as ArraySchema).forEach((v, k) => callback(v, k));\n }\n return $root.addCallback($root.refIds.get(ref), OPERATION.ADD, callback);\n };\n\n const onRemove = function (ref: Ref, callback: (value: any, key: any) => void) {\n return $root.addCallback($root.refIds.get(ref), OPERATION.DELETE, callback);\n };\n\n return new Proxy({\n onAdd: function(callback: (value, key) => void, immediate: boolean = true) {\n //\n // https://github.com/colyseus/schema/issues/147\n // If parent instance has \"onAdd\" registered, avoid triggering immediate callback.\n //\n // FIXME: \"isTriggeringOnAdd\" is a workaround. We should find a better way to handle this.\n //\n if (context.onInstanceAvailable) {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref, existing: boolean) =>\n onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));\n\n } else if (context.instance) {\n onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);\n }\n },\n onRemove: function(callback: (value, key) => void) {\n if (context.onInstanceAvailable) {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref) =>\n onRemove(ref, callback));\n\n } else if (context.instance) {\n onRemove(context.instance, callback);\n }\n },\n }, {\n get(target, prop: string) {\n if (!target[prop]) {\n throw new Error(`Can't access '${prop}' through callback proxy. access the instance directly.`);\n }\n return target[prop];\n },\n has(target, prop) { return target[prop] !== undefined; },\n set(_, _1, _2) { throw new Error(\"not allowed\"); },\n deleteProperty(_, _1) { throw new Error(\"not allowed\"); },\n });\n }\n }\n\n function $<T>(instance: T): GetProxyType<T> {\n return getProxy(undefined, { instance }) as GetProxyType<T>;\n }\n\n return {\n $,\n trigger: function trigger(changes: DataChange[]) {\n for (let i = 0, l = changes.length; i < l; i++) {\n const change = changes[i];\n\n change.op\n change.ref\n }\n }\n }\n\n}"]}
1
+ {"version":3,"file":"StateCallbacks.js","sourceRoot":"","sources":["../../../src/decoder/strategy/StateCallbacks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../../Metadata\";\nimport { Collection, NonFunctionNonPrimitivePropNames, NonFunctionPropNames } from \"../../types/HelperTypes\";\nimport { Ref } from \"../../encoder/ChangeTree\";\nimport { Decoder } from \"../Decoder\";\nimport { DataChange } from \"../DecodeOperation\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { DefinitionType } from \"../../annotations\";\nimport { Schema } from \"../../Schema\";\nimport type { ArraySchema } from \"../../types/custom/ArraySchema\";\n\n//\n// Discussion: https://github.com/colyseus/schema/issues/155\n//\n// Main points:\n// - Decouple structures from their callbacks.\n// - Registering deep callbacks can be confusing.\n// - Avoid closures by allowing to pass a context. (https://github.com/colyseus/schema/issues/155#issuecomment-1804694081)\n//\n\nexport type CallbackProxy<T> = unknown extends T // is \"any\"?\n ? InstanceCallback<T> & CollectionCallback<any, any>\n : T extends Collection<infer K, infer V, infer _>\n ? CollectionCallback<K, V>\n : InstanceCallback<T>\n\ntype InstanceCallback<T> = {\n listen<K extends NonFunctionPropNames<T>>(\n prop: K,\n callback: (value: T[K], previousValue: T[K]) => void,\n immediate?: boolean,\n )\n onChange(callback: () => void): void;\n bindTo(targetObject: any, properties?: Array<NonFunctionPropNames<T>>): void;\n} & {\n [K in NonFunctionNonPrimitivePropNames<T>]: CallbackProxy<T[K]>;\n}\n\ntype CollectionCallback<K, V> = {\n onAdd(callback: (item: V, index: K) => void, immediate?: boolean): void;\n onRemove(callback: (item: V, index: K) => void): void;\n};\n\ntype OnInstanceAvailableCallback = (callback: (ref: Ref, existing: boolean) => void) => void;\n\ntype CallContext = {\n instance?: any,\n parentInstance?: any,\n onInstanceAvailable?: OnInstanceAvailableCallback,\n}\n\nexport function getStateCallbacks<T extends Schema>(decoder: Decoder<T>): CallbackProxy<T> {\n const $root = decoder.root;\n const callbacks = $root.callbacks;\n\n let isTriggeringOnAdd = false;\n\n decoder.triggerChanges = function (allChanges: DataChange[]) {\n const uniqueRefIds = new Set<number>();\n\n for (let i = 0, l = allChanges.length; i < l; i++) {\n const change = allChanges[i];\n const refId = change.refId;\n const ref = change.ref;\n const $callbacks = callbacks[refId];\n\n if (!$callbacks) { continue; }\n\n //\n // trigger onRemove on child structure.\n //\n if (\n (change.op & OPERATION.DELETE) === OPERATION.DELETE &&\n change.previousValue instanceof Schema\n ) {\n const deleteCallbacks = callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE];\n for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {\n deleteCallbacks[i]();\n }\n }\n\n if (ref instanceof Schema) {\n //\n // Handle schema instance\n //\n\n if (!uniqueRefIds.has(refId)) {\n try {\n // trigger onChange\n const replaceCallbacks = $callbacks?.[OPERATION.REPLACE];\n for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {\n replaceCallbacks[i]();\n }\n\n } catch (e) {\n console.error(e);\n }\n }\n\n try {\n if ($callbacks.hasOwnProperty(change.field)) {\n const fieldCallbacks = $callbacks[change.field];\n for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {\n fieldCallbacks[i](change.value, change.previousValue);\n }\n }\n\n } catch (e) {\n //\n console.error(e);\n }\n\n } else {\n //\n // Handle collection of items\n //\n\n if (change.op === OPERATION.ADD && change.previousValue === undefined) {\n // triger onAdd\n\n isTriggeringOnAdd = true;\n const addCallbacks = $callbacks[OPERATION.ADD];\n for (let i = addCallbacks?.length - 1; i >= 0; i--) {\n addCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n isTriggeringOnAdd = false;\n\n } else if ((change.op & OPERATION.DELETE) === OPERATION.DELETE) {\n //\n // FIXME: `previousValue` should always be available.\n //\n if (change.previousValue !== undefined) {\n // triger onRemove\n const deleteCallbacks = $callbacks[OPERATION.DELETE];\n for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {\n deleteCallbacks[i](change.previousValue, change.dynamicIndex ?? change.field);\n }\n }\n\n // Handle DELETE_AND_ADD operations\n // FIXME: should we set \"isTriggeringOnAdd\" here?\n if ((change.op & OPERATION.ADD) === OPERATION.ADD) {\n const addCallbacks = $callbacks[OPERATION.ADD];\n for (let i = addCallbacks?.length - 1; i >= 0; i--) {\n addCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n }\n }\n\n // trigger onChange\n if (change.value !== change.previousValue) {\n const replaceCallbacks = $callbacks[OPERATION.REPLACE];\n for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {\n replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);\n }\n }\n }\n\n uniqueRefIds.add(refId);\n }\n };\n\n function getProxy(metadataOrType: Metadata | DefinitionType, context: CallContext) {\n let metadata: Metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;\n let isCollection = (\n (context.instance && typeof (context.instance['forEach']) === \"function\") ||\n (metadataOrType && typeof (metadataOrType[Symbol.metadata]) === \"undefined\")\n );\n\n if (metadata && !isCollection) {\n\n const onAdd = function (\n ref: Ref,\n prop: string,\n callback: (value: any, previousValue: any) => void, immediate: boolean\n ) {\n // immediate trigger\n if (\n immediate &&\n context.instance[prop] !== undefined &&\n !isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)\n ) {\n callback(context.instance[prop], undefined);\n }\n return $root.addCallback($root.refIds.get(ref), prop, callback);\n }\n\n /**\n * Schema instances\n */\n return new Proxy({\n listen: function listen(prop: string, callback: (value: any, previousValue: any) => void, immediate: boolean = true) {\n if (context.instance) {\n return onAdd(context.instance, prop, callback, immediate);\n\n } else {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref, existing: boolean) =>\n onAdd(ref, prop, callback, immediate && existing));\n }\n },\n onChange: function onChange(callback: () => void) {\n return $root.addCallback(\n $root.refIds.get(context.instance),\n OPERATION.REPLACE,\n callback\n );\n },\n bindTo: function bindTo(targetObject: any, properties?: string[]) {\n // return $root.addCallback(\n // $root.refIds.get(context.instance),\n // OPERATION.BIND,\n // callback\n // );\n console.log(\"bindTo\", targetObject, properties);\n }\n }, {\n get(target, prop: string) {\n if (metadata[prop]) {\n const instance = context.instance?.[prop];\n const onInstanceAvailable: OnInstanceAvailableCallback = (\n (callback: (ref: Ref, existing: boolean) => void) => {\n const unbind = $(context.instance).listen(prop, (value, _) => {\n callback(value, false);\n\n // FIXME: by \"unbinding\" the callback here,\n // it will not support when the server\n // re-instantiates the instance.\n //\n unbind?.();\n }, false);\n\n // has existing value\n if ($root.refIds.get(instance) !== undefined) {\n callback(instance, true);\n }\n }\n );\n return getProxy(metadata[prop].type, {\n instance,\n parentInstance: context.instance,\n onInstanceAvailable,\n });\n\n } else {\n // accessing the function\n return target[prop];\n }\n },\n has(target, prop: string) { return metadata[prop] !== undefined; },\n set(_, _1, _2) { throw new Error(\"not allowed\"); },\n deleteProperty(_, _1) { throw new Error(\"not allowed\"); },\n });\n\n } else {\n /**\n * Collection instances\n */\n\n const onAdd = function (ref: Ref, callback: (value: any, key: any) => void, immediate: boolean) {\n // Trigger callback on existing items\n if (immediate) {\n (ref as ArraySchema).forEach((v, k) => callback(v, k));\n }\n return $root.addCallback($root.refIds.get(ref), OPERATION.ADD, callback);\n };\n\n const onRemove = function (ref: Ref, callback: (value: any, key: any) => void) {\n return $root.addCallback($root.refIds.get(ref), OPERATION.DELETE, callback);\n };\n\n return new Proxy({\n onAdd: function(callback: (value, key) => void, immediate: boolean = true) {\n //\n // https://github.com/colyseus/schema/issues/147\n // If parent instance has \"onAdd\" registered, avoid triggering immediate callback.\n //\n // FIXME: \"isTriggeringOnAdd\" is a workaround. We should find a better way to handle this.\n //\n if (context.onInstanceAvailable) {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref, existing: boolean) =>\n onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));\n\n } else if (context.instance) {\n onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);\n }\n },\n onRemove: function(callback: (value, key) => void) {\n if (context.onInstanceAvailable) {\n // collection instance not received yet\n context.onInstanceAvailable((ref: Ref) =>\n onRemove(ref, callback));\n\n } else if (context.instance) {\n onRemove(context.instance, callback);\n }\n },\n }, {\n get(target, prop: string) {\n if (!target[prop]) {\n throw new Error(`Can't access '${prop}' through callback proxy. access the instance directly.`);\n }\n return target[prop];\n },\n has(target, prop) { return target[prop] !== undefined; },\n set(_, _1, _2) { throw new Error(\"not allowed\"); },\n deleteProperty(_, _1) { throw new Error(\"not allowed\"); },\n });\n }\n }\n\n function $<T>(instance: T): CallbackProxy<T> {\n return getProxy(undefined, { instance }) as CallbackProxy<T>;\n }\n\n return $(decoder.state);\n}"]}
@@ -13,7 +13,7 @@ export declare class Encoder<T extends Schema = any> {
13
13
  root: Root;
14
14
  constructor(root: T);
15
15
  protected setRoot(state: T): void;
16
- encode(it?: Iterator, view?: StateView, buffer?: Buffer, changeTrees?: Map<import("./ChangeTree").ChangeTree<any>, Map<number, OPERATION>>): Buffer;
16
+ encode(it?: Iterator, view?: StateView, buffer?: Buffer, changeTrees?: Map<import("./ChangeTree").ChangeTree<any>, Map<number, OPERATION>>, isEncodeAll?: boolean): Buffer;
17
17
  encodeAll(it?: Iterator, buffer?: Buffer): Buffer;
18
18
  encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Buffer): Buffer;
19
19
  debugAllFilteredChanges(): void;
@@ -27,9 +27,8 @@ class Encoder {
27
27
  this.state = state;
28
28
  state[symbols_1.$changes].setRoot(this.root);
29
29
  }
30
- encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
30
+ encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
31
31
  const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
32
- const isEncodeAll = this.root.allChanges === changeTrees;
33
32
  const hasView = (view !== undefined);
34
33
  const rootChangeTree = this.state[symbols_1.$changes];
35
34
  const changeTreesIterator = changeTrees.entries();
@@ -97,7 +96,7 @@ class Encoder {
97
96
  if (buffer === this.sharedBuffer) {
98
97
  this.sharedBuffer = buffer;
99
98
  }
100
- return this.encode({ offset: initialOffset }, view, buffer);
99
+ return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);
101
100
  }
102
101
  else {
103
102
  //
@@ -117,14 +116,14 @@ class Encoder {
117
116
  // Array.from(this.root.allChanges.entries()).map((item) => {
118
117
  // console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
119
118
  // });
120
- return this.encode(it, undefined, buffer, this.root.allChanges);
119
+ return this.encode(it, undefined, buffer, this.root.allChanges, true);
121
120
  }
122
121
  encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
123
122
  const viewOffset = it.offset;
124
123
  // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
125
124
  // this.debugAllFilteredChanges();
126
125
  // try to encode "filtered" changes
127
- this.encode(it, view, bytes, this.root.allFilteredChanges);
126
+ this.encode(it, view, bytes, this.root.allFilteredChanges, true);
128
127
  return Buffer.concat([
129
128
  bytes.subarray(0, sharedOffset),
130
129
  bytes.subarray(viewOffset, it.offset)
@@ -1 +1 @@
1
- {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../annotations\";\nimport { $changes, $encoder, $filter } from \"../types/symbols\";\n\nimport * as encode from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./ChangeTree\";\nimport { getNextPowerOf2 } from \"../utils\";\nimport type { StateView } from \"./StateView\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024;// 8KB\n sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for every new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(state: T) {\n this.root = new Root();\n this.state = state;\n state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeTrees = this.root.changes\n ): Buffer {\n const initialOffset = it.offset; // cache current offset in case we need to resize the buffer\n\n const isEncodeAll = this.root.allChanges === changeTrees;\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n const changeTreesIterator = changeTrees.entries();\n\n for (const [changeTree, changes] of changeTreesIterator) {\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"ChangeTree:\", { ref: ref.constructor.name, });\n // }\n // }\n\n if (hasView) {\n if (!view.items.has(changeTree)) {\n view.invisible.add(changeTree);\n continue; // skip this change tree\n\n } else if (view.invisible.has(changeTree)) {\n view.invisible.delete(changeTree); // remove from invisible list\n }\n }\n\n // skip root `refId` if it's the first change tree\n if (it.offset !== initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, changeTree.refId, it);\n }\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (filter && !filter(ref, fieldIndex, view)) {\n // console.log(\"SKIP FIELD:\", { ref: changeTree.ref.constructor.name, fieldIndex, })\n\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // // console.log(\"WILL ENCODE\", {\n // // ref: changeTree.ref.constructor.name,\n // // fieldIndex,\n // // operation: OPERATION[operation],\n // // });\n // }\n // }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n const newSize = getNextPowerOf2(buffer.byteLength * 2);\n console.warn(\"@colyseus/schema encode buffer overflow. Current buffer size: \" + buffer.byteLength + \", encoding offset: \" + it.offset + \", new size: \" + newSize);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n //\n buffer = Buffer.allocUnsafeSlow(newSize);\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer);\n\n } else {\n //\n // only clear changes after making sure buffer resize is not required.\n //\n if (!isEncodeAll && !hasView) {\n //\n // FIXME: avoid iterating over change trees twice.\n //\n this.onEndEncode(changeTrees);\n }\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {\n // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);\n\n // Array.from(this.root.allChanges.entries()).map((item) => {\n // console.log(\"->\", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });\n // });\n\n return this.encode(it, undefined, buffer, this.root.allChanges);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);\n // this.debugAllFilteredChanges();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.allFilteredChanges);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n\n debugAllFilteredChanges() {\n Array.from(this.root.allFilteredChanges.entries()).map((item) => {\n console.log(\"->\", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());\n if (Array.isArray(item[0].ref.toJSON())) {\n item[1].forEach((op, key) => {\n console.log(\" ->\", { key, op: OPERATION[op] });\n })\n }\n });\n }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.filteredChanges);\n\n // encode visibility changes (add/remove for this view)\n const viewChangesIterator = view.changes.entries();\n for (const [changeTree, changes] of viewChangesIterator) {\n if (changes.size === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0\", changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n onEndEncode(changeTrees = this.root.changes) {\n const changeTreesIterator = changeTrees.entries();\n for (const [changeTree, _] of changeTreesIterator) {\n changeTree.endEncode();\n }\n }\n\n discardChanges() {\n // discard shared changes\n if (this.root.changes.size > 0) {\n this.onEndEncode(this.root.changes);\n this.root.changes.clear();\n }\n // discard filtered changes\n if (this.root.filteredChanges.size > 0) {\n this.onEndEncode(this.root.filteredChanges);\n this.root.filteredChanges.clear();\n }\n }\n\n tryEncodeTypeId (bytes: Buffer, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n}"]}
1
+ {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../annotations\";\nimport { $changes, $encoder, $filter } from \"../types/symbols\";\n\nimport * as encode from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./ChangeTree\";\nimport { getNextPowerOf2 } from \"../utils\";\nimport type { StateView } from \"./StateView\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024;// 8KB\n sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for every new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(state: T) {\n this.root = new Root();\n this.state = state;\n state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeTrees = this.root.changes,\n isEncodeAll = this.root.allChanges === changeTrees,\n ): Buffer {\n const initialOffset = it.offset; // cache current offset in case we need to resize the buffer\n\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n const changeTreesIterator = changeTrees.entries();\n\n for (const [changeTree, changes] of changeTreesIterator) {\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"ChangeTree:\", { ref: ref.constructor.name, });\n // }\n // }\n\n if (hasView) {\n if (!view.items.has(changeTree)) {\n view.invisible.add(changeTree);\n continue; // skip this change tree\n\n } else if (view.invisible.has(changeTree)) {\n view.invisible.delete(changeTree); // remove from invisible list\n }\n }\n\n // skip root `refId` if it's the first change tree\n if (it.offset !== initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, changeTree.refId, it);\n }\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (filter && !filter(ref, fieldIndex, view)) {\n // console.log(\"SKIP FIELD:\", { ref: changeTree.ref.constructor.name, fieldIndex, })\n\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // // console.log(\"WILL ENCODE\", {\n // // ref: changeTree.ref.constructor.name,\n // // fieldIndex,\n // // operation: OPERATION[operation],\n // // });\n // }\n // }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n const newSize = getNextPowerOf2(buffer.byteLength * 2);\n console.warn(\"@colyseus/schema encode buffer overflow. Current buffer size: \" + buffer.byteLength + \", encoding offset: \" + it.offset + \", new size: \" + newSize);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n //\n buffer = Buffer.allocUnsafeSlow(newSize);\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);\n\n } else {\n //\n // only clear changes after making sure buffer resize is not required.\n //\n if (!isEncodeAll && !hasView) {\n //\n // FIXME: avoid iterating over change trees twice.\n //\n this.onEndEncode(changeTrees);\n }\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {\n // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);\n\n // Array.from(this.root.allChanges.entries()).map((item) => {\n // console.log(\"->\", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });\n // });\n\n return this.encode(it, undefined, buffer, this.root.allChanges, true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);\n // this.debugAllFilteredChanges();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.allFilteredChanges, true);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n\n debugAllFilteredChanges() {\n Array.from(this.root.allFilteredChanges.entries()).map((item) => {\n console.log(\"->\", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());\n if (Array.isArray(item[0].ref.toJSON())) {\n item[1].forEach((op, key) => {\n console.log(\" ->\", { key, op: OPERATION[op] });\n })\n }\n });\n }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.filteredChanges);\n\n // encode visibility changes (add/remove for this view)\n const viewChangesIterator = view.changes.entries();\n for (const [changeTree, changes] of viewChangesIterator) {\n if (changes.size === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0\", changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n onEndEncode(changeTrees = this.root.changes) {\n const changeTreesIterator = changeTrees.entries();\n for (const [changeTree, _] of changeTreesIterator) {\n changeTree.endEncode();\n }\n }\n\n discardChanges() {\n // discard shared changes\n if (this.root.changes.size > 0) {\n this.onEndEncode(this.root.changes);\n this.root.changes.clear();\n }\n // discard filtered changes\n if (this.root.filteredChanges.size > 0) {\n this.onEndEncode(this.root.filteredChanges);\n this.root.filteredChanges.clear();\n }\n }\n\n tryEncodeTypeId (bytes: Buffer, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n}"]}
package/lib/index.d.ts CHANGED
@@ -21,6 +21,8 @@ export { Reflection, ReflectionType, ReflectionField, } from "./Reflection";
21
21
  export { Metadata } from "./Metadata";
22
22
  export { type, deprecated, defineTypes, view, TypeContext, } from "./annotations";
23
23
  export type { DefinitionType, PrimitiveType, Definition, } from "./annotations";
24
+ export { getStateCallbacks, CallbackProxy } from "./decoder/strategy/StateCallbacks";
25
+ export { getRawChangesCallback } from "./decoder/strategy/RawChanges";
24
26
  export { Encoder } from "./encoder/Encoder";
25
27
  export { encodeSchemaOperation, encodeArray as encodeKeyValueOperation } from "./encoder/EncodeOperation";
26
28
  export { ChangeTree, Ref } from "./encoder/ChangeTree";
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OPERATION = exports.decodeKeyValueOperation = exports.decodeSchemaOperation = exports.Decoder = exports.StateView = exports.ChangeTree = exports.encodeKeyValueOperation = exports.encodeSchemaOperation = exports.Encoder = exports.TypeContext = exports.view = exports.defineTypes = exports.deprecated = exports.type = exports.Metadata = exports.ReflectionField = exports.ReflectionType = exports.Reflection = exports.decode = exports.encode = exports.dumpChanges = exports.registerType = exports.SetSchema = exports.CollectionSchema = exports.ArraySchema = exports.MapSchema = exports.$childType = exports.$changes = exports.$deleteByIndex = exports.$getByIndex = exports.$filter = exports.$decoder = exports.$encoder = exports.$track = exports.Schema = void 0;
3
+ exports.OPERATION = exports.decodeKeyValueOperation = exports.decodeSchemaOperation = exports.Decoder = exports.StateView = exports.ChangeTree = exports.encodeKeyValueOperation = exports.encodeSchemaOperation = exports.Encoder = exports.getRawChangesCallback = exports.getStateCallbacks = exports.TypeContext = exports.view = exports.defineTypes = exports.deprecated = exports.type = exports.Metadata = exports.ReflectionField = exports.ReflectionType = exports.Reflection = exports.decode = exports.encode = exports.dumpChanges = exports.registerType = exports.SetSchema = exports.CollectionSchema = exports.ArraySchema = exports.MapSchema = exports.$childType = exports.$changes = exports.$deleteByIndex = exports.$getByIndex = exports.$filter = exports.$decoder = exports.$encoder = exports.$track = exports.Schema = void 0;
4
4
  var Schema_1 = require("./Schema");
5
5
  Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return Schema_1.Schema; } });
6
6
  const symbols_1 = require("./types/symbols");
@@ -48,6 +48,10 @@ Object.defineProperty(exports, "defineTypes", { enumerable: true, get: function
48
48
  Object.defineProperty(exports, "view", { enumerable: true, get: function () { return annotations_1.view; } });
49
49
  // Internals
50
50
  Object.defineProperty(exports, "TypeContext", { enumerable: true, get: function () { return annotations_1.TypeContext; } });
51
+ var StateCallbacks_1 = require("./decoder/strategy/StateCallbacks");
52
+ Object.defineProperty(exports, "getStateCallbacks", { enumerable: true, get: function () { return StateCallbacks_1.getStateCallbacks; } });
53
+ var RawChanges_1 = require("./decoder/strategy/RawChanges");
54
+ Object.defineProperty(exports, "getRawChangesCallback", { enumerable: true, get: function () { return RawChanges_1.getRawChangesCallback; } });
51
55
  var Encoder_1 = require("./encoder/Encoder");
52
56
  Object.defineProperty(exports, "Encoder", { enumerable: true, get: function () { return Encoder_1.Encoder; } });
53
57
  var EncodeOperation_1 = require("./encoder/EncodeOperation");