@colyseus/schema 3.0.0-alpha.30 → 3.0.0-alpha.31

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 (73) hide show
  1. package/build/cjs/index.js +383 -341
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +383 -341
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +383 -341
  6. package/lib/Metadata.d.ts +14 -5
  7. package/lib/Metadata.js +49 -20
  8. package/lib/Metadata.js.map +1 -1
  9. package/lib/Reflection.js +4 -13
  10. package/lib/Reflection.js.map +1 -1
  11. package/lib/Schema.js +26 -39
  12. package/lib/Schema.js.map +1 -1
  13. package/lib/annotations.d.ts +1 -2
  14. package/lib/annotations.js +58 -52
  15. package/lib/annotations.js.map +1 -1
  16. package/lib/bench_encode.js +33 -11
  17. package/lib/bench_encode.js.map +1 -1
  18. package/lib/decoder/DecodeOperation.js +4 -8
  19. package/lib/decoder/DecodeOperation.js.map +1 -1
  20. package/lib/decoder/ReferenceTracker.js +3 -2
  21. package/lib/decoder/ReferenceTracker.js.map +1 -1
  22. package/lib/decoder/strategy/StateCallbacks.js +4 -3
  23. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  24. package/lib/encoder/ChangeTree.d.ts +8 -7
  25. package/lib/encoder/ChangeTree.js +128 -115
  26. package/lib/encoder/ChangeTree.js.map +1 -1
  27. package/lib/encoder/EncodeOperation.d.ts +1 -4
  28. package/lib/encoder/EncodeOperation.js +46 -46
  29. package/lib/encoder/EncodeOperation.js.map +1 -1
  30. package/lib/encoder/Encoder.js +11 -3
  31. package/lib/encoder/Encoder.js.map +1 -1
  32. package/lib/encoder/StateView.js +3 -3
  33. package/lib/encoder/StateView.js.map +1 -1
  34. package/lib/encoding/assert.d.ts +2 -1
  35. package/lib/encoding/assert.js +2 -2
  36. package/lib/encoding/assert.js.map +1 -1
  37. package/lib/index.d.ts +1 -2
  38. package/lib/index.js +11 -10
  39. package/lib/index.js.map +1 -1
  40. package/lib/types/TypeContext.js +7 -14
  41. package/lib/types/TypeContext.js.map +1 -1
  42. package/lib/types/custom/ArraySchema.js +6 -0
  43. package/lib/types/custom/ArraySchema.js.map +1 -1
  44. package/lib/types/custom/CollectionSchema.js +1 -0
  45. package/lib/types/custom/CollectionSchema.js.map +1 -1
  46. package/lib/types/custom/MapSchema.js +5 -0
  47. package/lib/types/custom/MapSchema.js.map +1 -1
  48. package/lib/types/custom/SetSchema.js +1 -0
  49. package/lib/types/custom/SetSchema.js.map +1 -1
  50. package/lib/types/symbols.d.ts +1 -0
  51. package/lib/types/symbols.js +2 -1
  52. package/lib/types/symbols.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/Metadata.ts +60 -29
  55. package/src/Reflection.ts +5 -15
  56. package/src/Schema.ts +33 -45
  57. package/src/annotations.ts +75 -67
  58. package/src/bench_encode.ts +37 -13
  59. package/src/decoder/DecodeOperation.ts +4 -10
  60. package/src/decoder/ReferenceTracker.ts +3 -2
  61. package/src/decoder/strategy/StateCallbacks.ts +4 -3
  62. package/src/encoder/ChangeTree.ts +146 -135
  63. package/src/encoder/EncodeOperation.ts +64 -58
  64. package/src/encoder/Encoder.ts +16 -4
  65. package/src/encoder/StateView.ts +4 -4
  66. package/src/encoding/assert.ts +4 -3
  67. package/src/index.ts +1 -4
  68. package/src/types/TypeContext.ts +10 -15
  69. package/src/types/custom/ArraySchema.ts +8 -0
  70. package/src/types/custom/CollectionSchema.ts +1 -0
  71. package/src/types/custom/MapSchema.ts +6 -0
  72. package/src/types/custom/SetSchema.ts +1 -0
  73. package/src/types/symbols.ts +2 -0
@@ -1,6 +1,6 @@
1
1
  import type { Schema } from "../Schema";
2
2
  import { TypeContext } from "../types/TypeContext";
3
- import { $changes, $encoder, $filter } from "../types/symbols";
3
+ import { $changes, $encoder, $filter, $isNew, $onEncodeEnd } from "../types/symbols";
4
4
 
5
5
  import * as encode from "../encoding/encode";
6
6
  import type { Iterator } from "../encoding/decode";
@@ -55,9 +55,9 @@ export class Encoder<T extends Schema = any> {
55
55
  const hasView = (view !== undefined);
56
56
  const rootChangeTree = this.state[$changes];
57
57
 
58
- const changeTreesIterator = changeTrees.entries();
58
+ const shouldClearChanges = !isEncodeAll && !hasView;
59
59
 
60
- for (const [changeTree, changes] of changeTreesIterator) {
60
+ for (const [changeTree, changes] of changeTrees.entries()) {
61
61
  const ref = changeTree.ref;
62
62
 
63
63
  const ctor = ref['constructor'];
@@ -117,6 +117,10 @@ export class Encoder<T extends Schema = any> {
117
117
 
118
118
  encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
119
119
  }
120
+
121
+ // if (shouldClearChanges) {
122
+ // changeTree.endEncode();
123
+ // }
120
124
  }
121
125
 
122
126
  if (it.offset > buffer.byteLength) {
@@ -143,7 +147,7 @@ export class Encoder<T extends Schema = any> {
143
147
  //
144
148
  // only clear changes after making sure buffer resize is not required.
145
149
  //
146
- if (!isEncodeAll && !hasView) {
150
+ if (shouldClearChanges) {
147
151
  //
148
152
  // FIXME: avoid iterating over change trees twice.
149
153
  //
@@ -251,6 +255,14 @@ export class Encoder<T extends Schema = any> {
251
255
  const changeTreesIterator = changeTrees.entries();
252
256
  for (const [changeTree, _] of changeTreesIterator) {
253
257
  changeTree.endEncode();
258
+ // changeTree.changes.clear();
259
+
260
+ // // ArraySchema and MapSchema have a custom "encode end" method
261
+ // changeTree.ref[$onEncodeEnd]?.();
262
+
263
+ // // Not a new instance anymore
264
+ // delete changeTree[$isNew];
265
+
254
266
  }
255
267
  }
256
268
 
@@ -34,7 +34,7 @@ export class StateView {
34
34
  return this;
35
35
  }
36
36
 
37
- // FIXME: ArraySchema/MapSchema does not have metadata
37
+ // FIXME: ArraySchema/MapSchema do not have metadata
38
38
  const metadata: Metadata = obj.constructor[Symbol.metadata];
39
39
  const changeTree: ChangeTree = obj[$changes];
40
40
  this.items.add(changeTree);
@@ -84,7 +84,7 @@ export class StateView {
84
84
  : changeTree.allChanges;
85
85
 
86
86
  changeSet.forEach((op, index) => {
87
- const tagAtIndex = metadata?.[metadata?.[index]].tag;
87
+ const tagAtIndex = metadata?.[index].tag;
88
88
  if (
89
89
  (
90
90
  isInvisible || // if "invisible", include all
@@ -101,7 +101,7 @@ export class StateView {
101
101
  // Add children of this ChangeTree to this view
102
102
  changeTree.forEachChild((change, index) => {
103
103
  // Do not ADD children that don't have the same tag
104
- if (metadata && metadata[metadata[index]].tag !== tag) {
104
+ if (metadata && metadata[index].tag !== tag) {
105
105
  return;
106
106
  }
107
107
  this.add(change.ref, tag, false);
@@ -166,7 +166,7 @@ export class StateView {
166
166
  let changes = this.changes.get(changeTree);
167
167
  if (changes === undefined) {
168
168
  changes = new Map<number, OPERATION>();
169
- this.changes.set(changeTree, changes)
169
+ this.changes.set(changeTree, changes);
170
170
  }
171
171
 
172
172
  if (tag === DEFAULT_VIEW_TAG) {
@@ -3,6 +3,7 @@ import { CollectionSchema } from "../types/custom/CollectionSchema";
3
3
  import { MapSchema } from "../types/custom/MapSchema";
4
4
  import { SetSchema } from "../types/custom/SetSchema";
5
5
  import { ArraySchema } from "../types/custom/ArraySchema";
6
+ import type { Ref } from "../encoder/ChangeTree";
6
7
 
7
8
  export class EncodeSchemaError extends Error {}
8
9
 
@@ -43,16 +44,16 @@ export function assertType(value: any, type: string, klass: Schema, field: strin
43
44
  }
44
45
 
45
46
  export function assertInstanceType(
46
- value: Schema,
47
+ value: Ref,
47
48
  type: typeof Schema
48
49
  | typeof ArraySchema
49
50
  | typeof MapSchema
50
51
  | typeof CollectionSchema
51
52
  | typeof SetSchema,
52
- klass: Schema,
53
+ instance: Ref,
53
54
  field: string | number,
54
55
  ) {
55
56
  if (!(value instanceof type)) {
56
- throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && (value as any).constructor.name}' was provided in ${klass.constructor.name}#${field}`);
57
+ throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && (value as any).constructor.name}' was provided in ${instance.constructor.name}#${field}`);
57
58
  }
58
59
  }
package/src/index.ts CHANGED
@@ -1,9 +1,5 @@
1
1
  export { Schema } from "./Schema";
2
2
  export type { DataChange } from "./decoder/DecodeOperation";
3
-
4
- import { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType } from "./types/symbols";
5
- export { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType };
6
-
7
3
  export type { ToJSON } from "./types/HelperTypes";
8
4
 
9
5
  import { MapSchema } from "./types/custom/MapSchema"
@@ -30,6 +26,7 @@ registerType("collection", { constructor: CollectionSchema, });
30
26
  export { dumpChanges } from "./utils";
31
27
 
32
28
  // Encoder / Decoder
29
+ export { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType } from "./types/symbols";
33
30
  export type { Iterator } from "./encoding/decode";
34
31
  import * as encode from "./encoding/encode";
35
32
  import * as decode from "./encoding/decode";
@@ -84,19 +84,11 @@ export class TypeContext {
84
84
  this.parentFiltered[`${this.schemas.get(klass)}-${parentIndex}`] = true;
85
85
  }
86
86
 
87
- for (const field in metadata) {
88
- // //
89
- // // Modify the field's metadata to include the parent field's view tag
90
- // //
91
- // if (
92
- // parentFieldViewTag !== undefined &&
93
- // metadata[field].tag === undefined
94
- // ) {
95
- // metadata[field].tag = parentFieldViewTag;
96
- // }
97
-
98
- const fieldType = metadata[field].type;
99
- const viewTag = metadata[field].tag;
87
+ for (const fieldIndex in metadata) {
88
+ const index = fieldIndex as any as number;
89
+
90
+ const fieldType = metadata[index].type;
91
+ const viewTag = metadata[index].tag;
100
92
 
101
93
  if (typeof (fieldType) === "string") {
102
94
  continue;
@@ -104,10 +96,13 @@ export class TypeContext {
104
96
 
105
97
  if (Array.isArray(fieldType)) {
106
98
  const type = fieldType[0];
99
+
100
+ // skip primitive types
107
101
  if (type === "string") {
108
102
  continue;
109
103
  }
110
- this.discoverTypes(type as typeof Schema, metadata[field].index, viewTag);
104
+
105
+ this.discoverTypes(type as typeof Schema, index, viewTag);
111
106
 
112
107
  } else if (typeof (fieldType) === "function") {
113
108
  this.discoverTypes(fieldType as typeof Schema, viewTag);
@@ -120,7 +115,7 @@ export class TypeContext {
120
115
  continue;
121
116
  }
122
117
 
123
- this.discoverTypes(type as typeof Schema, metadata[field].index, viewTag);
118
+ this.discoverTypes(type as typeof Schema, index, viewTag);
124
119
  }
125
120
  }
126
121
  }
@@ -8,6 +8,7 @@ import { Collection } from "../HelperTypes";
8
8
  import { encodeArray } from "../../encoder/EncodeOperation";
9
9
  import { decodeArray } from "../../decoder/DecodeOperation";
10
10
  import type { StateView } from "../../encoder/StateView";
11
+ import { assertInstanceType } from "../../encoding/assert";
11
12
 
12
13
  const DEFAULT_SORT = (a: any, b: any) => {
13
14
  const A = a.toString();
@@ -85,6 +86,8 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
85
86
 
86
87
  } else {
87
88
  if (setValue[$changes]) {
89
+ assertInstanceType(setValue, obj[$childType] as typeof Schema, obj, key);
90
+
88
91
  if (obj.items[key as unknown as number] !== undefined) {
89
92
  if (setValue[$changes][$isNew]) {
90
93
  this[$changes].indexedOperation(Number(key), OPERATION.MOVE_AND_ADD);
@@ -99,6 +102,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
99
102
  } else if (setValue[$changes][$isNew]) {
100
103
  this[$changes].indexedOperation(Number(key), OPERATION.ADD);
101
104
  }
105
+
102
106
  } else {
103
107
  obj.$changeAt(Number(key), setValue);
104
108
  }
@@ -133,6 +137,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
133
137
  });
134
138
 
135
139
  this[$changes] = new ChangeTree(proxy);
140
+ this[$changes].indexes = {};
136
141
  this.push.apply(this, items);
137
142
 
138
143
  return proxy;
@@ -159,6 +164,9 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
159
164
  // skip null values
160
165
  if (value === undefined || value === null) {
161
166
  return;
167
+
168
+ } else if (typeof (value) === "object" && this[$childType]) {
169
+ assertInstanceType(value as any, this[$childType] as typeof Schema, this, i);
162
170
  }
163
171
 
164
172
  const changeTree = this[$changes];
@@ -41,6 +41,7 @@ export class CollectionSchema<V=any> implements Collection<K, V>{
41
41
 
42
42
  constructor (initialValues?: Array<V>) {
43
43
  this[$changes] = new ChangeTree(this);
44
+ this[$changes].indexes = {};
44
45
 
45
46
  if (initialValues) {
46
47
  initialValues.forEach((v) => this.add(v));
@@ -6,6 +6,8 @@ import { Collection } from "../HelperTypes";
6
6
  import { decodeKeyValueOperation } from "../../decoder/DecodeOperation";
7
7
  import { encodeKeyValueOperation } from "../../encoder/EncodeOperation";
8
8
  import type { StateView } from "../../encoder/StateView";
9
+ import type { Schema } from "../../Schema";
10
+ import { assertInstanceType } from "../../encoding/assert";
9
11
 
10
12
  export class MapSchema<V=any, K extends string = string> implements Map<K, V>, Collection<K, V, [K, V]> {
11
13
  protected childType: new () => V;
@@ -39,6 +41,7 @@ export class MapSchema<V=any, K extends string = string> implements Map<K, V>, C
39
41
 
40
42
  constructor (initialValues?: Map<K, V> | Record<K, V>) {
41
43
  this[$changes] = new ChangeTree(this);
44
+ this[$changes].indexes = {};
42
45
 
43
46
  if (initialValues) {
44
47
  if (
@@ -71,6 +74,9 @@ export class MapSchema<V=any, K extends string = string> implements Map<K, V>, C
71
74
  set(key: K, value: V) {
72
75
  if (value === undefined || value === null) {
73
76
  throw new Error(`MapSchema#set('${key}', ${value}): trying to set ${value} value on '${key}'.`);
77
+
78
+ } else if (typeof(value) === "object" && this[$childType]) {
79
+ assertInstanceType(value as any, this[$childType] as typeof Schema, this, key);
74
80
  }
75
81
 
76
82
  // Force "key" as string
@@ -40,6 +40,7 @@ export class SetSchema<V=any> implements Collection<number, V> {
40
40
 
41
41
  constructor (initialValues?: Array<V>) {
42
42
  this[$changes] = new ChangeTree(this);
43
+ this[$changes].indexes = {};
43
44
 
44
45
  if (initialValues) {
45
46
  initialValues.forEach((v) => this.add(v));
@@ -7,6 +7,8 @@ export const $filter = Symbol("$filter");
7
7
  export const $getByIndex = Symbol("$getByIndex");
8
8
  export const $deleteByIndex = Symbol("$deleteByIndex");
9
9
 
10
+ export const $descriptors = Symbol("$descriptors");
11
+
10
12
  /**
11
13
  * Used to hold ChangeTree instances whitin the structures
12
14
  */