@colyseus/schema 2.0.31 → 3.0.0-alpha.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.
Files changed (159) hide show
  1. package/build/cjs/index.js +3614 -2634
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +3324 -2445
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +3614 -2634
  6. package/lib/Decoder.d.ts +16 -0
  7. package/lib/Decoder.js +182 -0
  8. package/lib/Decoder.js.map +1 -0
  9. package/lib/Encoder.d.ts +13 -0
  10. package/lib/Encoder.js +79 -0
  11. package/lib/Encoder.js.map +1 -0
  12. package/lib/Metadata.d.ts +36 -0
  13. package/lib/Metadata.js +91 -0
  14. package/lib/Metadata.js.map +1 -0
  15. package/lib/Reflection.d.ts +7 -5
  16. package/lib/Reflection.js +62 -58
  17. package/lib/Reflection.js.map +1 -1
  18. package/lib/Schema.d.ts +39 -51
  19. package/lib/Schema.js +189 -731
  20. package/lib/Schema.js.map +1 -1
  21. package/lib/annotations.d.ts +26 -45
  22. package/lib/annotations.js +363 -194
  23. package/lib/annotations.js.map +1 -1
  24. package/lib/changes/ChangeSet.d.ts +12 -0
  25. package/lib/changes/ChangeSet.js +35 -0
  26. package/lib/changes/ChangeSet.js.map +1 -0
  27. package/lib/changes/DecodeOperation.d.ts +15 -0
  28. package/lib/changes/DecodeOperation.js +186 -0
  29. package/lib/changes/DecodeOperation.js.map +1 -0
  30. package/lib/changes/EncodeOperation.d.ts +18 -0
  31. package/lib/changes/EncodeOperation.js +130 -0
  32. package/lib/changes/EncodeOperation.js.map +1 -0
  33. package/lib/changes/consts.d.ts +14 -0
  34. package/lib/changes/consts.js +18 -0
  35. package/lib/changes/consts.js.map +1 -0
  36. package/lib/decoder/DecodeOperation.d.ts +24 -0
  37. package/lib/decoder/DecodeOperation.js +256 -0
  38. package/lib/decoder/DecodeOperation.js.map +1 -0
  39. package/lib/decoder/Decoder.d.ts +21 -0
  40. package/lib/decoder/Decoder.js +114 -0
  41. package/lib/decoder/Decoder.js.map +1 -0
  42. package/lib/decoder/ReferenceTracker.d.ts +26 -0
  43. package/lib/decoder/ReferenceTracker.js +131 -0
  44. package/lib/decoder/ReferenceTracker.js.map +1 -0
  45. package/lib/decoder/strategy/RawChanges.d.ts +3 -0
  46. package/lib/decoder/strategy/RawChanges.js +8 -0
  47. package/lib/decoder/strategy/RawChanges.js.map +1 -0
  48. package/lib/decoder/strategy/StateCallbacks.d.ts +20 -0
  49. package/lib/decoder/strategy/StateCallbacks.js +240 -0
  50. package/lib/decoder/strategy/StateCallbacks.js.map +1 -0
  51. package/lib/decoding/decode.d.ts +48 -0
  52. package/lib/decoding/decode.js +267 -0
  53. package/lib/decoding/decode.js.map +1 -0
  54. package/lib/ecs.d.ts +11 -0
  55. package/lib/ecs.js +160 -0
  56. package/lib/ecs.js.map +1 -0
  57. package/lib/encoder/ChangeTree.d.ts +72 -0
  58. package/lib/encoder/ChangeTree.js +384 -0
  59. package/lib/encoder/ChangeTree.js.map +1 -0
  60. package/lib/encoder/EncodeOperation.d.ts +25 -0
  61. package/lib/encoder/EncodeOperation.js +156 -0
  62. package/lib/encoder/EncodeOperation.js.map +1 -0
  63. package/lib/encoder/Encoder.d.ts +23 -0
  64. package/lib/encoder/Encoder.js +192 -0
  65. package/lib/encoder/Encoder.js.map +1 -0
  66. package/lib/encoder/StateView.d.ts +21 -0
  67. package/lib/encoder/StateView.js +196 -0
  68. package/lib/encoder/StateView.js.map +1 -0
  69. package/lib/encoding/assert.d.ts +9 -0
  70. package/lib/encoding/assert.js +47 -0
  71. package/lib/encoding/assert.js.map +1 -0
  72. package/lib/encoding/decode.js +1 -1
  73. package/lib/encoding/decode.js.map +1 -1
  74. package/lib/encoding/encode.d.ts +17 -16
  75. package/lib/encoding/encode.js +88 -81
  76. package/lib/encoding/encode.js.map +1 -1
  77. package/lib/encoding/spec.d.ts +25 -0
  78. package/lib/encoding/spec.js +30 -0
  79. package/lib/encoding/spec.js.map +1 -0
  80. package/lib/index.d.ts +18 -10
  81. package/lib/index.js +39 -17
  82. package/lib/index.js.map +1 -1
  83. package/lib/symbol.shim.d.ts +6 -0
  84. package/lib/symbol.shim.js +4 -0
  85. package/lib/symbol.shim.js.map +1 -0
  86. package/lib/types/ArraySchema.js +0 -7
  87. package/lib/types/ArraySchema.js.map +1 -1
  88. package/lib/types/HelperTypes.d.ts +10 -2
  89. package/lib/types/HelperTypes.js.map +1 -1
  90. package/lib/types/custom/ArraySchema.d.ts +245 -0
  91. package/lib/types/custom/ArraySchema.js +659 -0
  92. package/lib/types/custom/ArraySchema.js.map +1 -0
  93. package/lib/types/custom/CollectionSchema.d.ts +42 -0
  94. package/lib/types/custom/CollectionSchema.js +165 -0
  95. package/lib/types/custom/CollectionSchema.js.map +1 -0
  96. package/lib/types/custom/MapSchema.d.ts +43 -0
  97. package/lib/types/custom/MapSchema.js +200 -0
  98. package/lib/types/custom/MapSchema.js.map +1 -0
  99. package/lib/types/custom/SetSchema.d.ts +39 -0
  100. package/lib/types/custom/SetSchema.js +177 -0
  101. package/lib/types/custom/SetSchema.js.map +1 -0
  102. package/lib/types/registry.d.ts +6 -0
  103. package/lib/types/registry.js +19 -0
  104. package/lib/types/registry.js.map +1 -0
  105. package/lib/types/symbols.d.ts +29 -0
  106. package/lib/types/symbols.js +33 -0
  107. package/lib/types/symbols.js.map +1 -0
  108. package/lib/types/utils.d.ts +0 -8
  109. package/lib/types/utils.js +1 -33
  110. package/lib/types/utils.js.map +1 -1
  111. package/lib/usage.d.ts +1 -0
  112. package/lib/usage.js +22 -0
  113. package/lib/usage.js.map +1 -0
  114. package/lib/utils.d.ts +13 -2
  115. package/lib/utils.js +36 -15
  116. package/lib/utils.js.map +1 -1
  117. package/lib/v3.d.ts +1 -0
  118. package/lib/v3.js +427 -0
  119. package/lib/v3.js.map +1 -0
  120. package/lib/v3_bench.d.ts +1 -0
  121. package/lib/v3_bench.js +130 -0
  122. package/lib/v3_bench.js.map +1 -0
  123. package/lib/v3_experiment.d.ts +1 -0
  124. package/lib/v3_experiment.js +407 -0
  125. package/lib/v3_experiment.js.map +1 -0
  126. package/package.json +5 -5
  127. package/src/Metadata.ts +135 -0
  128. package/src/Reflection.ts +75 -66
  129. package/src/Schema.ts +213 -931
  130. package/src/annotations.ts +430 -243
  131. package/src/decoder/DecodeOperation.ts +372 -0
  132. package/src/decoder/Decoder.ts +155 -0
  133. package/src/decoder/ReferenceTracker.ts +151 -0
  134. package/src/decoder/strategy/RawChanges.ts +9 -0
  135. package/src/decoder/strategy/StateCallbacks.ts +326 -0
  136. package/src/encoder/ChangeTree.ts +492 -0
  137. package/src/encoder/EncodeOperation.ts +237 -0
  138. package/src/encoder/Encoder.ts +246 -0
  139. package/src/encoder/StateView.ts +229 -0
  140. package/src/encoding/assert.ts +58 -0
  141. package/src/encoding/decode.ts +1 -1
  142. package/src/encoding/encode.ts +88 -82
  143. package/src/encoding/spec.ts +29 -0
  144. package/src/index.ts +22 -19
  145. package/src/symbol.shim.ts +12 -0
  146. package/src/types/HelperTypes.ts +16 -2
  147. package/src/types/{ArraySchema.ts → custom/ArraySchema.ts} +345 -251
  148. package/src/types/{CollectionSchema.ts → custom/CollectionSchema.ts} +56 -46
  149. package/src/types/{MapSchema.ts → custom/MapSchema.ts} +88 -115
  150. package/src/types/{SetSchema.ts → custom/SetSchema.ts} +58 -47
  151. package/src/types/{typeRegistry.ts → registry.ts} +6 -6
  152. package/src/types/symbols.ts +36 -0
  153. package/src/types/utils.ts +0 -46
  154. package/src/utils.ts +50 -21
  155. package/src/v3_bench.ts +107 -0
  156. package/src/changes/ChangeTree.ts +0 -295
  157. package/src/changes/ReferenceTracker.ts +0 -91
  158. package/src/filters/index.ts +0 -23
  159. package/src/spec.ts +0 -49
@@ -0,0 +1,16 @@
1
+ import { TypeContext } from "./annotations";
2
+ import { DataChange, Schema } from "./Schema";
3
+ import { Ref } from "./changes/ChangeTree";
4
+ import { Iterator } from "./encoding/decode";
5
+ import { ReferenceTracker } from "./changes/ReferenceTracker";
6
+ export declare class Decoder<T extends Schema = any> {
7
+ context: TypeContext;
8
+ root: T;
9
+ refs: ReferenceTracker;
10
+ currentRefId: number;
11
+ constructor(root: T, context?: TypeContext);
12
+ protected setRoot(root: T): void;
13
+ decode(bytes: number[], it?: Iterator, ref?: Ref): DataChange<any, string>[];
14
+ getInstanceType(bytes: number[], it: Iterator, defaultType: typeof Schema): typeof Schema;
15
+ createInstanceOfType(type: typeof Schema): Schema;
16
+ }
package/lib/Decoder.js ADDED
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Decoder = void 0;
4
+ const annotations_1 = require("./annotations");
5
+ const consts_1 = require("./changes/consts");
6
+ const decode = require("./encoding/decode");
7
+ const spec_1 = require("./spec");
8
+ const ReferenceTracker_1 = require("./changes/ReferenceTracker");
9
+ const DecodeOperation_1 = require("./changes/DecodeOperation");
10
+ class Decoder {
11
+ constructor(root, context) {
12
+ this.currentRefId = 0;
13
+ this.setRoot(root);
14
+ this.context = context || new annotations_1.TypeContext(root.constructor);
15
+ // console.log(">>>>>>>>>>>>>>>> Decoder types");
16
+ // this.context.schemas.forEach((id, schema) => {
17
+ // console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
18
+ // });
19
+ }
20
+ setRoot(root) {
21
+ this.root = root;
22
+ this.refs = new ReferenceTracker_1.ReferenceTracker();
23
+ this.refs.addRef(0, root);
24
+ }
25
+ decode(bytes, it = { offset: 0 }, ref = this.root) {
26
+ // console.log("------------------- DECODE -------------------");
27
+ const allChanges = [];
28
+ const $root = this.refs;
29
+ const totalBytes = bytes.length;
30
+ this.currentRefId = 0;
31
+ while (it.offset < totalBytes) {
32
+ //
33
+ // Peek ahead, check if it's a switch to a different structure
34
+ //
35
+ if (bytes[it.offset] == spec_1.SWITCH_TO_STRUCTURE) {
36
+ it.offset++;
37
+ this.currentRefId = decode.number(bytes, it);
38
+ const nextRef = $root.refs.get(this.currentRefId);
39
+ //
40
+ // Trying to access a reference that haven't been decoded yet.
41
+ //
42
+ if (!nextRef) {
43
+ throw new Error(`"refId" not found: ${this.currentRefId}`);
44
+ }
45
+ ref = nextRef;
46
+ continue;
47
+ }
48
+ const decoder = ref['constructor'][consts_1.$decoder];
49
+ const result = decoder(this, bytes, it, ref, allChanges);
50
+ if (result === DecodeOperation_1.DecodeState.DEFINITION_MISMATCH) {
51
+ console.warn("@colyseus/schema: definition mismatch");
52
+ //
53
+ // keep skipping next bytes until reaches a known structure
54
+ // by local decoder.
55
+ //
56
+ const nextIterator = { offset: it.offset };
57
+ while (it.offset < totalBytes) {
58
+ if (decode.switchStructureCheck(bytes, it)) {
59
+ nextIterator.offset = it.offset + 1;
60
+ if ($root.refs.has(decode.number(bytes, nextIterator))) {
61
+ break;
62
+ }
63
+ }
64
+ it.offset++;
65
+ }
66
+ continue;
67
+ }
68
+ }
69
+ // FIXME: trigger callbacks
70
+ // this._triggerChanges(allChanges);
71
+ // drop references of unused schemas
72
+ $root.garbageCollectDeletedRefs();
73
+ return allChanges;
74
+ }
75
+ /*
76
+ private _triggerChanges(changes: DataChange[]) {
77
+ const uniqueRefIds = new Set<number>();
78
+ const $refs = this.refs.refs;
79
+
80
+ for (let i = 0; i < changes.length; i++) {
81
+ const change = changes[i];
82
+ const refId = change.refId;
83
+ const ref = $refs.get(refId);
84
+ const $callbacks: Schema['$callbacks'] | SchemaDecoderCallbacks['$callbacks'] = ref['$callbacks'];
85
+
86
+ //
87
+ // trigger onRemove on child structure.
88
+ //
89
+ if (
90
+ (change.op & OPERATION.DELETE) === OPERATION.DELETE &&
91
+ change.previousValue instanceof Schema
92
+ ) {
93
+ change.previousValue['$callbacks']?.[OPERATION.DELETE]?.forEach(callback => callback());
94
+ }
95
+
96
+ // no callbacks defined, skip this structure!
97
+ if (!$callbacks) { continue; }
98
+
99
+ if (ref instanceof Schema) {
100
+ if (!uniqueRefIds.has(refId)) {
101
+ try {
102
+ // trigger onChange
103
+ ($callbacks as Schema['$callbacks'])?.[OPERATION.REPLACE]?.forEach(callback =>
104
+ callback());
105
+
106
+ } catch (e) {
107
+ Schema.onError(e);
108
+ }
109
+ }
110
+
111
+ try {
112
+ if ($callbacks.hasOwnProperty(change.field)) {
113
+ $callbacks[change.field]?.forEach((callback) =>
114
+ callback(change.value, change.previousValue));
115
+ }
116
+
117
+ } catch (e) {
118
+ Schema.onError(e);
119
+ }
120
+
121
+ } else {
122
+ // is a collection of items
123
+
124
+ if (change.op === OPERATION.ADD && change.previousValue === undefined) {
125
+ // triger onAdd
126
+ $callbacks[OPERATION.ADD]?.forEach(callback =>
127
+ callback(change.value, change.dynamicIndex ?? change.field));
128
+
129
+ } else if (change.op === OPERATION.DELETE) {
130
+ //
131
+ // FIXME: `previousValue` should always be available.
132
+ // ADD + DELETE operations are still encoding DELETE operation.
133
+ //
134
+ if (change.previousValue !== undefined) {
135
+ // triger onRemove
136
+ $callbacks[OPERATION.DELETE]?.forEach(callback =>
137
+ callback(change.previousValue, change.dynamicIndex ?? change.field));
138
+ }
139
+
140
+ } else if (change.op === OPERATION.DELETE_AND_ADD) {
141
+ // triger onRemove
142
+ if (change.previousValue !== undefined) {
143
+ $callbacks[OPERATION.DELETE]?.forEach(callback =>
144
+ callback(change.previousValue, change.dynamicIndex ?? change.field));
145
+ }
146
+
147
+ // triger onAdd
148
+ $callbacks[OPERATION.ADD]?.forEach(callback =>
149
+ callback(change.value, change.dynamicIndex ?? change.field));
150
+ }
151
+
152
+ // trigger onChange
153
+ if (change.value !== change.previousValue) {
154
+ $callbacks[OPERATION.REPLACE]?.forEach(callback =>
155
+ callback(change.value, change.dynamicIndex ?? change.field));
156
+ }
157
+ }
158
+
159
+ uniqueRefIds.add(refId);
160
+ }
161
+
162
+ }
163
+ */
164
+ getInstanceType(bytes, it, defaultType) {
165
+ let type;
166
+ if (bytes[it.offset] === spec_1.TYPE_ID) {
167
+ it.offset++;
168
+ const type_id = decode.number(bytes, it);
169
+ type = this.context.get(type_id);
170
+ }
171
+ return type || defaultType;
172
+ }
173
+ createInstanceOfType(type) {
174
+ // let instance: Schema = new (type as any)();
175
+ // // assign root on $changes
176
+ // instance[$changes].root = this.root[$changes].root;
177
+ // return instance;
178
+ return new type();
179
+ }
180
+ }
181
+ exports.Decoder = Decoder;
182
+ //# sourceMappingURL=Decoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../src/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"./Metadata\";\nimport { TypeContext } from \"./annotations\";\nimport { $childType, $decoder } from \"./changes/consts\";\nimport { DataChange, Schema, SchemaDecoderCallbacks } from \"./Schema\";\nimport { CollectionSchema } from \"./types/CollectionSchema\";\nimport { MapSchema } from \"./types/MapSchema\";\nimport { SetSchema } from \"./types/SetSchema\";\nimport { ArraySchema } from \"./types/ArraySchema\";\n\nimport * as decode from \"./encoding/decode\";\nimport { getType } from './types/typeRegistry';\nimport { SWITCH_TO_STRUCTURE, TYPE_ID, OPERATION } from './spec';\nimport { Ref } from \"./changes/ChangeTree\";\nimport { Iterator } from \"./encoding/decode\";\nimport { ReferenceTracker } from \"./changes/ReferenceTracker\";\nimport { DecodeState } from \"./changes/DecodeOperation\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n root: T;\n refs: ReferenceTracker;\n\n currentRefId: number = 0;\n\n constructor(root: T, context?: TypeContext) {\n this.setRoot(root);\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(root: T) {\n this.root = root;\n this.refs = new ReferenceTracker();\n this.refs.addRef(0, root);\n }\n\n decode(\n bytes: number[],\n it: Iterator = { offset: 0 },\n ref: Ref = this.root,\n ) {\n // console.log(\"------------------- DECODE -------------------\");\n const allChanges: DataChange[] = [];\n\n const $root = this.refs;\n const totalBytes = bytes.length;\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref = nextRef;\n\n continue;\n }\n\n const decoder = ref['constructor'][$decoder];\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DecodeState.DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: decode.Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (decode.switchStructureCheck(bytes, it)) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: trigger callbacks\n // this._triggerChanges(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n /*\n private _triggerChanges(changes: DataChange[]) {\n const uniqueRefIds = new Set<number>();\n const $refs = this.refs.refs;\n\n for (let i = 0; i < changes.length; i++) {\n const change = changes[i];\n const refId = change.refId;\n const ref = $refs.get(refId);\n const $callbacks: Schema['$callbacks'] | SchemaDecoderCallbacks['$callbacks'] = ref['$callbacks'];\n\n //\n // trigger onRemove on child structure.\n //\n if (\n (change.op & OPERATION.DELETE) === OPERATION.DELETE &&\n change.previousValue instanceof Schema\n ) {\n change.previousValue['$callbacks']?.[OPERATION.DELETE]?.forEach(callback => callback());\n }\n\n // no callbacks defined, skip this structure!\n if (!$callbacks) { continue; }\n\n if (ref instanceof Schema) {\n if (!uniqueRefIds.has(refId)) {\n try {\n // trigger onChange\n ($callbacks as Schema['$callbacks'])?.[OPERATION.REPLACE]?.forEach(callback =>\n callback());\n\n } catch (e) {\n Schema.onError(e);\n }\n }\n\n try {\n if ($callbacks.hasOwnProperty(change.field)) {\n $callbacks[change.field]?.forEach((callback) =>\n callback(change.value, change.previousValue));\n }\n\n } catch (e) {\n Schema.onError(e);\n }\n\n } else {\n // is a collection of items\n\n if (change.op === OPERATION.ADD && change.previousValue === undefined) {\n // triger onAdd\n $callbacks[OPERATION.ADD]?.forEach(callback =>\n callback(change.value, change.dynamicIndex ?? change.field));\n\n } else if (change.op === OPERATION.DELETE) {\n //\n // FIXME: `previousValue` should always be available.\n // ADD + DELETE operations are still encoding DELETE operation.\n //\n if (change.previousValue !== undefined) {\n // triger onRemove\n $callbacks[OPERATION.DELETE]?.forEach(callback =>\n callback(change.previousValue, change.dynamicIndex ?? change.field));\n }\n\n } else if (change.op === OPERATION.DELETE_AND_ADD) {\n // triger onRemove\n if (change.previousValue !== undefined) {\n $callbacks[OPERATION.DELETE]?.forEach(callback =>\n callback(change.previousValue, change.dynamicIndex ?? change.field));\n }\n\n // triger onAdd\n $callbacks[OPERATION.ADD]?.forEach(callback =>\n callback(change.value, change.dynamicIndex ?? change.field));\n }\n\n // trigger onChange\n if (change.value !== change.previousValue) {\n $callbacks[OPERATION.REPLACE]?.forEach(callback =>\n callback(change.value, change.dynamicIndex ?? change.field));\n }\n }\n\n uniqueRefIds.add(refId);\n }\n\n }\n */\n\n getInstanceType(bytes: number[], it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n}\n\n"]}
@@ -0,0 +1,13 @@
1
+ import type { Schema } from "./Schema";
2
+ import { TypeContext } from "./annotations";
3
+ import { Root } from "./changes/ChangeTree";
4
+ export declare class Encoder<T extends Schema = any> {
5
+ context: TypeContext;
6
+ root: T;
7
+ $root: Root;
8
+ constructor(root: T);
9
+ protected setRoot(root: T): void;
10
+ encode(encodeAll?: boolean, bytes?: number[], useFilters?: boolean): number[];
11
+ encodeAll(useFilters?: boolean): number[];
12
+ tryEncodeTypeId(bytes: number[], baseType: typeof Schema, targetType: typeof Schema): void;
13
+ }
package/lib/Encoder.js ADDED
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Encoder = void 0;
4
+ const annotations_1 = require("./annotations");
5
+ const consts_1 = require("./changes/consts");
6
+ const encode = require("./encoding/encode");
7
+ const spec_1 = require("./spec");
8
+ const ChangeTree_1 = require("./changes/ChangeTree");
9
+ class Encoder {
10
+ constructor(root) {
11
+ this.setRoot(root);
12
+ //
13
+ // TODO: cache and restore "Context" based on root schema
14
+ // (to avoid creating a new context for each new room)
15
+ //
16
+ this.context = new annotations_1.TypeContext(root.constructor);
17
+ // console.log(">>>>>>>>>>>>>>>> Encoder types");
18
+ // this.context.schemas.forEach((id, schema) => {
19
+ // console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
20
+ // });
21
+ }
22
+ setRoot(root) {
23
+ this.$root = new ChangeTree_1.Root();
24
+ this.root = root;
25
+ root[consts_1.$changes].setRoot(this.$root);
26
+ }
27
+ encode(encodeAll = false, bytes = [], useFilters = false) {
28
+ const rootChangeTree = this.root[consts_1.$changes];
29
+ // const changeTrees: ChangeTracker[] = Array.from(this.$root['currentQueue']);
30
+ const changeTrees = this.$root.changes;
31
+ const numChangeTrees = changeTrees.length;
32
+ // let numChangeTrees = 1;
33
+ // console.log("--------------------- ENCODE ----------------");
34
+ // console.log("Encode order:", changeTrees.map((c) => c.ref['constructor'].name));
35
+ for (let i = 0; i < numChangeTrees; i++) {
36
+ const changeTree = changeTrees[i];
37
+ const ref = changeTree.ref;
38
+ // Generate unique refId for the ChangeTree.
39
+ changeTree.ensureRefId();
40
+ // root `refId` is skipped.
41
+ if (changeTree !== rootChangeTree &&
42
+ (changeTree.changed || encodeAll)) {
43
+ encode.uint8(bytes, spec_1.SWITCH_TO_STRUCTURE);
44
+ encode.number(bytes, changeTree.refId);
45
+ }
46
+ const changes = (encodeAll)
47
+ ? changeTree.allChanges.values()
48
+ : changeTree.changes.values();
49
+ let change;
50
+ while (!(change = changes.next()).done) {
51
+ const operation = (encodeAll)
52
+ ? spec_1.OPERATION.ADD
53
+ : change.value.op;
54
+ const fieldIndex = (encodeAll)
55
+ ? change.value
56
+ : change.value.index;
57
+ const encoder = ref['constructor'][consts_1.$encoder];
58
+ encoder(this, bytes, changeTree, fieldIndex, operation);
59
+ }
60
+ if (!encodeAll && !useFilters) {
61
+ changeTree.discard();
62
+ }
63
+ }
64
+ return bytes;
65
+ }
66
+ encodeAll(useFilters) {
67
+ return this.encode(true, [], useFilters);
68
+ }
69
+ tryEncodeTypeId(bytes, baseType, targetType) {
70
+ const baseTypeId = this.context.getTypeId(baseType);
71
+ const targetTypeId = this.context.getTypeId(targetType);
72
+ if (baseTypeId !== targetTypeId) {
73
+ encode.uint8(bytes, spec_1.TYPE_ID);
74
+ encode.number(bytes, targetTypeId);
75
+ }
76
+ }
77
+ }
78
+ exports.Encoder = Encoder;
79
+ //# sourceMappingURL=Encoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../src/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"./Schema\";\nimport { TypeContext } from \"./annotations\";\nimport { $changes, $encoder } from \"./changes/consts\";\n\nimport * as encode from \"./encoding/encode\";\nimport { SWITCH_TO_STRUCTURE, TYPE_ID, OPERATION } from './spec';\nimport { ChangeOperation, ChangeTracker, Root } from \"./changes/ChangeTree\";\nimport { encodeKeyValueOperation, encodeSchemaOperation } from \"./changes/EncodeOperation\";\n\nexport class Encoder<T extends Schema = any> {\n context: TypeContext;\n\n root: T;\n $root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for each new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(root: T) {\n this.$root = new Root();\n this.root = root;\n root[$changes].setRoot(this.$root);\n }\n\n encode(\n encodeAll = false,\n bytes: number[] = [],\n useFilters: boolean = false,\n ) {\n const rootChangeTree = this.root[$changes];\n\n // const changeTrees: ChangeTracker[] = Array.from(this.$root['currentQueue']);\n const changeTrees: ChangeTracker[] = this.$root.changes;\n const numChangeTrees = changeTrees.length;\n // let numChangeTrees = 1;\n\n // console.log(\"--------------------- ENCODE ----------------\");\n // console.log(\"Encode order:\", changeTrees.map((c) => c.ref['constructor'].name));\n for (let i = 0; i < numChangeTrees; i++) {\n const changeTree = changeTrees[i];\n const ref = changeTree.ref;\n\n // Generate unique refId for the ChangeTree.\n changeTree.ensureRefId();\n\n // root `refId` is skipped.\n if (\n changeTree !== rootChangeTree &&\n (changeTree.changed || encodeAll)\n ) {\n encode.uint8(bytes, SWITCH_TO_STRUCTURE);\n encode.number(bytes, changeTree.refId);\n }\n\n const changes: IterableIterator<ChangeOperation | number> = (encodeAll)\n ? changeTree.allChanges.values()\n : changeTree.changes.values();\n\n let change: IteratorResult<ChangeOperation | number>;\n while (!(change = changes.next()).done) {\n const operation = (encodeAll)\n ? OPERATION.ADD\n : change.value.op;\n\n const fieldIndex = (encodeAll)\n ? change.value\n : change.value.index;\n\n const encoder = ref['constructor'][$encoder];\n encoder(this, bytes, changeTree, fieldIndex, operation);\n }\n\n if (!encodeAll && !useFilters) {\n changeTree.discard();\n }\n }\n\n return bytes;\n }\n\n encodeAll (useFilters?: boolean) {\n return this.encode(true, [], useFilters);\n }\n\n tryEncodeTypeId (bytes: number[], baseType: typeof Schema, targetType: typeof Schema) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (baseTypeId !== targetTypeId) {\n encode.uint8(bytes, TYPE_ID);\n encode.number(bytes, targetTypeId);\n }\n }\n\n}"]}
@@ -0,0 +1,36 @@
1
+ import { type DefinitionType } from "./annotations";
2
+ export type MetadataField = {
3
+ type: DefinitionType;
4
+ index: number;
5
+ tag?: number;
6
+ unreliable?: boolean;
7
+ deprecated?: boolean;
8
+ descriptor?: PropertyDescriptor;
9
+ };
10
+ export type Metadata = {
11
+ [-1]: number;
12
+ } & // number of fields
13
+ {
14
+ [-2]: number[];
15
+ } & // all field indexes with "view" tag
16
+ {
17
+ [-3]: {
18
+ [tag: number]: number[];
19
+ };
20
+ } & // field indexes by "view" tag
21
+ {
22
+ [field: number]: string;
23
+ } & // index => field name
24
+ {
25
+ [field: string]: MetadataField;
26
+ };
27
+ export declare const Metadata: {
28
+ addField(metadata: any, index: number, field: string, type: DefinitionType, descriptor?: PropertyDescriptor): void;
29
+ setTag(metadata: Metadata, fieldName: string, tag: number): void;
30
+ setFields(target: any, fields: {
31
+ [field: string]: DefinitionType;
32
+ }): void;
33
+ isDeprecated(metadata: any, field: string): boolean;
34
+ isValidInstance(klass: any): boolean;
35
+ getFields(klass: any): {};
36
+ };
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Metadata = void 0;
4
+ const annotations_1 = require("./annotations");
5
+ const registry_1 = require("./types/registry");
6
+ exports.Metadata = {
7
+ addField(metadata, index, field, type, descriptor) {
8
+ if (index > 64) {
9
+ throw new Error(`Can't define field '${field}'.\nSchema instances may only have up to 64 fields.`);
10
+ }
11
+ metadata[field] = Object.assign(metadata[field] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
12
+ {
13
+ type: (Array.isArray(type))
14
+ ? { array: type[0] }
15
+ : type,
16
+ index,
17
+ descriptor,
18
+ });
19
+ // map -1 as last field index
20
+ Object.defineProperty(metadata, -1, {
21
+ value: index,
22
+ enumerable: false,
23
+ configurable: true
24
+ });
25
+ // map index => field name (non enumerable)
26
+ Object.defineProperty(metadata, index, {
27
+ value: field,
28
+ enumerable: false,
29
+ configurable: true,
30
+ });
31
+ },
32
+ setTag(metadata, fieldName, tag) {
33
+ // add 'tag' to the field
34
+ const field = metadata[fieldName];
35
+ field.tag = tag;
36
+ if (!metadata[-2]) {
37
+ // -2: all field indexes with "view" tag
38
+ Object.defineProperty(metadata, -2, {
39
+ value: [],
40
+ enumerable: false,
41
+ configurable: true
42
+ });
43
+ // -3: field indexes by "view" tag
44
+ Object.defineProperty(metadata, -3, {
45
+ value: {},
46
+ enumerable: false,
47
+ configurable: true
48
+ });
49
+ }
50
+ metadata[-2].push(field.index);
51
+ if (!metadata[-3][tag]) {
52
+ metadata[-3][tag] = [];
53
+ }
54
+ metadata[-3][tag].push(field.index);
55
+ },
56
+ setFields(target, fields) {
57
+ const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});
58
+ // target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {
59
+ // changeTree.change(index, operation, encodeSchemaOperation);
60
+ // };
61
+ // target[$encoder] = encodeSchemaOperation;
62
+ // target[$decoder] = decodeSchemaOperation;
63
+ // if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }
64
+ let index = 0;
65
+ for (const field in fields) {
66
+ const type = fields[field];
67
+ // FIXME: this code is duplicated from @type() annotation
68
+ const complexTypeKlass = (Array.isArray(type))
69
+ ? (0, registry_1.getType)("array")
70
+ : (typeof (Object.keys(type)[0]) === "string") && (0, registry_1.getType)(Object.keys(type)[0]);
71
+ exports.Metadata.addField(metadata, index, field, type, (0, annotations_1.getPropertyDescriptor)(`_${field}`, index, type, complexTypeKlass, metadata, field));
72
+ index++;
73
+ }
74
+ },
75
+ isDeprecated(metadata, field) {
76
+ return metadata[field].deprecated === true;
77
+ },
78
+ isValidInstance(klass) {
79
+ return (klass.constructor[Symbol.metadata] &&
80
+ Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1));
81
+ },
82
+ getFields(klass) {
83
+ const metadata = klass[Symbol.metadata];
84
+ const fields = {};
85
+ for (let i = 0; i <= metadata[-1]; i++) {
86
+ fields[metadata[i]] = metadata[metadata[i]].type;
87
+ }
88
+ return fields;
89
+ }
90
+ };
91
+ //# sourceMappingURL=Metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Metadata.js","sourceRoot":"","sources":["../src/Metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPropertyDescriptor, type DefinitionType } from \"./annotations\";\nimport { getType } from \"./types/registry\";\n\nexport type MetadataField = {\n type: DefinitionType,\n index: number,\n tag?: number,\n unreliable?: boolean,\n deprecated?: boolean,\n descriptor?: PropertyDescriptor,\n};\n\nexport type Metadata =\n { [-1]: number; } & // number of fields\n { [-2]: number[]; } & // all field indexes with \"view\" tag\n { [-3]: {[tag: number]: number[]}; } & // field indexes by \"view\" tag\n { [field: number]: string; } & // index => field name\n { [field: string]: MetadataField; } // field name => field metadata\n\nexport const Metadata = {\n\n addField(metadata: any, index: number, field: string, type: DefinitionType, descriptor?: PropertyDescriptor) {\n if (index > 64) {\n throw new Error(`Can't define field '${field}'.\\nSchema instances may only have up to 64 fields.`);\n }\n\n metadata[field] = Object.assign(\n metadata[field] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)\n {\n type: (Array.isArray(type))\n ? { array: type[0] }\n : type,\n index,\n descriptor,\n }\n );\n\n // map -1 as last field index\n Object.defineProperty(metadata, -1, {\n value: index,\n enumerable: false,\n configurable: true\n });\n\n // map index => field name (non enumerable)\n Object.defineProperty(metadata, index, {\n value: field,\n enumerable: false,\n configurable: true,\n });\n },\n\n setTag(metadata: Metadata, fieldName: string, tag: number) {\n // add 'tag' to the field\n const field = metadata[fieldName];\n field.tag = tag;\n\n if (!metadata[-2]) {\n // -2: all field indexes with \"view\" tag\n Object.defineProperty(metadata, -2, {\n value: [],\n enumerable: false,\n configurable: true\n });\n\n // -3: field indexes by \"view\" tag\n Object.defineProperty(metadata, -3, {\n value: {},\n enumerable: false,\n configurable: true\n });\n }\n\n metadata[-2].push(field.index);\n\n if (!metadata[-3][tag]) {\n metadata[-3][tag] = [];\n }\n\n metadata[-3][tag].push(field.index);\n },\n\n setFields(target: any, fields: { [field: string]: DefinitionType }) {\n const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});\n\n // target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {\n // changeTree.change(index, operation, encodeSchemaOperation);\n // };\n\n // target[$encoder] = encodeSchemaOperation;\n // target[$decoder] = decodeSchemaOperation;\n\n // if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }\n\n let index = 0;\n for (const field in fields) {\n const type = fields[field];\n\n // FIXME: this code is duplicated from @type() annotation\n const complexTypeKlass = (Array.isArray(type))\n ? getType(\"array\")\n : (typeof(Object.keys(type)[0]) === \"string\") && getType(Object.keys(type)[0]);\n\n Metadata.addField(\n metadata,\n index,\n field,\n type,\n getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass, metadata, field)\n );\n\n index++;\n }\n },\n\n isDeprecated(metadata: any, field: string) {\n return metadata[field].deprecated === true;\n },\n\n isValidInstance(klass: any) {\n return (\n klass.constructor[Symbol.metadata] &&\n Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1) as boolean\n );\n },\n\n getFields(klass: any) {\n const metadata = klass[Symbol.metadata];\n const fields = {};\n for (let i = 0; i <= metadata[-1]; i++) {\n fields[metadata[i]] = metadata[metadata[i]].type;\n }\n return fields;\n }\n}"]}
@@ -1,6 +1,8 @@
1
- import { Schema } from "./Schema";
2
- import { ArraySchema } from "./types/ArraySchema";
1
+ /// <reference types="node" />
2
+ import { TypeContext } from "./annotations";
3
+ import { ArraySchema } from "./types/custom/ArraySchema";
3
4
  import { Iterator } from "./encoding/decode";
5
+ import { Schema } from "./Schema";
4
6
  /**
5
7
  * Reflection
6
8
  */
@@ -11,11 +13,11 @@ export declare class ReflectionField extends Schema {
11
13
  }
12
14
  export declare class ReflectionType extends Schema {
13
15
  id: number;
16
+ extendsId: number;
14
17
  fields: ArraySchema<ReflectionField>;
15
18
  }
16
19
  export declare class Reflection extends Schema {
17
20
  types: ArraySchema<ReflectionType>;
18
- rootType: number;
19
- static encode(instance: Schema): number[];
20
- static decode<T extends Schema = Schema>(bytes: number[], it?: Iterator): T;
21
+ static encode(instance: Schema, context?: TypeContext): Buffer;
22
+ static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): T;
21
23
  }