@colyseus/schema 3.0.0-alpha.4 → 3.0.0-alpha.41

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 (146) hide show
  1. package/README.md +148 -62
  2. package/bin/schema-debug +94 -0
  3. package/build/cjs/index.js +2201 -1507
  4. package/build/cjs/index.js.map +1 -1
  5. package/build/esm/index.mjs +2198 -1506
  6. package/build/esm/index.mjs.map +1 -1
  7. package/build/umd/index.js +2208 -1514
  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 -32
  13. package/lib/Reflection.js.map +1 -1
  14. package/lib/Schema.d.ts +4 -4
  15. package/lib/Schema.js +44 -50
  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/bench_encode.d.ts +1 -0
  21. package/lib/bench_encode.js +130 -0
  22. package/lib/bench_encode.js.map +1 -0
  23. package/lib/codegen/api.js +1 -2
  24. package/lib/codegen/api.js.map +1 -1
  25. package/lib/codegen/languages/cpp.js +1 -2
  26. package/lib/codegen/languages/cpp.js.map +1 -1
  27. package/lib/codegen/languages/csharp.js +2 -46
  28. package/lib/codegen/languages/csharp.js.map +1 -1
  29. package/lib/codegen/languages/haxe.js +1 -2
  30. package/lib/codegen/languages/haxe.js.map +1 -1
  31. package/lib/codegen/languages/java.js +1 -2
  32. package/lib/codegen/languages/java.js.map +1 -1
  33. package/lib/codegen/languages/js.js +1 -2
  34. package/lib/codegen/languages/js.js.map +1 -1
  35. package/lib/codegen/languages/lua.js +1 -2
  36. package/lib/codegen/languages/lua.js.map +1 -1
  37. package/lib/codegen/languages/ts.js +1 -2
  38. package/lib/codegen/languages/ts.js.map +1 -1
  39. package/lib/codegen/parser.js +85 -3
  40. package/lib/codegen/parser.js.map +1 -1
  41. package/lib/codegen/types.js +6 -3
  42. package/lib/codegen/types.js.map +1 -1
  43. package/lib/debug.d.ts +1 -0
  44. package/lib/debug.js +51 -0
  45. package/lib/debug.js.map +1 -0
  46. package/lib/decoder/DecodeOperation.d.ts +3 -4
  47. package/lib/decoder/DecodeOperation.js +37 -19
  48. package/lib/decoder/DecodeOperation.js.map +1 -1
  49. package/lib/decoder/Decoder.d.ts +6 -7
  50. package/lib/decoder/Decoder.js +14 -14
  51. package/lib/decoder/Decoder.js.map +1 -1
  52. package/lib/decoder/ReferenceTracker.js +3 -2
  53. package/lib/decoder/ReferenceTracker.js.map +1 -1
  54. package/lib/decoder/strategy/RawChanges.js +1 -2
  55. package/lib/decoder/strategy/RawChanges.js.map +1 -1
  56. package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
  57. package/lib/decoder/strategy/StateCallbacks.js +75 -65
  58. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  59. package/lib/encoder/ChangeTree.d.ts +27 -21
  60. package/lib/encoder/ChangeTree.js +246 -186
  61. package/lib/encoder/ChangeTree.js.map +1 -1
  62. package/lib/encoder/EncodeOperation.d.ts +3 -6
  63. package/lib/encoder/EncodeOperation.js +51 -65
  64. package/lib/encoder/EncodeOperation.js.map +1 -1
  65. package/lib/encoder/Encoder.d.ts +9 -8
  66. package/lib/encoder/Encoder.js +168 -91
  67. package/lib/encoder/Encoder.js.map +1 -1
  68. package/lib/encoder/Root.d.ts +22 -0
  69. package/lib/encoder/Root.js +81 -0
  70. package/lib/encoder/Root.js.map +1 -0
  71. package/lib/encoder/StateView.d.ts +7 -7
  72. package/lib/encoder/StateView.js +70 -74
  73. package/lib/encoder/StateView.js.map +1 -1
  74. package/lib/encoding/assert.d.ts +7 -6
  75. package/lib/encoding/assert.js +13 -5
  76. package/lib/encoding/assert.js.map +1 -1
  77. package/lib/encoding/decode.d.ts +35 -20
  78. package/lib/encoding/decode.js +43 -87
  79. package/lib/encoding/decode.js.map +1 -1
  80. package/lib/encoding/encode.d.ts +36 -17
  81. package/lib/encoding/encode.js +82 -68
  82. package/lib/encoding/encode.js.map +1 -1
  83. package/lib/encoding/spec.d.ts +4 -5
  84. package/lib/encoding/spec.js +1 -2
  85. package/lib/encoding/spec.js.map +1 -1
  86. package/lib/index.d.ts +10 -9
  87. package/lib/index.js +24 -17
  88. package/lib/index.js.map +1 -1
  89. package/lib/types/HelperTypes.d.ts +34 -2
  90. package/lib/types/HelperTypes.js.map +1 -1
  91. package/lib/types/TypeContext.d.ts +23 -0
  92. package/lib/types/TypeContext.js +111 -0
  93. package/lib/types/TypeContext.js.map +1 -0
  94. package/lib/types/custom/ArraySchema.d.ts +2 -2
  95. package/lib/types/custom/ArraySchema.js +33 -22
  96. package/lib/types/custom/ArraySchema.js.map +1 -1
  97. package/lib/types/custom/CollectionSchema.js +1 -0
  98. package/lib/types/custom/CollectionSchema.js.map +1 -1
  99. package/lib/types/custom/MapSchema.d.ts +3 -1
  100. package/lib/types/custom/MapSchema.js +12 -4
  101. package/lib/types/custom/MapSchema.js.map +1 -1
  102. package/lib/types/custom/SetSchema.js +1 -0
  103. package/lib/types/custom/SetSchema.js.map +1 -1
  104. package/lib/types/registry.d.ts +8 -1
  105. package/lib/types/registry.js +23 -6
  106. package/lib/types/registry.js.map +1 -1
  107. package/lib/types/symbols.d.ts +8 -5
  108. package/lib/types/symbols.js +9 -6
  109. package/lib/types/symbols.js.map +1 -1
  110. package/lib/types/utils.js +1 -2
  111. package/lib/types/utils.js.map +1 -1
  112. package/lib/utils.js +9 -7
  113. package/lib/utils.js.map +1 -1
  114. package/package.json +7 -6
  115. package/src/Metadata.ts +190 -42
  116. package/src/Reflection.ts +77 -39
  117. package/src/Schema.ts +59 -64
  118. package/src/annotations.ts +156 -202
  119. package/src/bench_encode.ts +108 -0
  120. package/src/codegen/languages/csharp.ts +1 -47
  121. package/src/codegen/parser.ts +107 -0
  122. package/src/codegen/types.ts +1 -0
  123. package/src/debug.ts +55 -0
  124. package/src/decoder/DecodeOperation.ts +46 -18
  125. package/src/decoder/Decoder.ts +17 -15
  126. package/src/decoder/ReferenceTracker.ts +3 -2
  127. package/src/decoder/strategy/StateCallbacks.ts +153 -82
  128. package/src/encoder/ChangeTree.ts +286 -202
  129. package/src/encoder/EncodeOperation.ts +78 -78
  130. package/src/encoder/Encoder.ts +202 -97
  131. package/src/encoder/Root.ts +93 -0
  132. package/src/encoder/StateView.ts +76 -88
  133. package/src/encoding/assert.ts +17 -8
  134. package/src/encoding/decode.ts +62 -97
  135. package/src/encoding/encode.ts +99 -65
  136. package/src/encoding/spec.ts +3 -5
  137. package/src/index.ts +12 -20
  138. package/src/types/HelperTypes.ts +54 -2
  139. package/src/types/TypeContext.ts +133 -0
  140. package/src/types/custom/ArraySchema.ts +49 -19
  141. package/src/types/custom/CollectionSchema.ts +1 -0
  142. package/src/types/custom/MapSchema.ts +18 -5
  143. package/src/types/custom/SetSchema.ts +1 -0
  144. package/src/types/registry.ts +22 -3
  145. package/src/types/symbols.ts +10 -7
  146. package/src/utils.ts +7 -3
package/src/Reflection.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { type, PrimitiveType, DefinitionType, TypeContext } from "./annotations";
1
+ import { type, PrimitiveType, DefinitionType } from "./annotations";
2
+ import { TypeContext } from "./types/TypeContext";
2
3
  import { Metadata } from "./Metadata";
3
4
  import { ArraySchema } from "./types/custom/ArraySchema";
4
5
  import { Iterator } from "./encoding/decode";
5
6
  import { Encoder } from "./encoder/Encoder";
6
7
  import { Decoder } from "./decoder/Decoder";
7
8
  import { Schema } from "./Schema";
9
+ import { $numFields } from "./types/symbols";
8
10
 
9
11
  /**
10
12
  * Reflection
@@ -22,18 +24,32 @@ export class ReflectionType extends Schema {
22
24
  }
23
25
 
24
26
  export class Reflection extends Schema {
25
- @type([ ReflectionType ]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();
26
-
27
- static encode (instance: Schema, context?: TypeContext) {
28
- if (!context) {
29
- context = new TypeContext(instance.constructor as typeof Schema);
30
- }
27
+ @type([ReflectionType]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();
28
+ @type("number") rootType: number;
29
+
30
+ /**
31
+ * Encodes the TypeContext of an Encoder into a buffer.
32
+ *
33
+ * @param encoder Encoder instance
34
+ * @param it
35
+ * @returns
36
+ */
37
+ static encode(encoder: Encoder, it: Iterator = { offset: 0 }) {
38
+ const context = encoder.context;
31
39
 
32
40
  const reflection = new Reflection();
33
- const encoder = new Encoder(reflection);
41
+ const reflectionEncoder = new Encoder(reflection);
42
+
43
+ // rootType is usually the first schema passed to the Encoder
44
+ // (unless it inherits from another schema)
45
+ const rootType = context.schemas.get(encoder.state.constructor);
46
+ if (rootType > 0) { reflection.rootType = rootType; }
34
47
 
35
48
  const buildType = (currentType: ReflectionType, metadata: Metadata) => {
36
- for (const fieldName in metadata) {
49
+ for (const fieldIndex in metadata) {
50
+ const index = Number(fieldIndex);
51
+ const fieldName = metadata[index].name;
52
+
37
53
  // skip fields from parent classes
38
54
  if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
39
55
  continue;
@@ -44,7 +60,7 @@ export class Reflection extends Schema {
44
60
 
45
61
  let fieldType: string;
46
62
 
47
- const type = metadata[fieldName].type;
63
+ const type = metadata[index].type;
48
64
 
49
65
  if (typeof (type) === "string") {
50
66
  fieldType = type;
@@ -96,73 +112,95 @@ export class Reflection extends Schema {
96
112
  buildType(type, klass[Symbol.metadata]);
97
113
  }
98
114
 
99
- const it = { offset: 0 };
100
- const buf = encoder.encodeAll(it);
115
+ const buf = reflectionEncoder.encodeAll(it);
101
116
  return Buffer.from(buf, 0, it.offset);
102
117
  }
103
118
 
104
- static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): T {
119
+ /**
120
+ * Decodes the TypeContext from a buffer into a Decoder instance.
121
+ *
122
+ * @param bytes Reflection.encode() output
123
+ * @param it
124
+ * @returns Decoder instance
125
+ */
126
+ static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): Decoder<T> {
105
127
  const reflection = new Reflection();
106
128
 
107
129
  const reflectionDecoder = new Decoder(reflection);
108
130
  reflectionDecoder.decode(bytes, it);
109
131
 
110
- const context = new TypeContext();
111
-
112
- const schemaTypes = reflection.types.reduce((types, reflectionType) => {
113
- const parentKlass: typeof Schema = types[reflectionType.extendsId] || Schema;
114
- const schema: typeof Schema = class _ extends parentKlass {};
132
+ const typeContext = new TypeContext();
115
133
 
116
- // const _metadata = Object.create(_classSuper[Symbol.metadata] ?? null);
117
- const _metadata = parentKlass && parentKlass[Symbol.metadata] || Object.create(null);
118
- Object.defineProperty(schema, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata })
134
+ // 1st pass, initialize metadata + inheritance
135
+ reflection.types.forEach((reflectionType) => {
136
+ const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;
137
+ const schema: typeof Schema = class _ extends parentClass {};
119
138
 
120
139
  // register for inheritance support
121
140
  TypeContext.register(schema);
122
141
 
123
- const typeid = reflectionType.id;
124
- types[typeid] = schema
125
- context.add(schema, typeid);
126
- return types;
127
- }, {});
142
+ // // for inheritance support
143
+ // Metadata.initialize(schema);
128
144
 
129
- reflection.types.forEach((reflectionType) => {
130
- const schemaType = schemaTypes[reflectionType.id];
131
- const metadata = schemaType[Symbol.metadata];
132
-
133
- const parentKlass = reflection.types[reflectionType.extendsId];
134
- const parentFieldIndex = parentKlass && parentKlass.fields.length || 0;
145
+ typeContext.add(schema, reflectionType.id);
146
+ }, {});
135
147
 
148
+ // define fields
149
+ const addFields = (metadata: Metadata, reflectionType: ReflectionType, parentFieldIndex: number) => {
136
150
  reflectionType.fields.forEach((field, i) => {
137
151
  const fieldIndex = parentFieldIndex + i;
138
152
 
139
153
  if (field.referencedType !== undefined) {
140
154
  let fieldType = field.type;
141
- let refType = schemaTypes[field.referencedType];
155
+ let refType: PrimitiveType = typeContext.get(field.referencedType);
142
156
 
143
157
  // map or array of primitive type (-1)
144
158
  if (!refType) {
145
159
  const typeInfo = field.type.split(":");
146
160
  fieldType = typeInfo[0];
147
- refType = typeInfo[1];
161
+ refType = typeInfo[1] as PrimitiveType; // string
148
162
  }
149
163
 
150
164
  if (fieldType === "ref") {
151
- // type(refType)(schemaType.prototype, field.name);
152
165
  Metadata.addField(metadata, fieldIndex, field.name, refType);
153
166
 
154
167
  } else {
155
- // type({ [fieldType]: refType } as DefinitionType)(schemaType.prototype, field.name);
156
- Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType } as DefinitionType);
168
+ Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });
157
169
  }
158
170
 
159
171
  } else {
160
- // type(field.type as PrimitiveType)(schemaType.prototype, field.name);
161
172
  Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);
162
173
  }
163
174
  });
175
+ };
176
+
177
+ // 2nd pass, set fields
178
+ reflection.types.forEach((reflectionType) => {
179
+ const schema = typeContext.get(reflectionType.id);
180
+
181
+ // for inheritance support
182
+ const metadata = Metadata.initialize(schema);
183
+
184
+ const inheritedTypes: ReflectionType[] = [];
185
+
186
+ let parentType: ReflectionType = reflectionType;
187
+ do {
188
+ inheritedTypes.push(parentType);
189
+ parentType = reflection.types.find((t) => t.id === parentType.extendsId);
190
+ } while (parentType);
191
+
192
+ let parentFieldIndex = 0;
193
+
194
+ inheritedTypes.reverse().forEach((reflectionType) => {
195
+ // add fields from all inherited classes
196
+ // TODO: refactor this to avoid adding fields from parent classes
197
+ addFields(metadata, reflectionType, parentFieldIndex);
198
+ parentFieldIndex += reflectionType.fields.length;
199
+ });
164
200
  });
165
201
 
166
- return new (schemaTypes[0])();
202
+ const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();
203
+
204
+ return new Decoder<T>(state, typeContext);
167
205
  }
168
206
  }
package/src/Schema.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { OPERATION } from './encoding/spec';
2
- import { DEFAULT_VIEW_TAG, DefinitionType } from "./annotations";
2
+ import { DEFAULT_VIEW_TAG, type DefinitionType } from "./annotations";
3
3
 
4
4
  import { NonFunctionPropNames, ToJSON } from './types/HelperTypes';
5
5
 
6
- import { ChangeTree, Ref } from './encoder/ChangeTree';
7
- import { $changes, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track } from './types/symbols';
6
+ import { ChangeSet, ChangeTree, Ref } from './encoder/ChangeTree';
7
+ import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $track } from './types/symbols';
8
8
  import { StateView } from './encoder/StateView';
9
9
 
10
10
  import { encodeSchemaOperation } from './encoder/EncodeOperation';
@@ -15,11 +15,12 @@ import { getIndent } from './utils';
15
15
  /**
16
16
  * Schema encoder / decoder
17
17
  */
18
- export abstract class Schema {
19
-
18
+ export class Schema {
20
19
  static [$encoder] = encodeSchemaOperation;
21
20
  static [$decoder] = decodeSchemaOperation;
22
21
 
22
+ // public [$changes]: ChangeTree;
23
+
23
24
  /**
24
25
  * Assign the property descriptors required to track changes on this instance.
25
26
  * @param instance
@@ -31,37 +32,7 @@ export abstract class Schema {
31
32
  writable: true
32
33
  });
33
34
 
34
- const metadata = instance.constructor[Symbol.metadata];
35
-
36
- // Define property descriptors
37
- for (const field in metadata) {
38
- if (metadata[field].descriptor) {
39
- // for encoder
40
- Object.defineProperty(instance, `_${field}`, {
41
- value: undefined,
42
- writable: true,
43
- enumerable: false,
44
- configurable: true,
45
- });
46
- Object.defineProperty(instance, field, metadata[field].descriptor);
47
-
48
- } else {
49
- // for decoder
50
- Object.defineProperty(instance, field, {
51
- value: undefined,
52
- writable: true,
53
- enumerable: true,
54
- configurable: true,
55
- });
56
- }
57
-
58
- // Object.defineProperty(instance, field, {
59
- // ...instance.constructor[Symbol.metadata][field].descriptor
60
- // });
61
- // if (args[0]?.hasOwnProperty(field)) {
62
- // instance[field] = args[0][field];
63
- // }
64
- }
35
+ Object.defineProperties(instance, instance.constructor[Symbol.metadata]?.[$descriptors] || {});
65
36
  }
66
37
 
67
38
  static is(type: DefinitionType) {
@@ -88,7 +59,7 @@ export abstract class Schema {
88
59
  */
89
60
  static [$filter] (ref: Schema, index: number, view: StateView) {
90
61
  const metadata: Metadata = ref.constructor[Symbol.metadata];
91
- const tag = metadata[metadata[index]].tag;
62
+ const tag = metadata[index]?.tag;
92
63
 
93
64
  if (view === undefined) {
94
65
  // shared pass/encode: encode if doesn't have a tag
@@ -111,13 +82,17 @@ export abstract class Schema {
111
82
 
112
83
  // allow inherited classes to have a constructor
113
84
  constructor(...args: any[]) {
85
+ //
86
+ // inline
87
+ // Schema.initialize(this);
88
+ //
114
89
  Schema.initialize(this);
115
90
 
116
91
  //
117
92
  // Assign initial values
118
93
  //
119
94
  if (args[0]) {
120
- this.assign(args[0]);
95
+ Object.assign(this, args[0]);
121
96
  }
122
97
  }
123
98
 
@@ -135,21 +110,25 @@ export abstract class Schema {
135
110
  * @param operation OPERATION to perform (detected automatically)
136
111
  */
137
112
  public setDirty<K extends NonFunctionPropNames<this>>(property: K | number, operation?: OPERATION) {
113
+ const metadata: Metadata = this.constructor[Symbol.metadata];
138
114
  this[$changes].change(
139
- this.constructor[Symbol.metadata][property as string].index,
115
+ metadata[metadata[property as string]].index,
140
116
  operation
141
117
  );
142
118
  }
143
119
 
144
120
  clone (): this {
145
121
  const cloned = new ((this as any).constructor);
146
- const metadata = this.constructor[Symbol.metadata];
122
+ const metadata: Metadata = this.constructor[Symbol.metadata];
147
123
 
148
124
  //
149
125
  // TODO: clone all properties, not only annotated ones
150
126
  //
151
127
  // for (const field in this) {
152
- for (const field in metadata) {
128
+ for (const fieldIndex in metadata) {
129
+ // const field = metadata[metadata[fieldIndex]].name;
130
+ const field = metadata[fieldIndex as any as number].name;
131
+
153
132
  if (
154
133
  typeof (this[field]) === "object" &&
155
134
  typeof (this[field]?.clone) === "function"
@@ -162,15 +141,16 @@ export abstract class Schema {
162
141
  cloned[field] = this[field];
163
142
  }
164
143
  }
144
+
165
145
  return cloned;
166
146
  }
167
147
 
168
148
  toJSON () {
169
- const metadata = this.constructor[Symbol.metadata];
170
-
171
149
  const obj: unknown = {};
172
- for (const fieldName in metadata) {
173
- const field = metadata[fieldName];
150
+ const metadata = this.constructor[Symbol.metadata];
151
+ for (const index in metadata) {
152
+ const field = metadata[index];
153
+ const fieldName = field.name;
174
154
  if (!field.deprecated && this[fieldName] !== null && typeof (this[fieldName]) !== "undefined") {
175
155
  obj[fieldName] = (typeof (this[fieldName]['toJSON']) === "function")
176
156
  ? this[fieldName]['toJSON']()
@@ -185,11 +165,13 @@ export abstract class Schema {
185
165
  }
186
166
 
187
167
  protected [$getByIndex](index: number) {
188
- return this[this.constructor[Symbol.metadata][index]];
168
+ const metadata: Metadata = this.constructor[Symbol.metadata];
169
+ return this[metadata[index].name];
189
170
  }
190
171
 
191
172
  protected [$deleteByIndex](index: number) {
192
- this[this.constructor[Symbol.metadata][index]] = undefined;
173
+ const metadata: Metadata = this.constructor[Symbol.metadata];
174
+ this[metadata[index].name] = undefined;
193
175
  }
194
176
 
195
177
  static debugRefIds(instance: Ref, jsonContents: boolean = true, level: number = 0) {
@@ -199,7 +181,7 @@ export abstract class Schema {
199
181
  const contents = (jsonContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
200
182
 
201
183
  let output = "";
202
- output += `${getIndent(level)}${ref.constructor.name} (${ref[$changes].refId})${contents}\n`;
184
+ output += `${getIndent(level)}${ref.constructor.name} (refId: ${ref[$changes].refId})${contents}\n`;
203
185
 
204
186
  changeTree.forEachChild((childChangeTree) =>
205
187
  output += this.debugRefIds(childChangeTree.ref, jsonContents, level + 1));
@@ -216,31 +198,41 @@ export abstract class Schema {
216
198
  * @returns
217
199
  */
218
200
  static debugChanges(instance: Ref, isEncodeAll: boolean = false) {
219
- const changeTree = instance[$changes];
201
+ const changeTree: ChangeTree = instance[$changes];
220
202
 
221
203
  const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
222
204
  const changeSetName = (isEncodeAll) ? "allChanges" : "changes";
223
205
 
224
206
  let output = `${instance.constructor.name} (${changeTree.refId}) -> .${changeSetName}:\n`;
225
207
 
226
- function dumpChangeSet(changeSet: Map<number, OPERATION>) {
227
- Array.from(changeSet)
228
- .sort((a, b) => a[0] - b[0])
229
- .forEach(([index, operation]) =>
230
- output += `- [${index}]: ${OPERATION[operation]} (${JSON.stringify(changeTree.getValue(index, isEncodeAll))})\n`
231
- );
208
+ function dumpChangeSet(changeSet: ChangeSet) {
209
+ changeSet.operations
210
+ .filter(op => op)
211
+ .forEach((index) => {
212
+ const operation = changeTree.indexedOperations[index];
213
+ console.log({ index, operation })
214
+ output += `- [${index}]: ${OPERATION[operation]} (${JSON.stringify(changeTree.getValue(Number(index), isEncodeAll))})\n`
215
+ });
232
216
  }
233
217
 
234
218
  dumpChangeSet(changeSet);
235
219
 
236
220
  // display filtered changes
237
- if (!isEncodeAll && changeTree.filteredChanges?.size > 0) {
221
+ if (
222
+ !isEncodeAll &&
223
+ changeTree.filteredChanges &&
224
+ (changeTree.filteredChanges.operations).filter(op => op).length > 0
225
+ ) {
238
226
  output += `${instance.constructor.name} (${changeTree.refId}) -> .filteredChanges:\n`;
239
227
  dumpChangeSet(changeTree.filteredChanges);
240
228
  }
241
229
 
242
230
  // display filtered changes
243
- if (isEncodeAll && changeTree.allFilteredChanges?.size > 0) {
231
+ if (
232
+ isEncodeAll &&
233
+ changeTree.allFilteredChanges &&
234
+ (changeTree.allFilteredChanges.operations).filter(op => op).length > 0
235
+ ) {
244
236
  output += `${instance.constructor.name} (${changeTree.refId}) -> .allFilteredChanges:\n`;
245
237
  dumpChangeSet(changeTree.allFilteredChanges);
246
238
  }
@@ -248,16 +240,19 @@ export abstract class Schema {
248
240
  return output;
249
241
  }
250
242
 
251
- static debugChangesDeep(ref: Ref) {
243
+ static debugChangesDeep(ref: Ref, changeSetName: "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes") {
252
244
  let output = "";
253
245
 
254
246
  const rootChangeTree = ref[$changes];
247
+ const root = rootChangeTree.root;
255
248
  const changeTrees: Map<ChangeTree, ChangeTree[]> = new Map();
256
249
 
257
250
  let totalInstances = 0;
258
251
  let totalOperations = 0;
259
252
 
260
- for (const [changeTree, changes] of (rootChangeTree.root.changes.entries())) {
253
+ for (const [refId, changes] of Object.entries(root[changeSetName])) {
254
+ const changeTree = root.changeTrees[refId];
255
+
261
256
  let includeChangeTree = false;
262
257
  let parentChangeTrees: ChangeTree[] = [];
263
258
  let parentChangeTree = changeTree.parent?.[$changes];
@@ -278,7 +273,7 @@ export abstract class Schema {
278
273
 
279
274
  if (includeChangeTree) {
280
275
  totalInstances += 1;
281
- totalOperations += changes.size;
276
+ totalOperations += Object.keys(changes).length;
282
277
  changeTrees.set(changeTree, parentChangeTrees.reverse());
283
278
  }
284
279
  }
@@ -299,17 +294,17 @@ export abstract class Schema {
299
294
  }
300
295
  });
301
296
 
302
- const changes = changeTree.changes;
297
+ const changes = changeTree.indexedOperations;
303
298
  const level = parentChangeTrees.length;
304
299
  const indent = getIndent(level);
305
300
 
306
301
  const parentIndex = (level > 0) ? `(${changeTree.parentIndex}) ` : "";
307
- output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${changes.size}\n`;
302
+ output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${Object.keys(changes).length}\n`;
308
303
 
309
- for (const [index, operation] of changes) {
304
+ for (const index in changes) {
305
+ const operation = changes[index];
310
306
  output += `${getIndent(level + 1)}${OPERATION[operation]}: ${index}\n`;
311
307
  }
312
-
313
308
  }
314
309
 
315
310
  return `${output}`;