@composy/store-vue 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.
Files changed (251) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +169 -154
  3. package/dist/index.js +151 -53
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.min.js +242 -170
  6. package/dist/index.min.js.map +1 -1
  7. package/es/.dts-output-manifest.json +1 -0
  8. package/es/.dts.tsbuildinfo +1 -0
  9. package/es/composables/defineSetupStore.d.ts +0 -1
  10. package/es/composables/defineSetupStore.d.ts.map +1 -1
  11. package/es/composables/defineSetupStore.js +1 -1
  12. package/es/composables/defineSetupStore.js.map +1 -1
  13. package/es/composables/index.d.ts +8 -9
  14. package/es/composables/index.d.ts.map +1 -1
  15. package/es/composables/index.js +1 -1
  16. package/es/composables/useFormStore.d.ts +0 -1
  17. package/es/composables/useFormStore.d.ts.map +1 -1
  18. package/es/composables/useFormStore.js +1 -1
  19. package/es/composables/useFormStore.js.map +1 -1
  20. package/es/composables/useOptimistic.d.ts +1 -52
  21. package/es/composables/useOptimistic.d.ts.map +1 -1
  22. package/es/composables/useOptimistic.js +35 -20
  23. package/es/composables/useOptimistic.js.map +1 -1
  24. package/es/composables/usePersist.d.ts +0 -1
  25. package/es/composables/usePersist.d.ts.map +1 -1
  26. package/es/composables/usePersist.js +16 -7
  27. package/es/composables/usePersist.js.map +1 -1
  28. package/es/composables/usePersistedState.d.ts +0 -1
  29. package/es/composables/usePersistedState.d.ts.map +1 -1
  30. package/es/composables/usePersistedState.js +16 -3
  31. package/es/composables/usePersistedState.js.map +1 -1
  32. package/es/composables/useSharedState.d.ts +0 -1
  33. package/es/composables/useSharedState.d.ts.map +1 -1
  34. package/es/composables/useSharedState.js +25 -8
  35. package/es/composables/useSharedState.js.map +1 -1
  36. package/es/composables/useStore.d.ts +0 -1
  37. package/es/composables/useStore.js +1 -1
  38. package/es/composables/useStore.js.map +1 -1
  39. package/es/composables/useStoreDevtools.d.ts +0 -1
  40. package/es/composables/useStoreDevtools.d.ts.map +1 -1
  41. package/es/composables/useStoreDevtools.js +1 -1
  42. package/es/composables/useStoreDevtools.js.map +1 -1
  43. package/es/composables/useStoreSnapshot.d.ts +0 -1
  44. package/es/composables/useStoreSnapshot.d.ts.map +1 -1
  45. package/es/composables/useStoreSnapshot.js +18 -8
  46. package/es/composables/useStoreSnapshot.js.map +1 -1
  47. package/es/composables/useSubscribe.d.ts +0 -1
  48. package/es/composables/useSubscribe.d.ts.map +1 -1
  49. package/es/composables/useSubscribe.js +1 -1
  50. package/es/composables/useSubscribe.js.map +1 -1
  51. package/es/context/injection-keys.d.ts +0 -1
  52. package/es/context/injection-keys.d.ts.map +1 -1
  53. package/es/context/injection-keys.js +1 -1
  54. package/es/context/injection-keys.js.map +1 -1
  55. package/es/index.d.ts +1 -2
  56. package/es/index.js +2 -2
  57. package/es/index.js.map +1 -1
  58. package/es/plugins/engine-plugin.d.ts +1 -2
  59. package/es/plugins/engine-plugin.d.ts.map +1 -1
  60. package/es/plugins/engine-plugin.js +2 -2
  61. package/es/plugins/engine-plugin.js.map +1 -1
  62. package/es/plugins/enhanced-persist-plugin.d.ts +0 -1
  63. package/es/plugins/enhanced-persist-plugin.js +1 -1
  64. package/es/plugins/index.d.ts +0 -1
  65. package/es/plugins/index.js +1 -1
  66. package/es/plugins/pinia-plugin.d.ts +0 -1
  67. package/es/plugins/pinia-plugin.d.ts.map +1 -1
  68. package/es/plugins/pinia-plugin.js +24 -6
  69. package/es/plugins/pinia-plugin.js.map +1 -1
  70. package/es/plugins/registry-plugin.d.ts +0 -1
  71. package/es/plugins/registry-plugin.js +1 -1
  72. package/es/plugins/vue-plugin.d.ts +0 -1
  73. package/es/plugins/vue-plugin.d.ts.map +1 -1
  74. package/es/plugins/vue-plugin.js +1 -1
  75. package/es/plugins/vue-plugin.js.map +1 -1
  76. package/es/runtime/install-store-app.d.ts +0 -1
  77. package/es/runtime/install-store-app.js +1 -1
  78. package/es/runtime/install-store-app.js.map +1 -1
  79. package/es/runtime/store-plugin-options.d.ts +0 -1
  80. package/es/runtime/store-plugin-options.js +1 -1
  81. package/es/runtime/store-plugin-options.js.map +1 -1
  82. package/es/runtime/store-registry.d.ts +0 -1
  83. package/es/runtime/store-registry.d.ts.map +1 -1
  84. package/es/runtime/store-registry.js +14 -4
  85. package/es/runtime/store-registry.js.map +1 -1
  86. package/es/runtime/store-runtime.d.ts +1 -2
  87. package/es/runtime/store-runtime.d.ts.map +1 -1
  88. package/es/runtime/store-runtime.js +8 -2
  89. package/es/runtime/store-runtime.js.map +1 -1
  90. package/es/types.d.ts +2 -1
  91. package/es/types.d.ts.map +1 -1
  92. package/es/types.js +1 -1
  93. package/esm/composables/defineSetupStore.d.ts.map +1 -1
  94. package/esm/composables/defineSetupStore.js +1 -1
  95. package/esm/composables/defineSetupStore.js.map +1 -1
  96. package/esm/composables/index.d.ts +8 -8
  97. package/esm/composables/index.d.ts.map +1 -1
  98. package/esm/composables/index.js +1 -1
  99. package/esm/composables/useFormStore.d.ts.map +1 -1
  100. package/esm/composables/useFormStore.js +1 -1
  101. package/esm/composables/useFormStore.js.map +1 -1
  102. package/esm/composables/useOptimistic.d.ts +1 -51
  103. package/esm/composables/useOptimistic.d.ts.map +1 -1
  104. package/esm/composables/useOptimistic.js +35 -20
  105. package/esm/composables/useOptimistic.js.map +1 -1
  106. package/esm/composables/usePersist.d.ts.map +1 -1
  107. package/esm/composables/usePersist.js +16 -7
  108. package/esm/composables/usePersist.js.map +1 -1
  109. package/esm/composables/usePersistedState.d.ts.map +1 -1
  110. package/esm/composables/usePersistedState.js +16 -3
  111. package/esm/composables/usePersistedState.js.map +1 -1
  112. package/esm/composables/useSharedState.d.ts.map +1 -1
  113. package/esm/composables/useSharedState.js +25 -8
  114. package/esm/composables/useSharedState.js.map +1 -1
  115. package/esm/composables/useStore.js +1 -1
  116. package/esm/composables/useStore.js.map +1 -1
  117. package/esm/composables/useStoreDevtools.d.ts.map +1 -1
  118. package/esm/composables/useStoreDevtools.js +1 -1
  119. package/esm/composables/useStoreDevtools.js.map +1 -1
  120. package/esm/composables/useStoreSnapshot.d.ts.map +1 -1
  121. package/esm/composables/useStoreSnapshot.js +18 -8
  122. package/esm/composables/useStoreSnapshot.js.map +1 -1
  123. package/esm/composables/useSubscribe.d.ts.map +1 -1
  124. package/esm/composables/useSubscribe.js +1 -1
  125. package/esm/composables/useSubscribe.js.map +1 -1
  126. package/esm/context/injection-keys.d.ts.map +1 -1
  127. package/esm/context/injection-keys.js +1 -1
  128. package/esm/context/injection-keys.js.map +1 -1
  129. package/esm/index.d.ts +1 -1
  130. package/esm/index.js +2 -2
  131. package/esm/index.js.map +1 -1
  132. package/esm/plugins/engine-plugin.d.ts +1 -1
  133. package/esm/plugins/engine-plugin.d.ts.map +1 -1
  134. package/esm/plugins/engine-plugin.js +2 -2
  135. package/esm/plugins/engine-plugin.js.map +1 -1
  136. package/esm/plugins/enhanced-persist-plugin.js +1 -1
  137. package/esm/plugins/index.js +1 -1
  138. package/esm/plugins/pinia-plugin.d.ts.map +1 -1
  139. package/esm/plugins/pinia-plugin.js +24 -6
  140. package/esm/plugins/pinia-plugin.js.map +1 -1
  141. package/esm/plugins/registry-plugin.js +1 -1
  142. package/esm/plugins/vue-plugin.d.ts.map +1 -1
  143. package/esm/plugins/vue-plugin.js +1 -1
  144. package/esm/plugins/vue-plugin.js.map +1 -1
  145. package/esm/runtime/install-store-app.js +1 -1
  146. package/esm/runtime/install-store-app.js.map +1 -1
  147. package/esm/runtime/store-plugin-options.js +1 -1
  148. package/esm/runtime/store-plugin-options.js.map +1 -1
  149. package/esm/runtime/store-registry.d.ts.map +1 -1
  150. package/esm/runtime/store-registry.js +14 -4
  151. package/esm/runtime/store-registry.js.map +1 -1
  152. package/esm/runtime/store-runtime.d.ts +1 -1
  153. package/esm/runtime/store-runtime.d.ts.map +1 -1
  154. package/esm/runtime/store-runtime.js +8 -2
  155. package/esm/runtime/store-runtime.js.map +1 -1
  156. package/esm/types.d.ts +2 -0
  157. package/esm/types.d.ts.map +1 -1
  158. package/esm/types.js +1 -1
  159. package/lib/composables/defineSetupStore.cjs +1 -1
  160. package/lib/composables/defineSetupStore.cjs.map +1 -1
  161. package/lib/composables/{defineSetupStore.d.ts → defineSetupStore.d.cts} +0 -1
  162. package/lib/composables/defineSetupStore.d.cts.map +1 -0
  163. package/lib/composables/index.cjs +1 -1
  164. package/lib/composables/{index.d.ts → index.d.cts} +8 -9
  165. package/lib/composables/index.d.cts.map +1 -0
  166. package/lib/composables/useFormStore.cjs +1 -1
  167. package/lib/composables/useFormStore.cjs.map +1 -1
  168. package/lib/composables/{useFormStore.d.ts → useFormStore.d.cts} +0 -1
  169. package/lib/composables/useFormStore.d.cts.map +1 -0
  170. package/lib/composables/useOptimistic.cjs +35 -20
  171. package/lib/composables/useOptimistic.cjs.map +1 -1
  172. package/lib/composables/useOptimistic.d.cts +16 -0
  173. package/lib/composables/useOptimistic.d.cts.map +1 -0
  174. package/lib/composables/usePersist.cjs +16 -7
  175. package/lib/composables/usePersist.cjs.map +1 -1
  176. package/lib/composables/{usePersist.d.ts → usePersist.d.cts} +0 -1
  177. package/lib/composables/usePersist.d.cts.map +1 -0
  178. package/lib/composables/usePersistedState.cjs +16 -3
  179. package/lib/composables/usePersistedState.cjs.map +1 -1
  180. package/lib/composables/{usePersistedState.d.ts → usePersistedState.d.cts} +0 -1
  181. package/lib/composables/usePersistedState.d.cts.map +1 -0
  182. package/lib/composables/useSharedState.cjs +24 -7
  183. package/lib/composables/useSharedState.cjs.map +1 -1
  184. package/lib/composables/{useSharedState.d.ts → useSharedState.d.cts} +0 -1
  185. package/lib/composables/useSharedState.d.cts.map +1 -0
  186. package/lib/composables/useStore.cjs +1 -1
  187. package/lib/composables/useStore.cjs.map +1 -1
  188. package/lib/composables/{useStore.d.ts → useStore.d.cts} +0 -1
  189. package/lib/composables/useStore.d.cts.map +1 -0
  190. package/lib/composables/useStoreDevtools.cjs +1 -1
  191. package/lib/composables/useStoreDevtools.cjs.map +1 -1
  192. package/lib/composables/{useStoreDevtools.d.ts → useStoreDevtools.d.cts} +0 -1
  193. package/lib/composables/useStoreDevtools.d.cts.map +1 -0
  194. package/lib/composables/useStoreSnapshot.cjs +18 -8
  195. package/lib/composables/useStoreSnapshot.cjs.map +1 -1
  196. package/lib/composables/{useStoreSnapshot.d.ts → useStoreSnapshot.d.cts} +0 -1
  197. package/lib/composables/useStoreSnapshot.d.cts.map +1 -0
  198. package/lib/composables/useSubscribe.cjs +1 -1
  199. package/lib/composables/useSubscribe.cjs.map +1 -1
  200. package/lib/composables/{useSubscribe.d.ts → useSubscribe.d.cts} +0 -1
  201. package/lib/composables/useSubscribe.d.cts.map +1 -0
  202. package/lib/context/injection-keys.cjs +1 -1
  203. package/lib/context/injection-keys.cjs.map +1 -1
  204. package/lib/context/{injection-keys.d.ts → injection-keys.d.cts} +0 -1
  205. package/lib/context/injection-keys.d.cts.map +1 -0
  206. package/lib/index.cjs +2 -2
  207. package/lib/index.cjs.map +1 -1
  208. package/lib/{index.d.ts → index.d.cts} +1 -2
  209. package/lib/index.d.cts.map +1 -0
  210. package/lib/plugins/engine-plugin.cjs +2 -2
  211. package/lib/plugins/engine-plugin.cjs.map +1 -1
  212. package/lib/plugins/{engine-plugin.d.ts → engine-plugin.d.cts} +1 -2
  213. package/lib/plugins/engine-plugin.d.cts.map +1 -0
  214. package/lib/plugins/enhanced-persist-plugin.cjs +1 -1
  215. package/lib/plugins/{enhanced-persist-plugin.d.ts → enhanced-persist-plugin.d.cts} +0 -1
  216. package/lib/plugins/enhanced-persist-plugin.d.cts.map +1 -0
  217. package/lib/plugins/index.cjs +1 -1
  218. package/lib/plugins/{index.d.ts → index.d.cts} +0 -1
  219. package/lib/plugins/index.d.cts.map +1 -0
  220. package/lib/plugins/pinia-plugin.cjs +24 -6
  221. package/lib/plugins/pinia-plugin.cjs.map +1 -1
  222. package/lib/plugins/{pinia-plugin.d.ts → pinia-plugin.d.cts} +0 -1
  223. package/lib/plugins/pinia-plugin.d.cts.map +1 -0
  224. package/lib/plugins/registry-plugin.cjs +1 -1
  225. package/lib/plugins/{registry-plugin.d.ts → registry-plugin.d.cts} +0 -1
  226. package/lib/plugins/registry-plugin.d.cts.map +1 -0
  227. package/lib/plugins/vue-plugin.cjs +1 -1
  228. package/lib/plugins/vue-plugin.cjs.map +1 -1
  229. package/lib/plugins/{vue-plugin.d.ts → vue-plugin.d.cts} +0 -1
  230. package/lib/plugins/vue-plugin.d.cts.map +1 -0
  231. package/lib/runtime/install-store-app.cjs +1 -1
  232. package/lib/runtime/install-store-app.cjs.map +1 -1
  233. package/lib/runtime/{install-store-app.d.ts → install-store-app.d.cts} +0 -1
  234. package/lib/runtime/install-store-app.d.cts.map +1 -0
  235. package/lib/runtime/store-plugin-options.cjs +1 -1
  236. package/lib/runtime/store-plugin-options.cjs.map +1 -1
  237. package/lib/runtime/{store-plugin-options.d.ts → store-plugin-options.d.cts} +0 -1
  238. package/lib/runtime/store-plugin-options.d.cts.map +1 -0
  239. package/lib/runtime/store-registry.cjs +14 -4
  240. package/lib/runtime/store-registry.cjs.map +1 -1
  241. package/lib/runtime/{store-registry.d.ts → store-registry.d.cts} +0 -1
  242. package/lib/runtime/store-registry.d.cts.map +1 -0
  243. package/lib/runtime/store-runtime.cjs +8 -2
  244. package/lib/runtime/store-runtime.cjs.map +1 -1
  245. package/lib/runtime/{store-runtime.d.ts → store-runtime.d.cts} +1 -2
  246. package/lib/runtime/store-runtime.d.cts.map +1 -0
  247. package/lib/types.cjs +1 -1
  248. package/lib/{types.d.ts → types.d.cts} +2 -1
  249. package/lib/types.d.cts.map +1 -0
  250. package/package.json +19 -16
  251. package/lib/composables/useOptimistic.d.ts +0 -67
@@ -2,13 +2,13 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
9
9
  */
10
10
  import { onUnmounted, ref, watch } from "vue";
11
- import { deepClone } from "@composy/store-core";
11
+ import { deepClone, deepEqual } from "@composy/store-core";
12
12
  //#region src/composables/useSharedState.ts
13
13
  function useSharedState(channelName, initialState, options = {}) {
14
14
  const { immediate = false, deep = true } = options;
@@ -16,7 +16,11 @@ function useSharedState(channelName, initialState, options = {}) {
16
16
  const peerCount = ref(0);
17
17
  const lastSyncAt = ref(null);
18
18
  let channel = null;
19
- let isReceiving = false;
19
+ const originId = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
20
+ let revision = 0;
21
+ const latestRemoteRevision = /* @__PURE__ */ new Map();
22
+ let pendingRemoteState;
23
+ let hasPendingRemoteState = false;
20
24
  if (typeof BroadcastChannel === "undefined") {
21
25
  console.warn("[useSharedState] BroadcastChannel not supported in this environment");
22
26
  return {
@@ -45,7 +49,9 @@ function useSharedState(channelName, initialState, options = {}) {
45
49
  channel.postMessage({
46
50
  type: "state-update",
47
51
  payload: deepClone(state.value),
48
- timestamp: Date.now()
52
+ timestamp: Date.now(),
53
+ origin: originId,
54
+ revision: ++revision
49
55
  });
50
56
  } catch (e) {
51
57
  console.warn("[useSharedState] broadcast error:", e);
@@ -55,15 +61,26 @@ function useSharedState(channelName, initialState, options = {}) {
55
61
  const msg = event.data;
56
62
  if (!msg || typeof msg !== "object") return;
57
63
  if (msg.type === "state-update") {
58
- isReceiving = true;
59
- state.value = msg.payload;
64
+ if (msg.origin === originId) return;
65
+ const remoteRevision = typeof msg.revision === "number" ? msg.revision : 0;
66
+ if (remoteRevision <= (latestRemoteRevision.get(String(msg.origin)) ?? -1)) return;
67
+ latestRemoteRevision.set(String(msg.origin), remoteRevision);
68
+ pendingRemoteState = deepClone(msg.payload);
69
+ hasPendingRemoteState = true;
70
+ state.value = pendingRemoteState;
60
71
  lastSyncAt.value = msg.timestamp || Date.now();
61
- isReceiving = false;
62
72
  } else if (msg.type === "ping") channel?.postMessage({ type: "pong" });
63
73
  else if (msg.type === "pong") peerCount.value++;
64
74
  };
65
75
  const stopWatch = watch(state, () => {
66
- if (!isReceiving) broadcast();
76
+ if (hasPendingRemoteState) {
77
+ if (deepEqual(state.value, pendingRemoteState)) {
78
+ hasPendingRemoteState = false;
79
+ return;
80
+ }
81
+ hasPendingRemoteState = false;
82
+ }
83
+ broadcast();
67
84
  }, { deep });
68
85
  function close() {
69
86
  stopWatch();
@@ -1 +1 @@
1
- {"version":3,"file":"useSharedState.js","names":[],"sources":["../../src/composables/useSharedState.ts"],"sourcesContent":["/**\n * useSharedState - 跨标签页状态同步\n *\n * 基于 BroadcastChannel API 实现多标签页实时状态同步\n * @module composables/useSharedState\n */\n\nimport type {Ref} from 'vue';\nimport { deepClone } from '@composy/store-core'\nimport { onUnmounted, ref, watch } from 'vue'\n\n/**\n * useSharedState 选项\n */\nexport interface UseSharedStateOptions {\n /** 是否立即将当前值广播给其他标签页 */\n immediate?: boolean\n /** 是否深度监听变化 */\n deep?: boolean\n}\n\n/**\n * useSharedState 返回值\n */\nexport interface UseSharedStateReturn<T> {\n /** 响应式状态 (双向同步) */\n state: Ref<T>\n /** 手动广播当前状态到其他标签页 */\n broadcast: () => void\n /** 连接的标签页数量 (近似值) */\n peerCount: Ref<number>\n /** 最后同步时间 */\n lastSyncAt: Ref<number | null>\n /** 关闭通道 */\n close: () => void\n}\n\n/**\n * 跨标签页状态同步 Hook\n *\n * 使用 BroadcastChannel API 在多个标签页之间实时同步状态。\n * 任意标签页修改状态后,其他标签页会自动收到更新。\n *\n * @template T - 状态类型 (必须可序列化)\n * @param channelName - 通道名称 (相同名称的标签页共享状态)\n * @param initialState - 初始状态\n * @param options - 选项\n * @returns 同步状态和控制 API\n *\n * @example\n * ```typescript\n * // 标签页 A\n * const { state } = useSharedState('my-channel', { count: 0, user: 'Alice' })\n * state.value.count++ // 所有标签页都会收到更新\n *\n * // 标签页 B (相同代码)\n * const { state } = useSharedState('my-channel', { count: 0, user: 'Alice' })\n * // state.value.count 会自动变为 1\n *\n * // 手动广播\n * broadcast()\n *\n * // 关闭通道\n * close()\n * ```\n */\nexport function useSharedState<T>(\n channelName: string,\n initialState: T,\n options: UseSharedStateOptions = {},\n): UseSharedStateReturn<T> {\n const { immediate = false, deep = true } = options\n\n const state = ref<T>(deepClone(initialState)) as Ref<T>\n const peerCount = ref(0)\n const lastSyncAt = ref<number | null>(null)\n\n let channel: BroadcastChannel | null = null\n let isReceiving = false\n\n // 检测 BroadcastChannel 是否可用\n if (typeof BroadcastChannel === 'undefined') {\n console.warn('[useSharedState] BroadcastChannel not supported in this environment')\n return {\n state,\n broadcast: () => {},\n peerCount,\n lastSyncAt,\n close: () => {},\n }\n }\n\n try {\n channel = new BroadcastChannel(channelName)\n }\n catch (e) {\n console.warn('[useSharedState] Failed to create BroadcastChannel:', e)\n return {\n state,\n broadcast: () => {},\n peerCount,\n lastSyncAt,\n close: () => {},\n }\n }\n\n /** 广播当前状态 */\n function broadcast(): void {\n if (!channel) return\n try {\n channel.postMessage({\n type: 'state-update',\n payload: deepClone(state.value),\n timestamp: Date.now(),\n })\n }\n catch (e) {\n console.warn('[useSharedState] broadcast error:', e)\n }\n }\n\n /** 接收其他标签页的消息 */\n channel.onmessage = (event: MessageEvent) => {\n const msg = event.data\n if (!msg || typeof msg !== 'object') return\n\n if (msg.type === 'state-update') {\n isReceiving = true\n state.value = msg.payload as T\n lastSyncAt.value = msg.timestamp || Date.now()\n isReceiving = false\n }\n else if (msg.type === 'ping') {\n channel?.postMessage({ type: 'pong' })\n }\n else if (msg.type === 'pong') {\n peerCount.value++\n }\n }\n\n /** 监听本地变化并广播 */\n const stopWatch = watch(\n state,\n () => {\n if (!isReceiving) {\n broadcast()\n }\n },\n { deep },\n )\n\n /** 关闭通道 */\n function close(): void {\n stopWatch()\n if (channel) {\n channel.close()\n channel = null\n }\n }\n\n // 通知其他标签页本页存在\n if (immediate) {\n broadcast()\n }\n\n // 发送 ping 探测其他标签页\n if (channel) {\n peerCount.value = 0\n channel.postMessage({ type: 'ping' })\n }\n\n onUnmounted(() => {\n close()\n })\n\n return {\n state,\n broadcast,\n peerCount,\n lastSyncAt,\n close,\n }\n}\n"],"mappings":";;;;;;;;;;;;AAkEO,SAAS,eACd,aACA,cACA,UAAiC,CAAC,GACT;CACzB,MAAM,EAAE,YAAY,OAAO,OAAO,SAAS;CAE3C,MAAM,QAAQ,IAAO,UAAU,YAAY,CAAC;CAC5C,MAAM,YAAY,IAAI,CAAC;CACvB,MAAM,aAAa,IAAmB,IAAI;CAE1C,IAAI,UAAmC;CACvC,IAAI,cAAc;CAGlB,IAAI,OAAO,qBAAqB,aAAa;EAC3C,QAAQ,KAAK,qEAAqE;EAClF,OAAO;GACL;GACA,iBAAiB,CAAC;GAClB;GACA;GACA,aAAa,CAAC;EAChB;CACF;CAEA,IAAI;EACF,UAAU,IAAI,iBAAiB,WAAW;CAC5C,SACO,GAAG;EACR,QAAQ,KAAK,uDAAuD,CAAC;EACrE,OAAO;GACL;GACA,iBAAiB,CAAC;GAClB;GACA;GACA,aAAa,CAAC;EAChB;CACF;CAGA,SAAS,YAAkB;EACzB,IAAI,CAAC,SAAS;EACd,IAAI;GACF,QAAQ,YAAY;IAClB,MAAM;IACN,SAAS,UAAU,MAAM,KAAK;IAC9B,WAAW,KAAK,IAAI;GACtB,CAAC;EACH,SACO,GAAG;GACR,QAAQ,KAAK,qCAAqC,CAAC;EACrD;CACF;CAGA,QAAQ,aAAa,UAAwB;EAC3C,MAAM,MAAM,MAAM;EAClB,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;EAErC,IAAI,IAAI,SAAS,gBAAgB;GAC/B,cAAc;GACd,MAAM,QAAQ,IAAI;GAClB,WAAW,QAAQ,IAAI,aAAa,KAAK,IAAI;GAC7C,cAAc;EAChB,OAAA,IACS,IAAI,SAAS,QACpB,SAAS,YAAY,EAAE,MAAM,OAAO,CAAC;OACvC,IACS,IAAI,SAAS,QACpB,UAAU;CAEd;CAGA,MAAM,YAAY,MAChB,aACM;EACJ,IAAI,CAAC,aACH,UAAU;CAEd,GACA,EAAE,KAAK,CACT;CAGA,SAAS,QAAc;EACrB,UAAU;EACV,IAAI,SAAS;GACX,QAAQ,MAAM;GACd,UAAU;EACZ;CACF;CAGA,IAAI,WACF,UAAU;CAIZ,IAAI,SAAS;EACX,UAAU,QAAQ;EAClB,QAAQ,YAAY,EAAE,MAAM,OAAO,CAAC;CACtC;CAEA,kBAAkB;EAChB,MAAM;CACR,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"useSharedState.js","names":[],"sources":["../../src/composables/useSharedState.ts"],"sourcesContent":["/**\r\n * useSharedState - 跨标签页状态同步\r\n *\r\n * 基于 BroadcastChannel API 实现多标签页实时状态同步\r\n * @module composables/useSharedState\r\n */\r\n\r\nimport type { Ref } from 'vue'\r\nimport { deepClone, deepEqual } from '@composy/store-core'\r\nimport { onUnmounted, ref, watch } from 'vue'\r\n\r\n/**\r\n * useSharedState 选项\r\n */\r\nexport interface UseSharedStateOptions {\r\n /** 是否立即将当前值广播给其他标签页 */\r\n immediate?: boolean\r\n /** 是否深度监听变化 */\r\n deep?: boolean\r\n}\r\n\r\n/**\r\n * useSharedState 返回值\r\n */\r\nexport interface UseSharedStateReturn<T> {\r\n /** 响应式状态 (双向同步) */\r\n state: Ref<T>\r\n /** 手动广播当前状态到其他标签页 */\r\n broadcast: () => void\r\n /** 连接的标签页数量 (近似值) */\r\n peerCount: Ref<number>\r\n /** 最后同步时间 */\r\n lastSyncAt: Ref<number | null>\r\n /** 关闭通道 */\r\n close: () => void\r\n}\r\n\r\n/**\r\n * 跨标签页状态同步 Hook\r\n *\r\n * 使用 BroadcastChannel API 在多个标签页之间实时同步状态。\r\n * 任意标签页修改状态后,其他标签页会自动收到更新。\r\n *\r\n * @template T - 状态类型 (必须可序列化)\r\n * @param channelName - 通道名称 (相同名称的标签页共享状态)\r\n * @param initialState - 初始状态\r\n * @param options - 选项\r\n * @returns 同步状态和控制 API\r\n *\r\n * @example\r\n * ```typescript\r\n * // 标签页 A\r\n * const { state } = useSharedState('my-channel', { count: 0, user: 'Alice' })\r\n * state.value.count++ // 所有标签页都会收到更新\r\n *\r\n * // 标签页 B (相同代码)\r\n * const { state } = useSharedState('my-channel', { count: 0, user: 'Alice' })\r\n * // state.value.count 会自动变为 1\r\n *\r\n * // 手动广播\r\n * broadcast()\r\n *\r\n * // 关闭通道\r\n * close()\r\n * ```\r\n */\r\nexport function useSharedState<T>(\r\n channelName: string,\r\n initialState: T,\r\n options: UseSharedStateOptions = {}\r\n): UseSharedStateReturn<T> {\r\n const { immediate = false, deep = true } = options\r\n\r\n const state = ref<T>(deepClone(initialState)) as Ref<T>\r\n const peerCount = ref(0)\r\n const lastSyncAt = ref<number | null>(null)\r\n\r\n let channel: BroadcastChannel | null = null\r\n const originId = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`\r\n let revision = 0\r\n const latestRemoteRevision = new Map<string, number>()\r\n let pendingRemoteState: T\r\n let hasPendingRemoteState = false\r\n\r\n // 检测 BroadcastChannel 是否可用\r\n if (typeof BroadcastChannel === 'undefined') {\r\n console.warn(\r\n '[useSharedState] BroadcastChannel not supported in this environment'\r\n )\r\n return {\r\n state,\r\n broadcast: () => {},\r\n peerCount,\r\n lastSyncAt,\r\n close: () => {},\r\n }\r\n }\r\n\r\n try {\r\n channel = new BroadcastChannel(channelName)\r\n } catch (e) {\r\n console.warn('[useSharedState] Failed to create BroadcastChannel:', e)\r\n return {\r\n state,\r\n broadcast: () => {},\r\n peerCount,\r\n lastSyncAt,\r\n close: () => {},\r\n }\r\n }\r\n\r\n /** 广播当前状态 */\r\n function broadcast(): void {\r\n if (!channel) return\r\n try {\r\n channel.postMessage({\r\n type: 'state-update',\r\n payload: deepClone(state.value),\r\n timestamp: Date.now(),\r\n origin: originId,\r\n revision: ++revision,\r\n })\r\n } catch (e) {\r\n console.warn('[useSharedState] broadcast error:', e)\r\n }\r\n }\r\n\r\n /** 接收其他标签页的消息 */\r\n channel.onmessage = (event: MessageEvent) => {\r\n const msg = event.data\r\n if (!msg || typeof msg !== 'object') return\r\n\r\n if (msg.type === 'state-update') {\r\n if (msg.origin === originId) return\r\n\r\n const remoteRevision = typeof msg.revision === 'number' ? msg.revision : 0\r\n const previousRevision =\r\n latestRemoteRevision.get(String(msg.origin)) ?? -1\r\n if (remoteRevision <= previousRevision) return\r\n latestRemoteRevision.set(String(msg.origin), remoteRevision)\r\n\r\n pendingRemoteState = deepClone(msg.payload as T)\r\n hasPendingRemoteState = true\r\n state.value = pendingRemoteState\r\n lastSyncAt.value = msg.timestamp || Date.now()\r\n } else if (msg.type === 'ping') {\r\n channel?.postMessage({ type: 'pong' })\r\n } else if (msg.type === 'pong') {\r\n peerCount.value++\r\n }\r\n }\r\n\r\n /** 监听本地变化并广播 */\r\n const stopWatch = watch(\r\n state,\r\n () => {\r\n if (hasPendingRemoteState) {\r\n if (deepEqual(state.value, pendingRemoteState)) {\r\n hasPendingRemoteState = false\r\n return\r\n }\r\n hasPendingRemoteState = false\r\n }\r\n broadcast()\r\n },\r\n { deep }\r\n )\r\n\r\n /** 关闭通道 */\r\n function close(): void {\r\n stopWatch()\r\n if (channel) {\r\n channel.close()\r\n channel = null\r\n }\r\n }\r\n\r\n // 通知其他标签页本页存在\r\n if (immediate) {\r\n broadcast()\r\n }\r\n\r\n // 发送 ping 探测其他标签页\r\n if (channel) {\r\n peerCount.value = 0\r\n channel.postMessage({ type: 'ping' })\r\n }\r\n\r\n onUnmounted(() => {\r\n close()\r\n })\r\n\r\n return {\r\n state,\r\n broadcast,\r\n peerCount,\r\n lastSyncAt,\r\n close,\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAkEO,SAAS,eACd,aACA,cACA,UAAiC,CAAC,GACT;CACzB,MAAM,EAAE,YAAY,OAAO,OAAO,SAAS;CAE3C,MAAM,QAAQ,IAAO,UAAU,YAAY,CAAC;CAC5C,MAAM,YAAY,IAAI,CAAC;CACvB,MAAM,aAAa,IAAmB,IAAI;CAE1C,IAAI,UAAmC;CACvC,MAAM,WAAW,GAAG,KAAK,IAAI,EAAC,GAAI,KAAK,OAAO,CAAA,CAAE,SAAS,EAAE,CAAA,CAAE,MAAM,GAAG,EAAE;CACxE,IAAI,WAAW;CACf,MAAM,uCAAuB,IAAI,IAAoB;CACrD,IAAI;CACJ,IAAI,wBAAwB;CAG5B,IAAI,OAAO,qBAAqB,aAAa;EAC3C,QAAQ,KACN,qEACF;EACA,OAAO;GACL;GACA,iBAAiB,CAAC;GAClB;GACA;GACA,aAAa,CAAC;EAChB;CACF;CAEA,IAAI;EACF,UAAU,IAAI,iBAAiB,WAAW;CAC5C,SAAS,GAAG;EACV,QAAQ,KAAK,uDAAuD,CAAC;EACrE,OAAO;GACL;GACA,iBAAiB,CAAC;GAClB;GACA;GACA,aAAa,CAAC;EAChB;CACF;CAGA,SAAS,YAAkB;EACzB,IAAI,CAAC,SAAS;EACd,IAAI;GACF,QAAQ,YAAY;IAClB,MAAM;IACN,SAAS,UAAU,MAAM,KAAK;IAC9B,WAAW,KAAK,IAAI;IACpB,QAAQ;IACR,UAAU,EAAE;GACd,CAAC;EACH,SAAS,GAAG;GACV,QAAQ,KAAK,qCAAqC,CAAC;EACrD;CACF;CAGA,QAAQ,aAAa,UAAwB;EAC3C,MAAM,MAAM,MAAM;EAClB,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;EAErC,IAAI,IAAI,SAAS,gBAAgB;GAC/B,IAAI,IAAI,WAAW,UAAU;GAE7B,MAAM,iBAAiB,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;GAGzE,IAAI,mBADF,qBAAqB,IAAI,OAAO,IAAI,MAAM,CAAC,KAAK,KACV;GACxC,qBAAqB,IAAI,OAAO,IAAI,MAAM,GAAG,cAAc;GAE3D,qBAAqB,UAAU,IAAI,OAAY;GAC/C,wBAAwB;GACxB,MAAM,QAAQ;GACd,WAAW,QAAQ,IAAI,aAAa,KAAK,IAAI;EAC/C,OAAA,IAAW,IAAI,SAAS,QACtB,SAAS,YAAY,EAAE,MAAM,OAAO,CAAC;OACvC,IAAW,IAAI,SAAS,QACtB,UAAU;CAEd;CAGA,MAAM,YAAY,MAChB,aACM;EACJ,IAAI,uBAAuB;GACzB,IAAI,UAAU,MAAM,OAAO,kBAAkB,GAAG;IAC9C,wBAAwB;IACxB;GACF;GACA,wBAAwB;EAC1B;EACA,UAAU;CACZ,GACA,EAAE,KAAK,CACT;CAGA,SAAS,QAAc;EACrB,UAAU;EACV,IAAI,SAAS;GACX,QAAQ,MAAM;GACd,UAAU;EACZ;CACF;CAGA,IAAI,WACF,UAAU;CAIZ,IAAI,SAAS;EACX,UAAU,QAAQ;EAClB,QAAQ,YAAY,EAAE,MAAM,OAAO,CAAC;CACtC;CAEA,kBAAkB;EAChB,MAAM;CACR,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"useStore.js","names":[],"sources":["../../src/composables/useStore.ts"],"sourcesContent":["/**\n * useStore Composable\n *\n * 提供在组件中使用 Store 的便捷方法\n * @module composables/useStore\n */\n\nimport type { StoreGeneric } from 'pinia'\nimport type { Ref } from 'vue'\nimport { storeToRefs } from 'pinia'\nimport { computed, ref, watch } from 'vue'\n\n/**\n * useStore 选项\n */\nexport interface UseStoreOptions {\n /** 是否立即同步状态 */\n immediate?: boolean\n /** 是否深度监听 */\n deep?: boolean\n}\n\n/**\n * 通用 Store Hook\n *\n * 提供对 Pinia Store 的便捷访问\n *\n * @template T - Store 类型\n * @param useStoreHook - Pinia useStore hook\n * @param _options - 选项\n * @returns Store 包装对象\n *\n * @example\n * ```typescript\n * // 定义 Store\n * const useCounterStore = defineStore('counter', {\n * state: () => ({ count: 0 }),\n * actions: {\n * increment() { this.count++ }\n * }\n * })\n *\n * // 在组件中使用\n * const { store, refs, reset } = useStore(useCounterStore)\n *\n * // 访问响应式状态\n * console.log(refs.count.value)\n *\n * // 调用 action\n * store.increment()\n * ```\n */\nexport function useStore<T extends StoreGeneric>(\n useStoreHook: () => T,\n _options: UseStoreOptions = {},\n): {\n store: T\n refs: ReturnType<typeof storeToRefs<T>>\n reset: () => void\n patch: (partial: Partial<T> | ((state: T) => void)) => void\n} {\n const store = useStoreHook()\n\n // 获取响应式 refs\n const refs = storeToRefs(store)\n\n // 重置函数\n const reset = (): void => {\n if ('$reset' in store && typeof store.$reset === 'function') {\n (store.$reset as () => void)()\n }\n }\n\n // 批量更新函数\n const patch = (partial: Partial<T> | ((state: T) => void)): void => {\n if ('$patch' in store && typeof store.$patch === 'function') {\n (store.$patch as (partial: unknown) => void)(partial)\n }\n }\n\n return {\n store,\n refs,\n reset,\n patch,\n }\n}\n\n/**\n * 创建简单的响应式 Store\n *\n * 不依赖 Pinia,适用于简单场景\n *\n * @template S - 状态类型\n * @param initialState - 初始状态\n * @returns 响应式 Store\n *\n * @example\n * ```typescript\n * const { state, setState, reset } = useSimpleStore({\n * count: 0,\n * name: 'test'\n * })\n *\n * // 更新状态\n * setState({ count: 1 })\n *\n * // 重置\n * reset()\n * ```\n */\nexport function useSimpleStore<S extends Record<string, unknown>>(\n initialState: S,\n): {\n state: Ref<S>\n setState: (partial: Partial<S>) => void\n reset: () => void\n subscribe: (callback: (state: S) => void) => () => void\n} {\n const state = ref({ ...initialState }) as Ref<S>\n const initialStateCopy = { ...initialState }\n\n const setState = (partial: Partial<S>): void => {\n Object.assign(state.value, partial)\n }\n\n const reset = (): void => {\n state.value = { ...initialStateCopy } as S\n }\n\n const subscribe = (callback: (state: S) => void): (() => void) => {\n const stop = watch(\n state,\n (newState) => {\n callback(newState)\n },\n { deep: true },\n )\n return stop\n }\n\n return {\n state,\n setState,\n reset,\n subscribe,\n }\n}\n\n/**\n * 创建计算属性 Store\n *\n * @template S - 状态类型\n * @template G - Getters 类型\n * @param state - 状态\n * @param getters - 计算属性\n * @returns 带计算属性的 Store\n */\nexport function useComputedStore<\n S extends Record<string, unknown>,\n G extends Record<string, (state: S) => unknown>,\n>(\n state: Ref<S>,\n getters: G,\n): {\n state: Ref<S>\n getters: { [K in keyof G]: ReturnType<G[K]> }\n} {\n const computedGetters = {} as { [K in keyof G]: ReturnType<G[K]> }\n\n for (const key in getters) {\n (computedGetters as Record<string, unknown>)[key] = computed(() =>\n getters[key](state.value),\n )\n }\n\n return {\n state,\n getters: computedGetters,\n }\n}\n\n"],"mappings":";;;;;;;;;;;;AAoDO,SAAS,SACd,cACA,WAA4B,CAAC,GAM7B;CACA,MAAM,QAAQ,aAAa;CAG3B,MAAM,OAAO,YAAY,KAAK;CAG9B,MAAM,cAAoB;EACxB,IAAI,YAAY,SAAS,OAAO,MAAM,WAAW,YAC9C,MAAM,OAAsB;CAEjC;CAGA,MAAM,SAAS,YAAqD;EAClE,IAAI,YAAY,SAAS,OAAO,MAAM,WAAW,YAC9C,MAAM,OAAsC,OAAO;CAExD;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;AAyBO,SAAS,eACd,cAMA;CACA,MAAM,QAAQ,IAAI,EAAE,GAAG,aAAa,CAAC;CACrC,MAAM,mBAAmB,EAAE,GAAG,aAAa;CAE3C,MAAM,YAAY,YAA8B;EAC9C,OAAO,OAAO,MAAM,OAAO,OAAO;CACpC;CAEA,MAAM,cAAoB;EACxB,MAAM,QAAQ,EAAE,GAAG,iBAAiB;CACtC;CAEA,MAAM,aAAa,aAA+C;EAQhE,OAPa,MACX,QACC,aAAa;GACZ,SAAS,QAAQ;EACnB,GACA,EAAE,MAAM,KAAK,CAER;CACT;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;AAWO,SAAS,iBAId,OACA,SAIA;CACA,MAAM,kBAAkB,CAAC;CAEzB,KAAA,MAAW,OAAO,SACf,gBAA4C,OAAO,eAClD,QAAQ,IAAG,CAAE,MAAM,KAAK,CAC1B;CAGF,OAAO;EACL;EACA,SAAS;CACX;AACF"}
1
+ {"version":3,"file":"useStore.js","names":[],"sources":["../../src/composables/useStore.ts"],"sourcesContent":["/**\r\n * useStore Composable\r\n *\r\n * 提供在组件中使用 Store 的便捷方法\r\n * @module composables/useStore\r\n */\r\n\r\nimport type { StoreGeneric } from 'pinia'\r\nimport type { Ref } from 'vue'\r\nimport { storeToRefs } from 'pinia'\r\nimport { computed, ref, watch } from 'vue'\r\n\r\n/**\r\n * useStore 选项\r\n */\r\nexport interface UseStoreOptions {\r\n /** 是否立即同步状态 */\r\n immediate?: boolean\r\n /** 是否深度监听 */\r\n deep?: boolean\r\n}\r\n\r\n/**\r\n * 通用 Store Hook\r\n *\r\n * 提供对 Pinia Store 的便捷访问\r\n *\r\n * @template T - Store 类型\r\n * @param useStoreHook - Pinia useStore hook\r\n * @param _options - 选项\r\n * @returns Store 包装对象\r\n *\r\n * @example\r\n * ```typescript\r\n * // 定义 Store\r\n * const useCounterStore = defineStore('counter', {\r\n * state: () => ({ count: 0 }),\r\n * actions: {\r\n * increment() { this.count++ }\r\n * }\r\n * })\r\n *\r\n * // 在组件中使用\r\n * const { store, refs, reset } = useStore(useCounterStore)\r\n *\r\n * // 访问响应式状态\r\n * console.log(refs.count.value)\r\n *\r\n * // 调用 action\r\n * store.increment()\r\n * ```\r\n */\r\nexport function useStore<T extends StoreGeneric>(\r\n useStoreHook: () => T,\r\n _options: UseStoreOptions = {}\r\n): {\r\n store: T\r\n refs: ReturnType<typeof storeToRefs<T>>\r\n reset: () => void\r\n patch: (partial: Partial<T> | ((state: T) => void)) => void\r\n} {\r\n const store = useStoreHook()\r\n\r\n // 获取响应式 refs\r\n const refs = storeToRefs(store)\r\n\r\n // 重置函数\r\n const reset = (): void => {\r\n if ('$reset' in store && typeof store.$reset === 'function') {\r\n ;(store.$reset as () => void)()\r\n }\r\n }\r\n\r\n // 批量更新函数\r\n const patch = (partial: Partial<T> | ((state: T) => void)): void => {\r\n if ('$patch' in store && typeof store.$patch === 'function') {\r\n ;(store.$patch as (partial: unknown) => void)(partial)\r\n }\r\n }\r\n\r\n return {\r\n store,\r\n refs,\r\n reset,\r\n patch,\r\n }\r\n}\r\n\r\n/**\r\n * 创建简单的响应式 Store\r\n *\r\n * 不依赖 Pinia,适用于简单场景\r\n *\r\n * @template S - 状态类型\r\n * @param initialState - 初始状态\r\n * @returns 响应式 Store\r\n *\r\n * @example\r\n * ```typescript\r\n * const { state, setState, reset } = useSimpleStore({\r\n * count: 0,\r\n * name: 'test'\r\n * })\r\n *\r\n * // 更新状态\r\n * setState({ count: 1 })\r\n *\r\n * // 重置\r\n * reset()\r\n * ```\r\n */\r\nexport function useSimpleStore<S extends Record<string, unknown>>(\r\n initialState: S\r\n): {\r\n state: Ref<S>\r\n setState: (partial: Partial<S>) => void\r\n reset: () => void\r\n subscribe: (callback: (state: S) => void) => () => void\r\n} {\r\n const state = ref({ ...initialState }) as Ref<S>\r\n const initialStateCopy = { ...initialState }\r\n\r\n const setState = (partial: Partial<S>): void => {\r\n Object.assign(state.value, partial)\r\n }\r\n\r\n const reset = (): void => {\r\n state.value = { ...initialStateCopy } as S\r\n }\r\n\r\n const subscribe = (callback: (state: S) => void): (() => void) => {\r\n const stop = watch(\r\n state,\r\n newState => {\r\n callback(newState)\r\n },\r\n { deep: true }\r\n )\r\n return stop\r\n }\r\n\r\n return {\r\n state,\r\n setState,\r\n reset,\r\n subscribe,\r\n }\r\n}\r\n\r\n/**\r\n * 创建计算属性 Store\r\n *\r\n * @template S - 状态类型\r\n * @template G - Getters 类型\r\n * @param state - 状态\r\n * @param getters - 计算属性\r\n * @returns 带计算属性的 Store\r\n */\r\nexport function useComputedStore<\r\n S extends Record<string, unknown>,\r\n G extends Record<string, (state: S) => unknown>,\r\n>(\r\n state: Ref<S>,\r\n getters: G\r\n): {\r\n state: Ref<S>\r\n getters: { [K in keyof G]: ReturnType<G[K]> }\r\n} {\r\n const computedGetters = {} as { [K in keyof G]: ReturnType<G[K]> }\r\n\r\n for (const key in getters) {\r\n ;(computedGetters as Record<string, unknown>)[key] = computed(() =>\r\n getters[key](state.value)\r\n )\r\n }\r\n\r\n return {\r\n state,\r\n getters: computedGetters,\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAoDO,SAAS,SACd,cACA,WAA4B,CAAC,GAM7B;CACA,MAAM,QAAQ,aAAa;CAG3B,MAAM,OAAO,YAAY,KAAK;CAG9B,MAAM,cAAoB;EACxB,IAAI,YAAY,SAAS,OAAO,MAAM,WAAW,YAC7C,MAAM,OAAsB;CAElC;CAGA,MAAM,SAAS,YAAqD;EAClE,IAAI,YAAY,SAAS,OAAO,MAAM,WAAW,YAC7C,MAAM,OAAsC,OAAO;CAEzD;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;AAyBO,SAAS,eACd,cAMA;CACA,MAAM,QAAQ,IAAI,EAAE,GAAG,aAAa,CAAC;CACrC,MAAM,mBAAmB,EAAE,GAAG,aAAa;CAE3C,MAAM,YAAY,YAA8B;EAC9C,OAAO,OAAO,MAAM,OAAO,OAAO;CACpC;CAEA,MAAM,cAAoB;EACxB,MAAM,QAAQ,EAAE,GAAG,iBAAiB;CACtC;CAEA,MAAM,aAAa,aAA+C;EAQhE,OAPa,MACX,QACA,aAAY;GACV,SAAS,QAAQ;EACnB,GACA,EAAE,MAAM,KAAK,CAER;CACT;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF;AAWO,SAAS,iBAId,OACA,SAIA;CACA,MAAM,kBAAkB,CAAC;CAEzB,KAAA,MAAW,OAAO,SACd,gBAA4C,OAAO,eACnD,QAAQ,IAAG,CAAE,MAAM,KAAK,CAC1B;CAGF,OAAO;EACL;EACA,SAAS;CACX;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useStoreDevtools.d.ts","sourceRoot":"","sources":["../../src/composables/useStoreDevtools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAe9B,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAA;IACxB,QAAQ,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAA;IAC9B,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC7D,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAwBD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE;IACxC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,sBAAsB,CAkH9B"}
1
+ {"version":3,"file":"useStoreDevtools.d.ts","sourceRoot":"","sources":["../../src/composables/useStoreDevtools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAe9B,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAA;IACxB,QAAQ,EAAE,GAAG,CAAC,aAAa,EAAE,CAAC,CAAA;IAC9B,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC1B,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC7D,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACnC,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAwBD,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE;IACP;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CAClB,GACL,sBAAsB,CAkHxB"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"useStoreDevtools.js","names":[],"sources":["../../src/composables/useStoreDevtools.ts"],"sourcesContent":["import type { EventData } from '@composy/store-core'\nimport type { Pinia, StoreGeneric } from 'pinia'\nimport type { Ref } from 'vue'\nimport { deepClone, globalEventBus } from '@composy/store-core'\nimport { getActivePinia } from 'pinia'\nimport { onUnmounted, ref } from 'vue'\n\nconst STORE_REFRESH_EVENTS = new Set([\n 'store:created',\n 'store:disposed',\n 'state:changed',\n])\n\ntype PiniaWithStores = Pinia & {\n _s?: Map<string, StoreGeneric>\n}\n\nexport interface StoreInfo {\n id: string\n state: Record<string, unknown>\n active: boolean\n}\n\nexport interface EventLogEntry {\n type: string\n payload: unknown\n timestamp: number\n time: string\n}\n\nexport interface UseStoreDevtoolsReturn {\n stores: Ref<StoreInfo[]>\n eventLog: Ref<EventLogEntry[]>\n isMonitoring: Ref<boolean>\n startMonitoring: () => void\n stopMonitoring: () => void\n clearLog: () => void\n refreshStores: () => void\n getStoreState: (id: string) => Record<string, unknown> | null\n resetStore: (id: string) => boolean\n resetAllStores: () => void\n}\n\nfunction formatTime(timestamp: number): string {\n const date = new Date(timestamp)\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 milliseconds = date.getMilliseconds().toString().padStart(3, '0')\n\n return `${hours}:${minutes}:${seconds}.${milliseconds}`\n}\n\nfunction getPinia(): PiniaWithStores | null {\n return (getActivePinia() ?? null) as PiniaWithStores | null\n}\n\nfunction snapshotStore(store: StoreGeneric, id: string): StoreInfo {\n return {\n id,\n state: deepClone(store.$state),\n active: true,\n }\n}\n\nexport function useStoreDevtools(options: {\n /**\n * 最多保留多少条事件日志。\n */\n maxLogEntries?: number\n} = {}): UseStoreDevtoolsReturn {\n const { maxLogEntries = 200 } = options\n\n const stores = ref<StoreInfo[]>([])\n const eventLog = ref<EventLogEntry[]>([])\n const isMonitoring = ref(false)\n\n let unsubscribe: (() => void) | null = null\n\n function refreshStores(): void {\n const pinia = getPinia()\n if (!pinia?._s) {\n stores.value = []\n return\n }\n\n stores.value = Array.from(pinia._s.entries(), ([id, store]) => {\n return snapshotStore(store, id)\n })\n }\n\n function startMonitoring(): void {\n if (isMonitoring.value) {\n return\n }\n\n isMonitoring.value = true\n unsubscribe = globalEventBus.on('*', (data: EventData) => {\n const entry: EventLogEntry = {\n type: data.type,\n payload: data.payload,\n timestamp: data.timestamp,\n time: formatTime(data.timestamp),\n }\n\n eventLog.value = [entry, ...eventLog.value].slice(0, maxLogEntries)\n\n if (STORE_REFRESH_EVENTS.has(data.type)) {\n refreshStores()\n }\n })\n }\n\n function stopMonitoring(): void {\n if (!isMonitoring.value) {\n return\n }\n\n isMonitoring.value = false\n unsubscribe?.()\n unsubscribe = null\n }\n\n function clearLog(): void {\n eventLog.value = []\n }\n\n function getStoreState(id: string): Record<string, unknown> | null {\n const pinia = getPinia()\n const store = pinia?._s?.get(id)\n\n if (!store) {\n return null\n }\n\n return deepClone(store.$state)\n }\n\n function resetStore(id: string): boolean {\n const pinia = getPinia()\n const store = pinia?._s?.get(id)\n\n if (!store || typeof store.$reset !== 'function') {\n return false\n }\n\n store.$reset()\n refreshStores()\n return true\n }\n\n function resetAllStores(): void {\n const pinia = getPinia()\n if (!pinia?._s) {\n return\n }\n\n pinia._s.forEach((store) => {\n if (typeof store.$reset === 'function') {\n store.$reset()\n }\n })\n\n refreshStores()\n }\n\n refreshStores()\n\n onUnmounted(() => {\n stopMonitoring()\n })\n\n return {\n stores,\n eventLog,\n isMonitoring,\n startMonitoring,\n stopMonitoring,\n clearLog,\n refreshStores,\n getStoreState,\n resetStore,\n resetAllStores,\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAOA,MAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;AACF,CAAC;AAgCD,SAAS,WAAW,WAA2B;CAC7C,MAAM,OAAO,IAAI,KAAK,SAAS;CAM/B,OAAO,GALO,KAAK,SAAS,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAK3C,EAAK,GAJC,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAItC,EAAO,GAHV,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAG3B,EAAO,GAFhB,KAAK,gBAAgB,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAE1B;AAC3C;AAEA,SAAS,WAAmC;CAC1C,OAAQ,eAAe,KAAK;AAC9B;AAEA,SAAS,cAAc,OAAqB,IAAuB;CACjE,OAAO;EACL;EACA,OAAO,UAAU,MAAM,MAAM;EAC7B,QAAQ;CACV;AACF;AAEO,SAAS,iBAAiB,UAK7B,CAAC,GAA2B;CAC9B,MAAM,EAAE,gBAAgB,QAAQ;CAEhC,MAAM,SAAS,IAAiB,CAAC,CAAC;CAClC,MAAM,WAAW,IAAqB,CAAC,CAAC;CACxC,MAAM,eAAe,IAAI,KAAK;CAE9B,IAAI,cAAmC;CAEvC,SAAS,gBAAsB;EAC7B,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO,IAAI;GACd,OAAO,QAAQ,CAAC;GAChB;EACF;EAEA,OAAO,QAAQ,MAAM,KAAK,MAAM,GAAG,QAAQ,IAAI,CAAC,IAAI,WAAW;GAC7D,OAAO,cAAc,OAAO,EAAE;EAChC,CAAC;CACH;CAEA,SAAS,kBAAwB;EAC/B,IAAI,aAAa,OACf;EAGF,aAAa,QAAQ;EACrB,cAAc,eAAe,GAAG,MAAM,SAAoB;GACxD,MAAM,QAAuB;IAC3B,MAAM,KAAK;IACX,SAAS,KAAK;IACd,WAAW,KAAK;IAChB,MAAM,WAAW,KAAK,SAAS;GACjC;GAEA,SAAS,QAAQ,CAAC,OAAO,GAAG,SAAS,KAAK,CAAA,CAAE,MAAM,GAAG,aAAa;GAElE,IAAI,qBAAqB,IAAI,KAAK,IAAI,GACpC,cAAc;EAElB,CAAC;CACH;CAEA,SAAS,iBAAuB;EAC9B,IAAI,CAAC,aAAa,OAChB;EAGF,aAAa,QAAQ;EACrB,cAAc;EACd,cAAc;CAChB;CAEA,SAAS,WAAiB;EACxB,SAAS,QAAQ,CAAC;CACpB;CAEA,SAAS,cAAc,IAA4C;EAEjE,MAAM,QADQ,SACA,CAAA,EAAO,IAAI,IAAI,EAAE;EAE/B,IAAI,CAAC,OACH,OAAO;EAGT,OAAO,UAAU,MAAM,MAAM;CAC/B;CAEA,SAAS,WAAW,IAAqB;EAEvC,MAAM,QADQ,SACA,CAAA,EAAO,IAAI,IAAI,EAAE;EAE/B,IAAI,CAAC,SAAS,OAAO,MAAM,WAAW,YACpC,OAAO;EAGT,MAAM,OAAO;EACb,cAAc;EACd,OAAO;CACT;CAEA,SAAS,iBAAuB;EAC9B,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO,IACV;EAGF,MAAM,GAAG,SAAS,UAAU;GAC1B,IAAI,OAAO,MAAM,WAAW,YAC1B,MAAM,OAAO;EAEjB,CAAC;EAED,cAAc;CAChB;CAEA,cAAc;CAEd,kBAAkB;EAChB,eAAe;CACjB,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"useStoreDevtools.js","names":[],"sources":["../../src/composables/useStoreDevtools.ts"],"sourcesContent":["import type { EventData } from '@composy/store-core'\r\nimport type { Pinia, StoreGeneric } from 'pinia'\r\nimport type { Ref } from 'vue'\r\nimport { deepClone, globalEventBus } from '@composy/store-core'\r\nimport { getActivePinia } from 'pinia'\r\nimport { onUnmounted, ref } from 'vue'\r\n\r\nconst STORE_REFRESH_EVENTS = new Set([\r\n 'store:created',\r\n 'store:disposed',\r\n 'state:changed',\r\n])\r\n\r\ntype PiniaWithStores = Pinia & {\r\n _s?: Map<string, StoreGeneric>\r\n}\r\n\r\nexport interface StoreInfo {\r\n id: string\r\n state: Record<string, unknown>\r\n active: boolean\r\n}\r\n\r\nexport interface EventLogEntry {\r\n type: string\r\n payload: unknown\r\n timestamp: number\r\n time: string\r\n}\r\n\r\nexport interface UseStoreDevtoolsReturn {\r\n stores: Ref<StoreInfo[]>\r\n eventLog: Ref<EventLogEntry[]>\r\n isMonitoring: Ref<boolean>\r\n startMonitoring: () => void\r\n stopMonitoring: () => void\r\n clearLog: () => void\r\n refreshStores: () => void\r\n getStoreState: (id: string) => Record<string, unknown> | null\r\n resetStore: (id: string) => boolean\r\n resetAllStores: () => void\r\n}\r\n\r\nfunction formatTime(timestamp: number): string {\r\n const date = new Date(timestamp)\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 milliseconds = date.getMilliseconds().toString().padStart(3, '0')\r\n\r\n return `${hours}:${minutes}:${seconds}.${milliseconds}`\r\n}\r\n\r\nfunction getPinia(): PiniaWithStores | null {\r\n return (getActivePinia() ?? null) as PiniaWithStores | null\r\n}\r\n\r\nfunction snapshotStore(store: StoreGeneric, id: string): StoreInfo {\r\n return {\r\n id,\r\n state: deepClone(store.$state),\r\n active: true,\r\n }\r\n}\r\n\r\nexport function useStoreDevtools(\r\n options: {\r\n /**\r\n * 最多保留多少条事件日志。\r\n */\r\n maxLogEntries?: number\r\n } = {}\r\n): UseStoreDevtoolsReturn {\r\n const { maxLogEntries = 200 } = options\r\n\r\n const stores = ref<StoreInfo[]>([])\r\n const eventLog = ref<EventLogEntry[]>([])\r\n const isMonitoring = ref(false)\r\n\r\n let unsubscribe: (() => void) | null = null\r\n\r\n function refreshStores(): void {\r\n const pinia = getPinia()\r\n if (!pinia?._s) {\r\n stores.value = []\r\n return\r\n }\r\n\r\n stores.value = Array.from(pinia._s.entries(), ([id, store]) => {\r\n return snapshotStore(store, id)\r\n })\r\n }\r\n\r\n function startMonitoring(): void {\r\n if (isMonitoring.value) {\r\n return\r\n }\r\n\r\n isMonitoring.value = true\r\n unsubscribe = globalEventBus.on('*', (data: EventData) => {\r\n const entry: EventLogEntry = {\r\n type: data.type,\r\n payload: data.payload,\r\n timestamp: data.timestamp,\r\n time: formatTime(data.timestamp),\r\n }\r\n\r\n eventLog.value = [entry, ...eventLog.value].slice(0, maxLogEntries)\r\n\r\n if (STORE_REFRESH_EVENTS.has(data.type)) {\r\n refreshStores()\r\n }\r\n })\r\n }\r\n\r\n function stopMonitoring(): void {\r\n if (!isMonitoring.value) {\r\n return\r\n }\r\n\r\n isMonitoring.value = false\r\n unsubscribe?.()\r\n unsubscribe = null\r\n }\r\n\r\n function clearLog(): void {\r\n eventLog.value = []\r\n }\r\n\r\n function getStoreState(id: string): Record<string, unknown> | null {\r\n const pinia = getPinia()\r\n const store = pinia?._s?.get(id)\r\n\r\n if (!store) {\r\n return null\r\n }\r\n\r\n return deepClone(store.$state)\r\n }\r\n\r\n function resetStore(id: string): boolean {\r\n const pinia = getPinia()\r\n const store = pinia?._s?.get(id)\r\n\r\n if (!store || typeof store.$reset !== 'function') {\r\n return false\r\n }\r\n\r\n store.$reset()\r\n refreshStores()\r\n return true\r\n }\r\n\r\n function resetAllStores(): void {\r\n const pinia = getPinia()\r\n if (!pinia?._s) {\r\n return\r\n }\r\n\r\n pinia._s.forEach(store => {\r\n if (typeof store.$reset === 'function') {\r\n store.$reset()\r\n }\r\n })\r\n\r\n refreshStores()\r\n }\r\n\r\n refreshStores()\r\n\r\n onUnmounted(() => {\r\n stopMonitoring()\r\n })\r\n\r\n return {\r\n stores,\r\n eventLog,\r\n isMonitoring,\r\n startMonitoring,\r\n stopMonitoring,\r\n clearLog,\r\n refreshStores,\r\n getStoreState,\r\n resetStore,\r\n resetAllStores,\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;AAOA,MAAM,uCAAuB,IAAI,IAAI;CACnC;CACA;CACA;AACF,CAAC;AAgCD,SAAS,WAAW,WAA2B;CAC7C,MAAM,OAAO,IAAI,KAAK,SAAS;CAM/B,OAAO,GALO,KAAK,SAAS,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAK3C,EAAK,GAJC,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAItC,EAAO,GAHV,KAAK,WAAW,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAG3B,EAAO,GAFhB,KAAK,gBAAgB,CAAA,CAAE,SAAS,CAAA,CAAE,SAAS,GAAG,GAE1B;AAC3C;AAEA,SAAS,WAAmC;CAC1C,OAAQ,eAAe,KAAK;AAC9B;AAEA,SAAS,cAAc,OAAqB,IAAuB;CACjE,OAAO;EACL;EACA,OAAO,UAAU,MAAM,MAAM;EAC7B,QAAQ;CACV;AACF;AAEO,SAAS,iBACd,UAKI,CAAC,GACmB;CACxB,MAAM,EAAE,gBAAgB,QAAQ;CAEhC,MAAM,SAAS,IAAiB,CAAC,CAAC;CAClC,MAAM,WAAW,IAAqB,CAAC,CAAC;CACxC,MAAM,eAAe,IAAI,KAAK;CAE9B,IAAI,cAAmC;CAEvC,SAAS,gBAAsB;EAC7B,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO,IAAI;GACd,OAAO,QAAQ,CAAC;GAChB;EACF;EAEA,OAAO,QAAQ,MAAM,KAAK,MAAM,GAAG,QAAQ,IAAI,CAAC,IAAI,WAAW;GAC7D,OAAO,cAAc,OAAO,EAAE;EAChC,CAAC;CACH;CAEA,SAAS,kBAAwB;EAC/B,IAAI,aAAa,OACf;EAGF,aAAa,QAAQ;EACrB,cAAc,eAAe,GAAG,MAAM,SAAoB;GACxD,MAAM,QAAuB;IAC3B,MAAM,KAAK;IACX,SAAS,KAAK;IACd,WAAW,KAAK;IAChB,MAAM,WAAW,KAAK,SAAS;GACjC;GAEA,SAAS,QAAQ,CAAC,OAAO,GAAG,SAAS,KAAK,CAAA,CAAE,MAAM,GAAG,aAAa;GAElE,IAAI,qBAAqB,IAAI,KAAK,IAAI,GACpC,cAAc;EAElB,CAAC;CACH;CAEA,SAAS,iBAAuB;EAC9B,IAAI,CAAC,aAAa,OAChB;EAGF,aAAa,QAAQ;EACrB,cAAc;EACd,cAAc;CAChB;CAEA,SAAS,WAAiB;EACxB,SAAS,QAAQ,CAAC;CACpB;CAEA,SAAS,cAAc,IAA4C;EAEjE,MAAM,QADQ,SACA,CAAA,EAAO,IAAI,IAAI,EAAE;EAE/B,IAAI,CAAC,OACH,OAAO;EAGT,OAAO,UAAU,MAAM,MAAM;CAC/B;CAEA,SAAS,WAAW,IAAqB;EAEvC,MAAM,QADQ,SACA,CAAA,EAAO,IAAI,IAAI,EAAE;EAE/B,IAAI,CAAC,SAAS,OAAO,MAAM,WAAW,YACpC,OAAO;EAGT,MAAM,OAAO;EACb,cAAc;EACd,OAAO;CACT;CAEA,SAAS,iBAAuB;EAC9B,MAAM,QAAQ,SAAS;EACvB,IAAI,CAAC,OAAO,IACV;EAGF,MAAM,GAAG,SAAQ,UAAS;GACxB,IAAI,OAAO,MAAM,WAAW,YAC1B,MAAM,OAAO;EAEjB,CAAC;EAED,cAAc;CAChB;CAEA,cAAc;CAEd,kBAAkB;EAChB,eAAe;CACjB,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useStoreSnapshot.d.ts","sourceRoot":"","sources":["../../src/composables/useStoreSnapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAE,GAAG,EAAC,MAAM,KAAK,CAAC;AAI1C;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,YAAY;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,WAAW;IACX,KAAK,EAAE,CAAC,CAAA;IACR,UAAU;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS;IACT,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS;IACT,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW;IACX,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,mBAAmB;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,WAAW;IACX,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,aAAa;IACb,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzB,aAAa;IACb,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,aAAa;IACb,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,WAAW;IACX,YAAY,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CAAA;IAClF,WAAW;IACX,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACxC,SAAS;IACT,IAAI,EAAE,MAAM,OAAO,CAAA;IACnB,SAAS;IACT,IAAI,EAAE,MAAM,OAAO,CAAA;IACnB,cAAc;IACd,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IAChC,WAAW;IACX,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,aAAa;IACb,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,SAAS,EAAE,CAAA;IAClE,WAAW;IACX,eAAe,EAAE,MAAM,MAAM,CAAA;IAC7B,WAAW;IACX,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAC3C;AAmHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAAC,CAAC,CAAC,CAuO3B"}
1
+ {"version":3,"file":"useStoreSnapshot.d.ts","sourceRoot":"","sources":["../../src/composables/useStoreSnapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAI3C;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,YAAY;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,WAAW;IACX,KAAK,EAAE,CAAC,CAAA;IACR,UAAU;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU;IACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS;IACT,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS;IACT,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW;IACX,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa;IACb,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,mBAAmB;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACvC,WAAW;IACX,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,aAAa;IACb,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACzB,aAAa;IACb,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,aAAa;IACb,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC7B,WAAW;IACX,YAAY,EAAE,CACZ,KAAK,CAAC,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC3B,aAAa,CAAC,CAAC,CAAC,CAAA;IACrB,WAAW;IACX,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAA;IACxC,SAAS;IACT,IAAI,EAAE,MAAM,OAAO,CAAA;IACnB,SAAS;IACT,IAAI,EAAE,MAAM,OAAO,CAAA;IACnB,cAAc;IACd,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IAChC,WAAW;IACX,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,aAAa;IACb,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,SAAS,EAAE,CAAA;IAClE,WAAW;IACX,eAAe,EAAE,MAAM,MAAM,CAAA;IAC7B,WAAW;IACX,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAC3C;AA6GD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC5B,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAAC,CAAC,CAAC,CAkP3B"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -76,6 +76,7 @@ function useStoreSnapshot(state, setState, options = {}) {
76
76
  const currentIndex = ref(-1);
77
77
  let debounceTimer;
78
78
  let isRestoring = false;
79
+ let previousAutoRecordState;
79
80
  const getState = () => {
80
81
  return typeof state === "function" ? state() : state.value;
81
82
  };
@@ -106,6 +107,7 @@ function useStoreSnapshot(state, setState, options = {}) {
106
107
  try {
107
108
  setState(deepClone(snapshots.value[index].state));
108
109
  currentIndex.value = index;
110
+ previousAutoRecordState = deepClone(getState());
109
111
  return true;
110
112
  } finally {
111
113
  isRestoring = false;
@@ -113,10 +115,12 @@ function useStoreSnapshot(state, setState, options = {}) {
113
115
  };
114
116
  const undo = () => {
115
117
  if (!canUndo.value) return false;
116
- currentIndex.value--;
118
+ const targetIndex = currentIndex.value - 1;
117
119
  isRestoring = true;
118
120
  try {
119
- setState(deepClone(snapshots.value[currentIndex.value].state));
121
+ setState(deepClone(snapshots.value[targetIndex].state));
122
+ currentIndex.value = targetIndex;
123
+ previousAutoRecordState = deepClone(getState());
120
124
  return true;
121
125
  } finally {
122
126
  isRestoring = false;
@@ -124,10 +128,12 @@ function useStoreSnapshot(state, setState, options = {}) {
124
128
  };
125
129
  const redo = () => {
126
130
  if (!canRedo.value) return false;
127
- currentIndex.value++;
131
+ const targetIndex = currentIndex.value + 1;
128
132
  isRestoring = true;
129
133
  try {
130
- setState(deepClone(snapshots.value[currentIndex.value].state));
134
+ setState(deepClone(snapshots.value[targetIndex].state));
135
+ currentIndex.value = targetIndex;
136
+ previousAutoRecordState = deepClone(getState());
131
137
  return true;
132
138
  } finally {
133
139
  isRestoring = false;
@@ -135,10 +141,11 @@ function useStoreSnapshot(state, setState, options = {}) {
135
141
  };
136
142
  const goto = (index) => {
137
143
  if (index < 0 || index >= snapshots.value.length) return false;
138
- currentIndex.value = index;
139
144
  isRestoring = true;
140
145
  try {
141
146
  setState(deepClone(snapshots.value[index].state));
147
+ currentIndex.value = index;
148
+ previousAutoRecordState = deepClone(getState());
142
149
  return true;
143
150
  } finally {
144
151
  isRestoring = false;
@@ -173,9 +180,12 @@ function useStoreSnapshot(state, setState, options = {}) {
173
180
  }
174
181
  };
175
182
  if (autoRecord) {
176
- const stopWatch = watch(typeof state === "function" ? computed(state) : state, (newState, oldState) => {
183
+ const stateRef = typeof state === "function" ? computed(state) : state;
184
+ previousAutoRecordState = deepClone(getState());
185
+ const stopWatch = watch(stateRef, (newState, oldState) => {
177
186
  if (isRestoring) return;
178
- if (deepEqual(newState, oldState)) return;
187
+ if (deepEqual(newState, previousAutoRecordState ?? oldState)) return;
188
+ previousAutoRecordState = deepClone(newState);
179
189
  if (debounceTimer) clearTimeout(debounceTimer);
180
190
  debounceTimer = setTimeout(() => {
181
191
  takeSnapshot();
@@ -1 +1 @@
1
- {"version":3,"file":"useStoreSnapshot.js","names":[],"sources":["../../src/composables/useStoreSnapshot.ts"],"sourcesContent":["/**\n * useStoreSnapshot - Store 状态快照工具\n *\n * 提供状态快照、历史记录和调试功能\n * @module composables/useStoreSnapshot\n */\n\nimport type {ComputedRef, Ref} from 'vue';\nimport { deepClone, deepEqual } from '@composy/store-core'\nimport { computed, onUnmounted, ref, watch } from 'vue'\n\n/**\n * 状态快照\n */\nexport interface StateSnapshot<S = unknown> {\n /** 快照 ID */\n id: string\n /** 状态数据 */\n state: S\n /** 时间戳 */\n timestamp: number\n /** 快照标签 */\n label?: string\n /** 元数据 */\n meta?: Record<string, unknown>\n}\n\n/**\n * 状态差异\n */\nexport interface StateDiff {\n /** 差异路径 */\n path: string\n /** 旧值 */\n oldValue: unknown\n /** 新值 */\n newValue: unknown\n /** 差异类型 */\n type: 'add' | 'remove' | 'change'\n}\n\n/**\n * useStoreSnapshot 选项\n */\nexport interface UseStoreSnapshotOptions {\n /** 最大快照数量 */\n maxSnapshots?: number\n /** 是否自动记录 */\n autoRecord?: boolean\n /** 自动记录防抖延迟(毫秒) */\n debounceMs?: number\n /** 是否深度监听 */\n deep?: boolean\n}\n\n/**\n * useStoreSnapshot 返回值\n */\nexport interface UseStoreSnapshotReturn<S> {\n /** 快照列表 */\n snapshots: Ref<Array<StateSnapshot<S>>>\n /** 当前快照索引 */\n currentIndex: Ref<number>\n /** 是否可以撤销 */\n canUndo: ComputedRef<boolean>\n /** 是否可以重做 */\n canRedo: ComputedRef<boolean>\n /** 创建快照 */\n takeSnapshot: (label?: string, meta?: Record<string, unknown>) => StateSnapshot<S>\n /** 恢复快照 */\n restoreSnapshot: (id: string) => boolean\n /** 撤销 */\n undo: () => boolean\n /** 重做 */\n redo: () => boolean\n /** 跳转到指定快照 */\n goto: (index: number) => boolean\n /** 清空快照 */\n clearSnapshots: () => void\n /** 获取状态差异 */\n getDiff: (snapshotId1: string, snapshotId2: string) => StateDiff[]\n /** 导出快照 */\n exportSnapshots: () => string\n /** 导入快照 */\n importSnapshots: (data: string) => boolean\n}\n\n/**\n * 生成唯一 ID\n */\nfunction generateId(): string {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n}\n\n/**\n * 计算两个对象的差异\n */\nfunction computeDiff(\n oldObj: unknown,\n newObj: unknown,\n path = '',\n): StateDiff[] {\n const diffs: StateDiff[] = []\n\n // 类型不同\n if (typeof oldObj !== typeof newObj) {\n diffs.push({\n path: path || '.',\n oldValue: oldObj,\n newValue: newObj,\n type: 'change',\n })\n return diffs\n }\n\n // 基础类型比较\n if (typeof oldObj !== 'object' || oldObj === null || newObj === null) {\n if (!Object.is(oldObj, newObj)) {\n diffs.push({\n path: path || '.',\n oldValue: oldObj,\n newValue: newObj,\n type: 'change',\n })\n }\n return diffs\n }\n\n // 数组比较\n if (Array.isArray(oldObj) && Array.isArray(newObj)) {\n const maxLen = Math.max(oldObj.length, newObj.length)\n for (let i = 0; i < maxLen; i++) {\n const itemPath = path ? `${path}[${i}]` : `[${i}]`\n if (i >= oldObj.length) {\n diffs.push({\n path: itemPath,\n oldValue: undefined,\n newValue: newObj[i],\n type: 'add',\n })\n }\n else if (i >= newObj.length) {\n diffs.push({\n path: itemPath,\n oldValue: oldObj[i],\n newValue: undefined,\n type: 'remove',\n })\n }\n else {\n diffs.push(...computeDiff(oldObj[i], newObj[i], itemPath))\n }\n }\n return diffs\n }\n\n // 对象比较\n const oldKeys = new Set(Object.keys(oldObj as Record<string, unknown>))\n const newKeys = new Set(Object.keys(newObj as Record<string, unknown>))\n\n // 检查新增的键\n for (const key of newKeys) {\n if (!oldKeys.has(key)) {\n diffs.push({\n path: path ? `${path}.${key}` : key,\n oldValue: undefined,\n newValue: (newObj as Record<string, unknown>)[key],\n type: 'add',\n })\n }\n }\n\n // 检查删除的键\n for (const key of oldKeys) {\n if (!newKeys.has(key)) {\n diffs.push({\n path: path ? `${path}.${key}` : key,\n oldValue: (oldObj as Record<string, unknown>)[key],\n newValue: undefined,\n type: 'remove',\n })\n }\n }\n\n // 检查修改的键\n for (const key of oldKeys) {\n if (newKeys.has(key)) {\n diffs.push(\n ...computeDiff(\n (oldObj as Record<string, unknown>)[key],\n (newObj as Record<string, unknown>)[key],\n path ? `${path}.${key}` : key,\n ),\n )\n }\n }\n\n return diffs\n}\n\n/**\n * Store 状态快照 Hook\n *\n * 提供状态快照、撤销/重做和调试功能\n *\n * @template S - 状态类型\n * @param state - 响应式状态\n * @param setState - 状态设置函数\n * @param options - 配置选项\n * @returns 快照操作对象\n *\n * @example\n * ```typescript\n * const store = useCounterStore()\n *\n * const {\n * snapshots,\n * canUndo,\n * canRedo,\n * takeSnapshot,\n * undo,\n * redo,\n * getDiff\n * } = useStoreSnapshot(\n * () => store.$state,\n * (state) => store.$patch(state),\n * { maxSnapshots: 50, autoRecord: true }\n * )\n *\n * // 手动创建快照\n * takeSnapshot('保存点 1')\n *\n * // 撤销操作\n * if (canUndo.value) {\n * undo()\n * }\n *\n * // 获取状态差异\n * const diff = getDiff(snapshots.value[0].id, snapshots.value[1].id)\n * ```\n */\nexport function useStoreSnapshot<S>(\n state: Ref<S> | (() => S),\n setState: (state: S) => void,\n options: UseStoreSnapshotOptions = {},\n): UseStoreSnapshotReturn<S> {\n const {\n maxSnapshots = 100,\n autoRecord = false,\n debounceMs = 300,\n deep = true,\n } = options\n\n const snapshots = ref<Array<StateSnapshot<S>>>([]) as Ref<Array<StateSnapshot<S>>>\n const currentIndex = ref(-1)\n let debounceTimer: ReturnType<typeof setTimeout> | undefined\n let isRestoring = false\n\n // 获取当前状态\n const getState = (): S => {\n return typeof state === 'function' ? state() : state.value\n }\n\n // 是否可以撤销\n const canUndo = computed(() => currentIndex.value > 0)\n\n // 是否可以重做\n const canRedo = computed(() => currentIndex.value < snapshots.value.length - 1)\n\n /**\n * 创建快照\n */\n const takeSnapshot = (label?: string, meta?: Record<string, unknown>): StateSnapshot<S> => {\n const currentState = getState()\n const snapshot: StateSnapshot<S> = {\n id: generateId(),\n state: deepClone(currentState),\n timestamp: Date.now(),\n label,\n meta,\n }\n\n // 如果当前不在最新位置,删除后面的快照\n if (currentIndex.value < snapshots.value.length - 1) {\n snapshots.value = snapshots.value.slice(0, currentIndex.value + 1)\n }\n\n // 添加新快照\n snapshots.value.push(snapshot)\n currentIndex.value = snapshots.value.length - 1\n\n // 限制快照数量\n if (snapshots.value.length > maxSnapshots) {\n snapshots.value.shift()\n currentIndex.value--\n }\n\n return snapshot\n }\n\n /**\n * 恢复快照\n */\n const restoreSnapshot = (id: string): boolean => {\n const index = snapshots.value.findIndex(s => s.id === id)\n if (index === -1) return false\n\n isRestoring = true\n try {\n setState(deepClone(snapshots.value[index].state))\n currentIndex.value = index\n return true\n }\n finally {\n isRestoring = false\n }\n }\n\n /**\n * 撤销\n */\n const undo = (): boolean => {\n if (!canUndo.value) return false\n\n currentIndex.value--\n isRestoring = true\n try {\n setState(deepClone(snapshots.value[currentIndex.value].state))\n return true\n }\n finally {\n isRestoring = false\n }\n }\n\n /**\n * 重做\n */\n const redo = (): boolean => {\n if (!canRedo.value) return false\n\n currentIndex.value++\n isRestoring = true\n try {\n setState(deepClone(snapshots.value[currentIndex.value].state))\n return true\n }\n finally {\n isRestoring = false\n }\n }\n\n /**\n * 跳转到指定快照\n */\n const goto = (index: number): boolean => {\n if (index < 0 || index >= snapshots.value.length) return false\n\n currentIndex.value = index\n isRestoring = true\n try {\n setState(deepClone(snapshots.value[index].state))\n return true\n }\n finally {\n isRestoring = false\n }\n }\n\n /**\n * 清空快照\n */\n const clearSnapshots = (): void => {\n snapshots.value = []\n currentIndex.value = -1\n }\n\n /**\n * 获取状态差异\n */\n const getDiff = (snapshotId1: string, snapshotId2: string): StateDiff[] => {\n const snapshot1 = snapshots.value.find(s => s.id === snapshotId1)\n const snapshot2 = snapshots.value.find(s => s.id === snapshotId2)\n\n if (!snapshot1 || !snapshot2) return []\n\n return computeDiff(snapshot1.state, snapshot2.state)\n }\n\n /**\n * 导出快照\n */\n const exportSnapshots = (): string => {\n return JSON.stringify({\n snapshots: snapshots.value,\n currentIndex: currentIndex.value,\n exportedAt: Date.now(),\n })\n }\n\n /**\n * 导入快照\n */\n const importSnapshots = (data: string): boolean => {\n try {\n const parsed = JSON.parse(data) as {\n snapshots: Array<StateSnapshot<S>>\n currentIndex: number\n }\n\n if (!Array.isArray(parsed.snapshots)) return false\n\n snapshots.value = parsed.snapshots\n currentIndex.value = Math.min(\n parsed.currentIndex ?? snapshots.value.length - 1,\n snapshots.value.length - 1,\n )\n\n return true\n }\n catch {\n return false\n }\n }\n\n // 自动记录\n if (autoRecord) {\n const stateRef = typeof state === 'function' ? computed(state) : state\n\n const stopWatch = watch(\n stateRef,\n (newState, oldState) => {\n // 如果是恢复操作,不记录\n if (isRestoring) return\n\n // 如果状态未变化,不记录\n if (deepEqual(newState, oldState)) return\n\n // 防抖记录\n if (debounceTimer) {\n clearTimeout(debounceTimer)\n }\n\n debounceTimer = setTimeout(() => {\n takeSnapshot()\n }, debounceMs)\n },\n { deep },\n )\n\n // 初始快照\n takeSnapshot('初始状态')\n\n onUnmounted(() => {\n stopWatch()\n if (debounceTimer) {\n clearTimeout(debounceTimer)\n }\n })\n }\n\n return {\n snapshots,\n currentIndex,\n canUndo,\n canRedo,\n takeSnapshot,\n restoreSnapshot,\n undo,\n redo,\n goto,\n clearSnapshots,\n getDiff,\n exportSnapshots,\n importSnapshots,\n }\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"useStoreSnapshot.js","names":[],"sources":["../../src/composables/useStoreSnapshot.ts"],"sourcesContent":["/**\r\n * useStoreSnapshot - Store 状态快照工具\r\n *\r\n * 提供状态快照、历史记录和调试功能\r\n * @module composables/useStoreSnapshot\r\n */\r\n\r\nimport type { ComputedRef, Ref } from 'vue'\r\nimport { deepClone, deepEqual } from '@composy/store-core'\r\nimport { computed, onUnmounted, ref, watch } from 'vue'\r\n\r\n/**\r\n * 状态快照\r\n */\r\nexport interface StateSnapshot<S = unknown> {\r\n /** 快照 ID */\r\n id: string\r\n /** 状态数据 */\r\n state: S\r\n /** 时间戳 */\r\n timestamp: number\r\n /** 快照标签 */\r\n label?: string\r\n /** 元数据 */\r\n meta?: Record<string, unknown>\r\n}\r\n\r\n/**\r\n * 状态差异\r\n */\r\nexport interface StateDiff {\r\n /** 差异路径 */\r\n path: string\r\n /** 旧值 */\r\n oldValue: unknown\r\n /** 新值 */\r\n newValue: unknown\r\n /** 差异类型 */\r\n type: 'add' | 'remove' | 'change'\r\n}\r\n\r\n/**\r\n * useStoreSnapshot 选项\r\n */\r\nexport interface UseStoreSnapshotOptions {\r\n /** 最大快照数量 */\r\n maxSnapshots?: number\r\n /** 是否自动记录 */\r\n autoRecord?: boolean\r\n /** 自动记录防抖延迟(毫秒) */\r\n debounceMs?: number\r\n /** 是否深度监听 */\r\n deep?: boolean\r\n}\r\n\r\n/**\r\n * useStoreSnapshot 返回值\r\n */\r\nexport interface UseStoreSnapshotReturn<S> {\r\n /** 快照列表 */\r\n snapshots: Ref<Array<StateSnapshot<S>>>\r\n /** 当前快照索引 */\r\n currentIndex: Ref<number>\r\n /** 是否可以撤销 */\r\n canUndo: ComputedRef<boolean>\r\n /** 是否可以重做 */\r\n canRedo: ComputedRef<boolean>\r\n /** 创建快照 */\r\n takeSnapshot: (\r\n label?: string,\r\n meta?: Record<string, unknown>\r\n ) => StateSnapshot<S>\r\n /** 恢复快照 */\r\n restoreSnapshot: (id: string) => boolean\r\n /** 撤销 */\r\n undo: () => boolean\r\n /** 重做 */\r\n redo: () => boolean\r\n /** 跳转到指定快照 */\r\n goto: (index: number) => boolean\r\n /** 清空快照 */\r\n clearSnapshots: () => void\r\n /** 获取状态差异 */\r\n getDiff: (snapshotId1: string, snapshotId2: string) => StateDiff[]\r\n /** 导出快照 */\r\n exportSnapshots: () => string\r\n /** 导入快照 */\r\n importSnapshots: (data: string) => boolean\r\n}\r\n\r\n/**\r\n * 生成唯一 ID\r\n */\r\nfunction generateId(): string {\r\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\r\n}\r\n\r\n/**\r\n * 计算两个对象的差异\r\n */\r\nfunction computeDiff(oldObj: unknown, newObj: unknown, path = ''): StateDiff[] {\r\n const diffs: StateDiff[] = []\r\n\r\n // 类型不同\r\n if (typeof oldObj !== typeof newObj) {\r\n diffs.push({\r\n path: path || '.',\r\n oldValue: oldObj,\r\n newValue: newObj,\r\n type: 'change',\r\n })\r\n return diffs\r\n }\r\n\r\n // 基础类型比较\r\n if (typeof oldObj !== 'object' || oldObj === null || newObj === null) {\r\n if (!Object.is(oldObj, newObj)) {\r\n diffs.push({\r\n path: path || '.',\r\n oldValue: oldObj,\r\n newValue: newObj,\r\n type: 'change',\r\n })\r\n }\r\n return diffs\r\n }\r\n\r\n // 数组比较\r\n if (Array.isArray(oldObj) && Array.isArray(newObj)) {\r\n const maxLen = Math.max(oldObj.length, newObj.length)\r\n for (let i = 0; i < maxLen; i++) {\r\n const itemPath = path ? `${path}[${i}]` : `[${i}]`\r\n if (i >= oldObj.length) {\r\n diffs.push({\r\n path: itemPath,\r\n oldValue: undefined,\r\n newValue: newObj[i],\r\n type: 'add',\r\n })\r\n } else if (i >= newObj.length) {\r\n diffs.push({\r\n path: itemPath,\r\n oldValue: oldObj[i],\r\n newValue: undefined,\r\n type: 'remove',\r\n })\r\n } else {\r\n diffs.push(...computeDiff(oldObj[i], newObj[i], itemPath))\r\n }\r\n }\r\n return diffs\r\n }\r\n\r\n // 对象比较\r\n const oldKeys = new Set(Object.keys(oldObj as Record<string, unknown>))\r\n const newKeys = new Set(Object.keys(newObj as Record<string, unknown>))\r\n\r\n // 检查新增的键\r\n for (const key of newKeys) {\r\n if (!oldKeys.has(key)) {\r\n diffs.push({\r\n path: path ? `${path}.${key}` : key,\r\n oldValue: undefined,\r\n newValue: (newObj as Record<string, unknown>)[key],\r\n type: 'add',\r\n })\r\n }\r\n }\r\n\r\n // 检查删除的键\r\n for (const key of oldKeys) {\r\n if (!newKeys.has(key)) {\r\n diffs.push({\r\n path: path ? `${path}.${key}` : key,\r\n oldValue: (oldObj as Record<string, unknown>)[key],\r\n newValue: undefined,\r\n type: 'remove',\r\n })\r\n }\r\n }\r\n\r\n // 检查修改的键\r\n for (const key of oldKeys) {\r\n if (newKeys.has(key)) {\r\n diffs.push(\r\n ...computeDiff(\r\n (oldObj as Record<string, unknown>)[key],\r\n (newObj as Record<string, unknown>)[key],\r\n path ? `${path}.${key}` : key\r\n )\r\n )\r\n }\r\n }\r\n\r\n return diffs\r\n}\r\n\r\n/**\r\n * Store 状态快照 Hook\r\n *\r\n * 提供状态快照、撤销/重做和调试功能\r\n *\r\n * @template S - 状态类型\r\n * @param state - 响应式状态\r\n * @param setState - 状态设置函数\r\n * @param options - 配置选项\r\n * @returns 快照操作对象\r\n *\r\n * @example\r\n * ```typescript\r\n * const store = useCounterStore()\r\n *\r\n * const {\r\n * snapshots,\r\n * canUndo,\r\n * canRedo,\r\n * takeSnapshot,\r\n * undo,\r\n * redo,\r\n * getDiff\r\n * } = useStoreSnapshot(\r\n * () => store.$state,\r\n * (state) => store.$patch(state),\r\n * { maxSnapshots: 50, autoRecord: true }\r\n * )\r\n *\r\n * // 手动创建快照\r\n * takeSnapshot('保存点 1')\r\n *\r\n * // 撤销操作\r\n * if (canUndo.value) {\r\n * undo()\r\n * }\r\n *\r\n * // 获取状态差异\r\n * const diff = getDiff(snapshots.value[0].id, snapshots.value[1].id)\r\n * ```\r\n */\r\nexport function useStoreSnapshot<S>(\r\n state: Ref<S> | (() => S),\r\n setState: (state: S) => void,\r\n options: UseStoreSnapshotOptions = {}\r\n): UseStoreSnapshotReturn<S> {\r\n const {\r\n maxSnapshots = 100,\r\n autoRecord = false,\r\n debounceMs = 300,\r\n deep = true,\r\n } = options\r\n\r\n const snapshots = ref<Array<StateSnapshot<S>>>([]) as Ref<\r\n Array<StateSnapshot<S>>\r\n >\r\n const currentIndex = ref(-1)\r\n let debounceTimer: ReturnType<typeof setTimeout> | undefined\r\n let isRestoring = false\r\n let previousAutoRecordState: S | undefined\r\n\r\n // 获取当前状态\r\n const getState = (): S => {\r\n return typeof state === 'function' ? state() : state.value\r\n }\r\n\r\n // 是否可以撤销\r\n const canUndo = computed(() => currentIndex.value > 0)\r\n\r\n // 是否可以重做\r\n const canRedo = computed(\r\n () => currentIndex.value < snapshots.value.length - 1\r\n )\r\n\r\n /**\r\n * 创建快照\r\n */\r\n const takeSnapshot = (\r\n label?: string,\r\n meta?: Record<string, unknown>\r\n ): StateSnapshot<S> => {\r\n const currentState = getState()\r\n const snapshot: StateSnapshot<S> = {\r\n id: generateId(),\r\n state: deepClone(currentState),\r\n timestamp: Date.now(),\r\n label,\r\n meta,\r\n }\r\n\r\n // 如果当前不在最新位置,删除后面的快照\r\n if (currentIndex.value < snapshots.value.length - 1) {\r\n snapshots.value = snapshots.value.slice(0, currentIndex.value + 1)\r\n }\r\n\r\n // 添加新快照\r\n snapshots.value.push(snapshot)\r\n currentIndex.value = snapshots.value.length - 1\r\n\r\n // 限制快照数量\r\n if (snapshots.value.length > maxSnapshots) {\r\n snapshots.value.shift()\r\n currentIndex.value--\r\n }\r\n\r\n return snapshot\r\n }\r\n\r\n /**\r\n * 恢复快照\r\n */\r\n const restoreSnapshot = (id: string): boolean => {\r\n const index = snapshots.value.findIndex(s => s.id === id)\r\n if (index === -1) return false\r\n\r\n isRestoring = true\r\n try {\r\n setState(deepClone(snapshots.value[index].state))\r\n currentIndex.value = index\r\n previousAutoRecordState = deepClone(getState())\r\n return true\r\n } finally {\r\n isRestoring = false\r\n }\r\n }\r\n\r\n /**\r\n * 撤销\r\n */\r\n const undo = (): boolean => {\r\n if (!canUndo.value) return false\r\n\r\n const targetIndex = currentIndex.value - 1\r\n isRestoring = true\r\n try {\r\n setState(deepClone(snapshots.value[targetIndex].state))\r\n currentIndex.value = targetIndex\r\n previousAutoRecordState = deepClone(getState())\r\n return true\r\n } finally {\r\n isRestoring = false\r\n }\r\n }\r\n\r\n /**\r\n * 重做\r\n */\r\n const redo = (): boolean => {\r\n if (!canRedo.value) return false\r\n\r\n const targetIndex = currentIndex.value + 1\r\n isRestoring = true\r\n try {\r\n setState(deepClone(snapshots.value[targetIndex].state))\r\n currentIndex.value = targetIndex\r\n previousAutoRecordState = deepClone(getState())\r\n return true\r\n } finally {\r\n isRestoring = false\r\n }\r\n }\r\n\r\n /**\r\n * 跳转到指定快照\r\n */\r\n const goto = (index: number): boolean => {\r\n if (index < 0 || index >= snapshots.value.length) return false\r\n\r\n isRestoring = true\r\n try {\r\n setState(deepClone(snapshots.value[index].state))\r\n currentIndex.value = index\r\n previousAutoRecordState = deepClone(getState())\r\n return true\r\n } finally {\r\n isRestoring = false\r\n }\r\n }\r\n\r\n /**\r\n * 清空快照\r\n */\r\n const clearSnapshots = (): void => {\r\n snapshots.value = []\r\n currentIndex.value = -1\r\n }\r\n\r\n /**\r\n * 获取状态差异\r\n */\r\n const getDiff = (snapshotId1: string, snapshotId2: string): StateDiff[] => {\r\n const snapshot1 = snapshots.value.find(s => s.id === snapshotId1)\r\n const snapshot2 = snapshots.value.find(s => s.id === snapshotId2)\r\n\r\n if (!snapshot1 || !snapshot2) return []\r\n\r\n return computeDiff(snapshot1.state, snapshot2.state)\r\n }\r\n\r\n /**\r\n * 导出快照\r\n */\r\n const exportSnapshots = (): string => {\r\n return JSON.stringify({\r\n snapshots: snapshots.value,\r\n currentIndex: currentIndex.value,\r\n exportedAt: Date.now(),\r\n })\r\n }\r\n\r\n /**\r\n * 导入快照\r\n */\r\n const importSnapshots = (data: string): boolean => {\r\n try {\r\n const parsed = JSON.parse(data) as {\r\n snapshots: Array<StateSnapshot<S>>\r\n currentIndex: number\r\n }\r\n\r\n if (!Array.isArray(parsed.snapshots)) return false\r\n\r\n snapshots.value = parsed.snapshots\r\n currentIndex.value = Math.min(\r\n parsed.currentIndex ?? snapshots.value.length - 1,\r\n snapshots.value.length - 1\r\n )\r\n\r\n return true\r\n } catch {\r\n return false\r\n }\r\n }\r\n\r\n // 自动记录\r\n if (autoRecord) {\r\n const stateRef = typeof state === 'function' ? computed(state) : state\r\n previousAutoRecordState = deepClone(getState())\r\n\r\n const stopWatch = watch(\r\n stateRef,\r\n (newState, oldState) => {\r\n // 如果是恢复操作,不记录\r\n if (isRestoring) return\r\n\r\n // 如果状态未变化,不记录\r\n if (deepEqual(newState, previousAutoRecordState ?? oldState)) return\r\n previousAutoRecordState = deepClone(newState)\r\n\r\n // 防抖记录\r\n if (debounceTimer) {\r\n clearTimeout(debounceTimer)\r\n }\r\n\r\n debounceTimer = setTimeout(() => {\r\n takeSnapshot()\r\n }, debounceMs)\r\n },\r\n { deep }\r\n )\r\n\r\n // 初始快照\r\n takeSnapshot('初始状态')\r\n\r\n onUnmounted(() => {\r\n stopWatch()\r\n if (debounceTimer) {\r\n clearTimeout(debounceTimer)\r\n }\r\n })\r\n }\r\n\r\n return {\r\n snapshots,\r\n currentIndex,\r\n canUndo,\r\n canRedo,\r\n takeSnapshot,\r\n restoreSnapshot,\r\n undo,\r\n redo,\r\n goto,\r\n clearSnapshots,\r\n getDiff,\r\n exportSnapshots,\r\n importSnapshots,\r\n }\r\n}\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSubscribe.d.ts","sourceRoot":"","sources":["../../src/composables/useSubscribe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAG9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,KAAK,EAAE,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,MAAM,IAAI,CAAA;CAAE,EACrI,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,EACvD,OAAO,GAAE,gBAAqB,GAC7B,MAAM,IAAI,CAyBZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,KAAK,EAAE,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,MAAM,IAAI,CAAA;CAAE,EACzG,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,EAC1C,QAAQ,UAAQ,GACf,MAAM,IAAI,CAeZ;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe;IACf,KAAK,EAAE,OAAO,CAAA;IACd,gBAAgB;IAChB,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,mBAAmB;IACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;IACpD,kBAAkB;IAClB,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EACd,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,EACxD,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAkBjB"}
1
+ {"version":3,"file":"useSubscribe.d.ts","sourceRoot":"","sources":["../../src/composables/useSubscribe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAG9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,KAAK,EAAE,CAAC,GAAG;IACT,UAAU,CAAC,EAAE,CACX,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAC7B,MAAM,IAAI,CAAA;CAChB,EACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,EACvD,OAAO,GAAE,gBAAqB,GAC7B,MAAM,IAAI,CAyBZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,KAAK,EAAE,CAAC,GAAG;IACT,SAAS,CAAC,EAAE,CACV,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,EAC1C,QAAQ,CAAC,EAAE,OAAO,KACf,MAAM,IAAI,CAAA;CAChB,EACD,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,EAC1C,QAAQ,UAAQ,GACf,MAAM,IAAI,CAeZ;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe;IACf,KAAK,EAAE,OAAO,CAAA;IACd,gBAAgB;IAChB,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,mBAAmB;IACnB,KAAK,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;IACpD,kBAAkB;IAClB,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EACd,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,EACxD,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAkBjB"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"useSubscribe.js","names":[],"sources":["../../src/composables/useSubscribe.ts"],"sourcesContent":["/**\n * useSubscribe Composable\n *\n * 提供 Store 订阅功能\n * @module composables/useSubscribe\n */\n\nimport type { Ref, WatchStopHandle } from 'vue'\nimport type { MutationInfo, SubscribeOptions } from '../types'\nimport { onUnmounted, watch } from 'vue'\n\n/**\n * 订阅 Store 状态变化\n *\n * @template S - 状态类型\n * @param store - Pinia Store 实例\n * @param callback - 回调函数\n * @param options - 订阅选项\n * @returns 取消订阅函数\n *\n * @example\n * ```typescript\n * const store = useCounterStore()\n *\n * // 订阅状态变化\n * const unsubscribe = useSubscribe(store, (mutation, state) => {\n * console.log('State changed:', mutation.type, state)\n * })\n *\n * // 取消订阅\n * unsubscribe()\n * ```\n */\nexport function useSubscribe<S extends Record<string, unknown>>(\n store: S & { $subscribe?: (callback: (mutation: MutationInfo<S>, state: S) => void, options?: { detached?: boolean }) => () => void },\n callback: (mutation: MutationInfo<S>, state: S) => void,\n options: SubscribeOptions = {},\n): () => void {\n const { detached = false } = options\n\n // 使用 Pinia 的 $subscribe\n if (store.$subscribe) {\n const unsubscribe = store.$subscribe(\n (mutation, state) => {\n callback(mutation as MutationInfo<S>, state as S)\n },\n { detached },\n )\n\n // 组件卸载时自动取消订阅\n if (!detached) {\n onUnmounted(() => {\n unsubscribe()\n })\n }\n\n return unsubscribe\n }\n\n // 如果不是 Pinia Store,返回空函数\n console.warn('[useSubscribe] Store 不支持 $subscribe 方法')\n return () => {}\n}\n\n/**\n * 订阅 Store Action 调用\n *\n * @template S - Store 类型\n * @param store - Pinia Store 实例\n * @param callback - 回调函数\n * @returns 取消订阅函数\n *\n * @example\n * ```typescript\n * const store = useCounterStore()\n *\n * // 订阅 Action 调用\n * useOnAction(store, ({ name, args, after, onError }) => {\n * console.log(`Action ${name} called with:`, args)\n *\n * after((result) => {\n * console.log(`Action ${name} finished with:`, result)\n * })\n *\n * onError((error) => {\n * console.error(`Action ${name} failed:`, error)\n * })\n * })\n * ```\n */\nexport function useOnAction<S extends Record<string, unknown>>(\n store: S & { $onAction?: (callback: (context: ActionContext) => void, detached?: boolean) => () => void },\n callback: (context: ActionContext) => void,\n detached = false,\n): () => void {\n if (store.$onAction) {\n const unsubscribe = store.$onAction(callback, detached)\n\n if (!detached) {\n onUnmounted(() => {\n unsubscribe()\n })\n }\n\n return unsubscribe\n }\n\n console.warn('[useOnAction] Store 不支持 $onAction 方法')\n return () => {}\n}\n\n/**\n * Action 上下文\n */\nexport interface ActionContext {\n /** Action 名称 */\n name: string\n /** Store 实例 */\n store: unknown\n /** Action 参数 */\n args: unknown[]\n /** Action 完成后回调 */\n after: (callback: (result: unknown) => void) => void\n /** Action 错误回调 */\n onError: (callback: (error: unknown) => void) => void\n}\n\n/**\n * 监听 ref 变化\n *\n * @template T - 值类型\n * @param source - 监听源\n * @param callback - 回调函数\n * @param options - 监听选项\n * @returns 停止监听函数\n */\nexport function useWatch<T>(\n source: Ref<T>,\n callback: (newValue: T, oldValue: T | undefined) => void,\n options: SubscribeOptions = {},\n): WatchStopHandle {\n const { immediate = false, deep = false, detached = false } = options\n\n const stop = watch(\n source,\n (newValue, oldValue) => {\n callback(newValue, oldValue)\n },\n { immediate, deep },\n )\n\n if (!detached) {\n onUnmounted(() => {\n stop()\n })\n }\n\n return stop\n}\n\n"],"mappings":";;;;;;;;;;;AAiCO,SAAS,aACd,OACA,UACA,UAA4B,CAAC,GACjB;CACZ,MAAM,EAAE,WAAW,UAAU;CAG7B,IAAI,MAAM,YAAY;EACpB,MAAM,cAAc,MAAM,YACvB,UAAU,UAAU;GACnB,SAAS,UAA6B,KAAU;EAClD,GACA,EAAE,SAAS,CACb;EAGA,IAAI,CAAC,UACH,kBAAkB;GAChB,YAAY;EACd,CAAC;EAGH,OAAO;CACT;CAGA,QAAQ,KAAK,wCAAwC;CACrD,aAAa,CAAC;AAChB;AA4BO,SAAS,YACd,OACA,UACA,WAAW,OACC;CACZ,IAAI,MAAM,WAAW;EACnB,MAAM,cAAc,MAAM,UAAU,UAAU,QAAQ;EAEtD,IAAI,CAAC,UACH,kBAAkB;GAChB,YAAY;EACd,CAAC;EAGH,OAAO;CACT;CAEA,QAAQ,KAAK,sCAAsC;CACnD,aAAa,CAAC;AAChB;AA2BO,SAAS,SACd,QACA,UACA,UAA4B,CAAC,GACZ;CACjB,MAAM,EAAE,YAAY,OAAO,OAAO,OAAO,WAAW,UAAU;CAE9D,MAAM,OAAO,MACX,SACC,UAAU,aAAa;EACtB,SAAS,UAAU,QAAQ;CAC7B,GACA;EAAE;EAAW;CAAK,CACpB;CAEA,IAAI,CAAC,UACH,kBAAkB;EAChB,KAAK;CACP,CAAC;CAGH,OAAO;AACT"}
1
+ {"version":3,"file":"useSubscribe.js","names":[],"sources":["../../src/composables/useSubscribe.ts"],"sourcesContent":["/**\r\n * useSubscribe Composable\r\n *\r\n * 提供 Store 订阅功能\r\n * @module composables/useSubscribe\r\n */\r\n\r\nimport type { Ref, WatchStopHandle } from 'vue'\r\nimport type { MutationInfo, SubscribeOptions } from '../types'\r\nimport { onUnmounted, watch } from 'vue'\r\n\r\n/**\r\n * 订阅 Store 状态变化\r\n *\r\n * @template S - 状态类型\r\n * @param store - Pinia Store 实例\r\n * @param callback - 回调函数\r\n * @param options - 订阅选项\r\n * @returns 取消订阅函数\r\n *\r\n * @example\r\n * ```typescript\r\n * const store = useCounterStore()\r\n *\r\n * // 订阅状态变化\r\n * const unsubscribe = useSubscribe(store, (mutation, state) => {\r\n * console.log('State changed:', mutation.type, state)\r\n * })\r\n *\r\n * // 取消订阅\r\n * unsubscribe()\r\n * ```\r\n */\r\nexport function useSubscribe<S extends Record<string, unknown>>(\r\n store: S & {\r\n $subscribe?: (\r\n callback: (mutation: MutationInfo<S>, state: S) => void,\r\n options?: { detached?: boolean }\r\n ) => () => void\r\n },\r\n callback: (mutation: MutationInfo<S>, state: S) => void,\r\n options: SubscribeOptions = {}\r\n): () => void {\r\n const { detached = false } = options\r\n\r\n // 使用 Pinia 的 $subscribe\r\n if (store.$subscribe) {\r\n const unsubscribe = store.$subscribe(\r\n (mutation, state) => {\r\n callback(mutation as MutationInfo<S>, state as S)\r\n },\r\n { detached }\r\n )\r\n\r\n // 组件卸载时自动取消订阅\r\n if (!detached) {\r\n onUnmounted(() => {\r\n unsubscribe()\r\n })\r\n }\r\n\r\n return unsubscribe\r\n }\r\n\r\n // 如果不是 Pinia Store,返回空函数\r\n console.warn('[useSubscribe] Store 不支持 $subscribe 方法')\r\n return () => {}\r\n}\r\n\r\n/**\r\n * 订阅 Store Action 调用\r\n *\r\n * @template S - Store 类型\r\n * @param store - Pinia Store 实例\r\n * @param callback - 回调函数\r\n * @returns 取消订阅函数\r\n *\r\n * @example\r\n * ```typescript\r\n * const store = useCounterStore()\r\n *\r\n * // 订阅 Action 调用\r\n * useOnAction(store, ({ name, args, after, onError }) => {\r\n * console.log(`Action ${name} called with:`, args)\r\n *\r\n * after((result) => {\r\n * console.log(`Action ${name} finished with:`, result)\r\n * })\r\n *\r\n * onError((error) => {\r\n * console.error(`Action ${name} failed:`, error)\r\n * })\r\n * })\r\n * ```\r\n */\r\nexport function useOnAction<S extends Record<string, unknown>>(\r\n store: S & {\r\n $onAction?: (\r\n callback: (context: ActionContext) => void,\r\n detached?: boolean\r\n ) => () => void\r\n },\r\n callback: (context: ActionContext) => void,\r\n detached = false\r\n): () => void {\r\n if (store.$onAction) {\r\n const unsubscribe = store.$onAction(callback, detached)\r\n\r\n if (!detached) {\r\n onUnmounted(() => {\r\n unsubscribe()\r\n })\r\n }\r\n\r\n return unsubscribe\r\n }\r\n\r\n console.warn('[useOnAction] Store 不支持 $onAction 方法')\r\n return () => {}\r\n}\r\n\r\n/**\r\n * Action 上下文\r\n */\r\nexport interface ActionContext {\r\n /** Action 名称 */\r\n name: string\r\n /** Store 实例 */\r\n store: unknown\r\n /** Action 参数 */\r\n args: unknown[]\r\n /** Action 完成后回调 */\r\n after: (callback: (result: unknown) => void) => void\r\n /** Action 错误回调 */\r\n onError: (callback: (error: unknown) => void) => void\r\n}\r\n\r\n/**\r\n * 监听 ref 变化\r\n *\r\n * @template T - 值类型\r\n * @param source - 监听源\r\n * @param callback - 回调函数\r\n * @param options - 监听选项\r\n * @returns 停止监听函数\r\n */\r\nexport function useWatch<T>(\r\n source: Ref<T>,\r\n callback: (newValue: T, oldValue: T | undefined) => void,\r\n options: SubscribeOptions = {}\r\n): WatchStopHandle {\r\n const { immediate = false, deep = false, detached = false } = options\r\n\r\n const stop = watch(\r\n source,\r\n (newValue, oldValue) => {\r\n callback(newValue, oldValue)\r\n },\r\n { immediate, deep }\r\n )\r\n\r\n if (!detached) {\r\n onUnmounted(() => {\r\n stop()\r\n })\r\n }\r\n\r\n return stop\r\n}\r\n"],"mappings":";;;;;;;;;;;AAiCO,SAAS,aACd,OAMA,UACA,UAA4B,CAAC,GACjB;CACZ,MAAM,EAAE,WAAW,UAAU;CAG7B,IAAI,MAAM,YAAY;EACpB,MAAM,cAAc,MAAM,YACvB,UAAU,UAAU;GACnB,SAAS,UAA6B,KAAU;EAClD,GACA,EAAE,SAAS,CACb;EAGA,IAAI,CAAC,UACH,kBAAkB;GAChB,YAAY;EACd,CAAC;EAGH,OAAO;CACT;CAGA,QAAQ,KAAK,wCAAwC;CACrD,aAAa,CAAC;AAChB;AA4BO,SAAS,YACd,OAMA,UACA,WAAW,OACC;CACZ,IAAI,MAAM,WAAW;EACnB,MAAM,cAAc,MAAM,UAAU,UAAU,QAAQ;EAEtD,IAAI,CAAC,UACH,kBAAkB;GAChB,YAAY;EACd,CAAC;EAGH,OAAO;CACT;CAEA,QAAQ,KAAK,sCAAsC;CACnD,aAAa,CAAC;AAChB;AA2BO,SAAS,SACd,QACA,UACA,UAA4B,CAAC,GACZ;CACjB,MAAM,EAAE,YAAY,OAAO,OAAO,OAAO,WAAW,UAAU;CAE9D,MAAM,OAAO,MACX,SACC,UAAU,aAAa;EACtB,SAAS,UAAU,QAAQ;CAC7B,GACA;EAAE;EAAW;CAAK,CACpB;CAEA,IAAI,CAAC,UACH,kBAAkB;EAChB,KAAK;CACP,CAAC;CAGH,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"injection-keys.d.ts","sourceRoot":"","sources":["../../src/context/injection-keys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAElC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAG9C,eAAO,MAAM,gBAAgB,EAAkC,YAAY,CAAC,cAAc,CAAC,CAAA;AAE3F,eAAO,MAAM,kBAAkB,EAAoC,YAAY,CAAC,KAAK,CAAC,CAAA;AAEtF,eAAO,MAAM,oBAAoB,EAAsC,YAAY,CAAC,YAAY,CAAC,CAAA"}
1
+ {"version":3,"file":"injection-keys.d.ts","sourceRoot":"","sources":["../../src/context/injection-keys.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAElC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAA;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAG9C,eAAO,MAAM,gBAAgB,EAExB,YAAY,CAAC,cAAc,CAAC,CAAA;AAEjC,eAAO,MAAM,kBAAkB,EAE1B,YAAY,CAAC,KAAK,CAAC,CAAA;AAExB,eAAO,MAAM,oBAAoB,EAE5B,YAAY,CAAC,YAAY,CAAC,CAAA"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -1 +1 @@
1
- {"version":3,"file":"injection-keys.js","names":[],"sources":["../../src/context/injection-keys.ts"],"sourcesContent":["// 从 pinia 导入 Pinia 类型\nimport type { Pinia } from 'pinia'\n// 从 vue 导入 InjectionKey 类型,用于类型安全的依赖注入\nimport type { InjectionKey } from 'vue'\n// 导入 StoreRuntime 类型,表示 store 运行时实例\nimport type { StoreRuntime } from '../runtime/store-runtime'\n// 导入 GlobalStoreAPI 类型,表示全局 store API 接口\nimport type { GlobalStoreAPI } from '../types'\n\n// store 全局 API 的注入键符号,用于 provide/inject 传递 GlobalStoreAPI 实例\nexport const STORE_API_SYMBOL = Symbol('ldesign-store-api') as InjectionKey<GlobalStoreAPI>\n// store Pinia 实例的注入键符号,用于 provide/inject 传递 Pinia 实例\nexport const STORE_PINIA_SYMBOL = Symbol('ldesign-store-pinia') as InjectionKey<Pinia>\n// store 运行时实例的注入键符号,用于 provide/inject 传递 StoreRuntime 实例\nexport const STORE_RUNTIME_SYMBOL = Symbol('ldesign-store-runtime') as InjectionKey<StoreRuntime>\n"],"mappings":";;;;;;;;;;AAUO,MAAM,mBAAmB,uBAAO,mBAAmB;AAEnD,MAAM,qBAAqB,uBAAO,qBAAqB;AAEvD,MAAM,uBAAuB,uBAAO,uBAAuB"}
1
+ {"version":3,"file":"injection-keys.js","names":[],"sources":["../../src/context/injection-keys.ts"],"sourcesContent":["// 从 pinia 导入 Pinia 类型\r\nimport type { Pinia } from 'pinia'\r\n// 从 vue 导入 InjectionKey 类型,用于类型安全的依赖注入\r\nimport type { InjectionKey } from 'vue'\r\n// 导入 StoreRuntime 类型,表示 store 运行时实例\r\nimport type { StoreRuntime } from '../runtime/store-runtime'\r\n// 导入 GlobalStoreAPI 类型,表示全局 store API 接口\r\nimport type { GlobalStoreAPI } from '../types'\r\n\r\n// store 全局 API 的注入键符号,用于 provide/inject 传递 GlobalStoreAPI 实例\r\nexport const STORE_API_SYMBOL = Symbol(\r\n 'ldesign-store-api'\r\n) as InjectionKey<GlobalStoreAPI>\r\n// store Pinia 实例的注入键符号,用于 provide/inject 传递 Pinia 实例\r\nexport const STORE_PINIA_SYMBOL = Symbol(\r\n 'ldesign-store-pinia'\r\n) as InjectionKey<Pinia>\r\n// store 运行时实例的注入键符号,用于 provide/inject 传递 StoreRuntime 实例\r\nexport const STORE_RUNTIME_SYMBOL = Symbol(\r\n 'ldesign-store-runtime'\r\n) as InjectionKey<StoreRuntime>\r\n"],"mappings":";;;;;;;;;;AAUO,MAAM,mBAAmB,uBAC9B,mBACF;AAEO,MAAM,qBAAqB,uBAChC,qBACF;AAEO,MAAM,uBAAuB,uBAClC,uBACF"}
package/esm/index.d.ts CHANGED
@@ -19,6 +19,6 @@ export type { GlobalStoreAPI, MutationInfo, PersistOptions, StoreEnginePluginOpt
19
19
  export { batch, combineSelectors, composePlugins, createAsyncAction, createBatchManager, createEventBus, createLoggerMiddleware, createMiddlewareManager, createPluginFactory, createPubSub, createPubSubWithValue, createSelector, createTimeTravelMiddleware, createValidationMiddleware, deepClone, deepMerge, defineStorePlugin, globalEventBus, } from '@composy/store-core';
20
20
  export { createPinia, defineStore, getActivePinia, mapActions, mapGetters, mapState, mapStores, mapWritableState, setActivePinia, storeToRefs, } from 'pinia';
21
21
  export type { Pinia, PiniaPlugin, PiniaPluginContext, StateTree, Store, StoreDefinition, StoreGeneric, StoreGetters, StoreState, } from 'pinia';
22
- export declare const version = "1.0.0";
22
+ export declare const version = "0.0.1";
23
23
  export declare const name = "@composy/store-vue";
24
24
  //# sourceMappingURL=index.d.ts.map
package/esm/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -26,7 +26,7 @@ import "./plugins/index.js";
26
26
  import { createPinia, defineStore, getActivePinia, mapActions, mapGetters, mapState, mapStores, mapWritableState, setActivePinia, storeToRefs } from "pinia";
27
27
  import { batch, combineSelectors, composePlugins, createAsyncAction, createBatchManager, createEventBus, createLoggerMiddleware, createMiddlewareManager, createPluginFactory, createPubSub, createPubSubWithValue, createSelector, createTimeTravelMiddleware, createValidationMiddleware, deepClone, deepMerge, defineStorePlugin, globalEventBus } from "@composy/store-core";
28
28
  //#region src/index.ts
29
- const version = "1.0.0";
29
+ const version = "0.0.1";
30
30
  const name = "@composy/store-vue";
31
31
  //#endregion
32
32
  export { batch, cleanupEnhancedPersist, combineSelectors, composePlugins, createAsyncAction, createBatchManager, createEnhancedPersistPlugin, createEventBus, createLoggerMiddleware, createMiddlewareManager, createPersistPlugin, createPinia, createPluginFactory, createPubSub, createPubSubWithValue, createSelector, createStoreEnginePlugin, createStoreGetters, createStoreRegistryPlugin, createStoreState, createStoreVuePlugin, createTimeTravelMiddleware, createValidationMiddleware, deepClone, deepMerge, defineSetupStore, defineStore, defineStorePlugin, email, getActivePinia, getGlobalStoreAPI, getStoreRegistry, globalEventBus, mapActions, mapGetters, mapState, mapStores, mapWritableState, maxLength, minLength, name, numberRange, pattern, required, setActivePinia, storeToRefs, useComputedStore, useFormStore, useOnAction, useOptimistic, usePersist, usePersistedRef, usePersistedRefWithTTL, usePersistedState, useSharedState, useSimpleStore, useStore, useStoreDevtools, useStoreSnapshot, useSubscribe, useWatch, version };
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @composy/store-vue - Vue 3 状态管理适配器\n *\n * 基于 Pinia 的增强版状态管理解决方案\n *\n * 主要功能:\n * - Pinia 集成与增强\n * - 状态持久化\n * - Engine 插件集成\n * - 丰富的 Composables\n *\n * @module @composy/store-vue\n */\n\n// === Composables ===\nexport {\n createStoreGetters,\n createStoreState,\n // Setup Store 助手\n defineSetupStore,\n email,\n maxLength,\n minLength,\n numberRange,\n pattern,\n // 验证规则工具\n required,\n useComputedStore,\n useFormStore,\n useOnAction,\n useOptimistic,\n usePersist,\n usePersistedRef,\n usePersistedRefWithTTL,\n usePersistedState,\n useSharedState,\n useSimpleStore,\n useStore,\n useStoreDevtools,\n useStoreSnapshot,\n useSubscribe,\n useWatch,\n} from './composables'\n\nexport type {\n ActionContext,\n EventLogEntry,\n FormFieldRules,\n FormFieldState,\n FormValidator,\n OptimisticEntry,\n PersistedStateOptions,\n PersistedStateReturn,\n StateDiff,\n StateSnapshot,\n StoreInfo,\n UseFormStoreOptions,\n UseFormStoreReturn,\n UseOptimisticReturn,\n UseSharedStateOptions,\n UseSharedStateReturn,\n UseStoreDevtoolsReturn,\n UseStoreSnapshotOptions,\n UseStoreSnapshotReturn,\n} from './composables'\n\n// === 插件 ===\nexport {\n cleanupEnhancedPersist,\n createEnhancedPersistPlugin,\n createPersistPlugin,\n createStoreEnginePlugin,\n createStoreRegistryPlugin,\n createStoreVuePlugin,\n getGlobalStoreAPI,\n getStoreRegistry,\n} from './plugins'\n\nexport type {\n EnhancedPersistOptions,\n EnhancedPersistPluginOptions,\n PersistPluginOptions,\n StoreVuePluginOptions,\n} from './plugins'\n\n// === 类型 ===\nexport type {\n GlobalStoreAPI,\n MutationInfo,\n PersistOptions,\n StoreEnginePluginOptions,\n StoreOptions,\n StoreProviderProps,\n SubscribeOptions,\n UsePersistOptions,\n UsePersistReturn,\n UseStoreReturn,\n} from './types'\n\n// === 从 @composy/store-core 重新导出常用功能 ===\nexport {\n // 核心\n batch,\n // 工具\n combineSelectors,\n // 插件\n composePlugins,\n createAsyncAction,\n createBatchManager,\n createEventBus,\n // 中间件\n createLoggerMiddleware,\n createMiddlewareManager,\n createPluginFactory,\n createPubSub,\n createPubSubWithValue,\n createSelector,\n createTimeTravelMiddleware,\n createValidationMiddleware,\n deepClone,\n deepMerge,\n defineStorePlugin,\n globalEventBus,\n} from '@composy/store-core'\n\n// === 从 Pinia 重新导出 ===\nexport {\n createPinia,\n defineStore,\n getActivePinia,\n mapActions,\n mapGetters,\n mapState,\n mapStores,\n mapWritableState,\n setActivePinia,\n storeToRefs,\n} from 'pinia'\n\nexport type {\n Pinia,\n PiniaPlugin,\n PiniaPluginContext,\n StateTree,\n Store,\n StoreDefinition,\n StoreGeneric,\n StoreGetters,\n StoreState,\n} from 'pinia'\n\n// === 版本信息 ===\nexport const version = '1.0.0'\nexport const name = '@composy/store-vue'\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwJO,MAAM,UAAU;AAChB,MAAM,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\r\n * @composy/store-vue - Vue 3 状态管理适配器\r\n *\r\n * 基于 Pinia 的增强版状态管理解决方案\r\n *\r\n * 主要功能:\r\n * - Pinia 集成与增强\r\n * - 状态持久化\r\n * - Engine 插件集成\r\n * - 丰富的 Composables\r\n *\r\n * @module @composy/store-vue\r\n */\r\n\r\n// === Composables ===\r\nexport {\r\n createStoreGetters,\r\n createStoreState,\r\n // Setup Store 助手\r\n defineSetupStore,\r\n email,\r\n maxLength,\r\n minLength,\r\n numberRange,\r\n pattern,\r\n // 验证规则工具\r\n required,\r\n useComputedStore,\r\n useFormStore,\r\n useOnAction,\r\n useOptimistic,\r\n usePersist,\r\n usePersistedRef,\r\n usePersistedRefWithTTL,\r\n usePersistedState,\r\n useSharedState,\r\n useSimpleStore,\r\n useStore,\r\n useStoreDevtools,\r\n useStoreSnapshot,\r\n useSubscribe,\r\n useWatch,\r\n} from './composables'\r\n\r\nexport type {\r\n ActionContext,\r\n EventLogEntry,\r\n FormFieldRules,\r\n FormFieldState,\r\n FormValidator,\r\n OptimisticEntry,\r\n PersistedStateOptions,\r\n PersistedStateReturn,\r\n StateDiff,\r\n StateSnapshot,\r\n StoreInfo,\r\n UseFormStoreOptions,\r\n UseFormStoreReturn,\r\n UseOptimisticReturn,\r\n UseSharedStateOptions,\r\n UseSharedStateReturn,\r\n UseStoreDevtoolsReturn,\r\n UseStoreSnapshotOptions,\r\n UseStoreSnapshotReturn,\r\n} from './composables'\r\n\r\n// === 插件 ===\r\nexport {\r\n cleanupEnhancedPersist,\r\n createEnhancedPersistPlugin,\r\n createPersistPlugin,\r\n createStoreEnginePlugin,\r\n createStoreRegistryPlugin,\r\n createStoreVuePlugin,\r\n getGlobalStoreAPI,\r\n getStoreRegistry,\r\n} from './plugins'\r\n\r\nexport type {\r\n EnhancedPersistOptions,\r\n EnhancedPersistPluginOptions,\r\n PersistPluginOptions,\r\n StoreVuePluginOptions,\r\n} from './plugins'\r\n\r\n// === 类型 ===\r\nexport type {\r\n GlobalStoreAPI,\r\n MutationInfo,\r\n PersistOptions,\r\n StoreEnginePluginOptions,\r\n StoreOptions,\r\n StoreProviderProps,\r\n SubscribeOptions,\r\n UsePersistOptions,\r\n UsePersistReturn,\r\n UseStoreReturn,\r\n} from './types'\r\n\r\n// === 从 @composy/store-core 重新导出常用功能 ===\r\nexport {\r\n // 核心\r\n batch,\r\n // 工具\r\n combineSelectors,\r\n // 插件\r\n composePlugins,\r\n createAsyncAction,\r\n createBatchManager,\r\n createEventBus,\r\n // 中间件\r\n createLoggerMiddleware,\r\n createMiddlewareManager,\r\n createPluginFactory,\r\n createPubSub,\r\n createPubSubWithValue,\r\n createSelector,\r\n createTimeTravelMiddleware,\r\n createValidationMiddleware,\r\n deepClone,\r\n deepMerge,\r\n defineStorePlugin,\r\n globalEventBus,\r\n} from '@composy/store-core'\r\n\r\n// === 从 Pinia 重新导出 ===\r\nexport {\r\n createPinia,\r\n defineStore,\r\n getActivePinia,\r\n mapActions,\r\n mapGetters,\r\n mapState,\r\n mapStores,\r\n mapWritableState,\r\n setActivePinia,\r\n storeToRefs,\r\n} from 'pinia'\r\n\r\nexport type {\r\n Pinia,\r\n PiniaPlugin,\r\n PiniaPluginContext,\r\n StateTree,\r\n Store,\r\n StoreDefinition,\r\n StoreGeneric,\r\n StoreGetters,\r\n StoreState,\r\n} from 'pinia'\r\n\r\n// === 版本信息 ===\r\nexport const version = '0.0.1'\r\nexport const name = '@composy/store-vue'\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwJO,MAAM,UAAU;AAChB,MAAM,OAAO"}
@@ -1,4 +1,4 @@
1
- import type { /* 引擎抽象接口 */ StoreEnginePluginContextLike } from '@composy/store-core/engine';
1
+ import type { StoreEnginePluginContextLike } from '@composy/store-core/engine';
2
2
  import type { App } from 'vue';
3
3
  import type { GlobalStoreAPI, StoreEnginePluginOptions } from '../types';
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"engine-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/engine-plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAE4B,YAAY,CAClD,4BAA4B,EAC7B,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAI9B,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAQxE;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,CAAC,OAAO,EAAE,4BAA4B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC9B,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,4BAA4B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACrE;AAoCD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,GAAG,iBAAiB,CAwFjG;AAGD,eAAe,uBAAuB,CAAA"}
1
+ {"version":3,"file":"engine-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/engine-plugin.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,4BAA4B,EAC7B,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAI9B,OAAO,KAAK,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AAcxE;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,CAAC,OAAO,EAAE,4BAA4B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC9B,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,4BAA4B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACrE;AAsCD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CAyFnB;AAGD,eAAe,uBAAuB,CAAA"}
@@ -2,7 +2,7 @@
2
2
  * ***********************************
3
3
  * @composy/store-vue v0.0.1 *
4
4
  * Built with rollup *
5
- * Build time: 2024-08-17 11:39:29 *
5
+ * Build time: 2024-10-12 17:40:04 *
6
6
  * Build mode: production *
7
7
  * Minified: No *
8
8
  * ***********************************
@@ -23,7 +23,7 @@ function getGlobalStoreAPI() {
23
23
  return getGlobalStoreAPI$1();
24
24
  }
25
25
  function createStoreEnginePlugin(options = {}) {
26
- const { debug = false, dependencies = [], name = "store", version = "1.0.0" } = options;
26
+ const { debug = false, dependencies = [], name = "store", version = "0.0.1" } = options;
27
27
  let bridge = null;
28
28
  const createBridge = () => {
29
29
  const activeBridge = createStoreEngineBridge({