synapse-storage 3.0.7 → 3.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -1
- package/dist/api.js +857 -4
- package/dist/core.js +2387 -2
- package/dist/index.js +4124 -5
- package/dist/react.js +238 -2
- package/dist/reactive.js +603 -2
- package/dist/utils.js +570 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,2 +1,238 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// src/react/hooks/useSelector.ts
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
var SELECTOR_REGISTRY = /* @__PURE__ */ new Map();
|
|
4
|
+
function useSelector(selector, options) {
|
|
5
|
+
const [state, setState] = useState(options?.initialValue);
|
|
6
|
+
const [isLoading, setIsLoading] = useState(!!options?.withLoading);
|
|
7
|
+
const prevValueRef = useRef(options?.initialValue);
|
|
8
|
+
const equalsRef = useRef(options?.equals || ((a, b) => a === b));
|
|
9
|
+
const selectorId = selector.getId();
|
|
10
|
+
const updateComponentState = (newValue) => {
|
|
11
|
+
if (prevValueRef.current === void 0 || !equalsRef.current(newValue, prevValueRef.current)) {
|
|
12
|
+
prevValueRef.current = newValue;
|
|
13
|
+
setState(newValue);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!SELECTOR_REGISTRY.has(selectorId)) {
|
|
18
|
+
SELECTOR_REGISTRY.set(selectorId, {
|
|
19
|
+
lastValue: void 0,
|
|
20
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
21
|
+
unsubscribe: null
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const registry = SELECTOR_REGISTRY.get(selectorId);
|
|
25
|
+
registry.listeners.add(updateComponentState);
|
|
26
|
+
if (registry.lastValue !== void 0) {
|
|
27
|
+
updateComponentState(registry.lastValue);
|
|
28
|
+
if (options?.withLoading) {
|
|
29
|
+
setIsLoading(false);
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
if (options?.withLoading) setIsLoading(true);
|
|
33
|
+
selector.select().then((initialValue) => {
|
|
34
|
+
registry.lastValue = initialValue;
|
|
35
|
+
registry.listeners.forEach((listener) => listener(initialValue));
|
|
36
|
+
if (options?.withLoading) setIsLoading(false);
|
|
37
|
+
}).catch((error) => {
|
|
38
|
+
console.error(`useSelector: \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0438 \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0434\u043B\u044F ${selectorId}`, error);
|
|
39
|
+
if (options?.withLoading) setIsLoading(false);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (!registry.unsubscribe) {
|
|
43
|
+
registry.unsubscribe = selector.subscribe({
|
|
44
|
+
notify: (newValue) => {
|
|
45
|
+
registry.lastValue = newValue;
|
|
46
|
+
registry.listeners.forEach((listener) => {
|
|
47
|
+
try {
|
|
48
|
+
listener(newValue);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error(`useSelector: \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438 \u0441\u043B\u0443\u0448\u0430\u0442\u0435\u043B\u044F \u0434\u043B\u044F ${selectorId}`, error);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return () => {
|
|
57
|
+
const registry2 = SELECTOR_REGISTRY.get(selectorId);
|
|
58
|
+
if (registry2) {
|
|
59
|
+
registry2.listeners.delete(updateComponentState);
|
|
60
|
+
if (registry2.listeners.size === 0) {
|
|
61
|
+
if (registry2.unsubscribe) {
|
|
62
|
+
registry2.unsubscribe();
|
|
63
|
+
}
|
|
64
|
+
SELECTOR_REGISTRY.delete(selectorId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, [selector, selectorId]);
|
|
69
|
+
if (options?.withLoading) {
|
|
70
|
+
return { data: state, isLoading };
|
|
71
|
+
}
|
|
72
|
+
return state;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/react/hooks/useStorageSubscribe.ts
|
|
76
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
77
|
+
var useStorageSubscribe = (storage, selector) => {
|
|
78
|
+
const [value, setValue] = useState2(void 0);
|
|
79
|
+
useEffect2(() => {
|
|
80
|
+
let isMounted = true;
|
|
81
|
+
const initializeValue = async () => {
|
|
82
|
+
try {
|
|
83
|
+
const state = await storage.getState();
|
|
84
|
+
const selectedValue = selector(state);
|
|
85
|
+
if (isMounted) {
|
|
86
|
+
setValue(selectedValue);
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("Failed to initialize storage value:", error);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
initializeValue();
|
|
93
|
+
let unsubscribe;
|
|
94
|
+
try {
|
|
95
|
+
unsubscribe = storage.subscribe(selector, (newValue) => {
|
|
96
|
+
if (isMounted) {
|
|
97
|
+
setValue(newValue);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("Failed to subscribe to storage:", error);
|
|
102
|
+
unsubscribe = () => {
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return () => {
|
|
106
|
+
isMounted = false;
|
|
107
|
+
unsubscribe();
|
|
108
|
+
};
|
|
109
|
+
}, [storage, selector]);
|
|
110
|
+
return value;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/react/utils/createSynapseCtx.tsx
|
|
114
|
+
import { createContext, useContext, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
115
|
+
|
|
116
|
+
// src/_utils/deepMerge.util.ts
|
|
117
|
+
var deepMerge = (target, source) => {
|
|
118
|
+
for (const key in source) {
|
|
119
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
120
|
+
if (typeof source[key] === "object" && source[key] !== null && !Array.isArray(source[key])) {
|
|
121
|
+
if (!target[key] || typeof target[key] !== "object") {
|
|
122
|
+
target[key] = {};
|
|
123
|
+
}
|
|
124
|
+
deepMerge(target[key], source[key]);
|
|
125
|
+
} else {
|
|
126
|
+
target[key] = source[key];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// src/react/utils/createSynapseCtx.tsx
|
|
133
|
+
import { jsx } from "react/jsx-runtime";
|
|
134
|
+
var ERROR_HOOK_MESSAGE = "useSynapseActions \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0432\u043D\u0443\u0442\u0440\u0438 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430 contextSynapse";
|
|
135
|
+
var ERROR_CONTEXT_INIT = "\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430:";
|
|
136
|
+
function createSynapseCtx(synapseStorePromise, options) {
|
|
137
|
+
const { loadingComponent = null, mergeFn = deepMerge } = options || {};
|
|
138
|
+
let synapseStore = null;
|
|
139
|
+
let storeReady = false;
|
|
140
|
+
const initPromise = (async () => {
|
|
141
|
+
try {
|
|
142
|
+
synapseStore = await (synapseStorePromise instanceof Promise ? synapseStorePromise : Promise.resolve(synapseStorePromise));
|
|
143
|
+
storeReady = true;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430 Synapse:", error);
|
|
146
|
+
}
|
|
147
|
+
})();
|
|
148
|
+
const SynapseContext = createContext(null);
|
|
149
|
+
const useSynapseStorage = () => {
|
|
150
|
+
const context = useContext(SynapseContext);
|
|
151
|
+
if (!context) throw new Error(ERROR_HOOK_MESSAGE);
|
|
152
|
+
return context.storage;
|
|
153
|
+
};
|
|
154
|
+
const useSynapseSelectors = () => {
|
|
155
|
+
const context = useContext(SynapseContext);
|
|
156
|
+
if (!context) throw new Error(ERROR_HOOK_MESSAGE);
|
|
157
|
+
return context.selectors;
|
|
158
|
+
};
|
|
159
|
+
const useSynapseActions = () => {
|
|
160
|
+
const context = useContext(SynapseContext);
|
|
161
|
+
if (!context) throw new Error(ERROR_HOOK_MESSAGE);
|
|
162
|
+
if ("actions" in context) {
|
|
163
|
+
return context.actions;
|
|
164
|
+
}
|
|
165
|
+
throw new Error("useSynapseActions: actions \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B \u0434\u043B\u044F \u044D\u0442\u043E\u0433\u043E \u0442\u0438\u043F\u0430 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044C, \u0447\u0442\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u043D\u0430 \u0444\u0443\u043D\u043A\u0446\u0438\u044F createDispatcherFn \u043F\u0440\u0438 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430.");
|
|
166
|
+
};
|
|
167
|
+
const useSynapseState$ = () => {
|
|
168
|
+
const context = useContext(SynapseContext);
|
|
169
|
+
if (!context) throw new Error(ERROR_HOOK_MESSAGE);
|
|
170
|
+
if ("state$" in context) {
|
|
171
|
+
return context.state$;
|
|
172
|
+
}
|
|
173
|
+
throw new Error("useSynapseState$: state$ \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0434\u043B\u044F \u044D\u0442\u043E\u0433\u043E \u0442\u0438\u043F\u0430 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044C, \u0447\u0442\u043E \u043F\u0435\u0440\u0435\u0434\u0430\u043D\u044B \u0444\u0443\u043D\u043A\u0446\u0438\u0438 createDispatcherFn \u0438 createEffectConfig \u043F\u0440\u0438 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430.");
|
|
174
|
+
};
|
|
175
|
+
function contextSynapse(Component) {
|
|
176
|
+
function WrappedComponent({ contextProps, ...props }) {
|
|
177
|
+
const [initialized, setInitialized] = useState3(false);
|
|
178
|
+
const [storeInitialized, setStoreInitialized] = useState3(storeReady);
|
|
179
|
+
const debugIdRef = useRef2(`synapse-${synapseStore?.storage.name || "initializing"}`);
|
|
180
|
+
useEffect3(() => {
|
|
181
|
+
if (!storeReady) {
|
|
182
|
+
initPromise.then(() => {
|
|
183
|
+
setStoreInitialized(true);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}, []);
|
|
187
|
+
useEffect3(() => {
|
|
188
|
+
if (!storeInitialized) return;
|
|
189
|
+
let mounted = true;
|
|
190
|
+
const initializeContext = async () => {
|
|
191
|
+
try {
|
|
192
|
+
if (synapseStore && contextProps && Object.keys(contextProps).length > 0) {
|
|
193
|
+
await synapseStore.storage.update((state) => {
|
|
194
|
+
mergeFn(state, contextProps);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
if (mounted) {
|
|
198
|
+
setInitialized(true);
|
|
199
|
+
}
|
|
200
|
+
} catch (error) {
|
|
201
|
+
console.error(`[${debugIdRef.current}] ${ERROR_CONTEXT_INIT}`, error);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
initializeContext();
|
|
205
|
+
return () => {
|
|
206
|
+
mounted = false;
|
|
207
|
+
};
|
|
208
|
+
}, [contextProps, storeInitialized]);
|
|
209
|
+
if (!storeInitialized) {
|
|
210
|
+
return loadingComponent || /* @__PURE__ */ jsx("div", { children: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430..." });
|
|
211
|
+
}
|
|
212
|
+
if (!initialized) {
|
|
213
|
+
return loadingComponent || /* @__PURE__ */ jsx("div", { children: "\u0418\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u044F \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430..." });
|
|
214
|
+
}
|
|
215
|
+
return /* @__PURE__ */ jsx(SynapseContext.Provider, { value: synapseStore, children: /* @__PURE__ */ jsx(Component, { ...props }) });
|
|
216
|
+
}
|
|
217
|
+
const componentName = Component.displayName || Component.name || "Component";
|
|
218
|
+
WrappedComponent.displayName = `SynapseContext(${componentName})`;
|
|
219
|
+
return WrappedComponent;
|
|
220
|
+
}
|
|
221
|
+
const cleanupSynapse = async () => {
|
|
222
|
+
await initPromise;
|
|
223
|
+
return synapseStore?.destroy() || Promise.resolve();
|
|
224
|
+
};
|
|
225
|
+
return {
|
|
226
|
+
contextSynapse,
|
|
227
|
+
useSynapseStorage,
|
|
228
|
+
useSynapseSelectors,
|
|
229
|
+
useSynapseActions,
|
|
230
|
+
useSynapseState$,
|
|
231
|
+
cleanupSynapse
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
export {
|
|
235
|
+
createSynapseCtx,
|
|
236
|
+
useSelector,
|
|
237
|
+
useStorageSubscribe
|
|
238
|
+
};
|