@colyseus/schema 3.0.0-alpha.4 → 3.0.0-alpha.41
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 +2201 -1507
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +2198 -1506
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +2208 -1514
- 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 -32
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +4 -4
- package/lib/Schema.js +44 -50
- 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 +2 -46
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +1 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +1 -2
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +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 +37 -19
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +6 -7
- package/lib/decoder/Decoder.js +14 -14
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +3 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +75 -65
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +27 -21
- package/lib/encoder/ChangeTree.js +246 -186
- 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 +9 -8
- package/lib/encoder/Encoder.js +168 -91
- 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 +70 -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 +35 -20
- package/lib/encoding/decode.js +43 -87
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +36 -17
- package/lib/encoding/encode.js +82 -68
- 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 +23 -0
- package/lib/types/TypeContext.js +111 -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.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -1
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.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 +7 -6
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +77 -39
- package/src/Schema.ts +59 -64
- package/src/annotations.ts +156 -202
- package/src/bench_encode.ts +108 -0
- package/src/codegen/languages/csharp.ts +1 -47
- 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 +46 -18
- package/src/decoder/Decoder.ts +17 -15
- package/src/decoder/ReferenceTracker.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +153 -82
- package/src/encoder/ChangeTree.ts +286 -202
- package/src/encoder/EncodeOperation.ts +78 -78
- package/src/encoder/Encoder.ts +202 -97
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +76 -88
- package/src/encoding/assert.ts +17 -8
- package/src/encoding/decode.ts +62 -97
- package/src/encoding/encode.ts +99 -65
- 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 +133 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +18 -5
- 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
|
@@ -1,95 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a;
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.ChangeTree =
|
|
3
|
+
exports.ChangeTree = void 0;
|
|
4
|
+
exports.setOperationAtIndex = setOperationAtIndex;
|
|
5
|
+
exports.deleteOperationAtIndex = deleteOperationAtIndex;
|
|
5
6
|
const spec_1 = require("../encoding/spec");
|
|
6
7
|
const symbols_1 = require("../types/symbols");
|
|
7
8
|
const Metadata_1 = require("../Metadata");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// all changes
|
|
13
|
-
this.allChanges = new Map();
|
|
14
|
-
this.allFilteredChanges = new Map();
|
|
15
|
-
// pending changes to be encoded
|
|
16
|
-
this.changes = new Map();
|
|
17
|
-
this.filteredChanges = new Map();
|
|
9
|
+
function setOperationAtIndex(changeSet, index) {
|
|
10
|
+
const operationsIndex = changeSet.indexes[index];
|
|
11
|
+
if (operationsIndex === undefined) {
|
|
12
|
+
changeSet.indexes[index] = changeSet.operations.push(index) - 1;
|
|
18
13
|
}
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
else {
|
|
15
|
+
changeSet.operations[operationsIndex] = index;
|
|
21
16
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const refCount = this.refCount.get(changeTree);
|
|
28
|
-
if (refCount <= 1) {
|
|
29
|
-
this.allChanges.delete(changeTree);
|
|
30
|
-
this.changes.delete(changeTree);
|
|
31
|
-
if (changeTree.isFiltered || changeTree.isPartiallyFiltered) {
|
|
32
|
-
this.allFilteredChanges.delete(changeTree);
|
|
33
|
-
this.filteredChanges.delete(changeTree);
|
|
34
|
-
}
|
|
35
|
-
this.refCount.delete(changeTree);
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
this.refCount.set(changeTree, refCount - 1);
|
|
39
|
-
}
|
|
40
|
-
changeTree.forEachChild((child, _) => this.remove(child));
|
|
17
|
+
}
|
|
18
|
+
function deleteOperationAtIndex(changeSet, index) {
|
|
19
|
+
const operationsIndex = changeSet.indexes[index];
|
|
20
|
+
if (operationsIndex !== undefined) {
|
|
21
|
+
changeSet.operations[operationsIndex] = undefined;
|
|
41
22
|
}
|
|
42
|
-
|
|
43
|
-
|
|
23
|
+
delete changeSet.indexes[index];
|
|
24
|
+
}
|
|
25
|
+
function enqueueChangeTree(root, changeTree, changeSet, queueRootIndex = changeTree[changeSet].queueRootIndex) {
|
|
26
|
+
if (root && root[changeSet][queueRootIndex] !== changeTree) {
|
|
27
|
+
changeTree[changeSet].queueRootIndex = root[changeSet].push(changeTree) - 1;
|
|
44
28
|
}
|
|
45
29
|
}
|
|
46
|
-
exports.Root = Root;
|
|
47
30
|
class ChangeTree {
|
|
48
|
-
static { _a = symbols_1.$isNew; }
|
|
49
|
-
;
|
|
50
31
|
constructor(ref) {
|
|
51
|
-
this.
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
32
|
+
this.isFiltered = false;
|
|
33
|
+
this.isPartiallyFiltered = false;
|
|
34
|
+
this.indexedOperations = {};
|
|
35
|
+
//
|
|
36
|
+
// TODO:
|
|
37
|
+
// try storing the index + operation per item.
|
|
38
|
+
// example: 1024 & 1025 => ADD, 1026 => DELETE
|
|
39
|
+
//
|
|
40
|
+
// => https://chatgpt.com/share/67107d0c-bc20-8004-8583-83b17dd7c196
|
|
41
|
+
//
|
|
42
|
+
this.changes = { indexes: {}, operations: [] };
|
|
43
|
+
this.allChanges = { indexes: {}, operations: [] };
|
|
44
|
+
/**
|
|
45
|
+
* Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.
|
|
46
|
+
*/
|
|
47
|
+
this.isNew = true;
|
|
58
48
|
this.ref = ref;
|
|
49
|
+
//
|
|
50
|
+
// Does this structure have "filters" declared?
|
|
51
|
+
//
|
|
52
|
+
if (ref.constructor[Symbol.metadata]?.[symbols_1.$viewFieldIndexes]) {
|
|
53
|
+
this.allFilteredChanges = { indexes: {}, operations: [] };
|
|
54
|
+
this.filteredChanges = { indexes: {}, operations: [] };
|
|
55
|
+
}
|
|
59
56
|
}
|
|
60
57
|
setRoot(root) {
|
|
61
58
|
this.root = root;
|
|
62
|
-
this.root.add(this);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
const isNewChangeTree = this.root.add(this);
|
|
60
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
61
|
+
if (this.root.types.hasFilters) {
|
|
62
|
+
//
|
|
63
|
+
// At Schema initialization, the "root" structure might not be available
|
|
64
|
+
// yet, as it only does once the "Encoder" has been set up.
|
|
65
|
+
//
|
|
66
|
+
// So the "parent" may be already set without a "root".
|
|
67
|
+
//
|
|
68
|
+
this.checkIsFiltered(metadata, this.parent, this.parentIndex);
|
|
69
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
70
|
+
enqueueChangeTree(root, this, 'filteredChanges');
|
|
71
|
+
if (isNewChangeTree) {
|
|
72
|
+
this.root.allFilteredChanges.push(this);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
72
76
|
if (!this.isFiltered) {
|
|
73
|
-
|
|
77
|
+
enqueueChangeTree(root, this, 'changes');
|
|
78
|
+
if (isNewChangeTree) {
|
|
79
|
+
this.root.allChanges.push(this);
|
|
80
|
+
}
|
|
74
81
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
// Recursively set root on child structures
|
|
83
|
+
if (metadata) {
|
|
84
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
85
|
+
const field = metadata[index];
|
|
86
|
+
const value = this.ref[field.name];
|
|
87
|
+
value?.[symbols_1.$changes].setRoot(root);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (this.ref[symbols_1.$childType] && typeof (this.ref[symbols_1.$childType]) !== "string") {
|
|
91
|
+
// MapSchema / ArraySchema, etc.
|
|
92
|
+
this.ref.forEach((value, key) => {
|
|
93
|
+
value[symbols_1.$changes].setRoot(root);
|
|
94
|
+
});
|
|
80
95
|
}
|
|
81
|
-
if (!this.isFiltered) {
|
|
82
|
-
this.root.allChanges.set(this, this.allChanges);
|
|
83
|
-
}
|
|
84
|
-
this.forEachChild((changeTree, _) => {
|
|
85
|
-
changeTree.setRoot(root);
|
|
86
|
-
});
|
|
87
|
-
// this.allChanges.forEach((_, index) => {
|
|
88
|
-
// const childRef = this.ref[$getByIndex](index);
|
|
89
|
-
// if (childRef && childRef[$changes]) {
|
|
90
|
-
// childRef[$changes].setRoot(root);
|
|
91
|
-
// }
|
|
92
|
-
// });
|
|
93
96
|
}
|
|
94
97
|
setParent(parent, root, parentIndex) {
|
|
95
98
|
this.parent = parent;
|
|
@@ -98,83 +101,104 @@ class ChangeTree {
|
|
|
98
101
|
if (!root) {
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
101
|
-
|
|
104
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
102
105
|
// skip if parent is already set
|
|
103
|
-
if (root
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
if (root !== this.root) {
|
|
107
|
+
this.root = root;
|
|
108
|
+
const isNewChangeTree = root.add(this);
|
|
109
|
+
if (root.types.hasFilters) {
|
|
110
|
+
this.checkIsFiltered(metadata, parent, parentIndex);
|
|
111
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
112
|
+
enqueueChangeTree(root, this, 'filteredChanges');
|
|
113
|
+
if (isNewChangeTree) {
|
|
114
|
+
this.root.allFilteredChanges.push(this);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!this.isFiltered) {
|
|
119
|
+
enqueueChangeTree(root, this, 'changes');
|
|
120
|
+
if (isNewChangeTree) {
|
|
121
|
+
this.root.allChanges.push(this);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
108
124
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (!this.isFiltered) {
|
|
112
|
-
this.root.changes.set(this, this.changes);
|
|
125
|
+
else {
|
|
126
|
+
root.add(this);
|
|
113
127
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
128
|
+
// assign same parent on child structures
|
|
129
|
+
if (metadata) {
|
|
130
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
131
|
+
const field = metadata[index];
|
|
132
|
+
const value = this.ref[field.name];
|
|
133
|
+
value?.[symbols_1.$changes].setParent(this.ref, root, index);
|
|
134
|
+
// try { throw new Error(); } catch (e) {
|
|
135
|
+
// console.log(e.stack);
|
|
136
|
+
// }
|
|
137
|
+
});
|
|
117
138
|
}
|
|
118
|
-
else {
|
|
119
|
-
|
|
139
|
+
else if (this.ref[symbols_1.$childType] && typeof (this.ref[symbols_1.$childType]) !== "string") {
|
|
140
|
+
// MapSchema / ArraySchema, etc.
|
|
141
|
+
this.ref.forEach((value, key) => {
|
|
142
|
+
value[symbols_1.$changes].setParent(this.ref, root, this.indexes[key] ?? key);
|
|
143
|
+
});
|
|
120
144
|
}
|
|
121
|
-
this.ensureRefId();
|
|
122
|
-
this.forEachChild((changeTree, atIndex) => {
|
|
123
|
-
changeTree.setParent(this.ref, root, atIndex);
|
|
124
|
-
});
|
|
125
145
|
}
|
|
126
146
|
forEachChild(callback) {
|
|
127
147
|
//
|
|
128
148
|
// assign same parent on child structures
|
|
129
149
|
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const value = this.ref[field];
|
|
135
|
-
if (value
|
|
136
|
-
callback(value[symbols_1.$changes],
|
|
150
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
151
|
+
if (metadata) {
|
|
152
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
153
|
+
const field = metadata[index];
|
|
154
|
+
const value = this.ref[field.name];
|
|
155
|
+
if (value) {
|
|
156
|
+
callback(value[symbols_1.$changes], index);
|
|
137
157
|
}
|
|
138
|
-
}
|
|
158
|
+
});
|
|
139
159
|
}
|
|
140
|
-
else if (typeof (this.ref)
|
|
160
|
+
else if (this.ref[symbols_1.$childType] && typeof (this.ref[symbols_1.$childType]) !== "string") {
|
|
141
161
|
// MapSchema / ArraySchema, etc.
|
|
142
162
|
this.ref.forEach((value, key) => {
|
|
143
|
-
|
|
144
|
-
callback(value[symbols_1.$changes], this.ref[symbols_1.$changes].indexes[key]);
|
|
145
|
-
}
|
|
163
|
+
callback(value[symbols_1.$changes], this.indexes[key] ?? key);
|
|
146
164
|
});
|
|
147
165
|
}
|
|
148
166
|
}
|
|
149
167
|
operation(op) {
|
|
150
|
-
|
|
151
|
-
this.
|
|
168
|
+
// operations without index use negative values to represent them
|
|
169
|
+
// this is checked during .encode() time.
|
|
170
|
+
this.changes.operations.push(-op);
|
|
171
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
152
172
|
}
|
|
153
173
|
change(index, operation = spec_1.OPERATION.ADD) {
|
|
154
|
-
const metadata = this.ref
|
|
155
|
-
const isFiltered = this.isFiltered || (metadata
|
|
174
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
175
|
+
const isFiltered = this.isFiltered || (metadata?.[index]?.tag !== undefined);
|
|
156
176
|
const changeSet = (isFiltered)
|
|
157
177
|
? this.filteredChanges
|
|
158
178
|
: this.changes;
|
|
159
|
-
const previousOperation =
|
|
179
|
+
const previousOperation = this.indexedOperations[index];
|
|
160
180
|
if (!previousOperation || previousOperation === spec_1.OPERATION.DELETE) {
|
|
161
181
|
const op = (!previousOperation)
|
|
162
182
|
? operation
|
|
163
183
|
: (previousOperation === spec_1.OPERATION.DELETE)
|
|
164
184
|
? spec_1.OPERATION.DELETE_AND_ADD
|
|
165
185
|
: operation;
|
|
166
|
-
|
|
186
|
+
//
|
|
187
|
+
// TODO: are DELETE operations being encoded as ADD here ??
|
|
188
|
+
//
|
|
189
|
+
this.indexedOperations[index] = op;
|
|
167
190
|
}
|
|
168
|
-
|
|
169
|
-
// TODO: are DELETE operations being encoded as ADD here ??
|
|
170
|
-
//
|
|
191
|
+
setOperationAtIndex(changeSet, index);
|
|
171
192
|
if (isFiltered) {
|
|
172
|
-
this.allFilteredChanges
|
|
173
|
-
this.root
|
|
193
|
+
setOperationAtIndex(this.allFilteredChanges, index);
|
|
194
|
+
if (this.root) {
|
|
195
|
+
enqueueChangeTree(this.root, this, 'filteredChanges');
|
|
196
|
+
enqueueChangeTree(this.root, this, 'allFilteredChanges');
|
|
197
|
+
}
|
|
174
198
|
}
|
|
175
199
|
else {
|
|
176
|
-
this.allChanges
|
|
177
|
-
this.root
|
|
200
|
+
setOperationAtIndex(this.allChanges, index);
|
|
201
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
178
202
|
}
|
|
179
203
|
}
|
|
180
204
|
shiftChangeIndexes(shiftIndex) {
|
|
@@ -186,12 +210,15 @@ class ChangeTree {
|
|
|
186
210
|
const changeSet = (this.isFiltered)
|
|
187
211
|
? this.filteredChanges
|
|
188
212
|
: this.changes;
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
213
|
+
const newIndexedOperations = {};
|
|
214
|
+
const newIndexes = {};
|
|
215
|
+
for (const index in this.indexedOperations) {
|
|
216
|
+
newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];
|
|
217
|
+
newIndexes[Number(index) + shiftIndex] = changeSet[index];
|
|
194
218
|
}
|
|
219
|
+
this.indexedOperations = newIndexedOperations;
|
|
220
|
+
changeSet.indexes = newIndexes;
|
|
221
|
+
changeSet.operations = changeSet.operations.map((index) => index + shiftIndex);
|
|
195
222
|
}
|
|
196
223
|
shiftAllChangeIndexes(shiftIndex, startIndex = 0) {
|
|
197
224
|
//
|
|
@@ -207,33 +234,42 @@ class ChangeTree {
|
|
|
207
234
|
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
|
|
208
235
|
}
|
|
209
236
|
}
|
|
210
|
-
_shiftAllChangeIndexes(shiftIndex, startIndex = 0,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
237
|
+
_shiftAllChangeIndexes(shiftIndex, startIndex = 0, changeSet) {
|
|
238
|
+
const newIndexes = {};
|
|
239
|
+
for (const key in changeSet.indexes) {
|
|
240
|
+
const index = changeSet.indexes[key];
|
|
241
|
+
if (index > startIndex) {
|
|
242
|
+
newIndexes[Number(key) + shiftIndex] = index;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
newIndexes[key] = index;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
changeSet.indexes = newIndexes;
|
|
249
|
+
for (let i = 0; i < changeSet.operations.length; i++) {
|
|
250
|
+
const index = changeSet.operations[i];
|
|
251
|
+
if (index > startIndex) {
|
|
252
|
+
changeSet.operations[i] = index + shiftIndex;
|
|
216
253
|
}
|
|
217
|
-
}
|
|
254
|
+
}
|
|
218
255
|
}
|
|
219
256
|
indexedOperation(index, operation, allChangesIndex = index) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
this.
|
|
224
|
-
this.
|
|
225
|
-
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
257
|
+
this.indexedOperations[index] = operation;
|
|
258
|
+
if (this.filteredChanges) {
|
|
259
|
+
setOperationAtIndex(this.allFilteredChanges, allChangesIndex);
|
|
260
|
+
setOperationAtIndex(this.filteredChanges, index);
|
|
261
|
+
enqueueChangeTree(this.root, this, 'filteredChanges');
|
|
226
262
|
}
|
|
227
263
|
else {
|
|
228
|
-
this.allChanges
|
|
229
|
-
this.changes
|
|
230
|
-
this.root
|
|
264
|
+
setOperationAtIndex(this.allChanges, allChangesIndex);
|
|
265
|
+
setOperationAtIndex(this.changes, index);
|
|
266
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
231
267
|
}
|
|
232
268
|
}
|
|
233
269
|
getType(index) {
|
|
234
270
|
if (Metadata_1.Metadata.isValidInstance(this.ref)) {
|
|
235
|
-
const metadata = this.ref
|
|
236
|
-
return metadata[
|
|
271
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
272
|
+
return metadata[index].type;
|
|
237
273
|
}
|
|
238
274
|
else {
|
|
239
275
|
//
|
|
@@ -246,8 +282,7 @@ class ChangeTree {
|
|
|
246
282
|
}
|
|
247
283
|
}
|
|
248
284
|
getChange(index) {
|
|
249
|
-
|
|
250
|
-
return this.changes.get(index) ?? this.filteredChanges.get(index);
|
|
285
|
+
return this.indexedOperations[index];
|
|
251
286
|
}
|
|
252
287
|
//
|
|
253
288
|
// used during `.encode()`
|
|
@@ -268,16 +303,14 @@ class ChangeTree {
|
|
|
268
303
|
}
|
|
269
304
|
return;
|
|
270
305
|
}
|
|
271
|
-
const
|
|
272
|
-
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
273
|
-
const changeSet = (isFiltered)
|
|
306
|
+
const changeSet = (this.filteredChanges)
|
|
274
307
|
? this.filteredChanges
|
|
275
308
|
: this.changes;
|
|
309
|
+
this.indexedOperations[index] = operation ?? spec_1.OPERATION.DELETE;
|
|
310
|
+
setOperationAtIndex(changeSet, index);
|
|
276
311
|
const previousValue = this.getValue(index);
|
|
277
|
-
changeSet.set(index, operation ?? spec_1.OPERATION.DELETE);
|
|
278
312
|
// remove `root` reference
|
|
279
313
|
if (previousValue && previousValue[symbols_1.$changes]) {
|
|
280
|
-
previousValue[symbols_1.$changes].root = undefined;
|
|
281
314
|
//
|
|
282
315
|
// FIXME: this.root is "undefined"
|
|
283
316
|
//
|
|
@@ -291,22 +324,26 @@ class ChangeTree {
|
|
|
291
324
|
this.root?.remove(previousValue[symbols_1.$changes]);
|
|
292
325
|
}
|
|
293
326
|
//
|
|
294
|
-
// FIXME: this is looking a
|
|
327
|
+
// FIXME: this is looking a ugly and repeated
|
|
295
328
|
//
|
|
296
|
-
if (
|
|
297
|
-
this.
|
|
298
|
-
this.
|
|
329
|
+
if (this.filteredChanges) {
|
|
330
|
+
deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);
|
|
331
|
+
enqueueChangeTree(this.root, this, 'filteredChanges');
|
|
299
332
|
}
|
|
300
333
|
else {
|
|
301
|
-
this.
|
|
302
|
-
this.
|
|
334
|
+
deleteOperationAtIndex(this.allChanges, allChangesIndex);
|
|
335
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
303
336
|
}
|
|
304
337
|
}
|
|
305
338
|
endEncode() {
|
|
306
|
-
this.
|
|
339
|
+
this.indexedOperations = {};
|
|
340
|
+
// // clear changes
|
|
341
|
+
// this.changes.indexes = {};
|
|
342
|
+
// this.changes.operations.length = 0;
|
|
343
|
+
// ArraySchema and MapSchema have a custom "encode end" method
|
|
307
344
|
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
308
345
|
// Not a new instance anymore
|
|
309
|
-
|
|
346
|
+
this.isNew = false;
|
|
310
347
|
}
|
|
311
348
|
discard(discardAll = false) {
|
|
312
349
|
//
|
|
@@ -315,13 +352,22 @@ class ChangeTree {
|
|
|
315
352
|
// REPLACE in case same key is used on next patches.
|
|
316
353
|
//
|
|
317
354
|
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
318
|
-
this.
|
|
319
|
-
this.
|
|
320
|
-
|
|
321
|
-
this.
|
|
355
|
+
this.indexedOperations = {};
|
|
356
|
+
this.changes.indexes = {};
|
|
357
|
+
this.changes.operations.length = 0;
|
|
358
|
+
this.changes.queueRootIndex = undefined;
|
|
359
|
+
if (this.filteredChanges !== undefined) {
|
|
360
|
+
this.filteredChanges.indexes = {};
|
|
361
|
+
this.filteredChanges.operations.length = 0;
|
|
362
|
+
this.filteredChanges.queueRootIndex = undefined;
|
|
363
|
+
}
|
|
322
364
|
if (discardAll) {
|
|
323
|
-
this.allChanges.
|
|
324
|
-
this.
|
|
365
|
+
this.allChanges.indexes = {};
|
|
366
|
+
this.allChanges.operations.length = 0;
|
|
367
|
+
if (this.allFilteredChanges !== undefined) {
|
|
368
|
+
this.allFilteredChanges.indexes = {};
|
|
369
|
+
this.allFilteredChanges.operations.length = 0;
|
|
370
|
+
}
|
|
325
371
|
// remove children references
|
|
326
372
|
this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
|
|
327
373
|
}
|
|
@@ -330,12 +376,13 @@ class ChangeTree {
|
|
|
330
376
|
* Recursively discard all changes from this, and child structures.
|
|
331
377
|
*/
|
|
332
378
|
discardAll() {
|
|
333
|
-
this.
|
|
334
|
-
|
|
379
|
+
const keys = Object.keys(this.indexedOperations);
|
|
380
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
381
|
+
const value = this.getValue(Number(keys[i]));
|
|
335
382
|
if (value && value[symbols_1.$changes]) {
|
|
336
383
|
value[symbols_1.$changes].discardAll();
|
|
337
384
|
}
|
|
338
|
-
}
|
|
385
|
+
}
|
|
339
386
|
this.discard();
|
|
340
387
|
}
|
|
341
388
|
ensureRefId() {
|
|
@@ -346,36 +393,49 @@ class ChangeTree {
|
|
|
346
393
|
this.refId = this.root.getNextUniqueId();
|
|
347
394
|
}
|
|
348
395
|
get changed() {
|
|
349
|
-
return this.
|
|
396
|
+
return (Object.entries(this.indexedOperations).length > 0);
|
|
350
397
|
}
|
|
351
|
-
checkIsFiltered(parent, parentIndex) {
|
|
398
|
+
checkIsFiltered(metadata, parent, parentIndex) {
|
|
352
399
|
// Detect if current structure has "filters" declared
|
|
353
|
-
this.isPartiallyFiltered =
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
400
|
+
this.isPartiallyFiltered = metadata?.[symbols_1.$viewFieldIndexes] !== undefined;
|
|
401
|
+
if (this.isPartiallyFiltered) {
|
|
402
|
+
this.filteredChanges = this.filteredChanges || { indexes: {}, operations: [] };
|
|
403
|
+
this.allFilteredChanges = this.allFilteredChanges || { indexes: {}, operations: [] };
|
|
404
|
+
}
|
|
405
|
+
// skip if parent is not set
|
|
406
|
+
if (!parent) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (!Metadata_1.Metadata.isValidInstance(parent)) {
|
|
410
|
+
const parentChangeTree = parent[symbols_1.$changes];
|
|
411
|
+
parent = parentChangeTree.parent;
|
|
412
|
+
parentIndex = parentChangeTree.parentIndex;
|
|
413
|
+
}
|
|
414
|
+
const parentMetadata = parent.constructor?.[Symbol.metadata];
|
|
415
|
+
this.isFiltered = parentMetadata?.[symbols_1.$viewFieldIndexes]?.includes(parentIndex);
|
|
364
416
|
//
|
|
365
417
|
// TODO: refactor this!
|
|
366
418
|
//
|
|
367
419
|
// swapping `changes` and `filteredChanges` is required here
|
|
368
420
|
// because "isFiltered" may not be imedialely available on `change()`
|
|
369
421
|
//
|
|
370
|
-
if (this.isFiltered
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
this.changes
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
422
|
+
if (this.isFiltered) {
|
|
423
|
+
this.filteredChanges = { indexes: {}, operations: [] };
|
|
424
|
+
this.allFilteredChanges = { indexes: {}, operations: [] };
|
|
425
|
+
if (this.changes.operations.length > 0) {
|
|
426
|
+
// swap changes reference
|
|
427
|
+
const changes = this.changes;
|
|
428
|
+
this.changes = this.filteredChanges;
|
|
429
|
+
this.filteredChanges = changes;
|
|
430
|
+
// swap "all changes" reference
|
|
431
|
+
const allFilteredChanges = this.allFilteredChanges;
|
|
432
|
+
this.allFilteredChanges = this.allChanges;
|
|
433
|
+
this.allChanges = allFilteredChanges;
|
|
434
|
+
// console.log("SWAP =>", {
|
|
435
|
+
// "this.allFilteredChanges": this.allFilteredChanges,
|
|
436
|
+
// "this.allChanges": this.allChanges
|
|
437
|
+
// })
|
|
438
|
+
}
|
|
379
439
|
}
|
|
380
440
|
}
|
|
381
441
|
}
|