@colyseus/schema 3.0.75 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/index.js +780 -429
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +778 -430
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +780 -429
- package/lib/Reflection.d.ts +50 -17
- package/lib/Reflection.js +151 -202
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +13 -1
- package/lib/Schema.js +73 -9
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +6 -1
- package/lib/annotations.js +8 -34
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.js +34 -1
- package/lib/bench_encode.js.map +1 -1
- package/lib/codegen/api.js +35 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/cli.js +4 -1
- package/lib/codegen/cli.js.map +1 -1
- package/lib/codegen/parser.js +35 -2
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +34 -1
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.d.ts +2 -2
- package/lib/decoder/DecodeOperation.js +3 -3
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +3 -3
- package/lib/decoder/Decoder.js +2 -2
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.d.ts +0 -1
- package/lib/decoder/ReferenceTracker.js +9 -7
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/Callbacks.d.ts +154 -0
- package/lib/decoder/strategy/Callbacks.js +340 -0
- package/lib/decoder/strategy/Callbacks.js.map +1 -0
- package/lib/decoder/strategy/{StateCallbacks.d.ts → getDecoderStateCallbacks.d.ts} +6 -0
- package/lib/decoder/strategy/{StateCallbacks.js → getDecoderStateCallbacks.js} +17 -10
- package/lib/decoder/strategy/getDecoderStateCallbacks.js.map +1 -0
- package/lib/encoder/ChangeTree.d.ts +2 -2
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +2 -2
- package/lib/encoder/EncodeOperation.js +3 -3
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +6 -6
- package/lib/encoder/Encoder.js +19 -18
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.js +17 -14
- package/lib/encoder/Root.js.map +1 -1
- package/lib/encoder/StateView.js +13 -12
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/decode.d.ts +2 -2
- package/lib/encoding/encode.d.ts +3 -1
- package/lib/encoding/encode.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.js +7 -3
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +7 -14
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/custom/ArraySchema.d.ts +2 -1
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -1
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -2
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -1
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/symbols.d.ts +1 -0
- package/lib/types/symbols.js +2 -1
- package/lib/types/symbols.js.map +1 -1
- package/lib/utils.js +1 -1
- package/lib/utils.js.map +1 -1
- package/package.json +12 -16
- package/src/Reflection.ts +185 -174
- package/src/Schema.ts +81 -13
- package/src/annotations.ts +14 -40
- package/src/codegen/parser.ts +1 -1
- package/src/decoder/DecodeOperation.ts +9 -9
- package/src/decoder/Decoder.ts +6 -6
- package/src/decoder/ReferenceTracker.ts +10 -8
- package/src/decoder/strategy/Callbacks.ts +547 -0
- package/src/decoder/strategy/{StateCallbacks.ts → getDecoderStateCallbacks.ts} +17 -11
- package/src/encoder/ChangeTree.ts +4 -7
- package/src/encoder/EncodeOperation.ts +9 -9
- package/src/encoder/Encoder.ts +26 -18
- package/src/encoder/Root.ts +20 -15
- package/src/encoder/StateView.ts +15 -13
- package/src/encoding/encode.ts +1 -1
- package/src/index.ts +3 -2
- package/src/types/HelperTypes.ts +13 -11
- package/src/types/custom/ArraySchema.ts +2 -1
- package/src/types/custom/CollectionSchema.ts +4 -2
- package/src/types/custom/MapSchema.ts +4 -2
- package/src/types/custom/SetSchema.ts +3 -1
- package/src/types/symbols.ts +1 -0
- package/src/utils.ts +2 -2
- package/lib/Decoder.d.ts +0 -16
- package/lib/Decoder.js +0 -182
- package/lib/Decoder.js.map +0 -1
- package/lib/Encoder.d.ts +0 -13
- package/lib/Encoder.js +0 -79
- package/lib/Encoder.js.map +0 -1
- package/lib/changes/ChangeSet.d.ts +0 -12
- package/lib/changes/ChangeSet.js +0 -35
- package/lib/changes/ChangeSet.js.map +0 -1
- package/lib/changes/ChangeTree.d.ts +0 -53
- package/lib/changes/ChangeTree.js +0 -202
- package/lib/changes/ChangeTree.js.map +0 -1
- package/lib/changes/DecodeOperation.d.ts +0 -15
- package/lib/changes/DecodeOperation.js +0 -186
- package/lib/changes/DecodeOperation.js.map +0 -1
- package/lib/changes/EncodeOperation.d.ts +0 -18
- package/lib/changes/EncodeOperation.js +0 -130
- package/lib/changes/EncodeOperation.js.map +0 -1
- package/lib/changes/ReferenceTracker.d.ts +0 -14
- package/lib/changes/ReferenceTracker.js +0 -83
- package/lib/changes/ReferenceTracker.js.map +0 -1
- package/lib/changes/consts.d.ts +0 -14
- package/lib/changes/consts.js +0 -18
- package/lib/changes/consts.js.map +0 -1
- package/lib/decoder/strategy/StateCallbacks.js.map +0 -1
- package/lib/decoding/decode.d.ts +0 -48
- package/lib/decoding/decode.js +0 -267
- package/lib/decoding/decode.js.map +0 -1
- package/lib/ecs.d.ts +0 -11
- package/lib/ecs.js +0 -160
- package/lib/ecs.js.map +0 -1
- package/lib/filters/index.d.ts +0 -8
- package/lib/filters/index.js +0 -24
- package/lib/filters/index.js.map +0 -1
- package/lib/spec.d.ts +0 -13
- package/lib/spec.js +0 -42
- package/lib/spec.js.map +0 -1
- package/lib/types/ArraySchema.d.ts +0 -238
- package/lib/types/ArraySchema.js +0 -555
- package/lib/types/ArraySchema.js.map +0 -1
- package/lib/types/CollectionSchema.d.ts +0 -35
- package/lib/types/CollectionSchema.js +0 -150
- package/lib/types/CollectionSchema.js.map +0 -1
- package/lib/types/MapSchema.d.ts +0 -38
- package/lib/types/MapSchema.js +0 -215
- package/lib/types/MapSchema.js.map +0 -1
- package/lib/types/SetSchema.d.ts +0 -32
- package/lib/types/SetSchema.js +0 -162
- package/lib/types/SetSchema.js.map +0 -1
- package/lib/types/typeRegistry.d.ts +0 -5
- package/lib/types/typeRegistry.js +0 -13
- package/lib/types/typeRegistry.js.map +0 -1
- package/lib/usage.d.ts +0 -1
- package/lib/usage.js +0 -22
- package/lib/usage.js.map +0 -1
- package/lib/v3.d.ts +0 -1
- package/lib/v3.js +0 -427
- package/lib/v3.js.map +0 -1
- package/lib/v3_experiment.d.ts +0 -1
- package/lib/v3_experiment.js +0 -407
- package/lib/v3_experiment.js.map +0 -1
package/src/Reflection.ts
CHANGED
|
@@ -1,31 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PrimitiveType, schema, SchemaType } from "./annotations";
|
|
2
2
|
import { TypeContext } from "./types/TypeContext";
|
|
3
3
|
import { Metadata } from "./Metadata";
|
|
4
|
-
import { ArraySchema } from "./types/custom/ArraySchema";
|
|
5
4
|
import { Iterator } from "./encoding/decode";
|
|
6
5
|
import { Encoder } from "./encoder/Encoder";
|
|
7
6
|
import { Decoder } from "./decoder/Decoder";
|
|
8
7
|
import { Schema } from "./Schema";
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
|
-
* Reflection
|
|
10
|
+
* Static methods available on Reflection
|
|
12
11
|
*/
|
|
13
|
-
|
|
14
|
-
@type("string") name: string;
|
|
15
|
-
@type("string") type: string;
|
|
16
|
-
@type("number") referencedType: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class ReflectionType extends Schema {
|
|
20
|
-
@type("number") id: number;
|
|
21
|
-
@type("number") extendsId: number;
|
|
22
|
-
@type([ ReflectionField ]) fields = new ArraySchema<ReflectionField>();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class Reflection extends Schema {
|
|
26
|
-
@type([ReflectionType]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();
|
|
27
|
-
@type("number") rootType: number;
|
|
28
|
-
|
|
12
|
+
interface ReflectionStatic {
|
|
29
13
|
/**
|
|
30
14
|
* Encodes the TypeContext of an Encoder into a buffer.
|
|
31
15
|
*
|
|
@@ -33,207 +17,234 @@ export class Reflection extends Schema {
|
|
|
33
17
|
* @param it
|
|
34
18
|
* @returns
|
|
35
19
|
*/
|
|
36
|
-
|
|
37
|
-
const context = encoder.context;
|
|
20
|
+
encode: (encoder: Encoder, it?: Iterator) => Uint8Array;
|
|
38
21
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Decodes the TypeContext from a buffer into a Decoder instance.
|
|
24
|
+
*
|
|
25
|
+
* @param bytes Reflection.encode() output
|
|
26
|
+
* @param it
|
|
27
|
+
* @returns Decoder instance
|
|
28
|
+
*/
|
|
29
|
+
decode: <T extends Schema = Schema>(bytes: Uint8Array, it?: Iterator) => Decoder<T>;
|
|
30
|
+
}
|
|
46
31
|
|
|
47
|
-
|
|
48
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Reflection
|
|
34
|
+
*/
|
|
35
|
+
export const ReflectionField = schema({
|
|
36
|
+
name: "string",
|
|
37
|
+
type: "string",
|
|
38
|
+
referencedType: "number",
|
|
39
|
+
})
|
|
40
|
+
export type ReflectionField = SchemaType<typeof ReflectionField>;
|
|
41
|
+
|
|
42
|
+
export const ReflectionType = schema({
|
|
43
|
+
id: "number",
|
|
44
|
+
extendsId: "number",
|
|
45
|
+
fields: [ ReflectionField ],
|
|
46
|
+
})
|
|
47
|
+
export type ReflectionType = SchemaType<typeof ReflectionType>;
|
|
48
|
+
|
|
49
|
+
export const Reflection = schema({
|
|
50
|
+
types: [ ReflectionType ],
|
|
51
|
+
rootType: "number",
|
|
52
|
+
}) as ReturnType<typeof schema<{
|
|
53
|
+
types: [typeof ReflectionType];
|
|
54
|
+
rootType: "number";
|
|
55
|
+
}>> & ReflectionStatic;
|
|
56
|
+
|
|
57
|
+
export type Reflection = SchemaType<typeof Reflection>;
|
|
58
|
+
|
|
59
|
+
Reflection.encode = function (encoder: Encoder, it: Iterator = { offset: 0 }) {
|
|
60
|
+
const context = encoder.context;
|
|
61
|
+
|
|
62
|
+
const reflection = new Reflection();
|
|
63
|
+
const reflectionEncoder = new Encoder(reflection);
|
|
64
|
+
|
|
65
|
+
// rootType is usually the first schema passed to the Encoder
|
|
66
|
+
// (unless it inherits from another schema)
|
|
67
|
+
const rootType = context.schemas.get(encoder.state.constructor);
|
|
68
|
+
if (rootType > 0) { reflection.rootType = rootType; }
|
|
69
|
+
|
|
70
|
+
const includedTypeIds = new Set<number>();
|
|
71
|
+
const pendingReflectionTypes: { [typeid: number]: ReflectionType[] } = {};
|
|
72
|
+
|
|
73
|
+
// add type to reflection in a way that respects inheritance
|
|
74
|
+
// (parent types should be added before their children)
|
|
75
|
+
const addType = (type: ReflectionType) => {
|
|
76
|
+
if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {
|
|
77
|
+
includedTypeIds.add(type.id);
|
|
78
|
+
|
|
79
|
+
reflection.types.push(type);
|
|
80
|
+
|
|
81
|
+
const deps = pendingReflectionTypes[type.id];
|
|
82
|
+
if (deps !== undefined) {
|
|
83
|
+
delete pendingReflectionTypes[type.id];
|
|
84
|
+
deps.forEach((childType) => addType(childType));
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
if (pendingReflectionTypes[type.extendsId] === undefined) {
|
|
88
|
+
pendingReflectionTypes[type.extendsId] = [];
|
|
89
|
+
}
|
|
90
|
+
pendingReflectionTypes[type.extendsId].push(type);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
49
93
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {
|
|
54
|
-
includedTypeIds.add(type.id);
|
|
94
|
+
context.schemas.forEach((typeid, klass) => {
|
|
95
|
+
const type = new ReflectionType();
|
|
96
|
+
type.id = Number(typeid);
|
|
55
97
|
|
|
56
|
-
|
|
98
|
+
// support inheritance
|
|
99
|
+
const inheritFrom = Object.getPrototypeOf(klass);
|
|
100
|
+
if (inheritFrom !== Schema) {
|
|
101
|
+
type.extendsId = context.schemas.get(inheritFrom);
|
|
102
|
+
}
|
|
57
103
|
|
|
58
|
-
|
|
59
|
-
if (deps !== undefined) {
|
|
60
|
-
delete pendingReflectionTypes[type.id];
|
|
61
|
-
deps.forEach((childType) => addType(childType));
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
if (pendingReflectionTypes[type.extendsId] === undefined) {
|
|
65
|
-
pendingReflectionTypes[type.extendsId] = [];
|
|
66
|
-
}
|
|
67
|
-
pendingReflectionTypes[type.extendsId].push(type);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
104
|
+
const metadata = klass[Symbol.metadata];
|
|
70
105
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
106
|
+
//
|
|
107
|
+
// FIXME: this is a workaround for inherited types without additional fields
|
|
108
|
+
// if metadata is the same reference as the parent class - it means the class has no own metadata
|
|
109
|
+
//
|
|
110
|
+
if (metadata !== inheritFrom[Symbol.metadata]) {
|
|
111
|
+
for (const fieldIndex in metadata) {
|
|
112
|
+
const index = Number(fieldIndex);
|
|
113
|
+
const fieldName = metadata[index].name;
|
|
74
114
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
115
|
+
// skip fields from parent classes
|
|
116
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
80
119
|
|
|
81
|
-
|
|
120
|
+
const reflectionField = new ReflectionField();
|
|
121
|
+
reflectionField.name = fieldName;
|
|
82
122
|
|
|
83
|
-
|
|
84
|
-
// FIXME: this is a workaround for inherited types without additional fields
|
|
85
|
-
// if metadata is the same reference as the parent class - it means the class has no own metadata
|
|
86
|
-
//
|
|
87
|
-
if (metadata !== inheritFrom[Symbol.metadata]) {
|
|
88
|
-
for (const fieldIndex in metadata) {
|
|
89
|
-
const index = Number(fieldIndex);
|
|
90
|
-
const fieldName = metadata[index].name;
|
|
123
|
+
let fieldType: string;
|
|
91
124
|
|
|
92
|
-
|
|
93
|
-
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
125
|
+
const field = metadata[index];
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
if (typeof (field.type) === "string") {
|
|
128
|
+
fieldType = field.type;
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const field = metadata[index];
|
|
130
|
+
} else {
|
|
131
|
+
let childTypeSchema: typeof Schema;
|
|
103
132
|
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
//
|
|
134
|
+
// TODO: refactor below.
|
|
135
|
+
//
|
|
136
|
+
if (Schema.is(field.type)) {
|
|
137
|
+
fieldType = "ref";
|
|
138
|
+
childTypeSchema = field.type as typeof Schema;
|
|
106
139
|
|
|
107
140
|
} else {
|
|
108
|
-
|
|
141
|
+
fieldType = Object.keys(field.type)[0];
|
|
109
142
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
if (Schema.is(field.type)) {
|
|
114
|
-
fieldType = "ref";
|
|
115
|
-
childTypeSchema = field.type as typeof Schema;
|
|
143
|
+
if (typeof (field.type[fieldType as keyof typeof field.type]) === "string") {
|
|
144
|
+
fieldType += ":" + field.type[fieldType as keyof typeof field.type]; // array:string
|
|
116
145
|
|
|
117
146
|
} else {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (typeof (field.type[fieldType as keyof typeof field.type]) === "string") {
|
|
121
|
-
fieldType += ":" + field.type[fieldType as keyof typeof field.type]; // array:string
|
|
122
|
-
|
|
123
|
-
} else {
|
|
124
|
-
childTypeSchema = field.type[fieldType as keyof typeof field.type];
|
|
125
|
-
}
|
|
147
|
+
childTypeSchema = field.type[fieldType as keyof typeof field.type];
|
|
126
148
|
}
|
|
127
|
-
|
|
128
|
-
reflectionField.referencedType = (childTypeSchema)
|
|
129
|
-
? context.getTypeId(childTypeSchema)
|
|
130
|
-
: -1;
|
|
131
149
|
}
|
|
132
150
|
|
|
133
|
-
reflectionField.
|
|
134
|
-
|
|
151
|
+
reflectionField.referencedType = (childTypeSchema)
|
|
152
|
+
? context.getTypeId(childTypeSchema)
|
|
153
|
+
: -1;
|
|
135
154
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
addType(type);
|
|
139
|
-
});
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
reflection.types.push(type))
|
|
156
|
+
reflectionField.type = fieldType;
|
|
157
|
+
type.fields.push(reflectionField);
|
|
158
|
+
}
|
|
145
159
|
}
|
|
146
160
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// return Buffer.from(buf, 0, it.offset);
|
|
150
|
-
}
|
|
161
|
+
addType(type);
|
|
162
|
+
});
|
|
151
163
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
* @returns Decoder instance
|
|
158
|
-
*/
|
|
159
|
-
static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): Decoder<T> {
|
|
160
|
-
const reflection = new Reflection();
|
|
164
|
+
// in case there are types that were not added due to inheritance
|
|
165
|
+
for (const typeid in pendingReflectionTypes) {
|
|
166
|
+
pendingReflectionTypes[typeid].forEach((type) =>
|
|
167
|
+
reflection.types.push(type))
|
|
168
|
+
}
|
|
161
169
|
|
|
162
|
-
|
|
163
|
-
|
|
170
|
+
const buf = reflectionEncoder.encodeAll(it);
|
|
171
|
+
return buf.slice(0, it.offset);
|
|
172
|
+
};
|
|
164
173
|
|
|
165
|
-
|
|
174
|
+
Reflection.decode = function <T extends Schema = Schema>(bytes: Uint8Array, it?: Iterator): Decoder<T> {
|
|
175
|
+
const reflection = new Reflection();
|
|
166
176
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;
|
|
170
|
-
const schema: typeof Schema = class _ extends parentClass {};
|
|
177
|
+
const reflectionDecoder = new Decoder(reflection);
|
|
178
|
+
reflectionDecoder.decode(bytes, it);
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
TypeContext.register(schema);
|
|
180
|
+
const typeContext = new TypeContext();
|
|
174
181
|
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
// 1st pass, initialize metadata + inheritance
|
|
183
|
+
reflection.types.forEach((reflectionType) => {
|
|
184
|
+
const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;
|
|
185
|
+
const schema: typeof Schema = class _ extends parentClass { };
|
|
177
186
|
|
|
178
|
-
|
|
179
|
-
|
|
187
|
+
// register for inheritance support
|
|
188
|
+
TypeContext.register(schema);
|
|
180
189
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
reflectionType.fields.forEach((field, i) => {
|
|
184
|
-
const fieldIndex = parentFieldIndex + i;
|
|
190
|
+
typeContext.add(schema, reflectionType.id);
|
|
191
|
+
}, {});
|
|
185
192
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
193
|
+
// define fields
|
|
194
|
+
const addFields = (metadata: Metadata, reflectionType: ReflectionType, parentFieldIndex: number) => {
|
|
195
|
+
reflectionType.fields.forEach((field, i) => {
|
|
196
|
+
const fieldIndex = parentFieldIndex + i;
|
|
189
197
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
fieldType = typeInfo[0];
|
|
194
|
-
refType = typeInfo[1] as PrimitiveType; // string
|
|
195
|
-
}
|
|
198
|
+
if (field.referencedType !== undefined) {
|
|
199
|
+
let fieldType = field.type;
|
|
200
|
+
let refType: PrimitiveType = typeContext.get(field.referencedType);
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
// map or array of primitive type (-1)
|
|
203
|
+
if (!refType) {
|
|
204
|
+
const typeInfo = field.type.split(":");
|
|
205
|
+
fieldType = typeInfo[0];
|
|
206
|
+
refType = typeInfo[1] as PrimitiveType; // string
|
|
207
|
+
}
|
|
199
208
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
209
|
+
if (fieldType === "ref") {
|
|
210
|
+
Metadata.addField(metadata, fieldIndex, field.name, refType);
|
|
203
211
|
|
|
204
212
|
} else {
|
|
205
|
-
Metadata.addField(metadata, fieldIndex, field.name,
|
|
213
|
+
Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });
|
|
206
214
|
}
|
|
207
|
-
});
|
|
208
|
-
};
|
|
209
215
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
} else {
|
|
217
|
+
Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
};
|
|
213
221
|
|
|
214
|
-
|
|
215
|
-
|
|
222
|
+
// 2nd pass, set fields
|
|
223
|
+
reflection.types.forEach((reflectionType) => {
|
|
224
|
+
const schema = typeContext.get(reflectionType.id);
|
|
216
225
|
|
|
217
|
-
|
|
226
|
+
// for inheritance support
|
|
227
|
+
const metadata = Metadata.initialize(schema);
|
|
218
228
|
|
|
219
|
-
|
|
220
|
-
do {
|
|
221
|
-
inheritedTypes.push(parentType);
|
|
222
|
-
parentType = reflection.types.find((t) => t.id === parentType.extendsId);
|
|
223
|
-
} while (parentType);
|
|
229
|
+
const inheritedTypes: ReflectionType[] = [];
|
|
224
230
|
|
|
225
|
-
|
|
231
|
+
let parentType: ReflectionType = reflectionType;
|
|
232
|
+
do {
|
|
233
|
+
inheritedTypes.push(parentType);
|
|
234
|
+
parentType = reflection.types.find((t) => t.id === parentType.extendsId);
|
|
235
|
+
} while (parentType);
|
|
226
236
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
237
|
+
let parentFieldIndex = 0;
|
|
238
|
+
|
|
239
|
+
inheritedTypes.reverse().forEach((reflectionType) => {
|
|
240
|
+
// add fields from all inherited classes
|
|
241
|
+
// TODO: refactor this to avoid adding fields from parent classes
|
|
242
|
+
addFields(metadata, reflectionType, parentFieldIndex);
|
|
243
|
+
parentFieldIndex += reflectionType.fields.length;
|
|
233
244
|
});
|
|
245
|
+
});
|
|
234
246
|
|
|
235
|
-
|
|
247
|
+
const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();
|
|
236
248
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
249
|
+
return new Decoder<T>(state, typeContext);
|
|
250
|
+
}
|
package/src/Schema.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { DEFAULT_VIEW_TAG, type DefinitionType } from "./annotations";
|
|
|
4
4
|
import { AssignableProps, NonFunctionPropNames, ToJSON } from './types/HelperTypes';
|
|
5
5
|
|
|
6
6
|
import { ChangeSet, ChangeSetName, ChangeTree, IRef, Ref } from './encoder/ChangeTree';
|
|
7
|
-
import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $track } from './types/symbols';
|
|
7
|
+
import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $refId, $track } from './types/symbols';
|
|
8
8
|
import { StateView } from './encoder/StateView';
|
|
9
9
|
|
|
10
10
|
import { encodeSchemaOperation } from './encoder/EncodeOperation';
|
|
@@ -22,6 +22,8 @@ export class Schema<C = any> implements IRef {
|
|
|
22
22
|
static [$encoder] = encodeSchemaOperation;
|
|
23
23
|
static [$decoder] = decodeSchemaOperation;
|
|
24
24
|
|
|
25
|
+
[$refId]?: number;
|
|
26
|
+
|
|
25
27
|
/**
|
|
26
28
|
* Assign the property descriptors required to track changes on this instance.
|
|
27
29
|
* @param instance
|
|
@@ -95,13 +97,79 @@ export class Schema<C = any> implements IRef {
|
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Assign properties to the instance.
|
|
102
|
+
* @param props Properties to assign to the instance
|
|
103
|
+
* @returns
|
|
104
|
+
*/
|
|
105
|
+
public assign<T extends Partial<this>>(props: AssignableProps<T>,): this {
|
|
101
106
|
Object.assign(this, props);
|
|
102
107
|
return this;
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Restore the instance from JSON data.
|
|
112
|
+
* @param jsonData JSON data to restore the instance from
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
public restore(jsonData: ToJSON<this>): this {
|
|
116
|
+
const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
|
|
117
|
+
|
|
118
|
+
for (const fieldIndex in metadata) {
|
|
119
|
+
const field = metadata[fieldIndex as any as number];
|
|
120
|
+
const fieldName = field.name as keyof this;
|
|
121
|
+
const fieldType = field.type;
|
|
122
|
+
const value = (jsonData as any)[fieldName];
|
|
123
|
+
|
|
124
|
+
if (value === undefined || value === null) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof fieldType === "string") {
|
|
129
|
+
// Primitive type: assign directly
|
|
130
|
+
this[fieldName] = value;
|
|
131
|
+
|
|
132
|
+
} else if (Schema.is(fieldType)) {
|
|
133
|
+
// Schema type: create instance and restore
|
|
134
|
+
const instance = new (fieldType as typeof Schema)();
|
|
135
|
+
instance.restore(value);
|
|
136
|
+
this[fieldName] = instance as any;
|
|
137
|
+
|
|
138
|
+
} else if (typeof fieldType === "object") {
|
|
139
|
+
// Collection types: { map: ... }, { array: ... }, etc.
|
|
140
|
+
const collectionType = Object.keys(fieldType)[0] as string;
|
|
141
|
+
const childType = (fieldType as any)[collectionType];
|
|
142
|
+
|
|
143
|
+
if (collectionType === "map") {
|
|
144
|
+
const mapSchema = this[fieldName] as any;
|
|
145
|
+
for (const key in value) {
|
|
146
|
+
if (Schema.is(childType)) {
|
|
147
|
+
const childInstance = new (childType as typeof Schema)();
|
|
148
|
+
childInstance.restore(value[key]);
|
|
149
|
+
mapSchema.set(key, childInstance);
|
|
150
|
+
} else {
|
|
151
|
+
mapSchema.set(key, value[key]);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
} else if (collectionType === "array") {
|
|
156
|
+
const arraySchema = this[fieldName] as any;
|
|
157
|
+
for (let i = 0; i < value.length; i++) {
|
|
158
|
+
if (Schema.is(childType)) {
|
|
159
|
+
const childInstance = new (childType as typeof Schema)();
|
|
160
|
+
childInstance.restore(value[i]);
|
|
161
|
+
arraySchema.push(childInstance);
|
|
162
|
+
} else {
|
|
163
|
+
arraySchema.push(value[i]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
105
173
|
/**
|
|
106
174
|
* (Server-side): Flag a property to be encoded for the next patch.
|
|
107
175
|
* @param instance Schema instance
|
|
@@ -190,7 +258,7 @@ export class Schema<C = any> implements IRef {
|
|
|
190
258
|
const contents = (showContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
|
|
191
259
|
const changeTree: ChangeTree = ref[$changes];
|
|
192
260
|
|
|
193
|
-
const refId = (
|
|
261
|
+
const refId = (ref as IRef)[$refId];
|
|
194
262
|
const root = (decoder) ? decoder.root : changeTree.root;
|
|
195
263
|
|
|
196
264
|
// log reference count if > 1
|
|
@@ -218,7 +286,7 @@ export class Schema<C = any> implements IRef {
|
|
|
218
286
|
let current = ref[$changes].root[changeSet].next;
|
|
219
287
|
while (current) {
|
|
220
288
|
if (current.changeTree) {
|
|
221
|
-
encodeOrder.push(current.changeTree.refId);
|
|
289
|
+
encodeOrder.push(current.changeTree.ref[$refId]);
|
|
222
290
|
}
|
|
223
291
|
current = current.next;
|
|
224
292
|
}
|
|
@@ -243,7 +311,7 @@ export class Schema<C = any> implements IRef {
|
|
|
243
311
|
const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
|
|
244
312
|
const changeSetName = (isEncodeAll) ? "allChanges" : "changes";
|
|
245
313
|
|
|
246
|
-
let output = `${instance.constructor.name} (${
|
|
314
|
+
let output = `${instance.constructor.name} (${instance[$refId]}) -> .${changeSetName}:\n`;
|
|
247
315
|
|
|
248
316
|
function dumpChangeSet(changeSet: ChangeSet) {
|
|
249
317
|
changeSet.operations
|
|
@@ -262,7 +330,7 @@ export class Schema<C = any> implements IRef {
|
|
|
262
330
|
changeTree.filteredChanges &&
|
|
263
331
|
(changeTree.filteredChanges.operations).filter(op => op).length > 0
|
|
264
332
|
) {
|
|
265
|
-
output += `${instance.constructor.name} (${
|
|
333
|
+
output += `${instance.constructor.name} (${instance[$refId]}) -> .filteredChanges:\n`;
|
|
266
334
|
dumpChangeSet(changeTree.filteredChanges);
|
|
267
335
|
}
|
|
268
336
|
|
|
@@ -272,7 +340,7 @@ export class Schema<C = any> implements IRef {
|
|
|
272
340
|
changeTree.allFilteredChanges &&
|
|
273
341
|
(changeTree.allFilteredChanges.operations).filter(op => op).length > 0
|
|
274
342
|
) {
|
|
275
|
-
output += `${instance.constructor.name} (${
|
|
343
|
+
output += `${instance.constructor.name} (${instance[$refId]}) -> .allFilteredChanges:\n`;
|
|
276
344
|
dumpChangeSet(changeTree.allFilteredChanges);
|
|
277
345
|
}
|
|
278
346
|
|
|
@@ -313,14 +381,14 @@ export class Schema<C = any> implements IRef {
|
|
|
313
381
|
}
|
|
314
382
|
|
|
315
383
|
if (includeChangeTree) {
|
|
316
|
-
instanceRefIds.push(changeTree.refId);
|
|
384
|
+
instanceRefIds.push(changeTree.ref[$refId]);
|
|
317
385
|
totalOperations += Object.keys(changes).length;
|
|
318
386
|
changeTrees.set(changeTree, parentChangeTrees.reverse());
|
|
319
387
|
}
|
|
320
388
|
}
|
|
321
389
|
|
|
322
390
|
output += "---\n"
|
|
323
|
-
output += `root refId: ${rootChangeTree.refId}\n`;
|
|
391
|
+
output += `root refId: ${rootChangeTree.ref[$refId]}\n`;
|
|
324
392
|
output += `Total instances: ${instanceRefIds.length} (refIds: ${instanceRefIds.join(", ")})\n`;
|
|
325
393
|
output += `Total changes: ${totalOperations}\n`;
|
|
326
394
|
output += "---\n"
|
|
@@ -330,7 +398,7 @@ export class Schema<C = any> implements IRef {
|
|
|
330
398
|
for (const [changeTree, parentChangeTrees] of changeTrees.entries()) {
|
|
331
399
|
parentChangeTrees.forEach((parentChangeTree, level) => {
|
|
332
400
|
if (!visitedParents.has(parentChangeTree)) {
|
|
333
|
-
output += `${getIndent(level)}${parentChangeTree.ref.constructor.name} (refId: ${parentChangeTree.refId})\n`;
|
|
401
|
+
output += `${getIndent(level)}${parentChangeTree.ref.constructor.name} (refId: ${parentChangeTree.ref[$refId]})\n`;
|
|
334
402
|
visitedParents.add(parentChangeTree);
|
|
335
403
|
}
|
|
336
404
|
});
|
|
@@ -340,7 +408,7 @@ export class Schema<C = any> implements IRef {
|
|
|
340
408
|
const indent = getIndent(level);
|
|
341
409
|
|
|
342
410
|
const parentIndex = (level > 0) ? `(${changeTree.parentIndex}) ` : "";
|
|
343
|
-
output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${Object.keys(changes).length}\n`;
|
|
411
|
+
output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.ref[$refId]}) - changes: ${Object.keys(changes).length}\n`;
|
|
344
412
|
|
|
345
413
|
for (const index in changes) {
|
|
346
414
|
const operation = changes[index];
|