insite-subscriptions-client 1.0.294
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/LICENSE +21 -0
- package/README.md +13 -0
- package/lib/Subscription.js +106 -0
- package/lib/SubscriptionArray.js +241 -0
- package/lib/SubscriptionGroup/SubscriptionGroup.js +292 -0
- package/lib/SubscriptionGroup/SubscriptionGroupItem.js +300 -0
- package/lib/SubscriptionGroup/common.js +1 -0
- package/lib/SubscriptionGroup/index.js +1 -0
- package/lib/SubscriptionMap.js +393 -0
- package/lib/SubscriptionObject.js +153 -0
- package/lib/index.js +21 -0
- package/lib/symbols.js +12 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Eugene Nesvetaev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
//#if _SSR
|
|
2
|
+
// import { publications } from "insite-subscriptions-server";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
// export const initialsMap = new Map();
|
|
6
|
+
|
|
7
|
+
// export const subscriptionContext = {};
|
|
8
|
+
|
|
9
|
+
// export async function Subscription(type, publicationName, args = [], handler) {
|
|
10
|
+
// const value = await publications.get(publicationName)?.fetch(subscriptionContext, ...args);
|
|
11
|
+
|
|
12
|
+
// subscriptionContext.initials.push(JSON.stringify(value));
|
|
13
|
+
|
|
14
|
+
// handler(value);
|
|
15
|
+
|
|
16
|
+
// }
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
//#else
|
|
20
|
+
let i, subscriptions, ws;
|
|
21
|
+
|
|
22
|
+
export class Subscription {
|
|
23
|
+
constructor(type, publicationName, args = [], handler, immediately = true) {
|
|
24
|
+
|
|
25
|
+
if (!ws)
|
|
26
|
+
throw new Error("Subscription is not binded to WS. Do Subscription.bindTo(ws) first");
|
|
27
|
+
|
|
28
|
+
this.i = i++;
|
|
29
|
+
this.type = type;
|
|
30
|
+
this.publicationName = publicationName;
|
|
31
|
+
this.args = args;
|
|
32
|
+
this.handler = handler;
|
|
33
|
+
this.immediately = immediately && !window.__initials;
|
|
34
|
+
|
|
35
|
+
subscriptions.set(this.i, this);
|
|
36
|
+
|
|
37
|
+
ws.on("open", this.start);
|
|
38
|
+
|
|
39
|
+
if (ws.isOpen)
|
|
40
|
+
this.start();
|
|
41
|
+
|
|
42
|
+
if (window.__initials) {
|
|
43
|
+
this.isActive = true;
|
|
44
|
+
this.handler(window.__initials.splice(0, 1)[0]);
|
|
45
|
+
} else
|
|
46
|
+
this.isActive = false;
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
start = () => {
|
|
51
|
+
|
|
52
|
+
ws.sendMessage("s-s"/* subscription subscribe */, this.type, this.publicationName, this.i, this.args, this.immediately);
|
|
53
|
+
|
|
54
|
+
this.immediately = true;
|
|
55
|
+
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
cancel() {
|
|
59
|
+
|
|
60
|
+
subscriptions.delete(this.i);
|
|
61
|
+
|
|
62
|
+
ws.off("open", this.start);
|
|
63
|
+
|
|
64
|
+
ws.sendMessage("s-u"/* subscription unsubscribe */, this.i);
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
static bindTo(_ws) {
|
|
70
|
+
ws = _ws;
|
|
71
|
+
|
|
72
|
+
i = 0;
|
|
73
|
+
|
|
74
|
+
subscriptions =
|
|
75
|
+
Subscription.subscriptions =
|
|
76
|
+
new Map();
|
|
77
|
+
|
|
78
|
+
ws.on("message:s-c"/* subscription changed */, (_i, data) => {
|
|
79
|
+
const subscription = subscriptions.get(_i);
|
|
80
|
+
if (subscription) {
|
|
81
|
+
subscription.isActive = true;
|
|
82
|
+
subscription.handler(data);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
ws.on("close", () => {
|
|
88
|
+
|
|
89
|
+
for (const subscription of subscriptions.values())
|
|
90
|
+
subscription.isActive = false;
|
|
91
|
+
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
ws.on("server-change", () => {
|
|
95
|
+
|
|
96
|
+
for (const subscription of subscriptions.values())
|
|
97
|
+
subscription.handler(null);
|
|
98
|
+
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
//#endif
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { removeOne } from "@nesvet/n";
|
|
2
|
+
import { Subscription } from "./Subscription";
|
|
3
|
+
import {
|
|
4
|
+
clearSymbol,
|
|
5
|
+
getAsInitialUpdatedSymbol,
|
|
6
|
+
getAsUpdatesSymbol,
|
|
7
|
+
getHandleUpdateSymbol,
|
|
8
|
+
getSubscriptionSymbol,
|
|
9
|
+
renewSymbol,
|
|
10
|
+
setHandleUpdateSymbol,
|
|
11
|
+
subscribeSymbol,
|
|
12
|
+
unsubscribeSymbol,
|
|
13
|
+
updateSymbol
|
|
14
|
+
} from "./symbols";
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const ascSort = (a, b) => a > b ? 1 : a < b ? -1 : 0;
|
|
18
|
+
const descSort = (a, b) => a > b ? -1 : a < b ? 1 : 0;
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export class SubscriptionArray extends Array {
|
|
22
|
+
constructor(updates, onUpdate) {
|
|
23
|
+
super();
|
|
24
|
+
|
|
25
|
+
this.handleUpdate = onUpdate;
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(updates))
|
|
28
|
+
this.update(updates);
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
sortDirection = 0;
|
|
33
|
+
|
|
34
|
+
sortCompareFunction = null;
|
|
35
|
+
|
|
36
|
+
[getHandleUpdateSymbol]() {
|
|
37
|
+
return this.handleUpdate;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[setHandleUpdateSymbol](handleUpdate) {
|
|
41
|
+
return (this.handleUpdate = handleUpdate);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
update(updates) {
|
|
45
|
+
|
|
46
|
+
const updated = [];
|
|
47
|
+
updated.deleted = [];
|
|
48
|
+
updated.added = [];
|
|
49
|
+
|
|
50
|
+
if (updates) {
|
|
51
|
+
let shouldSort = false;
|
|
52
|
+
|
|
53
|
+
for (const update of updates)
|
|
54
|
+
switch (update?.[0]) {
|
|
55
|
+
case "i"/* initial */: {
|
|
56
|
+
const [ , array, sort ] = update;
|
|
57
|
+
|
|
58
|
+
if (sort) {
|
|
59
|
+
this.sortDirection = sort;
|
|
60
|
+
this.sortCompareFunction = sort > 0 ? ascSort : descSort;
|
|
61
|
+
shouldSort = true;
|
|
62
|
+
} else {
|
|
63
|
+
this.sortDirection = 0;
|
|
64
|
+
this.sortCompareFunction = null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.length = 0;
|
|
68
|
+
|
|
69
|
+
for (const newItem of array) {
|
|
70
|
+
this.push(newItem);
|
|
71
|
+
updated.push(newItem);
|
|
72
|
+
updated.added.push(newItem);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case "a"/* add */: {
|
|
79
|
+
const newItem = update[1];
|
|
80
|
+
|
|
81
|
+
if (!this.includes(newItem)) {
|
|
82
|
+
this.push(newItem);
|
|
83
|
+
if (this.sortDirection)
|
|
84
|
+
shouldSort = true;
|
|
85
|
+
updated.push(newItem);
|
|
86
|
+
updated.added.push(newItem);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
case "d"/* delete */: {
|
|
93
|
+
const itemToDelete = update[1];
|
|
94
|
+
|
|
95
|
+
if (removeOne(this, itemToDelete))
|
|
96
|
+
updated.deleted.push(itemToDelete);
|
|
97
|
+
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
default:
|
|
102
|
+
this.clear();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (shouldSort)
|
|
106
|
+
this.sort(this.sortCompareFunction);
|
|
107
|
+
|
|
108
|
+
} else
|
|
109
|
+
this.clear();
|
|
110
|
+
|
|
111
|
+
this.handleUpdate?.(this, updated, updates?.[0] && updates);
|
|
112
|
+
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
[updateSymbol] = this.update;
|
|
117
|
+
|
|
118
|
+
getAsUpdates() {
|
|
119
|
+
return (
|
|
120
|
+
(this.length || this.sortDirection) ?
|
|
121
|
+
[ [ "i"/* initial */, [ ...this ], this.sortDirection ] ] :
|
|
122
|
+
null
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
[getAsUpdatesSymbol] = this.getAsUpdates;
|
|
127
|
+
|
|
128
|
+
getAsInitialUpdated() {
|
|
129
|
+
return Object.assign([ ...this.sorted ], {
|
|
130
|
+
added: [ ...this.sorted ],
|
|
131
|
+
deleted: []
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[getAsInitialUpdatedSymbol] = this.getAsInitialUpdated;
|
|
136
|
+
|
|
137
|
+
clear() {
|
|
138
|
+
|
|
139
|
+
this.length = 0;
|
|
140
|
+
this.sortDirection = 0;
|
|
141
|
+
this.sortCompareFunction = null;
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
[clearSymbol] = this.clear;
|
|
146
|
+
|
|
147
|
+
valueOf() {
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get [Symbol.toStringTag]() {
|
|
152
|
+
return "SubscriptionArray";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
static updateSymbol = updateSymbol;
|
|
157
|
+
static getHandleUpdateSymbol = getHandleUpdateSymbol;
|
|
158
|
+
static setHandleUpdateSymbol = setHandleUpdateSymbol;
|
|
159
|
+
static getAsUpdatesSymbol = getAsUpdatesSymbol;
|
|
160
|
+
static getAsInitialUpdatedSymbol = getAsInitialUpdatedSymbol;
|
|
161
|
+
static clearSymbol = clearSymbol;
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
SubscriptionArray.WithSubscription = class SubscriptionArrayWithSubscription extends SubscriptionArray {
|
|
167
|
+
constructor(publicationName, params, onUpdate, immediately = true) {
|
|
168
|
+
super(null, onUpdate);
|
|
169
|
+
|
|
170
|
+
this.publicationName = publicationName;
|
|
171
|
+
this.params = params;
|
|
172
|
+
|
|
173
|
+
if (immediately)
|
|
174
|
+
this.subscribe();
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
subscription = null;
|
|
179
|
+
|
|
180
|
+
subscribe() {
|
|
181
|
+
|
|
182
|
+
if (!this.subscription)
|
|
183
|
+
this.subscription = new Subscription("array", this.publicationName, this.params, updates => this.update(updates));
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
get [subscribeSymbol]() {
|
|
188
|
+
return this.subscribe;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
unsubscribe() {
|
|
192
|
+
|
|
193
|
+
if (this.subscription) {
|
|
194
|
+
this.subscription.cancel();
|
|
195
|
+
this.subscription = null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
get [unsubscribeSymbol]() {
|
|
201
|
+
return this.unsubscribe;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
renew(publicationName, params) {
|
|
205
|
+
|
|
206
|
+
if (this.subscription) {
|
|
207
|
+
this.unsubscribe();
|
|
208
|
+
|
|
209
|
+
if (publicationName)
|
|
210
|
+
if (Array.isArray(publicationName))
|
|
211
|
+
params = publicationName;
|
|
212
|
+
else
|
|
213
|
+
this.publicationName = publicationName;
|
|
214
|
+
|
|
215
|
+
if (params)
|
|
216
|
+
this.params = params;
|
|
217
|
+
|
|
218
|
+
this.subscribe();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get [renewSymbol]() {
|
|
224
|
+
return this.renew;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
[getSubscriptionSymbol]() {
|
|
228
|
+
return this.subscription;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get [Symbol.toStringTag]() {
|
|
232
|
+
return "SubscriptionArrayWithSubscription";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
static subscribeSymbol = subscribeSymbol;
|
|
237
|
+
static unsubscribeSymbol = unsubscribeSymbol;
|
|
238
|
+
static renewSymbol = renewSymbol;
|
|
239
|
+
static getSubscriptionSymbol = getSubscriptionSymbol;
|
|
240
|
+
|
|
241
|
+
};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { debounce } from "@nesvet/n";
|
|
2
|
+
import EventEmitter from "eventemitter3";
|
|
3
|
+
import { privates } from "./common";
|
|
4
|
+
import { SubscriptionGroupItem } from "./SubscriptionGroupItem";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function parseDefinition(definition) {
|
|
8
|
+
if (Array.isArray(definition)) {
|
|
9
|
+
const args = definition.slice();
|
|
10
|
+
|
|
11
|
+
const parsed = {};
|
|
12
|
+
|
|
13
|
+
parsed.name = args.shift();
|
|
14
|
+
if (typeof args[0] == "object" && !Array.isArray(args[0])) {
|
|
15
|
+
parsed.value = args.shift();
|
|
16
|
+
parsed.type = parsed.value.toString().match(/Subscription(Object|Array|Map)/)[1];
|
|
17
|
+
if (parsed.type)
|
|
18
|
+
parsed.type = parsed.type.toLowerCase();
|
|
19
|
+
else
|
|
20
|
+
throw new Error("Unknown value type");
|
|
21
|
+
} else {
|
|
22
|
+
if (typeof args[0] == "string")
|
|
23
|
+
parsed.type = args.shift();
|
|
24
|
+
if (typeof args[0] == "string")
|
|
25
|
+
parsed.publicationName = args.shift();
|
|
26
|
+
if (Array.isArray(args[0]))
|
|
27
|
+
parsed.params = args.shift();
|
|
28
|
+
}
|
|
29
|
+
if (typeof args[0] == "function")
|
|
30
|
+
parsed.handle = args.shift();
|
|
31
|
+
if (typeof args[0] == "function")
|
|
32
|
+
parsed.onBeforeInit = args.shift();
|
|
33
|
+
if (typeof args[0] == "number")
|
|
34
|
+
parsed.debounceLimit = args.shift();
|
|
35
|
+
if (typeof args[0] == "boolean")
|
|
36
|
+
parsed.preventBind = args.shift();
|
|
37
|
+
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return definition;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class SubscriptionGroup extends EventEmitter {
|
|
45
|
+
constructor(definitions, options = {}) {
|
|
46
|
+
super();
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
target,
|
|
50
|
+
debounce: debounceLimit = SubscriptionGroup.debounceLimit,
|
|
51
|
+
immediately
|
|
52
|
+
} = options;
|
|
53
|
+
|
|
54
|
+
this.#applyOptions({ target, debounceLimit });
|
|
55
|
+
|
|
56
|
+
this.#initPromise = new Promise(resolve => (this.#initResolve = resolve));
|
|
57
|
+
|
|
58
|
+
this.attach(definitions, false, immediately);
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
items = [];
|
|
63
|
+
values = [];
|
|
64
|
+
|
|
65
|
+
isLoaded = false;
|
|
66
|
+
isInited = false;
|
|
67
|
+
|
|
68
|
+
#loadPromise;
|
|
69
|
+
#initPromise;
|
|
70
|
+
#unloadPromise;
|
|
71
|
+
#loadResolve;
|
|
72
|
+
#initResolve;
|
|
73
|
+
#unloadResolve;
|
|
74
|
+
|
|
75
|
+
#debounceLimit = null;
|
|
76
|
+
|
|
77
|
+
#applyOptions({ target, debounceLimit }) {
|
|
78
|
+
|
|
79
|
+
if (this.target !== target) {
|
|
80
|
+
if (this.target)
|
|
81
|
+
for (const item of this.items)
|
|
82
|
+
if (item.isLoaded && !item.preventBind)
|
|
83
|
+
delete this.target[item.name];
|
|
84
|
+
|
|
85
|
+
this.target = target;
|
|
86
|
+
|
|
87
|
+
if (this.target)
|
|
88
|
+
for (const item of this.items)
|
|
89
|
+
if (item.isLoaded && !item.preventBind)
|
|
90
|
+
this.target[item.name] = item.value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.#debounceLimit !== debounceLimit) {
|
|
94
|
+
this.#debounceLimit = debounceLimit;
|
|
95
|
+
if (typeof this.#debounceLimit == "number") {
|
|
96
|
+
const emitUpdateDebounced = debounce(() => this.emit("update", this.values), this.#debounceLimit);
|
|
97
|
+
this.emitUpdate = () => emitUpdateDebounced();
|
|
98
|
+
} else
|
|
99
|
+
this.emitUpdate = () => this.emit("update", this.values);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
attach(definitions, shouldReload = this.isLoaded, immediately = true) {
|
|
105
|
+
if (shouldReload)
|
|
106
|
+
this.isLoaded = false;
|
|
107
|
+
|
|
108
|
+
if (!this.#loadPromise || this.#loadPromise.isResolved)
|
|
109
|
+
this.#loadPromise = new Promise(resolve => (this.#loadResolve = resolve));
|
|
110
|
+
|
|
111
|
+
if (!this.#unloadPromise || this.#unloadPromise.isResolved)
|
|
112
|
+
this.#unloadPromise = new Promise(resolve => (this.#unloadResolve = resolve));
|
|
113
|
+
|
|
114
|
+
return Promise.all(definitions.map(definition =>
|
|
115
|
+
new SubscriptionGroupItem(parseDefinition(definition), this)
|
|
116
|
+
).map(item => {
|
|
117
|
+
|
|
118
|
+
if (immediately)
|
|
119
|
+
item.subscribe();
|
|
120
|
+
|
|
121
|
+
return item.loaded();
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
detach(names, shouldUpdate = true) {
|
|
126
|
+
|
|
127
|
+
for (const name of names)
|
|
128
|
+
this.items[name]?.detach();
|
|
129
|
+
|
|
130
|
+
if (shouldUpdate) {
|
|
131
|
+
this.#unload();
|
|
132
|
+
this.#load();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
redefine(definitions) {
|
|
138
|
+
|
|
139
|
+
const itemsToDetach = new Map(this.items.map(item => [ item.name, item ]));
|
|
140
|
+
const definitionsToRedefine = [];
|
|
141
|
+
const definitionsToAttach = [];
|
|
142
|
+
|
|
143
|
+
for (let definition of definitions) {
|
|
144
|
+
definition = parseDefinition(definition);
|
|
145
|
+
if (itemsToDetach.delete(definition.name))
|
|
146
|
+
definitionsToRedefine.push(definition);
|
|
147
|
+
else
|
|
148
|
+
definitionsToAttach.push(definition);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.isLoaded = false;
|
|
152
|
+
|
|
153
|
+
this.detach([ ...itemsToDetach.keys() ], false);
|
|
154
|
+
|
|
155
|
+
return Promise.all([
|
|
156
|
+
...definitionsToRedefine.map(definition => {
|
|
157
|
+
const item = this.items[definition.name];
|
|
158
|
+
item.define(definition);
|
|
159
|
+
|
|
160
|
+
item.subscribe();
|
|
161
|
+
|
|
162
|
+
return item.loaded();
|
|
163
|
+
}),
|
|
164
|
+
...definitionsToAttach.length ? [ this.attach(definitionsToAttach, false) ] : []
|
|
165
|
+
]);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
subscribe() {
|
|
169
|
+
return this.items.map(item => item.subscribe());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
unsubscribe() {
|
|
173
|
+
return this.items.map(item => item.unsubscribe());
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#load() {
|
|
177
|
+
|
|
178
|
+
if (!this.isLoaded && this.items.every(item => item.isLoaded)) {
|
|
179
|
+
if (this.target)
|
|
180
|
+
for (const item of this.items)
|
|
181
|
+
if (!item.preventBind)
|
|
182
|
+
this.target[item.name] = item.value;
|
|
183
|
+
|
|
184
|
+
this.isLoaded = true;
|
|
185
|
+
|
|
186
|
+
for (const item of this.items)
|
|
187
|
+
privates.itemLoad(item);
|
|
188
|
+
|
|
189
|
+
this.emit("load", this.values);
|
|
190
|
+
|
|
191
|
+
if (this.isInited)
|
|
192
|
+
if (this.items.length)
|
|
193
|
+
for (const item of this.items)
|
|
194
|
+
item.emitUpdate();
|
|
195
|
+
else
|
|
196
|
+
this.emitUpdate();
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
this.#loadResolve(this);
|
|
200
|
+
this.#loadPromise.isResolved = true;
|
|
201
|
+
|
|
202
|
+
if (this.#unloadPromise.isResolved)
|
|
203
|
+
this.#unloadPromise = new Promise(resolve => (this.#unloadResolve = resolve));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#init() {
|
|
209
|
+
|
|
210
|
+
if (!this.isInited && this.items.every(item => item.isInited)) {
|
|
211
|
+
this.isInited = true;
|
|
212
|
+
|
|
213
|
+
if (this.isLoaded)
|
|
214
|
+
if (this.items.length)
|
|
215
|
+
for (const item of this.items)
|
|
216
|
+
item.emitUpdate();
|
|
217
|
+
else
|
|
218
|
+
this.emitUpdate();
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
for (const item of this.items)
|
|
222
|
+
privates.itemInit(item);
|
|
223
|
+
|
|
224
|
+
this.emit("init", this.values);
|
|
225
|
+
|
|
226
|
+
this.#initResolve(this);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
#unload() {
|
|
232
|
+
|
|
233
|
+
if (this.isLoaded && this.items.every(item => !item.isLoaded)) {
|
|
234
|
+
if (this.target)
|
|
235
|
+
for (const item of this.items)
|
|
236
|
+
if (!item.preventBind)
|
|
237
|
+
delete this.target[item.name];
|
|
238
|
+
|
|
239
|
+
this.isLoaded = false;
|
|
240
|
+
|
|
241
|
+
for (const item of this.items)
|
|
242
|
+
privates.itemUnload(item);
|
|
243
|
+
|
|
244
|
+
this.emit("unload", this.values);
|
|
245
|
+
|
|
246
|
+
if (this.items.length)
|
|
247
|
+
for (const item of this.items)
|
|
248
|
+
item.emitUpdate();
|
|
249
|
+
else
|
|
250
|
+
this.emitUpdate();
|
|
251
|
+
|
|
252
|
+
this.#unloadResolve(this);
|
|
253
|
+
this.#unloadPromise.isResolved = true;
|
|
254
|
+
|
|
255
|
+
if (this.#loadPromise.isResolved)
|
|
256
|
+
this.#loadPromise = new Promise(resolve => (this.#loadResolve = resolve));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
loaded() {
|
|
262
|
+
return this.#loadPromise;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
inited() {
|
|
266
|
+
return this.#initPromise;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
unloaded() {
|
|
270
|
+
return this.#unloadPromise;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
valueOf() {
|
|
274
|
+
return this.values;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
[Symbol.iterator]() {
|
|
278
|
+
return this.values[Symbol.iterator]();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
static debounceLimit = 8;
|
|
283
|
+
|
|
284
|
+
static {
|
|
285
|
+
|
|
286
|
+
privates.groupLoad = group => group.#load();
|
|
287
|
+
privates.groupInit = group => group.#init();
|
|
288
|
+
privates.groupUnload = group => group.#unload();
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
}
|