@colyseus/schema 3.0.0-alpha.3 → 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.
- package/README.md +131 -61
- package/build/cjs/index.js +966 -563
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +965 -562
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +966 -563
- package/lib/Metadata.d.ts +15 -4
- package/lib/Metadata.js +86 -18
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +2 -3
- package/lib/Reflection.js +24 -28
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +2 -2
- package/lib/Schema.js +28 -41
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +1 -21
- package/lib/annotations.js +73 -153
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.d.ts +1 -0
- package/lib/bench_encode.js +142 -0
- package/lib/bench_encode.js.map +1 -0
- package/lib/codegen/api.js +1 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/languages/cpp.js +1 -2
- package/lib/codegen/languages/cpp.js.map +1 -1
- package/lib/codegen/languages/csharp.js +1 -2
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +1 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +1 -2
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +2 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +3 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/debug.d.ts +1 -0
- package/lib/debug.js +52 -0
- package/lib/debug.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +0 -1
- package/lib/decoder/DecodeOperation.js +23 -11
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +6 -7
- package/lib/decoder/Decoder.js +8 -8
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +3 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +75 -65
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +9 -19
- package/lib/encoder/ChangeTree.js +129 -145
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +1 -5
- package/lib/encoder/EncodeOperation.js +74 -58
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +10 -8
- package/lib/encoder/Encoder.js +89 -56
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +17 -0
- package/lib/encoder/Root.js +44 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +2 -2
- package/lib/encoder/StateView.js +49 -59
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +2 -1
- package/lib/encoding/assert.js +5 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.js +21 -22
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +2 -2
- package/lib/encoding/encode.js +40 -39
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +2 -1
- package/lib/encoding/spec.js +1 -0
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.js +18 -13
- package/lib/index.js.map +1 -1
- package/lib/types/TypeContext.d.ts +23 -0
- package/lib/types/TypeContext.js +102 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +6 -9
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.js +5 -0
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.js +3 -4
- package/lib/types/registry.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/types/utils.js +1 -2
- package/lib/types/utils.js.map +1 -1
- package/lib/utils.js +3 -4
- package/lib/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/Metadata.ts +104 -26
- package/src/Reflection.ts +26 -28
- package/src/Schema.ts +35 -47
- package/src/annotations.ts +82 -176
- package/src/bench_encode.ts +121 -0
- package/src/debug.ts +56 -0
- package/src/decoder/DecodeOperation.ts +28 -11
- package/src/decoder/Decoder.ts +13 -11
- package/src/decoder/ReferenceTracker.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +152 -81
- package/src/encoder/ChangeTree.ts +147 -166
- package/src/encoder/EncodeOperation.ts +93 -70
- package/src/encoder/Encoder.ts +111 -65
- package/src/encoder/Root.ts +51 -0
- package/src/encoder/StateView.ts +53 -69
- package/src/encoding/assert.ts +4 -3
- package/src/encoding/decode.ts +1 -2
- package/src/encoding/encode.ts +25 -22
- package/src/encoding/spec.ts +1 -0
- package/src/index.ts +8 -14
- package/src/types/TypeContext.ts +122 -0
- package/src/types/custom/ArraySchema.ts +10 -2
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +6 -0
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/symbols.ts +2 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/schema",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.31",
|
|
4
4
|
"description": "Binary state serializer with delta encoding for games",
|
|
5
5
|
"bin": {
|
|
6
6
|
"schema-codegen": "./bin/schema-codegen"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"build": "tsc && rollup -c rollup.config.
|
|
9
|
+
"build": "tsc && rollup -c rollup.config.mjs",
|
|
10
10
|
"watch": "tsc -w",
|
|
11
11
|
"test": "mocha --require ts-node/register test/*.test.ts test/**/*.test.ts",
|
|
12
12
|
"coverage": "nyc mocha --require ts-node/register --require source-map-support/register --recursive test/**Test.ts",
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"nanoid": "^3.1.10",
|
|
74
74
|
"nyc": "^14.1.1",
|
|
75
75
|
"rimraf": "^3.0.0",
|
|
76
|
-
"rollup": "^
|
|
76
|
+
"rollup": "^4.18.0",
|
|
77
77
|
"sinon": "^7.2.2",
|
|
78
78
|
"source-map-support": "^0.5.13",
|
|
79
79
|
"ts-node": "^10.9.2",
|
|
80
80
|
"tslib": "^2.1.0",
|
|
81
|
-
"tsx": "^
|
|
82
|
-
"typescript": "^5.
|
|
81
|
+
"tsx": "^3.13.0",
|
|
82
|
+
"typescript": "^5.4.5"
|
|
83
83
|
},
|
|
84
84
|
"nyc": {
|
|
85
85
|
"extension": [
|
package/src/Metadata.ts
CHANGED
|
@@ -1,40 +1,65 @@
|
|
|
1
1
|
import { getPropertyDescriptor, type DefinitionType } from "./annotations";
|
|
2
2
|
import { getType } from "./types/registry";
|
|
3
|
+
import { $descriptors } from "./types/symbols";
|
|
3
4
|
|
|
4
5
|
export type MetadataField = {
|
|
5
6
|
type: DefinitionType,
|
|
7
|
+
name: string,
|
|
6
8
|
index: number,
|
|
7
9
|
tag?: number,
|
|
8
10
|
unreliable?: boolean,
|
|
9
11
|
deprecated?: boolean,
|
|
10
|
-
descriptor?: PropertyDescriptor,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export type Metadata =
|
|
14
15
|
{ [-1]: number; } & // number of fields
|
|
15
16
|
{ [-2]: number[]; } & // all field indexes with "view" tag
|
|
16
17
|
{ [-3]: {[tag: number]: number[]}; } & // field indexes by "view" tag
|
|
17
|
-
{ [
|
|
18
|
-
{ [field:
|
|
18
|
+
{ [-4]: number[]; } & // all field indexes containing Ref types (Schema, ArraySchema, MapSchema, etc)
|
|
19
|
+
{ [field: number]: MetadataField; } & // index => field name
|
|
20
|
+
{ [field: string]: number; } & // field name => field metadata
|
|
21
|
+
{ [$descriptors]: { [field: string]: PropertyDescriptor } } // property descriptors
|
|
19
22
|
|
|
20
23
|
export const Metadata = {
|
|
21
24
|
|
|
22
|
-
addField(metadata: any, index: number,
|
|
25
|
+
addField(metadata: any, index: number, name: string, type: DefinitionType, descriptor?: PropertyDescriptor) {
|
|
23
26
|
if (index > 64) {
|
|
24
|
-
throw new Error(`Can't define field '${
|
|
27
|
+
throw new Error(`Can't define field '${name}'.\nSchema instances may only have up to 64 fields.`);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
metadata[
|
|
28
|
-
metadata[
|
|
30
|
+
metadata[index] = Object.assign(
|
|
31
|
+
metadata[index] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
|
|
29
32
|
{
|
|
30
33
|
type: (Array.isArray(type))
|
|
31
34
|
? { array: type[0] }
|
|
32
35
|
: type,
|
|
33
36
|
index,
|
|
34
|
-
|
|
37
|
+
name,
|
|
35
38
|
}
|
|
36
39
|
);
|
|
37
40
|
|
|
41
|
+
// create "descriptors" map
|
|
42
|
+
metadata[$descriptors] ??= {};
|
|
43
|
+
|
|
44
|
+
if (descriptor) {
|
|
45
|
+
// for encoder
|
|
46
|
+
metadata[$descriptors][name] = descriptor;
|
|
47
|
+
metadata[$descriptors][`_${name}`] = {
|
|
48
|
+
value: undefined,
|
|
49
|
+
writable: true,
|
|
50
|
+
enumerable: false,
|
|
51
|
+
configurable: true,
|
|
52
|
+
};
|
|
53
|
+
} else {
|
|
54
|
+
// for decoder
|
|
55
|
+
metadata[$descriptors][name] = {
|
|
56
|
+
value: undefined,
|
|
57
|
+
writable: true,
|
|
58
|
+
enumerable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
// map -1 as last field index
|
|
39
64
|
Object.defineProperty(metadata, -1, {
|
|
40
65
|
value: index,
|
|
@@ -42,17 +67,31 @@ export const Metadata = {
|
|
|
42
67
|
configurable: true
|
|
43
68
|
});
|
|
44
69
|
|
|
45
|
-
// map
|
|
46
|
-
Object.defineProperty(metadata,
|
|
47
|
-
value:
|
|
70
|
+
// map field name => index (non enumerable)
|
|
71
|
+
Object.defineProperty(metadata, name, {
|
|
72
|
+
value: index,
|
|
48
73
|
enumerable: false,
|
|
49
74
|
configurable: true,
|
|
50
75
|
});
|
|
76
|
+
|
|
77
|
+
// if child Ref/complex type, add to -4
|
|
78
|
+
if (typeof (metadata[index].type) !== "string") {
|
|
79
|
+
if (metadata[-4] === undefined) {
|
|
80
|
+
Object.defineProperty(metadata, -4, {
|
|
81
|
+
value: [],
|
|
82
|
+
enumerable: false,
|
|
83
|
+
configurable: true,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
metadata[-4].push(index);
|
|
87
|
+
}
|
|
51
88
|
},
|
|
52
89
|
|
|
53
90
|
setTag(metadata: Metadata, fieldName: string, tag: number) {
|
|
91
|
+
const index = metadata[fieldName];
|
|
92
|
+
const field = metadata[index];
|
|
93
|
+
|
|
54
94
|
// add 'tag' to the field
|
|
55
|
-
const field = metadata[fieldName];
|
|
56
95
|
field.tag = tag;
|
|
57
96
|
|
|
58
97
|
if (!metadata[-2]) {
|
|
@@ -71,27 +110,18 @@ export const Metadata = {
|
|
|
71
110
|
});
|
|
72
111
|
}
|
|
73
112
|
|
|
74
|
-
metadata[-2].push(
|
|
113
|
+
metadata[-2].push(index);
|
|
75
114
|
|
|
76
115
|
if (!metadata[-3][tag]) {
|
|
77
116
|
metadata[-3][tag] = [];
|
|
78
117
|
}
|
|
79
118
|
|
|
80
|
-
metadata[-3][tag].push(
|
|
119
|
+
metadata[-3][tag].push(index);
|
|
81
120
|
},
|
|
82
121
|
|
|
83
122
|
setFields(target: any, fields: { [field: string]: DefinitionType }) {
|
|
84
123
|
const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});
|
|
85
124
|
|
|
86
|
-
// target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {
|
|
87
|
-
// changeTree.change(index, operation, encodeSchemaOperation);
|
|
88
|
-
// };
|
|
89
|
-
|
|
90
|
-
// target[$encoder] = encodeSchemaOperation;
|
|
91
|
-
// target[$decoder] = decodeSchemaOperation;
|
|
92
|
-
|
|
93
|
-
// if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }
|
|
94
|
-
|
|
95
125
|
let index = 0;
|
|
96
126
|
for (const field in fields) {
|
|
97
127
|
const type = fields[field];
|
|
@@ -106,7 +136,7 @@ export const Metadata = {
|
|
|
106
136
|
index,
|
|
107
137
|
field,
|
|
108
138
|
type,
|
|
109
|
-
getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass
|
|
139
|
+
getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass)
|
|
110
140
|
);
|
|
111
141
|
|
|
112
142
|
index++;
|
|
@@ -117,6 +147,54 @@ export const Metadata = {
|
|
|
117
147
|
return metadata[field].deprecated === true;
|
|
118
148
|
},
|
|
119
149
|
|
|
150
|
+
init(klass: any) {
|
|
151
|
+
//
|
|
152
|
+
// Used only to initialize an empty Schema (Encoder#constructor)
|
|
153
|
+
// TODO: remove/refactor this...
|
|
154
|
+
//
|
|
155
|
+
const metadata = {};
|
|
156
|
+
klass[Symbol.metadata] = metadata;
|
|
157
|
+
Object.defineProperty(metadata, -1, {
|
|
158
|
+
value: 0,
|
|
159
|
+
enumerable: false,
|
|
160
|
+
configurable: true,
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
initialize(constructor: any, parentMetadata?: Metadata) {
|
|
165
|
+
let metadata: Metadata = constructor[Symbol.metadata] ?? Object.create(null);
|
|
166
|
+
|
|
167
|
+
// make sure inherited classes have their own metadata object.
|
|
168
|
+
if (constructor[Symbol.metadata] === parentMetadata) {
|
|
169
|
+
metadata = Object.create(null);
|
|
170
|
+
|
|
171
|
+
if (parentMetadata) {
|
|
172
|
+
// assign parent metadata to current
|
|
173
|
+
Object.assign(metadata, parentMetadata);
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i <= parentMetadata[-1]; i++) {
|
|
176
|
+
const fieldName = parentMetadata[i].name;
|
|
177
|
+
Object.defineProperty(metadata, fieldName, {
|
|
178
|
+
value: parentMetadata[fieldName],
|
|
179
|
+
enumerable: false,
|
|
180
|
+
configurable: true,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
Object.defineProperty(metadata, -1, {
|
|
185
|
+
value: parentMetadata[-1],
|
|
186
|
+
enumerable: false,
|
|
187
|
+
configurable: true,
|
|
188
|
+
writable: true,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
constructor[Symbol.metadata] = metadata;
|
|
194
|
+
|
|
195
|
+
return metadata;
|
|
196
|
+
},
|
|
197
|
+
|
|
120
198
|
isValidInstance(klass: any) {
|
|
121
199
|
return (
|
|
122
200
|
klass.constructor[Symbol.metadata] &&
|
|
@@ -125,10 +203,10 @@ export const Metadata = {
|
|
|
125
203
|
},
|
|
126
204
|
|
|
127
205
|
getFields(klass: any) {
|
|
128
|
-
const metadata = klass[Symbol.metadata];
|
|
206
|
+
const metadata: Metadata = klass[Symbol.metadata];
|
|
129
207
|
const fields = {};
|
|
130
208
|
for (let i = 0; i <= metadata[-1]; i++) {
|
|
131
|
-
fields[metadata[i]] = metadata[
|
|
209
|
+
fields[metadata[i].name] = metadata[i].type;
|
|
132
210
|
}
|
|
133
211
|
return fields;
|
|
134
212
|
}
|
package/src/Reflection.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type, PrimitiveType, DefinitionType
|
|
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";
|
|
@@ -24,16 +25,17 @@ export class ReflectionType extends Schema {
|
|
|
24
25
|
export class Reflection extends Schema {
|
|
25
26
|
@type([ ReflectionType ]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();
|
|
26
27
|
|
|
27
|
-
static encode
|
|
28
|
-
|
|
29
|
-
context = new TypeContext(instance.constructor as typeof Schema);
|
|
30
|
-
}
|
|
28
|
+
static encode(instance: Schema, context?: TypeContext, it: Iterator = { offset: 0 }) {
|
|
29
|
+
context ??= new TypeContext(instance.constructor as typeof Schema);
|
|
31
30
|
|
|
32
31
|
const reflection = new Reflection();
|
|
33
32
|
const encoder = new Encoder(reflection);
|
|
34
33
|
|
|
35
34
|
const buildType = (currentType: ReflectionType, metadata: Metadata) => {
|
|
36
|
-
for (const
|
|
35
|
+
for (const fieldIndex in metadata) {
|
|
36
|
+
const index = Number(fieldIndex);
|
|
37
|
+
const fieldName = metadata[index].name;
|
|
38
|
+
|
|
37
39
|
// skip fields from parent classes
|
|
38
40
|
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
39
41
|
continue;
|
|
@@ -44,7 +46,7 @@ export class Reflection extends Schema {
|
|
|
44
46
|
|
|
45
47
|
let fieldType: string;
|
|
46
48
|
|
|
47
|
-
const type = metadata[
|
|
49
|
+
const type = metadata[index].type;
|
|
48
50
|
|
|
49
51
|
if (typeof (type) === "string") {
|
|
50
52
|
fieldType = type;
|
|
@@ -96,7 +98,6 @@ export class Reflection extends Schema {
|
|
|
96
98
|
buildType(type, klass[Symbol.metadata]);
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
const it = { offset: 0 };
|
|
100
101
|
const buf = encoder.encodeAll(it);
|
|
101
102
|
return Buffer.from(buf, 0, it.offset);
|
|
102
103
|
}
|
|
@@ -107,62 +108,59 @@ export class Reflection extends Schema {
|
|
|
107
108
|
const reflectionDecoder = new Decoder(reflection);
|
|
108
109
|
reflectionDecoder.decode(bytes, it);
|
|
109
110
|
|
|
110
|
-
const
|
|
111
|
+
const typeContext = new TypeContext();
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
113
|
+
// 1st pass, initialize metadata + inheritance
|
|
114
|
+
reflection.types.forEach((reflectionType) => {
|
|
115
|
+
const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;
|
|
116
|
+
const schema: typeof Schema = class _ extends parentClass {};
|
|
115
117
|
|
|
116
|
-
|
|
117
|
-
const _metadata = parentKlass && parentKlass[Symbol.metadata] || Object.create(null);
|
|
118
|
-
Object.defineProperty(schema, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata })
|
|
118
|
+
const parentMetadata = parentClass[Symbol.metadata];
|
|
119
119
|
|
|
120
120
|
// register for inheritance support
|
|
121
121
|
TypeContext.register(schema);
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
// for inheritance support
|
|
124
|
+
Metadata.initialize(schema, parentMetadata);
|
|
125
|
+
|
|
126
|
+
typeContext.add(schema, reflectionType.id);
|
|
127
127
|
}, {});
|
|
128
128
|
|
|
129
|
+
// 2nd pass, set fields
|
|
129
130
|
reflection.types.forEach((reflectionType) => {
|
|
130
|
-
const schemaType =
|
|
131
|
+
const schemaType = typeContext.get(reflectionType.id);
|
|
131
132
|
const metadata = schemaType[Symbol.metadata];
|
|
132
133
|
|
|
133
|
-
const
|
|
134
|
-
const parentFieldIndex = parentKlass && parentKlass.fields.length || 0;
|
|
134
|
+
const parentFieldIndex = 0;
|
|
135
135
|
|
|
136
136
|
reflectionType.fields.forEach((field, i) => {
|
|
137
137
|
const fieldIndex = parentFieldIndex + i;
|
|
138
138
|
|
|
139
139
|
if (field.referencedType !== undefined) {
|
|
140
140
|
let fieldType = field.type;
|
|
141
|
-
let refType =
|
|
141
|
+
let refType: PrimitiveType = typeContext.get(field.referencedType);
|
|
142
142
|
|
|
143
143
|
// map or array of primitive type (-1)
|
|
144
144
|
if (!refType) {
|
|
145
145
|
const typeInfo = field.type.split(":");
|
|
146
146
|
fieldType = typeInfo[0];
|
|
147
|
-
refType = typeInfo[1];
|
|
147
|
+
refType = typeInfo[1] as PrimitiveType; // string
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (fieldType === "ref") {
|
|
151
|
-
// type(refType)(schemaType.prototype, field.name);
|
|
152
151
|
Metadata.addField(metadata, fieldIndex, field.name, refType);
|
|
153
152
|
|
|
154
153
|
} else {
|
|
155
|
-
// type({ [fieldType]: refType } as DefinitionType)(schemaType.prototype, field.name);
|
|
156
154
|
Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType } as DefinitionType);
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
} else {
|
|
160
|
-
// type(field.type as PrimitiveType)(schemaType.prototype, field.name);
|
|
161
158
|
Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);
|
|
162
159
|
}
|
|
163
160
|
});
|
|
164
161
|
});
|
|
165
162
|
|
|
166
|
-
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
return new (typeContext.get(0))();
|
|
167
165
|
}
|
|
168
166
|
}
|
package/src/Schema.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { DEFAULT_VIEW_TAG, DefinitionType } from "./annotations";
|
|
|
4
4
|
import { NonFunctionPropNames, ToJSON } from './types/HelperTypes';
|
|
5
5
|
|
|
6
6
|
import { ChangeTree, Ref } from './encoder/ChangeTree';
|
|
7
|
-
import { $changes, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $track } from './types/symbols';
|
|
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';
|
|
@@ -16,7 +16,6 @@ import { getIndent } from './utils';
|
|
|
16
16
|
* Schema encoder / decoder
|
|
17
17
|
*/
|
|
18
18
|
export abstract class Schema {
|
|
19
|
-
|
|
20
19
|
static [$encoder] = encodeSchemaOperation;
|
|
21
20
|
static [$decoder] = decodeSchemaOperation;
|
|
22
21
|
|
|
@@ -31,37 +30,7 @@ export abstract class Schema {
|
|
|
31
30
|
writable: true
|
|
32
31
|
});
|
|
33
32
|
|
|
34
|
-
|
|
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
|
-
}
|
|
33
|
+
Object.defineProperties(instance, instance.constructor[Symbol.metadata]?.[$descriptors] || {});
|
|
65
34
|
}
|
|
66
35
|
|
|
67
36
|
static is(type: DefinitionType) {
|
|
@@ -88,7 +57,7 @@ export abstract class Schema {
|
|
|
88
57
|
*/
|
|
89
58
|
static [$filter] (ref: Schema, index: number, view: StateView) {
|
|
90
59
|
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
91
|
-
const tag = metadata[
|
|
60
|
+
const tag = metadata[index]?.tag;
|
|
92
61
|
|
|
93
62
|
if (view === undefined) {
|
|
94
63
|
// shared pass/encode: encode if doesn't have a tag
|
|
@@ -111,13 +80,24 @@ export abstract class Schema {
|
|
|
111
80
|
|
|
112
81
|
// allow inherited classes to have a constructor
|
|
113
82
|
constructor(...args: any[]) {
|
|
114
|
-
|
|
83
|
+
//
|
|
84
|
+
// inline
|
|
85
|
+
// Schema.initialize(this);
|
|
86
|
+
//
|
|
87
|
+
|
|
88
|
+
Object.defineProperty(this, $changes, {
|
|
89
|
+
value: new ChangeTree(this),
|
|
90
|
+
enumerable: false,
|
|
91
|
+
writable: true
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
Object.defineProperties(this, this.constructor[Symbol.metadata]?.[$descriptors] || {});
|
|
115
95
|
|
|
116
96
|
//
|
|
117
97
|
// Assign initial values
|
|
118
98
|
//
|
|
119
99
|
if (args[0]) {
|
|
120
|
-
|
|
100
|
+
Object.assign(this, args[0]);
|
|
121
101
|
}
|
|
122
102
|
}
|
|
123
103
|
|
|
@@ -135,21 +115,25 @@ export abstract class Schema {
|
|
|
135
115
|
* @param operation OPERATION to perform (detected automatically)
|
|
136
116
|
*/
|
|
137
117
|
public setDirty<K extends NonFunctionPropNames<this>>(property: K | number, operation?: OPERATION) {
|
|
118
|
+
const metadata: Metadata = this.constructor[Symbol.metadata];
|
|
138
119
|
this[$changes].change(
|
|
139
|
-
|
|
120
|
+
metadata[metadata[property as string]].index,
|
|
140
121
|
operation
|
|
141
122
|
);
|
|
142
123
|
}
|
|
143
124
|
|
|
144
125
|
clone (): this {
|
|
145
126
|
const cloned = new ((this as any).constructor);
|
|
146
|
-
const metadata = this.constructor[Symbol.metadata];
|
|
127
|
+
const metadata: Metadata = this.constructor[Symbol.metadata];
|
|
147
128
|
|
|
148
129
|
//
|
|
149
130
|
// TODO: clone all properties, not only annotated ones
|
|
150
131
|
//
|
|
151
132
|
// for (const field in this) {
|
|
152
|
-
for (const
|
|
133
|
+
for (const fieldIndex in metadata) {
|
|
134
|
+
// const field = metadata[metadata[fieldIndex]].name;
|
|
135
|
+
const field = metadata[fieldIndex as any as number].name;
|
|
136
|
+
|
|
153
137
|
if (
|
|
154
138
|
typeof (this[field]) === "object" &&
|
|
155
139
|
typeof (this[field]?.clone) === "function"
|
|
@@ -162,15 +146,17 @@ export abstract class Schema {
|
|
|
162
146
|
cloned[field] = this[field];
|
|
163
147
|
}
|
|
164
148
|
}
|
|
149
|
+
|
|
165
150
|
return cloned;
|
|
166
151
|
}
|
|
167
152
|
|
|
168
153
|
toJSON () {
|
|
169
|
-
const metadata = this.constructor[Symbol.metadata];
|
|
170
|
-
|
|
171
154
|
const obj: unknown = {};
|
|
172
|
-
|
|
173
|
-
|
|
155
|
+
|
|
156
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
157
|
+
for (const index in metadata) {
|
|
158
|
+
const field = metadata[index];
|
|
159
|
+
const fieldName = field.name;
|
|
174
160
|
if (!field.deprecated && this[fieldName] !== null && typeof (this[fieldName]) !== "undefined") {
|
|
175
161
|
obj[fieldName] = (typeof (this[fieldName]['toJSON']) === "function")
|
|
176
162
|
? this[fieldName]['toJSON']()
|
|
@@ -185,11 +171,13 @@ export abstract class Schema {
|
|
|
185
171
|
}
|
|
186
172
|
|
|
187
173
|
protected [$getByIndex](index: number) {
|
|
188
|
-
|
|
174
|
+
const metadata: Metadata = this.constructor[Symbol.metadata];
|
|
175
|
+
return this[metadata[index].name];
|
|
189
176
|
}
|
|
190
177
|
|
|
191
178
|
protected [$deleteByIndex](index: number) {
|
|
192
|
-
this
|
|
179
|
+
const metadata: Metadata = this.constructor[Symbol.metadata];
|
|
180
|
+
this[metadata[index].name] = undefined;
|
|
193
181
|
}
|
|
194
182
|
|
|
195
183
|
static debugRefIds(instance: Ref, jsonContents: boolean = true, level: number = 0) {
|
|
@@ -248,7 +236,7 @@ export abstract class Schema {
|
|
|
248
236
|
return output;
|
|
249
237
|
}
|
|
250
238
|
|
|
251
|
-
static debugChangesDeep(ref: Ref) {
|
|
239
|
+
static debugChangesDeep(ref: Ref, changeSetName: "changes" | "allChanges" | "allFilteredChanges" | "filteredChanges" = "changes") {
|
|
252
240
|
let output = "";
|
|
253
241
|
|
|
254
242
|
const rootChangeTree = ref[$changes];
|
|
@@ -257,7 +245,7 @@ export abstract class Schema {
|
|
|
257
245
|
let totalInstances = 0;
|
|
258
246
|
let totalOperations = 0;
|
|
259
247
|
|
|
260
|
-
for (const [changeTree, changes] of (rootChangeTree.root.
|
|
248
|
+
for (const [changeTree, changes] of (rootChangeTree.root[changeSetName].entries())) {
|
|
261
249
|
let includeChangeTree = false;
|
|
262
250
|
let parentChangeTrees: ChangeTree[] = [];
|
|
263
251
|
let parentChangeTree = changeTree.parent?.[$changes];
|