multyx-client 0.1.1 → 0.1.2
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/dist/index.d.ts +35 -15
- package/dist/index.js +106 -60
- package/dist/items/index.d.ts +2 -1
- package/dist/items/index.js +4 -0
- package/dist/items/list.d.ts +33 -14
- package/dist/items/list.js +186 -46
- package/dist/items/object.d.ts +14 -10
- package/dist/items/object.js +84 -38
- package/dist/items/value.d.ts +7 -8
- package/dist/items/value.js +27 -59
- package/dist/message.d.ts +105 -1
- package/dist/message.js +68 -4
- package/dist/types.d.ts +6 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +2 -1
- package/multyx.js +1 -1
- package/package.json +3 -3
- package/src/index.ts +102 -59
- package/src/items/index.ts +5 -0
- package/src/items/list.ts +220 -55
- package/src/items/object.ts +96 -49
- package/src/items/value.ts +37 -66
- package/src/message.ts +60 -4
- package/src/types.ts +7 -1
- package/src/utils.ts +1 -0
package/src/items/object.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Message } from "../message";
|
|
2
2
|
import { RawObject } from '../types';
|
|
3
|
-
import {
|
|
3
|
+
import { Done, Edit, EditWrapper, Unpack } from "../utils";
|
|
4
4
|
|
|
5
5
|
import type Multyx from '../index';
|
|
6
|
-
import type
|
|
6
|
+
import { IsMultyxClientItem, type MultyxClientList, type MultyxClientItem } from ".";
|
|
7
7
|
import MultyxClientItemRouter from "./router";
|
|
8
8
|
import MultyxClientValue from "./value";
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ export default class MultyxClientObject {
|
|
|
13
13
|
propertyPath: string[];
|
|
14
14
|
editable: boolean;
|
|
15
15
|
|
|
16
|
-
private
|
|
16
|
+
private editCallbacks: ((key: any, value: any) => void)[] = [];
|
|
17
17
|
|
|
18
18
|
get value() {
|
|
19
19
|
const parsed = {};
|
|
@@ -21,19 +21,39 @@ export default class MultyxClientObject {
|
|
|
21
21
|
return parsed;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
addEditCallback(callback: (key: any, value: any) => void) {
|
|
25
|
+
this.editCallbacks.push(callback);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[Edit](updatePath: string[], value: any) {
|
|
29
|
+
if(updatePath.length == 1) {
|
|
30
|
+
this.set(updatePath[0], new EditWrapper(value));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if(updatePath.length == 0 && this.multyx.options.verbose) {
|
|
35
|
+
console.error("Update path is empty. Attempting to edit MultyxClientObject with no path.");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if(!this.has(updatePath[0])) {
|
|
39
|
+
this.set(updatePath[0], new EditWrapper({}));
|
|
40
|
+
}
|
|
41
|
+
this.get(updatePath[0])[Edit](updatePath.slice(1), value);
|
|
42
|
+
}
|
|
43
|
+
|
|
24
44
|
constructor(multyx: Multyx, object: RawObject | EditWrapper<RawObject>, propertyPath: string[] = [], editable: boolean) {
|
|
25
45
|
this.object = {};
|
|
26
46
|
this.propertyPath = propertyPath;
|
|
27
47
|
this.multyx = multyx;
|
|
28
48
|
this.editable = editable;
|
|
29
49
|
|
|
30
|
-
|
|
31
|
-
|
|
50
|
+
const isEditWrapper = object instanceof EditWrapper;
|
|
32
51
|
if(object instanceof MultyxClientObject) object = object.value;
|
|
52
|
+
if(object instanceof EditWrapper) object = object.value;
|
|
33
53
|
|
|
34
|
-
for(const prop in
|
|
35
|
-
this.set(prop,
|
|
36
|
-
? new EditWrapper(object
|
|
54
|
+
for(const prop in object) {
|
|
55
|
+
this.set(prop, isEditWrapper
|
|
56
|
+
? new EditWrapper(object[prop])
|
|
37
57
|
: object[prop]
|
|
38
58
|
);
|
|
39
59
|
}
|
|
@@ -44,11 +64,11 @@ export default class MultyxClientObject {
|
|
|
44
64
|
has: (o, p) => {
|
|
45
65
|
return o.has(p);
|
|
46
66
|
},
|
|
47
|
-
get: (o, p) => {
|
|
67
|
+
get: (o, p: string) => {
|
|
48
68
|
if(p in o) return o[p];
|
|
49
69
|
return o.get(p);
|
|
50
70
|
},
|
|
51
|
-
set: (o, p, v) => {
|
|
71
|
+
set: (o, p: string, v) => {
|
|
52
72
|
if(p in o) {
|
|
53
73
|
o[p] = v;
|
|
54
74
|
return true;
|
|
@@ -65,47 +85,74 @@ export default class MultyxClientObject {
|
|
|
65
85
|
return property in this.object;
|
|
66
86
|
}
|
|
67
87
|
|
|
68
|
-
get(property:
|
|
69
|
-
return this.object[property];
|
|
88
|
+
get(property: string | string[]): MultyxClientItem {
|
|
89
|
+
if(typeof property === 'string') return this.object[property];
|
|
90
|
+
if(property.length == 0) return this;
|
|
91
|
+
if(property.length == 1) return this.object[property[0]];
|
|
92
|
+
|
|
93
|
+
const next = this.object[property[0]];
|
|
94
|
+
if(!next || (next instanceof MultyxClientValue)) return undefined;
|
|
95
|
+
return next.get(property.slice(1));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private recursiveSet(path: string[], value: any): boolean {
|
|
99
|
+
if(path.length == 0) {
|
|
100
|
+
if(this.multyx.options.verbose) {
|
|
101
|
+
console.error(`Attempting to edit MultyxClientObject with no path. Setting '${this.propertyPath.join('.')}' to ${value}`);
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if(path.length == 1) return this.set(path[0], value);
|
|
106
|
+
|
|
107
|
+
let next = this.get(path[0]);
|
|
108
|
+
if(next instanceof MultyxClientValue || next == undefined) {
|
|
109
|
+
if(isNaN(parseInt(path[1]))) {
|
|
110
|
+
this.set(path[0], new EditWrapper({}));
|
|
111
|
+
next = this.get(path[0]) as MultyxClientObject;
|
|
112
|
+
} else {
|
|
113
|
+
this.set(path[0], new EditWrapper([]));
|
|
114
|
+
next = this.get(path[0]) as MultyxClientList;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return next.set(path.slice(1), value);
|
|
70
118
|
}
|
|
71
119
|
|
|
72
|
-
set(property:
|
|
73
|
-
if(
|
|
120
|
+
set(property: string | string[], value: any): boolean {
|
|
121
|
+
if(Array.isArray(property)) return this.recursiveSet(property, value);
|
|
74
122
|
|
|
75
|
-
|
|
76
|
-
|
|
123
|
+
const serverSet = value instanceof EditWrapper;
|
|
124
|
+
const allowed = serverSet || this.editable;
|
|
125
|
+
if(serverSet || IsMultyxClientItem(value)) value = value.value;
|
|
126
|
+
if(value === undefined) return this.delete(property, serverSet);
|
|
77
127
|
|
|
78
|
-
//
|
|
79
|
-
if(
|
|
128
|
+
// Only create new MultyxClientItem when needed
|
|
129
|
+
if(this.object[property] instanceof MultyxClientValue && typeof value != 'object') {
|
|
130
|
+
return this.object[property].set(serverSet ? new EditWrapper(value) : value);
|
|
131
|
+
}
|
|
80
132
|
|
|
81
133
|
// Attempting to edit property not editable to client
|
|
82
|
-
if(!
|
|
134
|
+
if(!allowed) {
|
|
83
135
|
if(this.multyx.options.verbose) {
|
|
84
136
|
console.error(`Attempting to set property that is not editable. Setting '${this.propertyPath.join('.') + '.' + property}' to ${value}`);
|
|
85
137
|
}
|
|
86
138
|
return false;
|
|
87
139
|
}
|
|
88
|
-
|
|
140
|
+
|
|
89
141
|
// Creating a new value
|
|
90
|
-
this.object[property] = new (MultyxClientItemRouter(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
142
|
+
this.object[property] = new (MultyxClientItemRouter(value))(
|
|
143
|
+
this.multyx,
|
|
144
|
+
serverSet ? new EditWrapper(value) : value,
|
|
145
|
+
[...this.propertyPath, property],
|
|
146
|
+
this.editable
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const propSymbol = Symbol.for("_" + this.propertyPath.join('.') + '.' + property);
|
|
150
|
+
if(this.multyx.events.has(propSymbol)) {
|
|
151
|
+
this.multyx[Done].push(...this.multyx.events.get(propSymbol).map(e =>
|
|
152
|
+
() => e(this.object[property])
|
|
153
|
+
));
|
|
100
154
|
}
|
|
101
155
|
|
|
102
|
-
// Relay change to server if not edit wrapped
|
|
103
|
-
if(!(value instanceof EditWrapper)) this.multyx.ws.send(Message.Native({
|
|
104
|
-
instruction: 'edit',
|
|
105
|
-
path: this.propertyPath,
|
|
106
|
-
value: this.object[property].value
|
|
107
|
-
}));
|
|
108
|
-
|
|
109
156
|
return true;
|
|
110
157
|
}
|
|
111
158
|
|
|
@@ -131,17 +178,6 @@ export default class MultyxClientObject {
|
|
|
131
178
|
return true;
|
|
132
179
|
}
|
|
133
180
|
|
|
134
|
-
/**
|
|
135
|
-
* Create a callback function that gets called for any current or future property in object
|
|
136
|
-
* @param callbackfn Function to call for every property
|
|
137
|
-
*/
|
|
138
|
-
forAll(callbackfn: (key: any, value: any) => void) {
|
|
139
|
-
for(let prop in this.object) {
|
|
140
|
-
callbackfn(prop, this.get(prop));
|
|
141
|
-
}
|
|
142
|
-
this.setterListeners.push(callbackfn);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
181
|
keys(): any[] {
|
|
146
182
|
return Object.keys(this.object);
|
|
147
183
|
}
|
|
@@ -158,13 +194,24 @@ export default class MultyxClientObject {
|
|
|
158
194
|
return entryList;
|
|
159
195
|
}
|
|
160
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Wait for a specific property to be set
|
|
199
|
+
* @param property Property to wait for
|
|
200
|
+
* @returns Promise that resolves when the value is set
|
|
201
|
+
*/
|
|
202
|
+
await(property: string) {
|
|
203
|
+
if(this.has(property)) return Promise.resolve(this.get(property));
|
|
204
|
+
const propSymbol = Symbol.for("_" + this.propertyPath.join('.') + '.' + property);
|
|
205
|
+
return new Promise(res => this.multyx.on(propSymbol, res));
|
|
206
|
+
}
|
|
207
|
+
|
|
161
208
|
/**
|
|
162
209
|
* Unpack constraints from server
|
|
163
210
|
* @param constraints Packed constraints object mirroring MultyxClientObject shape
|
|
164
211
|
*/
|
|
165
212
|
[Unpack](constraints: RawObject) {
|
|
166
213
|
for(const prop in constraints) {
|
|
167
|
-
this.object[prop][Unpack](constraints[prop]);
|
|
214
|
+
this.object[prop]?.[Unpack](constraints[prop]);
|
|
168
215
|
}
|
|
169
216
|
}
|
|
170
217
|
}
|
package/src/items/value.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type Multyx from '../';
|
|
2
2
|
import { Message } from "../message";
|
|
3
3
|
import { Constraint, RawObject, Value } from "../types";
|
|
4
|
-
import { BuildConstraint, EditWrapper, Unpack } from '../utils';
|
|
4
|
+
import { BuildConstraint, Done, Edit, EditWrapper, Unpack } from '../utils';
|
|
5
5
|
|
|
6
6
|
export default class MultyxClientValue {
|
|
7
7
|
private _value: Value;
|
|
@@ -10,20 +10,29 @@ export default class MultyxClientValue {
|
|
|
10
10
|
editable: boolean;
|
|
11
11
|
constraints: { [key: string]: Constraint };
|
|
12
12
|
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
history: { time: number, value: Value }[]
|
|
17
|
-
};
|
|
18
|
-
|
|
13
|
+
private readModifiers: ((value: Value) => Value)[] = [];
|
|
14
|
+
private editCallbacks: ((value: Value, previousValue: Value) => void)[] = [];
|
|
15
|
+
|
|
19
16
|
get value() {
|
|
20
|
-
|
|
21
|
-
return this._value;
|
|
17
|
+
return this.readModifiers.reduce((value, modifier) => modifier(value), this._value);
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
set value(v) {
|
|
25
21
|
this._value = v;
|
|
26
|
-
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
addReadModifier(modifier: (value: Value) => Value) {
|
|
25
|
+
this.readModifiers.push(modifier);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
addEditCallback(callback: (value: Value, previousValue: Value) => void) {
|
|
29
|
+
this.editCallbacks.push(callback);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
[Edit](updatePath: string[], value: any) {
|
|
33
|
+
if(updatePath.length != 0) return;
|
|
34
|
+
|
|
35
|
+
this.set(new EditWrapper(value));
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
constructor(multyx: Multyx, value: Value | EditWrapper<Value>, propertyPath: string[] = [], editable: boolean) {
|
|
@@ -32,11 +41,20 @@ export default class MultyxClientValue {
|
|
|
32
41
|
this.multyx = multyx;
|
|
33
42
|
this.constraints = {};
|
|
34
43
|
this.set(value);
|
|
44
|
+
|
|
45
|
+
const propSymbol = Symbol.for("_" + this.propertyPath.join('.'));
|
|
46
|
+
if(this.multyx.events.has(propSymbol)) {
|
|
47
|
+
this.multyx[Done].push(...this.multyx.events.get(propSymbol).map(e =>
|
|
48
|
+
() => e(this.value)
|
|
49
|
+
));
|
|
50
|
+
}
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
set(value: Value | EditWrapper<Value>) {
|
|
38
54
|
if(value instanceof EditWrapper) {
|
|
55
|
+
const oldValue = this.value;
|
|
39
56
|
this.value = value.value;
|
|
57
|
+
this.editCallbacks.forEach(fn => fn(value.value, oldValue));
|
|
40
58
|
return true;
|
|
41
59
|
}
|
|
42
60
|
|
|
@@ -53,7 +71,7 @@ export default class MultyxClientValue {
|
|
|
53
71
|
const fn = this.constraints[constraint];
|
|
54
72
|
nv = fn(nv);
|
|
55
73
|
|
|
56
|
-
if(nv === null) {
|
|
74
|
+
if(nv === null) {
|
|
57
75
|
if(this.multyx.options.verbose) {
|
|
58
76
|
console.error(`Attempting to set property that failed on constraint. Setting '${this.propertyPath.join('.')}' to ${value}, stopped by constraint '${constraint}'`);
|
|
59
77
|
}
|
|
@@ -76,6 +94,14 @@ export default class MultyxClientValue {
|
|
|
76
94
|
return true;
|
|
77
95
|
}
|
|
78
96
|
|
|
97
|
+
bindElement(element: HTMLElement) {
|
|
98
|
+
this.addEditCallback((value, previousValue) => {
|
|
99
|
+
if(value !== previousValue) {
|
|
100
|
+
element.innerText = value.toString();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
79
105
|
/**
|
|
80
106
|
* Unpack constraints sent from server and store
|
|
81
107
|
* @param constraints Packed constraints from server
|
|
@@ -88,61 +114,6 @@ export default class MultyxClientValue {
|
|
|
88
114
|
}
|
|
89
115
|
}
|
|
90
116
|
|
|
91
|
-
/**
|
|
92
|
-
* Linearly interpolate value across frames
|
|
93
|
-
* Will run 1 frame behind on average
|
|
94
|
-
*/
|
|
95
|
-
Lerp() {
|
|
96
|
-
this.interpolator = {
|
|
97
|
-
history: [
|
|
98
|
-
{ value: this._value, time: Date.now() },
|
|
99
|
-
{ value: this._value, time: Date.now() }
|
|
100
|
-
],
|
|
101
|
-
get: () => {
|
|
102
|
-
const [e, s] = this.interpolator.history;
|
|
103
|
-
const ratio = Math.min(1, (Date.now() - e.time) / Math.min(250, e.time - s.time));
|
|
104
|
-
if(Number.isNaN(ratio) || typeof e.value != 'number' || typeof s.value != 'number') return e.value;
|
|
105
|
-
return e.value * ratio + s.value * (1 - ratio);
|
|
106
|
-
},
|
|
107
|
-
set: () => {
|
|
108
|
-
this.interpolator.history.pop();
|
|
109
|
-
this.interpolator.history.unshift({
|
|
110
|
-
value: this._value,
|
|
111
|
-
time: Date.now()
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
PredictiveLerp() {
|
|
118
|
-
this.interpolator = {
|
|
119
|
-
history: [
|
|
120
|
-
{ value: this._value, time: Date.now() },
|
|
121
|
-
{ value: this._value, time: Date.now() },
|
|
122
|
-
{ value: this._value, time: Date.now() }
|
|
123
|
-
],
|
|
124
|
-
get: () => {
|
|
125
|
-
const [e, s, p] = this.interpolator.history;
|
|
126
|
-
const ratio = Math.min(1, (Date.now() - e.time) / (e.time - s.time));
|
|
127
|
-
|
|
128
|
-
if(Number.isNaN(ratio) || typeof p.value != 'number') return e.value;
|
|
129
|
-
if(typeof e.value != 'number' || typeof s.value != 'number') return e.value;
|
|
130
|
-
|
|
131
|
-
// Speed changed too fast, don't interpolate, return new value
|
|
132
|
-
if(Math.abs((e.value - s.value) / (s.value - p.value) - 1) > 0.2) return e.value;
|
|
133
|
-
|
|
134
|
-
return e.value * (1 + ratio) - s.value * ratio;
|
|
135
|
-
},
|
|
136
|
-
set: () => {
|
|
137
|
-
this.interpolator.history.pop();
|
|
138
|
-
this.interpolator.history.unshift({
|
|
139
|
-
value: this._value,
|
|
140
|
-
time: Date.now()
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
117
|
/* Native methods to allow MultyxValue to be treated as primitive */
|
|
147
118
|
toString = () => this.value.toString();
|
|
148
119
|
valueOf = () => this.value;
|
package/src/message.ts
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
import { Update } from "./types";
|
|
2
2
|
|
|
3
|
+
export function UncompressUpdate(str: string) {
|
|
4
|
+
const [target, ...escapedData] = str.split(/;,/);
|
|
5
|
+
const instruction = target[0];
|
|
6
|
+
const specifier = target.slice(1).replace(/;_/g, ';');
|
|
7
|
+
const data = escapedData.map(d => d.replace(/;_/g, ';')).map(d => d == "undefined" ? undefined : JSON.parse(d));
|
|
8
|
+
|
|
9
|
+
if(instruction == '0') return { instruction: 'edit', team: false, path: specifier.split('.'), value: data[0] };
|
|
10
|
+
if(instruction == '1') return { instruction: 'edit', team: true, path: specifier.split('.'), value: data[0] };
|
|
11
|
+
|
|
12
|
+
if(instruction == '2') return { instruction: 'self', property: "controller", data: JSON.parse(specifier) };
|
|
13
|
+
if(instruction == '3') return { instruction: 'self', property: "uuid", data: JSON.parse(specifier) };
|
|
14
|
+
if(instruction == '4') return { instruction: 'self', property: "constraint", data: JSON.parse(specifier) };
|
|
15
|
+
if(instruction == '9') return { instruction: 'self', property: "space", data: JSON.parse(specifier) };
|
|
16
|
+
|
|
17
|
+
if(instruction == '5') return { instruction: 'resp', name: specifier, response: data[0] };
|
|
18
|
+
if(instruction == '6') return { instruction: 'conn', uuid: specifier, publicData: data[0] };
|
|
19
|
+
if(instruction == '7') return { instruction: 'dcon', clientUUID: specifier };
|
|
20
|
+
|
|
21
|
+
if(instruction == '8') return {
|
|
22
|
+
instruction: 'init',
|
|
23
|
+
client: JSON.parse(specifier),
|
|
24
|
+
tps: data[0],
|
|
25
|
+
constraintTable: data[1],
|
|
26
|
+
clients: data[2],
|
|
27
|
+
teams: data[3]
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function CompressUpdate(update: Update) {
|
|
32
|
+
let code, pieces;
|
|
33
|
+
if(update.instruction == 'edit') {
|
|
34
|
+
code = 0;
|
|
35
|
+
pieces = [
|
|
36
|
+
update.path.join('.'),
|
|
37
|
+
JSON.stringify(update.value)
|
|
38
|
+
];
|
|
39
|
+
} else if(update.instruction == 'input') {
|
|
40
|
+
code = 1;
|
|
41
|
+
pieces = [update.input];
|
|
42
|
+
} else if(update.instruction == 'resp') {
|
|
43
|
+
code = 2;
|
|
44
|
+
pieces = [update.name, JSON.stringify(update.response)];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if(!pieces) return '';
|
|
48
|
+
let compressed = code;
|
|
49
|
+
for(let i = 0; i < pieces.length; i++) {
|
|
50
|
+
compressed += pieces[i].replace(/;/g, ';_');
|
|
51
|
+
if(i < pieces.length - 1) compressed += ';,';
|
|
52
|
+
}
|
|
53
|
+
return JSON.stringify([compressed]);
|
|
54
|
+
}
|
|
55
|
+
|
|
3
56
|
export class Message {
|
|
4
57
|
name: string;
|
|
5
58
|
data: any;
|
|
@@ -13,20 +66,23 @@ export class Message {
|
|
|
13
66
|
this.native = native;
|
|
14
67
|
}
|
|
15
68
|
|
|
16
|
-
static BundleOperations(deltaTime, operations) {
|
|
69
|
+
static BundleOperations(deltaTime: number, operations: Update[]) {
|
|
17
70
|
if(!Array.isArray(operations)) operations = [operations];
|
|
18
71
|
return JSON.stringify(new Message('_', { operations, deltaTime }));
|
|
19
72
|
}
|
|
20
73
|
|
|
21
74
|
static Native(update: Update) {
|
|
22
|
-
return
|
|
75
|
+
return CompressUpdate(update);
|
|
23
76
|
}
|
|
24
77
|
|
|
25
78
|
static Parse(str: string) {
|
|
26
79
|
const parsed = JSON.parse(str);
|
|
27
|
-
if(parsed.name[0] == '_') parsed.name = parsed.name.slice(1);
|
|
28
80
|
|
|
29
|
-
|
|
81
|
+
if(Array.isArray(parsed)) {
|
|
82
|
+
return new Message('_', parsed, true);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return new Message(parsed.name ?? '', parsed.data ?? '', false);
|
|
30
86
|
}
|
|
31
87
|
|
|
32
88
|
static Create(name: string, data: any) {
|
package/src/types.ts
CHANGED
|
@@ -14,4 +14,10 @@ export type InputUpdate = {
|
|
|
14
14
|
data?: RawObject<Value>
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export type
|
|
17
|
+
export type ResponseUpdate = {
|
|
18
|
+
instruction: 'resp',
|
|
19
|
+
name: string,
|
|
20
|
+
response: any
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type Update = EditUpdate | InputUpdate | ResponseUpdate;
|
package/src/utils.ts
CHANGED