@colyseus/schema 3.0.0-alpha.33 → 3.0.0-alpha.35
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/bin/schema-debug +94 -0
- package/build/cjs/index.js +465 -303
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +465 -303
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +465 -303
- package/lib/Metadata.d.ts +5 -5
- package/lib/Metadata.js +17 -17
- package/lib/Metadata.js.map +1 -1
- package/lib/Schema.js +24 -17
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.js +11 -11
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.js +12 -5
- package/lib/bench_encode.js.map +1 -1
- package/lib/decoder/Decoder.js +1 -1
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +23 -7
- package/lib/encoder/ChangeTree.js +183 -106
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +2 -1
- package/lib/encoder/EncodeOperation.js +2 -2
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +3 -5
- package/lib/encoder/Encoder.js +93 -61
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +12 -7
- package/lib/encoder/Root.js +41 -20
- package/lib/encoder/Root.js.map +1 -1
- package/lib/encoder/StateView.d.ts +5 -5
- package/lib/encoder/StateView.js +29 -23
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/encode.js +12 -9
- package/lib/encoding/encode.js.map +1 -1
- package/lib/types/TypeContext.js +2 -1
- package/lib/types/TypeContext.js.map +1 -1
- package/lib/types/custom/ArraySchema.js +27 -13
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -1
- package/lib/types/custom/MapSchema.js +7 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -6
- package/lib/types/symbols.js +9 -7
- package/lib/types/symbols.js.map +1 -1
- package/lib/utils.js +6 -3
- package/lib/utils.js.map +1 -1
- package/package.json +3 -2
- package/src/Metadata.ts +22 -22
- package/src/Schema.ts +33 -25
- package/src/annotations.ts +12 -12
- package/src/bench_encode.ts +15 -6
- package/src/decoder/Decoder.ts +1 -1
- package/src/encoder/ChangeTree.ts +220 -115
- package/src/encoder/EncodeOperation.ts +5 -1
- package/src/encoder/Encoder.ts +110 -68
- package/src/encoder/Root.ts +41 -21
- package/src/encoder/StateView.ts +32 -28
- package/src/encoding/encode.ts +12 -9
- package/src/types/TypeContext.ts +2 -1
- package/src/types/custom/ArraySchema.ts +39 -17
- package/src/types/custom/MapSchema.ts +12 -5
- package/src/types/symbols.ts +10 -9
- package/src/utils.ts +7 -3
package/lib/bench_encode.js
CHANGED
|
@@ -8,8 +8,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
const nanoid_1 = require("nanoid");
|
|
10
10
|
const _1 = require(".");
|
|
11
|
-
const benchmark = require("benchmark");
|
|
12
|
-
const suite = new benchmark.Suite();
|
|
13
11
|
class Attribute extends _1.Schema {
|
|
14
12
|
}
|
|
15
13
|
__decorate([
|
|
@@ -92,8 +90,11 @@ now = Date.now();
|
|
|
92
90
|
// encoder.encodeAll();
|
|
93
91
|
// }
|
|
94
92
|
// console.log(Date.now() - now);
|
|
93
|
+
const total = 100;
|
|
95
94
|
const allEncodes = Date.now();
|
|
96
|
-
|
|
95
|
+
let avgTimeToEncode = 0;
|
|
96
|
+
let avgTimeToMakeChanges = 0;
|
|
97
|
+
for (let i = 0; i < total; i++) {
|
|
97
98
|
now = Date.now();
|
|
98
99
|
for (let j = 0; j < 50; j++) {
|
|
99
100
|
const player = new Player();
|
|
@@ -112,12 +113,18 @@ for (let i = 0; i < 100; i++) {
|
|
|
112
113
|
player.items.set(`item-${k}`, item);
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
+
const timeToMakeChanges = Date.now() - now;
|
|
117
|
+
console.log("time to make changes:", timeToMakeChanges);
|
|
118
|
+
avgTimeToMakeChanges += timeToMakeChanges;
|
|
116
119
|
now = Date.now();
|
|
117
120
|
encoder.encode();
|
|
118
121
|
encoder.discardChanges();
|
|
119
|
-
|
|
122
|
+
const timeToEncode = Date.now() - now;
|
|
123
|
+
console.log("time to encode:", timeToEncode);
|
|
124
|
+
avgTimeToEncode += timeToEncode;
|
|
120
125
|
}
|
|
126
|
+
console.log("avg time to encode:", (avgTimeToEncode) / total);
|
|
127
|
+
console.log("avg time to make changes:", (avgTimeToMakeChanges) / total);
|
|
121
128
|
console.log("time for all encodes:", Date.now() - allEncodes);
|
|
122
129
|
console.log(Array.from(encoder.encodeAll()).length, "bytes");
|
|
123
130
|
//# sourceMappingURL=bench_encode.js.map
|
package/lib/bench_encode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bench_encode.js","sourceRoot":"","sources":["../src/bench_encode.ts"],"names":[],"mappings":";;;;;;;;AAAA,mCAAgC;AAChC,wBAAkE;
|
|
1
|
+
{"version":3,"file":"bench_encode.js","sourceRoot":"","sources":["../src/bench_encode.ts"],"names":[],"mappings":"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","sourcesContent":["import { nanoid } from \"nanoid\";\nimport { Schema, type, MapSchema, ArraySchema, Encoder } from \".\";\n\nclass Attribute extends Schema {\n @type(\"string\") name: string;\n @type(\"number\") value: number;\n}\n\nclass Item extends Schema {\n @type(\"number\") price: number;\n @type([ Attribute ]) attributes = new ArraySchema<Attribute>();\n}\n\nclass Position extends Schema {\n @type(\"number\") x: number;\n @type(\"number\") y: number;\n}\n\nclass Player extends Schema {\n @type(Position) position = new Position();\n @type({ map: Item }) items = new MapSchema<Item>();\n}\n\nclass State extends Schema {\n @type({ map: Player }) players = new MapSchema<Player>();\n @type(\"string\") currentTurn;\n}\n\nconst state = new State();\n\nEncoder.BUFFER_SIZE = 4096 * 4096;\nconst encoder = new Encoder(state);\n\n\nlet now = Date.now();\n\n// for (let i = 0; i < 10000; i++) {\n// const player = new Player();\n// state.players.set(`p-${nanoid()}`, player);\n//\n// player.position.x = (i + 1) * 100;\n// player.position.y = (i + 1) * 100;\n// for (let j = 0; j < 10; j++) {\n// const item = new Item();\n// player.items.set(`item-${j}`, item);\n// item.price = (i + 1) * 50;\n// for (let k = 0; k < 5; k++) {\n// const attr = new Attribute();\n// attr.name = `Attribute ${k}`;\n// attr.value = k;\n// item.attributes.push(attr);\n// }\n// }\n// }\n// console.log(\"time to make changes:\", Date.now() - now);\n\n\n// measure time to .encodeAll()\n\nnow = Date.now();\n// for (let i = 0; i < 1000; i++) {\n// encoder.encodeAll();\n// }\n// console.log(Date.now() - now);\n\nconst total = 100;\nconst allEncodes = Date.now();\n\nlet avgTimeToEncode = 0;\nlet avgTimeToMakeChanges = 0;\n\nfor (let i = 0; i < total; i++) {\n now = Date.now();\n for (let j = 0; j < 50; j++) {\n const player = new Player();\n state.players.set(`p-${nanoid()}`, player);\n\n player.position.x = (j + 1) * 100;\n player.position.y = (j + 1) * 100;\n for (let k = 0; k < 10; k++) {\n const item = new Item();\n item.price = (j + 1) * 50;\n for (let l = 0; l < 5; l++) {\n const attr = new Attribute();\n attr.name = `Attribute ${l}`;\n attr.value = l;\n item.attributes.push(attr);\n }\n player.items.set(`item-${k}`, item);\n }\n }\n const timeToMakeChanges = Date.now() - now;\n console.log(\"time to make changes:\", timeToMakeChanges);\n avgTimeToMakeChanges += timeToMakeChanges;\n\n now = Date.now();\n encoder.encode();\n encoder.discardChanges();\n\n const timeToEncode = Date.now() - now;\n console.log(\"time to encode:\", timeToEncode);\n avgTimeToEncode += timeToEncode;\n}\nconsole.log(\"avg time to encode:\", (avgTimeToEncode) / total);\nconsole.log(\"avg time to make changes:\", (avgTimeToMakeChanges) / total);\nconsole.log(\"time for all encodes:\", Date.now() - allEncodes);\n\nconsole.log(Array.from(encoder.encodeAll()).length, \"bytes\");\n"]}
|
package/lib/decoder/Decoder.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":";;;AAAA,sDAAmD;AACnD,8CAAgF;AAGhF,6CAA6C;AAC7C,2CAA2E;AAG3E,yDAAsD;AACtD,uDAA+F;AAG/F,MAAa,OAAO;IAUhB,YAAY,IAAO,EAAE,OAAqB;QAJ1C,iBAAY,GAAW,CAAC,CAAC;QAKrB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEpB,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,IAAI,yBAAW,CAAC,IAAI,CAAC,WAA4B,CAAC,CAAC;QAE7E,iDAAiD;QACjD,iDAAiD;QACjD,mFAAmF;QACnF,MAAM;IACV,CAAC;IAES,QAAQ,CAAC,IAAO;QACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,IAAI,mCAAgB,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,CACF,KAAa,EACb,KAAe,EAAE,MAAM,EAAE,CAAC,EAAE,EAC5B,MAAW,IAAI,CAAC,KAAK;QAErB,MAAM,UAAU,GAAiB,EAAE,CAAC;QAEpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QACxB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QAEpC,IAAI,OAAO,GAAoB,GAAG,CAAC,aAAa,CAAC,CAAC,kBAAQ,CAAC,CAAC;QAE5D,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QAEtB,OAAO,EAAE,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,EAAE;YACF,8DAA8D;YAC9D,EAAE;YACF,IAAI,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,0BAAmB,EAAE,CAAC;gBAC1C,EAAE,CAAC,MAAM,EAAE,CAAC;gBAEZ,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAW,CAAC;gBAE5D,EAAE;gBACF,8DAA8D;gBAC9D,EAAE;gBACF,IAAI,CAAC,OAAO,EAAE,CAAC;oBAAC,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;gBAAC,CAAC;gBAC7E,GAAG,CAAC,sBAAY,CAAC,EAAE,EAAE,CAAA;gBACrB,GAAG,GAAG,OAAO,CAAC;gBAEd,OAAO,GAAG,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport * as decode from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setState(root);\n\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 setState(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\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[$onDecodeEnd]?.()\n ref = nextRef;\n\n decoder = ref.constructor[$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === 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: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, 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 removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OPERATION } from "../encoding/spec";
|
|
2
2
|
import { Schema } from "../Schema";
|
|
3
|
-
import { $changes, $decoder, $encoder
|
|
3
|
+
import { $changes, $decoder, $encoder } from "../types/symbols";
|
|
4
4
|
import type { MapSchema } from "../types/custom/MapSchema";
|
|
5
5
|
import type { ArraySchema } from "../types/custom/ArraySchema";
|
|
6
6
|
import type { CollectionSchema } from "../types/custom/CollectionSchema";
|
|
@@ -17,6 +17,19 @@ declare global {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
export type Ref = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;
|
|
20
|
+
export type ChangeSetName = "changes" | "allChanges" | "filteredChanges" | "allFilteredChanges";
|
|
21
|
+
export interface IndexedOperations {
|
|
22
|
+
[index: number]: OPERATION;
|
|
23
|
+
}
|
|
24
|
+
export interface ChangeSet {
|
|
25
|
+
indexes: {
|
|
26
|
+
[index: number]: number;
|
|
27
|
+
};
|
|
28
|
+
operations: OPERATION[];
|
|
29
|
+
queueRootIndex?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare function setOperationAtIndex(changeSet: ChangeSet, index: number): void;
|
|
32
|
+
export declare function deleteOperationAtIndex(changeSet: ChangeSet, index: number): void;
|
|
20
33
|
export declare class ChangeTree<T extends Ref = any> {
|
|
21
34
|
ref: T;
|
|
22
35
|
refId: number;
|
|
@@ -25,15 +38,18 @@ export declare class ChangeTree<T extends Ref = any> {
|
|
|
25
38
|
parentIndex?: number;
|
|
26
39
|
isFiltered: boolean;
|
|
27
40
|
isPartiallyFiltered: boolean;
|
|
28
|
-
|
|
29
|
-
changes:
|
|
30
|
-
allChanges:
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
indexedOperations: IndexedOperations;
|
|
42
|
+
changes: ChangeSet;
|
|
43
|
+
allChanges: ChangeSet;
|
|
44
|
+
filteredChanges: ChangeSet;
|
|
45
|
+
allFilteredChanges: ChangeSet;
|
|
33
46
|
indexes: {
|
|
34
47
|
[index: string]: any;
|
|
35
48
|
};
|
|
36
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.
|
|
51
|
+
*/
|
|
52
|
+
isNew: boolean;
|
|
37
53
|
constructor(ref: T);
|
|
38
54
|
setRoot(root: Root): void;
|
|
39
55
|
setParent(parent: Ref, root?: Root, parentIndex?: number): void;
|
|
@@ -1,31 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var _a;
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
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");
|
|
9
|
+
function setOperationAtIndex(changeSet, index) {
|
|
10
|
+
const operationsIndex = changeSet.indexes[index];
|
|
11
|
+
if (operationsIndex === undefined) {
|
|
12
|
+
changeSet.indexes[index] = changeSet.operations.push(index) - 1;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
changeSet.operations[operationsIndex] = index;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function deleteOperationAtIndex(changeSet, index) {
|
|
19
|
+
const operationsIndex = changeSet.indexes[index];
|
|
20
|
+
if (operationsIndex !== undefined) {
|
|
21
|
+
changeSet.operations[operationsIndex] = undefined;
|
|
22
|
+
}
|
|
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;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
8
30
|
class ChangeTree {
|
|
9
|
-
static { _a = symbols_1.$isNew; }
|
|
10
31
|
constructor(ref) {
|
|
11
32
|
this.isFiltered = false;
|
|
12
33
|
this.isPartiallyFiltered = false;
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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;
|
|
17
48
|
this.ref = ref;
|
|
18
49
|
//
|
|
19
50
|
// Does this structure have "filters" declared?
|
|
20
51
|
//
|
|
21
|
-
if (ref.constructor[Symbol.metadata]?.[
|
|
22
|
-
this.allFilteredChanges =
|
|
23
|
-
this.filteredChanges =
|
|
52
|
+
if (ref.constructor[Symbol.metadata]?.[symbols_1.$viewFieldIndexes]) {
|
|
53
|
+
this.allFilteredChanges = { indexes: {}, operations: [] };
|
|
54
|
+
this.filteredChanges = { indexes: {}, operations: [] };
|
|
24
55
|
}
|
|
25
56
|
}
|
|
26
57
|
setRoot(root) {
|
|
27
58
|
this.root = root;
|
|
28
|
-
this.root.add(this);
|
|
59
|
+
const isNewChangeTree = this.root.add(this);
|
|
29
60
|
const metadata = this.ref.constructor[Symbol.metadata];
|
|
30
61
|
if (this.root.types.hasFilters) {
|
|
31
62
|
//
|
|
@@ -36,22 +67,24 @@ class ChangeTree {
|
|
|
36
67
|
//
|
|
37
68
|
this.checkIsFiltered(metadata, this.parent, this.parentIndex);
|
|
38
69
|
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
39
|
-
|
|
40
|
-
|
|
70
|
+
enqueueChangeTree(root, this, 'filteredChanges');
|
|
71
|
+
if (isNewChangeTree) {
|
|
72
|
+
this.root.allFilteredChanges.push(this);
|
|
73
|
+
}
|
|
41
74
|
}
|
|
42
75
|
}
|
|
43
76
|
if (!this.isFiltered) {
|
|
44
|
-
|
|
45
|
-
|
|
77
|
+
enqueueChangeTree(root, this, 'changes');
|
|
78
|
+
if (isNewChangeTree) {
|
|
79
|
+
this.root.allChanges.push(this);
|
|
80
|
+
}
|
|
46
81
|
}
|
|
47
|
-
|
|
82
|
+
// Recursively set root on child structures
|
|
48
83
|
if (metadata) {
|
|
49
|
-
metadata[
|
|
84
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
50
85
|
const field = metadata[index];
|
|
51
86
|
const value = this.ref[field.name];
|
|
52
|
-
|
|
53
|
-
value[symbols_1.$changes].setRoot(root);
|
|
54
|
-
}
|
|
87
|
+
value?.[symbols_1.$changes].setRoot(root);
|
|
55
88
|
});
|
|
56
89
|
}
|
|
57
90
|
else if (this.ref[symbols_1.$childType] && typeof (this.ref[symbols_1.$childType]) !== "string") {
|
|
@@ -68,31 +101,36 @@ class ChangeTree {
|
|
|
68
101
|
if (!root) {
|
|
69
102
|
return;
|
|
70
103
|
}
|
|
71
|
-
root.add(this);
|
|
72
104
|
const metadata = this.ref.constructor[Symbol.metadata];
|
|
73
105
|
// skip if parent is already set
|
|
74
106
|
if (root !== this.root) {
|
|
75
107
|
this.root = root;
|
|
108
|
+
const isNewChangeTree = root.add(this);
|
|
76
109
|
if (root.types.hasFilters) {
|
|
77
110
|
this.checkIsFiltered(metadata, parent, parentIndex);
|
|
78
111
|
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
enqueueChangeTree(root, this, 'filteredChanges');
|
|
113
|
+
if (isNewChangeTree) {
|
|
114
|
+
this.root.allFilteredChanges.push(this);
|
|
115
|
+
}
|
|
81
116
|
}
|
|
82
117
|
}
|
|
83
118
|
if (!this.isFiltered) {
|
|
84
|
-
|
|
85
|
-
|
|
119
|
+
enqueueChangeTree(root, this, 'changes');
|
|
120
|
+
if (isNewChangeTree) {
|
|
121
|
+
this.root.allChanges.push(this);
|
|
122
|
+
}
|
|
86
123
|
}
|
|
87
|
-
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
root.add(this);
|
|
88
127
|
}
|
|
89
128
|
// assign same parent on child structures
|
|
90
129
|
if (metadata) {
|
|
91
|
-
metadata[
|
|
130
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
92
131
|
const field = metadata[index];
|
|
93
132
|
const value = this.ref[field.name];
|
|
94
133
|
value?.[symbols_1.$changes].setParent(this.ref, root, index);
|
|
95
|
-
// console.log(this.ref.constructor.name, field.name, value);
|
|
96
134
|
// try { throw new Error(); } catch (e) {
|
|
97
135
|
// console.log(e.stack);
|
|
98
136
|
// }
|
|
@@ -111,7 +149,7 @@ class ChangeTree {
|
|
|
111
149
|
//
|
|
112
150
|
const metadata = this.ref.constructor[Symbol.metadata];
|
|
113
151
|
if (metadata) {
|
|
114
|
-
metadata[
|
|
152
|
+
metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
|
|
115
153
|
const field = metadata[index];
|
|
116
154
|
const value = this.ref[field.name];
|
|
117
155
|
if (value) {
|
|
@@ -127,8 +165,10 @@ class ChangeTree {
|
|
|
127
165
|
}
|
|
128
166
|
}
|
|
129
167
|
operation(op) {
|
|
130
|
-
|
|
131
|
-
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');
|
|
132
172
|
}
|
|
133
173
|
change(index, operation = spec_1.OPERATION.ADD) {
|
|
134
174
|
const metadata = this.ref.constructor[Symbol.metadata];
|
|
@@ -136,7 +176,7 @@ class ChangeTree {
|
|
|
136
176
|
const changeSet = (isFiltered)
|
|
137
177
|
? this.filteredChanges
|
|
138
178
|
: this.changes;
|
|
139
|
-
const previousOperation =
|
|
179
|
+
const previousOperation = this.indexedOperations[index];
|
|
140
180
|
if (!previousOperation || previousOperation === spec_1.OPERATION.DELETE) {
|
|
141
181
|
const op = (!previousOperation)
|
|
142
182
|
? operation
|
|
@@ -146,16 +186,19 @@ class ChangeTree {
|
|
|
146
186
|
//
|
|
147
187
|
// TODO: are DELETE operations being encoded as ADD here ??
|
|
148
188
|
//
|
|
149
|
-
|
|
189
|
+
this.indexedOperations[index] = op;
|
|
150
190
|
}
|
|
191
|
+
setOperationAtIndex(changeSet, index);
|
|
151
192
|
if (isFiltered) {
|
|
152
|
-
this.allFilteredChanges
|
|
153
|
-
this.root
|
|
154
|
-
|
|
193
|
+
setOperationAtIndex(this.allFilteredChanges, index);
|
|
194
|
+
if (this.root) {
|
|
195
|
+
enqueueChangeTree(this.root, this, 'filteredChanges');
|
|
196
|
+
enqueueChangeTree(this.root, this, 'allFilteredChanges');
|
|
197
|
+
}
|
|
155
198
|
}
|
|
156
199
|
else {
|
|
157
|
-
this.allChanges
|
|
158
|
-
this.root
|
|
200
|
+
setOperationAtIndex(this.allChanges, index);
|
|
201
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
159
202
|
}
|
|
160
203
|
}
|
|
161
204
|
shiftChangeIndexes(shiftIndex) {
|
|
@@ -167,12 +210,15 @@ class ChangeTree {
|
|
|
167
210
|
const changeSet = (this.isFiltered)
|
|
168
211
|
? this.filteredChanges
|
|
169
212
|
: this.changes;
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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];
|
|
175
218
|
}
|
|
219
|
+
this.indexedOperations = newIndexedOperations;
|
|
220
|
+
changeSet.indexes = newIndexes;
|
|
221
|
+
changeSet.operations = changeSet.operations.map((index) => index + shiftIndex);
|
|
176
222
|
}
|
|
177
223
|
shiftAllChangeIndexes(shiftIndex, startIndex = 0) {
|
|
178
224
|
//
|
|
@@ -188,24 +234,36 @@ class ChangeTree {
|
|
|
188
234
|
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
|
|
189
235
|
}
|
|
190
236
|
}
|
|
191
|
-
_shiftAllChangeIndexes(shiftIndex, startIndex = 0,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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;
|
|
196
253
|
}
|
|
197
|
-
}
|
|
254
|
+
}
|
|
198
255
|
}
|
|
199
256
|
indexedOperation(index, operation, allChangesIndex = index) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
this.
|
|
203
|
-
this.
|
|
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');
|
|
204
262
|
}
|
|
205
263
|
else {
|
|
206
|
-
this.allChanges
|
|
207
|
-
this.changes
|
|
208
|
-
this.root
|
|
264
|
+
setOperationAtIndex(this.allChanges, allChangesIndex);
|
|
265
|
+
setOperationAtIndex(this.changes, index);
|
|
266
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
209
267
|
}
|
|
210
268
|
}
|
|
211
269
|
getType(index) {
|
|
@@ -224,8 +282,7 @@ class ChangeTree {
|
|
|
224
282
|
}
|
|
225
283
|
}
|
|
226
284
|
getChange(index) {
|
|
227
|
-
|
|
228
|
-
return this.changes.get(index) ?? this.filteredChanges?.get(index);
|
|
285
|
+
return this.indexedOperations[index];
|
|
229
286
|
}
|
|
230
287
|
//
|
|
231
288
|
// used during `.encode()`
|
|
@@ -249,8 +306,9 @@ class ChangeTree {
|
|
|
249
306
|
const changeSet = (this.filteredChanges)
|
|
250
307
|
? this.filteredChanges
|
|
251
308
|
: this.changes;
|
|
309
|
+
this.indexedOperations[index] = operation ?? spec_1.OPERATION.DELETE;
|
|
310
|
+
setOperationAtIndex(changeSet, index);
|
|
252
311
|
const previousValue = this.getValue(index);
|
|
253
|
-
changeSet.set(index, operation ?? spec_1.OPERATION.DELETE);
|
|
254
312
|
// remove `root` reference
|
|
255
313
|
if (previousValue && previousValue[symbols_1.$changes]) {
|
|
256
314
|
//
|
|
@@ -266,23 +324,26 @@ class ChangeTree {
|
|
|
266
324
|
this.root?.remove(previousValue[symbols_1.$changes]);
|
|
267
325
|
}
|
|
268
326
|
//
|
|
269
|
-
// FIXME: this is looking a
|
|
327
|
+
// FIXME: this is looking a ugly and repeated
|
|
270
328
|
//
|
|
271
329
|
if (this.filteredChanges) {
|
|
272
|
-
this.
|
|
273
|
-
this.
|
|
330
|
+
deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);
|
|
331
|
+
enqueueChangeTree(this.root, this, 'filteredChanges');
|
|
274
332
|
}
|
|
275
333
|
else {
|
|
276
|
-
this.
|
|
277
|
-
this.
|
|
334
|
+
deleteOperationAtIndex(this.allChanges, allChangesIndex);
|
|
335
|
+
enqueueChangeTree(this.root, this, 'changes');
|
|
278
336
|
}
|
|
279
337
|
}
|
|
280
338
|
endEncode() {
|
|
281
|
-
this.
|
|
339
|
+
this.indexedOperations = {};
|
|
340
|
+
// // clear changes
|
|
341
|
+
// this.changes.indexes = {};
|
|
342
|
+
// this.changes.operations.length = 0;
|
|
282
343
|
// ArraySchema and MapSchema have a custom "encode end" method
|
|
283
344
|
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
284
345
|
// Not a new instance anymore
|
|
285
|
-
|
|
346
|
+
this.isNew = false;
|
|
286
347
|
}
|
|
287
348
|
discard(discardAll = false) {
|
|
288
349
|
//
|
|
@@ -291,13 +352,22 @@ class ChangeTree {
|
|
|
291
352
|
// REPLACE in case same key is used on next patches.
|
|
292
353
|
//
|
|
293
354
|
this.ref[symbols_1.$onEncodeEnd]?.();
|
|
294
|
-
this.
|
|
295
|
-
this.
|
|
296
|
-
|
|
297
|
-
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
|
+
}
|
|
298
364
|
if (discardAll) {
|
|
299
|
-
this.allChanges.
|
|
300
|
-
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
|
+
}
|
|
301
371
|
// remove children references
|
|
302
372
|
this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
|
|
303
373
|
}
|
|
@@ -306,12 +376,13 @@ class ChangeTree {
|
|
|
306
376
|
* Recursively discard all changes from this, and child structures.
|
|
307
377
|
*/
|
|
308
378
|
discardAll() {
|
|
309
|
-
this.
|
|
310
|
-
|
|
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]));
|
|
311
382
|
if (value && value[symbols_1.$changes]) {
|
|
312
383
|
value[symbols_1.$changes].discardAll();
|
|
313
384
|
}
|
|
314
|
-
}
|
|
385
|
+
}
|
|
315
386
|
this.discard();
|
|
316
387
|
}
|
|
317
388
|
ensureRefId() {
|
|
@@ -322,42 +393,48 @@ class ChangeTree {
|
|
|
322
393
|
this.refId = this.root.getNextUniqueId();
|
|
323
394
|
}
|
|
324
395
|
get changed() {
|
|
325
|
-
return this.
|
|
396
|
+
return (Object.entries(this.indexedOperations).length > 0);
|
|
326
397
|
}
|
|
327
398
|
checkIsFiltered(metadata, parent, parentIndex) {
|
|
328
399
|
// Detect if current structure has "filters" declared
|
|
329
|
-
this.isPartiallyFiltered = metadata?.[
|
|
400
|
+
this.isPartiallyFiltered = metadata?.[symbols_1.$viewFieldIndexes] !== undefined;
|
|
330
401
|
if (this.isPartiallyFiltered) {
|
|
331
|
-
this.filteredChanges = this.filteredChanges ||
|
|
332
|
-
this.allFilteredChanges = this.allFilteredChanges ||
|
|
333
|
-
}
|
|
334
|
-
if
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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);
|
|
416
|
+
//
|
|
417
|
+
// TODO: refactor this!
|
|
418
|
+
//
|
|
419
|
+
// swapping `changes` and `filteredChanges` is required here
|
|
420
|
+
// because "isFiltered" may not be imedialely available on `change()`
|
|
421
|
+
//
|
|
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
|
+
// })
|
|
361
438
|
}
|
|
362
439
|
}
|
|
363
440
|
}
|