@colyseus/schema 3.0.0-alpha.8 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -62
- package/bin/schema-debug +94 -0
- package/build/cjs/index.js +2227 -1519
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2228 -1522
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2230 -1522
- package/lib/Metadata.d.ts +21 -9
- package/lib/Metadata.js +169 -32
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +19 -4
- package/lib/Reflection.js +66 -31
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +12 -5
- package/lib/Schema.js +57 -56
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +31 -34
- package/lib/annotations.js +110 -160
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.d.ts +1 -0
- package/lib/bench_encode.js +130 -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 +9 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +4 -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 +23 -25
- 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 +85 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +6 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/debug.d.ts +1 -0
- package/lib/debug.js +51 -0
- package/lib/debug.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +3 -4
- package/lib/decoder/DecodeOperation.js +35 -17
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +5 -6
- package/lib/decoder/Decoder.js +10 -10
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +4 -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 +74 -64
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +28 -20
- package/lib/encoder/ChangeTree.js +242 -188
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +3 -6
- package/lib/encoder/EncodeOperation.js +51 -65
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +8 -7
- package/lib/encoder/Encoder.js +133 -85
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +22 -0
- package/lib/encoder/Root.js +81 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +7 -7
- package/lib/encoder/StateView.js +72 -74
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +7 -6
- package/lib/encoding/assert.js +13 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.d.ts +36 -19
- package/lib/encoding/decode.js +54 -84
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -18
- package/lib/encoding/encode.js +61 -48
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +4 -5
- package/lib/encoding/spec.js +1 -2
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +10 -9
- package/lib/index.js +24 -17
- 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.d.ts +29 -0
- package/lib/types/TypeContext.js +151 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +33 -22
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -2
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +18 -16
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -2
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.d.ts +8 -1
- package/lib/types/registry.js +23 -6
- package/lib/types/registry.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -5
- package/lib/types/symbols.js +9 -6
- 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 +9 -7
- package/lib/utils.js.map +1 -1
- package/package.json +19 -18
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +76 -38
- package/src/Schema.ts +72 -70
- package/src/annotations.ts +156 -202
- package/src/bench_encode.ts +108 -0
- package/src/codegen/languages/csharp.ts +8 -47
- package/src/codegen/languages/haxe.ts +4 -0
- package/src/codegen/languages/lua.ts +19 -27
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/debug.ts +55 -0
- package/src/decoder/DecodeOperation.ts +43 -15
- package/src/decoder/Decoder.ts +12 -10
- package/src/decoder/ReferenceTracker.ts +5 -3
- package/src/decoder/strategy/StateCallbacks.ts +152 -81
- package/src/encoder/ChangeTree.ts +282 -209
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +157 -93
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +80 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +73 -93
- package/src/encoding/encode.ts +76 -45
- package/src/encoding/spec.ts +3 -5
- package/src/index.ts +12 -20
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +175 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +30 -17
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/registry.ts +22 -3
- package/src/types/symbols.ts +10 -7
- package/src/utils.ts +7 -3
package/src/encoding/encode.ts
CHANGED
|
@@ -35,9 +35,17 @@ let textEncoder: TextEncoder;
|
|
|
35
35
|
// @ts-ignore
|
|
36
36
|
try { textEncoder = new TextEncoder(); } catch (e) { }
|
|
37
37
|
|
|
38
|
+
// force little endian to facilitate decoding on multiple implementations
|
|
39
|
+
const _isLittleEndian = true; // new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
40
|
+
const _convoBuffer = new ArrayBuffer(8);
|
|
41
|
+
const _int32 = new Int32Array(_convoBuffer);
|
|
42
|
+
const _float32 = new Float32Array(_convoBuffer);
|
|
43
|
+
const _float64 = new Float64Array(_convoBuffer);
|
|
44
|
+
const _int64 = new BigInt64Array(_convoBuffer);
|
|
45
|
+
|
|
38
46
|
const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
const utf8Length: (str: string, _?: any) => number = (hasBufferByteLength)
|
|
41
49
|
? Buffer.byteLength // node
|
|
42
50
|
: function (str: string, _?: any) {
|
|
43
51
|
var c = 0, length = 0;
|
|
@@ -60,7 +68,7 @@ export const utf8Length = (hasBufferByteLength)
|
|
|
60
68
|
return length;
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
|
|
71
|
+
function utf8Write(view: BufferLike, str: string, it: Iterator) {
|
|
64
72
|
var c = 0;
|
|
65
73
|
for (var i = 0, l = str.length; i < l; i++) {
|
|
66
74
|
c = str.charCodeAt(i);
|
|
@@ -68,51 +76,54 @@ export function utf8Write(view: BufferLike, str: string, it: Iterator) {
|
|
|
68
76
|
view[it.offset++] = c;
|
|
69
77
|
}
|
|
70
78
|
else if (c < 0x800) {
|
|
71
|
-
view[it.offset
|
|
72
|
-
view[it.offset
|
|
79
|
+
view[it.offset] = 0xc0 | (c >> 6);
|
|
80
|
+
view[it.offset + 1] = 0x80 | (c & 0x3f);
|
|
81
|
+
it.offset += 2;
|
|
73
82
|
}
|
|
74
83
|
else if (c < 0xd800 || c >= 0xe000) {
|
|
75
|
-
view[it.offset
|
|
76
|
-
view[it.offset
|
|
77
|
-
view[it.offset
|
|
84
|
+
view[it.offset] = 0xe0 | (c >> 12);
|
|
85
|
+
view[it.offset+1] = 0x80 | (c >> 6 & 0x3f);
|
|
86
|
+
view[it.offset+2] = 0x80 | (c & 0x3f);
|
|
87
|
+
it.offset += 3;
|
|
78
88
|
}
|
|
79
89
|
else {
|
|
80
90
|
i++;
|
|
81
91
|
c = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
|
|
82
|
-
view[it.offset
|
|
83
|
-
view[it.offset
|
|
84
|
-
view[it.offset
|
|
85
|
-
view[it.offset
|
|
92
|
+
view[it.offset] = 0xf0 | (c >> 18);
|
|
93
|
+
view[it.offset+1] = 0x80 | (c >> 12 & 0x3f);
|
|
94
|
+
view[it.offset+2] = 0x80 | (c >> 6 & 0x3f);
|
|
95
|
+
view[it.offset+3] = 0x80 | (c & 0x3f);
|
|
96
|
+
it.offset += 4;
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
99
|
}
|
|
89
100
|
|
|
90
|
-
|
|
101
|
+
function int8(bytes: BufferLike, value: number, it: Iterator) {
|
|
91
102
|
bytes[it.offset++] = value & 255;
|
|
92
103
|
};
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
function uint8(bytes: BufferLike, value: number, it: Iterator) {
|
|
95
106
|
bytes[it.offset++] = value & 255;
|
|
96
107
|
};
|
|
97
108
|
|
|
98
|
-
|
|
109
|
+
function int16(bytes: BufferLike, value: number, it: Iterator) {
|
|
99
110
|
bytes[it.offset++] = value & 255;
|
|
100
111
|
bytes[it.offset++] = (value >> 8) & 255;
|
|
101
112
|
};
|
|
102
113
|
|
|
103
|
-
|
|
114
|
+
function uint16(bytes: BufferLike, value: number, it: Iterator) {
|
|
104
115
|
bytes[it.offset++] = value & 255;
|
|
105
116
|
bytes[it.offset++] = (value >> 8) & 255;
|
|
106
117
|
};
|
|
107
118
|
|
|
108
|
-
|
|
119
|
+
function int32(bytes: BufferLike, value: number, it: Iterator) {
|
|
109
120
|
bytes[it.offset++] = value & 255;
|
|
110
121
|
bytes[it.offset++] = (value >> 8) & 255;
|
|
111
122
|
bytes[it.offset++] = (value >> 16) & 255;
|
|
112
123
|
bytes[it.offset++] = (value >> 24) & 255;
|
|
113
124
|
};
|
|
114
125
|
|
|
115
|
-
|
|
126
|
+
function uint32(bytes: BufferLike, value: number, it: Iterator) {
|
|
116
127
|
const b4 = value >> 24;
|
|
117
128
|
const b3 = value >> 16;
|
|
118
129
|
const b2 = value >> 8;
|
|
@@ -123,50 +134,48 @@ export function uint32(bytes: BufferLike, value: number, it: Iterator) {
|
|
|
123
134
|
bytes[it.offset++] = b4 & 255;
|
|
124
135
|
};
|
|
125
136
|
|
|
126
|
-
|
|
137
|
+
function int64(bytes: BufferLike, value: number, it: Iterator) {
|
|
127
138
|
const high = Math.floor(value / Math.pow(2, 32));
|
|
128
139
|
const low = value >>> 0;
|
|
129
140
|
uint32(bytes, low, it);
|
|
130
141
|
uint32(bytes, high, it);
|
|
131
142
|
};
|
|
132
143
|
|
|
133
|
-
|
|
144
|
+
function uint64(bytes: BufferLike, value: number, it: Iterator) {
|
|
134
145
|
const high = (value / Math.pow(2, 32)) >> 0;
|
|
135
146
|
const low = value >>> 0;
|
|
136
147
|
uint32(bytes, low, it);
|
|
137
148
|
uint32(bytes, high, it);
|
|
138
149
|
};
|
|
139
150
|
|
|
140
|
-
|
|
141
|
-
|
|
151
|
+
function bigint64(bytes: BufferLike, value: bigint, it: Iterator) {
|
|
152
|
+
_int64[0] = BigInt.asIntN(64, value);
|
|
153
|
+
int32(bytes, _int32[0], it);
|
|
154
|
+
int32(bytes, _int32[1], it);
|
|
142
155
|
}
|
|
143
156
|
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
function biguint64(bytes: BufferLike, value: bigint, it: Iterator) {
|
|
158
|
+
_int64[0] = BigInt.asIntN(64, value);
|
|
159
|
+
int32(bytes, _int32[0], it);
|
|
160
|
+
int32(bytes, _int32[1], it);
|
|
146
161
|
}
|
|
147
162
|
|
|
148
|
-
|
|
149
|
-
const _isLittleEndian = true; // new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
150
|
-
const _int32 = new Int32Array(2);
|
|
151
|
-
const _float32 = new Float32Array(_int32.buffer);
|
|
152
|
-
const _float64 = new Float64Array(_int32.buffer);
|
|
153
|
-
|
|
154
|
-
export function writeFloat32(bytes: BufferLike, value: number, it: Iterator) {
|
|
163
|
+
function float32(bytes: BufferLike, value: number, it: Iterator) {
|
|
155
164
|
_float32[0] = value;
|
|
156
165
|
int32(bytes, _int32[0], it);
|
|
157
|
-
}
|
|
166
|
+
}
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
function float64(bytes: BufferLike, value: number, it: Iterator) {
|
|
160
169
|
_float64[0] = value;
|
|
161
170
|
int32(bytes, _int32[_isLittleEndian ? 0 : 1], it);
|
|
162
171
|
int32(bytes, _int32[_isLittleEndian ? 1 : 0], it);
|
|
163
|
-
}
|
|
172
|
+
}
|
|
164
173
|
|
|
165
|
-
|
|
174
|
+
function boolean(bytes: BufferLike, value: number, it: Iterator) {
|
|
166
175
|
bytes[it.offset++] = value ? 1 : 0; // uint8
|
|
167
176
|
};
|
|
168
177
|
|
|
169
|
-
|
|
178
|
+
function string(bytes: BufferLike, value: string, it: Iterator) {
|
|
170
179
|
// encode `null` strings as empty.
|
|
171
180
|
if (!value) { value = ""; }
|
|
172
181
|
|
|
@@ -204,7 +213,7 @@ export function string(bytes: BufferLike, value: string, it: Iterator) {
|
|
|
204
213
|
return size + length;
|
|
205
214
|
}
|
|
206
215
|
|
|
207
|
-
|
|
216
|
+
function number(bytes: BufferLike, value: number, it: Iterator) {
|
|
208
217
|
if (isNaN(value)) {
|
|
209
218
|
return number(bytes, 0, it);
|
|
210
219
|
|
|
@@ -212,17 +221,19 @@ export function number(bytes: BufferLike, value: number, it: Iterator) {
|
|
|
212
221
|
return number(bytes, (value > 0) ? Number.MAX_SAFE_INTEGER : -Number.MAX_SAFE_INTEGER, it);
|
|
213
222
|
|
|
214
223
|
} else if (value !== (value|0)) {
|
|
224
|
+
if (Math.abs(value) <= 3.4028235e+38) { // range check
|
|
225
|
+
_float32[0] = value;
|
|
226
|
+
if (Math.abs(Math.abs(_float32[0]) - Math.abs(value)) < 1e-4) { // precision check; adjust 1e-n (n = precision) to in-/decrease acceptable precision loss
|
|
227
|
+
// now we know value is in range for f32 and has acceptable precision for f32
|
|
228
|
+
bytes[it.offset++] = 0xca;
|
|
229
|
+
float32(bytes, value, it);
|
|
230
|
+
return 5;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
215
234
|
bytes[it.offset++] = 0xcb;
|
|
216
|
-
|
|
235
|
+
float64(bytes, value, it);
|
|
217
236
|
return 9;
|
|
218
|
-
|
|
219
|
-
// TODO: encode float 32?
|
|
220
|
-
// is it possible to differentiate between float32 / float64 here?
|
|
221
|
-
|
|
222
|
-
// // float 32
|
|
223
|
-
// bytes.push(0xca);
|
|
224
|
-
// writeFloat32(bytes, value);
|
|
225
|
-
// return 5;
|
|
226
237
|
}
|
|
227
238
|
|
|
228
239
|
if (value >= 0) {
|
|
@@ -293,3 +304,23 @@ export function number(bytes: BufferLike, value: number, it: Iterator) {
|
|
|
293
304
|
return 9;
|
|
294
305
|
}
|
|
295
306
|
}
|
|
307
|
+
|
|
308
|
+
export const encode = {
|
|
309
|
+
int8,
|
|
310
|
+
uint8,
|
|
311
|
+
int16,
|
|
312
|
+
uint16,
|
|
313
|
+
int32,
|
|
314
|
+
uint32,
|
|
315
|
+
int64,
|
|
316
|
+
uint64,
|
|
317
|
+
bigint64,
|
|
318
|
+
biguint64,
|
|
319
|
+
float32,
|
|
320
|
+
float64,
|
|
321
|
+
boolean,
|
|
322
|
+
string,
|
|
323
|
+
number,
|
|
324
|
+
utf8Write,
|
|
325
|
+
utf8Length,
|
|
326
|
+
}
|
package/src/encoding/spec.ts
CHANGED
|
@@ -8,8 +8,8 @@ export enum OPERATION {
|
|
|
8
8
|
ADD = 128, // (10000000) add new structure/primitive
|
|
9
9
|
REPLACE = 0, // (00000001) replace structure/primitive
|
|
10
10
|
DELETE = 64, // (01000000) delete field
|
|
11
|
-
DELETE_AND_MOVE = 96, // ()
|
|
12
|
-
MOVE_AND_ADD = 160, // ()
|
|
11
|
+
DELETE_AND_MOVE = 96, // () ArraySchema only
|
|
12
|
+
MOVE_AND_ADD = 160, // () ArraySchema only
|
|
13
13
|
DELETE_AND_ADD = 192, // (11000000) DELETE field, followed by an ADD
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -20,10 +20,8 @@ export enum OPERATION {
|
|
|
20
20
|
/**
|
|
21
21
|
* ArraySchema operations
|
|
22
22
|
*/
|
|
23
|
-
PUSH = 11,
|
|
24
|
-
UNSHIFT = 12,
|
|
25
23
|
REVERSE = 15,
|
|
26
24
|
MOVE = 32,
|
|
27
25
|
DELETE_BY_REFID = 33, // This operation is only used at ENCODING time. During DECODING, DELETE_BY_REFID is converted to DELETE
|
|
28
|
-
|
|
26
|
+
ADD_BY_REFID = 129,
|
|
29
27
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export { Schema } from "./Schema";
|
|
2
2
|
export type { DataChange } from "./decoder/DecodeOperation";
|
|
3
|
-
|
|
4
|
-
import { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType } from "./types/symbols";
|
|
5
|
-
export { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType };
|
|
3
|
+
export type { ToJSON } from "./types/HelperTypes";
|
|
6
4
|
|
|
7
5
|
import { MapSchema } from "./types/custom/MapSchema"
|
|
8
6
|
export { MapSchema };
|
|
@@ -16,8 +14,8 @@ export { CollectionSchema };
|
|
|
16
14
|
import { SetSchema } from "./types/custom/SetSchema";
|
|
17
15
|
export { SetSchema };
|
|
18
16
|
|
|
19
|
-
import { registerType } from "./types/registry";
|
|
20
|
-
export { registerType };
|
|
17
|
+
import { registerType, defineCustomTypes } from "./types/registry";
|
|
18
|
+
export { registerType, defineCustomTypes };
|
|
21
19
|
|
|
22
20
|
registerType("map", { constructor: MapSchema });
|
|
23
21
|
registerType("array", { constructor: ArraySchema });
|
|
@@ -28,10 +26,9 @@ registerType("collection", { constructor: CollectionSchema, });
|
|
|
28
26
|
export { dumpChanges } from "./utils";
|
|
29
27
|
|
|
30
28
|
// Encoder / Decoder
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export { encode, decode };
|
|
29
|
+
export { $track, $encoder, $decoder, $filter, $getByIndex, $deleteByIndex, $changes, $childType } from "./types/symbols";
|
|
30
|
+
export { encode } from "./encoding/encode";
|
|
31
|
+
export { decode, type Iterator } from "./encoding/decode";
|
|
35
32
|
|
|
36
33
|
// Reflection
|
|
37
34
|
export {
|
|
@@ -40,22 +37,17 @@ export {
|
|
|
40
37
|
ReflectionField,
|
|
41
38
|
} from "./Reflection";
|
|
42
39
|
|
|
40
|
+
// Annotations, Metadata and TypeContext
|
|
43
41
|
export { Metadata } from "./Metadata";
|
|
44
|
-
|
|
45
|
-
export {
|
|
46
|
-
// Annotations
|
|
47
|
-
type,
|
|
48
|
-
deprecated,
|
|
49
|
-
defineTypes,
|
|
50
|
-
view,
|
|
51
|
-
|
|
52
|
-
// Internals
|
|
53
|
-
TypeContext,
|
|
54
|
-
} from "./annotations";
|
|
42
|
+
export { type, deprecated, defineTypes, view, schema, type SchemaWithExtends, } from "./annotations";
|
|
43
|
+
export { TypeContext } from "./types/TypeContext";
|
|
55
44
|
|
|
56
45
|
// Annotation types
|
|
57
46
|
export type { DefinitionType, PrimitiveType, Definition, } from "./annotations";
|
|
58
47
|
|
|
48
|
+
export { getDecoderStateCallbacks, CallbackProxy, GetCallbackProxy } from "./decoder/strategy/StateCallbacks";
|
|
49
|
+
export { getRawChangesCallback } from "./decoder/strategy/RawChanges";
|
|
50
|
+
|
|
59
51
|
export { Encoder } from "./encoder/Encoder";
|
|
60
52
|
export { encodeSchemaOperation, encodeArray as encodeKeyValueOperation } from "./encoder/EncodeOperation";
|
|
61
53
|
export { ChangeTree, Ref } from "./encoder/ChangeTree";
|
package/src/types/HelperTypes.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { Definition, DefinitionType, PrimitiveType, RawPrimitiveType } from "../annotations";
|
|
2
|
+
import type { Schema } from "../Schema";
|
|
3
|
+
import type { ArraySchema } from "./custom/ArraySchema";
|
|
4
|
+
import type { CollectionSchema } from "./custom/CollectionSchema";
|
|
5
|
+
import type { MapSchema } from "./custom/MapSchema";
|
|
6
|
+
import type { SetSchema } from "./custom/SetSchema";
|
|
7
|
+
|
|
8
|
+
export type Constructor<T = {}> = new (...args: any[]) => T;
|
|
3
9
|
|
|
4
10
|
export interface Collection<K = any, V = any, IT = V> {
|
|
5
11
|
[Symbol.iterator](): IterableIterator<IT>;
|
|
@@ -7,6 +13,52 @@ export interface Collection<K = any, V = any, IT = V> {
|
|
|
7
13
|
entries(): IterableIterator<[K, V]>;
|
|
8
14
|
}
|
|
9
15
|
|
|
16
|
+
export type InferValueType<T extends DefinitionType> =
|
|
17
|
+
T extends "string" ? string
|
|
18
|
+
: T extends "number" ? number
|
|
19
|
+
: T extends "int8" ? number
|
|
20
|
+
: T extends "uint8" ? number
|
|
21
|
+
: T extends "int16" ? number
|
|
22
|
+
: T extends "uint16" ? number
|
|
23
|
+
: T extends "int32" ? number
|
|
24
|
+
: T extends "uint32" ? number
|
|
25
|
+
: T extends "int64" ? number
|
|
26
|
+
: T extends "uint64" ? number
|
|
27
|
+
: T extends "float32" ? number
|
|
28
|
+
: T extends "float64" ? number
|
|
29
|
+
: T extends "boolean" ? boolean
|
|
30
|
+
|
|
31
|
+
: T extends { type: infer ChildType extends Constructor } ? InstanceType<ChildType>
|
|
32
|
+
: T extends { type: infer ChildType extends PrimitiveType } ? ChildType
|
|
33
|
+
|
|
34
|
+
: T extends Array<infer ChildType extends Constructor> ? InstanceType<ChildType>[]
|
|
35
|
+
: T extends Array<infer ChildType extends RawPrimitiveType> ? ChildType[]
|
|
36
|
+
|
|
37
|
+
: T extends { array: infer ChildType extends Constructor } ? InstanceType<ChildType>[]
|
|
38
|
+
: T extends { array: infer ChildType extends PrimitiveType } ? ChildType[]
|
|
39
|
+
|
|
40
|
+
: T extends { map: infer ChildType extends Constructor } ? MapSchema<InstanceType<ChildType>>
|
|
41
|
+
: T extends { map: infer ChildType extends PrimitiveType } ? MapSchema<ChildType>
|
|
42
|
+
|
|
43
|
+
: T extends { set: infer ChildType extends Constructor } ? SetSchema<InstanceType<ChildType>>
|
|
44
|
+
: T extends { set: infer ChildType extends PrimitiveType } ? SetSchema<ChildType>
|
|
45
|
+
|
|
46
|
+
: T extends { collection: infer ChildType extends Constructor } ? CollectionSchema<InstanceType<ChildType>>
|
|
47
|
+
: T extends { collection: infer ChildType extends PrimitiveType } ? CollectionSchema<ChildType>
|
|
48
|
+
|
|
49
|
+
: T extends Constructor ? InstanceType<T>
|
|
50
|
+
: T extends PrimitiveType ? T
|
|
51
|
+
|
|
52
|
+
: never;
|
|
53
|
+
|
|
54
|
+
export type InferSchemaInstanceType<T extends Definition> = {
|
|
55
|
+
[K in keyof T]: InferValueType<T[K]>
|
|
56
|
+
} & Schema;
|
|
57
|
+
|
|
58
|
+
export type DefinedSchemaType<T extends Definition, P extends typeof Schema> = {
|
|
59
|
+
new (): InferSchemaInstanceType<T> & InstanceType<P>;
|
|
60
|
+
} & typeof Schema;
|
|
61
|
+
|
|
10
62
|
export type NonFunctionProps<T> = Omit<T, {
|
|
11
63
|
[K in keyof T]: T[K] extends Function ? K : never;
|
|
12
64
|
}[keyof T]>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Metadata } from "../Metadata";
|
|
2
|
+
import { Schema } from "../Schema";
|
|
3
|
+
import { $viewFieldIndexes } from "./symbols";
|
|
4
|
+
|
|
5
|
+
export class TypeContext {
|
|
6
|
+
types: { [id: number]: typeof Schema; } = {};
|
|
7
|
+
schemas = new Map<typeof Schema, number>();
|
|
8
|
+
|
|
9
|
+
hasFilters: boolean = false;
|
|
10
|
+
parentFiltered: {[typeIdAndParentIndex: string]: boolean} = {};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* For inheritance support
|
|
14
|
+
* Keeps track of which classes extends which. (parent -> children)
|
|
15
|
+
*/
|
|
16
|
+
static inheritedTypes = new Map<typeof Schema, Set<typeof Schema>>();
|
|
17
|
+
|
|
18
|
+
static register(target: typeof Schema) {
|
|
19
|
+
const parent = Object.getPrototypeOf(target);
|
|
20
|
+
if (parent !== Schema) {
|
|
21
|
+
let inherits = TypeContext.inheritedTypes.get(parent);
|
|
22
|
+
if (!inherits) {
|
|
23
|
+
inherits = new Set<typeof Schema>();
|
|
24
|
+
TypeContext.inheritedTypes.set(parent, inherits);
|
|
25
|
+
}
|
|
26
|
+
inherits.add(target);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(rootClass?: typeof Schema) {
|
|
31
|
+
if (rootClass) {
|
|
32
|
+
//
|
|
33
|
+
// TODO:
|
|
34
|
+
// cache "discoverTypes" results for each rootClass
|
|
35
|
+
// to avoid re-discovering types for each new context/room
|
|
36
|
+
//
|
|
37
|
+
this.discoverTypes(rootClass);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
has(schema: typeof Schema) {
|
|
42
|
+
return this.schemas.has(schema);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get(typeid: number) {
|
|
46
|
+
return this.types[typeid];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
add(schema: typeof Schema, typeid = this.schemas.size) {
|
|
50
|
+
// skip if already registered
|
|
51
|
+
if (this.schemas.has(schema)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.types[typeid] = schema;
|
|
56
|
+
|
|
57
|
+
//
|
|
58
|
+
// Workaround to allow using an empty Schema (with no `@type()` fields)
|
|
59
|
+
//
|
|
60
|
+
if (schema[Symbol.metadata] === undefined) {
|
|
61
|
+
Metadata.initialize(schema);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.schemas.set(schema, typeid);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getTypeId(klass: typeof Schema) {
|
|
69
|
+
return this.schemas.get(klass);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private discoverTypes(klass: typeof Schema, parentType?: typeof Schema, parentIndex?: number, parentHasViewTag?: boolean) {
|
|
73
|
+
if (parentHasViewTag) {
|
|
74
|
+
this.registerFilteredByParent(klass, parentType, parentIndex);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// skip if already registered
|
|
78
|
+
if (!this.add(klass)) { return; }
|
|
79
|
+
|
|
80
|
+
// add classes inherited from this base class
|
|
81
|
+
TypeContext.inheritedTypes.get(klass)?.forEach((child) => {
|
|
82
|
+
this.discoverTypes(child, parentType, parentIndex, parentHasViewTag);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// add parent classes
|
|
86
|
+
let parent: any = klass;
|
|
87
|
+
while (
|
|
88
|
+
(parent = Object.getPrototypeOf(parent)) &&
|
|
89
|
+
parent !== Schema && // stop at root (Schema)
|
|
90
|
+
parent !== Function.prototype // stop at root (non-Schema)
|
|
91
|
+
) {
|
|
92
|
+
this.discoverTypes(parent);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const metadata: Metadata = (klass[Symbol.metadata] ??= {});
|
|
96
|
+
|
|
97
|
+
// if any schema/field has filters, mark "context" as having filters.
|
|
98
|
+
if (metadata[$viewFieldIndexes]) {
|
|
99
|
+
this.hasFilters = true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (const fieldIndex in metadata) {
|
|
103
|
+
const index = fieldIndex as any as number;
|
|
104
|
+
|
|
105
|
+
const fieldType = metadata[index].type;
|
|
106
|
+
const fieldHasViewTag = (metadata[index].tag !== undefined);
|
|
107
|
+
|
|
108
|
+
if (typeof (fieldType) === "string") {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (Array.isArray(fieldType)) {
|
|
113
|
+
const type = fieldType[0];
|
|
114
|
+
|
|
115
|
+
// skip primitive types
|
|
116
|
+
if (type === "string") {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.discoverTypes(type as typeof Schema, klass, index, parentHasViewTag || fieldHasViewTag);
|
|
121
|
+
|
|
122
|
+
} else if (typeof (fieldType) === "function") {
|
|
123
|
+
this.discoverTypes(fieldType as typeof Schema, klass, index, parentHasViewTag || fieldHasViewTag);
|
|
124
|
+
|
|
125
|
+
} else {
|
|
126
|
+
const type = Object.values(fieldType)[0];
|
|
127
|
+
|
|
128
|
+
// skip primitive types
|
|
129
|
+
if (typeof (type) === "string") {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
this.discoverTypes(type as typeof Schema, klass, index, parentHasViewTag || fieldHasViewTag);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Keep track of which classes have filters applied.
|
|
140
|
+
* Format: `${typeid}-${parentTypeid}-${parentIndex}`
|
|
141
|
+
*/
|
|
142
|
+
private registerFilteredByParent(schema: typeof Schema, parentType?: typeof Schema, parentIndex?: number) {
|
|
143
|
+
const typeid = this.schemas.get(schema) ?? this.schemas.size;
|
|
144
|
+
|
|
145
|
+
let key = `${typeid}`;
|
|
146
|
+
if (parentType) { key += `-${this.schemas.get(parentType)}`; }
|
|
147
|
+
|
|
148
|
+
key += `-${parentIndex}`;
|
|
149
|
+
this.parentFiltered[key] = true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
debug() {
|
|
153
|
+
let parentFiltered = "";
|
|
154
|
+
|
|
155
|
+
for (const key in this.parentFiltered) {
|
|
156
|
+
const keys: number[] = key.split("-").map(Number);
|
|
157
|
+
const fieldIndex = keys.pop();
|
|
158
|
+
|
|
159
|
+
parentFiltered += `\n\t\t`;
|
|
160
|
+
parentFiltered += `${key}: ${keys.reverse().map((id, i) => {
|
|
161
|
+
const klass = this.types[id];
|
|
162
|
+
const metadata: Metadata = klass[Symbol.metadata];
|
|
163
|
+
let txt = klass.name;
|
|
164
|
+
if (i === 0) { txt += `[${metadata[fieldIndex].name}]`; }
|
|
165
|
+
return `${txt}`;
|
|
166
|
+
}).join(" -> ")}`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return `TypeContext ->\n` +
|
|
170
|
+
`\tSchema types: ${this.schemas.size}\n` +
|
|
171
|
+
`\thasFilters: ${this.hasFilters}\n` +
|
|
172
|
+
`\tparentFiltered:${parentFiltered}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
}
|