@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.
Files changed (202) hide show
  1. package/README.md +148 -62
  2. package/bin/schema-debug +94 -0
  3. package/build/cjs/index.js +2222 -1513
  4. package/build/cjs/index.js.map +1 -1
  5. package/build/esm/index.mjs +2223 -1516
  6. package/build/esm/index.mjs.map +1 -1
  7. package/build/umd/index.js +2225 -1516
  8. package/lib/Metadata.d.ts +21 -9
  9. package/lib/Metadata.js +169 -32
  10. package/lib/Metadata.js.map +1 -1
  11. package/lib/Reflection.d.ts +19 -4
  12. package/lib/Reflection.js +66 -31
  13. package/lib/Reflection.js.map +1 -1
  14. package/lib/Schema.d.ts +12 -5
  15. package/lib/Schema.js +57 -56
  16. package/lib/Schema.js.map +1 -1
  17. package/lib/annotations.d.ts +31 -34
  18. package/lib/annotations.js +110 -160
  19. package/lib/annotations.js.map +1 -1
  20. package/lib/codegen/api.js +1 -2
  21. package/lib/codegen/api.js.map +1 -1
  22. package/lib/codegen/languages/cpp.js +1 -2
  23. package/lib/codegen/languages/cpp.js.map +1 -1
  24. package/lib/codegen/languages/csharp.js +9 -46
  25. package/lib/codegen/languages/csharp.js.map +1 -1
  26. package/lib/codegen/languages/haxe.js +4 -2
  27. package/lib/codegen/languages/haxe.js.map +1 -1
  28. package/lib/codegen/languages/java.js +1 -2
  29. package/lib/codegen/languages/java.js.map +1 -1
  30. package/lib/codegen/languages/js.js +1 -2
  31. package/lib/codegen/languages/js.js.map +1 -1
  32. package/lib/codegen/languages/lua.js +23 -25
  33. package/lib/codegen/languages/lua.js.map +1 -1
  34. package/lib/codegen/languages/ts.js +1 -2
  35. package/lib/codegen/languages/ts.js.map +1 -1
  36. package/lib/codegen/parser.js +85 -3
  37. package/lib/codegen/parser.js.map +1 -1
  38. package/lib/codegen/types.js +6 -3
  39. package/lib/codegen/types.js.map +1 -1
  40. package/lib/decoder/DecodeOperation.d.ts +3 -4
  41. package/lib/decoder/DecodeOperation.js +35 -17
  42. package/lib/decoder/DecodeOperation.js.map +1 -1
  43. package/lib/decoder/Decoder.d.ts +5 -6
  44. package/lib/decoder/Decoder.js +10 -10
  45. package/lib/decoder/Decoder.js.map +1 -1
  46. package/lib/decoder/ReferenceTracker.js +4 -2
  47. package/lib/decoder/ReferenceTracker.js.map +1 -1
  48. package/lib/decoder/strategy/RawChanges.js +1 -2
  49. package/lib/decoder/strategy/RawChanges.js.map +1 -1
  50. package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
  51. package/lib/decoder/strategy/StateCallbacks.js +74 -64
  52. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  53. package/lib/encoder/ChangeTree.d.ts +28 -20
  54. package/lib/encoder/ChangeTree.js +242 -188
  55. package/lib/encoder/ChangeTree.js.map +1 -1
  56. package/lib/encoder/EncodeOperation.d.ts +3 -6
  57. package/lib/encoder/EncodeOperation.js +51 -65
  58. package/lib/encoder/EncodeOperation.js.map +1 -1
  59. package/lib/encoder/Encoder.d.ts +8 -7
  60. package/lib/encoder/Encoder.js +128 -79
  61. package/lib/encoder/Encoder.js.map +1 -1
  62. package/lib/encoder/Root.d.ts +22 -0
  63. package/lib/encoder/Root.js +81 -0
  64. package/lib/encoder/Root.js.map +1 -0
  65. package/lib/encoder/StateView.d.ts +7 -7
  66. package/lib/encoder/StateView.js +72 -74
  67. package/lib/encoder/StateView.js.map +1 -1
  68. package/lib/encoding/assert.d.ts +7 -6
  69. package/lib/encoding/assert.js +13 -5
  70. package/lib/encoding/assert.js.map +1 -1
  71. package/lib/encoding/decode.d.ts +36 -19
  72. package/lib/encoding/decode.js +54 -84
  73. package/lib/encoding/decode.js.map +1 -1
  74. package/lib/encoding/encode.d.ts +36 -18
  75. package/lib/encoding/encode.js +61 -48
  76. package/lib/encoding/encode.js.map +1 -1
  77. package/lib/encoding/spec.d.ts +4 -5
  78. package/lib/encoding/spec.js +1 -2
  79. package/lib/encoding/spec.js.map +1 -1
  80. package/lib/index.d.ts +10 -9
  81. package/lib/index.js +24 -17
  82. package/lib/index.js.map +1 -1
  83. package/lib/types/HelperTypes.d.ts +34 -2
  84. package/lib/types/HelperTypes.js.map +1 -1
  85. package/lib/types/TypeContext.d.ts +29 -0
  86. package/lib/types/TypeContext.js +151 -0
  87. package/lib/types/TypeContext.js.map +1 -0
  88. package/lib/types/custom/ArraySchema.d.ts +2 -2
  89. package/lib/types/custom/ArraySchema.js +33 -22
  90. package/lib/types/custom/ArraySchema.js.map +1 -1
  91. package/lib/types/custom/CollectionSchema.d.ts +2 -2
  92. package/lib/types/custom/CollectionSchema.js +1 -0
  93. package/lib/types/custom/CollectionSchema.js.map +1 -1
  94. package/lib/types/custom/MapSchema.d.ts +18 -16
  95. package/lib/types/custom/MapSchema.js +12 -4
  96. package/lib/types/custom/MapSchema.js.map +1 -1
  97. package/lib/types/custom/SetSchema.d.ts +2 -2
  98. package/lib/types/custom/SetSchema.js +1 -0
  99. package/lib/types/custom/SetSchema.js.map +1 -1
  100. package/lib/types/registry.d.ts +8 -1
  101. package/lib/types/registry.js +23 -6
  102. package/lib/types/registry.js.map +1 -1
  103. package/lib/types/symbols.d.ts +8 -5
  104. package/lib/types/symbols.js +9 -6
  105. package/lib/types/symbols.js.map +1 -1
  106. package/lib/types/utils.js +1 -2
  107. package/lib/types/utils.js.map +1 -1
  108. package/lib/utils.js +9 -7
  109. package/lib/utils.js.map +1 -1
  110. package/package.json +19 -18
  111. package/src/Metadata.ts +190 -42
  112. package/src/Reflection.ts +76 -38
  113. package/src/Schema.ts +72 -70
  114. package/src/annotations.ts +156 -202
  115. package/src/codegen/languages/csharp.ts +8 -47
  116. package/src/codegen/languages/haxe.ts +4 -0
  117. package/src/codegen/languages/lua.ts +19 -27
  118. package/src/codegen/parser.ts +107 -0
  119. package/src/codegen/types.ts +1 -0
  120. package/src/decoder/DecodeOperation.ts +43 -15
  121. package/src/decoder/Decoder.ts +12 -10
  122. package/src/decoder/ReferenceTracker.ts +5 -3
  123. package/src/decoder/strategy/StateCallbacks.ts +152 -81
  124. package/src/encoder/ChangeTree.ts +282 -209
  125. package/src/encoder/EncodeOperation.ts +78 -78
  126. package/src/encoder/Encoder.ts +152 -88
  127. package/src/encoder/Root.ts +93 -0
  128. package/src/encoder/StateView.ts +80 -88
  129. package/src/encoding/assert.ts +17 -8
  130. package/src/encoding/decode.ts +73 -93
  131. package/src/encoding/encode.ts +76 -45
  132. package/src/encoding/spec.ts +3 -5
  133. package/src/index.ts +12 -20
  134. package/src/types/HelperTypes.ts +54 -2
  135. package/src/types/TypeContext.ts +175 -0
  136. package/src/types/custom/ArraySchema.ts +49 -19
  137. package/src/types/custom/CollectionSchema.ts +1 -0
  138. package/src/types/custom/MapSchema.ts +30 -17
  139. package/src/types/custom/SetSchema.ts +1 -0
  140. package/src/types/registry.ts +22 -3
  141. package/src/types/symbols.ts +10 -7
  142. package/src/utils.ts +7 -3
  143. package/lib/Decoder.d.ts +0 -16
  144. package/lib/Decoder.js +0 -182
  145. package/lib/Decoder.js.map +0 -1
  146. package/lib/Encoder.d.ts +0 -13
  147. package/lib/Encoder.js +0 -79
  148. package/lib/Encoder.js.map +0 -1
  149. package/lib/changes/ChangeSet.d.ts +0 -12
  150. package/lib/changes/ChangeSet.js +0 -35
  151. package/lib/changes/ChangeSet.js.map +0 -1
  152. package/lib/changes/ChangeTree.d.ts +0 -53
  153. package/lib/changes/ChangeTree.js +0 -202
  154. package/lib/changes/ChangeTree.js.map +0 -1
  155. package/lib/changes/DecodeOperation.d.ts +0 -15
  156. package/lib/changes/DecodeOperation.js +0 -186
  157. package/lib/changes/DecodeOperation.js.map +0 -1
  158. package/lib/changes/EncodeOperation.d.ts +0 -18
  159. package/lib/changes/EncodeOperation.js +0 -130
  160. package/lib/changes/EncodeOperation.js.map +0 -1
  161. package/lib/changes/ReferenceTracker.d.ts +0 -14
  162. package/lib/changes/ReferenceTracker.js +0 -83
  163. package/lib/changes/ReferenceTracker.js.map +0 -1
  164. package/lib/changes/consts.d.ts +0 -14
  165. package/lib/changes/consts.js +0 -18
  166. package/lib/changes/consts.js.map +0 -1
  167. package/lib/decoding/decode.d.ts +0 -48
  168. package/lib/decoding/decode.js +0 -267
  169. package/lib/decoding/decode.js.map +0 -1
  170. package/lib/ecs.d.ts +0 -11
  171. package/lib/ecs.js +0 -160
  172. package/lib/ecs.js.map +0 -1
  173. package/lib/filters/index.d.ts +0 -8
  174. package/lib/filters/index.js +0 -24
  175. package/lib/filters/index.js.map +0 -1
  176. package/lib/spec.d.ts +0 -13
  177. package/lib/spec.js +0 -42
  178. package/lib/spec.js.map +0 -1
  179. package/lib/types/ArraySchema.d.ts +0 -238
  180. package/lib/types/ArraySchema.js +0 -555
  181. package/lib/types/ArraySchema.js.map +0 -1
  182. package/lib/types/CollectionSchema.d.ts +0 -35
  183. package/lib/types/CollectionSchema.js +0 -150
  184. package/lib/types/CollectionSchema.js.map +0 -1
  185. package/lib/types/MapSchema.d.ts +0 -38
  186. package/lib/types/MapSchema.js +0 -215
  187. package/lib/types/MapSchema.js.map +0 -1
  188. package/lib/types/SetSchema.d.ts +0 -32
  189. package/lib/types/SetSchema.js +0 -162
  190. package/lib/types/SetSchema.js.map +0 -1
  191. package/lib/types/typeRegistry.d.ts +0 -5
  192. package/lib/types/typeRegistry.js +0 -13
  193. package/lib/types/typeRegistry.js.map +0 -1
  194. package/lib/usage.d.ts +0 -1
  195. package/lib/usage.js +0 -22
  196. package/lib/usage.js.map +0 -1
  197. package/lib/v3.d.ts +0 -1
  198. package/lib/v3.js +0 -427
  199. package/lib/v3.js.map +0 -1
  200. package/lib/v3_experiment.d.ts +0 -1
  201. package/lib/v3_experiment.js +0 -407
  202. package/lib/v3_experiment.js.map +0 -1
@@ -1,23 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Decoder = void 0;
4
- const annotations_1 = require("../annotations");
4
+ const TypeContext_1 = require("../types/TypeContext");
5
5
  const symbols_1 = require("../types/symbols");
6
- const decode = require("../encoding/decode");
6
+ const decode_1 = require("../encoding/decode");
7
7
  const spec_1 = require("../encoding/spec");
8
8
  const ReferenceTracker_1 = require("./ReferenceTracker");
9
9
  const DecodeOperation_1 = require("./DecodeOperation");
10
10
  class Decoder {
11
11
  constructor(root, context) {
12
12
  this.currentRefId = 0;
13
- this.setRoot(root);
14
- this.context = context || new annotations_1.TypeContext(root.constructor);
13
+ this.setState(root);
14
+ this.context = context || new TypeContext_1.TypeContext(root.constructor);
15
15
  // console.log(">>>>>>>>>>>>>>>> Decoder types");
16
16
  // this.context.schemas.forEach((id, schema) => {
17
17
  // console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
18
18
  // });
19
19
  }
20
- setRoot(root) {
20
+ setState(root) {
21
21
  this.state = root;
22
22
  this.root = new ReferenceTracker_1.ReferenceTracker();
23
23
  this.root.addRef(0, root);
@@ -34,7 +34,7 @@ class Decoder {
34
34
  //
35
35
  if (bytes[it.offset] == spec_1.SWITCH_TO_STRUCTURE) {
36
36
  it.offset++;
37
- this.currentRefId = decode.number(bytes, it);
37
+ this.currentRefId = decode_1.decode.number(bytes, it);
38
38
  const nextRef = $root.refs.get(this.currentRefId);
39
39
  //
40
40
  // Trying to access a reference that haven't been decoded yet.
@@ -44,7 +44,7 @@ class Decoder {
44
44
  }
45
45
  ref[symbols_1.$onDecodeEnd]?.();
46
46
  ref = nextRef;
47
- decoder = ref['constructor'][symbols_1.$decoder];
47
+ decoder = ref.constructor[symbols_1.$decoder];
48
48
  continue;
49
49
  }
50
50
  const result = decoder(this, bytes, it, ref, allChanges);
@@ -56,9 +56,9 @@ class Decoder {
56
56
  //
57
57
  const nextIterator = { offset: it.offset };
58
58
  while (it.offset < totalBytes) {
59
- if (decode.switchStructureCheck(bytes, it)) {
59
+ if (bytes[it.offset] === spec_1.SWITCH_TO_STRUCTURE) {
60
60
  nextIterator.offset = it.offset + 1;
61
- if ($root.refs.has(decode.number(bytes, nextIterator))) {
61
+ if ($root.refs.has(decode_1.decode.number(bytes, nextIterator))) {
62
62
  break;
63
63
  }
64
64
  }
@@ -79,7 +79,7 @@ class Decoder {
79
79
  let type;
80
80
  if (bytes[it.offset] === spec_1.TYPE_ID) {
81
81
  it.offset++;
82
- const type_id = decode.number(bytes, it);
82
+ const type_id = decode_1.decode.number(bytes, it);
83
83
  type = this.context.get(type_id);
84
84
  }
85
85
  return type || defaultType;
@@ -1 +1 @@
1
- {"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../annotations\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport * as decode from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, DataChange, DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setRoot(root);\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder 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(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref[$onDecodeEnd]?.()\n ref = nextRef;\n decoder = ref['constructor'][$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: decode.Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (decode.switchStructureCheck(bytes, it)) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
1
+ {"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport { decode } from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setState(root);\n\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder 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 setState(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref[$onDecodeEnd]?.()\n ref = nextRef;\n\n decoder = ref.constructor[$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (bytes[it.offset] === SWITCH_TO_STRUCTURE) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
@@ -67,6 +67,7 @@ class ReferenceTracker {
67
67
  clearRefs() {
68
68
  this.refs.clear();
69
69
  this.deletedRefs.clear();
70
+ this.callbacks = {};
70
71
  this.refCounts = {};
71
72
  }
72
73
  // for decoding
@@ -83,8 +84,9 @@ class ReferenceTracker {
83
84
  // Ensure child schema instances have their references removed as well.
84
85
  //
85
86
  if (Metadata_1.Metadata.isValidInstance(ref)) {
86
- const metadata = ref['constructor'][Symbol.metadata];
87
- for (const field in metadata) {
87
+ const metadata = ref.constructor[Symbol.metadata];
88
+ for (const index in metadata) {
89
+ const field = metadata[index].name;
88
90
  const childRefId = typeof (ref[field]) === "object" && this.refIds.get(ref[field]);
89
91
  if (childRefId) {
90
92
  this.removeRef(childRefId);
@@ -1 +1 @@
1
- {"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/decoder/ReferenceTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../Metadata\";\nimport { $childType } from \"../types/symbols\";\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { spliceOne } from \"../types/utils\";\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport { OPERATION } from \"../encoding/spec\";\n\nclass DecodingWarning extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DecodingWarning\";\n }\n}\n\n/**\n * Used for decoding only.\n */\n\nexport type SchemaCallbacks = { [field: string | number]: Function[] };\n\nexport class ReferenceTracker {\n //\n // Relation of refId => Schema structure\n // For direct access of structures during decoding time.\n //\n public refs = new Map<number, Ref>();\n public refIds = new WeakMap<Ref, number>();\n\n public refCounts: { [refId: number]: number; } = {};\n public deletedRefs = new Set<number>();\n\n public callbacks: { [refId: number]: SchemaCallbacks } = {};\n protected nextUniqueId: number = 0;\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n // for decoding\n addRef(refId: number, ref: Ref, incrementCount: boolean = true) {\n this.refs.set(refId, ref);\n this.refIds.set(ref, refId);\n\n if (incrementCount) {\n this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;\n }\n\n if (this.deletedRefs.has(refId)) {\n this.deletedRefs.delete(refId);\n }\n }\n\n // for decoding\n removeRef(refId: number) {\n const refCount = this.refCounts[refId];\n\n if (refCount === undefined) {\n try {\n throw new DecodingWarning(\"trying to remove refId that doesn't exist\");\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if (refCount === 0) {\n try {\n const ref = this.refs.get(refId);\n throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if ((this.refCounts[refId] = refCount - 1) <= 0) {\n this.deletedRefs.add(refId);\n }\n }\n\n clearRefs() {\n this.refs.clear();\n this.deletedRefs.clear();\n this.refCounts = {};\n }\n\n // for decoding\n garbageCollectDeletedRefs() {\n this.deletedRefs.forEach((refId) => {\n //\n // Skip active references.\n //\n if (this.refCounts[refId] > 0) { return; }\n\n const ref = this.refs.get(refId);\n\n //\n // Ensure child schema instances have their references removed as well.\n //\n if (Metadata.isValidInstance(ref)) {\n const metadata: Metadata = ref['constructor'][Symbol.metadata];\n for (const field in metadata) {\n const childRefId = typeof(ref[field]) === \"object\" && this.refIds.get(ref[field]);\n if (childRefId) {\n this.removeRef(childRefId);\n }\n }\n\n } else {\n if (typeof (Object.values(ref[$childType])[0]) === \"function\") {\n Array.from((ref as MapSchema).values())\n .forEach((child) => this.removeRef(this.refIds.get(child)));\n }\n }\n\n this.refs.delete(refId); // remove ref\n delete this.refCounts[refId]; // remove ref count\n delete this.callbacks[refId]; // remove callbacks\n });\n\n // clear deleted refs.\n this.deletedRefs.clear();\n }\n\n addCallback(refId: number, fieldOrOperation: string | number, callback: Function) {\n if (refId === undefined) {\n const name = (typeof(fieldOrOperation) === \"number\")\n ? OPERATION[fieldOrOperation]\n : fieldOrOperation\n throw new Error(\n `Can't addCallback on '${name}' (refId is undefined)`\n );\n }\n if (!this.callbacks[refId]) {\n this.callbacks[refId] = {};\n }\n if (!this.callbacks[refId][fieldOrOperation]) {\n this.callbacks[refId][fieldOrOperation] = [];\n }\n this.callbacks[refId][fieldOrOperation].push(callback);\n return () => this.removeCallback(refId, fieldOrOperation, callback);\n }\n\n removeCallback(refId: number, field: string | number, callback: Function) {\n const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);\n if (index !== -1) {\n spliceOne(this.callbacks[refId][field], index);\n }\n }\n\n}"]}
1
+ {"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/decoder/ReferenceTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../Metadata\";\nimport { $childType } from \"../types/symbols\";\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { spliceOne } from \"../types/utils\";\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport { OPERATION } from \"../encoding/spec\";\n\nclass DecodingWarning extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DecodingWarning\";\n }\n}\n\n/**\n * Used for decoding only.\n */\n\nexport type SchemaCallbacks = { [field: string | number]: Function[] };\n\nexport class ReferenceTracker {\n //\n // Relation of refId => Schema structure\n // For direct access of structures during decoding time.\n //\n public refs = new Map<number, Ref>();\n public refIds = new WeakMap<Ref, number>();\n\n public refCounts: { [refId: number]: number; } = {};\n public deletedRefs = new Set<number>();\n\n public callbacks: { [refId: number]: SchemaCallbacks } = {};\n protected nextUniqueId: number = 0;\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n // for decoding\n addRef(refId: number, ref: Ref, incrementCount: boolean = true) {\n this.refs.set(refId, ref);\n this.refIds.set(ref, refId);\n\n if (incrementCount) {\n this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;\n }\n\n if (this.deletedRefs.has(refId)) {\n this.deletedRefs.delete(refId);\n }\n }\n\n // for decoding\n removeRef(refId: number) {\n const refCount = this.refCounts[refId];\n\n if (refCount === undefined) {\n try {\n throw new DecodingWarning(\"trying to remove refId that doesn't exist\");\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if (refCount === 0) {\n try {\n const ref = this.refs.get(refId);\n throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if ((this.refCounts[refId] = refCount - 1) <= 0) {\n this.deletedRefs.add(refId);\n }\n }\n\n clearRefs() {\n this.refs.clear();\n this.deletedRefs.clear();\n this.callbacks = {};\n this.refCounts = {};\n }\n\n // for decoding\n garbageCollectDeletedRefs() {\n this.deletedRefs.forEach((refId) => {\n //\n // Skip active references.\n //\n if (this.refCounts[refId] > 0) { return; }\n\n const ref = this.refs.get(refId);\n\n //\n // Ensure child schema instances have their references removed as well.\n //\n if (Metadata.isValidInstance(ref)) {\n const metadata: Metadata = ref.constructor[Symbol.metadata];\n for (const index in metadata) {\n const field = metadata[index as any as number].name;\n const childRefId = typeof(ref[field]) === \"object\" && this.refIds.get(ref[field]);\n if (childRefId) {\n this.removeRef(childRefId);\n }\n }\n\n } else {\n if (typeof (Object.values(ref[$childType])[0]) === \"function\") {\n Array.from((ref as MapSchema).values())\n .forEach((child) => this.removeRef(this.refIds.get(child)));\n }\n }\n\n this.refs.delete(refId); // remove ref\n delete this.refCounts[refId]; // remove ref count\n delete this.callbacks[refId]; // remove callbacks\n });\n\n // clear deleted refs.\n this.deletedRefs.clear();\n }\n\n addCallback(refId: number, fieldOrOperation: string | number, callback: Function) {\n if (refId === undefined) {\n const name = (typeof(fieldOrOperation) === \"number\")\n ? OPERATION[fieldOrOperation]\n : fieldOrOperation\n throw new Error(\n `Can't addCallback on '${name}' (refId is undefined)`\n );\n }\n if (!this.callbacks[refId]) {\n this.callbacks[refId] = {};\n }\n if (!this.callbacks[refId][fieldOrOperation]) {\n this.callbacks[refId][fieldOrOperation] = [];\n }\n this.callbacks[refId][fieldOrOperation].push(callback);\n return () => this.removeCallback(refId, fieldOrOperation, callback);\n }\n\n removeCallback(refId: number, field: string | number, callback: Function) {\n const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);\n if (index !== -1) {\n spliceOne(this.callbacks[refId][field], index);\n }\n }\n\n}\n"]}
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRawChangesCallback = void 0;
3
+ exports.getRawChangesCallback = getRawChangesCallback;
4
4
  function getRawChangesCallback(decoder, callback) {
5
5
  decoder.triggerChanges = callback;
6
6
  }
7
- exports.getRawChangesCallback = getRawChangesCallback;
8
7
  //# sourceMappingURL=RawChanges.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"RawChanges.js","sourceRoot":"","sources":["../../../src/decoder/strategy/RawChanges.ts"],"names":[],"mappings":";;;AAGA,SAAgB,qBAAqB,CACjC,OAAgB,EAChB,QAAyC;IAEzC,OAAO,CAAC,cAAc,GAAG,QAAQ,CAAC;AACtC,CAAC;AALD,sDAKC","sourcesContent":["import { DataChange } from \"../DecodeOperation\";\nimport { Decoder } from \"../Decoder\";\n\nexport function getRawChangesCallback(\n decoder: Decoder,\n callback: (changes: DataChange[]) => void\n) {\n decoder.triggerChanges = callback;\n}"]}
1
+ {"version":3,"file":"RawChanges.js","sourceRoot":"","sources":["../../../src/decoder/strategy/RawChanges.ts"],"names":[],"mappings":";;AAGA,sDAKC;AALD,SAAgB,qBAAqB,CACjC,OAAgB,EAChB,QAAyC;IAEzC,OAAO,CAAC,cAAc,GAAG,QAAQ,CAAC;AACtC,CAAC","sourcesContent":["import { DataChange } from \"../DecodeOperation\";\nimport { Decoder } from \"../Decoder\";\n\nexport function getRawChangesCallback(\n decoder: Decoder,\n callback: (changes: DataChange[]) => void\n) {\n decoder.triggerChanges = callback;\n}"]}
@@ -1,20 +1,53 @@
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 GetCallbackProxy = (<T extends Schema>(instance: T) => CallbackProxy<T>);
5
+ 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
6
  type InstanceCallback<T> = {
6
- listen<K extends NonFunctionPropNames<T>>(prop: K, callback: (value: T[K], previousValue: T[K]) => void, immediate?: boolean): any;
7
- onChange(callback: () => void): void;
7
+ /**
8
+ * Trigger callback when value of a property changes.
9
+ *
10
+ * @param prop name of the property
11
+ * @param callback callback to be triggered on property change
12
+ * @param immediate trigger immediatelly if property has been already set.
13
+ * @return callback to detach the listener
14
+ */
15
+ listen<K extends NonFunctionPropNames<T>>(prop: K, callback: (value: T[K], previousValue: T[K]) => void, immediate?: boolean): () => void;
16
+ /**
17
+ * Trigger callback whenever any property changed within this instance.
18
+ *
19
+ * @param prop name of the property
20
+ * @param callback callback to be triggered on property change
21
+ * @param immediate trigger immediatelly if property has been already set.
22
+ * @return callback to detach the listener
23
+ */
24
+ onChange(callback: () => void): () => void;
25
+ /**
26
+ * Bind properties to another object. Changes on the properties will be reflected on the target object.
27
+ *
28
+ * @param targetObject object to bind properties to
29
+ * @param properties list of properties to bind. If not provided, all properties will be bound.
30
+ */
8
31
  bindTo(targetObject: any, properties?: Array<NonFunctionPropNames<T>>): void;
9
32
  } & {
10
- [K in NonFunctionNonPrimitivePropNames<T>]: GetProxyType<T[K]>;
33
+ [K in NonFunctionNonPrimitivePropNames<T>]: CallbackProxy<T[K]>;
11
34
  };
12
35
  type CollectionCallback<K, V> = {
13
- onAdd(callback: (item: V, index: K) => void, immediate?: boolean): void;
14
- onRemove(callback: (item: V, index: K) => void): void;
15
- };
16
- export declare function getStateCallbacks(decoder: Decoder): {
17
- $: <T>(instance: T) => GetProxyType<T>;
18
- trigger: (changes: DataChange[]) => void;
36
+ /**
37
+ * Trigger callback when an item has been added to the collection.
38
+ *
39
+ * @param callback
40
+ * @param immediate
41
+ * @return callback to detach the onAdd listener
42
+ */
43
+ onAdd(callback: (item: V, index: K) => void, immediate?: boolean): () => void;
44
+ /**
45
+ * Trigger callback when an item has been removed to the collection.
46
+ *
47
+ * @param callback
48
+ * @return callback to detach the onRemove listener
49
+ */
50
+ onRemove(callback: (item: V, index: K) => void): () => void;
19
51
  };
52
+ export declare function getDecoderStateCallbacks<T extends Schema>(decoder: Decoder<T>): GetCallbackProxy;
20
53
  export {};
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getStateCallbacks = void 0;
3
+ exports.getDecoderStateCallbacks = getDecoderStateCallbacks;
4
4
  const spec_1 = require("../../encoding/spec");
5
5
  const Schema_1 = require("../../Schema");
6
- function getStateCallbacks(decoder) {
6
+ function getDecoderStateCallbacks(decoder) {
7
7
  const $root = decoder.root;
8
8
  const callbacks = $root.callbacks;
9
- let isTriggeringOnAdd = false;
9
+ const onAddCalls = new WeakMap();
10
+ let currentOnAddCallback;
10
11
  decoder.triggerChanges = function (allChanges) {
11
12
  const uniqueRefIds = new Set();
12
13
  for (let i = 0, l = allChanges.length; i < l; i++) {
@@ -26,52 +27,38 @@ function getStateCallbacks(decoder) {
26
27
  for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
27
28
  deleteCallbacks[i]();
28
29
  }
29
- // callbacks[$root.refIds.get(change.previousValue)]?.[OPERATION.DELETE]?.forEach(callback =>
30
- // callback());
31
30
  }
32
31
  if (ref instanceof Schema_1.Schema) {
33
32
  //
34
33
  // Handle schema instance
35
34
  //
36
35
  if (!uniqueRefIds.has(refId)) {
37
- try {
38
- // trigger onChange
39
- const replaceCallbacks = $callbacks?.[spec_1.OPERATION.REPLACE];
40
- for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
41
- replaceCallbacks[i]();
42
- }
43
- }
44
- catch (e) {
45
- console.error(e);
36
+ // trigger onChange
37
+ const replaceCallbacks = $callbacks?.[spec_1.OPERATION.REPLACE];
38
+ for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
39
+ replaceCallbacks[i]();
40
+ // try {
41
+ // } catch (e) {
42
+ // console.error(e);
43
+ // }
46
44
  }
47
45
  }
48
- try {
49
- if ($callbacks.hasOwnProperty(change.field)) {
50
- const fieldCallbacks = $callbacks[change.field];
51
- for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
52
- fieldCallbacks[i](change.value, change.previousValue);
53
- }
46
+ if ($callbacks.hasOwnProperty(change.field)) {
47
+ const fieldCallbacks = $callbacks[change.field];
48
+ for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
49
+ fieldCallbacks[i](change.value, change.previousValue);
50
+ // try {
51
+ // } catch (e) {
52
+ // console.error(e);
53
+ // }
54
54
  }
55
55
  }
56
- catch (e) {
57
- //
58
- console.error(e);
59
- }
60
56
  }
61
57
  else {
62
58
  //
63
59
  // Handle collection of items
64
60
  //
65
- if (change.op === spec_1.OPERATION.ADD && change.previousValue === undefined) {
66
- // triger onAdd
67
- isTriggeringOnAdd = true;
68
- const addCallbacks = $callbacks[spec_1.OPERATION.ADD];
69
- for (let i = addCallbacks?.length - 1; i >= 0; i--) {
70
- addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
71
- }
72
- isTriggeringOnAdd = false;
73
- }
74
- else if ((change.op & spec_1.OPERATION.DELETE) === spec_1.OPERATION.DELETE) {
61
+ if ((change.op & spec_1.OPERATION.DELETE) === spec_1.OPERATION.DELETE) {
75
62
  //
76
63
  // FIXME: `previousValue` should always be available.
77
64
  //
@@ -83,7 +70,6 @@ function getStateCallbacks(decoder) {
83
70
  }
84
71
  }
85
72
  // Handle DELETE_AND_ADD operations
86
- // FIXME: should we set "isTriggeringOnAdd" here?
87
73
  if ((change.op & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD) {
88
74
  const addCallbacks = $callbacks[spec_1.OPERATION.ADD];
89
75
  for (let i = addCallbacks?.length - 1; i >= 0; i--) {
@@ -91,6 +77,13 @@ function getStateCallbacks(decoder) {
91
77
  }
92
78
  }
93
79
  }
80
+ else if ((change.op & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD && change.previousValue === undefined) {
81
+ // triger onAdd
82
+ const addCallbacks = $callbacks[spec_1.OPERATION.ADD];
83
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
84
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
85
+ }
86
+ }
94
87
  // trigger onChange
95
88
  if (change.value !== change.previousValue) {
96
89
  const replaceCallbacks = $callbacks[spec_1.OPERATION.REPLACE];
@@ -107,11 +100,11 @@ function getStateCallbacks(decoder) {
107
100
  let isCollection = ((context.instance && typeof (context.instance['forEach']) === "function") ||
108
101
  (metadataOrType && typeof (metadataOrType[Symbol.metadata]) === "undefined"));
109
102
  if (metadata && !isCollection) {
110
- const onAdd = function (ref, prop, callback, immediate) {
103
+ const onAddListen = function (ref, prop, callback, immediate) {
111
104
  // immediate trigger
112
105
  if (immediate &&
113
106
  context.instance[prop] !== undefined &&
114
- !isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)
107
+ !onAddCalls.has(currentOnAddCallback) // Workaround for https://github.com/colyseus/schema/issues/147
115
108
  ) {
116
109
  callback(context.instance[prop], undefined);
117
110
  }
@@ -123,22 +116,36 @@ function getStateCallbacks(decoder) {
123
116
  return new Proxy({
124
117
  listen: function listen(prop, callback, immediate = true) {
125
118
  if (context.instance) {
126
- return onAdd(context.instance, prop, callback, immediate);
119
+ return onAddListen(context.instance, prop, callback, immediate);
127
120
  }
128
121
  else {
129
122
  // collection instance not received yet
130
- context.onInstanceAvailable((ref, existing) => onAdd(ref, prop, callback, immediate && existing));
123
+ let detachCallback = () => { };
124
+ context.onInstanceAvailable((ref, existing) => {
125
+ detachCallback = onAddListen(ref, prop, callback, immediate && existing && !onAddCalls.has(currentOnAddCallback));
126
+ });
127
+ return () => detachCallback();
131
128
  }
132
129
  },
133
130
  onChange: function onChange(callback) {
134
131
  return $root.addCallback($root.refIds.get(context.instance), spec_1.OPERATION.REPLACE, callback);
135
132
  },
133
+ //
134
+ // TODO: refactor `bindTo()` implementation.
135
+ // There is room for improvement.
136
+ //
136
137
  bindTo: function bindTo(targetObject, properties) {
137
- console.log("bindTo", targetObject, properties);
138
+ if (!properties) {
139
+ properties = Object.keys(metadata).map((index) => metadata[index].name);
140
+ }
141
+ return $root.addCallback($root.refIds.get(context.instance), spec_1.OPERATION.REPLACE, () => {
142
+ properties.forEach((prop) => targetObject[prop] = context.instance[prop]);
143
+ });
138
144
  }
139
145
  }, {
140
146
  get(target, prop) {
141
- if (metadata[prop]) {
147
+ const metadataField = metadata[metadata[prop]];
148
+ if (metadataField) {
142
149
  const instance = context.instance?.[prop];
143
150
  const onInstanceAvailable = ((callback) => {
144
151
  const unbind = $(context.instance).listen(prop, (value, _) => {
@@ -154,8 +161,9 @@ function getStateCallbacks(decoder) {
154
161
  callback(instance, true);
155
162
  }
156
163
  });
157
- return getProxy(metadata[prop].type, {
158
- instance,
164
+ return getProxy(metadataField.type, {
165
+ // make sure refId is available, otherwise need to wait for the instance to be available.
166
+ instance: ($root.refIds.get(instance) && instance),
159
167
  parentInstance: context.instance,
160
168
  onInstanceAvailable,
161
169
  });
@@ -179,7 +187,13 @@ function getStateCallbacks(decoder) {
179
187
  if (immediate) {
180
188
  ref.forEach((v, k) => callback(v, k));
181
189
  }
182
- return $root.addCallback($root.refIds.get(ref), spec_1.OPERATION.ADD, callback);
190
+ return $root.addCallback($root.refIds.get(ref), spec_1.OPERATION.ADD, (value, key) => {
191
+ onAddCalls.set(callback, true);
192
+ currentOnAddCallback = callback;
193
+ callback(value, key);
194
+ onAddCalls.delete(callback);
195
+ currentOnAddCallback = undefined;
196
+ });
183
197
  };
184
198
  const onRemove = function (ref, callback) {
185
199
  return $root.addCallback($root.refIds.get(ref), spec_1.OPERATION.DELETE, callback);
@@ -190,23 +204,29 @@ function getStateCallbacks(decoder) {
190
204
  // https://github.com/colyseus/schema/issues/147
191
205
  // If parent instance has "onAdd" registered, avoid triggering immediate callback.
192
206
  //
193
- // FIXME: "isTriggeringOnAdd" is a workaround. We should find a better way to handle this.
194
- //
195
- if (context.onInstanceAvailable) {
196
- // collection instance not received yet
197
- context.onInstanceAvailable((ref, existing) => onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));
207
+ if (context.instance) {
208
+ return onAdd(context.instance, callback, immediate && !onAddCalls.has(currentOnAddCallback));
198
209
  }
199
- else if (context.instance) {
200
- onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);
210
+ else if (context.onInstanceAvailable) {
211
+ // collection instance not received yet
212
+ let detachCallback = () => { };
213
+ context.onInstanceAvailable((ref, existing) => {
214
+ detachCallback = onAdd(ref, callback, immediate && existing && !onAddCalls.has(currentOnAddCallback));
215
+ });
216
+ return () => detachCallback();
201
217
  }
202
218
  },
203
219
  onRemove: function (callback) {
204
220
  if (context.onInstanceAvailable) {
205
221
  // collection instance not received yet
206
- context.onInstanceAvailable((ref) => onRemove(ref, callback));
222
+ let detachCallback = () => { };
223
+ context.onInstanceAvailable((ref) => {
224
+ detachCallback = onRemove(ref, callback);
225
+ });
226
+ return () => detachCallback();
207
227
  }
208
228
  else if (context.instance) {
209
- onRemove(context.instance, callback);
229
+ return onRemove(context.instance, callback);
210
230
  }
211
231
  },
212
232
  }, {
@@ -225,16 +245,6 @@ function getStateCallbacks(decoder) {
225
245
  function $(instance) {
226
246
  return getProxy(undefined, { instance });
227
247
  }
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
- };
248
+ return $;
238
249
  }
239
- exports.getStateCallbacks = getStateCallbacks;
240
250
  //# sourceMappingURL=StateCallbacks.js.map