@composy/store-core 0.0.1 → 0.0.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/CHANGELOG.md +64 -3
- package/README.md +196 -172
- package/dist/index.js +1331 -1115
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +578 -417
- package/dist/index.min.js.map +1 -1
- package/es/.dts-output-manifest.json +1 -0
- package/es/.dts.tsbuildinfo +1 -0
- package/es/core/async-action.d.ts +1 -71
- package/es/core/async-action.js +83 -35
- package/es/core/async-action.js.map +1 -1
- package/es/core/base-store.d.ts +27 -62
- package/es/core/base-store.js +174 -74
- package/es/core/base-store.js.map +1 -1
- package/es/core/batch-manager.d.ts +0 -1
- package/es/core/batch-manager.js +15 -2
- package/es/core/batch-manager.js.map +1 -1
- package/es/core/create-store.d.ts +3 -3
- package/es/core/create-store.js +3 -3
- package/es/core/create-store.js.map +1 -1
- package/es/core/event-bus.d.ts +0 -1
- package/es/core/event-bus.js +1 -1
- package/es/core/event-bus.js.map +1 -1
- package/es/core/index.d.ts +1 -2
- package/es/core/index.js +2 -2
- package/es/core/pub-sub.d.ts +0 -1
- package/es/core/pub-sub.js +1 -1
- package/es/core/pub-sub.js.map +1 -1
- package/es/engine/index.d.ts +0 -1
- package/es/engine/index.js +1 -1
- package/es/engine/plugin.d.ts +0 -1
- package/es/engine/plugin.js +11 -2
- package/es/engine/plugin.js.map +1 -1
- package/es/engine/types.d.ts +0 -1
- package/es/engine/types.js +1 -1
- package/es/errors/index.d.ts +0 -1
- package/es/errors/index.js +17 -1
- package/es/errors/index.js.map +1 -1
- package/es/index.d.ts +3 -4
- package/es/index.js +8 -8
- package/es/index.js.map +1 -1
- package/es/middleware/index.d.ts +3 -4
- package/es/middleware/index.js +2 -2
- package/es/middleware/logger.d.ts +0 -1
- package/es/middleware/logger.js +2 -2
- package/es/middleware/logger.js.map +1 -1
- package/es/middleware/middleware-manager.d.ts +0 -1
- package/es/middleware/middleware-manager.js +5 -2
- package/es/middleware/middleware-manager.js.map +1 -1
- package/es/middleware/persist.d.ts +0 -1
- package/es/middleware/persist.js +3 -3
- package/es/middleware/persist.js.map +1 -1
- package/es/middleware/time-travel.d.ts +0 -1
- package/es/middleware/time-travel.js +1 -1
- package/es/middleware/time-travel.js.map +1 -1
- package/es/middleware/validation.d.ts +0 -1
- package/es/middleware/validation.js +2 -2
- package/es/middleware/validation.js.map +1 -1
- package/es/plugins/define-plugin.d.ts +1 -2
- package/es/plugins/define-plugin.js +2 -2
- package/es/plugins/define-plugin.js.map +1 -1
- package/es/plugins/index.d.ts +0 -1
- package/es/plugins/index.js +2 -2
- package/es/plugins/plugin-manager.d.ts +1 -31
- package/es/plugins/plugin-manager.js +58 -27
- package/es/plugins/plugin-manager.js.map +1 -1
- package/es/types/action.d.ts +2 -0
- package/es/types/action.js +10 -0
- package/es/types/batch.d.ts +2 -0
- package/es/types/batch.js +10 -0
- package/es/types/event.d.ts +2 -0
- package/es/types/event.js +10 -0
- package/es/types/index.d.ts +2 -3
- package/es/types/index.js +1 -1
- package/es/types/middleware.d.ts +10 -2
- package/es/types/middleware.js +1 -1
- package/es/types/mutation.d.ts +2 -0
- package/es/types/mutation.js +10 -0
- package/es/types/plugin.d.ts +4 -1
- package/es/types/plugin.js +1 -1
- package/es/types/state.d.ts +2 -0
- package/es/types/state.js +10 -0
- package/es/types/store.d.ts +19 -1
- package/es/types/store.js +1 -1
- package/es/types/subscription.d.ts +7 -2
- package/es/types/subscription.js +1 -1
- package/es/types/time-travel.d.ts +2 -0
- package/es/types/time-travel.js +10 -0
- package/es/types/utility.d.ts +3 -4
- package/es/types/utility.js +1 -1
- package/es/utils/debounce-throttle.d.ts +0 -1
- package/es/utils/debounce-throttle.js +1 -1
- package/es/utils/debounce-throttle.js.map +1 -1
- package/es/utils/deep-clone.d.ts +0 -1
- package/es/utils/deep-clone.js +1 -1
- package/es/utils/deep-clone.js.map +1 -1
- package/es/utils/index.d.ts +4 -5
- package/es/utils/index.js +1 -1
- package/es/utils/selector.d.ts +0 -1
- package/es/utils/selector.js +1 -1
- package/es/utils/selector.js.map +1 -1
- package/esm/core/async-action.js +83 -35
- package/esm/core/async-action.js.map +1 -1
- package/esm/core/base-store.js +174 -74
- package/esm/core/base-store.js.map +1 -1
- package/esm/core/batch-manager.js +15 -2
- package/esm/core/batch-manager.js.map +1 -1
- package/esm/core/create-store.js +3 -3
- package/esm/core/create-store.js.map +1 -1
- package/esm/core/event-bus.js +1 -1
- package/esm/core/event-bus.js.map +1 -1
- package/esm/core/index.js +2 -2
- package/esm/core/pub-sub.js +1 -1
- package/esm/core/pub-sub.js.map +1 -1
- package/esm/engine/index.js +1 -1
- package/esm/engine/plugin.js +11 -2
- package/esm/engine/plugin.js.map +1 -1
- package/esm/errors/index.js +17 -1
- package/esm/errors/index.js.map +1 -1
- package/esm/index.js +8 -8
- package/esm/index.js.map +1 -1
- package/esm/middleware/logger.js +2 -2
- package/esm/middleware/logger.js.map +1 -1
- package/esm/middleware/middleware-manager.js +5 -2
- package/esm/middleware/middleware-manager.js.map +1 -1
- package/esm/middleware/persist.js +3 -3
- package/esm/middleware/persist.js.map +1 -1
- package/esm/middleware/time-travel.js +1 -1
- package/esm/middleware/time-travel.js.map +1 -1
- package/esm/middleware/validation.js +2 -2
- package/esm/middleware/validation.js.map +1 -1
- package/esm/plugins/define-plugin.js +2 -2
- package/esm/plugins/define-plugin.js.map +1 -1
- package/esm/plugins/plugin-manager.js +58 -27
- package/esm/plugins/plugin-manager.js.map +1 -1
- package/esm/utils/debounce-throttle.js +1 -1
- package/esm/utils/debounce-throttle.js.map +1 -1
- package/esm/utils/deep-clone.js +1 -1
- package/esm/utils/deep-clone.js.map +1 -1
- package/esm/utils/selector.js +1 -1
- package/esm/utils/selector.js.map +1 -1
- package/lib/core/async-action.cjs +83 -35
- package/lib/core/async-action.cjs.map +1 -1
- package/lib/core/async-action.d.cts +25 -0
- package/lib/core/base-store.cjs +174 -74
- package/lib/core/base-store.cjs.map +1 -1
- package/lib/core/base-store.d.cts +50 -0
- package/lib/core/batch-manager.cjs +15 -2
- package/lib/core/batch-manager.cjs.map +1 -1
- package/{esm/core/batch-manager.d.ts → lib/core/batch-manager.d.cts} +0 -1
- package/lib/core/create-store.cjs +3 -3
- package/lib/core/create-store.cjs.map +1 -1
- package/lib/core/{create-store.d.ts → create-store.d.cts} +3 -3
- package/lib/core/event-bus.cjs +1 -1
- package/lib/core/event-bus.cjs.map +1 -1
- package/lib/core/{event-bus.d.ts → event-bus.d.cts} +0 -1
- package/lib/core/index.cjs +2 -2
- package/{esm/core/index.d.ts → lib/core/index.d.cts} +1 -2
- package/lib/core/pub-sub.cjs +1 -1
- package/lib/core/pub-sub.cjs.map +1 -1
- package/lib/core/{pub-sub.d.ts → pub-sub.d.cts} +0 -1
- package/lib/engine/index.cjs +1 -1
- package/{esm/engine/index.d.ts → lib/engine/index.d.cts} +0 -1
- package/lib/engine/plugin.cjs +11 -2
- package/lib/engine/plugin.cjs.map +1 -1
- package/{esm/engine/plugin.d.ts → lib/engine/plugin.d.cts} +0 -1
- package/lib/engine/types.cjs +1 -1
- package/lib/engine/{types.d.ts → types.d.cts} +0 -1
- package/lib/errors/index.cjs +17 -1
- package/lib/errors/index.cjs.map +1 -1
- package/lib/errors/{index.d.ts → index.d.cts} +0 -1
- package/lib/index.cjs +8 -8
- package/lib/index.cjs.map +1 -1
- package/lib/{index.d.ts → index.d.cts} +3 -4
- package/lib/middleware/index.cjs +2 -2
- package/lib/middleware/{index.d.ts → index.d.cts} +3 -4
- package/lib/middleware/logger.cjs +2 -2
- package/lib/middleware/logger.cjs.map +1 -1
- package/lib/middleware/{logger.d.ts → logger.d.cts} +0 -1
- package/lib/middleware/middleware-manager.cjs +5 -2
- package/lib/middleware/middleware-manager.cjs.map +1 -1
- package/lib/middleware/{middleware-manager.d.ts → middleware-manager.d.cts} +0 -1
- package/lib/middleware/persist.cjs +3 -3
- package/lib/middleware/persist.cjs.map +1 -1
- package/{esm/middleware/persist.d.ts → lib/middleware/persist.d.cts} +0 -1
- package/lib/middleware/time-travel.cjs +1 -1
- package/lib/middleware/time-travel.cjs.map +1 -1
- package/{esm/middleware/time-travel.d.ts → lib/middleware/time-travel.d.cts} +0 -1
- package/lib/middleware/validation.cjs +2 -2
- package/lib/middleware/validation.cjs.map +1 -1
- package/{esm/middleware/validation.d.ts → lib/middleware/validation.d.cts} +0 -1
- package/lib/plugins/define-plugin.cjs +2 -2
- package/lib/plugins/define-plugin.cjs.map +1 -1
- package/{esm/plugins/define-plugin.d.ts → lib/plugins/define-plugin.d.cts} +1 -2
- package/lib/plugins/index.cjs +2 -2
- package/{esm/plugins/index.d.ts → lib/plugins/index.d.cts} +0 -1
- package/lib/plugins/plugin-manager.cjs +58 -27
- package/lib/plugins/plugin-manager.cjs.map +1 -1
- package/lib/plugins/plugin-manager.d.cts +5 -0
- package/lib/types/action.cjs +12 -0
- package/lib/types/action.d.cts +2 -0
- package/lib/types/batch.cjs +12 -0
- package/lib/types/batch.d.cts +2 -0
- package/lib/types/event.cjs +12 -0
- package/lib/types/event.d.cts +2 -0
- package/lib/types/index.cjs +1 -1
- package/{esm/types/index.d.ts → lib/types/index.d.cts} +2 -3
- package/lib/types/middleware.cjs +1 -1
- package/lib/types/{middleware.d.ts → middleware.d.cts} +10 -2
- package/lib/types/mutation.cjs +12 -0
- package/lib/types/mutation.d.cts +2 -0
- package/lib/types/plugin.cjs +1 -1
- package/lib/types/{plugin.d.ts → plugin.d.cts} +4 -1
- package/lib/types/state.cjs +12 -0
- package/lib/types/state.d.cts +2 -0
- package/lib/types/store.cjs +1 -1
- package/lib/types/{store.d.ts → store.d.cts} +19 -1
- package/lib/types/subscription.cjs +1 -1
- package/lib/types/{subscription.d.ts → subscription.d.cts} +7 -2
- package/lib/types/time-travel.cjs +12 -0
- package/lib/types/time-travel.d.cts +2 -0
- package/lib/types/utility.cjs +1 -1
- package/lib/types/{utility.d.ts → utility.d.cts} +3 -4
- package/lib/utils/debounce-throttle.cjs +1 -1
- package/lib/utils/debounce-throttle.cjs.map +1 -1
- package/{esm/utils/debounce-throttle.d.ts → lib/utils/debounce-throttle.d.cts} +0 -1
- package/lib/utils/deep-clone.cjs +1 -1
- package/lib/utils/deep-clone.cjs.map +1 -1
- package/lib/utils/{deep-clone.d.ts → deep-clone.d.cts} +0 -1
- package/lib/utils/index.cjs +1 -1
- package/lib/utils/{index.d.ts → index.d.cts} +4 -5
- package/lib/utils/selector.cjs +1 -1
- package/lib/utils/selector.cjs.map +1 -1
- package/lib/utils/{selector.d.ts → selector.d.cts} +0 -1
- package/package.json +14 -11
- package/es/core/async-action.d.ts.map +0 -1
- package/es/core/base-store.d.ts.map +0 -1
- package/es/core/batch-manager.d.ts.map +0 -1
- package/es/core/create-store.d.ts.map +0 -1
- package/es/core/event-bus.d.ts.map +0 -1
- package/es/core/index.d.ts.map +0 -1
- package/es/core/pub-sub.d.ts.map +0 -1
- package/es/engine/index.d.ts.map +0 -1
- package/es/engine/plugin.d.ts.map +0 -1
- package/es/engine/types.d.ts.map +0 -1
- package/es/errors/index.d.ts.map +0 -1
- package/es/index.d.ts.map +0 -1
- package/es/middleware/index.d.ts.map +0 -1
- package/es/middleware/logger.d.ts.map +0 -1
- package/es/middleware/middleware-manager.d.ts.map +0 -1
- package/es/middleware/persist.d.ts.map +0 -1
- package/es/middleware/time-travel.d.ts.map +0 -1
- package/es/middleware/validation.d.ts.map +0 -1
- package/es/plugins/define-plugin.d.ts.map +0 -1
- package/es/plugins/index.d.ts.map +0 -1
- package/es/plugins/plugin-manager.d.ts.map +0 -1
- package/es/types/index.d.ts.map +0 -1
- package/es/types/middleware.d.ts.map +0 -1
- package/es/types/plugin.d.ts.map +0 -1
- package/es/types/store.d.ts.map +0 -1
- package/es/types/subscription.d.ts.map +0 -1
- package/es/types/utility.d.ts.map +0 -1
- package/es/utils/debounce-throttle.d.ts.map +0 -1
- package/es/utils/deep-clone.d.ts.map +0 -1
- package/es/utils/index.d.ts.map +0 -1
- package/es/utils/selector.d.ts.map +0 -1
- package/esm/core/async-action.d.ts +0 -95
- package/esm/core/base-store.d.ts +0 -85
- package/esm/core/create-store.d.ts +0 -66
- package/esm/core/event-bus.d.ts +0 -34
- package/esm/core/pub-sub.d.ts +0 -41
- package/esm/engine/types.d.ts +0 -81
- package/esm/errors/index.d.ts +0 -208
- package/esm/index.d.ts +0 -27
- package/esm/middleware/index.d.ts +0 -13
- package/esm/middleware/logger.d.ts +0 -67
- package/esm/middleware/middleware-manager.d.ts +0 -40
- package/esm/plugins/plugin-manager.d.ts +0 -35
- package/esm/types/middleware.d.ts +0 -172
- package/esm/types/plugin.d.ts +0 -136
- package/esm/types/store.d.ts +0 -198
- package/esm/types/subscription.d.ts +0 -158
- package/esm/types/utility.d.ts +0 -312
- package/esm/utils/deep-clone.d.ts +0 -143
- package/esm/utils/index.d.ts +0 -13
- package/esm/utils/selector.d.ts +0 -213
- package/lib/core/async-action.d.ts +0 -95
- package/lib/core/base-store.d.ts +0 -85
- package/lib/core/batch-manager.d.ts +0 -46
- package/lib/core/index.d.ts +0 -14
- package/lib/engine/index.d.ts +0 -10
- package/lib/engine/plugin.d.ts +0 -20
- package/lib/middleware/persist.d.ts +0 -34
- package/lib/middleware/time-travel.d.ts +0 -30
- package/lib/middleware/validation.d.ts +0 -100
- package/lib/plugins/define-plugin.d.ts +0 -74
- package/lib/plugins/index.d.ts +0 -8
- package/lib/plugins/plugin-manager.d.ts +0 -35
- package/lib/types/index.d.ts +0 -12
- package/lib/utils/debounce-throttle.d.ts +0 -86
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* ***********************************
|
|
3
3
|
* @composy/store-core v0.0.1 *
|
|
4
4
|
* Built with rollup *
|
|
5
|
-
* Build time: 2024-
|
|
5
|
+
* Build time: 2024-10-12 17:23:58 *
|
|
6
6
|
* Build mode: production *
|
|
7
7
|
* Minified: No *
|
|
8
8
|
* ***********************************
|
|
@@ -72,8 +72,24 @@
|
|
|
72
72
|
}
|
|
73
73
|
//#endregion
|
|
74
74
|
//#region src/core/async-action.ts
|
|
75
|
-
function
|
|
76
|
-
return
|
|
75
|
+
function abortError() {
|
|
76
|
+
return /* @__PURE__ */ new Error("Aborted");
|
|
77
|
+
}
|
|
78
|
+
function delay(ms, signal) {
|
|
79
|
+
if (signal.aborted) return Promise.reject(abortError());
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
let timer;
|
|
82
|
+
const onAbort = () => {
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
signal.removeEventListener("abort", onAbort);
|
|
85
|
+
reject(abortError());
|
|
86
|
+
};
|
|
87
|
+
timer = setTimeout(() => {
|
|
88
|
+
signal.removeEventListener("abort", onAbort);
|
|
89
|
+
resolve();
|
|
90
|
+
}, ms);
|
|
91
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
92
|
+
});
|
|
77
93
|
}
|
|
78
94
|
function createAsyncAction(fn, options = {}) {
|
|
79
95
|
const { retryCount = 0, retryDelay = 1e3, timeout = 0, resetOnExecute = true } = options;
|
|
@@ -87,39 +103,64 @@
|
|
|
87
103
|
const statePubSub = createPubSub();
|
|
88
104
|
const successPubSub = createPubSub();
|
|
89
105
|
const errorPubSub = createPubSub();
|
|
90
|
-
let
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const executeWithRetry = async (args, retriesLeft) => {
|
|
106
|
+
let nextExecutionId = 0;
|
|
107
|
+
let activeExecution = null;
|
|
108
|
+
const notify = () => statePubSub.publish({ ..._state });
|
|
109
|
+
const invoke = fn;
|
|
110
|
+
const executeWithRetry = async (args, retriesLeft, execution) => {
|
|
111
|
+
if (execution.controller.signal.aborted) throw execution.abortReason ?? abortError();
|
|
95
112
|
try {
|
|
96
|
-
|
|
113
|
+
const result = await invoke(...args, execution.controller.signal);
|
|
114
|
+
if (execution.controller.signal.aborted) throw execution.abortReason ?? abortError();
|
|
115
|
+
return result;
|
|
97
116
|
} catch (error) {
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
117
|
+
if (execution.controller.signal.aborted) throw execution.abortReason ?? abortError();
|
|
118
|
+
if (retriesLeft <= 0) throw error;
|
|
119
|
+
await delay(retryDelay, execution.controller.signal);
|
|
120
|
+
return executeWithRetry(args, retriesLeft - 1, execution);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const cancelExecution = (execution, reason) => {
|
|
124
|
+
execution.abortReason = reason;
|
|
125
|
+
if (!execution.controller.signal.aborted) execution.controller.abort();
|
|
126
|
+
execution.rejectAbort?.(reason);
|
|
127
|
+
if (execution.timeoutId) {
|
|
128
|
+
clearTimeout(execution.timeoutId);
|
|
129
|
+
execution.timeoutId = void 0;
|
|
104
130
|
}
|
|
105
131
|
};
|
|
106
132
|
const execute = async (...args) => {
|
|
107
|
-
if (
|
|
108
|
-
|
|
133
|
+
if (activeExecution) cancelExecution(activeExecution, abortError());
|
|
134
|
+
const execution = {
|
|
135
|
+
id: ++nextExecutionId,
|
|
136
|
+
controller: new AbortController()
|
|
137
|
+
};
|
|
138
|
+
activeExecution = execution;
|
|
109
139
|
if (resetOnExecute) _state.error = null;
|
|
110
140
|
_state.loading = true;
|
|
111
141
|
_state.executionCount++;
|
|
112
142
|
_state.lastExecutedAt = Date.now();
|
|
113
143
|
notify();
|
|
114
144
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
145
|
+
const work = executeWithRetry(args, retryCount, execution);
|
|
146
|
+
const abortPromise = new Promise((_, reject) => {
|
|
147
|
+
execution.rejectAbort = reject;
|
|
148
|
+
});
|
|
149
|
+
const timeoutPromise = timeout > 0 ? new Promise((_, reject) => {
|
|
150
|
+
execution.timeoutId = setTimeout(() => {
|
|
151
|
+
const error = /* @__PURE__ */ new Error(`Timeout after ${timeout}ms`);
|
|
152
|
+
execution.abortReason = error;
|
|
153
|
+
execution.controller.abort();
|
|
154
|
+
reject(error);
|
|
155
|
+
}, timeout);
|
|
156
|
+
}) : null;
|
|
157
|
+
execution.result = timeoutPromise ? Promise.race([
|
|
158
|
+
work,
|
|
159
|
+
abortPromise,
|
|
160
|
+
timeoutPromise
|
|
161
|
+
]) : Promise.race([work, abortPromise]);
|
|
162
|
+
const result = await execution.result;
|
|
163
|
+
if (activeExecution?.id === execution.id && !execution.controller.signal.aborted) {
|
|
123
164
|
_state.data = result;
|
|
124
165
|
_state.error = null;
|
|
125
166
|
_state.loading = false;
|
|
@@ -128,20 +169,27 @@
|
|
|
128
169
|
}
|
|
129
170
|
return result;
|
|
130
171
|
} catch (error) {
|
|
131
|
-
if (
|
|
172
|
+
if (activeExecution?.id === execution.id) {
|
|
132
173
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
133
174
|
_state.error = err;
|
|
134
175
|
_state.loading = false;
|
|
135
176
|
notify();
|
|
136
|
-
errorPubSub.publish(err);
|
|
177
|
+
if (execution.abortReason?.message !== "Aborted") errorPubSub.publish(err);
|
|
137
178
|
}
|
|
138
179
|
throw error;
|
|
180
|
+
} finally {
|
|
181
|
+
if (execution.timeoutId) {
|
|
182
|
+
clearTimeout(execution.timeoutId);
|
|
183
|
+
execution.timeoutId = void 0;
|
|
184
|
+
}
|
|
185
|
+
if (activeExecution?.id === execution.id) activeExecution = null;
|
|
139
186
|
}
|
|
140
187
|
};
|
|
141
188
|
const reset = () => {
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
189
|
+
if (activeExecution) {
|
|
190
|
+
const execution = activeExecution;
|
|
191
|
+
activeExecution = null;
|
|
192
|
+
cancelExecution(execution, abortError());
|
|
145
193
|
}
|
|
146
194
|
_state.data = null;
|
|
147
195
|
_state.error = null;
|
|
@@ -151,13 +199,13 @@
|
|
|
151
199
|
notify();
|
|
152
200
|
};
|
|
153
201
|
const abort = () => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
const execution = activeExecution;
|
|
203
|
+
if (!execution) return;
|
|
204
|
+
activeExecution = null;
|
|
205
|
+
cancelExecution(execution, abortError());
|
|
158
206
|
if (_state.loading) {
|
|
159
207
|
_state.loading = false;
|
|
160
|
-
_state.error =
|
|
208
|
+
_state.error = execution.abortReason ?? abortError();
|
|
161
209
|
notify();
|
|
162
210
|
}
|
|
163
211
|
};
|
|
@@ -174,955 +222,478 @@
|
|
|
174
222
|
};
|
|
175
223
|
}
|
|
176
224
|
//#endregion
|
|
177
|
-
//#region src/
|
|
178
|
-
function
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
listeners.set(type, set);
|
|
185
|
-
}
|
|
186
|
-
return set;
|
|
225
|
+
//#region src/middleware/middleware-manager.ts
|
|
226
|
+
function createMiddlewareManager() {
|
|
227
|
+
const middlewares = /* @__PURE__ */ new Map();
|
|
228
|
+
let sortedMiddlewares = null;
|
|
229
|
+
const getSortedMiddlewares = () => {
|
|
230
|
+
if (sortedMiddlewares === null) sortedMiddlewares = Array.from(middlewares.values()).sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
|
231
|
+
return sortedMiddlewares;
|
|
187
232
|
};
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
set.add(listener);
|
|
191
|
-
return () => {
|
|
192
|
-
set.delete(listener);
|
|
193
|
-
if (set.size === 0) listeners.delete(type);
|
|
194
|
-
};
|
|
233
|
+
const invalidateCache = () => {
|
|
234
|
+
sortedMiddlewares = null;
|
|
195
235
|
};
|
|
196
|
-
const
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
set.delete(listener);
|
|
201
|
-
if (set.size === 0) listeners.delete(type);
|
|
202
|
-
}
|
|
203
|
-
} else listeners.delete(type);
|
|
236
|
+
const use = (middleware) => {
|
|
237
|
+
if (middlewares.has(middleware.name)) console.warn(`[Middleware] \u4E2D\u95F4\u4EF6 "${middleware.name}" \u5DF2\u5B58\u5728\uFF0C\u5C06\u88AB\u8986\u76D6`);
|
|
238
|
+
middlewares.set(middleware.name, middleware);
|
|
239
|
+
invalidateCache();
|
|
204
240
|
};
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
listener(data);
|
|
208
|
-
off(type, wrappedListener);
|
|
209
|
-
};
|
|
210
|
-
return on(type, wrappedListener);
|
|
241
|
+
const remove = (name) => {
|
|
242
|
+
if (middlewares.delete(name)) invalidateCache();
|
|
211
243
|
};
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
244
|
+
const get = (name) => {
|
|
245
|
+
return middlewares.get(name);
|
|
246
|
+
};
|
|
247
|
+
const has = (name) => {
|
|
248
|
+
return middlewares.has(name);
|
|
249
|
+
};
|
|
250
|
+
const execute = async (context) => {
|
|
251
|
+
const sorted = getSortedMiddlewares();
|
|
252
|
+
if (sorted.length === 0) return;
|
|
253
|
+
const dispatch = async (index) => {
|
|
254
|
+
const middleware = sorted[index];
|
|
255
|
+
if (!middleware) {
|
|
256
|
+
context.meta?.commit?.();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
let called = false;
|
|
260
|
+
const next = async () => {
|
|
261
|
+
if (called) throw new Error(`[Middleware] next() called multiple times in "${middleware.name}"`);
|
|
262
|
+
called = true;
|
|
263
|
+
await dispatch(index + 1);
|
|
264
|
+
};
|
|
265
|
+
await middleware.handler(context, next);
|
|
217
266
|
};
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
267
|
+
await dispatch(0);
|
|
268
|
+
};
|
|
269
|
+
const getAll = () => {
|
|
270
|
+
return getSortedMiddlewares();
|
|
222
271
|
};
|
|
223
272
|
const clear = () => {
|
|
224
|
-
|
|
273
|
+
middlewares.clear();
|
|
274
|
+
invalidateCache();
|
|
225
275
|
};
|
|
226
276
|
return {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
277
|
+
use,
|
|
278
|
+
remove,
|
|
279
|
+
get,
|
|
280
|
+
has,
|
|
281
|
+
execute,
|
|
282
|
+
getAll,
|
|
231
283
|
clear
|
|
232
284
|
};
|
|
233
285
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return !!value && typeof value.then === "function";
|
|
286
|
+
let globalMiddlewareManager = null;
|
|
287
|
+
function getGlobalMiddlewareManager() {
|
|
288
|
+
if (!globalMiddlewareManager) globalMiddlewareManager = createMiddlewareManager();
|
|
289
|
+
return globalMiddlewareManager;
|
|
239
290
|
}
|
|
240
|
-
|
|
241
|
-
|
|
291
|
+
function setGlobalMiddlewareManager(manager) {
|
|
292
|
+
globalMiddlewareManager = manager;
|
|
242
293
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
*/
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
return this._state;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* 设置状态
|
|
272
|
-
*/
|
|
273
|
-
set $state(newState) {
|
|
274
|
-
this._state = newState;
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* 重置状态到初始值
|
|
278
|
-
*/
|
|
279
|
-
$reset() {
|
|
280
|
-
this.checkDisposed();
|
|
281
|
-
const oldState = { ...this._state };
|
|
282
|
-
this._state = this.initialStateFactory();
|
|
283
|
-
this.notifyStateChange({
|
|
284
|
-
type: "direct",
|
|
285
|
-
storeId: this.$id,
|
|
286
|
-
oldState
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* 批量更新状态
|
|
291
|
-
*/
|
|
292
|
-
$patch(partialState) {
|
|
293
|
-
this.checkDisposed();
|
|
294
|
-
const oldState = { ...this._state };
|
|
295
|
-
if (typeof partialState === "function") {
|
|
296
|
-
partialState(this._state);
|
|
297
|
-
this.notifyStateChange({
|
|
298
|
-
type: "patch function",
|
|
299
|
-
storeId: this.$id,
|
|
300
|
-
oldState
|
|
301
|
-
});
|
|
302
|
-
} else {
|
|
303
|
-
Object.assign(this._state, partialState);
|
|
304
|
-
this.notifyStateChange({
|
|
305
|
-
type: "patch object",
|
|
306
|
-
storeId: this.$id,
|
|
307
|
-
oldState,
|
|
308
|
-
events: Object.keys(partialState)
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* 订阅状态变化
|
|
314
|
-
*/
|
|
315
|
-
$subscribe(callback, options = {}) {
|
|
316
|
-
this.checkDisposed();
|
|
317
|
-
return this.stateSubscribers.subscribe(({ mutation, state }) => callback(mutation, state), { immediate: options.immediate });
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* 订阅 Action 调用
|
|
321
|
-
*/
|
|
322
|
-
$onAction(callback) {
|
|
323
|
-
this.checkDisposed();
|
|
324
|
-
return this.actionSubscribers.subscribe(callback);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* 销毁 Store
|
|
328
|
-
*/
|
|
329
|
-
$dispose() {
|
|
330
|
-
if (this.disposed) return;
|
|
331
|
-
this.disposed = true;
|
|
332
|
-
this.stateSubscribers.clear();
|
|
333
|
-
this.actionSubscribers.clear();
|
|
334
|
-
globalEventBus.emit("store:disposed", { storeId: this.$id });
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* 通知状态变化
|
|
338
|
-
*/
|
|
339
|
-
notifyStateChange(mutation) {
|
|
340
|
-
this.stateSubscribers.publish({
|
|
341
|
-
mutation,
|
|
342
|
-
state: this._state
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region src/plugins/plugin-manager.ts
|
|
296
|
+
function reportPluginError(action, name, error) {
|
|
297
|
+
console.error(`[Plugin] ${action} failed for "${name}":`, error);
|
|
298
|
+
}
|
|
299
|
+
function createPluginManager() {
|
|
300
|
+
const plugins = /* @__PURE__ */ new Map();
|
|
301
|
+
const contexts = /* @__PURE__ */ new Map();
|
|
302
|
+
const stores = /* @__PURE__ */ new Map();
|
|
303
|
+
const storeManager = {
|
|
304
|
+
getStore: (id) => stores.get(id),
|
|
305
|
+
hasStore: (id) => stores.has(id),
|
|
306
|
+
getStoreIds: () => Array.from(stores.keys())
|
|
307
|
+
};
|
|
308
|
+
const createContext = (options) => ({
|
|
309
|
+
storeManager,
|
|
310
|
+
storeId: "",
|
|
311
|
+
store: null,
|
|
312
|
+
options: options || {}
|
|
313
|
+
});
|
|
314
|
+
const use = (plugin, options) => {
|
|
315
|
+
const previous = plugins.get(plugin.name);
|
|
316
|
+
const previousContext = contexts.get(plugin.name);
|
|
317
|
+
if (previous && previousContext) Promise.resolve(previous.uninstall?.(previousContext)).catch((error) => {
|
|
318
|
+
reportPluginError("uninstall", plugin.name, error);
|
|
343
319
|
});
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
320
|
+
const context = createContext(options);
|
|
321
|
+
plugins.set(plugin.name, plugin);
|
|
322
|
+
contexts.set(plugin.name, context);
|
|
323
|
+
Promise.resolve(plugin.install(context, options)).catch((error) => {
|
|
324
|
+
reportPluginError("install", plugin.name, error);
|
|
348
325
|
});
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* 检查是否已销毁
|
|
358
|
-
*/
|
|
359
|
-
checkDisposed() {
|
|
360
|
-
if (this.disposed) throw new Error(`[Store] Store "${this.$id}" \u5DF2\u88AB\u9500\u6BC1`);
|
|
361
|
-
}
|
|
362
|
-
createGetters(gettersDefinition) {
|
|
363
|
-
const getterCache = {};
|
|
364
|
-
for (const key of Object.keys(gettersDefinition)) Object.defineProperty(getterCache, key, {
|
|
365
|
-
enumerable: true,
|
|
366
|
-
get: () => gettersDefinition[key](this._state)
|
|
326
|
+
stores.forEach((store) => plugin.onStoreCreated?.(store));
|
|
327
|
+
};
|
|
328
|
+
const remove = (name) => {
|
|
329
|
+
const plugin = plugins.get(name);
|
|
330
|
+
const context = contexts.get(name);
|
|
331
|
+
if (plugin && context) Promise.resolve(plugin.uninstall?.(context)).catch((error) => {
|
|
332
|
+
reportPluginError("uninstall", name, error);
|
|
367
333
|
});
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
args,
|
|
381
|
-
name: key,
|
|
382
|
-
onError: (callback) => errorCallbacks.push(callback),
|
|
383
|
-
storeId: this.$id
|
|
384
|
-
};
|
|
385
|
-
this.notifyAction(context);
|
|
386
|
-
try {
|
|
387
|
-
const result = action.apply(this, args);
|
|
388
|
-
if (isPromiseLike(result)) return result.then(async (resolvedResult) => {
|
|
389
|
-
await runCallbacks(afterCallbacks, resolvedResult);
|
|
390
|
-
return resolvedResult;
|
|
391
|
-
}).catch(async (error) => {
|
|
392
|
-
await runCallbacks(errorCallbacks, error);
|
|
393
|
-
throw error;
|
|
394
|
-
});
|
|
395
|
-
runCallbacks(afterCallbacks, result);
|
|
396
|
-
return result;
|
|
397
|
-
} catch (error) {
|
|
398
|
-
runCallbacks(errorCallbacks, error);
|
|
399
|
-
throw error;
|
|
400
|
-
}
|
|
334
|
+
plugins.delete(name);
|
|
335
|
+
contexts.delete(name);
|
|
336
|
+
};
|
|
337
|
+
const get = (name) => plugins.get(name);
|
|
338
|
+
const has = (name) => plugins.has(name);
|
|
339
|
+
const getAll = () => new Map(plugins);
|
|
340
|
+
const size = () => plugins.size;
|
|
341
|
+
const clear = () => {
|
|
342
|
+
plugins.forEach((plugin, name) => {
|
|
343
|
+
const context = contexts.get(name);
|
|
344
|
+
if (context) Promise.resolve(plugin.uninstall?.(context)).catch((error) => {
|
|
345
|
+
reportPluginError("uninstall", name, error);
|
|
401
346
|
});
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
};
|
|
406
|
-
//#endregion
|
|
407
|
-
//#region src/core/batch-manager.ts
|
|
408
|
-
function createBatchManager(onFlush) {
|
|
409
|
-
let batchDepth = 0;
|
|
410
|
-
const pendingStores = /* @__PURE__ */ new Set();
|
|
411
|
-
const flush = () => {
|
|
412
|
-
if (pendingStores.size > 0) {
|
|
413
|
-
const stores = new Set(pendingStores);
|
|
414
|
-
pendingStores.clear();
|
|
415
|
-
onFlush?.(stores);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
const start = () => {
|
|
419
|
-
batchDepth++;
|
|
347
|
+
});
|
|
348
|
+
plugins.clear();
|
|
349
|
+
contexts.clear();
|
|
420
350
|
};
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
351
|
+
const notifyStoreCreated = (store) => {
|
|
352
|
+
const id = readStoreId(store);
|
|
353
|
+
if (id) stores.set(id, store);
|
|
354
|
+
plugins.forEach((plugin) => plugin.onStoreCreated?.(store));
|
|
425
355
|
};
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
if (
|
|
356
|
+
const notifyStoreDisposed = (store) => {
|
|
357
|
+
const id = readStoreId(store);
|
|
358
|
+
if (id) stores.delete(id);
|
|
359
|
+
plugins.forEach((plugin) => plugin.onStoreDisposed?.(store));
|
|
429
360
|
};
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
try {
|
|
433
|
-
return fn();
|
|
434
|
-
} finally {
|
|
435
|
-
end();
|
|
436
|
-
}
|
|
361
|
+
const notifyStateChange = (storeId, state, oldState) => {
|
|
362
|
+
plugins.forEach((plugin) => plugin.onStateChange?.(storeId, state, oldState));
|
|
437
363
|
};
|
|
438
|
-
const isBatching = () => batchDepth > 0;
|
|
439
364
|
return {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
365
|
+
use,
|
|
366
|
+
remove,
|
|
367
|
+
get,
|
|
368
|
+
has,
|
|
369
|
+
getAll,
|
|
370
|
+
size,
|
|
371
|
+
clear,
|
|
372
|
+
notifyStoreCreated,
|
|
373
|
+
notifyStoreDisposed,
|
|
374
|
+
notifyStateChange
|
|
445
375
|
};
|
|
446
376
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return
|
|
377
|
+
function readStoreId(store) {
|
|
378
|
+
if (!store || typeof store !== "object") return void 0;
|
|
379
|
+
const id = store.$id;
|
|
380
|
+
return typeof id === "string" ? id : void 0;
|
|
451
381
|
}
|
|
452
|
-
|
|
453
|
-
|
|
382
|
+
let globalPluginManager = null;
|
|
383
|
+
function getGlobalPluginManager() {
|
|
384
|
+
if (!globalPluginManager) globalPluginManager = createPluginManager();
|
|
385
|
+
return globalPluginManager;
|
|
454
386
|
}
|
|
455
|
-
function
|
|
456
|
-
|
|
387
|
+
function setGlobalPluginManager(manager) {
|
|
388
|
+
globalPluginManager = manager;
|
|
457
389
|
}
|
|
458
390
|
//#endregion
|
|
459
|
-
//#region src/
|
|
460
|
-
function
|
|
461
|
-
let
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
391
|
+
//#region src/utils/debounce-throttle.ts
|
|
392
|
+
function debounce(fn, delay, immediate = false) {
|
|
393
|
+
let timer = null;
|
|
394
|
+
let lastArgs = null;
|
|
395
|
+
const debounced = ((...args) => {
|
|
396
|
+
lastArgs = args;
|
|
397
|
+
if (timer) clearTimeout(timer);
|
|
398
|
+
if (immediate && !timer) {
|
|
399
|
+
fn(...args);
|
|
400
|
+
timer = setTimeout(() => {
|
|
401
|
+
timer = null;
|
|
402
|
+
lastArgs = null;
|
|
403
|
+
}, delay);
|
|
404
|
+
} else timer = setTimeout(() => {
|
|
405
|
+
fn(...args);
|
|
406
|
+
timer = null;
|
|
407
|
+
lastArgs = null;
|
|
408
|
+
}, delay);
|
|
409
|
+
});
|
|
410
|
+
debounced.cancel = () => {
|
|
411
|
+
if (timer) {
|
|
412
|
+
clearTimeout(timer);
|
|
413
|
+
timer = null;
|
|
414
|
+
lastArgs = null;
|
|
415
|
+
}
|
|
472
416
|
};
|
|
417
|
+
debounced.flush = () => {
|
|
418
|
+
if (timer && lastArgs) {
|
|
419
|
+
clearTimeout(timer);
|
|
420
|
+
fn(...lastArgs);
|
|
421
|
+
timer = null;
|
|
422
|
+
lastArgs = null;
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
debounced.pending = () => timer !== null;
|
|
426
|
+
return debounced;
|
|
473
427
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
resetAll: runtime.storeAPI.resetAll
|
|
428
|
+
function throttle(fn, interval, options = {}) {
|
|
429
|
+
const { leading = true, trailing = true } = options;
|
|
430
|
+
let timer = null;
|
|
431
|
+
let lastTime = 0;
|
|
432
|
+
let lastArgs = null;
|
|
433
|
+
const throttled = ((...args) => {
|
|
434
|
+
const now = Date.now();
|
|
435
|
+
const remaining = interval - (now - lastTime);
|
|
436
|
+
lastArgs = args;
|
|
437
|
+
if (remaining <= 0 || remaining > interval) {
|
|
438
|
+
if (timer) {
|
|
439
|
+
clearTimeout(timer);
|
|
440
|
+
timer = null;
|
|
441
|
+
}
|
|
442
|
+
lastTime = now;
|
|
443
|
+
if (leading || lastTime !== 0) fn(...args);
|
|
444
|
+
lastArgs = null;
|
|
445
|
+
} else if (!timer && trailing) timer = setTimeout(() => {
|
|
446
|
+
lastTime = trailing ? Date.now() : 0;
|
|
447
|
+
timer = null;
|
|
448
|
+
if (lastArgs) {
|
|
449
|
+
fn(...lastArgs);
|
|
450
|
+
lastArgs = null;
|
|
451
|
+
}
|
|
452
|
+
}, remaining);
|
|
453
|
+
});
|
|
454
|
+
throttled.cancel = () => {
|
|
455
|
+
if (timer) {
|
|
456
|
+
clearTimeout(timer);
|
|
457
|
+
timer = null;
|
|
458
|
+
}
|
|
459
|
+
lastTime = 0;
|
|
460
|
+
lastArgs = null;
|
|
508
461
|
};
|
|
462
|
+
return throttled;
|
|
509
463
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
engine.api.register(name, api);
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
engine.api.register(api);
|
|
464
|
+
//#endregion
|
|
465
|
+
//#region src/utils/deep-clone.ts
|
|
466
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
467
|
+
function hasOwnKey(value, key) {
|
|
468
|
+
return hasOwnProperty.call(value, key);
|
|
519
469
|
}
|
|
520
|
-
function
|
|
521
|
-
|
|
522
|
-
engine.state?.set?.(storeStateKeys.PINIA, runtime.pinia);
|
|
523
|
-
engine.state?.set?.(storeStateKeys.API, runtime.storeAPI);
|
|
524
|
-
engine.state?.set?.(storeStateKeys.REGISTRY, runtime.registry);
|
|
525
|
-
engine.state?.set?.(storeStateKeys.BUS, globalEventBus);
|
|
526
|
-
engine.state?.set?.(`plugins.${name}`, runtime.storeAPI);
|
|
527
|
-
engine.state?.set?.(`plugins.${name}.config`, options);
|
|
470
|
+
function isObject(value) {
|
|
471
|
+
return value !== null && typeof value === "object";
|
|
528
472
|
}
|
|
529
|
-
function
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
engine.state?.delete?.(storeStateKeys.REGISTRY);
|
|
534
|
-
engine.state?.delete?.(storeStateKeys.BUS);
|
|
535
|
-
engine.state?.delete?.(`plugins.${name}`);
|
|
536
|
-
engine.state?.delete?.(`plugins.${name}.config`);
|
|
473
|
+
function isPlainObject(value) {
|
|
474
|
+
if (!isObject(value)) return false;
|
|
475
|
+
const proto = Object.getPrototypeOf(value);
|
|
476
|
+
return proto === null || proto === Object.prototype;
|
|
537
477
|
}
|
|
538
|
-
function
|
|
539
|
-
if (
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
478
|
+
function isStructuredCloneable(value) {
|
|
479
|
+
if (value === null || value === void 0) return true;
|
|
480
|
+
if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return true;
|
|
481
|
+
if (typeof value === "bigint") return true;
|
|
482
|
+
if (typeof value === "function" || typeof value === "symbol") return false;
|
|
483
|
+
if (value instanceof Date || value instanceof RegExp) return true;
|
|
484
|
+
if (value instanceof ArrayBuffer || value instanceof DataView) return true;
|
|
485
|
+
if (value instanceof Map || value instanceof Set) return true;
|
|
486
|
+
if (ArrayBuffer.isView(value)) return true;
|
|
487
|
+
if (Array.isArray(value)) return value.every((item) => isStructuredCloneable(item));
|
|
488
|
+
if (isPlainObject(value)) return Object.values(value).every((v) => isStructuredCloneable(v));
|
|
489
|
+
return false;
|
|
546
490
|
}
|
|
547
|
-
function
|
|
548
|
-
const {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
return
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const createdApp = options.resolveApp ? options.resolveApp(activeEngine, activeContext ?? {}, payload) : resolveDefaultApp(activeEngine, activeContext, payload);
|
|
585
|
-
if (createdApp && (!options.isApp || options.isApp(createdApp))) attachToApp(createdApp);
|
|
491
|
+
function deepClone(value, options = {}) {
|
|
492
|
+
const { useStructuredClone: preferStructuredClone = true, cloneFunctions = false, cloneSymbols = false, maxDepth = Infinity, customCloner } = options;
|
|
493
|
+
if (preferStructuredClone && typeof structuredClone === "function" && isStructuredCloneable(value)) try {
|
|
494
|
+
return structuredClone(value);
|
|
495
|
+
} catch {}
|
|
496
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
497
|
+
function cloneInternal(val, depth) {
|
|
498
|
+
if (val === null || val === void 0) return val;
|
|
499
|
+
if (typeof val === "boolean" || typeof val === "number" || typeof val === "string") return val;
|
|
500
|
+
if (typeof val === "bigint") return val;
|
|
501
|
+
if (typeof val === "symbol") return cloneSymbols ? Symbol(val.description) : val;
|
|
502
|
+
if (typeof val === "function") return cloneFunctions ? val.bind({}) : val;
|
|
503
|
+
if (depth > maxDepth) return val;
|
|
504
|
+
if (customCloner) {
|
|
505
|
+
const customResult = customCloner(val, (v) => cloneInternal(v, depth + 1));
|
|
506
|
+
if (customResult !== void 0) return customResult;
|
|
507
|
+
}
|
|
508
|
+
if (typeof val === "object" && val !== null) {
|
|
509
|
+
if (cache.has(val)) return cache.get(val);
|
|
510
|
+
}
|
|
511
|
+
if (val instanceof Date) return new Date(val.getTime());
|
|
512
|
+
if (val instanceof RegExp) {
|
|
513
|
+
const result = new RegExp(val.source, val.flags);
|
|
514
|
+
result.lastIndex = val.lastIndex;
|
|
515
|
+
return result;
|
|
516
|
+
}
|
|
517
|
+
if (val instanceof Error) {
|
|
518
|
+
const result = new val.constructor(val.message);
|
|
519
|
+
result.stack = val.stack;
|
|
520
|
+
result.name = val.name;
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
523
|
+
if (val instanceof Map) {
|
|
524
|
+
const result = /* @__PURE__ */ new Map();
|
|
525
|
+
cache.set(val, result);
|
|
526
|
+
val.forEach((v, k) => {
|
|
527
|
+
result.set(cloneInternal(k, depth + 1), cloneInternal(v, depth + 1));
|
|
586
528
|
});
|
|
529
|
+
return result;
|
|
587
530
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
if (
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
531
|
+
if (val instanceof Set) {
|
|
532
|
+
const result = /* @__PURE__ */ new Set();
|
|
533
|
+
cache.set(val, result);
|
|
534
|
+
val.forEach((v) => {
|
|
535
|
+
result.add(cloneInternal(v, depth + 1));
|
|
536
|
+
});
|
|
537
|
+
return result;
|
|
538
|
+
}
|
|
539
|
+
if (val instanceof ArrayBuffer) return val.slice(0);
|
|
540
|
+
if (ArrayBuffer.isView(val) && !(val instanceof DataView)) {
|
|
541
|
+
const TypedArrayConstructor = val.constructor;
|
|
542
|
+
return new TypedArrayConstructor(val.buffer.slice(0));
|
|
543
|
+
}
|
|
544
|
+
if (Array.isArray(val)) {
|
|
545
|
+
const result = [];
|
|
546
|
+
cache.set(val, result);
|
|
547
|
+
for (let i = 0; i < val.length; i++) result[i] = cloneInternal(val[i], depth + 1);
|
|
548
|
+
return result;
|
|
549
|
+
}
|
|
550
|
+
if (isPlainObject(val)) {
|
|
551
|
+
const result = {};
|
|
552
|
+
cache.set(val, result);
|
|
553
|
+
const keys = Object.keys(val);
|
|
554
|
+
for (const key of keys) result[key] = cloneInternal(val[key], depth + 1);
|
|
555
|
+
if (cloneSymbols) {
|
|
556
|
+
const symbolKeys = Object.getOwnPropertySymbols(val);
|
|
557
|
+
for (const sym of symbolKeys) result[sym] = cloneInternal(val[sym], depth + 1);
|
|
558
|
+
}
|
|
559
|
+
return result;
|
|
560
|
+
}
|
|
561
|
+
return val;
|
|
562
|
+
}
|
|
563
|
+
return cloneInternal(value, 0);
|
|
613
564
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
*/
|
|
648
|
-
constructor(message, code = "UNKNOWN_ERROR", context = {}, severity = "error", cause) {
|
|
649
|
-
super(message);
|
|
650
|
-
this.name = "StoreError";
|
|
651
|
-
this.code = code;
|
|
652
|
-
this.context = {
|
|
653
|
-
...context,
|
|
654
|
-
timestamp: context.timestamp ?? Date.now()
|
|
655
|
-
};
|
|
656
|
-
this.severity = severity;
|
|
657
|
-
this.cause = cause;
|
|
658
|
-
Object.setPrototypeOf(this, StoreError.prototype);
|
|
659
|
-
if (Error.captureStackTrace) Error.captureStackTrace(this, StoreError);
|
|
565
|
+
function shallowClone(value) {
|
|
566
|
+
if (value === null || value === void 0) return value;
|
|
567
|
+
if (typeof value !== "object") return value;
|
|
568
|
+
if (Array.isArray(value)) return [...value];
|
|
569
|
+
if (value instanceof Map) return new Map(value);
|
|
570
|
+
if (value instanceof Set) return new Set(value);
|
|
571
|
+
if (value instanceof Date) return new Date(value.getTime());
|
|
572
|
+
return { ...value };
|
|
573
|
+
}
|
|
574
|
+
function deepMerge(target, ...sources) {
|
|
575
|
+
return deepMergeWithOptions(target, {}, ...sources);
|
|
576
|
+
}
|
|
577
|
+
function deepMergeWithOptions(target, options, ...sources) {
|
|
578
|
+
const { arrayStrategy = "replace", clone = true, maxDepth = Infinity } = options;
|
|
579
|
+
function mergeInternal(targetObj, sourceObj, depth) {
|
|
580
|
+
if (depth > maxDepth) return targetObj;
|
|
581
|
+
for (const key of Object.keys(sourceObj)) {
|
|
582
|
+
const sourceValue = sourceObj[key];
|
|
583
|
+
const targetValue = targetObj[key];
|
|
584
|
+
if (Array.isArray(sourceValue)) if (arrayStrategy === "concat" && Array.isArray(targetValue)) targetObj[key] = [...targetValue, ...sourceValue];
|
|
585
|
+
else if (arrayStrategy === "merge" && Array.isArray(targetValue)) {
|
|
586
|
+
const result2 = [...targetValue];
|
|
587
|
+
sourceValue.forEach((item, index) => {
|
|
588
|
+
if (isPlainObject(item) && isPlainObject(result2[index])) result2[index] = mergeInternal(result2[index], item, depth + 1);
|
|
589
|
+
else result2[index] = clone ? deepClone(item) : item;
|
|
590
|
+
});
|
|
591
|
+
targetObj[key] = result2;
|
|
592
|
+
} else targetObj[key] = clone ? deepClone(sourceValue) : sourceValue;
|
|
593
|
+
else if (isPlainObject(sourceValue)) if (isPlainObject(targetValue)) targetObj[key] = mergeInternal(targetValue, sourceValue, depth + 1);
|
|
594
|
+
else targetObj[key] = clone ? deepClone(sourceValue) : sourceValue;
|
|
595
|
+
else targetObj[key] = clone && isObject(sourceValue) ? deepClone(sourceValue) : sourceValue;
|
|
596
|
+
}
|
|
597
|
+
return targetObj;
|
|
660
598
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
599
|
+
let result = target;
|
|
600
|
+
for (const source of sources) if (source !== null && source !== void 0) result = mergeInternal(result, source, 0);
|
|
601
|
+
return result;
|
|
602
|
+
}
|
|
603
|
+
function deepEqual(a, b) {
|
|
604
|
+
if (a === b) return true;
|
|
605
|
+
if (a === null || b === null || a === void 0 || b === void 0) return a === b;
|
|
606
|
+
if (typeof a !== typeof b) return false;
|
|
607
|
+
if (typeof a !== "object") return a === b;
|
|
608
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
609
|
+
if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
|
|
610
|
+
if (a instanceof Map && b instanceof Map) {
|
|
611
|
+
if (a.size !== b.size) return false;
|
|
612
|
+
for (const [key, value] of a) if (!b.has(key) || !deepEqual(value, b.get(key))) return false;
|
|
613
|
+
return true;
|
|
673
614
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
const parts = [`[${this.code}] ${this.message}`];
|
|
679
|
-
if (this.context.storeId) parts.push(`Store: ${this.context.storeId}`);
|
|
680
|
-
if (this.context.action) parts.push(`Action: ${this.context.action}`);
|
|
681
|
-
return parts.join(" | ");
|
|
615
|
+
if (a instanceof Set && b instanceof Set) {
|
|
616
|
+
if (a.size !== b.size) return false;
|
|
617
|
+
for (const value of a) if (!b.has(value)) return false;
|
|
618
|
+
return true;
|
|
682
619
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
storeId,
|
|
688
|
-
action
|
|
689
|
-
}, "error");
|
|
690
|
-
this.name = "StoreDisposedError";
|
|
691
|
-
Object.setPrototypeOf(this, StoreDisposedError.prototype);
|
|
620
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
621
|
+
if (a.length !== b.length) return false;
|
|
622
|
+
for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;
|
|
623
|
+
return true;
|
|
692
624
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
625
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
626
|
+
const keysA = Object.keys(a);
|
|
627
|
+
const keysB = Object.keys(b);
|
|
628
|
+
if (keysA.length !== keysB.length) return false;
|
|
629
|
+
for (const key of keysA) {
|
|
630
|
+
if (!hasOwnKey(b, key)) return false;
|
|
631
|
+
if (!deepEqual(a[key], b[key])) return false;
|
|
632
|
+
}
|
|
633
|
+
return true;
|
|
699
634
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
};
|
|
708
|
-
var InvalidStateError = class InvalidStateError extends StoreError {
|
|
709
|
-
constructor(message, storeId, data) {
|
|
710
|
-
super(message, "INVALID_STATE", {
|
|
711
|
-
storeId,
|
|
712
|
-
data
|
|
713
|
-
}, "error");
|
|
714
|
-
this.name = "InvalidStateError";
|
|
715
|
-
Object.setPrototypeOf(this, InvalidStateError.prototype);
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
var SerializationError = class SerializationError extends StoreError {
|
|
719
|
-
constructor(message, cause, storeId) {
|
|
720
|
-
super(message, "SERIALIZATION_ERROR", { storeId }, "error", cause);
|
|
721
|
-
this.name = "SerializationError";
|
|
722
|
-
Object.setPrototypeOf(this, SerializationError.prototype);
|
|
723
|
-
}
|
|
724
|
-
};
|
|
725
|
-
var DeserializationError = class DeserializationError extends StoreError {
|
|
726
|
-
constructor(message, cause, storeId) {
|
|
727
|
-
super(message, "DESERIALIZATION_ERROR", { storeId }, "error", cause);
|
|
728
|
-
this.name = "DeserializationError";
|
|
729
|
-
Object.setPrototypeOf(this, DeserializationError.prototype);
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
var StorageError = class StorageError extends StoreError {
|
|
733
|
-
constructor(message, cause, storeId) {
|
|
734
|
-
super(message, "STORAGE_ERROR", { storeId }, "error", cause);
|
|
735
|
-
this.name = "StorageError";
|
|
736
|
-
Object.setPrototypeOf(this, StorageError.prototype);
|
|
737
|
-
}
|
|
738
|
-
};
|
|
739
|
-
var PluginError = class PluginError extends StoreError {
|
|
740
|
-
constructor(message, pluginName, cause) {
|
|
741
|
-
super(message, "PLUGIN_ERROR", { plugin: pluginName }, "error", cause);
|
|
742
|
-
this.name = "PluginError";
|
|
743
|
-
Object.setPrototypeOf(this, PluginError.prototype);
|
|
744
|
-
}
|
|
745
|
-
};
|
|
746
|
-
var MiddlewareError = class MiddlewareError extends StoreError {
|
|
747
|
-
constructor(message, middlewareName, cause) {
|
|
748
|
-
super(message, "MIDDLEWARE_ERROR", { middleware: middlewareName }, "error", cause);
|
|
749
|
-
this.name = "MiddlewareError";
|
|
750
|
-
Object.setPrototypeOf(this, MiddlewareError.prototype);
|
|
751
|
-
}
|
|
752
|
-
};
|
|
753
|
-
var SubscriptionError = class SubscriptionError extends StoreError {
|
|
754
|
-
constructor(message, cause, storeId) {
|
|
755
|
-
super(message, "SUBSCRIPTION_ERROR", { storeId }, "warning", cause);
|
|
756
|
-
this.name = "SubscriptionError";
|
|
757
|
-
Object.setPrototypeOf(this, SubscriptionError.prototype);
|
|
758
|
-
}
|
|
759
|
-
};
|
|
760
|
-
var TimeoutError = class TimeoutError extends StoreError {
|
|
761
|
-
constructor(message, storeId, action) {
|
|
762
|
-
super(message, "TIMEOUT_ERROR", {
|
|
763
|
-
storeId,
|
|
764
|
-
action
|
|
765
|
-
}, "error");
|
|
766
|
-
this.name = "TimeoutError";
|
|
767
|
-
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
const errorUtils = {
|
|
771
|
-
/**
|
|
772
|
-
* 判断是否为 Store 错误
|
|
773
|
-
*/
|
|
774
|
-
isStoreError(error) {
|
|
775
|
-
return error instanceof StoreError;
|
|
776
|
-
},
|
|
777
|
-
/**
|
|
778
|
-
* 判断是否为特定类型的错误
|
|
779
|
-
*/
|
|
780
|
-
isErrorCode(error, code) {
|
|
781
|
-
return error instanceof StoreError && error.code === code;
|
|
782
|
-
},
|
|
783
|
-
/**
|
|
784
|
-
* 包装错误为 Store 错误
|
|
785
|
-
*/
|
|
786
|
-
wrap(error, code = "UNKNOWN_ERROR", context = {}) {
|
|
787
|
-
if (error instanceof StoreError) return error;
|
|
788
|
-
return new StoreError(error instanceof Error ? error.message : String(error), code, context, "error", error instanceof Error ? error : void 0);
|
|
789
|
-
},
|
|
790
|
-
/**
|
|
791
|
-
* 安全执行函数,捕获并包装错误
|
|
792
|
-
*/
|
|
793
|
-
async tryCatch(fn, code = "UNKNOWN_ERROR", context = {}) {
|
|
794
|
-
try {
|
|
795
|
-
return await fn();
|
|
796
|
-
} catch (error) {
|
|
797
|
-
throw errorUtils.wrap(error, code, context);
|
|
798
|
-
}
|
|
799
|
-
},
|
|
800
|
-
/**
|
|
801
|
-
* 创建错误日志记录器
|
|
802
|
-
*/
|
|
803
|
-
createLogger(prefix) {
|
|
804
|
-
return {
|
|
805
|
-
error(error) {
|
|
806
|
-
console.error(`[${prefix}]`, error.format());
|
|
807
|
-
if (error.cause) console.error(`[${prefix}] Caused by:`, error.cause);
|
|
808
|
-
},
|
|
809
|
-
warn(error) {
|
|
810
|
-
console.warn(`[${prefix}]`, error.format());
|
|
811
|
-
},
|
|
812
|
-
log(error) {
|
|
813
|
-
if (error.severity === "fatal" || error.severity === "error") this.error(error);
|
|
814
|
-
else this.warn(error);
|
|
815
|
-
}
|
|
816
|
-
};
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
function deepFreeze(obj) {
|
|
638
|
+
const propNames = Object.getOwnPropertyNames(obj);
|
|
639
|
+
for (const name of propNames) {
|
|
640
|
+
const value = obj[name];
|
|
641
|
+
if (value && typeof value === "object") deepFreeze(value);
|
|
817
642
|
}
|
|
818
|
-
|
|
643
|
+
return Object.freeze(obj);
|
|
644
|
+
}
|
|
819
645
|
//#endregion
|
|
820
|
-
//#region src/utils/
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
let
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
if (
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
} else timer = setTimeout(() => {
|
|
834
|
-
fn(...args);
|
|
835
|
-
timer = null;
|
|
836
|
-
lastArgs = null;
|
|
837
|
-
}, delay);
|
|
838
|
-
});
|
|
839
|
-
debounced.cancel = () => {
|
|
840
|
-
if (timer) {
|
|
841
|
-
clearTimeout(timer);
|
|
842
|
-
timer = null;
|
|
843
|
-
lastArgs = null;
|
|
844
|
-
}
|
|
845
|
-
};
|
|
846
|
-
debounced.flush = () => {
|
|
847
|
-
if (timer && lastArgs) {
|
|
848
|
-
clearTimeout(timer);
|
|
849
|
-
fn(...lastArgs);
|
|
850
|
-
timer = null;
|
|
851
|
-
lastArgs = null;
|
|
852
|
-
}
|
|
646
|
+
//#region src/utils/selector.ts
|
|
647
|
+
const ARRAY_INDEX_RE = /^\d+$/;
|
|
648
|
+
function createSelector(selector, equalityFn = Object.is) {
|
|
649
|
+
let lastState;
|
|
650
|
+
let lastResult;
|
|
651
|
+
let initialized = false;
|
|
652
|
+
return (state) => {
|
|
653
|
+
if (initialized && lastState === state) return lastResult;
|
|
654
|
+
const result = selector(state);
|
|
655
|
+
if (!initialized || !equalityFn(result, lastResult)) lastResult = result;
|
|
656
|
+
lastState = state;
|
|
657
|
+
initialized = true;
|
|
658
|
+
return lastResult;
|
|
853
659
|
};
|
|
854
|
-
debounced.pending = () => timer !== null;
|
|
855
|
-
return debounced;
|
|
856
660
|
}
|
|
857
|
-
function
|
|
858
|
-
const {
|
|
859
|
-
let
|
|
860
|
-
let
|
|
861
|
-
let
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
661
|
+
function createSelectorWithDeps(dependencies, combiner, options = {}) {
|
|
662
|
+
const { equalityFn = Object.is, trackHitRate = false } = options;
|
|
663
|
+
let lastDeps;
|
|
664
|
+
let lastResult;
|
|
665
|
+
let initialized = false;
|
|
666
|
+
let hits = 0;
|
|
667
|
+
let calls = 0;
|
|
668
|
+
const selector = (state) => {
|
|
669
|
+
if (trackHitRate) calls++;
|
|
670
|
+
const deps = dependencies.map((dep) => dep(state));
|
|
671
|
+
if (initialized && lastDeps) {
|
|
672
|
+
let changed = false;
|
|
673
|
+
for (let i = 0; i < deps.length; i++) if (!Object.is(deps[i], lastDeps[i])) {
|
|
674
|
+
changed = true;
|
|
675
|
+
break;
|
|
870
676
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
} else if (!timer && trailing) timer = setTimeout(() => {
|
|
875
|
-
lastTime = trailing ? Date.now() : 0;
|
|
876
|
-
timer = null;
|
|
877
|
-
if (lastArgs) {
|
|
878
|
-
fn(...lastArgs);
|
|
879
|
-
lastArgs = null;
|
|
677
|
+
if (!changed) {
|
|
678
|
+
if (trackHitRate) hits++;
|
|
679
|
+
return lastResult;
|
|
880
680
|
}
|
|
881
|
-
}, remaining);
|
|
882
|
-
});
|
|
883
|
-
throttled.cancel = () => {
|
|
884
|
-
if (timer) {
|
|
885
|
-
clearTimeout(timer);
|
|
886
|
-
timer = null;
|
|
887
681
|
}
|
|
888
|
-
|
|
889
|
-
|
|
682
|
+
const result = combiner(...deps);
|
|
683
|
+
if (!initialized || !equalityFn(result, lastResult)) lastResult = result;
|
|
684
|
+
lastDeps = deps;
|
|
685
|
+
initialized = true;
|
|
686
|
+
return lastResult;
|
|
890
687
|
};
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
896
|
-
function hasOwnKey(value, key) {
|
|
897
|
-
return hasOwnProperty.call(value, key);
|
|
898
|
-
}
|
|
899
|
-
function isObject(value) {
|
|
900
|
-
return value !== null && typeof value === "object";
|
|
688
|
+
if (trackHitRate) selector.getHitRate = () => {
|
|
689
|
+
return calls > 0 ? hits / calls : 0;
|
|
690
|
+
};
|
|
691
|
+
return selector;
|
|
901
692
|
}
|
|
902
|
-
function
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
function isStructuredCloneable(value) {
|
|
908
|
-
if (value === null || value === void 0) return true;
|
|
909
|
-
if (typeof value === "boolean" || typeof value === "number" || typeof value === "string") return true;
|
|
910
|
-
if (typeof value === "bigint") return true;
|
|
911
|
-
if (typeof value === "function" || typeof value === "symbol") return false;
|
|
912
|
-
if (value instanceof Date || value instanceof RegExp) return true;
|
|
913
|
-
if (value instanceof ArrayBuffer || value instanceof DataView) return true;
|
|
914
|
-
if (value instanceof Map || value instanceof Set) return true;
|
|
915
|
-
if (ArrayBuffer.isView(value)) return true;
|
|
916
|
-
if (Array.isArray(value)) return value.every((item) => isStructuredCloneable(item));
|
|
917
|
-
if (isPlainObject(value)) return Object.values(value).every((v) => isStructuredCloneable(v));
|
|
918
|
-
return false;
|
|
919
|
-
}
|
|
920
|
-
function deepClone(value, options = {}) {
|
|
921
|
-
const { useStructuredClone: preferStructuredClone = true, cloneFunctions = false, cloneSymbols = false, maxDepth = Infinity, customCloner } = options;
|
|
922
|
-
if (preferStructuredClone && typeof structuredClone === "function" && isStructuredCloneable(value)) try {
|
|
923
|
-
return structuredClone(value);
|
|
924
|
-
} catch {}
|
|
925
|
-
const cache = /* @__PURE__ */ new WeakMap();
|
|
926
|
-
function cloneInternal(val, depth) {
|
|
927
|
-
if (val === null || val === void 0) return val;
|
|
928
|
-
if (typeof val === "boolean" || typeof val === "number" || typeof val === "string") return val;
|
|
929
|
-
if (typeof val === "bigint") return val;
|
|
930
|
-
if (typeof val === "symbol") return cloneSymbols ? Symbol(val.description) : val;
|
|
931
|
-
if (typeof val === "function") return cloneFunctions ? val.bind({}) : val;
|
|
932
|
-
if (depth > maxDepth) return val;
|
|
933
|
-
if (customCloner) {
|
|
934
|
-
const customResult = customCloner(val, (v) => cloneInternal(v, depth + 1));
|
|
935
|
-
if (customResult !== void 0) return customResult;
|
|
936
|
-
}
|
|
937
|
-
if (typeof val === "object" && val !== null) {
|
|
938
|
-
if (cache.has(val)) return cache.get(val);
|
|
939
|
-
}
|
|
940
|
-
if (val instanceof Date) return new Date(val.getTime());
|
|
941
|
-
if (val instanceof RegExp) {
|
|
942
|
-
const result = new RegExp(val.source, val.flags);
|
|
943
|
-
result.lastIndex = val.lastIndex;
|
|
944
|
-
return result;
|
|
945
|
-
}
|
|
946
|
-
if (val instanceof Error) {
|
|
947
|
-
const result = new val.constructor(val.message);
|
|
948
|
-
result.stack = val.stack;
|
|
949
|
-
result.name = val.name;
|
|
950
|
-
return result;
|
|
951
|
-
}
|
|
952
|
-
if (val instanceof Map) {
|
|
953
|
-
const result = /* @__PURE__ */ new Map();
|
|
954
|
-
cache.set(val, result);
|
|
955
|
-
val.forEach((v, k) => {
|
|
956
|
-
result.set(cloneInternal(k, depth + 1), cloneInternal(v, depth + 1));
|
|
957
|
-
});
|
|
958
|
-
return result;
|
|
959
|
-
}
|
|
960
|
-
if (val instanceof Set) {
|
|
961
|
-
const result = /* @__PURE__ */ new Set();
|
|
962
|
-
cache.set(val, result);
|
|
963
|
-
val.forEach((v) => {
|
|
964
|
-
result.add(cloneInternal(v, depth + 1));
|
|
965
|
-
});
|
|
966
|
-
return result;
|
|
967
|
-
}
|
|
968
|
-
if (val instanceof ArrayBuffer) return val.slice(0);
|
|
969
|
-
if (ArrayBuffer.isView(val) && !(val instanceof DataView)) {
|
|
970
|
-
const TypedArrayConstructor = val.constructor;
|
|
971
|
-
return new TypedArrayConstructor(val.buffer.slice(0));
|
|
972
|
-
}
|
|
973
|
-
if (Array.isArray(val)) {
|
|
974
|
-
const result = [];
|
|
975
|
-
cache.set(val, result);
|
|
976
|
-
for (let i = 0; i < val.length; i++) result[i] = cloneInternal(val[i], depth + 1);
|
|
977
|
-
return result;
|
|
978
|
-
}
|
|
979
|
-
if (isPlainObject(val)) {
|
|
980
|
-
const result = {};
|
|
981
|
-
cache.set(val, result);
|
|
982
|
-
const keys = Object.keys(val);
|
|
983
|
-
for (const key of keys) result[key] = cloneInternal(val[key], depth + 1);
|
|
984
|
-
if (cloneSymbols) {
|
|
985
|
-
const symbolKeys = Object.getOwnPropertySymbols(val);
|
|
986
|
-
for (const sym of symbolKeys) result[sym] = cloneInternal(val[sym], depth + 1);
|
|
987
|
-
}
|
|
988
|
-
return result;
|
|
989
|
-
}
|
|
990
|
-
return val;
|
|
991
|
-
}
|
|
992
|
-
return cloneInternal(value, 0);
|
|
993
|
-
}
|
|
994
|
-
function shallowClone(value) {
|
|
995
|
-
if (value === null || value === void 0) return value;
|
|
996
|
-
if (typeof value !== "object") return value;
|
|
997
|
-
if (Array.isArray(value)) return [...value];
|
|
998
|
-
if (value instanceof Map) return new Map(value);
|
|
999
|
-
if (value instanceof Set) return new Set(value);
|
|
1000
|
-
if (value instanceof Date) return new Date(value.getTime());
|
|
1001
|
-
return { ...value };
|
|
1002
|
-
}
|
|
1003
|
-
function deepMerge(target, ...sources) {
|
|
1004
|
-
return deepMergeWithOptions(target, {}, ...sources);
|
|
1005
|
-
}
|
|
1006
|
-
function deepMergeWithOptions(target, options, ...sources) {
|
|
1007
|
-
const { arrayStrategy = "replace", clone = true, maxDepth = Infinity } = options;
|
|
1008
|
-
function mergeInternal(targetObj, sourceObj, depth) {
|
|
1009
|
-
if (depth > maxDepth) return targetObj;
|
|
1010
|
-
for (const key of Object.keys(sourceObj)) {
|
|
1011
|
-
const sourceValue = sourceObj[key];
|
|
1012
|
-
const targetValue = targetObj[key];
|
|
1013
|
-
if (Array.isArray(sourceValue)) if (arrayStrategy === "concat" && Array.isArray(targetValue)) targetObj[key] = [...targetValue, ...sourceValue];
|
|
1014
|
-
else if (arrayStrategy === "merge" && Array.isArray(targetValue)) {
|
|
1015
|
-
const result2 = [...targetValue];
|
|
1016
|
-
sourceValue.forEach((item, index) => {
|
|
1017
|
-
if (isPlainObject(item) && isPlainObject(result2[index])) result2[index] = mergeInternal(result2[index], item, depth + 1);
|
|
1018
|
-
else result2[index] = clone ? deepClone(item) : item;
|
|
1019
|
-
});
|
|
1020
|
-
targetObj[key] = result2;
|
|
1021
|
-
} else targetObj[key] = clone ? deepClone(sourceValue) : sourceValue;
|
|
1022
|
-
else if (isPlainObject(sourceValue)) if (isPlainObject(targetValue)) targetObj[key] = mergeInternal(targetValue, sourceValue, depth + 1);
|
|
1023
|
-
else targetObj[key] = clone ? deepClone(sourceValue) : sourceValue;
|
|
1024
|
-
else targetObj[key] = clone && isObject(sourceValue) ? deepClone(sourceValue) : sourceValue;
|
|
1025
|
-
}
|
|
1026
|
-
return targetObj;
|
|
1027
|
-
}
|
|
1028
|
-
let result = target;
|
|
1029
|
-
for (const source of sources) if (source !== null && source !== void 0) result = mergeInternal(result, source, 0);
|
|
1030
|
-
return result;
|
|
1031
|
-
}
|
|
1032
|
-
function deepEqual(a, b) {
|
|
1033
|
-
if (a === b) return true;
|
|
1034
|
-
if (a === null || b === null || a === void 0 || b === void 0) return a === b;
|
|
1035
|
-
if (typeof a !== typeof b) return false;
|
|
1036
|
-
if (typeof a !== "object") return a === b;
|
|
1037
|
-
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
1038
|
-
if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
|
|
1039
|
-
if (a instanceof Map && b instanceof Map) {
|
|
1040
|
-
if (a.size !== b.size) return false;
|
|
1041
|
-
for (const [key, value] of a) if (!b.has(key) || !deepEqual(value, b.get(key))) return false;
|
|
1042
|
-
return true;
|
|
1043
|
-
}
|
|
1044
|
-
if (a instanceof Set && b instanceof Set) {
|
|
1045
|
-
if (a.size !== b.size) return false;
|
|
1046
|
-
for (const value of a) if (!b.has(value)) return false;
|
|
1047
|
-
return true;
|
|
1048
|
-
}
|
|
1049
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1050
|
-
if (a.length !== b.length) return false;
|
|
1051
|
-
for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false;
|
|
1052
|
-
return true;
|
|
1053
|
-
}
|
|
1054
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
1055
|
-
const keysA = Object.keys(a);
|
|
1056
|
-
const keysB = Object.keys(b);
|
|
1057
|
-
if (keysA.length !== keysB.length) return false;
|
|
1058
|
-
for (const key of keysA) {
|
|
1059
|
-
if (!hasOwnKey(b, key)) return false;
|
|
1060
|
-
if (!deepEqual(a[key], b[key])) return false;
|
|
1061
|
-
}
|
|
1062
|
-
return true;
|
|
1063
|
-
}
|
|
1064
|
-
return false;
|
|
1065
|
-
}
|
|
1066
|
-
function deepFreeze(obj) {
|
|
1067
|
-
const propNames = Object.getOwnPropertyNames(obj);
|
|
1068
|
-
for (const name of propNames) {
|
|
1069
|
-
const value = obj[name];
|
|
1070
|
-
if (value && typeof value === "object") deepFreeze(value);
|
|
1071
|
-
}
|
|
1072
|
-
return Object.freeze(obj);
|
|
1073
|
-
}
|
|
1074
|
-
//#endregion
|
|
1075
|
-
//#region src/utils/selector.ts
|
|
1076
|
-
const ARRAY_INDEX_RE = /^\d+$/;
|
|
1077
|
-
function createSelector(selector, equalityFn = Object.is) {
|
|
1078
|
-
let lastState;
|
|
1079
|
-
let lastResult;
|
|
1080
|
-
let initialized = false;
|
|
1081
|
-
return (state) => {
|
|
1082
|
-
if (initialized && lastState === state) return lastResult;
|
|
1083
|
-
const result = selector(state);
|
|
1084
|
-
if (!initialized || !equalityFn(result, lastResult)) lastResult = result;
|
|
1085
|
-
lastState = state;
|
|
1086
|
-
initialized = true;
|
|
1087
|
-
return lastResult;
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
function createSelectorWithDeps(dependencies, combiner, options = {}) {
|
|
1091
|
-
const { equalityFn = Object.is, trackHitRate = false } = options;
|
|
1092
|
-
let lastDeps;
|
|
1093
|
-
let lastResult;
|
|
1094
|
-
let initialized = false;
|
|
1095
|
-
let hits = 0;
|
|
1096
|
-
let calls = 0;
|
|
1097
|
-
const selector = (state) => {
|
|
1098
|
-
if (trackHitRate) calls++;
|
|
1099
|
-
const deps = dependencies.map((dep) => dep(state));
|
|
1100
|
-
if (initialized && lastDeps) {
|
|
1101
|
-
let changed = false;
|
|
1102
|
-
for (let i = 0; i < deps.length; i++) if (!Object.is(deps[i], lastDeps[i])) {
|
|
1103
|
-
changed = true;
|
|
1104
|
-
break;
|
|
1105
|
-
}
|
|
1106
|
-
if (!changed) {
|
|
1107
|
-
if (trackHitRate) hits++;
|
|
1108
|
-
return lastResult;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
const result = combiner(...deps);
|
|
1112
|
-
if (!initialized || !equalityFn(result, lastResult)) lastResult = result;
|
|
1113
|
-
lastDeps = deps;
|
|
1114
|
-
initialized = true;
|
|
1115
|
-
return lastResult;
|
|
1116
|
-
};
|
|
1117
|
-
if (trackHitRate) selector.getHitRate = () => {
|
|
1118
|
-
return calls > 0 ? hits / calls : 0;
|
|
1119
|
-
};
|
|
1120
|
-
return selector;
|
|
1121
|
-
}
|
|
1122
|
-
function combineSelectors(selectors, combiner) {
|
|
1123
|
-
return (state) => {
|
|
1124
|
-
return combiner(...selectors.map((selector) => selector(state)));
|
|
1125
|
-
};
|
|
693
|
+
function combineSelectors(selectors, combiner) {
|
|
694
|
+
return (state) => {
|
|
695
|
+
return combiner(...selectors.map((selector) => selector(state)));
|
|
696
|
+
};
|
|
1126
697
|
}
|
|
1127
698
|
function createCachedSelector(selector, options = {}) {
|
|
1128
699
|
const { maxSize = 10 } = options;
|
|
@@ -1158,58 +729,835 @@
|
|
|
1158
729
|
if (typeof result !== "object") return defaultValue;
|
|
1159
730
|
result = result[key];
|
|
1160
731
|
}
|
|
1161
|
-
return result === void 0 ? defaultValue : result;
|
|
1162
|
-
}
|
|
1163
|
-
function setByPath(obj, path, value) {
|
|
1164
|
-
if (!path || path.length === 0) return false;
|
|
1165
|
-
const keys = path.replace(/\[([^\]]+)\]/g, ".$1").split(".").filter(Boolean);
|
|
1166
|
-
let current = obj;
|
|
1167
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
1168
|
-
const key = keys[i];
|
|
1169
|
-
const nextKey = keys[i + 1] ?? "";
|
|
1170
|
-
const nextValue = current[key] ?? (ARRAY_INDEX_RE.test(nextKey) ? [] : {});
|
|
1171
|
-
current[key] = nextValue;
|
|
1172
|
-
current = current[key];
|
|
732
|
+
return result === void 0 ? defaultValue : result;
|
|
733
|
+
}
|
|
734
|
+
function setByPath(obj, path, value) {
|
|
735
|
+
if (!path || path.length === 0) return false;
|
|
736
|
+
const keys = path.replace(/\[([^\]]+)\]/g, ".$1").split(".").filter(Boolean);
|
|
737
|
+
let current = obj;
|
|
738
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
739
|
+
const key = keys[i];
|
|
740
|
+
const nextKey = keys[i + 1] ?? "";
|
|
741
|
+
const nextValue = current[key] ?? (ARRAY_INDEX_RE.test(nextKey) ? [] : {});
|
|
742
|
+
current[key] = nextValue;
|
|
743
|
+
current = current[key];
|
|
744
|
+
}
|
|
745
|
+
const lastKey = keys[keys.length - 1];
|
|
746
|
+
current[lastKey] = value;
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
function deleteByPath(obj, path) {
|
|
750
|
+
if (!path || path.length === 0) return false;
|
|
751
|
+
const keys = path.replace(/\[([^\]]+)\]/g, ".$1").split(".").filter(Boolean);
|
|
752
|
+
let current = obj;
|
|
753
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
754
|
+
const key = keys[i];
|
|
755
|
+
if (current[key] === void 0 || current[key] === null) return false;
|
|
756
|
+
current = current[key];
|
|
757
|
+
}
|
|
758
|
+
const lastKey = keys[keys.length - 1];
|
|
759
|
+
if (lastKey in current) {
|
|
760
|
+
if (Array.isArray(current)) {
|
|
761
|
+
const index = Number.parseInt(lastKey, 10);
|
|
762
|
+
if (!Number.isNaN(index)) {
|
|
763
|
+
current.splice(index, 1);
|
|
764
|
+
return true;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
delete current[lastKey];
|
|
768
|
+
return true;
|
|
769
|
+
}
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
function hasPath(obj, path) {
|
|
773
|
+
if (!path || path.length === 0) return true;
|
|
774
|
+
const keys = path.replace(/\[([^\]]+)\]/g, ".$1").split(".").filter(Boolean);
|
|
775
|
+
let current = obj;
|
|
776
|
+
for (const key of keys) {
|
|
777
|
+
if (current === null || current === void 0) return false;
|
|
778
|
+
if (typeof current !== "object") return false;
|
|
779
|
+
if (!(key in current)) return false;
|
|
780
|
+
current = current[key];
|
|
781
|
+
}
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
//#endregion
|
|
785
|
+
//#region src/core/batch-manager.ts
|
|
786
|
+
function createBatchManager(onFlush) {
|
|
787
|
+
let batchDepth = 0;
|
|
788
|
+
const flushListeners = /* @__PURE__ */ new Set();
|
|
789
|
+
const pendingStores = /* @__PURE__ */ new Set();
|
|
790
|
+
const flush = () => {
|
|
791
|
+
if (pendingStores.size > 0) {
|
|
792
|
+
const stores = new Set(pendingStores);
|
|
793
|
+
pendingStores.clear();
|
|
794
|
+
onFlush?.(stores);
|
|
795
|
+
flushListeners.forEach((listener) => {
|
|
796
|
+
try {
|
|
797
|
+
listener(stores);
|
|
798
|
+
} catch (error) {
|
|
799
|
+
console.error("[Batch] flush listener failed:", error);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
const start = () => {
|
|
805
|
+
batchDepth++;
|
|
806
|
+
};
|
|
807
|
+
const end = () => {
|
|
808
|
+
if (batchDepth === 0) return;
|
|
809
|
+
batchDepth--;
|
|
810
|
+
if (batchDepth === 0) flush();
|
|
811
|
+
};
|
|
812
|
+
const markDirty = (storeId) => {
|
|
813
|
+
pendingStores.add(storeId);
|
|
814
|
+
if (batchDepth === 0) flush();
|
|
815
|
+
};
|
|
816
|
+
const batch2 = (fn) => {
|
|
817
|
+
start();
|
|
818
|
+
try {
|
|
819
|
+
return fn();
|
|
820
|
+
} finally {
|
|
821
|
+
end();
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
const isBatching = () => batchDepth > 0;
|
|
825
|
+
const onFlushListener = (listener) => {
|
|
826
|
+
flushListeners.add(listener);
|
|
827
|
+
return () => flushListeners.delete(listener);
|
|
828
|
+
};
|
|
829
|
+
return {
|
|
830
|
+
start,
|
|
831
|
+
end,
|
|
832
|
+
markDirty,
|
|
833
|
+
batch: batch2,
|
|
834
|
+
isBatching,
|
|
835
|
+
onFlush: onFlushListener
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
let globalBatchManager = null;
|
|
839
|
+
function getGlobalBatchManager() {
|
|
840
|
+
if (!globalBatchManager) globalBatchManager = createBatchManager();
|
|
841
|
+
return globalBatchManager;
|
|
842
|
+
}
|
|
843
|
+
function setGlobalBatchManager(manager) {
|
|
844
|
+
globalBatchManager = manager;
|
|
845
|
+
}
|
|
846
|
+
function batch(fn) {
|
|
847
|
+
return getGlobalBatchManager().batch(fn);
|
|
848
|
+
}
|
|
849
|
+
//#endregion
|
|
850
|
+
//#region src/core/event-bus.ts
|
|
851
|
+
function createEventBus() {
|
|
852
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
853
|
+
const getListeners = (type) => {
|
|
854
|
+
let set = listeners.get(type);
|
|
855
|
+
if (!set) {
|
|
856
|
+
set = /* @__PURE__ */ new Set();
|
|
857
|
+
listeners.set(type, set);
|
|
858
|
+
}
|
|
859
|
+
return set;
|
|
860
|
+
};
|
|
861
|
+
const on = (type, listener) => {
|
|
862
|
+
const set = getListeners(type);
|
|
863
|
+
set.add(listener);
|
|
864
|
+
return () => {
|
|
865
|
+
set.delete(listener);
|
|
866
|
+
if (set.size === 0) listeners.delete(type);
|
|
867
|
+
};
|
|
868
|
+
};
|
|
869
|
+
const off = (type, listener) => {
|
|
870
|
+
if (listener) {
|
|
871
|
+
const set = listeners.get(type);
|
|
872
|
+
if (set) {
|
|
873
|
+
set.delete(listener);
|
|
874
|
+
if (set.size === 0) listeners.delete(type);
|
|
875
|
+
}
|
|
876
|
+
} else listeners.delete(type);
|
|
877
|
+
};
|
|
878
|
+
const once = (type, listener) => {
|
|
879
|
+
const wrappedListener = (data) => {
|
|
880
|
+
listener(data);
|
|
881
|
+
off(type, wrappedListener);
|
|
882
|
+
};
|
|
883
|
+
return on(type, wrappedListener);
|
|
884
|
+
};
|
|
885
|
+
const emit = (type, payload) => {
|
|
886
|
+
const data = {
|
|
887
|
+
type,
|
|
888
|
+
payload,
|
|
889
|
+
timestamp: Date.now()
|
|
890
|
+
};
|
|
891
|
+
const typeListeners = listeners.get(type);
|
|
892
|
+
if (typeListeners) typeListeners.forEach((listener) => listener(data));
|
|
893
|
+
const wildcardListeners = listeners.get("*");
|
|
894
|
+
if (wildcardListeners) wildcardListeners.forEach((listener) => listener(data));
|
|
895
|
+
};
|
|
896
|
+
const clear = () => {
|
|
897
|
+
listeners.clear();
|
|
898
|
+
};
|
|
899
|
+
return {
|
|
900
|
+
on,
|
|
901
|
+
once,
|
|
902
|
+
off,
|
|
903
|
+
emit,
|
|
904
|
+
clear
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
const globalEventBus = createEventBus();
|
|
908
|
+
//#endregion
|
|
909
|
+
//#region src/core/base-store.ts
|
|
910
|
+
var __defProp$1 = Object.defineProperty;
|
|
911
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
|
|
912
|
+
enumerable: true,
|
|
913
|
+
configurable: true,
|
|
914
|
+
writable: true,
|
|
915
|
+
value
|
|
916
|
+
}) : obj[key] = value;
|
|
917
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
918
|
+
function isPromiseLike(value) {
|
|
919
|
+
return !!value && typeof value.then === "function";
|
|
920
|
+
}
|
|
921
|
+
async function runCallbacks(callbacks, value) {
|
|
922
|
+
for (const callback of callbacks) await callback(value);
|
|
923
|
+
}
|
|
924
|
+
var BaseStore = class {
|
|
925
|
+
constructor(definition, options = {}) {
|
|
926
|
+
__publicField$1(this, "$id");
|
|
927
|
+
__publicField$1(this, "getters");
|
|
928
|
+
__publicField$1(this, "actions");
|
|
929
|
+
__publicField$1(this, "stateSubscribers", createPubSub());
|
|
930
|
+
__publicField$1(this, "actionSubscribers", createPubSub());
|
|
931
|
+
__publicField$1(this, "initialStateFactory");
|
|
932
|
+
__publicField$1(this, "middlewareManager");
|
|
933
|
+
__publicField$1(this, "pluginManager");
|
|
934
|
+
__publicField$1(this, "batchManager");
|
|
935
|
+
__publicField$1(this, "pendingBatchMutation", null);
|
|
936
|
+
__publicField$1(this, "stopBatchFlush");
|
|
937
|
+
__publicField$1(this, "mutationQueue", Promise.resolve());
|
|
938
|
+
__publicField$1(this, "pendingMutations", 0);
|
|
939
|
+
__publicField$1(this, "_state");
|
|
940
|
+
__publicField$1(this, "disposed", false);
|
|
941
|
+
this.$id = definition.id;
|
|
942
|
+
this.initialStateFactory = definition.state;
|
|
943
|
+
this._state = definition.state();
|
|
944
|
+
this.middlewareManager = options.middleware ?? getGlobalMiddlewareManager();
|
|
945
|
+
this.pluginManager = options.plugins ?? getGlobalPluginManager();
|
|
946
|
+
this.batchManager = options.batch ?? getGlobalBatchManager();
|
|
947
|
+
this.getters = this.createGetters(definition.getters || {});
|
|
948
|
+
this.actions = this.createActions(definition.actions || {});
|
|
949
|
+
this.stopBatchFlush = this.batchManager.onFlush?.((storeIds) => {
|
|
950
|
+
if (!storeIds.has(this.$id) || !this.pendingBatchMutation) return;
|
|
951
|
+
const mutation = this.pendingBatchMutation;
|
|
952
|
+
this.pendingBatchMutation = null;
|
|
953
|
+
this.publishStateChange(mutation);
|
|
954
|
+
});
|
|
955
|
+
globalEventBus.emit("store:created", { storeId: this.$id });
|
|
956
|
+
this.notifyPluginStoreCreated();
|
|
957
|
+
}
|
|
958
|
+
get $state() {
|
|
959
|
+
return this._state;
|
|
960
|
+
}
|
|
961
|
+
set $state(newState) {
|
|
962
|
+
this.checkDisposed();
|
|
963
|
+
const nextState = deepClone(newState);
|
|
964
|
+
const operation = () => this.runStateMutation(nextState, newState);
|
|
965
|
+
this.scheduleMutation(operation).catch((error) => {
|
|
966
|
+
console.error(`[Store] Failed to replace state for "${this.$id}":`, error);
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
$reset() {
|
|
970
|
+
this.checkDisposed();
|
|
971
|
+
this.scheduleMutation(() => this.runStateMutation()).catch((error) => {
|
|
972
|
+
console.error(`[Store] Failed to reset "${this.$id}":`, error);
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
$patch(partialState) {
|
|
976
|
+
this.checkDisposed();
|
|
977
|
+
const patch = typeof partialState === "function" ? partialState : deepClone(partialState);
|
|
978
|
+
this.scheduleMutation(() => this.runPatchMutation(patch)).catch((error) => {
|
|
979
|
+
console.error(`[Store] Failed to patch "${this.$id}":`, error);
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
async $patchAsync(partialState) {
|
|
983
|
+
this.checkDisposed();
|
|
984
|
+
const patch = typeof partialState === "function" ? partialState : deepClone(partialState);
|
|
985
|
+
await this.scheduleMutation(() => this.runPatchMutation(patch));
|
|
986
|
+
}
|
|
987
|
+
$subscribe(callback, options = {}) {
|
|
988
|
+
this.checkDisposed();
|
|
989
|
+
const unsubscribe = this.stateSubscribers.subscribe(({ mutation, state }) => callback(mutation, state), { immediate: options.immediate });
|
|
990
|
+
if (options.immediate) try {
|
|
991
|
+
callback({
|
|
992
|
+
type: "direct",
|
|
993
|
+
storeId: this.$id
|
|
994
|
+
}, deepClone(this._state));
|
|
995
|
+
} catch (error) {
|
|
996
|
+
console.error("[Store] immediate subscriber failed:", error);
|
|
997
|
+
}
|
|
998
|
+
return unsubscribe;
|
|
999
|
+
}
|
|
1000
|
+
$onAction(callback) {
|
|
1001
|
+
this.checkDisposed();
|
|
1002
|
+
return this.actionSubscribers.subscribe(callback);
|
|
1003
|
+
}
|
|
1004
|
+
$dispose() {
|
|
1005
|
+
if (this.disposed) return;
|
|
1006
|
+
this.disposed = true;
|
|
1007
|
+
this.stopBatchFlush?.();
|
|
1008
|
+
this.stopBatchFlush = void 0;
|
|
1009
|
+
this.mutationQueue = Promise.resolve();
|
|
1010
|
+
this.pendingMutations = 0;
|
|
1011
|
+
this.stateSubscribers.clear();
|
|
1012
|
+
this.actionSubscribers.clear();
|
|
1013
|
+
this.notifyPluginStoreDisposed();
|
|
1014
|
+
globalEventBus.emit("store:disposed", { storeId: this.$id });
|
|
1015
|
+
}
|
|
1016
|
+
notifyStateChange(mutation) {
|
|
1017
|
+
this.publishStateChange(mutation);
|
|
1018
|
+
}
|
|
1019
|
+
publishStateChange(mutation) {
|
|
1020
|
+
const stateSnapshot = deepClone(this._state);
|
|
1021
|
+
this.stateSubscribers.publish({
|
|
1022
|
+
mutation,
|
|
1023
|
+
state: stateSnapshot
|
|
1024
|
+
});
|
|
1025
|
+
globalEventBus.emit("state:changed", {
|
|
1026
|
+
storeId: this.$id,
|
|
1027
|
+
state: stateSnapshot,
|
|
1028
|
+
mutation
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
async runMutation(candidate, mutation, payload, previousState) {
|
|
1032
|
+
this.checkDisposed();
|
|
1033
|
+
let committed = false;
|
|
1034
|
+
const commit = () => {
|
|
1035
|
+
if (committed || this.disposed) return;
|
|
1036
|
+
committed = true;
|
|
1037
|
+
this._state = candidate;
|
|
1038
|
+
this.notifyPluginStateChange(candidate, previousState);
|
|
1039
|
+
if (this.batchManager.isBatching() && this.batchManager.onFlush) {
|
|
1040
|
+
this.pendingBatchMutation = this.pendingBatchMutation ? {
|
|
1041
|
+
...mutation,
|
|
1042
|
+
oldState: this.pendingBatchMutation.oldState
|
|
1043
|
+
} : mutation;
|
|
1044
|
+
this.batchManager.markDirty(this.$id);
|
|
1045
|
+
} else this.publishStateChange(mutation);
|
|
1046
|
+
};
|
|
1047
|
+
if (this.middlewareManager.getAll().length === 0) {
|
|
1048
|
+
commit();
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
await this.middlewareManager.execute({
|
|
1052
|
+
storeId: this.$id,
|
|
1053
|
+
state: candidate,
|
|
1054
|
+
type: mutation.type === "direct" ? "state:reset" : "state:patch",
|
|
1055
|
+
payload,
|
|
1056
|
+
meta: {
|
|
1057
|
+
candidateState: candidate,
|
|
1058
|
+
previousState,
|
|
1059
|
+
commit
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
commit();
|
|
1063
|
+
}
|
|
1064
|
+
runStateMutation(nextState, payload) {
|
|
1065
|
+
this.checkDisposed();
|
|
1066
|
+
const previousState = deepClone(this._state);
|
|
1067
|
+
const mutation = {
|
|
1068
|
+
type: "direct",
|
|
1069
|
+
storeId: this.$id,
|
|
1070
|
+
oldState: previousState
|
|
1071
|
+
};
|
|
1072
|
+
return this.runMutation(deepClone(nextState ?? this.initialStateFactory()), mutation, payload, previousState);
|
|
1073
|
+
}
|
|
1074
|
+
runPatchMutation(partialState) {
|
|
1075
|
+
this.checkDisposed();
|
|
1076
|
+
const previousState = deepClone(this._state);
|
|
1077
|
+
const candidate = deepClone(this._state);
|
|
1078
|
+
const mutation = typeof partialState === "function" ? {
|
|
1079
|
+
type: "patch function",
|
|
1080
|
+
storeId: this.$id,
|
|
1081
|
+
oldState: previousState
|
|
1082
|
+
} : {
|
|
1083
|
+
type: "patch object",
|
|
1084
|
+
storeId: this.$id,
|
|
1085
|
+
oldState: previousState,
|
|
1086
|
+
events: Object.keys(partialState)
|
|
1087
|
+
};
|
|
1088
|
+
if (typeof partialState === "function") partialState(candidate);
|
|
1089
|
+
else Object.assign(candidate, partialState);
|
|
1090
|
+
return this.runMutation(candidate, mutation, partialState, previousState);
|
|
1091
|
+
}
|
|
1092
|
+
scheduleMutation(operation) {
|
|
1093
|
+
if (this.pendingMutations === 0 && this.middlewareManager.getAll().length === 0) return operation();
|
|
1094
|
+
this.pendingMutations += 1;
|
|
1095
|
+
const queuedOperation = this.mutationQueue.then(operation);
|
|
1096
|
+
this.mutationQueue = queuedOperation.catch(() => void 0);
|
|
1097
|
+
queuedOperation.then(() => {
|
|
1098
|
+
this.pendingMutations -= 1;
|
|
1099
|
+
}, () => {
|
|
1100
|
+
this.pendingMutations -= 1;
|
|
1101
|
+
});
|
|
1102
|
+
return queuedOperation;
|
|
1103
|
+
}
|
|
1104
|
+
notifyPluginStoreCreated() {
|
|
1105
|
+
if (this.pluginManager.notifyStoreCreated) {
|
|
1106
|
+
this.pluginManager.notifyStoreCreated(this);
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
this.pluginManager.getAll().forEach((plugin) => plugin.onStoreCreated?.(this));
|
|
1110
|
+
}
|
|
1111
|
+
notifyPluginStoreDisposed() {
|
|
1112
|
+
if (this.pluginManager.notifyStoreDisposed) {
|
|
1113
|
+
this.pluginManager.notifyStoreDisposed(this);
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
this.pluginManager.getAll().forEach((plugin) => plugin.onStoreDisposed?.(this));
|
|
1117
|
+
}
|
|
1118
|
+
notifyPluginStateChange(state, previousState) {
|
|
1119
|
+
if (this.pluginManager.notifyStateChange) {
|
|
1120
|
+
this.pluginManager.notifyStateChange(this.$id, deepClone(state), deepClone(previousState));
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
this.pluginManager.getAll().forEach((plugin) => plugin.onStateChange?.(this.$id, deepClone(state), deepClone(previousState)));
|
|
1124
|
+
}
|
|
1125
|
+
checkDisposed() {
|
|
1126
|
+
if (this.disposed) throw new Error(`[Store] Store "${this.$id}" has been disposed`);
|
|
1127
|
+
}
|
|
1128
|
+
createGetters(gettersDefinition) {
|
|
1129
|
+
const getterCache = {};
|
|
1130
|
+
for (const key of Object.keys(gettersDefinition)) Object.defineProperty(getterCache, key, {
|
|
1131
|
+
enumerable: true,
|
|
1132
|
+
get: () => gettersDefinition[key](this._state)
|
|
1133
|
+
});
|
|
1134
|
+
return getterCache;
|
|
1135
|
+
}
|
|
1136
|
+
createActions(actionsDefinition) {
|
|
1137
|
+
const actionCache = {};
|
|
1138
|
+
for (const key of Object.keys(actionsDefinition)) {
|
|
1139
|
+
const action = actionsDefinition[key];
|
|
1140
|
+
actionCache[key] = ((...args) => {
|
|
1141
|
+
this.checkDisposed();
|
|
1142
|
+
const afterCallbacks = [];
|
|
1143
|
+
const errorCallbacks = [];
|
|
1144
|
+
const context = {
|
|
1145
|
+
after: (callback) => afterCallbacks.push(callback),
|
|
1146
|
+
args,
|
|
1147
|
+
name: key,
|
|
1148
|
+
onError: (callback) => errorCallbacks.push(callback),
|
|
1149
|
+
storeId: this.$id
|
|
1150
|
+
};
|
|
1151
|
+
this.notifyAction(context);
|
|
1152
|
+
try {
|
|
1153
|
+
const result = action.apply(this, args);
|
|
1154
|
+
if (isPromiseLike(result)) return result.then(async (resolvedResult) => {
|
|
1155
|
+
await runCallbacks(afterCallbacks, resolvedResult);
|
|
1156
|
+
return resolvedResult;
|
|
1157
|
+
}).catch(async (error) => {
|
|
1158
|
+
await runCallbacks(errorCallbacks, error);
|
|
1159
|
+
throw error;
|
|
1160
|
+
});
|
|
1161
|
+
runCallbacks(afterCallbacks, result);
|
|
1162
|
+
return result;
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
runCallbacks(errorCallbacks, error);
|
|
1165
|
+
throw error;
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
return actionCache;
|
|
1170
|
+
}
|
|
1171
|
+
notifyAction(context) {
|
|
1172
|
+
this.actionSubscribers.publish(context);
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
//#endregion
|
|
1176
|
+
//#region src/core/create-store.ts
|
|
1177
|
+
function createStore(definition, options = {}) {
|
|
1178
|
+
let instance = null;
|
|
1179
|
+
return () => {
|
|
1180
|
+
if (instance) return instance;
|
|
1181
|
+
const store = new BaseStore(definition, options);
|
|
1182
|
+
const originalDispose = store.$dispose.bind(store);
|
|
1183
|
+
store.$dispose = () => {
|
|
1184
|
+
originalDispose();
|
|
1185
|
+
instance = null;
|
|
1186
|
+
};
|
|
1187
|
+
instance = store;
|
|
1188
|
+
return store;
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
//#endregion
|
|
1192
|
+
//#region src/engine/plugin.ts
|
|
1193
|
+
const storeStateKeys = {
|
|
1194
|
+
BUS: "store:bus",
|
|
1195
|
+
PINIA: "store:pinia",
|
|
1196
|
+
API: "store:api",
|
|
1197
|
+
REGISTRY: "store:registry",
|
|
1198
|
+
RUNTIME: "store:runtime"
|
|
1199
|
+
};
|
|
1200
|
+
const storeEventKeys = {
|
|
1201
|
+
INSTALLED: "store:installed",
|
|
1202
|
+
UNINSTALLED: "store:uninstalled"
|
|
1203
|
+
};
|
|
1204
|
+
function resolveEngine(context) {
|
|
1205
|
+
const value = context;
|
|
1206
|
+
if (value && typeof value === "object" && "engine" in value) return value.engine ?? {};
|
|
1207
|
+
return value ?? {};
|
|
1208
|
+
}
|
|
1209
|
+
function resolvePluginContext(context) {
|
|
1210
|
+
return context && typeof context === "object" ? context : void 0;
|
|
1211
|
+
}
|
|
1212
|
+
function resolveDefaultApp(engine, context, payload) {
|
|
1213
|
+
const payloadObject = payload;
|
|
1214
|
+
return payloadObject?.app ?? payloadObject?.framework?.app ?? engine.getApp?.() ?? context?.framework?.app;
|
|
1215
|
+
}
|
|
1216
|
+
function createRegisteredApi(name, version, runtime) {
|
|
1217
|
+
return {
|
|
1218
|
+
name,
|
|
1219
|
+
version,
|
|
1220
|
+
pinia: runtime.pinia,
|
|
1221
|
+
getStore: runtime.storeAPI.getStore,
|
|
1222
|
+
hasStore: runtime.storeAPI.hasStore,
|
|
1223
|
+
getStoreIds: runtime.storeAPI.getStoreIds,
|
|
1224
|
+
resetAll: runtime.storeAPI.resetAll
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
function registerEngineApi(engine, name, version, runtime) {
|
|
1228
|
+
if (!engine.api?.register) return;
|
|
1229
|
+
const api = createRegisteredApi(name, version, runtime);
|
|
1230
|
+
engine.api.unregister?.(name);
|
|
1231
|
+
if (engine.api.register.length >= 2) {
|
|
1232
|
+
engine.api.register(name, api);
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
engine.api.register(api);
|
|
1236
|
+
}
|
|
1237
|
+
function syncEngineState(engine, name, options, runtime) {
|
|
1238
|
+
engine.state?.set?.(storeStateKeys.RUNTIME, runtime);
|
|
1239
|
+
engine.state?.set?.(storeStateKeys.PINIA, runtime.pinia);
|
|
1240
|
+
engine.state?.set?.(storeStateKeys.API, runtime.storeAPI);
|
|
1241
|
+
engine.state?.set?.(storeStateKeys.REGISTRY, runtime.registry);
|
|
1242
|
+
engine.state?.set?.(storeStateKeys.BUS, globalEventBus);
|
|
1243
|
+
engine.state?.set?.(`plugins.${name}`, runtime.storeAPI);
|
|
1244
|
+
engine.state?.set?.(`plugins.${name}.config`, options);
|
|
1245
|
+
}
|
|
1246
|
+
function clearEngineState(engine, name) {
|
|
1247
|
+
engine.state?.delete?.(storeStateKeys.RUNTIME);
|
|
1248
|
+
engine.state?.delete?.(storeStateKeys.PINIA);
|
|
1249
|
+
engine.state?.delete?.(storeStateKeys.API);
|
|
1250
|
+
engine.state?.delete?.(storeStateKeys.REGISTRY);
|
|
1251
|
+
engine.state?.delete?.(storeStateKeys.BUS);
|
|
1252
|
+
engine.state?.delete?.(`plugins.${name}`);
|
|
1253
|
+
engine.state?.delete?.(`plugins.${name}.config`);
|
|
1254
|
+
}
|
|
1255
|
+
function registerContainerServices(context, runtime) {
|
|
1256
|
+
if (!context?.container?.singleton) return;
|
|
1257
|
+
try {
|
|
1258
|
+
context.container.singleton("pinia", runtime.pinia);
|
|
1259
|
+
context.container.singleton("storeAPI", runtime.storeAPI);
|
|
1260
|
+
context.container.singleton("storeRegistry", runtime.registry);
|
|
1261
|
+
context.container.singleton("storeRuntime", runtime);
|
|
1262
|
+
} catch {}
|
|
1263
|
+
}
|
|
1264
|
+
function createStoreEngineBridge(options) {
|
|
1265
|
+
const { createRuntime, debug = false, name = "store", onRuntimeChange, version = "0.0.1" } = options;
|
|
1266
|
+
let activeEngine = {};
|
|
1267
|
+
let activeContext;
|
|
1268
|
+
let runtime = null;
|
|
1269
|
+
let runtimeOwner = null;
|
|
1270
|
+
let lifecycleToken = 0;
|
|
1271
|
+
let pendingAppCreatedToken = null;
|
|
1272
|
+
const bindRuntime = (nextRuntime, owner) => {
|
|
1273
|
+
const previousRuntime = runtime;
|
|
1274
|
+
const previousOwner = runtimeOwner;
|
|
1275
|
+
runtime = nextRuntime;
|
|
1276
|
+
runtimeOwner = owner;
|
|
1277
|
+
onRuntimeChange?.(nextRuntime);
|
|
1278
|
+
syncEngineState(activeEngine, name, options, nextRuntime);
|
|
1279
|
+
registerEngineApi(activeEngine, name, version, nextRuntime);
|
|
1280
|
+
registerContainerServices(activeContext, nextRuntime);
|
|
1281
|
+
if (previousRuntime && previousRuntime !== nextRuntime && previousOwner === "engine") previousRuntime.dispose?.();
|
|
1282
|
+
return nextRuntime;
|
|
1283
|
+
};
|
|
1284
|
+
const ensureRuntime = () => {
|
|
1285
|
+
if (runtime && runtimeOwner === "engine") return runtime;
|
|
1286
|
+
return createRuntime();
|
|
1287
|
+
};
|
|
1288
|
+
const attachToApp = (app) => {
|
|
1289
|
+
const installedRuntime = options.getRuntimeFromApp?.(app);
|
|
1290
|
+
if (installedRuntime) return bindRuntime(installedRuntime, "external");
|
|
1291
|
+
const nextRuntime = ensureRuntime();
|
|
1292
|
+
const mountedRuntime = options.attachToApp ? options.attachToApp(app, nextRuntime) : nextRuntime;
|
|
1293
|
+
return bindRuntime(mountedRuntime, mountedRuntime === nextRuntime ? "engine" : "external");
|
|
1294
|
+
};
|
|
1295
|
+
const install = async (context) => {
|
|
1296
|
+
const installToken = ++lifecycleToken;
|
|
1297
|
+
pendingAppCreatedToken = null;
|
|
1298
|
+
activeEngine = resolveEngine(context);
|
|
1299
|
+
activeContext = resolvePluginContext(context);
|
|
1300
|
+
const app = options.resolveApp ? options.resolveApp(activeEngine, activeContext ?? {}, void 0) : resolveDefaultApp(activeEngine, activeContext);
|
|
1301
|
+
if (app && (!options.isApp || options.isApp(app))) attachToApp(app);
|
|
1302
|
+
else {
|
|
1303
|
+
bindRuntime(ensureRuntime(), "engine");
|
|
1304
|
+
pendingAppCreatedToken = installToken;
|
|
1305
|
+
activeEngine.events?.once?.("app:created", (payload) => {
|
|
1306
|
+
if (pendingAppCreatedToken !== installToken || lifecycleToken !== installToken || !runtime) return;
|
|
1307
|
+
pendingAppCreatedToken = null;
|
|
1308
|
+
const createdApp = options.resolveApp ? options.resolveApp(activeEngine, activeContext ?? {}, payload) : resolveDefaultApp(activeEngine, activeContext, payload);
|
|
1309
|
+
if (createdApp && (!options.isApp || options.isApp(createdApp))) attachToApp(createdApp);
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
await activeEngine.events?.emit?.(storeEventKeys.INSTALLED, {
|
|
1313
|
+
name,
|
|
1314
|
+
version,
|
|
1315
|
+
pinia: runtime?.pinia,
|
|
1316
|
+
storeAPI: runtime?.storeAPI
|
|
1317
|
+
});
|
|
1318
|
+
if (debug) activeEngine.logger?.info?.("[StoreEngineBridge] installed");
|
|
1319
|
+
};
|
|
1320
|
+
const uninstall = async (context) => {
|
|
1321
|
+
lifecycleToken++;
|
|
1322
|
+
pendingAppCreatedToken = null;
|
|
1323
|
+
const engine = context ? resolveEngine(context) : activeEngine;
|
|
1324
|
+
engine.api?.unregister?.(name);
|
|
1325
|
+
clearEngineState(engine, name);
|
|
1326
|
+
await engine.events?.emit?.(storeEventKeys.UNINSTALLED, { name });
|
|
1327
|
+
if (runtime && runtimeOwner === "engine") runtime.dispose?.();
|
|
1328
|
+
runtime = null;
|
|
1329
|
+
runtimeOwner = null;
|
|
1330
|
+
onRuntimeChange?.(null);
|
|
1331
|
+
if (debug) engine.logger?.info?.("[StoreEngineBridge] uninstalled");
|
|
1332
|
+
};
|
|
1333
|
+
return {
|
|
1334
|
+
attachToApp,
|
|
1335
|
+
getRuntime: () => runtime,
|
|
1336
|
+
install,
|
|
1337
|
+
uninstall
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
//#endregion
|
|
1341
|
+
//#region src/errors/index.ts
|
|
1342
|
+
var __defProp = Object.defineProperty;
|
|
1343
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
1344
|
+
enumerable: true,
|
|
1345
|
+
configurable: true,
|
|
1346
|
+
writable: true,
|
|
1347
|
+
value
|
|
1348
|
+
}) : obj[key] = value;
|
|
1349
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1350
|
+
var StoreErrorCode = /* @__PURE__ */ ((StoreErrorCode2) => {
|
|
1351
|
+
StoreErrorCode2["STORE_DISPOSED"] = "STORE_DISPOSED";
|
|
1352
|
+
StoreErrorCode2["STORE_NOT_FOUND"] = "STORE_NOT_FOUND";
|
|
1353
|
+
StoreErrorCode2["STORE_ALREADY_EXISTS"] = "STORE_ALREADY_EXISTS";
|
|
1354
|
+
StoreErrorCode2["INVALID_STATE"] = "INVALID_STATE";
|
|
1355
|
+
StoreErrorCode2["INVALID_ACTION"] = "INVALID_ACTION";
|
|
1356
|
+
StoreErrorCode2["SERIALIZATION_ERROR"] = "SERIALIZATION_ERROR";
|
|
1357
|
+
StoreErrorCode2["DESERIALIZATION_ERROR"] = "DESERIALIZATION_ERROR";
|
|
1358
|
+
StoreErrorCode2["STORAGE_ERROR"] = "STORAGE_ERROR";
|
|
1359
|
+
StoreErrorCode2["PLUGIN_ERROR"] = "PLUGIN_ERROR";
|
|
1360
|
+
StoreErrorCode2["MIDDLEWARE_ERROR"] = "MIDDLEWARE_ERROR";
|
|
1361
|
+
StoreErrorCode2["SUBSCRIPTION_ERROR"] = "SUBSCRIPTION_ERROR";
|
|
1362
|
+
StoreErrorCode2["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
|
|
1363
|
+
StoreErrorCode2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
1364
|
+
return StoreErrorCode2;
|
|
1365
|
+
})(StoreErrorCode || {});
|
|
1366
|
+
var ErrorSeverity = /* @__PURE__ */ ((ErrorSeverity2) => {
|
|
1367
|
+
ErrorSeverity2["WARNING"] = "warning";
|
|
1368
|
+
ErrorSeverity2["ERROR"] = "error";
|
|
1369
|
+
ErrorSeverity2["FATAL"] = "fatal";
|
|
1370
|
+
return ErrorSeverity2;
|
|
1371
|
+
})(ErrorSeverity || {});
|
|
1372
|
+
var StoreError = class StoreError extends Error {
|
|
1373
|
+
/**
|
|
1374
|
+
* 创建 Store 错误
|
|
1375
|
+
*
|
|
1376
|
+
* @param message - 错误消息
|
|
1377
|
+
* @param code - 错误代码
|
|
1378
|
+
* @param context - 错误上下文
|
|
1379
|
+
* @param severity - 错误严重级别
|
|
1380
|
+
* @param cause - 原始错误
|
|
1381
|
+
*/
|
|
1382
|
+
constructor(message, code = "UNKNOWN_ERROR", context = {}, severity = "error", cause) {
|
|
1383
|
+
super(message);
|
|
1384
|
+
/** 错误代码 */
|
|
1385
|
+
__publicField(this, "code");
|
|
1386
|
+
/** 错误上下文 */
|
|
1387
|
+
__publicField(this, "context");
|
|
1388
|
+
/** 错误严重级别 */
|
|
1389
|
+
__publicField(this, "severity");
|
|
1390
|
+
/** 原始错误 */
|
|
1391
|
+
__publicField(this, "cause");
|
|
1392
|
+
this.name = "StoreError";
|
|
1393
|
+
this.code = code;
|
|
1394
|
+
this.context = {
|
|
1395
|
+
...context,
|
|
1396
|
+
timestamp: context.timestamp ?? Date.now()
|
|
1397
|
+
};
|
|
1398
|
+
this.severity = severity;
|
|
1399
|
+
this.cause = cause;
|
|
1400
|
+
Object.setPrototypeOf(this, StoreError.prototype);
|
|
1401
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, StoreError);
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* 转换为 JSON
|
|
1405
|
+
*/
|
|
1406
|
+
toJSON() {
|
|
1407
|
+
return {
|
|
1408
|
+
name: this.name,
|
|
1409
|
+
message: this.message,
|
|
1410
|
+
code: this.code,
|
|
1411
|
+
context: this.context,
|
|
1412
|
+
severity: this.severity,
|
|
1413
|
+
stack: this.stack
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* 格式化错误信息
|
|
1418
|
+
*/
|
|
1419
|
+
format() {
|
|
1420
|
+
const parts = [`[${this.code}] ${this.message}`];
|
|
1421
|
+
if (this.context.storeId) parts.push(`Store: ${this.context.storeId}`);
|
|
1422
|
+
if (this.context.action) parts.push(`Action: ${this.context.action}`);
|
|
1423
|
+
return parts.join(" | ");
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
var StoreDisposedError = class StoreDisposedError extends StoreError {
|
|
1427
|
+
constructor(storeId, action) {
|
|
1428
|
+
super(`Store "${storeId}" \u5DF2\u88AB\u9500\u6BC1\uFF0C\u65E0\u6CD5\u6267\u884C\u64CD\u4F5C${action ? `: ${action}` : ""}`, "STORE_DISPOSED", {
|
|
1429
|
+
storeId,
|
|
1430
|
+
action
|
|
1431
|
+
}, "error");
|
|
1432
|
+
this.name = "StoreDisposedError";
|
|
1433
|
+
Object.setPrototypeOf(this, StoreDisposedError.prototype);
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
var StoreNotFoundError = class StoreNotFoundError extends StoreError {
|
|
1437
|
+
constructor(storeId) {
|
|
1438
|
+
super(`Store "${storeId}" \u4E0D\u5B58\u5728`, "STORE_NOT_FOUND", { storeId }, "error");
|
|
1439
|
+
this.name = "StoreNotFoundError";
|
|
1440
|
+
Object.setPrototypeOf(this, StoreNotFoundError.prototype);
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
var StoreAlreadyExistsError = class StoreAlreadyExistsError extends StoreError {
|
|
1444
|
+
constructor(storeId) {
|
|
1445
|
+
super(`Store "${storeId}" \u5DF2\u5B58\u5728`, "STORE_ALREADY_EXISTS", { storeId }, "warning");
|
|
1446
|
+
this.name = "StoreAlreadyExistsError";
|
|
1447
|
+
Object.setPrototypeOf(this, StoreAlreadyExistsError.prototype);
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
var InvalidStateError = class InvalidStateError extends StoreError {
|
|
1451
|
+
constructor(message, storeId, data) {
|
|
1452
|
+
super(message, "INVALID_STATE", {
|
|
1453
|
+
storeId,
|
|
1454
|
+
data
|
|
1455
|
+
}, "error");
|
|
1456
|
+
this.name = "InvalidStateError";
|
|
1457
|
+
Object.setPrototypeOf(this, InvalidStateError.prototype);
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
var SerializationError = class SerializationError extends StoreError {
|
|
1461
|
+
constructor(message, cause, storeId) {
|
|
1462
|
+
super(message, "SERIALIZATION_ERROR", { storeId }, "error", cause);
|
|
1463
|
+
this.name = "SerializationError";
|
|
1464
|
+
Object.setPrototypeOf(this, SerializationError.prototype);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
var DeserializationError = class DeserializationError extends StoreError {
|
|
1468
|
+
constructor(message, cause, storeId) {
|
|
1469
|
+
super(message, "DESERIALIZATION_ERROR", { storeId }, "error", cause);
|
|
1470
|
+
this.name = "DeserializationError";
|
|
1471
|
+
Object.setPrototypeOf(this, DeserializationError.prototype);
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
var StorageError = class StorageError extends StoreError {
|
|
1475
|
+
constructor(message, cause, storeId) {
|
|
1476
|
+
super(message, "STORAGE_ERROR", { storeId }, "error", cause);
|
|
1477
|
+
this.name = "StorageError";
|
|
1478
|
+
Object.setPrototypeOf(this, StorageError.prototype);
|
|
1173
1479
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
const keys = path.replace(/\[([^\]]+)\]/g, ".$1").split(".").filter(Boolean);
|
|
1181
|
-
let current = obj;
|
|
1182
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
1183
|
-
const key = keys[i];
|
|
1184
|
-
if (current[key] === void 0 || current[key] === null) return false;
|
|
1185
|
-
current = current[key];
|
|
1480
|
+
};
|
|
1481
|
+
var PluginError = class PluginError extends StoreError {
|
|
1482
|
+
constructor(message, pluginName, cause) {
|
|
1483
|
+
super(message, "PLUGIN_ERROR", { plugin: pluginName }, "error", cause);
|
|
1484
|
+
this.name = "PluginError";
|
|
1485
|
+
Object.setPrototypeOf(this, PluginError.prototype);
|
|
1186
1486
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
return true;
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
delete current[lastKey];
|
|
1197
|
-
return true;
|
|
1487
|
+
};
|
|
1488
|
+
var MiddlewareError = class MiddlewareError extends StoreError {
|
|
1489
|
+
constructor(message, middlewareName, cause) {
|
|
1490
|
+
super(message, "MIDDLEWARE_ERROR", { middleware: middlewareName }, "error", cause);
|
|
1491
|
+
this.name = "MiddlewareError";
|
|
1492
|
+
Object.setPrototypeOf(this, MiddlewareError.prototype);
|
|
1198
1493
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
for (const key of keys) {
|
|
1206
|
-
if (current === null || current === void 0) return false;
|
|
1207
|
-
if (typeof current !== "object") return false;
|
|
1208
|
-
if (!(key in current)) return false;
|
|
1209
|
-
current = current[key];
|
|
1494
|
+
};
|
|
1495
|
+
var SubscriptionError = class SubscriptionError extends StoreError {
|
|
1496
|
+
constructor(message, cause, storeId) {
|
|
1497
|
+
super(message, "SUBSCRIPTION_ERROR", { storeId }, "warning", cause);
|
|
1498
|
+
this.name = "SubscriptionError";
|
|
1499
|
+
Object.setPrototypeOf(this, SubscriptionError.prototype);
|
|
1210
1500
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1501
|
+
};
|
|
1502
|
+
var TimeoutError = class TimeoutError extends StoreError {
|
|
1503
|
+
constructor(message, storeId, action) {
|
|
1504
|
+
super(message, "TIMEOUT_ERROR", {
|
|
1505
|
+
storeId,
|
|
1506
|
+
action
|
|
1507
|
+
}, "error");
|
|
1508
|
+
this.name = "TimeoutError";
|
|
1509
|
+
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
const errorUtils = {
|
|
1513
|
+
/**
|
|
1514
|
+
* 判断是否为 Store 错误
|
|
1515
|
+
*/
|
|
1516
|
+
isStoreError(error) {
|
|
1517
|
+
return error instanceof StoreError;
|
|
1518
|
+
},
|
|
1519
|
+
/**
|
|
1520
|
+
* 判断是否为特定类型的错误
|
|
1521
|
+
*/
|
|
1522
|
+
isErrorCode(error, code) {
|
|
1523
|
+
return error instanceof StoreError && error.code === code;
|
|
1524
|
+
},
|
|
1525
|
+
/**
|
|
1526
|
+
* 包装错误为 Store 错误
|
|
1527
|
+
*/
|
|
1528
|
+
wrap(error, code = "UNKNOWN_ERROR", context = {}) {
|
|
1529
|
+
if (error instanceof StoreError) return error;
|
|
1530
|
+
return new StoreError(error instanceof Error ? error.message : String(error), code, context, "error", error instanceof Error ? error : void 0);
|
|
1531
|
+
},
|
|
1532
|
+
/**
|
|
1533
|
+
* 安全执行函数,捕获并包装错误
|
|
1534
|
+
*/
|
|
1535
|
+
async tryCatch(fn, code = "UNKNOWN_ERROR", context = {}) {
|
|
1536
|
+
try {
|
|
1537
|
+
return await fn();
|
|
1538
|
+
} catch (error) {
|
|
1539
|
+
throw errorUtils.wrap(error, code, context);
|
|
1540
|
+
}
|
|
1541
|
+
},
|
|
1542
|
+
/**
|
|
1543
|
+
* 创建错误日志记录器
|
|
1544
|
+
*/
|
|
1545
|
+
createLogger(prefix) {
|
|
1546
|
+
return {
|
|
1547
|
+
error(error) {
|
|
1548
|
+
console.error(`[${prefix}]`, error.format());
|
|
1549
|
+
if (error.cause) console.error(`[${prefix}] Caused by:`, error.cause);
|
|
1550
|
+
},
|
|
1551
|
+
warn(error) {
|
|
1552
|
+
console.warn(`[${prefix}]`, error.format());
|
|
1553
|
+
},
|
|
1554
|
+
log(error) {
|
|
1555
|
+
if (error.severity === "fatal" || error.severity === "error") this.error(error);
|
|
1556
|
+
else this.warn(error);
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1213
1561
|
//#endregion
|
|
1214
1562
|
//#region src/middleware/logger.ts
|
|
1215
1563
|
const defaultOptions$2 = {
|
|
@@ -1316,80 +1664,13 @@
|
|
|
1316
1664
|
};
|
|
1317
1665
|
}
|
|
1318
1666
|
//#endregion
|
|
1319
|
-
//#region src/middleware/middleware-manager.ts
|
|
1320
|
-
function createMiddlewareManager() {
|
|
1321
|
-
const middlewares = /* @__PURE__ */ new Map();
|
|
1322
|
-
let sortedMiddlewares = null;
|
|
1323
|
-
const getSortedMiddlewares = () => {
|
|
1324
|
-
if (sortedMiddlewares === null) sortedMiddlewares = Array.from(middlewares.values()).sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
|
1325
|
-
return sortedMiddlewares;
|
|
1326
|
-
};
|
|
1327
|
-
const invalidateCache = () => {
|
|
1328
|
-
sortedMiddlewares = null;
|
|
1329
|
-
};
|
|
1330
|
-
const use = (middleware) => {
|
|
1331
|
-
if (middlewares.has(middleware.name)) console.warn(`[Middleware] \u4E2D\u95F4\u4EF6 "${middleware.name}" \u5DF2\u5B58\u5728\uFF0C\u5C06\u88AB\u8986\u76D6`);
|
|
1332
|
-
middlewares.set(middleware.name, middleware);
|
|
1333
|
-
invalidateCache();
|
|
1334
|
-
};
|
|
1335
|
-
const remove = (name) => {
|
|
1336
|
-
if (middlewares.delete(name)) invalidateCache();
|
|
1337
|
-
};
|
|
1338
|
-
const get = (name) => {
|
|
1339
|
-
return middlewares.get(name);
|
|
1340
|
-
};
|
|
1341
|
-
const has = (name) => {
|
|
1342
|
-
return middlewares.has(name);
|
|
1343
|
-
};
|
|
1344
|
-
const execute = async (context) => {
|
|
1345
|
-
const sorted = getSortedMiddlewares();
|
|
1346
|
-
if (sorted.length === 0) return;
|
|
1347
|
-
const dispatch = async (index) => {
|
|
1348
|
-
const middleware = sorted[index];
|
|
1349
|
-
if (!middleware) return;
|
|
1350
|
-
let called = false;
|
|
1351
|
-
const next = async () => {
|
|
1352
|
-
if (called) throw new Error(`[Middleware] next() called multiple times in "${middleware.name}"`);
|
|
1353
|
-
called = true;
|
|
1354
|
-
await dispatch(index + 1);
|
|
1355
|
-
};
|
|
1356
|
-
await middleware.handler(context, next);
|
|
1357
|
-
};
|
|
1358
|
-
await dispatch(0);
|
|
1359
|
-
};
|
|
1360
|
-
const getAll = () => {
|
|
1361
|
-
return getSortedMiddlewares();
|
|
1362
|
-
};
|
|
1363
|
-
const clear = () => {
|
|
1364
|
-
middlewares.clear();
|
|
1365
|
-
invalidateCache();
|
|
1366
|
-
};
|
|
1367
|
-
return {
|
|
1368
|
-
use,
|
|
1369
|
-
remove,
|
|
1370
|
-
get,
|
|
1371
|
-
has,
|
|
1372
|
-
execute,
|
|
1373
|
-
getAll,
|
|
1374
|
-
clear
|
|
1375
|
-
};
|
|
1376
|
-
}
|
|
1377
|
-
let globalMiddlewareManager = null;
|
|
1378
|
-
function getGlobalMiddlewareManager() {
|
|
1379
|
-
if (!globalMiddlewareManager) globalMiddlewareManager = createMiddlewareManager();
|
|
1380
|
-
return globalMiddlewareManager;
|
|
1381
|
-
}
|
|
1382
|
-
function setGlobalMiddlewareManager(manager) {
|
|
1383
|
-
globalMiddlewareManager = manager;
|
|
1384
|
-
}
|
|
1385
|
-
//#endregion
|
|
1386
1667
|
//#region src/middleware/persist.ts
|
|
1387
1668
|
const defaultOptions$1 = {
|
|
1388
1669
|
keyPrefix: "ldesign-store:",
|
|
1389
1670
|
storage: "localStorage",
|
|
1390
1671
|
debounce: 100,
|
|
1391
|
-
serialize: JSON.stringify,
|
|
1392
|
-
deserialize: JSON.parse
|
|
1672
|
+
serialize: (value) => JSON.stringify(value),
|
|
1673
|
+
deserialize: (value) => JSON.parse(value)
|
|
1393
1674
|
};
|
|
1394
1675
|
function resolveOptions(options) {
|
|
1395
1676
|
return {
|
|
@@ -1655,13 +1936,13 @@
|
|
|
1655
1936
|
await next();
|
|
1656
1937
|
return;
|
|
1657
1938
|
}
|
|
1658
|
-
await next();
|
|
1659
1939
|
const result = await validateState(storeId, state);
|
|
1660
1940
|
if (!result.valid) {
|
|
1661
1941
|
lastErrors = result.errors;
|
|
1662
1942
|
onValidationError?.(result);
|
|
1663
1943
|
if (blocking) throw new Error(`[Validation] ${storeId}: ${result.errors.map((e) => e.message).join("; ")}`);
|
|
1664
1944
|
} else lastErrors = lastErrors.filter((e) => e.storeId !== storeId);
|
|
1945
|
+
await next();
|
|
1665
1946
|
}
|
|
1666
1947
|
},
|
|
1667
1948
|
validate: validateState,
|
|
@@ -1693,7 +1974,7 @@
|
|
|
1693
1974
|
function composePlugins(plugins) {
|
|
1694
1975
|
return {
|
|
1695
1976
|
name: "composed-plugins",
|
|
1696
|
-
version: "
|
|
1977
|
+
version: "0.0.1",
|
|
1697
1978
|
async install(context, options) {
|
|
1698
1979
|
for (const plugin of plugins) await plugin.install(context, options);
|
|
1699
1980
|
},
|
|
@@ -1712,73 +1993,8 @@
|
|
|
1712
1993
|
};
|
|
1713
1994
|
}
|
|
1714
1995
|
//#endregion
|
|
1715
|
-
//#region src/plugins/plugin-manager.ts
|
|
1716
|
-
function createPluginManager() {
|
|
1717
|
-
const plugins = /* @__PURE__ */ new Map();
|
|
1718
|
-
const contexts = /* @__PURE__ */ new Map();
|
|
1719
|
-
const use = (plugin, options) => {
|
|
1720
|
-
if (plugins.has(plugin.name)) console.warn(`[Plugin] \u63D2\u4EF6 "${plugin.name}" \u5DF2\u5B58\u5728\uFF0C\u5C06\u88AB\u8986\u76D6`);
|
|
1721
|
-
plugins.set(plugin.name, plugin);
|
|
1722
|
-
const context = {
|
|
1723
|
-
storeManager: {
|
|
1724
|
-
getStore: () => null,
|
|
1725
|
-
hasStore: () => false,
|
|
1726
|
-
getStoreIds: () => []
|
|
1727
|
-
},
|
|
1728
|
-
storeId: "",
|
|
1729
|
-
store: null,
|
|
1730
|
-
options: options || {}
|
|
1731
|
-
};
|
|
1732
|
-
contexts.set(plugin.name, context);
|
|
1733
|
-
};
|
|
1734
|
-
const remove = (name) => {
|
|
1735
|
-
const plugin = plugins.get(name);
|
|
1736
|
-
const context = contexts.get(name);
|
|
1737
|
-
if (plugin && context) plugin.uninstall?.(context);
|
|
1738
|
-
plugins.delete(name);
|
|
1739
|
-
contexts.delete(name);
|
|
1740
|
-
};
|
|
1741
|
-
const get = (name) => {
|
|
1742
|
-
return plugins.get(name);
|
|
1743
|
-
};
|
|
1744
|
-
const has = (name) => {
|
|
1745
|
-
return plugins.has(name);
|
|
1746
|
-
};
|
|
1747
|
-
const getAll = () => {
|
|
1748
|
-
return new Map(plugins);
|
|
1749
|
-
};
|
|
1750
|
-
const size = () => {
|
|
1751
|
-
return plugins.size;
|
|
1752
|
-
};
|
|
1753
|
-
const clear = () => {
|
|
1754
|
-
plugins.forEach((plugin, name) => {
|
|
1755
|
-
const context = contexts.get(name);
|
|
1756
|
-
if (context) plugin.uninstall?.(context);
|
|
1757
|
-
});
|
|
1758
|
-
plugins.clear();
|
|
1759
|
-
contexts.clear();
|
|
1760
|
-
};
|
|
1761
|
-
return {
|
|
1762
|
-
use,
|
|
1763
|
-
remove,
|
|
1764
|
-
get,
|
|
1765
|
-
has,
|
|
1766
|
-
getAll,
|
|
1767
|
-
size,
|
|
1768
|
-
clear
|
|
1769
|
-
};
|
|
1770
|
-
}
|
|
1771
|
-
let globalPluginManager = null;
|
|
1772
|
-
function getGlobalPluginManager() {
|
|
1773
|
-
if (!globalPluginManager) globalPluginManager = createPluginManager();
|
|
1774
|
-
return globalPluginManager;
|
|
1775
|
-
}
|
|
1776
|
-
function setGlobalPluginManager(manager) {
|
|
1777
|
-
globalPluginManager = manager;
|
|
1778
|
-
}
|
|
1779
|
-
//#endregion
|
|
1780
1996
|
//#region src/index.ts
|
|
1781
|
-
const version = "
|
|
1997
|
+
const version = "0.0.1";
|
|
1782
1998
|
const name = "@composy/store-core";
|
|
1783
1999
|
//#endregion
|
|
1784
2000
|
exports.BaseStore = BaseStore;
|