@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
|
@@ -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
|
* ***********************************
|
|
@@ -10,12 +10,20 @@
|
|
|
10
10
|
//#region src/core/batch-manager.ts
|
|
11
11
|
function createBatchManager(onFlush) {
|
|
12
12
|
let batchDepth = 0;
|
|
13
|
+
const flushListeners = /* @__PURE__ */ new Set();
|
|
13
14
|
const pendingStores = /* @__PURE__ */ new Set();
|
|
14
15
|
const flush = () => {
|
|
15
16
|
if (pendingStores.size > 0) {
|
|
16
17
|
const stores = new Set(pendingStores);
|
|
17
18
|
pendingStores.clear();
|
|
18
19
|
onFlush?.(stores);
|
|
20
|
+
flushListeners.forEach((listener) => {
|
|
21
|
+
try {
|
|
22
|
+
listener(stores);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("[Batch] flush listener failed:", error);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
19
27
|
}
|
|
20
28
|
};
|
|
21
29
|
const start = () => {
|
|
@@ -39,12 +47,17 @@ function createBatchManager(onFlush) {
|
|
|
39
47
|
}
|
|
40
48
|
};
|
|
41
49
|
const isBatching = () => batchDepth > 0;
|
|
50
|
+
const onFlushListener = (listener) => {
|
|
51
|
+
flushListeners.add(listener);
|
|
52
|
+
return () => flushListeners.delete(listener);
|
|
53
|
+
};
|
|
42
54
|
return {
|
|
43
55
|
start,
|
|
44
56
|
end,
|
|
45
57
|
markDirty,
|
|
46
58
|
batch: batch2,
|
|
47
|
-
isBatching
|
|
59
|
+
isBatching,
|
|
60
|
+
onFlush: onFlushListener
|
|
48
61
|
};
|
|
49
62
|
}
|
|
50
63
|
let globalBatchManager = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch-manager.js","names":["batch"],"sources":["../../src/core/batch-manager.ts"],"sourcesContent":["/**\n * 批量更新管理器\n *\n * 用于优化多个状态更新的性能\n * @module core/batch-manager\n */\n\nimport type { BatchManager, StoreId } from '../types'\n\n/**\n * 创建批量更新管理器\n *\n * @param onFlush - 刷新回调,接收所有待更新的 Store ID\n * @returns 批量更新管理器实例\n *\n * @example\n * ```typescript\n * const batchManager = createBatchManager((storeIds) => {\n * storeIds.forEach(id => {\n * // 通知订阅者更新\n * notifySubscribers(id)\n * })\n * })\n *\n * // 批量更新\n * batchManager.batch(() => {\n * store1.count++\n * store2.name = 'new name'\n * })\n * ```\n */\nexport function createBatchManager(\n onFlush?: (storeIds: Set<StoreId>) => void
|
|
1
|
+
{"version":3,"file":"batch-manager.js","names":["batch"],"sources":["../../src/core/batch-manager.ts"],"sourcesContent":["/**\r\n * 批量更新管理器\r\n *\r\n * 用于优化多个状态更新的性能\r\n * @module core/batch-manager\r\n */\r\n\r\nimport type { BatchManager, StoreId, Unsubscribe } from '../types'\r\n\r\n/**\r\n * 创建批量更新管理器\r\n *\r\n * @param onFlush - 刷新回调,接收所有待更新的 Store ID\r\n * @returns 批量更新管理器实例\r\n *\r\n * @example\r\n * ```typescript\r\n * const batchManager = createBatchManager((storeIds) => {\r\n * storeIds.forEach(id => {\r\n * // 通知订阅者更新\r\n * notifySubscribers(id)\r\n * })\r\n * })\r\n *\r\n * // 批量更新\r\n * batchManager.batch(() => {\r\n * store1.count++\r\n * store2.name = 'new name'\r\n * })\r\n * ```\r\n */\r\nexport function createBatchManager(\r\n onFlush?: (storeIds: Set<StoreId>) => void\r\n): BatchManager {\r\n /** 批处理嵌套深度,0 表示不在批处理上下文。 */\r\n let batchDepth = 0\r\n\r\n /** 批处理完成监听器,允许 Store Runtime 延迟一次通知 */\r\n const flushListeners = new Set<(storeIds: Set<StoreId>) => void>()\r\n\r\n /** 待更新的 Store ID 集合 */\r\n const pendingStores = new Set<StoreId>()\r\n\r\n /**\r\n * 刷新待更新的 Store\r\n */\r\n const flush = (): void => {\r\n if (pendingStores.size > 0) {\r\n const stores = new Set(pendingStores)\r\n pendingStores.clear()\r\n onFlush?.(stores)\r\n flushListeners.forEach(listener => {\r\n try {\r\n listener(stores)\r\n } catch (error) {\r\n console.error('[Batch] flush listener failed:', error)\r\n }\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * 开始批量更新\r\n */\r\n const start = (): void => {\r\n batchDepth++\r\n }\r\n\r\n /**\r\n * 结束批量更新\r\n */\r\n const end = (): void => {\r\n if (batchDepth === 0) {\r\n return\r\n }\r\n\r\n batchDepth--\r\n if (batchDepth === 0) {\r\n flush()\r\n }\r\n }\r\n\r\n /**\r\n * 标记 Store 需要更新\r\n */\r\n const markDirty = (storeId: StoreId): void => {\r\n pendingStores.add(storeId)\r\n\r\n // 如果不在批量更新中,立即刷新\r\n if (batchDepth === 0) {\r\n flush()\r\n }\r\n }\r\n\r\n /**\r\n * 在批量上下文中执行\r\n */\r\n const batch = <T>(fn: () => T): T => {\r\n start()\r\n try {\r\n return fn()\r\n } finally {\r\n end()\r\n }\r\n }\r\n\r\n /**\r\n * 是否正在批量更新\r\n */\r\n const isBatching = (): boolean => batchDepth > 0\r\n\r\n const onFlushListener = (\r\n listener: (storeIds: Set<StoreId>) => void\r\n ): Unsubscribe => {\r\n flushListeners.add(listener)\r\n return () => flushListeners.delete(listener)\r\n }\r\n\r\n return {\r\n start,\r\n end,\r\n markDirty,\r\n batch,\r\n isBatching,\r\n onFlush: onFlushListener,\r\n }\r\n}\r\n\r\n/**\r\n * 全局批量更新管理器\r\n */\r\nlet globalBatchManager: BatchManager | null = null\r\n\r\n/**\r\n * 获取全局批量更新管理器\r\n */\r\nexport function getGlobalBatchManager(): BatchManager {\r\n if (!globalBatchManager) {\r\n globalBatchManager = createBatchManager()\r\n }\r\n return globalBatchManager\r\n}\r\n\r\n/**\r\n * 设置全局批量更新管理器\r\n */\r\nexport function setGlobalBatchManager(manager: BatchManager): void {\r\n globalBatchManager = manager\r\n}\r\n\r\n/**\r\n * 批量更新辅助函数\r\n *\r\n * @param fn - 执行函数\r\n * @returns 执行结果\r\n */\r\nexport function batch<T>(fn: () => T): T {\r\n return getGlobalBatchManager().batch(fn)\r\n}\r\n"],"mappings":";;;;;;;;;;AA+BO,SAAS,mBACd,SACc;CAEd,IAAI,aAAa;CAGjB,MAAM,iCAAiB,IAAI,IAAsC;CAGjE,MAAM,gCAAgB,IAAI,IAAa;CAKvC,MAAM,cAAoB;EACxB,IAAI,cAAc,OAAO,GAAG;GAC1B,MAAM,SAAS,IAAI,IAAI,aAAa;GACpC,cAAc,MAAM;GACpB,UAAU,MAAM;GAChB,eAAe,SAAQ,aAAY;IACjC,IAAI;KACF,SAAS,MAAM;IACjB,SAAS,OAAO;KACd,QAAQ,MAAM,kCAAkC,KAAK;IACvD;GACF,CAAC;EACH;CACF;CAKA,MAAM,cAAoB;EACxB;CACF;CAKA,MAAM,YAAkB;EACtB,IAAI,eAAe,GACjB;EAGF;EACA,IAAI,eAAe,GACjB,MAAM;CAEV;CAKA,MAAM,aAAa,YAA2B;EAC5C,cAAc,IAAI,OAAO;EAGzB,IAAI,eAAe,GACjB,MAAM;CAEV;CAKA,MAAMA,UAAY,OAAmB;EACnC,MAAM;EACN,IAAI;GACF,OAAO,GAAG;EACZ,UAAE;GACA,IAAI;EACN;CACF;CAKA,MAAM,mBAA4B,aAAa;CAE/C,MAAM,mBACJ,aACgB;EAChB,eAAe,IAAI,QAAQ;EAC3B,aAAa,eAAe,OAAO,QAAQ;CAC7C;CAEA,OAAO;EACL;EACA;EACA;EACA,OAAAA;EACA;EACA,SAAS;CACX;AACF;AAKA,IAAI,qBAA0C;AAKvC,SAAS,wBAAsC;CACpD,IAAI,CAAC,oBACH,qBAAqB,mBAAmB;CAE1C,OAAO;AACT;AAKO,SAAS,sBAAsB,SAA6B;CACjE,qBAAqB;AACvB;AAQO,SAAS,MAAS,IAAgB;CACvC,OAAO,sBAAsB,CAAA,CAAE,MAAM,EAAE;AACzC"}
|
package/esm/core/create-store.js
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
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
|
* ***********************************
|
|
9
9
|
*/
|
|
10
10
|
import { BaseStore } from "./base-store.js";
|
|
11
11
|
//#region src/core/create-store.ts
|
|
12
|
-
function createStore(definition) {
|
|
12
|
+
function createStore(definition, options = {}) {
|
|
13
13
|
let instance = null;
|
|
14
14
|
return () => {
|
|
15
15
|
if (instance) return instance;
|
|
16
|
-
const store = new BaseStore(definition);
|
|
16
|
+
const store = new BaseStore(definition, options);
|
|
17
17
|
const originalDispose = store.$dispose.bind(store);
|
|
18
18
|
store.$dispose = () => {
|
|
19
19
|
originalDispose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-store.js","names":[],"sources":["../../src/core/create-store.ts"],"sourcesContent":["/**\n * @module store/core/create-store\n *\n * Store 工厂函数,用于创建单例 Store 的惰性初始化函数。\n * 基于 BaseStore 实现,返回的工厂函数在首次调用时创建 Store 实例,\n * 后续调用返回同一实例,直到调用 $dispose() 后重置。\n */\n\nimport type {\n ActionSubscriber,\n StateMutation,\n StateSubscriber,\n StateTree,\n StoreId,\n Unsubscribe,\n} from '../types'\nimport { BaseStore } from './base-store'\n\n/**\n * Store 定义描述接口\n *\n * @typeParam Id - Store 唯一标识符类型\n * @typeParam S - 状态树类型\n * @typeParam G - 计算属性定义类型\n * @typeParam A - Action 定义类型\n */\nexport interface CreateStoreDefinition<\n Id extends StoreId,\n S extends StateTree,\n G extends Record<string, (state: S) => unknown>,\n A extends Record
|
|
1
|
+
{"version":3,"file":"create-store.js","names":[],"sources":["../../src/core/create-store.ts"],"sourcesContent":["/**\r\n * @module store/core/create-store\r\n *\r\n * Store 工厂函数,用于创建单例 Store 的惰性初始化函数。\r\n * 基于 BaseStore 实现,返回的工厂函数在首次调用时创建 Store 实例,\r\n * 后续调用返回同一实例,直到调用 $dispose() 后重置。\r\n */\r\n\r\nimport type {\r\n ActionSubscriber,\r\n StateMutation,\r\n StateSubscriber,\r\n StateTree,\r\n StoreId,\r\n StoreOptions,\r\n Unsubscribe,\r\n} from '../types'\r\nimport { BaseStore } from './base-store'\r\n\r\n/**\r\n * Store 定义描述接口\r\n *\r\n * @typeParam Id - Store 唯一标识符类型\r\n * @typeParam S - 状态树类型\r\n * @typeParam G - 计算属性定义类型\r\n * @typeParam A - Action 定义类型\r\n */\r\nexport interface CreateStoreDefinition<\r\n Id extends StoreId,\r\n S extends StateTree,\r\n G extends Record<string, (state: S) => unknown>,\r\n A extends Record<\r\n string,\r\n (this: StoreAPI<Id, S, G, A>, ...args: unknown[]) => unknown\r\n >,\r\n> {\r\n id: Id\r\n state: () => S\r\n getters?: G\r\n actions?: A\r\n}\r\n\r\n/**\r\n * Store 实例的公共 API 接口\r\n *\r\n * 提供状态读取、订阅、补丁、重置、Action 监听和生命周期管理等能力。\r\n *\r\n * @typeParam Id - Store 唯一标识符类型\r\n * @typeParam S - 状态树类型\r\n * @typeParam G - 计算属性定义类型\r\n * @typeParam A - Action 定义类型\r\n */\r\nexport interface StoreAPI<\r\n Id extends StoreId = StoreId,\r\n S extends StateTree = StateTree,\r\n G extends Record<string, (state: S) => unknown> = Record<string, never>,\r\n A extends Record<string, (...args: unknown[]) => unknown> = Record<\r\n string,\r\n never\r\n >,\r\n> {\r\n readonly $id: Id\r\n readonly $state: S\r\n $reset: () => void\r\n $patch: (partial: Partial<S> | ((state: S) => void)) => void\r\n $patchAsync: (partial: Partial<S> | ((state: S) => void)) => Promise<void>\r\n $subscribe: (\r\n callback: StateSubscriber<S>,\r\n options?: { immediate?: boolean }\r\n ) => Unsubscribe\r\n $onAction: (callback: ActionSubscriber<A>) => Unsubscribe\r\n $dispose: () => void\r\n readonly getters: { [K in keyof G]: ReturnType<G[K]> }\r\n readonly actions: { [K in keyof A]: A[K] }\r\n}\r\n\r\n/**\r\n * 创建 Store 的工厂函数\r\n *\r\n * 返回一个惰性初始化的工厂函数。首次调用时基于定义创建 Store 实例,\r\n * 后续调用返回缓存的单例,直到 $dispose() 被调用后重置。\r\n *\r\n * @typeParam Id - Store 唯一标识符类型\r\n * @typeParam S - 状态树类型\r\n * @typeParam G - 计算属性定义类型\r\n * @typeParam A - Action 定义类型\r\n * @param definition - Store 定义,包含 id、state 工厂、getters 和 actions\r\n * @returns 惰性初始化的 Store 工厂函数,调用后返回 StoreAPI 实例\r\n */\r\nexport function createStore<\r\n Id extends StoreId,\r\n S extends StateTree,\r\n G extends Record<string, (state: S) => unknown> = Record<string, never>,\r\n A extends Record<\r\n string,\r\n (this: StoreAPI<Id, S, G, A>, ...args: unknown[]) => unknown\r\n > = Record<string, never>,\r\n>(\r\n definition: CreateStoreDefinition<Id, S, G, A>,\r\n options: StoreOptions = {}\r\n): () => StoreAPI<Id, S, G, A> {\r\n let instance: StoreAPI<Id, S, G, A> | null = null\r\n\r\n return (): StoreAPI<Id, S, G, A> => {\r\n if (instance) {\r\n return instance\r\n }\r\n\r\n const store = new BaseStore<Id, S, G, A>(definition, options)\r\n const originalDispose = store.$dispose.bind(store)\r\n store.$dispose = (): void => {\r\n originalDispose()\r\n instance = null\r\n }\r\n\r\n instance = store as unknown as StoreAPI<Id, S, G, A>\r\n\r\n return store\r\n }\r\n}\r\n\r\n/** 状态变更类型,支持部分更新或通过函数直接修改状态 */\r\nexport type { StateMutation }\r\n"],"mappings":";;;;;;;;;;;AAyFO,SAAS,YASd,YACA,UAAwB,CAAC,GACI;CAC7B,IAAI,WAAyC;CAE7C,aAAoC;EAClC,IAAI,UACF,OAAO;EAGT,MAAM,QAAQ,IAAI,UAAuB,YAAY,OAAO;EAC5D,MAAM,kBAAkB,MAAM,SAAS,KAAK,KAAK;EACjD,MAAM,iBAAuB;GAC3B,gBAAgB;GAChB,WAAW;EACb;EAEA,WAAW;EAEX,OAAO;CACT;AACF"}
|
package/esm/core/event-bus.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-bus.js","names":[],"sources":["../../src/core/event-bus.ts"],"sourcesContent":["/**\n * 事件总线实现\n *\n * 提供事件的发布/订阅功能\n * @module core/event-bus\n */\n\nimport type {
|
|
1
|
+
{"version":3,"file":"event-bus.js","names":[],"sources":["../../src/core/event-bus.ts"],"sourcesContent":["/**\r\n * 事件总线实现\r\n *\r\n * 提供事件的发布/订阅功能\r\n * @module core/event-bus\r\n */\r\n\r\nimport type {\r\n EventBus,\r\n EventData,\r\n EventListener,\r\n EventType,\r\n Unsubscribe,\r\n} from '../types'\r\n\r\n/**\r\n * 创建事件总线\r\n *\r\n * @returns 事件总线实例\r\n *\r\n * @example\r\n * ```typescript\r\n * const bus = createEventBus()\r\n *\r\n * // 监听事件\r\n * const unsubscribe = bus.on('state:changed', (data) => {\r\n * console.log('状态变化:', data)\r\n * })\r\n *\r\n * // 发送事件\r\n * bus.emit('state:changed', { storeId: 'counter', newValue: 1 })\r\n *\r\n * // 取消监听\r\n * unsubscribe()\r\n * ```\r\n */\r\nexport function createEventBus(): EventBus {\r\n /** 事件监听器映射 */\r\n const listeners = new Map<EventType | '*', Set<EventListener>>()\r\n\r\n /**\r\n * 获取或创建监听器集合\r\n */\r\n const getListeners = (type: EventType | '*'): Set<EventListener> => {\r\n let set = listeners.get(type)\r\n if (!set) {\r\n set = new Set()\r\n listeners.set(type, set)\r\n }\r\n return set\r\n }\r\n\r\n /**\r\n * 监听事件\r\n */\r\n const on = (type: EventType | '*', listener: EventListener): Unsubscribe => {\r\n const set = getListeners(type)\r\n set.add(listener)\r\n\r\n return () => {\r\n set.delete(listener)\r\n if (set.size === 0) {\r\n listeners.delete(type)\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 取消监听\r\n */\r\n const off = (type: EventType | '*', listener?: EventListener): void => {\r\n if (listener) {\r\n const set = listeners.get(type)\r\n if (set) {\r\n set.delete(listener)\r\n if (set.size === 0) {\r\n listeners.delete(type)\r\n }\r\n }\r\n } else {\r\n listeners.delete(type)\r\n }\r\n }\r\n\r\n /**\r\n * 监听一次\r\n */\r\n const once = (type: EventType, listener: EventListener): Unsubscribe => {\r\n const wrappedListener: EventListener = data => {\r\n listener(data)\r\n off(type, wrappedListener)\r\n }\r\n return on(type, wrappedListener)\r\n }\r\n\r\n /**\r\n * 发送事件\r\n */\r\n const emit = (type: EventType, payload?: unknown): void => {\r\n const data: EventData = {\r\n type,\r\n payload,\r\n timestamp: Date.now(),\r\n }\r\n\r\n // 触发特定类型的监听器\r\n const typeListeners = listeners.get(type)\r\n if (typeListeners) {\r\n typeListeners.forEach(listener => listener(data))\r\n }\r\n\r\n // 触发通配符监听器\r\n const wildcardListeners = listeners.get('*')\r\n if (wildcardListeners) {\r\n wildcardListeners.forEach(listener => listener(data))\r\n }\r\n }\r\n\r\n /**\r\n * 清空所有监听器\r\n */\r\n const clear = (): void => {\r\n listeners.clear()\r\n }\r\n\r\n return {\r\n on,\r\n once,\r\n off,\r\n emit,\r\n clear,\r\n }\r\n}\r\n\r\n/**\r\n * 全局事件总线实例\r\n */\r\nexport const globalEventBus = createEventBus()\r\n"],"mappings":";;;;;;;;;;AAoCO,SAAS,iBAA2B;CAEzC,MAAM,4BAAY,IAAI,IAAyC;CAK/D,MAAM,gBAAgB,SAA8C;EAClE,IAAI,MAAM,UAAU,IAAI,IAAI;EAC5B,IAAI,CAAC,KAAK;GACR,sBAAM,IAAI,IAAI;GACd,UAAU,IAAI,MAAM,GAAG;EACzB;EACA,OAAO;CACT;CAKA,MAAM,MAAM,MAAuB,aAAyC;EAC1E,MAAM,MAAM,aAAa,IAAI;EAC7B,IAAI,IAAI,QAAQ;EAEhB,aAAa;GACX,IAAI,OAAO,QAAQ;GACnB,IAAI,IAAI,SAAS,GACf,UAAU,OAAO,IAAI;EAEzB;CACF;CAKA,MAAM,OAAO,MAAuB,aAAmC;EACrE,IAAI,UAAU;GACZ,MAAM,MAAM,UAAU,IAAI,IAAI;GAC9B,IAAI,KAAK;IACP,IAAI,OAAO,QAAQ;IACnB,IAAI,IAAI,SAAS,GACf,UAAU,OAAO,IAAI;GAEzB;EACF,OACE,UAAU,OAAO,IAAI;CAEzB;CAKA,MAAM,QAAQ,MAAiB,aAAyC;EACtE,MAAM,mBAAiC,SAAQ;GAC7C,SAAS,IAAI;GACb,IAAI,MAAM,eAAe;EAC3B;EACA,OAAO,GAAG,MAAM,eAAe;CACjC;CAKA,MAAM,QAAQ,MAAiB,YAA4B;EACzD,MAAM,OAAkB;GACtB;GACA;GACA,WAAW,KAAK,IAAI;EACtB;EAGA,MAAM,gBAAgB,UAAU,IAAI,IAAI;EACxC,IAAI,eACF,cAAc,SAAQ,aAAY,SAAS,IAAI,CAAC;EAIlD,MAAM,oBAAoB,UAAU,IAAI,GAAG;EAC3C,IAAI,mBACF,kBAAkB,SAAQ,aAAY,SAAS,IAAI,CAAC;CAExD;CAKA,MAAM,cAAoB;EACxB,UAAU,MAAM;CAClB;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;CACF;AACF;AAKO,MAAM,iBAAiB,eAAe"}
|
package/esm/core/index.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
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
|
* ***********************************
|
|
9
9
|
*/
|
|
10
10
|
import { createPubSub, createPubSubWithValue } from "./pub-sub.js";
|
|
11
11
|
import { createAsyncAction } from "./async-action.js";
|
|
12
|
+
import { batch, createBatchManager, getGlobalBatchManager, setGlobalBatchManager } from "./batch-manager.js";
|
|
12
13
|
import { createEventBus, globalEventBus } from "./event-bus.js";
|
|
13
14
|
import { BaseStore } from "./base-store.js";
|
|
14
|
-
import { batch, createBatchManager, getGlobalBatchManager, setGlobalBatchManager } from "./batch-manager.js";
|
|
15
15
|
import { createStore } from "./create-store.js";
|
|
16
16
|
export { BaseStore, batch, createAsyncAction, createBatchManager, createEventBus, createPubSub, createPubSubWithValue, createStore, getGlobalBatchManager, globalEventBus, setGlobalBatchManager };
|
|
17
17
|
/*! End of @composy/store-core | Powered by @composy/builder */
|
package/esm/core/pub-sub.js
CHANGED
package/esm/core/pub-sub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pub-sub.js","names":[],"sources":["../../src/core/pub-sub.ts"],"sourcesContent":["/**\n * 发布订阅模式实现\n *\n * @module core/pub-sub\n */\n\nimport type {
|
|
1
|
+
{"version":3,"file":"pub-sub.js","names":[],"sources":["../../src/core/pub-sub.ts"],"sourcesContent":["/**\r\n * 发布订阅模式实现\r\n *\r\n * @module core/pub-sub\r\n */\r\n\r\nimport type {\r\n PubSub,\r\n Subscriber,\r\n SubscriptionOptions,\r\n Unsubscribe,\r\n} from '../types'\r\n\r\n/**\r\n * 订阅者信息\r\n */\r\ninterface SubscriberInfo<T> {\r\n /** 回调函数 */\r\n callback: Subscriber<T>\r\n /** 订阅选项 */\r\n options: SubscriptionOptions\r\n}\r\n\r\n/**\r\n * 创建发布订阅管理器\r\n *\r\n * @template T - 数据类型\r\n * @returns 发布订阅管理器实例\r\n *\r\n * @example\r\n * ```typescript\r\n * const pubsub = createPubSub<number>()\r\n *\r\n * // 订阅\r\n * const unsubscribe = pubsub.subscribe((value, oldValue) => {\r\n * console.log(`值从 ${oldValue} 变为 ${value}`)\r\n * })\r\n *\r\n * // 发布\r\n * pubsub.publish(1, 0)\r\n *\r\n * // 取消订阅\r\n * unsubscribe()\r\n * ```\r\n */\r\nexport function createPubSub<T = unknown>(): PubSub<T> {\r\n /** 订阅者列表 */\r\n const subscribers = new Set<SubscriberInfo<T>>()\r\n\r\n /**\r\n * 订阅\r\n */\r\n const subscribe = (\r\n callback: Subscriber<T>,\r\n options: SubscriptionOptions = {}\r\n ): Unsubscribe => {\r\n const info: SubscriberInfo<T> = {\r\n callback,\r\n options,\r\n }\r\n subscribers.add(info)\r\n\r\n return () => {\r\n subscribers.delete(info)\r\n }\r\n }\r\n\r\n /**\r\n * 发布\r\n */\r\n const publish = (value: T, oldValue?: T): void => {\r\n subscribers.forEach(info => {\r\n try {\r\n info.callback(value, oldValue)\r\n } catch (error) {\r\n console.error('[PubSub] 订阅回调执行出错:', error)\r\n }\r\n })\r\n }\r\n\r\n /**\r\n * 清空所有订阅\r\n */\r\n const clear = (): void => {\r\n subscribers.clear()\r\n }\r\n\r\n /**\r\n * 获取订阅者数量\r\n */\r\n const size = (): number => {\r\n return subscribers.size\r\n }\r\n\r\n return {\r\n subscribe,\r\n publish,\r\n clear,\r\n size,\r\n }\r\n}\r\n\r\n/**\r\n * 创建带立即执行的发布订阅管理器\r\n *\r\n * @template T - 数据类型\r\n * @param initialValue - 初始值\r\n * @returns 发布订阅管理器实例\r\n */\r\nexport function createPubSubWithValue<T>(initialValue: T): PubSub<T> & {\r\n getValue: () => T\r\n setValue: (value: T) => void\r\n} {\r\n let currentValue = initialValue\r\n const pubsub = createPubSub<T>()\r\n\r\n const getValue = (): T => currentValue\r\n\r\n const setValue = (value: T): void => {\r\n const oldValue = currentValue\r\n currentValue = value\r\n pubsub.publish(value, oldValue)\r\n }\r\n\r\n const subscribe = (\r\n callback: Subscriber<T>,\r\n options: SubscriptionOptions = {}\r\n ): Unsubscribe => {\r\n const unsubscribe = pubsub.subscribe(callback, options)\r\n\r\n // 立即执行\r\n if (options.immediate) {\r\n callback(currentValue)\r\n }\r\n\r\n return unsubscribe\r\n }\r\n\r\n return {\r\n subscribe,\r\n publish: pubsub.publish,\r\n clear: pubsub.clear,\r\n size: pubsub.size,\r\n getValue,\r\n setValue,\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;AA6CO,SAAS,eAAuC;CAErD,MAAM,8BAAc,IAAI,IAAuB;CAK/C,MAAM,aACJ,UACA,UAA+B,CAAC,MAChB;EAChB,MAAM,OAA0B;GAC9B;GACA;EACF;EACA,YAAY,IAAI,IAAI;EAEpB,aAAa;GACX,YAAY,OAAO,IAAI;EACzB;CACF;CAKA,MAAM,WAAW,OAAU,aAAuB;EAChD,YAAY,SAAQ,SAAQ;GAC1B,IAAI;IACF,KAAK,SAAS,OAAO,QAAQ;GAC/B,SAAS,OAAO;IACd,QAAQ,MAAM,sBAAsB,KAAK;GAC3C;EACF,CAAC;CACH;CAKA,MAAM,cAAoB;EACxB,YAAY,MAAM;CACpB;CAKA,MAAM,aAAqB;EACzB,OAAO,YAAY;CACrB;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;AASO,SAAS,sBAAyB,cAGvC;CACA,IAAI,eAAe;CACnB,MAAM,SAAS,aAAgB;CAE/B,MAAM,iBAAoB;CAE1B,MAAM,YAAY,UAAmB;EACnC,MAAM,WAAW;EACjB,eAAe;EACf,OAAO,QAAQ,OAAO,QAAQ;CAChC;CAEA,MAAM,aACJ,UACA,UAA+B,CAAC,MAChB;EAChB,MAAM,cAAc,OAAO,UAAU,UAAU,OAAO;EAGtD,IAAI,QAAQ,WACV,SAAS,YAAY;EAGvB,OAAO;CACT;CAEA,OAAO;EACL;EACA,SAAS,OAAO;EAChB,OAAO,OAAO;EACd,MAAM,OAAO;EACb;EACA;CACF;AACF"}
|
package/esm/engine/index.js
CHANGED
package/esm/engine/plugin.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
|
* ***********************************
|
|
@@ -81,11 +81,13 @@ function registerContainerServices(context, runtime) {
|
|
|
81
81
|
} catch {}
|
|
82
82
|
}
|
|
83
83
|
function createStoreEngineBridge(options) {
|
|
84
|
-
const { createRuntime, debug = false, name = "store", onRuntimeChange, version = "
|
|
84
|
+
const { createRuntime, debug = false, name = "store", onRuntimeChange, version = "0.0.1" } = options;
|
|
85
85
|
let activeEngine = {};
|
|
86
86
|
let activeContext;
|
|
87
87
|
let runtime = null;
|
|
88
88
|
let runtimeOwner = null;
|
|
89
|
+
let lifecycleToken = 0;
|
|
90
|
+
let pendingAppCreatedToken = null;
|
|
89
91
|
const bindRuntime = (nextRuntime, owner) => {
|
|
90
92
|
const previousRuntime = runtime;
|
|
91
93
|
const previousOwner = runtimeOwner;
|
|
@@ -110,13 +112,18 @@ function createStoreEngineBridge(options) {
|
|
|
110
112
|
return bindRuntime(mountedRuntime, mountedRuntime === nextRuntime ? "engine" : "external");
|
|
111
113
|
};
|
|
112
114
|
const install = async (context) => {
|
|
115
|
+
const installToken = ++lifecycleToken;
|
|
116
|
+
pendingAppCreatedToken = null;
|
|
113
117
|
activeEngine = resolveEngine(context);
|
|
114
118
|
activeContext = resolvePluginContext(context);
|
|
115
119
|
const app = options.resolveApp ? options.resolveApp(activeEngine, activeContext ?? {}, void 0) : resolveDefaultApp(activeEngine, activeContext);
|
|
116
120
|
if (app && (!options.isApp || options.isApp(app))) attachToApp(app);
|
|
117
121
|
else {
|
|
118
122
|
bindRuntime(ensureRuntime(), "engine");
|
|
123
|
+
pendingAppCreatedToken = installToken;
|
|
119
124
|
activeEngine.events?.once?.("app:created", (payload) => {
|
|
125
|
+
if (pendingAppCreatedToken !== installToken || lifecycleToken !== installToken || !runtime) return;
|
|
126
|
+
pendingAppCreatedToken = null;
|
|
120
127
|
const createdApp = options.resolveApp ? options.resolveApp(activeEngine, activeContext ?? {}, payload) : resolveDefaultApp(activeEngine, activeContext, payload);
|
|
121
128
|
if (createdApp && (!options.isApp || options.isApp(createdApp))) attachToApp(createdApp);
|
|
122
129
|
});
|
|
@@ -130,6 +137,8 @@ function createStoreEngineBridge(options) {
|
|
|
130
137
|
if (debug) activeEngine.logger?.info?.("[StoreEngineBridge] installed");
|
|
131
138
|
};
|
|
132
139
|
const uninstall = async (context) => {
|
|
140
|
+
lifecycleToken++;
|
|
141
|
+
pendingAppCreatedToken = null;
|
|
133
142
|
const engine = context ? resolveEngine(context) : activeEngine;
|
|
134
143
|
engine.api?.unregister?.(name);
|
|
135
144
|
clearEngineState(engine, name);
|
package/esm/engine/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../src/engine/plugin.ts"],"sourcesContent":["/**\n * @composy/store-core Engine 桥接能力\n *\n * Core 负责 engine 生命周期、state/API 同步和事件派发;框架适配层只提供 runtime 创建与 App 挂载。\n * @module engine/plugin\n */\n\nimport type {\n StoreEngineBridge,\n StoreEngineBridgeOptions,\n StoreEngineLike,\n StoreEnginePluginContextLike,\n StoreEngineRegisteredApi,\n StoreRuntimeLike,\n} from './types'\nimport { globalEventBus } from '../core/event-bus'\n\nexport const storeStateKeys = {\n BUS: 'store:bus' as const,\n PINIA: 'store:pinia' as const,\n API: 'store:api' as const,\n REGISTRY: 'store:registry' as const,\n RUNTIME: 'store:runtime' as const,\n} as const\n\nexport const storeEventKeys = {\n INSTALLED: 'store:installed' as const,\n UNINSTALLED: 'store:uninstalled' as const,\n} as const\n\ntype RuntimeOwner = 'engine' | 'external'\n\nfunction resolveEngine(context: unknown): StoreEngineLike {\n const value = context as StoreEnginePluginContextLike | StoreEngineLike | null | undefined\n if (value && typeof value === 'object' && 'engine' in value) {\n return value.engine ?? {}\n }\n\n return (value ?? {}) as StoreEngineLike\n}\n\nfunction resolvePluginContext(context: unknown): StoreEnginePluginContextLike | undefined {\n return context && typeof context === 'object'\n ? context as StoreEnginePluginContextLike\n : undefined\n}\n\nfunction resolveDefaultApp(\n engine: StoreEngineLike,\n context: StoreEnginePluginContextLike | undefined,\n payload?: unknown,\n): unknown {\n const payloadObject = payload as { app?: unknown; framework?: { app?: unknown } } | undefined\n return payloadObject?.app\n ?? payloadObject?.framework?.app\n ?? engine.getApp?.()\n ?? context?.framework?.app\n}\n\nfunction createRegisteredApi(\n name: string,\n version: string,\n runtime: StoreRuntimeLike,\n): StoreEngineRegisteredApi {\n return {\n name,\n version,\n pinia: runtime.pinia,\n getStore: runtime.storeAPI.getStore,\n hasStore: runtime.storeAPI.hasStore,\n getStoreIds: runtime.storeAPI.getStoreIds,\n resetAll: runtime.storeAPI.resetAll,\n }\n}\n\nfunction registerEngineApi(\n engine: StoreEngineLike,\n name: string,\n version: string,\n runtime: StoreRuntimeLike,\n): void {\n if (!engine.api?.register) {\n return\n }\n\n const api = createRegisteredApi(name, version, runtime)\n engine.api.unregister?.(name)\n\n if (engine.api.register.length >= 2) {\n ;(engine.api.register as (name: string, api: StoreEngineRegisteredApi) => void)(name, api)\n return\n }\n\n ;(engine.api.register as (api: StoreEngineRegisteredApi) => void)(api)\n}\n\nfunction syncEngineState<Runtime extends StoreRuntimeLike>(\n engine: StoreEngineLike,\n name: string,\n options: StoreEngineBridgeOptions<Runtime>,\n runtime: Runtime,\n): void {\n engine.state?.set?.(storeStateKeys.RUNTIME, runtime)\n engine.state?.set?.(storeStateKeys.PINIA, runtime.pinia)\n engine.state?.set?.(storeStateKeys.API, runtime.storeAPI)\n engine.state?.set?.(storeStateKeys.REGISTRY, runtime.registry)\n engine.state?.set?.(storeStateKeys.BUS, globalEventBus)\n engine.state?.set?.(`plugins.${name}`, runtime.storeAPI)\n engine.state?.set?.(`plugins.${name}.config`, options)\n}\n\nfunction clearEngineState(engine: StoreEngineLike, name: string): void {\n engine.state?.delete?.(storeStateKeys.RUNTIME)\n engine.state?.delete?.(storeStateKeys.PINIA)\n engine.state?.delete?.(storeStateKeys.API)\n engine.state?.delete?.(storeStateKeys.REGISTRY)\n engine.state?.delete?.(storeStateKeys.BUS)\n engine.state?.delete?.(`plugins.${name}`)\n engine.state?.delete?.(`plugins.${name}.config`)\n}\n\nfunction registerContainerServices(\n context: StoreEnginePluginContextLike | undefined,\n runtime: StoreRuntimeLike,\n): void {\n if (!context?.container?.singleton) {\n return\n }\n\n try {\n context.container.singleton('pinia', runtime.pinia)\n context.container.singleton('storeAPI', runtime.storeAPI)\n context.container.singleton('storeRegistry', runtime.registry)\n context.container.singleton('storeRuntime', runtime)\n }\n catch {\n // 同一个 engine 重复安装时可能已存在单例,保持幂等即可。\n }\n}\n\nexport function createStoreEngineBridge<Runtime extends StoreRuntimeLike>(\n options: StoreEngineBridgeOptions<Runtime>,\n): StoreEngineBridge {\n const {\n createRuntime,\n debug = false,\n name = 'store',\n onRuntimeChange,\n version = '1.0.0',\n } = options\n\n let activeEngine: StoreEngineLike = {}\n let activeContext: StoreEnginePluginContextLike | undefined\n let runtime: Runtime | null = null\n let runtimeOwner: RuntimeOwner | null = null\n\n const bindRuntime = (\n nextRuntime: Runtime,\n owner: RuntimeOwner,\n ): Runtime => {\n const previousRuntime = runtime\n const previousOwner = runtimeOwner\n\n runtime = nextRuntime\n runtimeOwner = owner\n onRuntimeChange?.(nextRuntime)\n\n syncEngineState(activeEngine, name, options, nextRuntime)\n registerEngineApi(activeEngine, name, version, nextRuntime)\n registerContainerServices(activeContext, nextRuntime)\n\n if (\n previousRuntime\n && previousRuntime !== nextRuntime\n && previousOwner === 'engine'\n ) {\n previousRuntime.dispose?.()\n }\n\n return nextRuntime\n }\n\n const ensureRuntime = (): Runtime => {\n if (runtime && runtimeOwner === 'engine') {\n return runtime\n }\n\n return createRuntime()\n }\n\n const attachToApp = (app: unknown): Runtime => {\n const installedRuntime = options.getRuntimeFromApp?.(app)\n if (installedRuntime) {\n return bindRuntime(installedRuntime, 'external')\n }\n\n const nextRuntime = ensureRuntime()\n const mountedRuntime = options.attachToApp\n ? options.attachToApp(app, nextRuntime)\n : nextRuntime\n const owner: RuntimeOwner = mountedRuntime === nextRuntime ? 'engine' : 'external'\n return bindRuntime(mountedRuntime, owner)\n }\n\n const install = async (context: unknown): Promise<void> => {\n activeEngine = resolveEngine(context)\n activeContext = resolvePluginContext(context)\n\n const app = options.resolveApp\n ? options.resolveApp(activeEngine, activeContext ?? {}, undefined)\n : resolveDefaultApp(activeEngine, activeContext)\n\n if (app && (!options.isApp || options.isApp(app))) {\n attachToApp(app)\n }\n else {\n bindRuntime(ensureRuntime(), 'engine')\n activeEngine.events?.once?.('app:created', (payload?: unknown) => {\n const createdApp = options.resolveApp\n ? options.resolveApp(activeEngine, activeContext ?? {}, payload)\n : resolveDefaultApp(activeEngine, activeContext, payload)\n if (createdApp && (!options.isApp || options.isApp(createdApp))) {\n attachToApp(createdApp)\n }\n })\n }\n\n await activeEngine.events?.emit?.(storeEventKeys.INSTALLED, {\n name,\n version,\n pinia: runtime?.pinia,\n storeAPI: runtime?.storeAPI,\n })\n\n if (debug) {\n activeEngine.logger?.info?.('[StoreEngineBridge] installed')\n }\n }\n\n const uninstall = async (context?: unknown): Promise<void> => {\n const engine = context ? resolveEngine(context) : activeEngine\n\n engine.api?.unregister?.(name)\n clearEngineState(engine, name)\n await engine.events?.emit?.(storeEventKeys.UNINSTALLED, { name })\n\n if (runtime && runtimeOwner === 'engine') {\n runtime.dispose?.()\n }\n\n runtime = null\n runtimeOwner = null\n onRuntimeChange?.(null)\n\n if (debug) {\n engine.logger?.info?.('[StoreEngineBridge] uninstalled')\n }\n }\n\n return {\n attachToApp,\n getRuntime: () => runtime,\n install,\n uninstall,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../src/engine/plugin.ts"],"sourcesContent":["/**\r\n * @composy/store-core Engine 桥接能力\r\n *\r\n * Core 负责 engine 生命周期、state/API 同步和事件派发;框架适配层只提供 runtime 创建与 App 挂载。\r\n * @module engine/plugin\r\n */\r\n\r\nimport type {\r\n StoreEngineBridge,\r\n StoreEngineBridgeOptions,\r\n StoreEngineLike,\r\n StoreEnginePluginContextLike,\r\n StoreEngineRegisteredApi,\r\n StoreRuntimeLike,\r\n} from './types'\r\nimport { globalEventBus } from '../core/event-bus'\r\n\r\nexport const storeStateKeys = {\r\n BUS: 'store:bus' as const,\r\n PINIA: 'store:pinia' as const,\r\n API: 'store:api' as const,\r\n REGISTRY: 'store:registry' as const,\r\n RUNTIME: 'store:runtime' as const,\r\n} as const\r\n\r\nexport const storeEventKeys = {\r\n INSTALLED: 'store:installed' as const,\r\n UNINSTALLED: 'store:uninstalled' as const,\r\n} as const\r\n\r\ntype RuntimeOwner = 'engine' | 'external'\r\n\r\nfunction resolveEngine(context: unknown): StoreEngineLike {\r\n const value = context as\r\n StoreEnginePluginContextLike | StoreEngineLike | null | undefined\r\n if (value && typeof value === 'object' && 'engine' in value) {\r\n return value.engine ?? {}\r\n }\r\n\r\n return (value ?? {}) as StoreEngineLike\r\n}\r\n\r\nfunction resolvePluginContext(\r\n context: unknown\r\n): StoreEnginePluginContextLike | undefined {\r\n return context && typeof context === 'object'\r\n ? (context as StoreEnginePluginContextLike)\r\n : undefined\r\n}\r\n\r\nfunction resolveDefaultApp(\r\n engine: StoreEngineLike,\r\n context: StoreEnginePluginContextLike | undefined,\r\n payload?: unknown\r\n): unknown {\r\n const payloadObject = payload as\r\n { app?: unknown; framework?: { app?: unknown } } | undefined\r\n return (\r\n payloadObject?.app ??\r\n payloadObject?.framework?.app ??\r\n engine.getApp?.() ??\r\n context?.framework?.app\r\n )\r\n}\r\n\r\nfunction createRegisteredApi(\r\n name: string,\r\n version: string,\r\n runtime: StoreRuntimeLike\r\n): StoreEngineRegisteredApi {\r\n return {\r\n name,\r\n version,\r\n pinia: runtime.pinia,\r\n getStore: runtime.storeAPI.getStore,\r\n hasStore: runtime.storeAPI.hasStore,\r\n getStoreIds: runtime.storeAPI.getStoreIds,\r\n resetAll: runtime.storeAPI.resetAll,\r\n }\r\n}\r\n\r\nfunction registerEngineApi(\r\n engine: StoreEngineLike,\r\n name: string,\r\n version: string,\r\n runtime: StoreRuntimeLike\r\n): void {\r\n if (!engine.api?.register) {\r\n return\r\n }\r\n\r\n const api = createRegisteredApi(name, version, runtime)\r\n engine.api.unregister?.(name)\r\n\r\n if (engine.api.register.length >= 2) {\r\n ;(\r\n engine.api.register as (\r\n name: string,\r\n api: StoreEngineRegisteredApi\r\n ) => void\r\n )(name, api)\r\n return\r\n }\r\n\r\n ;(engine.api.register as (api: StoreEngineRegisteredApi) => void)(api)\r\n}\r\n\r\nfunction syncEngineState<Runtime extends StoreRuntimeLike>(\r\n engine: StoreEngineLike,\r\n name: string,\r\n options: StoreEngineBridgeOptions<Runtime>,\r\n runtime: Runtime\r\n): void {\r\n engine.state?.set?.(storeStateKeys.RUNTIME, runtime)\r\n engine.state?.set?.(storeStateKeys.PINIA, runtime.pinia)\r\n engine.state?.set?.(storeStateKeys.API, runtime.storeAPI)\r\n engine.state?.set?.(storeStateKeys.REGISTRY, runtime.registry)\r\n engine.state?.set?.(storeStateKeys.BUS, globalEventBus)\r\n engine.state?.set?.(`plugins.${name}`, runtime.storeAPI)\r\n engine.state?.set?.(`plugins.${name}.config`, options)\r\n}\r\n\r\nfunction clearEngineState(engine: StoreEngineLike, name: string): void {\r\n engine.state?.delete?.(storeStateKeys.RUNTIME)\r\n engine.state?.delete?.(storeStateKeys.PINIA)\r\n engine.state?.delete?.(storeStateKeys.API)\r\n engine.state?.delete?.(storeStateKeys.REGISTRY)\r\n engine.state?.delete?.(storeStateKeys.BUS)\r\n engine.state?.delete?.(`plugins.${name}`)\r\n engine.state?.delete?.(`plugins.${name}.config`)\r\n}\r\n\r\nfunction registerContainerServices(\r\n context: StoreEnginePluginContextLike | undefined,\r\n runtime: StoreRuntimeLike\r\n): void {\r\n if (!context?.container?.singleton) {\r\n return\r\n }\r\n\r\n try {\r\n context.container.singleton('pinia', runtime.pinia)\r\n context.container.singleton('storeAPI', runtime.storeAPI)\r\n context.container.singleton('storeRegistry', runtime.registry)\r\n context.container.singleton('storeRuntime', runtime)\r\n } catch {\r\n // 同一个 engine 重复安装时可能已存在单例,保持幂等即可。\r\n }\r\n}\r\n\r\nexport function createStoreEngineBridge<Runtime extends StoreRuntimeLike>(\r\n options: StoreEngineBridgeOptions<Runtime>\r\n): StoreEngineBridge {\r\n const {\r\n createRuntime,\r\n debug = false,\r\n name = 'store',\r\n onRuntimeChange,\r\n version = '0.0.1',\r\n } = options\r\n\r\n let activeEngine: StoreEngineLike = {}\r\n let activeContext: StoreEnginePluginContextLike | undefined\r\n let runtime: Runtime | null = null\r\n let runtimeOwner: RuntimeOwner | null = null\r\n let lifecycleToken = 0\r\n let pendingAppCreatedToken: number | null = null\r\n\r\n const bindRuntime = (nextRuntime: Runtime, owner: RuntimeOwner): Runtime => {\r\n const previousRuntime = runtime\r\n const previousOwner = runtimeOwner\r\n\r\n runtime = nextRuntime\r\n runtimeOwner = owner\r\n onRuntimeChange?.(nextRuntime)\r\n\r\n syncEngineState(activeEngine, name, options, nextRuntime)\r\n registerEngineApi(activeEngine, name, version, nextRuntime)\r\n registerContainerServices(activeContext, nextRuntime)\r\n\r\n if (\r\n previousRuntime &&\r\n previousRuntime !== nextRuntime &&\r\n previousOwner === 'engine'\r\n ) {\r\n previousRuntime.dispose?.()\r\n }\r\n\r\n return nextRuntime\r\n }\r\n\r\n const ensureRuntime = (): Runtime => {\r\n if (runtime && runtimeOwner === 'engine') {\r\n return runtime\r\n }\r\n\r\n return createRuntime()\r\n }\r\n\r\n const attachToApp = (app: unknown): Runtime => {\r\n const installedRuntime = options.getRuntimeFromApp?.(app)\r\n if (installedRuntime) {\r\n return bindRuntime(installedRuntime, 'external')\r\n }\r\n\r\n const nextRuntime = ensureRuntime()\r\n const mountedRuntime = options.attachToApp\r\n ? options.attachToApp(app, nextRuntime)\r\n : nextRuntime\r\n const owner: RuntimeOwner =\r\n mountedRuntime === nextRuntime ? 'engine' : 'external'\r\n return bindRuntime(mountedRuntime, owner)\r\n }\r\n\r\n const install = async (context: unknown): Promise<void> => {\r\n const installToken = ++lifecycleToken\r\n pendingAppCreatedToken = null\r\n activeEngine = resolveEngine(context)\r\n activeContext = resolvePluginContext(context)\r\n\r\n const app = options.resolveApp\r\n ? options.resolveApp(activeEngine, activeContext ?? {}, undefined)\r\n : resolveDefaultApp(activeEngine, activeContext)\r\n\r\n if (app && (!options.isApp || options.isApp(app))) {\r\n attachToApp(app)\r\n } else {\r\n bindRuntime(ensureRuntime(), 'engine')\r\n pendingAppCreatedToken = installToken\r\n activeEngine.events?.once?.('app:created', (payload?: unknown) => {\r\n if (\r\n pendingAppCreatedToken !== installToken ||\r\n lifecycleToken !== installToken ||\r\n !runtime\r\n ) {\r\n return\r\n }\r\n\r\n pendingAppCreatedToken = null\r\n const createdApp = options.resolveApp\r\n ? options.resolveApp(activeEngine, activeContext ?? {}, payload)\r\n : resolveDefaultApp(activeEngine, activeContext, payload)\r\n if (createdApp && (!options.isApp || options.isApp(createdApp))) {\r\n attachToApp(createdApp)\r\n }\r\n })\r\n }\r\n\r\n await activeEngine.events?.emit?.(storeEventKeys.INSTALLED, {\r\n name,\r\n version,\r\n pinia: runtime?.pinia,\r\n storeAPI: runtime?.storeAPI,\r\n })\r\n\r\n if (debug) {\r\n activeEngine.logger?.info?.('[StoreEngineBridge] installed')\r\n }\r\n }\r\n\r\n const uninstall = async (context?: unknown): Promise<void> => {\r\n lifecycleToken++\r\n pendingAppCreatedToken = null\r\n const engine = context ? resolveEngine(context) : activeEngine\r\n\r\n engine.api?.unregister?.(name)\r\n clearEngineState(engine, name)\r\n await engine.events?.emit?.(storeEventKeys.UNINSTALLED, { name })\r\n\r\n if (runtime && runtimeOwner === 'engine') {\r\n runtime.dispose?.()\r\n }\r\n\r\n runtime = null\r\n runtimeOwner = null\r\n onRuntimeChange?.(null)\r\n\r\n if (debug) {\r\n engine.logger?.info?.('[StoreEngineBridge] uninstalled')\r\n }\r\n }\r\n\r\n return {\r\n attachToApp,\r\n getRuntime: () => runtime,\r\n install,\r\n uninstall,\r\n }\r\n}\r\n"],"mappings":"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"}
|
package/esm/errors/index.js
CHANGED
|
@@ -2,12 +2,20 @@
|
|
|
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
|
* ***********************************
|
|
9
9
|
*/
|
|
10
10
|
//#region src/errors/index.ts
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value
|
|
17
|
+
}) : obj[key] = value;
|
|
18
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
11
19
|
var StoreErrorCode = /* @__PURE__ */ ((StoreErrorCode2) => {
|
|
12
20
|
StoreErrorCode2["STORE_DISPOSED"] = "STORE_DISPOSED";
|
|
13
21
|
StoreErrorCode2["STORE_NOT_FOUND"] = "STORE_NOT_FOUND";
|
|
@@ -42,6 +50,14 @@ var StoreError = class StoreError extends Error {
|
|
|
42
50
|
*/
|
|
43
51
|
constructor(message, code = "UNKNOWN_ERROR", context = {}, severity = "error", cause) {
|
|
44
52
|
super(message);
|
|
53
|
+
/** 错误代码 */
|
|
54
|
+
__publicField(this, "code");
|
|
55
|
+
/** 错误上下文 */
|
|
56
|
+
__publicField(this, "context");
|
|
57
|
+
/** 错误严重级别 */
|
|
58
|
+
__publicField(this, "severity");
|
|
59
|
+
/** 原始错误 */
|
|
60
|
+
__publicField(this, "cause");
|
|
45
61
|
this.name = "StoreError";
|
|
46
62
|
this.code = code;
|
|
47
63
|
this.context = {
|
package/esm/errors/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["StoreErrorCode","ErrorSeverity"],"sources":["../../src/errors/index.ts"],"sourcesContent":["/**\n * 自定义错误类\n *\n * 提供统一的错误处理模式\n * @module errors\n */\n\n/**\n * Store 错误代码\n */\nexport enum StoreErrorCode {\n /** Store 已销毁 */\n STORE_DISPOSED = 'STORE_DISPOSED',\n /** Store 不存在 */\n STORE_NOT_FOUND = 'STORE_NOT_FOUND',\n /** Store 已存在 */\n STORE_ALREADY_EXISTS = 'STORE_ALREADY_EXISTS',\n /** 无效的状态 */\n INVALID_STATE = 'INVALID_STATE',\n /** 无效的 Action */\n INVALID_ACTION = 'INVALID_ACTION',\n /** 序列化错误 */\n SERIALIZATION_ERROR = 'SERIALIZATION_ERROR',\n /** 反序列化错误 */\n DESERIALIZATION_ERROR = 'DESERIALIZATION_ERROR',\n /** 存储错误 */\n STORAGE_ERROR = 'STORAGE_ERROR',\n /** 插件错误 */\n PLUGIN_ERROR = 'PLUGIN_ERROR',\n /** 中间件错误 */\n MIDDLEWARE_ERROR = 'MIDDLEWARE_ERROR',\n /** 订阅错误 */\n SUBSCRIPTION_ERROR = 'SUBSCRIPTION_ERROR',\n /** 超时错误 */\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\n /** 未知错误 */\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * 错误严重级别\n */\nexport enum ErrorSeverity {\n /** 警告 - 不影响功能,但需要注意 */\n WARNING = 'warning',\n /** 错误 - 影响部分功能 */\n ERROR = 'error',\n /** 致命 - 导致系统无法正常运行 */\n FATAL = 'fatal',\n}\n\n/**\n * Store 错误上下文\n */\nexport interface StoreErrorContext {\n /** Store ID */\n storeId?: string\n /** Action 名称 */\n action?: string\n /** 插件名称 */\n plugin?: string\n /** 中间件名称 */\n middleware?: string\n /** 额外数据 */\n data?: unknown\n /** 时间戳 */\n timestamp?: number\n}\n\n/**\n * Store 基础错误类\n *\n * 所有 Store 相关错误的基类\n *\n * @example\n * ```typescript\n * try {\n * store.someAction()\n * } catch (error) {\n * if (error instanceof StoreError) {\n * console.log('Store error:', error.code, error.message)\n * console.log('Context:', error.context)\n * }\n * }\n * ```\n */\nexport class StoreError extends Error {\n /** 错误代码 */\n readonly code: StoreErrorCode\n\n /** 错误上下文 */\n readonly context: StoreErrorContext\n\n /** 错误严重级别 */\n readonly severity: ErrorSeverity\n\n /** 原始错误 */\n readonly cause?: Error\n\n /**\n * 创建 Store 错误\n *\n * @param message - 错误消息\n * @param code - 错误代码\n * @param context - 错误上下文\n * @param severity - 错误严重级别\n * @param cause - 原始错误\n */\n constructor(\n message: string,\n code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR,\n context: StoreErrorContext = {},\n severity: ErrorSeverity = ErrorSeverity.ERROR,\n cause?: Error,\n ) {\n super(message)\n this.name = 'StoreError'\n this.code = code\n this.context = {\n ...context,\n timestamp: context.timestamp ?? Date.now(),\n }\n this.severity = severity\n this.cause = cause\n\n // 保持正确的原型链\n Object.setPrototypeOf(this, StoreError.prototype)\n\n // 捕获堆栈跟踪\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, StoreError)\n }\n }\n\n /**\n * 转换为 JSON\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n context: this.context,\n severity: this.severity,\n stack: this.stack,\n }\n }\n\n /**\n * 格式化错误信息\n */\n format(): string {\n const parts = [`[${this.code}] ${this.message}`]\n\n if (this.context.storeId) {\n parts.push(`Store: ${this.context.storeId}`)\n }\n\n if (this.context.action) {\n parts.push(`Action: ${this.context.action}`)\n }\n\n return parts.join(' | ')\n }\n}\n\n/**\n * Store 销毁错误\n *\n * 当尝试操作已销毁的 Store 时抛出\n */\nexport class StoreDisposedError extends StoreError {\n constructor(storeId: string, action?: string) {\n super(\n `Store \"${storeId}\" 已被销毁,无法执行操作${action ? `: ${action}` : ''}`,\n StoreErrorCode.STORE_DISPOSED,\n { storeId, action },\n ErrorSeverity.ERROR,\n )\n this.name = 'StoreDisposedError'\n Object.setPrototypeOf(this, StoreDisposedError.prototype)\n }\n}\n\n/**\n * Store 不存在错误\n */\nexport class StoreNotFoundError extends StoreError {\n constructor(storeId: string) {\n super(\n `Store \"${storeId}\" 不存在`,\n StoreErrorCode.STORE_NOT_FOUND,\n { storeId },\n ErrorSeverity.ERROR,\n )\n this.name = 'StoreNotFoundError'\n Object.setPrototypeOf(this, StoreNotFoundError.prototype)\n }\n}\n\n/**\n * Store 已存在错误\n */\nexport class StoreAlreadyExistsError extends StoreError {\n constructor(storeId: string) {\n super(\n `Store \"${storeId}\" 已存在`,\n StoreErrorCode.STORE_ALREADY_EXISTS,\n { storeId },\n ErrorSeverity.WARNING,\n )\n this.name = 'StoreAlreadyExistsError'\n Object.setPrototypeOf(this, StoreAlreadyExistsError.prototype)\n }\n}\n\n/**\n * 无效状态错误\n */\nexport class InvalidStateError extends StoreError {\n constructor(message: string, storeId?: string, data?: unknown) {\n super(\n message,\n StoreErrorCode.INVALID_STATE,\n { storeId, data },\n ErrorSeverity.ERROR,\n )\n this.name = 'InvalidStateError'\n Object.setPrototypeOf(this, InvalidStateError.prototype)\n }\n}\n\n/**\n * 序列化错误\n */\nexport class SerializationError extends StoreError {\n constructor(message: string, cause?: Error, storeId?: string) {\n super(\n message,\n StoreErrorCode.SERIALIZATION_ERROR,\n { storeId },\n ErrorSeverity.ERROR,\n cause,\n )\n this.name = 'SerializationError'\n Object.setPrototypeOf(this, SerializationError.prototype)\n }\n}\n\n/**\n * 反序列化错误\n */\nexport class DeserializationError extends StoreError {\n constructor(message: string, cause?: Error, storeId?: string) {\n super(\n message,\n StoreErrorCode.DESERIALIZATION_ERROR,\n { storeId },\n ErrorSeverity.ERROR,\n cause,\n )\n this.name = 'DeserializationError'\n Object.setPrototypeOf(this, DeserializationError.prototype)\n }\n}\n\n/**\n * 存储错误\n */\nexport class StorageError extends StoreError {\n constructor(message: string, cause?: Error, storeId?: string) {\n super(\n message,\n StoreErrorCode.STORAGE_ERROR,\n { storeId },\n ErrorSeverity.ERROR,\n cause,\n )\n this.name = 'StorageError'\n Object.setPrototypeOf(this, StorageError.prototype)\n }\n}\n\n/**\n * 插件错误\n */\nexport class PluginError extends StoreError {\n constructor(message: string, pluginName: string, cause?: Error) {\n super(\n message,\n StoreErrorCode.PLUGIN_ERROR,\n { plugin: pluginName },\n ErrorSeverity.ERROR,\n cause,\n )\n this.name = 'PluginError'\n Object.setPrototypeOf(this, PluginError.prototype)\n }\n}\n\n/**\n * 中间件错误\n */\nexport class MiddlewareError extends StoreError {\n constructor(message: string, middlewareName: string, cause?: Error) {\n super(\n message,\n StoreErrorCode.MIDDLEWARE_ERROR,\n { middleware: middlewareName },\n ErrorSeverity.ERROR,\n cause,\n )\n this.name = 'MiddlewareError'\n Object.setPrototypeOf(this, MiddlewareError.prototype)\n }\n}\n\n/**\n * 订阅错误\n */\nexport class SubscriptionError extends StoreError {\n constructor(message: string, cause?: Error, storeId?: string) {\n super(\n message,\n StoreErrorCode.SUBSCRIPTION_ERROR,\n { storeId },\n ErrorSeverity.WARNING,\n cause,\n )\n this.name = 'SubscriptionError'\n Object.setPrototypeOf(this, SubscriptionError.prototype)\n }\n}\n\n/**\n * 超时错误\n */\nexport class TimeoutError extends StoreError {\n constructor(message: string, storeId?: string, action?: string) {\n super(\n message,\n StoreErrorCode.TIMEOUT_ERROR,\n { storeId, action },\n ErrorSeverity.ERROR,\n )\n this.name = 'TimeoutError'\n Object.setPrototypeOf(this, TimeoutError.prototype)\n }\n}\n\n/**\n * 错误处理工具\n */\nexport const errorUtils = {\n /**\n * 判断是否为 Store 错误\n */\n isStoreError(error: unknown): error is StoreError {\n return error instanceof StoreError\n },\n\n /**\n * 判断是否为特定类型的错误\n */\n isErrorCode(error: unknown, code: StoreErrorCode): boolean {\n return error instanceof StoreError && error.code === code\n },\n\n /**\n * 包装错误为 Store 错误\n */\n wrap(error: unknown, code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR, context: StoreErrorContext = {}): StoreError {\n if (error instanceof StoreError) {\n return error\n }\n\n const message = error instanceof Error ? error.message : String(error)\n const cause = error instanceof Error ? error : undefined\n\n return new StoreError(message, code, context, ErrorSeverity.ERROR, cause)\n },\n\n /**\n * 安全执行函数,捕获并包装错误\n */\n async tryCatch<T>(\n fn: () => T | Promise<T>,\n code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR,\n context: StoreErrorContext = {},\n ): Promise<T> {\n try {\n return await fn()\n }\n catch (error) {\n throw errorUtils.wrap(error, code, context)\n }\n },\n\n /**\n * 创建错误日志记录器\n */\n createLogger(prefix: string) {\n return {\n error(error: StoreError): void {\n console.error(`[${prefix}]`, error.format())\n if (error.cause) {\n console.error(`[${prefix}] Caused by:`, error.cause)\n }\n },\n\n warn(error: StoreError): void {\n console.warn(`[${prefix}]`, error.format())\n },\n\n log(error: StoreError): void {\n if (error.severity === ErrorSeverity.FATAL || error.severity === ErrorSeverity.ERROR) {\n this.error(error)\n }\n else {\n this.warn(error)\n }\n },\n }\n },\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["StoreErrorCode","ErrorSeverity"],"sources":["../../src/errors/index.ts"],"sourcesContent":["/**\r\n * 自定义错误类\r\n *\r\n * 提供统一的错误处理模式\r\n * @module errors\r\n */\r\n\r\n/**\r\n * Store 错误代码\r\n */\r\nexport enum StoreErrorCode {\r\n /** Store 已销毁 */\r\n STORE_DISPOSED = 'STORE_DISPOSED',\r\n /** Store 不存在 */\r\n STORE_NOT_FOUND = 'STORE_NOT_FOUND',\r\n /** Store 已存在 */\r\n STORE_ALREADY_EXISTS = 'STORE_ALREADY_EXISTS',\r\n /** 无效的状态 */\r\n INVALID_STATE = 'INVALID_STATE',\r\n /** 无效的 Action */\r\n INVALID_ACTION = 'INVALID_ACTION',\r\n /** 序列化错误 */\r\n SERIALIZATION_ERROR = 'SERIALIZATION_ERROR',\r\n /** 反序列化错误 */\r\n DESERIALIZATION_ERROR = 'DESERIALIZATION_ERROR',\r\n /** 存储错误 */\r\n STORAGE_ERROR = 'STORAGE_ERROR',\r\n /** 插件错误 */\r\n PLUGIN_ERROR = 'PLUGIN_ERROR',\r\n /** 中间件错误 */\r\n MIDDLEWARE_ERROR = 'MIDDLEWARE_ERROR',\r\n /** 订阅错误 */\r\n SUBSCRIPTION_ERROR = 'SUBSCRIPTION_ERROR',\r\n /** 超时错误 */\r\n TIMEOUT_ERROR = 'TIMEOUT_ERROR',\r\n /** 未知错误 */\r\n UNKNOWN_ERROR = 'UNKNOWN_ERROR',\r\n}\r\n\r\n/**\r\n * 错误严重级别\r\n */\r\nexport enum ErrorSeverity {\r\n /** 警告 - 不影响功能,但需要注意 */\r\n WARNING = 'warning',\r\n /** 错误 - 影响部分功能 */\r\n ERROR = 'error',\r\n /** 致命 - 导致系统无法正常运行 */\r\n FATAL = 'fatal',\r\n}\r\n\r\n/**\r\n * Store 错误上下文\r\n */\r\nexport interface StoreErrorContext {\r\n /** Store ID */\r\n storeId?: string\r\n /** Action 名称 */\r\n action?: string\r\n /** 插件名称 */\r\n plugin?: string\r\n /** 中间件名称 */\r\n middleware?: string\r\n /** 额外数据 */\r\n data?: unknown\r\n /** 时间戳 */\r\n timestamp?: number\r\n}\r\n\r\n/**\r\n * Store 基础错误类\r\n *\r\n * 所有 Store 相关错误的基类\r\n *\r\n * @example\r\n * ```typescript\r\n * try {\r\n * store.someAction()\r\n * } catch (error) {\r\n * if (error instanceof StoreError) {\r\n * console.log('Store error:', error.code, error.message)\r\n * console.log('Context:', error.context)\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport class StoreError extends Error {\r\n /** 错误代码 */\r\n readonly code: StoreErrorCode\r\n\r\n /** 错误上下文 */\r\n readonly context: StoreErrorContext\r\n\r\n /** 错误严重级别 */\r\n readonly severity: ErrorSeverity\r\n\r\n /** 原始错误 */\r\n readonly cause?: Error\r\n\r\n /**\r\n * 创建 Store 错误\r\n *\r\n * @param message - 错误消息\r\n * @param code - 错误代码\r\n * @param context - 错误上下文\r\n * @param severity - 错误严重级别\r\n * @param cause - 原始错误\r\n */\r\n constructor(\r\n message: string,\r\n code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR,\r\n context: StoreErrorContext = {},\r\n severity: ErrorSeverity = ErrorSeverity.ERROR,\r\n cause?: Error\r\n ) {\r\n super(message)\r\n this.name = 'StoreError'\r\n this.code = code\r\n this.context = {\r\n ...context,\r\n timestamp: context.timestamp ?? Date.now(),\r\n }\r\n this.severity = severity\r\n this.cause = cause\r\n\r\n // 保持正确的原型链\r\n Object.setPrototypeOf(this, StoreError.prototype)\r\n\r\n // 捕获堆栈跟踪\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, StoreError)\r\n }\r\n }\r\n\r\n /**\r\n * 转换为 JSON\r\n */\r\n toJSON(): Record<string, unknown> {\r\n return {\r\n name: this.name,\r\n message: this.message,\r\n code: this.code,\r\n context: this.context,\r\n severity: this.severity,\r\n stack: this.stack,\r\n }\r\n }\r\n\r\n /**\r\n * 格式化错误信息\r\n */\r\n format(): string {\r\n const parts = [`[${this.code}] ${this.message}`]\r\n\r\n if (this.context.storeId) {\r\n parts.push(`Store: ${this.context.storeId}`)\r\n }\r\n\r\n if (this.context.action) {\r\n parts.push(`Action: ${this.context.action}`)\r\n }\r\n\r\n return parts.join(' | ')\r\n }\r\n}\r\n\r\n/**\r\n * Store 销毁错误\r\n *\r\n * 当尝试操作已销毁的 Store 时抛出\r\n */\r\nexport class StoreDisposedError extends StoreError {\r\n constructor(storeId: string, action?: string) {\r\n super(\r\n `Store \"${storeId}\" 已被销毁,无法执行操作${action ? `: ${action}` : ''}`,\r\n StoreErrorCode.STORE_DISPOSED,\r\n { storeId, action },\r\n ErrorSeverity.ERROR\r\n )\r\n this.name = 'StoreDisposedError'\r\n Object.setPrototypeOf(this, StoreDisposedError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * Store 不存在错误\r\n */\r\nexport class StoreNotFoundError extends StoreError {\r\n constructor(storeId: string) {\r\n super(\r\n `Store \"${storeId}\" 不存在`,\r\n StoreErrorCode.STORE_NOT_FOUND,\r\n { storeId },\r\n ErrorSeverity.ERROR\r\n )\r\n this.name = 'StoreNotFoundError'\r\n Object.setPrototypeOf(this, StoreNotFoundError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * Store 已存在错误\r\n */\r\nexport class StoreAlreadyExistsError extends StoreError {\r\n constructor(storeId: string) {\r\n super(\r\n `Store \"${storeId}\" 已存在`,\r\n StoreErrorCode.STORE_ALREADY_EXISTS,\r\n { storeId },\r\n ErrorSeverity.WARNING\r\n )\r\n this.name = 'StoreAlreadyExistsError'\r\n Object.setPrototypeOf(this, StoreAlreadyExistsError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 无效状态错误\r\n */\r\nexport class InvalidStateError extends StoreError {\r\n constructor(message: string, storeId?: string, data?: unknown) {\r\n super(\r\n message,\r\n StoreErrorCode.INVALID_STATE,\r\n { storeId, data },\r\n ErrorSeverity.ERROR\r\n )\r\n this.name = 'InvalidStateError'\r\n Object.setPrototypeOf(this, InvalidStateError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 序列化错误\r\n */\r\nexport class SerializationError extends StoreError {\r\n constructor(message: string, cause?: Error, storeId?: string) {\r\n super(\r\n message,\r\n StoreErrorCode.SERIALIZATION_ERROR,\r\n { storeId },\r\n ErrorSeverity.ERROR,\r\n cause\r\n )\r\n this.name = 'SerializationError'\r\n Object.setPrototypeOf(this, SerializationError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 反序列化错误\r\n */\r\nexport class DeserializationError extends StoreError {\r\n constructor(message: string, cause?: Error, storeId?: string) {\r\n super(\r\n message,\r\n StoreErrorCode.DESERIALIZATION_ERROR,\r\n { storeId },\r\n ErrorSeverity.ERROR,\r\n cause\r\n )\r\n this.name = 'DeserializationError'\r\n Object.setPrototypeOf(this, DeserializationError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 存储错误\r\n */\r\nexport class StorageError extends StoreError {\r\n constructor(message: string, cause?: Error, storeId?: string) {\r\n super(\r\n message,\r\n StoreErrorCode.STORAGE_ERROR,\r\n { storeId },\r\n ErrorSeverity.ERROR,\r\n cause\r\n )\r\n this.name = 'StorageError'\r\n Object.setPrototypeOf(this, StorageError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 插件错误\r\n */\r\nexport class PluginError extends StoreError {\r\n constructor(message: string, pluginName: string, cause?: Error) {\r\n super(\r\n message,\r\n StoreErrorCode.PLUGIN_ERROR,\r\n { plugin: pluginName },\r\n ErrorSeverity.ERROR,\r\n cause\r\n )\r\n this.name = 'PluginError'\r\n Object.setPrototypeOf(this, PluginError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 中间件错误\r\n */\r\nexport class MiddlewareError extends StoreError {\r\n constructor(message: string, middlewareName: string, cause?: Error) {\r\n super(\r\n message,\r\n StoreErrorCode.MIDDLEWARE_ERROR,\r\n { middleware: middlewareName },\r\n ErrorSeverity.ERROR,\r\n cause\r\n )\r\n this.name = 'MiddlewareError'\r\n Object.setPrototypeOf(this, MiddlewareError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 订阅错误\r\n */\r\nexport class SubscriptionError extends StoreError {\r\n constructor(message: string, cause?: Error, storeId?: string) {\r\n super(\r\n message,\r\n StoreErrorCode.SUBSCRIPTION_ERROR,\r\n { storeId },\r\n ErrorSeverity.WARNING,\r\n cause\r\n )\r\n this.name = 'SubscriptionError'\r\n Object.setPrototypeOf(this, SubscriptionError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 超时错误\r\n */\r\nexport class TimeoutError extends StoreError {\r\n constructor(message: string, storeId?: string, action?: string) {\r\n super(\r\n message,\r\n StoreErrorCode.TIMEOUT_ERROR,\r\n { storeId, action },\r\n ErrorSeverity.ERROR\r\n )\r\n this.name = 'TimeoutError'\r\n Object.setPrototypeOf(this, TimeoutError.prototype)\r\n }\r\n}\r\n\r\n/**\r\n * 错误处理工具\r\n */\r\nexport const errorUtils = {\r\n /**\r\n * 判断是否为 Store 错误\r\n */\r\n isStoreError(error: unknown): error is StoreError {\r\n return error instanceof StoreError\r\n },\r\n\r\n /**\r\n * 判断是否为特定类型的错误\r\n */\r\n isErrorCode(error: unknown, code: StoreErrorCode): boolean {\r\n return error instanceof StoreError && error.code === code\r\n },\r\n\r\n /**\r\n * 包装错误为 Store 错误\r\n */\r\n wrap(\r\n error: unknown,\r\n code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR,\r\n context: StoreErrorContext = {}\r\n ): StoreError {\r\n if (error instanceof StoreError) {\r\n return error\r\n }\r\n\r\n const message = error instanceof Error ? error.message : String(error)\r\n const cause = error instanceof Error ? error : undefined\r\n\r\n return new StoreError(message, code, context, ErrorSeverity.ERROR, cause)\r\n },\r\n\r\n /**\r\n * 安全执行函数,捕获并包装错误\r\n */\r\n async tryCatch<T>(\r\n fn: () => T | Promise<T>,\r\n code: StoreErrorCode = StoreErrorCode.UNKNOWN_ERROR,\r\n context: StoreErrorContext = {}\r\n ): Promise<T> {\r\n try {\r\n return await fn()\r\n } catch (error) {\r\n throw errorUtils.wrap(error, code, context)\r\n }\r\n },\r\n\r\n /**\r\n * 创建错误日志记录器\r\n */\r\n createLogger(prefix: string) {\r\n return {\r\n error(error: StoreError): void {\r\n console.error(`[${prefix}]`, error.format())\r\n if (error.cause) {\r\n console.error(`[${prefix}] Caused by:`, error.cause)\r\n }\r\n },\r\n\r\n warn(error: StoreError): void {\r\n console.warn(`[${prefix}]`, error.format())\r\n },\r\n\r\n log(error: StoreError): void {\r\n if (\r\n error.severity === ErrorSeverity.FATAL ||\r\n error.severity === ErrorSeverity.ERROR\r\n ) {\r\n this.error(error)\r\n } else {\r\n this.warn(error)\r\n }\r\n },\r\n }\r\n },\r\n}\r\n"],"mappings":"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"}
|
package/esm/index.js
CHANGED
|
@@ -2,33 +2,33 @@
|
|
|
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
|
* ***********************************
|
|
9
9
|
*/
|
|
10
10
|
import { createPubSub, createPubSubWithValue } from "./core/pub-sub.js";
|
|
11
11
|
import { createAsyncAction } from "./core/async-action.js";
|
|
12
|
+
import { createMiddlewareManager, getGlobalMiddlewareManager, setGlobalMiddlewareManager } from "./middleware/middleware-manager.js";
|
|
13
|
+
import { createPluginManager, getGlobalPluginManager, setGlobalPluginManager } from "./plugins/plugin-manager.js";
|
|
14
|
+
import { debounce, throttle } from "./utils/debounce-throttle.js";
|
|
15
|
+
import { deepClone, deepEqual, deepFreeze, deepMerge, deepMergeWithOptions, isObject, isPlainObject, shallowClone } from "./utils/deep-clone.js";
|
|
16
|
+
import { combineSelectors, createCachedSelector, createMemoizedSelector, createSelector, createSelectorWithDeps, deleteByPath, getByPath, hasPath, setByPath } from "./utils/selector.js";
|
|
17
|
+
import { batch, createBatchManager, getGlobalBatchManager, setGlobalBatchManager } from "./core/batch-manager.js";
|
|
12
18
|
import { createEventBus, globalEventBus } from "./core/event-bus.js";
|
|
13
19
|
import { BaseStore } from "./core/base-store.js";
|
|
14
|
-
import { batch, createBatchManager, getGlobalBatchManager, setGlobalBatchManager } from "./core/batch-manager.js";
|
|
15
20
|
import { createStore } from "./core/create-store.js";
|
|
16
21
|
import "./core/index.js";
|
|
17
22
|
import { createStoreEngineBridge, storeEventKeys, storeStateKeys } from "./engine/plugin.js";
|
|
18
23
|
import "./engine/index.js";
|
|
19
24
|
import { DeserializationError, ErrorSeverity, InvalidStateError, MiddlewareError, PluginError, SerializationError, StorageError, StoreAlreadyExistsError, StoreDisposedError, StoreError, StoreErrorCode, StoreNotFoundError, SubscriptionError, TimeoutError, errorUtils } from "./errors/index.js";
|
|
20
|
-
import { debounce, throttle } from "./utils/debounce-throttle.js";
|
|
21
|
-
import { deepClone, deepEqual, deepFreeze, deepMerge, deepMergeWithOptions, isObject, isPlainObject, shallowClone } from "./utils/deep-clone.js";
|
|
22
|
-
import { combineSelectors, createCachedSelector, createMemoizedSelector, createSelector, createSelectorWithDeps, deleteByPath, getByPath, hasPath, setByPath } from "./utils/selector.js";
|
|
23
25
|
import { createLoggerMiddleware, createSimpleLoggerMiddleware } from "./middleware/logger.js";
|
|
24
|
-
import { createMiddlewareManager, getGlobalMiddlewareManager, setGlobalMiddlewareManager } from "./middleware/middleware-manager.js";
|
|
25
26
|
import { createPersistMiddleware, restoreState } from "./middleware/persist.js";
|
|
26
27
|
import { createTimeTravelMiddleware, setRestoreCallback } from "./middleware/time-travel.js";
|
|
27
28
|
import { createValidationMiddleware } from "./middleware/validation.js";
|
|
28
29
|
import { composePlugins, createPluginFactory, defineStorePlugin } from "./plugins/define-plugin.js";
|
|
29
|
-
import { createPluginManager, getGlobalPluginManager, setGlobalPluginManager } from "./plugins/plugin-manager.js";
|
|
30
30
|
//#region src/index.ts
|
|
31
|
-
const version = "
|
|
31
|
+
const version = "0.0.1";
|
|
32
32
|
const name = "@composy/store-core";
|
|
33
33
|
//#endregion
|
|
34
34
|
export { BaseStore, DeserializationError, ErrorSeverity, InvalidStateError, MiddlewareError, PluginError, SerializationError, StorageError, StoreAlreadyExistsError, StoreDisposedError, StoreError, StoreErrorCode, StoreNotFoundError, SubscriptionError, TimeoutError, batch, combineSelectors, composePlugins, createAsyncAction, createBatchManager, createCachedSelector, createEventBus, createLoggerMiddleware, createMemoizedSelector, createMiddlewareManager, createPersistMiddleware, createPluginFactory, createPluginManager, createPubSub, createPubSubWithValue, createSelector, createSelectorWithDeps, createSimpleLoggerMiddleware, createStore, createStoreEngineBridge, createTimeTravelMiddleware, createValidationMiddleware, debounce, deepClone, deepEqual, deepFreeze, deepMerge, deepMergeWithOptions, defineStorePlugin, deleteByPath, errorUtils, getByPath, getGlobalBatchManager, getGlobalMiddlewareManager, getGlobalPluginManager, globalEventBus, hasPath, isObject, isPlainObject, name, restoreState, setByPath, setGlobalBatchManager, setGlobalMiddlewareManager, setGlobalPluginManager, setRestoreCallback, shallowClone, storeEventKeys, storeStateKeys, throttle, version };
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @composy/store-core - 框架无关的状态管理核心库\n *\n * 主要功能模块:\n * - 核心抽象:Store、State、Action、Getter 等核心概念\n * - 插件系统:可扩展的插件机制\n * - 中间件:日志、持久化、时间旅行等\n * - 订阅发布:状态变化订阅、事件总线\n * - 批量更新:性能优化的批量状态更新\n * - 工具函数:深拷贝、选择器等\n *\n * @module @composy/store-core\n */\n\n// === 核心模块 ===\nexport {\n BaseStore,\n batch,\n createAsyncAction,\n createBatchManager,\n createEventBus,\n createPubSub,\n createPubSubWithValue,\n createStore,\n getGlobalBatchManager,\n globalEventBus,\n setGlobalBatchManager,\n} from './core'\n\nexport type {\n AsyncAction,\n AsyncActionOptions,\n AsyncActionState,\n CreateStoreDefinition,\n StoreAPI,\n} from './core'\n\n// Engine 插件\nexport * from './engine'\n\n// === 错误处理 ===\nexport {\n DeserializationError,\n ErrorSeverity,\n errorUtils,\n InvalidStateError,\n MiddlewareError,\n PluginError,\n SerializationError,\n StorageError,\n StoreAlreadyExistsError,\n StoreDisposedError,\n StoreError,\n StoreErrorCode,\n StoreNotFoundError,\n SubscriptionError,\n TimeoutError,\n} from './errors'\n\nexport type {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * @composy/store-core - 框架无关的状态管理核心库\r\n *\r\n * 主要功能模块:\r\n * - 核心抽象:Store、State、Action、Getter 等核心概念\r\n * - 插件系统:可扩展的插件机制\r\n * - 中间件:日志、持久化、时间旅行等\r\n * - 订阅发布:状态变化订阅、事件总线\r\n * - 批量更新:性能优化的批量状态更新\r\n * - 工具函数:深拷贝、选择器等\r\n *\r\n * @module @composy/store-core\r\n */\r\n\r\n// === 核心模块 ===\r\nexport {\r\n BaseStore,\r\n batch,\r\n createAsyncAction,\r\n createBatchManager,\r\n createEventBus,\r\n createPubSub,\r\n createPubSubWithValue,\r\n createStore,\r\n getGlobalBatchManager,\r\n globalEventBus,\r\n setGlobalBatchManager,\r\n} from './core'\r\n\r\nexport type {\r\n AsyncAction,\r\n AsyncActionOptions,\r\n AsyncActionState,\r\n CreateStoreDefinition,\r\n StoreAPI,\r\n} from './core'\r\n\r\n// Engine 插件\r\nexport * from './engine'\r\n\r\n// === 错误处理 ===\r\nexport {\r\n DeserializationError,\r\n ErrorSeverity,\r\n errorUtils,\r\n InvalidStateError,\r\n MiddlewareError,\r\n PluginError,\r\n SerializationError,\r\n StorageError,\r\n StoreAlreadyExistsError,\r\n StoreDisposedError,\r\n StoreError,\r\n StoreErrorCode,\r\n StoreNotFoundError,\r\n SubscriptionError,\r\n TimeoutError,\r\n} from './errors'\r\n\r\nexport type { StoreErrorContext } from './errors'\r\n\r\n// === 中间件模块 ===\r\nexport {\r\n createLoggerMiddleware,\r\n createMiddlewareManager,\r\n createPersistMiddleware,\r\n createSimpleLoggerMiddleware,\r\n createTimeTravelMiddleware,\r\n createValidationMiddleware,\r\n getGlobalMiddlewareManager,\r\n restoreState,\r\n setGlobalMiddlewareManager,\r\n setRestoreCallback,\r\n} from './middleware'\r\n\r\nexport type {\r\n StoreValidationRules,\r\n ValidationError,\r\n ValidationMiddlewareOptions,\r\n ValidationResult,\r\n ValidationRule,\r\n} from './middleware'\r\n\r\n// === 插件模块 ===\r\nexport {\r\n composePlugins,\r\n createPluginFactory,\r\n createPluginManager,\r\n defineStorePlugin,\r\n getGlobalPluginManager,\r\n setGlobalPluginManager,\r\n} from './plugins'\r\n\r\n// === 类型定义 ===\r\nexport type {\r\n // Store 类型\r\n ActionContext,\r\n ActionSubscriber,\r\n // 订阅类型\r\n BatchContext,\r\n BatchManager,\r\n // 插件类型\r\n DefinePluginOptions,\r\n EventBus,\r\n EventData,\r\n EventListener,\r\n EventType,\r\n // 中间件类型\r\n LoggerMiddlewareOptions,\r\n Middleware,\r\n MiddlewareActionType,\r\n MiddlewareContext,\r\n MiddlewareFunction,\r\n MiddlewareManager,\r\n PersistMiddlewareOptions,\r\n PersistOptions,\r\n PluginContext,\r\n PluginFactory,\r\n PluginManager,\r\n PubSub,\r\n Selector,\r\n SelectorOptions,\r\n StateMutation,\r\n StateSnapshot,\r\n StateSubscriber,\r\n StateTree,\r\n StorageAdapter,\r\n Store,\r\n StoreAction,\r\n StoreActions,\r\n StoreDefinition,\r\n StoreGetter,\r\n StoreGetters,\r\n StoreId,\r\n StoreInstance,\r\n StoreManagerLike,\r\n StoreMiddleware,\r\n StoreMutation,\r\n StoreOptions,\r\n StorePlugin,\r\n StoreState,\r\n StoreSubscription,\r\n SubscribeOptions,\r\n Subscriber,\r\n SubscriptionOptions,\r\n TimeTravelController,\r\n TimeTravelMiddlewareOptions,\r\n Unsubscribe,\r\n} from './types'\r\n\r\n// === 工具函数 ===\r\nexport {\r\n combineSelectors,\r\n createCachedSelector,\r\n createMemoizedSelector,\r\n createSelector,\r\n createSelectorWithDeps,\r\n debounce,\r\n deepClone,\r\n deepEqual,\r\n deepFreeze,\r\n deepMerge,\r\n deepMergeWithOptions,\r\n deleteByPath,\r\n getByPath,\r\n hasPath,\r\n isObject,\r\n isPlainObject,\r\n setByPath,\r\n shallowClone,\r\n throttle,\r\n} from './utils'\r\n\r\n// === 版本信息 ===\r\nexport const version = '0.0.1'\r\nexport const name = '@composy/store-core'\r\n\r\nexport type {\r\n DebouncedFunction,\r\n DeepCloneOptions,\r\n DeepMergeOptions,\r\n MemoizedSelectorOptions,\r\n SelectorEqualityFn,\r\n ThrottledFunction,\r\n} from './utils'\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8KO,MAAM,UAAU;AAChB,MAAM,OAAO"}
|
package/esm/middleware/logger.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
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
|
* ***********************************
|
|
9
9
|
*/
|
|
10
|
-
import { MiddlewareError } from "../errors/index.js";
|
|
11
10
|
import { deepClone } from "../utils/deep-clone.js";
|
|
11
|
+
import { MiddlewareError } from "../errors/index.js";
|
|
12
12
|
//#region src/middleware/logger.ts
|
|
13
13
|
const defaultOptions = {
|
|
14
14
|
logState: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","names":[],"sources":["../../src/middleware/logger.ts"],"sourcesContent":["/**\n * 日志中间件\n *\n * 提供状态变化和 Action 调用的日志记录,支持多种日志级别和格式化选项\n * @module middleware/logger\n */\n\nimport type { LoggerMiddlewareOptions, Middleware, MiddlewareContext, StateTree } from '../types'\nimport { MiddlewareError } from '../errors'\nimport { deepClone } from '../utils'\n\n/**\n * 默认日志选项\n */\nconst defaultOptions: Required<Omit<LoggerMiddlewareOptions, 'logger' | 'filter'>> = {\n logState: true,\n logAction: true,\n collapsed: true,\n timestamp: true,\n level: 'log',\n}\n\n/**\n * 日志颜色配置\n */\nconst LOG_COLORS = {\n prevState: 'color: #9E9E9E; font-weight: bold',\n action: 'color: #03A9F4; font-weight: bold',\n nextState: 'color: #4CAF50; font-weight: bold',\n error: 'color: #F44336; font-weight: bold',\n duration: 'color: #9C27B0; font-weight: normal',\n title: 'color: inherit; font-weight: bold',\n} as const\n\n/**\n * 格式化时间戳\n *\n * @param date - 日期对象\n * @returns 格式化的时间字符串\n */\nfunction formatTime(date: Date): string {\n const hours = date.getHours().toString().padStart(2, '0')\n const minutes = date.getMinutes().toString().padStart(2, '0')\n const seconds = date.getSeconds().toString().padStart(2, '0')\n const ms = date.getMilliseconds().toString().padStart(3, '0')\n return `${hours}:${minutes}:${seconds}.${ms}`\n}\n\n/**\n * 格式化时间差\n *\n * @param startTime - 开始时间\n * @param endTime - 结束时间\n * @returns 格式化的时间差字符串\n */\nfunction formatDuration(startTime: number, endTime: number): string {\n const duration = endTime - startTime\n if (duration < 1) {\n return '< 1ms'\n }\n return `${duration.toFixed(2)}ms`\n}\n\n/**\n * 安全克隆状态(防止日志中的对象被修改)\n *\n * @param state - 状态对象\n * @returns 克隆后的状态\n */\nfunction safeCloneState<S extends StateTree>(state: S): S {\n try {\n return deepClone(state)\n }\n catch {\n // 如果克隆失败,返回浅拷贝\n return { ...state }\n }\n}\n\n/**\n * 创建日志中间件\n *\n * 提供完整的状态变化和 Action 调用日志记录,支持时间戳、分组和性能计时\n *\n * @param options - 日志选项\n * @returns 日志中间件\n *\n * @example\n * ```typescript\n * const logger = createLoggerMiddleware({\n * logState: true,\n * collapsed: true,\n * timestamp: true,\n * filter: (context) => context.storeId !== 'internal'\n * })\n *\n * middlewareManager.use(logger)\n * ```\n */\nexport function createLoggerMiddleware(\n options: LoggerMiddlewareOptions = {},\n): Middleware {\n const opts = { ...defaultOptions, ...options }\n const logger = opts.logger ?? console\n\n return {\n name: 'logger',\n priority: 0, // 最先执行,确保能记录所有操作\n\n handler: async (context: MiddlewareContext, next: () => void | Promise<void>) => {\n const { storeId, type, state, payload } = context\n\n // 应用自定义过滤器\n if (opts.filter && !opts.filter(context)) {\n await next()\n return\n }\n\n // 判断是否需要记录\n const isStateChange = type.startsWith('state:')\n const isAction = type.startsWith('action:')\n\n if ((isStateChange && !opts.logState) || (isAction && !opts.logAction)) {\n await next()\n return\n }\n\n const timestamp = opts.timestamp ? formatTime(new Date()) : ''\n const prefix = `[Store: ${storeId}]`\n const startTime = performance.now()\n\n // 保存操作前的状态\n const prevState = safeCloneState(state)\n\n // 开始分组\n const groupTitle = timestamp ? `${timestamp} ${prefix} ${type}` : `${prefix} ${type}`\n\n const startGroup = (): void => {\n if (opts.collapsed && typeof logger.groupCollapsed === 'function') {\n logger.groupCollapsed(`%c${groupTitle}`, LOG_COLORS.title)\n }\n else if (typeof logger.group === 'function') {\n logger.group(`%c${groupTitle}`, LOG_COLORS.title)\n }\n }\n\n const endGroup = (): void => {\n if (typeof logger.groupEnd === 'function') {\n logger.groupEnd()\n }\n }\n\n startGroup()\n\n try {\n // 记录操作前的状态\n const logFn = logger[opts.level ?? 'log'] ?? logger.log\n\n if (typeof logFn === 'function') {\n logFn.call(logger, '%c prev state', LOG_COLORS.prevState, prevState)\n\n if (payload !== undefined) {\n logFn.call(logger, '%c payload', LOG_COLORS.action, payload)\n }\n }\n\n // 执行下一个中间件\n await next()\n\n const endTime = performance.now()\n\n // 记录操作后的状态\n if (typeof logFn === 'function') {\n logFn.call(logger, '%c next state', LOG_COLORS.nextState, safeCloneState(context.state))\n logFn.call(logger, '%c duration', LOG_COLORS.duration, formatDuration(startTime, endTime))\n }\n }\n catch (error) {\n // 记录错误\n if (typeof logger.error === 'function') {\n logger.error('%c error', LOG_COLORS.error, error)\n }\n\n // 包装并重新抛出错误\n throw new MiddlewareError(\n `日志中间件执行错误: ${error instanceof Error ? error.message : String(error)}`,\n 'logger',\n error instanceof Error ? error : undefined,\n )\n }\n finally {\n endGroup()\n }\n },\n }\n}\n\n/**\n * 简单日志中间件(不使用分组,适合生产环境)\n *\n * @param options - 配置选项\n * @param options.includePayload - 是否输出 payload\n * @param options.format - 自定义日志格式化函数\n * @param options.filter - 日志过滤器\n * @returns 简单日志中间件\n *\n * @example\n * ```typescript\n * const logger = createSimpleLoggerMiddleware({\n * includePayload: true,\n * format: (ctx) => `${ctx.storeId}: ${ctx.type}`\n * })\n * ```\n */\nexport function createSimpleLoggerMiddleware(options: {\n /** 是否包含 payload */\n includePayload?: boolean\n /** 自定义格式化函数 */\n format?: (context: MiddlewareContext) => string\n /** 过滤器 */\n filter?: (context: MiddlewareContext) => boolean\n} = {}): Middleware {\n const { includePayload = true, format, filter } = options\n\n return {\n name: 'simple-logger',\n priority: 0,\n\n handler: async (context: MiddlewareContext, next: () => void | Promise<void>) => {\n const { storeId, type, payload } = context\n\n // 应用过滤器\n if (filter && !filter(context)) {\n await next()\n return\n }\n\n // 使用自定义格式化或默认格式\n const message = format\n ? format(context)\n : `[Store: ${storeId}] ${type}`\n\n if (includePayload && payload !== undefined) {\n console.info(message, payload)\n }\n else {\n console.info(message)\n }\n\n await next()\n },\n }\n}\n\n/**\n * 创建生产环境日志中间件\n *\n * 只记录错误和警告,不记录正常状态变化\n *\n * @param options - 配置选项\n * @param options.onError - 自定义错误处理器\n * @returns 生产环境日志中间件\n */\nexport function createProductionLoggerMiddleware(options: {\n /** 自定义错误处理器 */\n onError?: (error: Error, context: MiddlewareContext) => void\n} = {}): Middleware {\n const { onError } = options\n\n return {\n name: 'production-logger',\n priority: 0,\n\n handler: async (context: MiddlewareContext, next: () => void | Promise<void>) => {\n try {\n await next()\n }\n catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n\n if (onError) {\n onError(err, context)\n }\n else {\n console.error(`[Store Error] ${context.storeId}:`, err)\n }\n\n throw error\n }\n },\n }\n}\n\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,iBAA+E;CACnF,UAAU;CACV,WAAW;CACX,WAAW;CACX,WAAW;CACX,OAAO;AACT;AAKA,MAAM,aAAa;CACjB,WAAW;CACX,QAAQ;CACR,WAAW;CACX,OAAO;CACP,UAAU;CACV,OAAO;AACT;AAQA,SAAS,WAAW,MAAoB;CAKtC,OAAO,GAJO,KAAK,SAAS,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAI3C,EAAK,GAHC,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAGtC,EAAO,GAFV,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAE3B,EAAO,GAD1B,KAAK,gBAAgB,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAChB;AAC3C;AASA,SAAS,eAAe,WAAmB,SAAyB;CAClE,MAAM,WAAW,UAAU;CAC3B,IAAI,WAAW,GACb,OAAO;CAET,OAAO,GAAG,SAAS,QAAQ,CAAC,EAAC;AAC/B;AAQA,SAAS,eAAoC,OAAa;CACxD,IAAI;EACF,OAAO,UAAU,KAAK;CACxB,QACM;EAEJ,OAAO,EAAE,GAAG,MAAM;CACpB;AACF;AAsBO,SAAS,uBACd,UAAmC,CAAC,GACxB;CACZ,MAAM,OAAO;EAAE,GAAG;EAAgB,GAAG;CAAQ;CAC7C,MAAM,SAAS,KAAK,UAAU;CAE9B,OAAO;EACL,MAAM;EACN,UAAU;EAEV,SAAS,OAAO,SAA4B,SAAqC;GAC/E,MAAM,EAAE,SAAS,MAAM,OAAO,YAAY;GAG1C,IAAI,KAAK,UAAU,CAAC,KAAK,OAAO,OAAO,GAAG;IACxC,MAAM,KAAK;IACX;GACF;GAGA,MAAM,gBAAgB,KAAK,WAAW,QAAQ;GAC9C,MAAM,WAAW,KAAK,WAAW,SAAS;GAE1C,IAAK,iBAAiB,CAAC,KAAK,YAAc,YAAY,CAAC,KAAK,WAAY;IACtE,MAAM,KAAK;IACX;GACF;GAEA,MAAM,YAAY,KAAK,YAAY,2BAAW,IAAI,KAAK,CAAC,IAAI;GAC5D,MAAM,SAAS,WAAW,QAAO;GACjC,MAAM,YAAY,YAAY,IAAI;GAGlC,MAAM,YAAY,eAAe,KAAK;GAGtC,MAAM,aAAa,YAAY,GAAG,UAAS,GAAI,OAAM,GAAI,SAAS,GAAG,OAAM,GAAI;GAE/E,MAAM,mBAAyB;IAC7B,IAAI,KAAK,aAAa,OAAO,OAAO,mBAAmB,YACrD,OAAO,eAAe,KAAK,cAAc,WAAW,KAAK;SAC3D,IACS,OAAO,OAAO,UAAU,YAC/B,OAAO,MAAM,KAAK,cAAc,WAAW,KAAK;GAEpD;GAEA,MAAM,iBAAuB;IAC3B,IAAI,OAAO,OAAO,aAAa,YAC7B,OAAO,SAAS;GAEpB;GAEA,WAAW;GAEX,IAAI;IAEF,MAAM,QAAQ,OAAO,KAAK,SAAS,UAAU,OAAO;IAEpD,IAAI,OAAO,UAAU,YAAY;KAC/B,MAAM,KAAK,QAAQ,iBAAiB,WAAW,WAAW,SAAS;KAEnE,IAAI,YAAY,KAAA,GACd,MAAM,KAAK,QAAQ,cAAc,WAAW,QAAQ,OAAO;IAE/D;IAGA,MAAM,KAAK;IAEX,MAAM,UAAU,YAAY,IAAI;IAGhC,IAAI,OAAO,UAAU,YAAY;KAC/B,MAAM,KAAK,QAAQ,iBAAiB,WAAW,WAAW,eAAe,QAAQ,KAAK,CAAC;KACvF,MAAM,KAAK,QAAQ,eAAe,WAAW,UAAU,eAAe,WAAW,OAAO,CAAC;IAC3F;GACF,SACO,OAAO;IAEZ,IAAI,OAAO,OAAO,UAAU,YAC1B,OAAO,MAAM,YAAY,WAAW,OAAO,KAAK;IAIlD,MAAM,IAAI,gBACR,2DAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACnE,UACA,iBAAiB,QAAQ,QAAQ,KAAA,CACnC;GACF,UACA;IACE,SAAS;GACX;EACF;CACF;AACF;AAmBO,SAAS,6BAA6B,UAOzC,CAAC,GAAe;CAClB,MAAM,EAAE,iBAAiB,MAAM,QAAQ,WAAW;CAElD,OAAO;EACL,MAAM;EACN,UAAU;EAEV,SAAS,OAAO,SAA4B,SAAqC;GAC/E,MAAM,EAAE,SAAS,MAAM,YAAY;GAGnC,IAAI,UAAU,CAAC,OAAO,OAAO,GAAG;IAC9B,MAAM,KAAK;IACX;GACF;GAGA,MAAM,UAAU,SACZ,OAAO,OAAO,IACd,WAAW,QAAO,IAAK;GAE3B,IAAI,kBAAkB,YAAY,KAAA,GAChC,QAAQ,KAAK,SAAS,OAAO;QAG7B,QAAQ,KAAK,OAAO;GAGtB,MAAM,KAAK;EACb;CACF;AACF"}
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../../src/middleware/logger.ts"],"sourcesContent":["/**\r\n * 日志中间件\r\n *\r\n * 提供状态变化和 Action 调用的日志记录,支持多种日志级别和格式化选项\r\n * @module middleware/logger\r\n */\r\n\r\nimport type {\r\n LoggerMiddlewareOptions,\r\n Middleware,\r\n MiddlewareContext,\r\n StateTree,\r\n} from '../types'\r\nimport { MiddlewareError } from '../errors'\r\nimport { deepClone } from '../utils'\r\n\r\n/**\r\n * 默认日志选项\r\n */\r\nconst defaultOptions: Required<\r\n Omit<LoggerMiddlewareOptions, 'logger' | 'filter'>\r\n> = {\r\n logState: true,\r\n logAction: true,\r\n collapsed: true,\r\n timestamp: true,\r\n level: 'log',\r\n}\r\n\r\n/**\r\n * 日志颜色配置\r\n */\r\nconst LOG_COLORS = {\r\n prevState: 'color: #9E9E9E; font-weight: bold',\r\n action: 'color: #03A9F4; font-weight: bold',\r\n nextState: 'color: #4CAF50; font-weight: bold',\r\n error: 'color: #F44336; font-weight: bold',\r\n duration: 'color: #9C27B0; font-weight: normal',\r\n title: 'color: inherit; font-weight: bold',\r\n} as const\r\n\r\n/**\r\n * 格式化时间戳\r\n *\r\n * @param date - 日期对象\r\n * @returns 格式化的时间字符串\r\n */\r\nfunction formatTime(date: Date): string {\r\n const hours = date.getHours().toString().padStart(2, '0')\r\n const minutes = date.getMinutes().toString().padStart(2, '0')\r\n const seconds = date.getSeconds().toString().padStart(2, '0')\r\n const ms = date.getMilliseconds().toString().padStart(3, '0')\r\n return `${hours}:${minutes}:${seconds}.${ms}`\r\n}\r\n\r\n/**\r\n * 格式化时间差\r\n *\r\n * @param startTime - 开始时间\r\n * @param endTime - 结束时间\r\n * @returns 格式化的时间差字符串\r\n */\r\nfunction formatDuration(startTime: number, endTime: number): string {\r\n const duration = endTime - startTime\r\n if (duration < 1) {\r\n return '< 1ms'\r\n }\r\n return `${duration.toFixed(2)}ms`\r\n}\r\n\r\n/**\r\n * 安全克隆状态(防止日志中的对象被修改)\r\n *\r\n * @param state - 状态对象\r\n * @returns 克隆后的状态\r\n */\r\nfunction safeCloneState<S extends StateTree>(state: S): S {\r\n try {\r\n return deepClone(state)\r\n } catch {\r\n // 如果克隆失败,返回浅拷贝\r\n return { ...state }\r\n }\r\n}\r\n\r\n/**\r\n * 创建日志中间件\r\n *\r\n * 提供完整的状态变化和 Action 调用日志记录,支持时间戳、分组和性能计时\r\n *\r\n * @param options - 日志选项\r\n * @returns 日志中间件\r\n *\r\n * @example\r\n * ```typescript\r\n * const logger = createLoggerMiddleware({\r\n * logState: true,\r\n * collapsed: true,\r\n * timestamp: true,\r\n * filter: (context) => context.storeId !== 'internal'\r\n * })\r\n *\r\n * middlewareManager.use(logger)\r\n * ```\r\n */\r\nexport function createLoggerMiddleware(\r\n options: LoggerMiddlewareOptions = {}\r\n): Middleware {\r\n const opts = { ...defaultOptions, ...options }\r\n const logger = opts.logger ?? console\r\n\r\n return {\r\n name: 'logger',\r\n priority: 0, // 最先执行,确保能记录所有操作\r\n\r\n handler: async (\r\n context: MiddlewareContext,\r\n next: () => void | Promise<void>\r\n ) => {\r\n const { storeId, type, state, payload } = context\r\n\r\n // 应用自定义过滤器\r\n if (opts.filter && !opts.filter(context)) {\r\n await next()\r\n return\r\n }\r\n\r\n // 判断是否需要记录\r\n const isStateChange = type.startsWith('state:')\r\n const isAction = type.startsWith('action:')\r\n\r\n if ((isStateChange && !opts.logState) || (isAction && !opts.logAction)) {\r\n await next()\r\n return\r\n }\r\n\r\n const timestamp = opts.timestamp ? formatTime(new Date()) : ''\r\n const prefix = `[Store: ${storeId}]`\r\n const startTime = performance.now()\r\n\r\n // 保存操作前的状态\r\n const prevState = safeCloneState(state)\r\n\r\n // 开始分组\r\n const groupTitle = timestamp\r\n ? `${timestamp} ${prefix} ${type}`\r\n : `${prefix} ${type}`\r\n\r\n const startGroup = (): void => {\r\n if (opts.collapsed && typeof logger.groupCollapsed === 'function') {\r\n logger.groupCollapsed(`%c${groupTitle}`, LOG_COLORS.title)\r\n } else if (typeof logger.group === 'function') {\r\n logger.group(`%c${groupTitle}`, LOG_COLORS.title)\r\n }\r\n }\r\n\r\n const endGroup = (): void => {\r\n if (typeof logger.groupEnd === 'function') {\r\n logger.groupEnd()\r\n }\r\n }\r\n\r\n startGroup()\r\n\r\n try {\r\n // 记录操作前的状态\r\n const logFn = logger[opts.level ?? 'log'] ?? logger.log\r\n\r\n if (typeof logFn === 'function') {\r\n logFn.call(logger, '%c prev state', LOG_COLORS.prevState, prevState)\r\n\r\n if (payload !== undefined) {\r\n logFn.call(logger, '%c payload', LOG_COLORS.action, payload)\r\n }\r\n }\r\n\r\n // 执行下一个中间件\r\n await next()\r\n\r\n const endTime = performance.now()\r\n\r\n // 记录操作后的状态\r\n if (typeof logFn === 'function') {\r\n logFn.call(\r\n logger,\r\n '%c next state',\r\n LOG_COLORS.nextState,\r\n safeCloneState(context.state)\r\n )\r\n logFn.call(\r\n logger,\r\n '%c duration',\r\n LOG_COLORS.duration,\r\n formatDuration(startTime, endTime)\r\n )\r\n }\r\n } catch (error) {\r\n // 记录错误\r\n if (typeof logger.error === 'function') {\r\n logger.error('%c error', LOG_COLORS.error, error)\r\n }\r\n\r\n // 包装并重新抛出错误\r\n throw new MiddlewareError(\r\n `日志中间件执行错误: ${error instanceof Error ? error.message : String(error)}`,\r\n 'logger',\r\n error instanceof Error ? error : undefined\r\n )\r\n } finally {\r\n endGroup()\r\n }\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 简单日志中间件(不使用分组,适合生产环境)\r\n *\r\n * @param options - 配置选项\r\n * @param options.includePayload - 是否输出 payload\r\n * @param options.format - 自定义日志格式化函数\r\n * @param options.filter - 日志过滤器\r\n * @returns 简单日志中间件\r\n *\r\n * @example\r\n * ```typescript\r\n * const logger = createSimpleLoggerMiddleware({\r\n * includePayload: true,\r\n * format: (ctx) => `${ctx.storeId}: ${ctx.type}`\r\n * })\r\n * ```\r\n */\r\nexport function createSimpleLoggerMiddleware(\r\n options: {\r\n /** 是否包含 payload */\r\n includePayload?: boolean\r\n /** 自定义格式化函数 */\r\n format?: (context: MiddlewareContext) => string\r\n /** 过滤器 */\r\n filter?: (context: MiddlewareContext) => boolean\r\n } = {}\r\n): Middleware {\r\n const { includePayload = true, format, filter } = options\r\n\r\n return {\r\n name: 'simple-logger',\r\n priority: 0,\r\n\r\n handler: async (\r\n context: MiddlewareContext,\r\n next: () => void | Promise<void>\r\n ) => {\r\n const { storeId, type, payload } = context\r\n\r\n // 应用过滤器\r\n if (filter && !filter(context)) {\r\n await next()\r\n return\r\n }\r\n\r\n // 使用自定义格式化或默认格式\r\n const message = format ? format(context) : `[Store: ${storeId}] ${type}`\r\n\r\n if (includePayload && payload !== undefined) {\r\n console.info(message, payload)\r\n } else {\r\n console.info(message)\r\n }\r\n\r\n await next()\r\n },\r\n }\r\n}\r\n\r\n/**\r\n * 创建生产环境日志中间件\r\n *\r\n * 只记录错误和警告,不记录正常状态变化\r\n *\r\n * @param options - 配置选项\r\n * @param options.onError - 自定义错误处理器\r\n * @returns 生产环境日志中间件\r\n */\r\nexport function createProductionLoggerMiddleware(\r\n options: {\r\n /** 自定义错误处理器 */\r\n onError?: (error: Error, context: MiddlewareContext) => void\r\n } = {}\r\n): Middleware {\r\n const { onError } = options\r\n\r\n return {\r\n name: 'production-logger',\r\n priority: 0,\r\n\r\n handler: async (\r\n context: MiddlewareContext,\r\n next: () => void | Promise<void>\r\n ) => {\r\n try {\r\n await next()\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error))\r\n\r\n if (onError) {\r\n onError(err, context)\r\n } else {\r\n console.error(`[Store Error] ${context.storeId}:`, err)\r\n }\r\n\r\n throw error\r\n }\r\n },\r\n }\r\n}\r\n"],"mappings":"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"}
|