synapse-storage 3.0.3 → 3.0.4
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/api.cjs +1 -891
- package/dist/api.js +1 -860
- package/dist/chunk-22J2S57D.cjs +1 -0
- package/dist/chunk-4USKKL5R.js +1 -0
- package/dist/chunk-5X65PSGD.js +1 -0
- package/dist/chunk-635Q6YJZ.cjs +1 -0
- package/dist/chunk-6RNZVHSR.js +1 -0
- package/dist/chunk-FW5NGLPP.cjs +1 -0
- package/dist/chunk-IPUPRMZK.js +1 -0
- package/dist/chunk-NMDHQXMS.cjs +1 -0
- package/dist/chunk-S7X7IDBT.js +1 -0
- package/dist/chunk-UFBCZ25Y.cjs +1 -0
- package/dist/chunk-VSIVOWZF.cjs +1 -0
- package/dist/chunk-WC5TDS6C.cjs +1 -0
- package/dist/chunk-WQNH3LVB.js +1 -0
- package/dist/chunk-ZE2EJX2Y.js +1 -0
- package/dist/core.cjs +1 -2389
- package/dist/core.js +1 -2356
- package/dist/index.cjs +1 -4148
- package/dist/index.js +1 -4093
- package/dist/react.cjs +1 -268
- package/dist/react.js +1 -239
- package/dist/reactive.cjs +1 -643
- package/dist/reactive.js +1 -604
- package/dist/utils.cjs +1 -601
- package/dist/utils.js +1 -574
- package/package.json +1 -1
- package/dist/api.cjs.map +0 -1
- package/dist/api.js.map +0 -1
- package/dist/core.cjs.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/react.cjs.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/reactive.cjs.map +0 -1
- package/dist/reactive.js.map +0 -1
- package/dist/utils.cjs.map +0 -1
- package/dist/utils.js.map +0 -1
package/dist/utils.js
CHANGED
|
@@ -1,574 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var DEBUG = false;
|
|
3
|
-
var GLOBAL_SELECTOR_CACHE = /* @__PURE__ */ new Map();
|
|
4
|
-
function getStringHash(str) {
|
|
5
|
-
let hash = 0;
|
|
6
|
-
if (str.length === 0) return hash.toString(36);
|
|
7
|
-
for (let i = 0; i < str.length; i++) {
|
|
8
|
-
const char = str.charCodeAt(i);
|
|
9
|
-
hash = (hash << 5) - hash + char;
|
|
10
|
-
hash = hash & hash;
|
|
11
|
-
}
|
|
12
|
-
return Math.abs(hash).toString(36).substring(0, 6);
|
|
13
|
-
}
|
|
14
|
-
function defaultEquals(a, b) {
|
|
15
|
-
if (a === b) return true;
|
|
16
|
-
if (a == null || b == null) return false;
|
|
17
|
-
if (typeof a !== "object" && typeof a !== "function" && typeof b !== "object" && typeof b !== "function") {
|
|
18
|
-
return a === b;
|
|
19
|
-
}
|
|
20
|
-
if (typeof a !== typeof b) return false;
|
|
21
|
-
if (a instanceof Date && b instanceof Date) {
|
|
22
|
-
return a.getTime() === b.getTime();
|
|
23
|
-
}
|
|
24
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
25
|
-
if (a.length !== b.length) return false;
|
|
26
|
-
for (let i = 0; i < a.length; i++) {
|
|
27
|
-
if (!defaultEquals(a[i], b[i])) return false;
|
|
28
|
-
}
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
if (typeof a === "object" && typeof b === "object") {
|
|
32
|
-
const keysA = Object.keys(a);
|
|
33
|
-
const keysB = Object.keys(b);
|
|
34
|
-
if (keysA.length !== keysB.length) return false;
|
|
35
|
-
return keysA.every((key) => {
|
|
36
|
-
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
|
|
37
|
-
return defaultEquals(a[key], b[key]);
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
function memoizeSelector(selectorFn, equals = defaultEquals) {
|
|
43
|
-
let lastState;
|
|
44
|
-
let lastResult;
|
|
45
|
-
let hasResult = false;
|
|
46
|
-
return function memoized(state) {
|
|
47
|
-
if (!hasResult || lastState !== state) {
|
|
48
|
-
const newResult = selectorFn(state);
|
|
49
|
-
if (!hasResult || !equals(newResult, lastResult)) {
|
|
50
|
-
lastResult = newResult;
|
|
51
|
-
}
|
|
52
|
-
lastState = state;
|
|
53
|
-
hasResult = true;
|
|
54
|
-
}
|
|
55
|
-
return lastResult;
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
var SelectorSubscription = class {
|
|
59
|
-
constructor(name, getState, equals = defaultEquals, logger) {
|
|
60
|
-
this.name = name;
|
|
61
|
-
this.equals = equals;
|
|
62
|
-
this.logger = logger;
|
|
63
|
-
this.id = name;
|
|
64
|
-
this.memoizedGetState = this.createMemoizedGetState(getState);
|
|
65
|
-
if (DEBUG) {
|
|
66
|
-
console.log(`[${this.id}] \u0421\u043E\u0437\u0434\u0430\u043D new SelectorSubscription`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
id;
|
|
70
|
-
subscribers = /* @__PURE__ */ new Set();
|
|
71
|
-
lastValue;
|
|
72
|
-
memoizedGetState;
|
|
73
|
-
// Создает мемоизированную версию getState с кешированием результата
|
|
74
|
-
createMemoizedGetState(getState) {
|
|
75
|
-
let lastPromise = null;
|
|
76
|
-
let isExecuting = false;
|
|
77
|
-
return async () => {
|
|
78
|
-
if (isExecuting && lastPromise) {
|
|
79
|
-
return lastPromise;
|
|
80
|
-
}
|
|
81
|
-
isExecuting = true;
|
|
82
|
-
try {
|
|
83
|
-
lastPromise = getState();
|
|
84
|
-
return await lastPromise;
|
|
85
|
-
} finally {
|
|
86
|
-
isExecuting = false;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
async notify() {
|
|
91
|
-
try {
|
|
92
|
-
const newValue = await this.memoizedGetState();
|
|
93
|
-
if (this.lastValue === void 0 || !this.equals(newValue, this.lastValue)) {
|
|
94
|
-
if (DEBUG) {
|
|
95
|
-
console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C, notify()`, {
|
|
96
|
-
old: this.lastValue,
|
|
97
|
-
new: newValue
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
this.lastValue = newValue;
|
|
101
|
-
const promises = Array.from(this.subscribers).map(async (subscriber) => {
|
|
102
|
-
try {
|
|
103
|
-
await subscriber.notify(newValue);
|
|
104
|
-
} catch (error) {
|
|
105
|
-
this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u0430`, { error });
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
await Promise.all(promises);
|
|
109
|
-
} else if (DEBUG) {
|
|
110
|
-
console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C in notify(), \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F`);
|
|
111
|
-
}
|
|
112
|
-
} catch (error) {
|
|
113
|
-
this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 notify()`, { error });
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
subscribe(subscriber) {
|
|
118
|
-
if (DEBUG) {
|
|
119
|
-
console.log(`[${this.id}] \u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u043E \u043D\u043E\u0432\u044B\u0439 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A, \u0432\u0441\u0435\u0433\u043E: ${this.subscribers.size + 1}`);
|
|
120
|
-
}
|
|
121
|
-
this.subscribers.add(subscriber);
|
|
122
|
-
if (this.lastValue !== void 0) {
|
|
123
|
-
Promise.resolve().then(() => {
|
|
124
|
-
try {
|
|
125
|
-
subscriber.notify(this.lastValue);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043F\u0435\u0440\u0432\u043E\u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438`, { error });
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
} else {
|
|
131
|
-
this.notify().catch((error) => {
|
|
132
|
-
this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043F\u0435\u0440\u0432\u043E\u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438`, { error });
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
return () => {
|
|
136
|
-
if (DEBUG) {
|
|
137
|
-
console.log(`[${this.id}] \u041F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A \u0443\u0434\u0430\u043B\u0435\u043D, \u043E\u0441\u0442\u0430\u043B\u043E\u0441\u044C: ${this.subscribers.size - 1}`);
|
|
138
|
-
}
|
|
139
|
-
this.subscribers.delete(subscriber);
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
cleanup() {
|
|
143
|
-
if (DEBUG) {
|
|
144
|
-
console.log(`[${this.id}] \u041E\u0447\u0438\u0441\u0442\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438, \u0431\u044B\u043B\u043E ${this.subscribers.size} \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u043E\u0432`);
|
|
145
|
-
}
|
|
146
|
-
this.subscribers.clear();
|
|
147
|
-
this.lastValue = void 0;
|
|
148
|
-
}
|
|
149
|
-
getId() {
|
|
150
|
-
return this.id;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
var SelectorModule = class {
|
|
154
|
-
constructor(source, logger) {
|
|
155
|
-
this.source = source;
|
|
156
|
-
this.logger = logger;
|
|
157
|
-
this.storageName = source.name;
|
|
158
|
-
if (DEBUG) {
|
|
159
|
-
console.log(`\u0421\u043E\u0437\u0434\u0430\u043D SelectorModule \u0434\u043B\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430: ${this.storageName}`);
|
|
160
|
-
}
|
|
161
|
-
this.source.getState().then((state) => {
|
|
162
|
-
this.cachedState = state;
|
|
163
|
-
if (DEBUG) {
|
|
164
|
-
console.log(`\u041A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0434\u043B\u044F ${this.storageName}`);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
storageName;
|
|
169
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
170
|
-
cachedState;
|
|
171
|
-
localSelectorCache = /* @__PURE__ */ new Map();
|
|
172
|
-
// Флаг для батчинга обновлений
|
|
173
|
-
batchUpdateInProgress = false;
|
|
174
|
-
pendingUpdates = /* @__PURE__ */ new Set();
|
|
175
|
-
/**
|
|
176
|
-
* Генерирует имя для селектора на основе его типа и функции
|
|
177
|
-
*/
|
|
178
|
-
generateName(isSimpleSelector, selectorOrDeps, resultFnOrOptions) {
|
|
179
|
-
const type = isSimpleSelector ? "simple" : "combined";
|
|
180
|
-
let hash = "";
|
|
181
|
-
if (isSimpleSelector) {
|
|
182
|
-
const selectorStr = selectorOrDeps.toString();
|
|
183
|
-
hash = getStringHash(selectorStr);
|
|
184
|
-
} else {
|
|
185
|
-
const depsIds = selectorOrDeps.map((s) => s.getId()).join("_");
|
|
186
|
-
const resultFnStr = resultFnOrOptions.toString();
|
|
187
|
-
hash = getStringHash(depsIds + resultFnStr);
|
|
188
|
-
}
|
|
189
|
-
return `${this.storageName}_${type}_${hash}`;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Обрабатывает отложенные обновления, чтобы избежать каскадных уведомлений
|
|
193
|
-
*/
|
|
194
|
-
processPendingUpdates() {
|
|
195
|
-
if (this.pendingUpdates.size === 0 || this.batchUpdateInProgress) return;
|
|
196
|
-
this.batchUpdateInProgress = true;
|
|
197
|
-
setTimeout(async () => {
|
|
198
|
-
try {
|
|
199
|
-
const subscriptionsToUpdate = Array.from(this.pendingUpdates);
|
|
200
|
-
this.pendingUpdates.clear();
|
|
201
|
-
this.cachedState = await this.source.getState();
|
|
202
|
-
const updatePromises = subscriptionsToUpdate.map(async (id) => {
|
|
203
|
-
const subscription = this.subscriptions.get(id);
|
|
204
|
-
if (subscription) {
|
|
205
|
-
try {
|
|
206
|
-
return await subscription.notify();
|
|
207
|
-
} catch (error) {
|
|
208
|
-
this.logger?.error(`\u041E\u0448\u0438\u0431\u043A\u0430 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u0430 ${id}`, { error });
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return Promise.resolve();
|
|
212
|
-
});
|
|
213
|
-
await Promise.all(updatePromises);
|
|
214
|
-
} catch (error) {
|
|
215
|
-
this.logger?.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0438 \u043E\u0436\u0438\u0434\u0430\u044E\u0449\u0438\u0445 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439", { error });
|
|
216
|
-
} finally {
|
|
217
|
-
this.batchUpdateInProgress = false;
|
|
218
|
-
if (this.pendingUpdates.size > 0) {
|
|
219
|
-
this.processPendingUpdates();
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}, 0);
|
|
223
|
-
}
|
|
224
|
-
createSelector(selectorOrDeps, resultFnOrOptions, optionsArg) {
|
|
225
|
-
const isSimpleSelector = !Array.isArray(selectorOrDeps);
|
|
226
|
-
const options = isSimpleSelector ? resultFnOrOptions || {} : optionsArg || {};
|
|
227
|
-
const selectorId = options.name || this.generateName(isSimpleSelector, selectorOrDeps, isSimpleSelector ? void 0 : resultFnOrOptions);
|
|
228
|
-
if (this.localSelectorCache.has(selectorId)) {
|
|
229
|
-
if (DEBUG) {
|
|
230
|
-
console.log(`[${this.storageName}] Reusing cached selector: ${selectorId}`);
|
|
231
|
-
}
|
|
232
|
-
return this.localSelectorCache.get(selectorId).api;
|
|
233
|
-
}
|
|
234
|
-
if (GLOBAL_SELECTOR_CACHE.has(selectorId)) {
|
|
235
|
-
const cached = GLOBAL_SELECTOR_CACHE.get(selectorId);
|
|
236
|
-
cached.refCount++;
|
|
237
|
-
if (DEBUG) {
|
|
238
|
-
console.log(`[${this.storageName}] \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440\u0430: ${selectorId}, refCount: ${cached.refCount}`);
|
|
239
|
-
}
|
|
240
|
-
return cached.api;
|
|
241
|
-
}
|
|
242
|
-
let result;
|
|
243
|
-
let dependencies;
|
|
244
|
-
let unsubscribeFunctions = [];
|
|
245
|
-
if (isSimpleSelector) {
|
|
246
|
-
const memoized = memoizeSelector(selectorOrDeps, options.equals || defaultEquals);
|
|
247
|
-
const created = this.createSimpleSelector(memoized, { ...options, name: selectorId, equals: options.equals || defaultEquals });
|
|
248
|
-
result = created.api;
|
|
249
|
-
unsubscribeFunctions = created.unsubscribeFunctions;
|
|
250
|
-
} else {
|
|
251
|
-
dependencies = selectorOrDeps;
|
|
252
|
-
const created = this.createCombinedSelector(dependencies, resultFnOrOptions, {
|
|
253
|
-
...options,
|
|
254
|
-
name: selectorId,
|
|
255
|
-
equals: options.equals || defaultEquals
|
|
256
|
-
});
|
|
257
|
-
result = created.api;
|
|
258
|
-
unsubscribeFunctions = created.unsubscribeFunctions;
|
|
259
|
-
}
|
|
260
|
-
this.localSelectorCache.set(selectorId, {
|
|
261
|
-
api: result,
|
|
262
|
-
dependencies,
|
|
263
|
-
unsubscribeFunctions
|
|
264
|
-
});
|
|
265
|
-
GLOBAL_SELECTOR_CACHE.set(selectorId, {
|
|
266
|
-
api: result,
|
|
267
|
-
refCount: 1,
|
|
268
|
-
unsubscribeFunctions
|
|
269
|
-
});
|
|
270
|
-
if (DEBUG) {
|
|
271
|
-
console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043D\u043E\u0432\u044B\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${selectorId}`);
|
|
272
|
-
}
|
|
273
|
-
return result;
|
|
274
|
-
}
|
|
275
|
-
createSimpleSelector(selector, options) {
|
|
276
|
-
if (DEBUG) {
|
|
277
|
-
console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043F\u0440\u043E\u0441\u0442\u043E\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${options.name}`);
|
|
278
|
-
}
|
|
279
|
-
const getState = async () => {
|
|
280
|
-
if (this.cachedState) {
|
|
281
|
-
return selector(this.cachedState);
|
|
282
|
-
}
|
|
283
|
-
const state = await this.source.getState();
|
|
284
|
-
this.cachedState = state;
|
|
285
|
-
return selector(state);
|
|
286
|
-
};
|
|
287
|
-
const subscription = new SelectorSubscription(options.name, getState, options.equals || defaultEquals, this.logger);
|
|
288
|
-
const id = subscription.getId();
|
|
289
|
-
this.subscriptions.set(id, subscription);
|
|
290
|
-
const unsubscribeFromStorage = this.source.subscribeToAll(async (event) => {
|
|
291
|
-
if (event?.type === "storage:update") {
|
|
292
|
-
if (DEBUG) {
|
|
293
|
-
console.log(`[${id}] \u041F\u043E\u043B\u0443\u0447\u0435\u043D\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430`);
|
|
294
|
-
}
|
|
295
|
-
this.pendingUpdates.add(id);
|
|
296
|
-
this.processPendingUpdates();
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
const unsubscribeFunctions = [unsubscribeFromStorage];
|
|
300
|
-
return {
|
|
301
|
-
api: {
|
|
302
|
-
select: () => getState(),
|
|
303
|
-
subscribe: (subscriber) => {
|
|
304
|
-
return subscription.subscribe(subscriber);
|
|
305
|
-
},
|
|
306
|
-
getId: () => id
|
|
307
|
-
},
|
|
308
|
-
unsubscribeFunctions
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
createCombinedSelector(selectors, resultFn, options) {
|
|
312
|
-
const memoizedResultFn = memoizeSelector((args) => resultFn(...args), options.equals || defaultEquals);
|
|
313
|
-
const getState = async () => {
|
|
314
|
-
const values = await Promise.all(selectors.map((s) => s.select()));
|
|
315
|
-
return memoizedResultFn(values);
|
|
316
|
-
};
|
|
317
|
-
const subscription = new SelectorSubscription(options.name, getState, options.equals || defaultEquals, this.logger);
|
|
318
|
-
const id = subscription.getId();
|
|
319
|
-
this.subscriptions.set(id, subscription);
|
|
320
|
-
let debounceTimer = null;
|
|
321
|
-
const triggerUpdate = () => {
|
|
322
|
-
if (debounceTimer !== null) {
|
|
323
|
-
clearTimeout(debounceTimer);
|
|
324
|
-
}
|
|
325
|
-
debounceTimer = setTimeout(() => {
|
|
326
|
-
debounceTimer = null;
|
|
327
|
-
subscription.notify().catch((error) => this.logger?.error(`[${id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043E\u0431\u044A\u0435\u0434\u0438\u043D\u0435\u043D\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438:`, { error }));
|
|
328
|
-
}, 10);
|
|
329
|
-
};
|
|
330
|
-
const unsubscribeFunctions = selectors.map(
|
|
331
|
-
(selector) => selector.subscribe({
|
|
332
|
-
notify: () => {
|
|
333
|
-
triggerUpdate();
|
|
334
|
-
}
|
|
335
|
-
})
|
|
336
|
-
);
|
|
337
|
-
return {
|
|
338
|
-
api: {
|
|
339
|
-
select: () => getState(),
|
|
340
|
-
subscribe: (subscriber) => {
|
|
341
|
-
return subscription.subscribe(subscriber);
|
|
342
|
-
},
|
|
343
|
-
getId: () => id
|
|
344
|
-
},
|
|
345
|
-
unsubscribeFunctions
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
destroy() {
|
|
349
|
-
if (DEBUG) {
|
|
350
|
-
console.log(`[${this.storageName}] \u041D\u0430\u0447\u0430\u043B\u043E\u0441\u044C \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u0438\u0435 SelectorModule`);
|
|
351
|
-
}
|
|
352
|
-
this.subscriptions.forEach((sub) => sub.cleanup());
|
|
353
|
-
this.subscriptions.clear();
|
|
354
|
-
this.cachedState = void 0;
|
|
355
|
-
this.pendingUpdates.clear();
|
|
356
|
-
this.localSelectorCache.forEach((cached) => {
|
|
357
|
-
cached.unsubscribeFunctions.forEach((unsub) => unsub());
|
|
358
|
-
});
|
|
359
|
-
const keysToCheck = /* @__PURE__ */ new Set();
|
|
360
|
-
this.localSelectorCache.forEach((_, key) => {
|
|
361
|
-
keysToCheck.add(key);
|
|
362
|
-
});
|
|
363
|
-
this.localSelectorCache.clear();
|
|
364
|
-
keysToCheck.forEach((key) => {
|
|
365
|
-
const globalCached = GLOBAL_SELECTOR_CACHE.get(key);
|
|
366
|
-
if (globalCached) {
|
|
367
|
-
globalCached.refCount--;
|
|
368
|
-
if (globalCached.refCount <= 0) {
|
|
369
|
-
globalCached.unsubscribeFunctions.forEach((unsub) => unsub());
|
|
370
|
-
GLOBAL_SELECTOR_CACHE.delete(key);
|
|
371
|
-
if (DEBUG) {
|
|
372
|
-
console.log(`[${this.storageName}] \u0423\u0434\u0430\u043B\u0435\u043D \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440 \u0438\u0437 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0430: ${key}`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
if (DEBUG) {
|
|
378
|
-
console.log(`[${this.storageName}] \u0423\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D`);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
// src/reactive/dispatcher/dispatcher.module.ts
|
|
384
|
-
import { Subject } from "rxjs";
|
|
385
|
-
|
|
386
|
-
// src/reactive/effects/effects.module.ts
|
|
387
|
-
import { combineLatest, merge, Observable as Observable4, of as of2, pipe, Subject as Subject2 } from "rxjs";
|
|
388
|
-
import { catchError, filter, map, share, switchMap, take } from "rxjs/operators";
|
|
389
|
-
|
|
390
|
-
// src/reactive/effects/utils/chunkRequestConsistent.ts
|
|
391
|
-
import { of } from "rxjs";
|
|
392
|
-
import { concatAll, delay, mergeMap, toArray } from "rxjs/operators";
|
|
393
|
-
|
|
394
|
-
// src/reactive/effects/utils/chunkRequestParallel.ts
|
|
395
|
-
import { forkJoin, timer } from "rxjs";
|
|
396
|
-
import { mergeMap as mergeMap2 } from "rxjs/operators";
|
|
397
|
-
|
|
398
|
-
// src/reactive/effects/effects.module.ts
|
|
399
|
-
var EffectsModule = class {
|
|
400
|
-
/**
|
|
401
|
-
* Создает модуль эффектов с доступом к состоянию, внешним состояниям и конфигурации
|
|
402
|
-
* @param storage Хранилище состояния
|
|
403
|
-
* @param externalStates Внешние состояния
|
|
404
|
-
* @param dispatchers Объект с диспетчерами
|
|
405
|
-
* @param services Объект с сервисами
|
|
406
|
-
* @param config Глобальная конфигурация для всех эффектов
|
|
407
|
-
*/
|
|
408
|
-
constructor(storage, externalStates = {}, dispatchers, services = {}, config = {}) {
|
|
409
|
-
this.storage = storage;
|
|
410
|
-
this.externalStates = externalStates;
|
|
411
|
-
this.dispatchers = dispatchers;
|
|
412
|
-
this.services = services;
|
|
413
|
-
this.config = config;
|
|
414
|
-
this.subscribeToDispatchers();
|
|
415
|
-
this.state$ = new Observable4((observer) => {
|
|
416
|
-
this.storage.getState().then((state) => observer.next(state));
|
|
417
|
-
const unsubscribe = this.storage.subscribeToAll(() => {
|
|
418
|
-
this.storage.getState().then((state) => observer.next(state));
|
|
419
|
-
});
|
|
420
|
-
return () => unsubscribe();
|
|
421
|
-
}).pipe(share());
|
|
422
|
-
}
|
|
423
|
-
effects = [];
|
|
424
|
-
subscriptions = [];
|
|
425
|
-
running = false;
|
|
426
|
-
action$ = new Subject2();
|
|
427
|
-
/**
|
|
428
|
-
* Поток состояния
|
|
429
|
-
*/
|
|
430
|
-
state$;
|
|
431
|
-
/**
|
|
432
|
-
* Подписывается на действия от всех диспетчеров
|
|
433
|
-
*/
|
|
434
|
-
subscribeToDispatchers() {
|
|
435
|
-
for (const [_, dispatcher] of Object.entries(this.dispatchers)) {
|
|
436
|
-
const subscription = dispatcher.actions.subscribe((action) => {
|
|
437
|
-
this.action$.next(action);
|
|
438
|
-
});
|
|
439
|
-
this.subscriptions.push(subscription);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
add(effect) {
|
|
443
|
-
this.effects.push(effect);
|
|
444
|
-
if (this.running) {
|
|
445
|
-
this.subscribeToEffect(effect);
|
|
446
|
-
}
|
|
447
|
-
return this;
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Добавляет несколько эффектов
|
|
451
|
-
* @param effects Эффекты для добавления
|
|
452
|
-
* @returns Текущий модуль
|
|
453
|
-
*/
|
|
454
|
-
addEffects(effects) {
|
|
455
|
-
effects.forEach((effect) => this.add(effect));
|
|
456
|
-
return this;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Запускает все эффекты
|
|
460
|
-
* @returns Текущий модуль
|
|
461
|
-
*/
|
|
462
|
-
start() {
|
|
463
|
-
if (this.running) {
|
|
464
|
-
return this;
|
|
465
|
-
}
|
|
466
|
-
this.effects.forEach((effect) => this.subscribeToEffect(effect));
|
|
467
|
-
this.running = true;
|
|
468
|
-
return this;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Останавливает все эффекты
|
|
472
|
-
* @returns Текущий модуль
|
|
473
|
-
*/
|
|
474
|
-
stop() {
|
|
475
|
-
this.subscriptions.forEach((sub) => sub.unsubscribe());
|
|
476
|
-
this.subscriptions = [];
|
|
477
|
-
this.running = false;
|
|
478
|
-
return this;
|
|
479
|
-
}
|
|
480
|
-
/**
|
|
481
|
-
* Подписывается на конкретный эффект
|
|
482
|
-
* @param effect Эффект для подписки
|
|
483
|
-
*/
|
|
484
|
-
subscribeToEffect(effect) {
|
|
485
|
-
try {
|
|
486
|
-
const output$ = effect(this.action$.asObservable(), this.state$, this.externalStates, this.dispatchers, this.services, this.config).pipe(
|
|
487
|
-
catchError((err) => {
|
|
488
|
-
console.error("Error in effect:", err);
|
|
489
|
-
return of2(null);
|
|
490
|
-
})
|
|
491
|
-
);
|
|
492
|
-
const subscription = output$.subscribe((result) => {
|
|
493
|
-
if (result === null || result === void 0) {
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
if (typeof result === "function") {
|
|
497
|
-
try {
|
|
498
|
-
result();
|
|
499
|
-
} catch (callError) {
|
|
500
|
-
console.error("Error calling effect result function:", callError);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
this.subscriptions.push(subscription);
|
|
505
|
-
} catch (setupError) {
|
|
506
|
-
console.error("Error setting up effect:", setupError);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
// src/utils/createSynapse.ts
|
|
512
|
-
async function createSynapse(config) {
|
|
513
|
-
const storageInstance = config.createStorageFn ? await config.createStorageFn() : config.storage;
|
|
514
|
-
const cleanupCallbacks = [];
|
|
515
|
-
const result = {
|
|
516
|
-
storage: storageInstance,
|
|
517
|
-
selectors: {},
|
|
518
|
-
destroy: async () => {
|
|
519
|
-
for (const callback of cleanupCallbacks) {
|
|
520
|
-
await callback();
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
cleanupCallbacks.push(() => storageInstance.destroy());
|
|
525
|
-
let dispatcher;
|
|
526
|
-
let selectorModule;
|
|
527
|
-
let effectsModule;
|
|
528
|
-
if (config.createSelectorsFn) {
|
|
529
|
-
try {
|
|
530
|
-
selectorModule = new SelectorModule(storageInstance);
|
|
531
|
-
const externalSelectors = config.externalSelectors || {};
|
|
532
|
-
result.selectors = config.createSelectorsFn(selectorModule, externalSelectors);
|
|
533
|
-
if (typeof selectorModule.destroy === "function") {
|
|
534
|
-
cleanupCallbacks.push(() => selectorModule.destroy());
|
|
535
|
-
}
|
|
536
|
-
} catch (error) {
|
|
537
|
-
console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F selectors:", error);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
if (config.createDispatcherFn) {
|
|
541
|
-
dispatcher = config.createDispatcherFn(storageInstance);
|
|
542
|
-
result.dispatcher = dispatcher;
|
|
543
|
-
if (dispatcher && "dispatch" in dispatcher) {
|
|
544
|
-
result.actions = dispatcher.dispatch;
|
|
545
|
-
if (typeof dispatcher.destroy === "function") {
|
|
546
|
-
cleanupCallbacks.push(() => dispatcher.destroy());
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (config.createEffectConfig && dispatcher) {
|
|
551
|
-
try {
|
|
552
|
-
const { dispatchers, api, config: effectConfig, externalStates } = config.createEffectConfig(dispatcher);
|
|
553
|
-
const effectExternalStates = externalStates || {};
|
|
554
|
-
effectsModule = new EffectsModule(storageInstance, effectExternalStates, dispatchers, api, effectConfig);
|
|
555
|
-
if (Array.isArray(config.effects)) {
|
|
556
|
-
config.effects.forEach((effect) => {
|
|
557
|
-
if (effectsModule) effectsModule.add(effect);
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
effectsModule.start();
|
|
561
|
-
result.state$ = effectsModule.state$;
|
|
562
|
-
cleanupCallbacks.push(() => {
|
|
563
|
-
if (effectsModule) effectsModule.stop();
|
|
564
|
-
});
|
|
565
|
-
} catch (error) {
|
|
566
|
-
console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043C\u043E\u0434\u0443\u043B\u044F \u044D\u0444\u0444\u0435\u043A\u0442\u043E\u0432:", error);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
return result;
|
|
570
|
-
}
|
|
571
|
-
export {
|
|
572
|
-
createSynapse
|
|
573
|
-
};
|
|
574
|
-
//# sourceMappingURL=utils.js.map
|
|
1
|
+
export{a as createSynapse}from'./chunk-WQNH3LVB.js';import'./chunk-6RNZVHSR.js';import'./chunk-IPUPRMZK.js';import'./chunk-ZE2EJX2Y.js';import'./chunk-5X65PSGD.js';
|