@colyseus/schema 3.0.0-alpha.37 → 3.0.0-alpha.39
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 +142 -32
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +142 -33
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +142 -32
- package/lib/Metadata.d.ts +3 -2
- package/lib/Metadata.js +57 -15
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +4 -3
- package/lib/Reflection.js +36 -11
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +2 -2
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +29 -12
- package/lib/annotations.js +36 -3
- package/lib/annotations.js.map +1 -1
- package/lib/codegen/parser.js +83 -0
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +3 -0
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +4 -0
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/EncodeOperation.js +2 -2
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +34 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/TypeContext.js +9 -1
- package/lib/types/TypeContext.js.map +1 -1
- package/package.json +1 -1
- package/src/Metadata.ts +62 -16
- package/src/Reflection.ts +43 -16
- package/src/Schema.ts +2 -3
- package/src/annotations.ts +68 -18
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/decoder/DecodeOperation.ts +4 -0
- package/src/decoder/strategy/StateCallbacks.ts +1 -1
- package/src/encoder/EncodeOperation.ts +4 -2
- package/src/index.ts +1 -1
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +11 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HelperTypes.js","sourceRoot":"","sources":["../../src/types/HelperTypes.ts"],"names":[],"mappings":"","sourcesContent":["import { ArraySchema } from \"./custom/ArraySchema\";\nimport { MapSchema } from \"./custom/MapSchema\";\n\nexport interface Collection<K = any, V = any, IT = V> {\n [Symbol.iterator](): IterableIterator<IT>;\n forEach(callback: Function);\n entries(): IterableIterator<[K, V]>;\n}\n\nexport type NonFunctionProps<T> = Omit<T, {\n [K in keyof T]: T[K] extends Function ? K : never;\n}[keyof T]>;\n\nexport type NonFunctionPropNames<T> = {\n [K in keyof T]: T[K] extends Function ? never : K\n}[keyof T];\n\nexport type NonFunctionNonPrimitivePropNames<T> = {\n [K in keyof T]: T[K] extends Function\n ? never\n : T[K] extends number | string | boolean\n ? never\n : K\n}[keyof T];\n\nexport type ToJSON<T> = NonFunctionProps<{\n [K in keyof T]: T[K] extends MapSchema<infer U>\n ? Record<string, U>\n : T[K] extends Map<string, infer U>\n ? Record<string, U>\n : T[K] extends ArraySchema<infer U>\n ? U[]\n : T[K]\n}>;"]}
|
|
1
|
+
{"version":3,"file":"HelperTypes.js","sourceRoot":"","sources":["../../src/types/HelperTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { Definition, DefinitionType, PrimitiveType, RawPrimitiveType } from \"../annotations\";\nimport type { Schema } from \"../Schema\";\nimport type { ArraySchema } from \"./custom/ArraySchema\";\nimport type { CollectionSchema } from \"./custom/CollectionSchema\";\nimport type { MapSchema } from \"./custom/MapSchema\";\nimport type { SetSchema } from \"./custom/SetSchema\";\n\nexport type Constructor<T = {}> = new (...args: any[]) => T;\n\nexport interface Collection<K = any, V = any, IT = V> {\n [Symbol.iterator](): IterableIterator<IT>;\n forEach(callback: Function);\n entries(): IterableIterator<[K, V]>;\n}\n\nexport type InferValueType<T extends DefinitionType> =\n T extends \"string\" ? string\n : T extends \"number\" ? number\n : T extends \"int8\" ? number\n : T extends \"uint8\" ? number\n : T extends \"int16\" ? number\n : T extends \"uint16\" ? number\n : T extends \"int32\" ? number\n : T extends \"uint32\" ? number\n : T extends \"int64\" ? number\n : T extends \"uint64\" ? number\n : T extends \"float32\" ? number\n : T extends \"float64\" ? number\n : T extends \"boolean\" ? boolean\n\n : T extends { type: infer ChildType extends Constructor } ? InstanceType<ChildType>\n : T extends { type: infer ChildType extends PrimitiveType } ? ChildType\n\n : T extends Array<infer ChildType extends Constructor> ? InstanceType<ChildType>[]\n : T extends Array<infer ChildType extends RawPrimitiveType> ? ChildType[]\n\n : T extends { array: infer ChildType extends Constructor } ? InstanceType<ChildType>[]\n : T extends { array: infer ChildType extends PrimitiveType } ? ChildType[]\n\n : T extends { map: infer ChildType extends Constructor } ? MapSchema<InstanceType<ChildType>>\n : T extends { map: infer ChildType extends PrimitiveType } ? MapSchema<ChildType>\n\n : T extends { set: infer ChildType extends Constructor } ? SetSchema<InstanceType<ChildType>>\n : T extends { set: infer ChildType extends PrimitiveType } ? SetSchema<ChildType>\n\n : T extends { collection: infer ChildType extends Constructor } ? CollectionSchema<InstanceType<ChildType>>\n : T extends { collection: infer ChildType extends PrimitiveType } ? CollectionSchema<ChildType>\n\n : T extends Constructor ? InstanceType<T>\n : T extends PrimitiveType ? T\n\n : never;\n\nexport type InferSchemaInstanceType<T extends Definition> = {\n [K in keyof T]: InferValueType<T[K]>\n} & Schema;\n\nexport type DefinedSchemaType<T extends Definition, P extends typeof Schema> = {\n new (): InferSchemaInstanceType<T> & InstanceType<P>;\n} & typeof Schema;\n\nexport type NonFunctionProps<T> = Omit<T, {\n [K in keyof T]: T[K] extends Function ? K : never;\n}[keyof T]>;\n\nexport type NonFunctionPropNames<T> = {\n [K in keyof T]: T[K] extends Function ? never : K\n}[keyof T];\n\nexport type NonFunctionNonPrimitivePropNames<T> = {\n [K in keyof T]: T[K] extends Function\n ? never\n : T[K] extends number | string | boolean\n ? never\n : K\n}[keyof T];\n\nexport type ToJSON<T> = NonFunctionProps<{\n [K in keyof T]: T[K] extends MapSchema<infer U>\n ? Record<string, U>\n : T[K] extends Map<string, infer U>\n ? Record<string, U>\n : T[K] extends ArraySchema<infer U>\n ? U[]\n : T[K]\n}>;"]}
|
package/lib/types/TypeContext.js
CHANGED
|
@@ -46,7 +46,7 @@ class TypeContext {
|
|
|
46
46
|
// Workaround to allow using an empty Schema (with no `@type()` fields)
|
|
47
47
|
//
|
|
48
48
|
if (schema[Symbol.metadata] === undefined) {
|
|
49
|
-
Metadata_1.Metadata.
|
|
49
|
+
Metadata_1.Metadata.initialize(schema);
|
|
50
50
|
}
|
|
51
51
|
this.schemas.set(schema, typeid);
|
|
52
52
|
return true;
|
|
@@ -62,6 +62,14 @@ class TypeContext {
|
|
|
62
62
|
TypeContext.inheritedTypes.get(klass)?.forEach((child) => {
|
|
63
63
|
this.discoverTypes(child, parentIndex, parentFieldViewTag);
|
|
64
64
|
});
|
|
65
|
+
// add parent classes
|
|
66
|
+
let parent = klass;
|
|
67
|
+
while ((parent = Object.getPrototypeOf(parent)) &&
|
|
68
|
+
parent !== Schema_1.Schema && // stop at root (Schema)
|
|
69
|
+
parent !== Function.prototype // stop at root (non-Schema)
|
|
70
|
+
) {
|
|
71
|
+
this.discoverTypes(parent);
|
|
72
|
+
}
|
|
65
73
|
const metadata = (klass[Symbol.metadata] ??= {});
|
|
66
74
|
// if any schema/field has filters, mark "context" as having filters.
|
|
67
75
|
if (metadata[symbols_1.$viewFieldIndexes]) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeContext.js","sourceRoot":"","sources":["../../src/types/TypeContext.ts"],"names":[],"mappings":";;;AAAA,0CAAuC;AACvC,sCAAmC;AACnC,uCAA8C;AAE9C,MAAa,WAAW;IAOpB;;;OAGG;aACI,mBAAc,GAAG,IAAI,GAAG,EAAqC,AAA/C,CAAgD;IAErE,MAAM,CAAC,QAAQ,CAAC,MAAqB;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,MAAM,KAAK,eAAM,EAAE,CAAC;YACpB,IAAI,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACZ,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAC;gBACpC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACrD,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IAED,YAAY,SAAyB;QAxBrC,UAAK,GAAqC,EAAE,CAAC;QAC7C,YAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;QAE3C,eAAU,GAAY,KAAK,CAAC;QAC5B,mBAAc,GAA8C,EAAE,CAAC;QAqB3D,IAAI,SAAS,EAAE,CAAC;YACZ,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAClC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,MAAqB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,GAAG,CAAC,MAAc;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,GAAG,CAAC,MAAqB,EAAE,SAAiB,IAAI,CAAC,OAAO,CAAC,IAAI;QACzD,6BAA6B;QAC7B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QAE5B,EAAE;QACF,uEAAuE;QACvE,EAAE;QACF,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;YACxC,mBAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"TypeContext.js","sourceRoot":"","sources":["../../src/types/TypeContext.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../Metadata\";\nimport { Schema } from \"../Schema\";\nimport { $viewFieldIndexes } from \"./symbols\";\n\nexport class TypeContext {\n types: { [id: number]: typeof Schema; } = {};\n schemas = new Map<typeof Schema, number>();\n\n hasFilters: boolean = false;\n parentFiltered: {[typeIdAndParentIndex: string]: boolean} = {};\n\n /**\n * For inheritance support\n * Keeps track of which classes extends which. (parent -> children)\n */\n static inheritedTypes = new Map<typeof Schema, Set<typeof Schema>>();\n\n static register(target: typeof Schema) {\n const parent = Object.getPrototypeOf(target);\n if (parent !== Schema) {\n let inherits = TypeContext.inheritedTypes.get(parent);\n if (!inherits) {\n inherits = new Set<typeof Schema>();\n TypeContext.inheritedTypes.set(parent, inherits);\n }\n inherits.add(target);\n }\n }\n\n constructor(rootClass?: typeof Schema) {\n if (rootClass) {\n this.discoverTypes(rootClass);\n }\n }\n\n has(schema: typeof Schema) {\n return this.schemas.has(schema);\n }\n\n get(typeid: number) {\n return this.types[typeid];\n }\n\n add(schema: typeof Schema, typeid: number = this.schemas.size) {\n // skip if already registered\n if (this.schemas.has(schema)) {\n return false;\n }\n\n this.types[typeid] = schema;\n\n //\n // Workaround to allow using an empty Schema (with no `@type()` fields)\n //\n if (schema[Symbol.metadata] === undefined) {\n Metadata.initialize(schema);\n }\n\n this.schemas.set(schema, typeid);\n return true;\n }\n\n getTypeId(klass: typeof Schema) {\n return this.schemas.get(klass);\n }\n\n private discoverTypes(klass: typeof Schema, parentIndex?: number, parentFieldViewTag?: number) {\n if (!this.add(klass)) {\n return;\n }\n\n // add classes inherited from this base class\n TypeContext.inheritedTypes.get(klass)?.forEach((child) => {\n this.discoverTypes(child, parentIndex, parentFieldViewTag);\n });\n\n // add parent classes\n let parent: any = klass;\n while (\n (parent = Object.getPrototypeOf(parent)) &&\n parent !== Schema && // stop at root (Schema)\n parent !== Function.prototype // stop at root (non-Schema)\n ) {\n this.discoverTypes(parent);\n }\n\n const metadata: Metadata = (klass[Symbol.metadata] ??= {});\n\n // if any schema/field has filters, mark \"context\" as having filters.\n if (metadata[$viewFieldIndexes]) {\n this.hasFilters = true;\n }\n\n if (parentFieldViewTag !== undefined) {\n this.parentFiltered[`${this.schemas.get(klass)}-${parentIndex}`] = true;\n }\n\n for (const fieldIndex in metadata) {\n const index = fieldIndex as any as number;\n\n const fieldType = metadata[index].type;\n const viewTag = metadata[index].tag;\n\n if (typeof (fieldType) === \"string\") {\n continue;\n }\n\n if (Array.isArray(fieldType)) {\n const type = fieldType[0];\n\n // skip primitive types\n if (type === \"string\") {\n continue;\n }\n\n this.discoverTypes(type as typeof Schema, index, viewTag);\n\n } else if (typeof (fieldType) === \"function\") {\n this.discoverTypes(fieldType as typeof Schema, viewTag);\n\n } else {\n const type = Object.values(fieldType)[0];\n\n // skip primitive types\n if (typeof (type) === \"string\") {\n continue;\n }\n\n this.discoverTypes(type as typeof Schema, index, viewTag);\n }\n }\n }\n}\n"]}
|
package/package.json
CHANGED
package/src/Metadata.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Definition, DefinitionType, getPropertyDescriptor } from "./annotations";
|
|
2
2
|
import { Schema } from "./Schema";
|
|
3
3
|
import { getType } from "./types/registry";
|
|
4
4
|
import { $decoder, $descriptors, $encoder, $fieldIndexesByViewTag, $numFields, $refTypeFieldIndexes, $track, $viewFieldIndexes } from "./types/symbols";
|
|
@@ -22,6 +22,14 @@ export type Metadata =
|
|
|
22
22
|
{ [field: string]: number; } & // field name => field metadata
|
|
23
23
|
{ [$descriptors]: { [field: string]: PropertyDescriptor } } // property descriptors
|
|
24
24
|
|
|
25
|
+
export function getNormalizedType(type: DefinitionType): DefinitionType {
|
|
26
|
+
return (Array.isArray(type))
|
|
27
|
+
? { array: type[0] }
|
|
28
|
+
: (typeof(type['type']) !== "undefined")
|
|
29
|
+
? type['type']
|
|
30
|
+
: type;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
export const Metadata = {
|
|
26
34
|
|
|
27
35
|
addField(metadata: any, index: number, name: string, type: DefinitionType, descriptor?: PropertyDescriptor) {
|
|
@@ -32,16 +40,18 @@ export const Metadata = {
|
|
|
32
40
|
metadata[index] = Object.assign(
|
|
33
41
|
metadata[index] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
|
|
34
42
|
{
|
|
35
|
-
type: (
|
|
36
|
-
? { array: type[0] }
|
|
37
|
-
: type,
|
|
43
|
+
type: getNormalizedType(type),
|
|
38
44
|
index,
|
|
39
45
|
name,
|
|
40
46
|
}
|
|
41
47
|
);
|
|
42
48
|
|
|
43
49
|
// create "descriptors" map
|
|
44
|
-
metadata
|
|
50
|
+
Object.defineProperty(metadata, $descriptors, {
|
|
51
|
+
value: metadata[$descriptors] || {},
|
|
52
|
+
enumerable: false,
|
|
53
|
+
configurable: true,
|
|
54
|
+
});
|
|
45
55
|
|
|
46
56
|
if (descriptor) {
|
|
47
57
|
// for encoder
|
|
@@ -128,7 +138,7 @@ export const Metadata = {
|
|
|
128
138
|
|
|
129
139
|
const parentClass = Object.getPrototypeOf(constructor);
|
|
130
140
|
const parentMetadata = parentClass && parentClass[Symbol.metadata];
|
|
131
|
-
const metadata = Metadata.initialize(constructor
|
|
141
|
+
const metadata = Metadata.initialize(constructor);
|
|
132
142
|
|
|
133
143
|
// Use Schema's methods if not defined in the class
|
|
134
144
|
if (!constructor[$track]) { constructor[$track] = Schema[$track]; }
|
|
@@ -147,18 +157,23 @@ export const Metadata = {
|
|
|
147
157
|
|
|
148
158
|
for (const field in fields) {
|
|
149
159
|
const type = fields[field];
|
|
160
|
+
const normalizedType = getNormalizedType(type);
|
|
150
161
|
|
|
151
162
|
// FIXME: this code is duplicated from @type() annotation
|
|
152
163
|
const complexTypeKlass = (Array.isArray(type))
|
|
153
164
|
? getType("array")
|
|
154
165
|
: (typeof(Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
|
|
155
166
|
|
|
167
|
+
const childType = (complexTypeKlass)
|
|
168
|
+
? Object.values(type)[0]
|
|
169
|
+
: normalizedType;
|
|
170
|
+
|
|
156
171
|
Metadata.addField(
|
|
157
172
|
metadata,
|
|
158
173
|
fieldIndex,
|
|
159
174
|
field,
|
|
160
175
|
type,
|
|
161
|
-
getPropertyDescriptor(`_${field}`, fieldIndex,
|
|
176
|
+
getPropertyDescriptor(`_${field}`, fieldIndex, childType, complexTypeKlass)
|
|
162
177
|
);
|
|
163
178
|
|
|
164
179
|
fieldIndex++;
|
|
@@ -185,28 +200,59 @@ export const Metadata = {
|
|
|
185
200
|
});
|
|
186
201
|
},
|
|
187
202
|
|
|
188
|
-
initialize(constructor: any
|
|
203
|
+
initialize(constructor: any) {
|
|
204
|
+
const parentClass = Object.getPrototypeOf(constructor);
|
|
205
|
+
const parentMetadata: Metadata = parentClass[Symbol.metadata];
|
|
206
|
+
|
|
189
207
|
let metadata: Metadata = constructor[Symbol.metadata] ?? Object.create(null);
|
|
190
208
|
|
|
191
209
|
// make sure inherited classes have their own metadata object.
|
|
192
|
-
if (
|
|
210
|
+
if (parentClass !== Schema && metadata === parentMetadata) {
|
|
193
211
|
metadata = Object.create(null);
|
|
194
212
|
|
|
195
213
|
if (parentMetadata) {
|
|
214
|
+
//
|
|
196
215
|
// assign parent metadata to current
|
|
197
|
-
|
|
216
|
+
//
|
|
217
|
+
Object.setPrototypeOf(metadata, parentMetadata);
|
|
218
|
+
|
|
219
|
+
// $numFields
|
|
220
|
+
Object.defineProperty(metadata, $numFields, {
|
|
221
|
+
value: parentMetadata[$numFields],
|
|
222
|
+
enumerable: false,
|
|
223
|
+
configurable: true,
|
|
224
|
+
writable: true,
|
|
225
|
+
});
|
|
198
226
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
Object.defineProperty(metadata,
|
|
202
|
-
value: parentMetadata[
|
|
227
|
+
// $viewFieldIndexes / $fieldIndexesByViewTag
|
|
228
|
+
if (parentMetadata[$viewFieldIndexes] !== undefined) {
|
|
229
|
+
Object.defineProperty(metadata, $viewFieldIndexes, {
|
|
230
|
+
value: [...parentMetadata[$viewFieldIndexes]],
|
|
231
|
+
enumerable: false,
|
|
232
|
+
configurable: true,
|
|
233
|
+
writable: true,
|
|
234
|
+
});
|
|
235
|
+
Object.defineProperty(metadata, $fieldIndexesByViewTag, {
|
|
236
|
+
value: { ...parentMetadata[$fieldIndexesByViewTag] },
|
|
203
237
|
enumerable: false,
|
|
204
238
|
configurable: true,
|
|
239
|
+
writable: true,
|
|
205
240
|
});
|
|
206
241
|
}
|
|
207
242
|
|
|
208
|
-
|
|
209
|
-
|
|
243
|
+
// $refTypeFieldIndexes
|
|
244
|
+
if (parentMetadata[$refTypeFieldIndexes] !== undefined) {
|
|
245
|
+
Object.defineProperty(metadata, $refTypeFieldIndexes, {
|
|
246
|
+
value: [...parentMetadata[$refTypeFieldIndexes]],
|
|
247
|
+
enumerable: false,
|
|
248
|
+
configurable: true,
|
|
249
|
+
writable: true,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// $descriptors
|
|
254
|
+
Object.defineProperty(metadata, $descriptors, {
|
|
255
|
+
value: { ...parentMetadata[$descriptors] },
|
|
210
256
|
enumerable: false,
|
|
211
257
|
configurable: true,
|
|
212
258
|
writable: true,
|
package/src/Reflection.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Iterator } from "./encoding/decode";
|
|
|
6
6
|
import { Encoder } from "./encoder/Encoder";
|
|
7
7
|
import { Decoder } from "./decoder/Decoder";
|
|
8
8
|
import { Schema } from "./Schema";
|
|
9
|
+
import { $numFields } from "./types/symbols";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Reflection
|
|
@@ -23,19 +24,27 @@ export class ReflectionType extends Schema {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export class Reflection extends Schema {
|
|
26
|
-
@type([
|
|
27
|
+
@type([ReflectionType]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();
|
|
28
|
+
@type("number") rootType: number;
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* Encodes the TypeContext of an Encoder into a buffer.
|
|
30
32
|
*
|
|
31
|
-
* @param
|
|
33
|
+
* @param encoder Encoder instance
|
|
32
34
|
* @param it
|
|
33
35
|
* @returns
|
|
34
36
|
*/
|
|
35
|
-
static encode(
|
|
37
|
+
static encode(encoder: Encoder, it: Iterator = { offset: 0 }) {
|
|
38
|
+
const context = encoder.context;
|
|
39
|
+
|
|
36
40
|
const reflection = new Reflection();
|
|
37
41
|
const reflectionEncoder = new Encoder(reflection);
|
|
38
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; }
|
|
47
|
+
|
|
39
48
|
const buildType = (currentType: ReflectionType, metadata: Metadata) => {
|
|
40
49
|
for (const fieldIndex in metadata) {
|
|
41
50
|
const index = Number(fieldIndex);
|
|
@@ -127,24 +136,17 @@ export class Reflection extends Schema {
|
|
|
127
136
|
const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;
|
|
128
137
|
const schema: typeof Schema = class _ extends parentClass {};
|
|
129
138
|
|
|
130
|
-
const parentMetadata = parentClass[Symbol.metadata];
|
|
131
|
-
|
|
132
139
|
// register for inheritance support
|
|
133
140
|
TypeContext.register(schema);
|
|
134
141
|
|
|
135
|
-
// for inheritance support
|
|
136
|
-
Metadata.initialize(schema
|
|
142
|
+
// // for inheritance support
|
|
143
|
+
// Metadata.initialize(schema);
|
|
137
144
|
|
|
138
145
|
typeContext.add(schema, reflectionType.id);
|
|
139
146
|
}, {});
|
|
140
147
|
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
const schemaType = typeContext.get(reflectionType.id);
|
|
144
|
-
const metadata = schemaType[Symbol.metadata];
|
|
145
|
-
|
|
146
|
-
const parentFieldIndex = 0;
|
|
147
|
-
|
|
148
|
+
// define fields
|
|
149
|
+
const addFields = (metadata: Metadata, reflectionType: ReflectionType, parentFieldIndex: number) => {
|
|
148
150
|
reflectionType.fields.forEach((field, i) => {
|
|
149
151
|
const fieldIndex = parentFieldIndex + i;
|
|
150
152
|
|
|
@@ -163,16 +165,41 @@ export class Reflection extends Schema {
|
|
|
163
165
|
Metadata.addField(metadata, fieldIndex, field.name, refType);
|
|
164
166
|
|
|
165
167
|
} else {
|
|
166
|
-
Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType }
|
|
168
|
+
Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
} else {
|
|
170
172
|
Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);
|
|
171
173
|
}
|
|
172
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
|
+
});
|
|
173
200
|
});
|
|
174
201
|
|
|
175
|
-
const state: T = new (typeContext.get(0) as unknown as any)();
|
|
202
|
+
const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();
|
|
176
203
|
|
|
177
204
|
return new Decoder<T>(state, typeContext);
|
|
178
205
|
}
|
package/src/Schema.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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
|
|
|
@@ -15,7 +15,7 @@ import { getIndent } from './utils';
|
|
|
15
15
|
/**
|
|
16
16
|
* Schema encoder / decoder
|
|
17
17
|
*/
|
|
18
|
-
export
|
|
18
|
+
export class Schema {
|
|
19
19
|
static [$encoder] = encodeSchemaOperation;
|
|
20
20
|
static [$decoder] = decodeSchemaOperation;
|
|
21
21
|
|
|
@@ -147,7 +147,6 @@ export abstract class Schema {
|
|
|
147
147
|
|
|
148
148
|
toJSON () {
|
|
149
149
|
const obj: unknown = {};
|
|
150
|
-
|
|
151
150
|
const metadata = this.constructor[Symbol.metadata];
|
|
152
151
|
for (const index in metadata) {
|
|
153
152
|
const field = metadata[index];
|
package/src/annotations.ts
CHANGED
|
@@ -9,12 +9,11 @@ import { OPERATION } from "./encoding/spec";
|
|
|
9
9
|
import { TypeContext } from "./types/TypeContext";
|
|
10
10
|
import { assertInstanceType, assertType } from "./encoding/assert";
|
|
11
11
|
import type { Ref } from "./encoder/ChangeTree";
|
|
12
|
+
import type { DefinedSchemaType, InferValueType } from "./types/HelperTypes";
|
|
13
|
+
import type { CollectionSchema } from "./types/custom/CollectionSchema";
|
|
14
|
+
import type { SetSchema } from "./types/custom/SetSchema";
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
* Data types
|
|
15
|
-
*/
|
|
16
|
-
export type PrimitiveType =
|
|
17
|
-
"string" |
|
|
16
|
+
export type RawPrimitiveType = "string" |
|
|
18
17
|
"number" |
|
|
19
18
|
"boolean" |
|
|
20
19
|
"int8" |
|
|
@@ -26,16 +25,18 @@ export type PrimitiveType =
|
|
|
26
25
|
"int64" |
|
|
27
26
|
"uint64" |
|
|
28
27
|
"float32" |
|
|
29
|
-
"float64"
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
"float64";
|
|
29
|
+
|
|
30
|
+
export type PrimitiveType = RawPrimitiveType | typeof Schema | object;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
| {
|
|
37
|
-
| {
|
|
38
|
-
| {
|
|
32
|
+
// TODO: infer "default" value type correctly.
|
|
33
|
+
export type DefinitionType<T extends PrimitiveType = PrimitiveType> = T
|
|
34
|
+
| T[]
|
|
35
|
+
| { type: T, default?: InferValueType<T>, view?: boolean | number }
|
|
36
|
+
| { array: T, default?: ArraySchema<InferValueType<T>>, view?: boolean | number }
|
|
37
|
+
| { map: T, default?: MapSchema<InferValueType<T>>, view?: boolean | number }
|
|
38
|
+
| { collection: T, default?: CollectionSchema<InferValueType<T>>, view?: boolean | number }
|
|
39
|
+
| { set: T, default?: SetSchema<InferValueType<T>>, view?: boolean | number };
|
|
39
40
|
|
|
40
41
|
export type Definition = { [field: string]: DefinitionType };
|
|
41
42
|
|
|
@@ -286,15 +287,15 @@ export function type (
|
|
|
286
287
|
TypeContext.register(constructor);
|
|
287
288
|
|
|
288
289
|
const parentClass = Object.getPrototypeOf(constructor);
|
|
289
|
-
const parentMetadata =
|
|
290
|
-
const metadata = Metadata.initialize(constructor
|
|
290
|
+
const parentMetadata = parentClass[Symbol.metadata];
|
|
291
|
+
const metadata = Metadata.initialize(constructor);
|
|
291
292
|
|
|
292
293
|
let fieldIndex: number = metadata[field];
|
|
293
294
|
|
|
294
295
|
/**
|
|
295
296
|
* skip if descriptor already exists for this field (`@deprecated()`)
|
|
296
297
|
*/
|
|
297
|
-
if (metadata[fieldIndex]) {
|
|
298
|
+
if (metadata[fieldIndex] !== undefined) {
|
|
298
299
|
if (metadata[fieldIndex].deprecated) {
|
|
299
300
|
// do not create accessors for deprecated properties.
|
|
300
301
|
return;
|
|
@@ -479,7 +480,7 @@ export function deprecated(throws: boolean = true): PropertyDecorator {
|
|
|
479
480
|
|
|
480
481
|
export function defineTypes(
|
|
481
482
|
target: typeof Schema,
|
|
482
|
-
fields:
|
|
483
|
+
fields: Definition,
|
|
483
484
|
options?: TypeOptions
|
|
484
485
|
) {
|
|
485
486
|
for (let field in fields) {
|
|
@@ -487,3 +488,52 @@ export function defineTypes(
|
|
|
487
488
|
}
|
|
488
489
|
return target;
|
|
489
490
|
}
|
|
491
|
+
|
|
492
|
+
export interface SchemaWithExtends<T extends Definition, P extends typeof Schema> extends DefinedSchemaType<T, P> {
|
|
493
|
+
extends: <T2 extends Definition>(
|
|
494
|
+
fields: T2,
|
|
495
|
+
name?: string
|
|
496
|
+
) => SchemaWithExtends<T & T2, typeof this>;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export function schema<T extends Definition, P extends typeof Schema = typeof Schema>(
|
|
500
|
+
fields: T,
|
|
501
|
+
name?: string,
|
|
502
|
+
inherits: P = Schema as P
|
|
503
|
+
): SchemaWithExtends<T, P> {
|
|
504
|
+
const defaultValues: any = {};
|
|
505
|
+
const viewTagFields: any = {};
|
|
506
|
+
|
|
507
|
+
for (let fieldName in fields) {
|
|
508
|
+
const field = fields[fieldName] as DefinitionType;
|
|
509
|
+
if (typeof (field) === "object") {
|
|
510
|
+
if (field['default'] !== undefined) {
|
|
511
|
+
defaultValues[fieldName] = field['default'];
|
|
512
|
+
}
|
|
513
|
+
if (field['view'] !== undefined) {
|
|
514
|
+
viewTagFields[fieldName] = (typeof (field['view']) === "boolean")
|
|
515
|
+
? DEFAULT_VIEW_TAG
|
|
516
|
+
: field['view'];
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const klass = Metadata.setFields(class extends inherits {
|
|
522
|
+
constructor (...args: any[]) {
|
|
523
|
+
args[0] = Object.assign({}, defaultValues, args[0]);
|
|
524
|
+
super(...args);
|
|
525
|
+
}
|
|
526
|
+
}, fields) as SchemaWithExtends<T, P>;
|
|
527
|
+
|
|
528
|
+
for (let fieldName in viewTagFields) {
|
|
529
|
+
view(viewTagFields[fieldName])(klass.prototype, fieldName);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (name) {
|
|
533
|
+
Object.defineProperty(klass, "name", { value: name });
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
klass.extends = (fields, name) => schema(fields, name, klass);
|
|
537
|
+
|
|
538
|
+
return klass;
|
|
539
|
+
}
|
package/src/codegen/parser.ts
CHANGED
|
@@ -148,6 +148,49 @@ function inspectNode(node: ts.Node, context: Context, decoratorName: string) {
|
|
|
148
148
|
defineProperty(property, typeArgument);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
} else if (
|
|
152
|
+
node.getText() === "setFields" &&
|
|
153
|
+
(
|
|
154
|
+
node.parent.kind === ts.SyntaxKind.CallExpression ||
|
|
155
|
+
node.parent.kind === ts.SyntaxKind.PropertyAccessExpression
|
|
156
|
+
)
|
|
157
|
+
) {
|
|
158
|
+
/**
|
|
159
|
+
* Metadata.setFields(klassName, { ... })
|
|
160
|
+
*/
|
|
161
|
+
const callExpression = (node.parent.kind === ts.SyntaxKind.PropertyAccessExpression)
|
|
162
|
+
? node.parent.parent as ts.CallExpression
|
|
163
|
+
: node.parent as ts.CallExpression;
|
|
164
|
+
|
|
165
|
+
if (callExpression.kind !== ts.SyntaxKind.CallExpression) {
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const classNameNode = callExpression.arguments[0];
|
|
170
|
+
const className = ts.isClassExpression(classNameNode)
|
|
171
|
+
? classNameNode.name?.escapedText.toString()
|
|
172
|
+
: classNameNode.getText();
|
|
173
|
+
|
|
174
|
+
// skip if no className is provided
|
|
175
|
+
if (!className) { break; }
|
|
176
|
+
|
|
177
|
+
if (currentStructure.name !== className) {
|
|
178
|
+
currentStructure = new Class();
|
|
179
|
+
}
|
|
180
|
+
context.addStructure(currentStructure);
|
|
181
|
+
(currentStructure as Class).extends = "Schema"; // force extends to Schema
|
|
182
|
+
currentStructure.name = className;
|
|
183
|
+
|
|
184
|
+
const types = callExpression.arguments[1] as any;
|
|
185
|
+
for (let i = 0; i < types.properties.length; i++) {
|
|
186
|
+
const prop = types.properties[i];
|
|
187
|
+
|
|
188
|
+
const property = currentProperty || new Property();
|
|
189
|
+
property.name = prop.name.escapedText;
|
|
190
|
+
|
|
191
|
+
currentStructure.addProperty(property);
|
|
192
|
+
defineProperty(property, prop.initializer);
|
|
193
|
+
}
|
|
151
194
|
|
|
152
195
|
} else if (
|
|
153
196
|
node.getText() === "defineTypes" &&
|
|
@@ -192,6 +235,70 @@ function inspectNode(node: ts.Node, context: Context, decoratorName: string) {
|
|
|
192
235
|
|
|
193
236
|
break;
|
|
194
237
|
|
|
238
|
+
case ts.SyntaxKind.CallExpression:
|
|
239
|
+
/**
|
|
240
|
+
* Defining schema via `schema.schema({ ... })`
|
|
241
|
+
* - schema.schema({})
|
|
242
|
+
* - schema({})
|
|
243
|
+
* - ClassName.extends({})
|
|
244
|
+
*/
|
|
245
|
+
if (
|
|
246
|
+
(
|
|
247
|
+
(
|
|
248
|
+
(node as ts.CallExpression).expression?.getText() === "schema.schema" ||
|
|
249
|
+
(node as ts.CallExpression).expression?.getText() === "schema"
|
|
250
|
+
) ||
|
|
251
|
+
(
|
|
252
|
+
(node as ts.CallExpression).expression?.getText().indexOf(".extends") !== -1
|
|
253
|
+
)
|
|
254
|
+
) &&
|
|
255
|
+
(node as ts.CallExpression).arguments[0].kind === ts.SyntaxKind.ObjectLiteralExpression
|
|
256
|
+
) {
|
|
257
|
+
const callExpression = node as ts.CallExpression;
|
|
258
|
+
|
|
259
|
+
let className = callExpression.arguments[1]?.getText();
|
|
260
|
+
|
|
261
|
+
if (!className && callExpression.parent.kind === ts.SyntaxKind.VariableDeclaration) {
|
|
262
|
+
className = (callExpression.parent as ts.VariableDeclaration).name?.getText();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// skip if no className is provided
|
|
266
|
+
if (!className) { break; }
|
|
267
|
+
|
|
268
|
+
if (currentStructure.name !== className) {
|
|
269
|
+
currentStructure = new Class();
|
|
270
|
+
context.addStructure(currentStructure);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if ((node as ts.CallExpression).expression?.getText().indexOf(".extends") !== -1) {
|
|
274
|
+
// if it's using `.extends({})`
|
|
275
|
+
const extendsClass = (node as any).expression?.expression?.escapedText;
|
|
276
|
+
|
|
277
|
+
// skip if no extendsClass is provided
|
|
278
|
+
if (!extendsClass) { break; }
|
|
279
|
+
(currentStructure as Class).extends = extendsClass;
|
|
280
|
+
|
|
281
|
+
} else {
|
|
282
|
+
// if it's using `schema({})`
|
|
283
|
+
(currentStructure as Class).extends = "Schema"; // force extends to Schema
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
currentStructure.name = className;
|
|
287
|
+
|
|
288
|
+
const types = callExpression.arguments[0] as any;
|
|
289
|
+
for (let i = 0; i < types.properties.length; i++) {
|
|
290
|
+
const prop = types.properties[i];
|
|
291
|
+
|
|
292
|
+
const property = currentProperty || new Property();
|
|
293
|
+
property.name = prop.name.escapedText;
|
|
294
|
+
|
|
295
|
+
currentStructure.addProperty(property);
|
|
296
|
+
defineProperty(property, prop.initializer);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
break;
|
|
301
|
+
|
|
195
302
|
case ts.SyntaxKind.EnumMember:
|
|
196
303
|
if (currentStructure instanceof Enum) {
|
|
197
304
|
const initializer = (node as any).initializer?.text;
|
package/src/codegen/types.ts
CHANGED
|
@@ -327,6 +327,10 @@ export const decodeArray: DecodeOperation = function (
|
|
|
327
327
|
(ref as ArraySchema).clear();
|
|
328
328
|
return;
|
|
329
329
|
|
|
330
|
+
} else if (operation === OPERATION.REVERSE) {
|
|
331
|
+
(ref as ArraySchema).reverse();
|
|
332
|
+
return;
|
|
333
|
+
|
|
330
334
|
} else if (operation === OPERATION.DELETE_BY_REFID) {
|
|
331
335
|
// TODO: refactor here, try to follow same flow as below
|
|
332
336
|
const refId = decode.number(bytes, it);
|
|
@@ -4,8 +4,8 @@ import { Ref } from "../../encoder/ChangeTree";
|
|
|
4
4
|
import { Decoder } from "../Decoder";
|
|
5
5
|
import { DataChange } from "../DecodeOperation";
|
|
6
6
|
import { OPERATION } from "../../encoding/spec";
|
|
7
|
-
import { DefinitionType } from "../../annotations";
|
|
8
7
|
import { Schema } from "../../Schema";
|
|
8
|
+
import type { DefinitionType } from "../../annotations";
|
|
9
9
|
import type { CollectionSchema } from "../../types/custom/CollectionSchema";
|
|
10
10
|
|
|
11
11
|
//
|
|
@@ -79,7 +79,6 @@ export const encodeSchemaOperation: EncodeOperation = function (
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const ref = changeTree.ref;
|
|
82
|
-
// const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
83
82
|
const field = metadata[index];
|
|
84
83
|
|
|
85
84
|
// TODO: inline this function call small performance gain
|
|
@@ -200,7 +199,10 @@ export const encodeArray: EncodeOperation = function (
|
|
|
200
199
|
bytes[it.offset++] = operation & 255;
|
|
201
200
|
|
|
202
201
|
// custom operations
|
|
203
|
-
if (
|
|
202
|
+
if (
|
|
203
|
+
operation === OPERATION.CLEAR ||
|
|
204
|
+
operation === OPERATION.REVERSE
|
|
205
|
+
) {
|
|
204
206
|
return;
|
|
205
207
|
}
|
|
206
208
|
|