electron-state-sync 1.1.0

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 (97) hide show
  1. package/CLAUDE.md +254 -0
  2. package/LICENSE +21 -0
  3. package/README.md +753 -0
  4. package/README.zh-CN.md +743 -0
  5. package/bun.lock +542 -0
  6. package/bunfig.toml +7 -0
  7. package/dist/jotai.cjs +106 -0
  8. package/dist/jotai.d.cts +48 -0
  9. package/dist/jotai.d.cts.map +1 -0
  10. package/dist/jotai.d.ts +48 -0
  11. package/dist/jotai.d.ts.map +1 -0
  12. package/dist/jotai.js +105 -0
  13. package/dist/jotai.js.map +1 -0
  14. package/dist/main.cjs +177 -0
  15. package/dist/main.d.cts +26 -0
  16. package/dist/main.d.cts.map +1 -0
  17. package/dist/main.d.ts +26 -0
  18. package/dist/main.d.ts.map +1 -0
  19. package/dist/main.js +177 -0
  20. package/dist/main.js.map +1 -0
  21. package/dist/preact.cjs +46 -0
  22. package/dist/preact.d.cts +11 -0
  23. package/dist/preact.d.cts.map +1 -0
  24. package/dist/preact.d.ts +11 -0
  25. package/dist/preact.d.ts.map +1 -0
  26. package/dist/preact.js +46 -0
  27. package/dist/preact.js.map +1 -0
  28. package/dist/preload.cjs +51 -0
  29. package/dist/preload.d.cts +20 -0
  30. package/dist/preload.d.cts.map +1 -0
  31. package/dist/preload.d.ts +20 -0
  32. package/dist/preload.d.ts.map +1 -0
  33. package/dist/preload.js +51 -0
  34. package/dist/preload.js.map +1 -0
  35. package/dist/react-query.cjs +113 -0
  36. package/dist/react-query.d.cts +58 -0
  37. package/dist/react-query.d.cts.map +1 -0
  38. package/dist/react-query.d.ts +58 -0
  39. package/dist/react-query.d.ts.map +1 -0
  40. package/dist/react-query.js +112 -0
  41. package/dist/react-query.js.map +1 -0
  42. package/dist/react.cjs +46 -0
  43. package/dist/react.d.cts +11 -0
  44. package/dist/react.d.cts.map +1 -0
  45. package/dist/react.d.ts +11 -0
  46. package/dist/react.d.ts.map +1 -0
  47. package/dist/react.js +46 -0
  48. package/dist/react.js.map +1 -0
  49. package/dist/redux.cjs +148 -0
  50. package/dist/redux.d.cts +80 -0
  51. package/dist/redux.d.cts.map +1 -0
  52. package/dist/redux.d.ts +80 -0
  53. package/dist/redux.d.ts.map +1 -0
  54. package/dist/redux.js +146 -0
  55. package/dist/redux.js.map +1 -0
  56. package/dist/renderer/index.cjs +7 -0
  57. package/dist/renderer/index.d.cts +23 -0
  58. package/dist/renderer/index.d.cts.map +1 -0
  59. package/dist/renderer/index.d.ts +23 -0
  60. package/dist/renderer/index.d.ts.map +1 -0
  61. package/dist/renderer/index.js +3 -0
  62. package/dist/renderer-C7zF3UQm.js +57 -0
  63. package/dist/renderer-C7zF3UQm.js.map +1 -0
  64. package/dist/renderer-D3YziJ_U.cjs +86 -0
  65. package/dist/solid.cjs +74 -0
  66. package/dist/solid.d.cts +13 -0
  67. package/dist/solid.d.cts.map +1 -0
  68. package/dist/solid.d.ts +13 -0
  69. package/dist/solid.d.ts.map +1 -0
  70. package/dist/solid.js +74 -0
  71. package/dist/solid.js.map +1 -0
  72. package/dist/svelte.cjs +63 -0
  73. package/dist/svelte.d.cts +14 -0
  74. package/dist/svelte.d.cts.map +1 -0
  75. package/dist/svelte.d.ts +14 -0
  76. package/dist/svelte.d.ts.map +1 -0
  77. package/dist/svelte.js +63 -0
  78. package/dist/svelte.js.map +1 -0
  79. package/dist/types-7wPPX0ty.d.ts +37 -0
  80. package/dist/types-7wPPX0ty.d.ts.map +1 -0
  81. package/dist/types-C18dHgLI.d.cts +37 -0
  82. package/dist/types-C18dHgLI.d.cts.map +1 -0
  83. package/dist/vue.cjs +69 -0
  84. package/dist/vue.d.cts +15 -0
  85. package/dist/vue.d.cts.map +1 -0
  86. package/dist/vue.d.ts +15 -0
  87. package/dist/vue.d.ts.map +1 -0
  88. package/dist/vue.js +70 -0
  89. package/dist/vue.js.map +1 -0
  90. package/dist/zustand.cjs +193 -0
  91. package/dist/zustand.d.cts +61 -0
  92. package/dist/zustand.d.cts.map +1 -0
  93. package/dist/zustand.d.ts +61 -0
  94. package/dist/zustand.d.ts.map +1 -0
  95. package/dist/zustand.js +191 -0
  96. package/dist/zustand.js.map +1 -0
  97. package/package.json +162 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solid.js","names":[],"sources":["../src/renderer/solid.ts"],"sourcesContent":["import { createSignal, onCleanup, onMount, type Accessor } from \"solid-js\";\n\nimport type { SyncStateChannelOptions } from \"../channels\";\nimport type { SyncStateBridge } from \"../types\";\nimport { resolveSyncStateBridge } from \"./bridge\";\nimport { getGlobalConfig } from \"./index\";\n\nexport interface UseSyncStateSolidOptions extends SyncStateChannelOptions {\n bridge?: SyncStateBridge;\n}\n\n// Solid Setter type\nexport type SyncStateSolidSetter<StateValue> = (\n value: StateValue | ((prev: StateValue) => StateValue),\n) => StateValue;\n\n// Solid Hook return type\nexport type UseSyncStateSolidResult<StateValue> = readonly [\n Accessor<StateValue>,\n SyncStateSolidSetter<StateValue>,\n Accessor<boolean>,\n];\n\n// Remote update tracker\ninterface RemoteUpdateTracker<StateValue> {\n // Apply main process update\n applyRemoteValue: (value: StateValue) => void;\n // Check if should skip local sync\n shouldSkipLocalSync: () => boolean;\n}\n\nconst createChannelOptions = (options: UseSyncStateSolidOptions): SyncStateChannelOptions => {\n const globalConfig = getGlobalConfig();\n return {\n baseChannel: options.baseChannel ?? globalConfig.baseChannel,\n name: options.name,\n };\n};\n\nconst createRemoteUpdateTracker = <StateValue>(\n setState: (value: StateValue) => StateValue,\n setIsSynced: (value: boolean) => void,\n): RemoteUpdateTracker<StateValue> => {\n // Whether update is from main process\n let isRemoteUpdate = false;\n\n const applyRemoteValue = (value: StateValue): void => {\n isRemoteUpdate = true;\n setState(value);\n // Mark first sync as completed\n setIsSynced(true);\n // Reset immediately since Solid doesn't have a watch that consumes this synchronously\n isRemoteUpdate = false;\n };\n\n const shouldSkipLocalSync = (): boolean => {\n if (!isRemoteUpdate) {\n return false;\n }\n isRemoteUpdate = false;\n return true;\n };\n\n return {\n applyRemoteValue,\n shouldSkipLocalSync,\n };\n};\n\n// Sync Setter options\ninterface SyncSetterOptions<StateValue> {\n accessor: Accessor<StateValue>;\n setState: (value: StateValue) => StateValue;\n bridge: SyncStateBridge;\n channelOptions: SyncStateChannelOptions;\n tracker: RemoteUpdateTracker<StateValue>;\n}\n\nconst createSyncSetter =\n <StateValue>(options: SyncSetterOptions<StateValue>): SyncStateSolidSetter<StateValue> =>\n (value: StateValue | ((prev: StateValue) => StateValue)) => {\n const { accessor, bridge, channelOptions, setState, tracker } = options;\n let nextValue = value as StateValue;\n\n if (typeof value === \"function\") {\n nextValue = (value as (prev: StateValue) => StateValue)(accessor());\n }\n\n if (tracker.shouldSkipLocalSync()) {\n return setState(nextValue);\n }\n\n const resultValue = setState(nextValue);\n void bridge.set(channelOptions, nextValue);\n return resultValue;\n };\n\nexport const useSyncState = <StateValue>(\n initialValue: StateValue,\n options: UseSyncStateSolidOptions,\n): UseSyncStateSolidResult<StateValue> => {\n const [rawStateValue, rawSetStateValue] = createSignal<StateValue>(initialValue as StateValue);\n const stateValue = rawStateValue as Accessor<StateValue>;\n // First sync completion flag\n const [isSynced, setIsSynced] = createSignal(false);\n const setStateValue = (value: StateValue): StateValue => {\n (rawSetStateValue as (nextValue: StateValue) => void)(value);\n return value;\n };\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = createChannelOptions(options);\n const tracker = createRemoteUpdateTracker(setStateValue, setIsSynced);\n const setAndSync = createSyncSetter<StateValue>({\n accessor: stateValue,\n bridge,\n channelOptions,\n setState: setStateValue,\n tracker,\n });\n\n onMount(() => {\n const unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);\n void bridge.get<StateValue>(channelOptions).then(tracker.applyRemoteValue);\n\n onCleanup(() => {\n unsubscribe();\n });\n });\n\n return [stateValue, setAndSync, isSynced] as const;\n};\n\n// Backward compatibility alias\nexport { useSyncState as useSyncStateSolid };\n"],"mappings":";;;;AA+BA,MAAM,wBAAwB,YAA+D;CAC3F,MAAM,eAAe,iBAAiB;AACtC,QAAO;EACL,aAAa,QAAQ,eAAe,aAAa;EACjD,MAAM,QAAQ;EACf;;AAGH,MAAM,6BACJ,UACA,gBACoC;CAEpC,IAAI,iBAAiB;CAErB,MAAM,oBAAoB,UAA4B;AACpD,mBAAiB;AACjB,WAAS,MAAM;AAEf,cAAY,KAAK;AAEjB,mBAAiB;;CAGnB,MAAM,4BAAqC;AACzC,MAAI,CAAC,eACH,QAAO;AAET,mBAAiB;AACjB,SAAO;;AAGT,QAAO;EACL;EACA;EACD;;AAYH,MAAM,oBACS,aACZ,UAA2D;CAC1D,MAAM,EAAE,UAAU,QAAQ,gBAAgB,UAAU,YAAY;CAChE,IAAI,YAAY;AAEhB,KAAI,OAAO,UAAU,WACnB,aAAa,MAA2C,UAAU,CAAC;AAGrE,KAAI,QAAQ,qBAAqB,CAC/B,QAAO,SAAS,UAAU;CAG5B,MAAM,cAAc,SAAS,UAAU;AACvC,CAAK,OAAO,IAAI,gBAAgB,UAAU;AAC1C,QAAO;;AAGX,MAAa,gBACX,cACA,YACwC;CACxC,MAAM,CAAC,eAAe,oBAAoB,aAAyB,aAA2B;CAC9F,MAAM,aAAa;CAEnB,MAAM,CAAC,UAAU,eAAe,aAAa,MAAM;CACnD,MAAM,iBAAiB,UAAkC;AACvD,EAAC,iBAAqD,MAAM;AAC5D,SAAO;;CAET,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,qBAAqB,QAAQ;CACpD,MAAM,UAAU,0BAA0B,eAAe,YAAY;CACrE,MAAM,aAAa,iBAA6B;EAC9C,UAAU;EACV;EACA;EACA,UAAU;EACV;EACD,CAAC;AAEF,eAAc;EACZ,MAAM,cAAc,OAAO,UAAU,gBAAgB,QAAQ,iBAAiB;AAC9E,EAAK,OAAO,IAAgB,eAAe,CAAC,KAAK,QAAQ,iBAAiB;AAE1E,kBAAgB;AACd,gBAAa;IACb;GACF;AAEF,QAAO;EAAC;EAAY;EAAY;EAAS"}
@@ -0,0 +1,63 @@
1
+ const require_renderer = require('./renderer-D3YziJ_U.cjs');
2
+ let svelte_store = require("svelte/store");
3
+
4
+ //#region src/renderer/svelte.ts
5
+ const createChannelOptions = (options) => {
6
+ const globalConfig = require_renderer.getGlobalConfig();
7
+ return {
8
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
9
+ name: options.name
10
+ };
11
+ };
12
+ const createRemoteUpdateTracker = (setStoreValue, isSynced) => {
13
+ let isRemoteUpdate = false;
14
+ const applyRemoteValue = (value) => {
15
+ isRemoteUpdate = true;
16
+ setStoreValue(value);
17
+ isSynced.set(true);
18
+ isRemoteUpdate = false;
19
+ };
20
+ const shouldSkipLocalSync = () => {
21
+ if (!isRemoteUpdate) return false;
22
+ isRemoteUpdate = false;
23
+ return true;
24
+ };
25
+ return {
26
+ applyRemoteValue,
27
+ shouldSkipLocalSync
28
+ };
29
+ };
30
+ const useSyncState = (initialValue, options) => {
31
+ const globalConfig = require_renderer.getGlobalConfig();
32
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
33
+ const channelOptions = createChannelOptions(options);
34
+ const isSynced = (0, svelte_store.writable)(false);
35
+ let tracker = void 0;
36
+ const store = (0, svelte_store.writable)(initialValue, (setStoreValue) => {
37
+ tracker = createRemoteUpdateTracker(setStoreValue, isSynced);
38
+ const unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);
39
+ bridge.get(channelOptions).then(tracker.applyRemoteValue);
40
+ return () => {
41
+ unsubscribe();
42
+ tracker = void 0;
43
+ };
44
+ });
45
+ const set = (value) => {
46
+ if (tracker?.shouldSkipLocalSync()) return;
47
+ store.set(value);
48
+ bridge.set(channelOptions, value);
49
+ };
50
+ const update = (updater) => {
51
+ set(updater((0, svelte_store.get)(store)));
52
+ };
53
+ return {
54
+ isSynced,
55
+ set,
56
+ subscribe: store.subscribe,
57
+ update
58
+ };
59
+ };
60
+
61
+ //#endregion
62
+ exports.createSyncStateStore = useSyncState;
63
+ exports.useSyncState = useSyncState;
@@ -0,0 +1,14 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-C18dHgLI.cjs";
2
+ import { Readable, Writable } from "svelte/store";
3
+
4
+ //#region src/renderer/svelte.d.ts
5
+ interface SyncStateSvelteOptions extends SyncStateChannelOptions {
6
+ bridge?: SyncStateBridge;
7
+ }
8
+ interface SyncStateStore<StateValue> extends Writable<StateValue> {
9
+ isSynced: Readable<boolean>;
10
+ }
11
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: SyncStateSvelteOptions) => SyncStateStore<StateValue>;
12
+ //#endregion
13
+ export { SyncStateStore, SyncStateSvelteOptions, useSyncState as createSyncStateStore, useSyncState };
14
+ //# sourceMappingURL=svelte.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte.d.cts","names":[],"sources":["../src/renderer/svelte.ts"],"sourcesContent":[],"mappings":";;;;UAOiB,sBAAA,SAA+B;EAA/B,MAAA,CAAA,EACN,eADM;AASjB;AAA6D,UAA5C,cAA4C,CAAA,UAAA,CAAA,SAAT,QAAS,CAAA,UAAA,CAAA,CAAA;EACjD,QAAA,EAAA,QAAA,CAAA,OAAA,CAAA;;AADgD,cAwC/C,YAxC+C,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAyC5C,UAzC4C,EAAA,OAAA,EA0CjD,sBA1CiD,EAAA,GA2CzD,cA3CyD,CA2C1C,UA3C0C,CAAA"}
@@ -0,0 +1,14 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-7wPPX0ty.js";
2
+ import { Readable, Writable } from "svelte/store";
3
+
4
+ //#region src/renderer/svelte.d.ts
5
+ interface SyncStateSvelteOptions extends SyncStateChannelOptions {
6
+ bridge?: SyncStateBridge;
7
+ }
8
+ interface SyncStateStore<StateValue> extends Writable<StateValue> {
9
+ isSynced: Readable<boolean>;
10
+ }
11
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: SyncStateSvelteOptions) => SyncStateStore<StateValue>;
12
+ //#endregion
13
+ export { SyncStateStore, SyncStateSvelteOptions, useSyncState as createSyncStateStore, useSyncState };
14
+ //# sourceMappingURL=svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte.d.ts","names":[],"sources":["../src/renderer/svelte.ts"],"sourcesContent":[],"mappings":";;;;UAOiB,sBAAA,SAA+B;EAA/B,MAAA,CAAA,EACN,eADM;AASjB;AAA6D,UAA5C,cAA4C,CAAA,UAAA,CAAA,SAAT,QAAS,CAAA,UAAA,CAAA,CAAA;EACjD,QAAA,EAAA,QAAA,CAAA,OAAA,CAAA;;AADgD,cAwC/C,YAxC+C,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAyC5C,UAzC4C,EAAA,OAAA,EA0CjD,sBA1CiD,EAAA,GA2CzD,cA3CyD,CA2C1C,UA3C0C,CAAA"}
package/dist/svelte.js ADDED
@@ -0,0 +1,63 @@
1
+ import { a as resolveSyncStateBridge, t as getGlobalConfig } from "./renderer-C7zF3UQm.js";
2
+ import { get, writable } from "svelte/store";
3
+
4
+ //#region src/renderer/svelte.ts
5
+ const createChannelOptions = (options) => {
6
+ const globalConfig = getGlobalConfig();
7
+ return {
8
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
9
+ name: options.name
10
+ };
11
+ };
12
+ const createRemoteUpdateTracker = (setStoreValue, isSynced) => {
13
+ let isRemoteUpdate = false;
14
+ const applyRemoteValue = (value) => {
15
+ isRemoteUpdate = true;
16
+ setStoreValue(value);
17
+ isSynced.set(true);
18
+ isRemoteUpdate = false;
19
+ };
20
+ const shouldSkipLocalSync = () => {
21
+ if (!isRemoteUpdate) return false;
22
+ isRemoteUpdate = false;
23
+ return true;
24
+ };
25
+ return {
26
+ applyRemoteValue,
27
+ shouldSkipLocalSync
28
+ };
29
+ };
30
+ const useSyncState = (initialValue, options) => {
31
+ const globalConfig = getGlobalConfig();
32
+ const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
33
+ const channelOptions = createChannelOptions(options);
34
+ const isSynced = writable(false);
35
+ let tracker = void 0;
36
+ const store = writable(initialValue, (setStoreValue) => {
37
+ tracker = createRemoteUpdateTracker(setStoreValue, isSynced);
38
+ const unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);
39
+ bridge.get(channelOptions).then(tracker.applyRemoteValue);
40
+ return () => {
41
+ unsubscribe();
42
+ tracker = void 0;
43
+ };
44
+ });
45
+ const set = (value) => {
46
+ if (tracker?.shouldSkipLocalSync()) return;
47
+ store.set(value);
48
+ bridge.set(channelOptions, value);
49
+ };
50
+ const update = (updater) => {
51
+ set(updater(get(store)));
52
+ };
53
+ return {
54
+ isSynced,
55
+ set,
56
+ subscribe: store.subscribe,
57
+ update
58
+ };
59
+ };
60
+
61
+ //#endregion
62
+ export { useSyncState as createSyncStateStore, useSyncState };
63
+ //# sourceMappingURL=svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte.js","names":[],"sources":["../src/renderer/svelte.ts"],"sourcesContent":["import { get, writable, type Readable, type Updater, type Writable } from \"svelte/store\";\n\nimport type { SyncStateChannelOptions } from \"../channels\";\nimport type { SyncStateBridge } from \"../types\";\nimport { resolveSyncStateBridge } from \"./bridge\";\nimport { getGlobalConfig } from \"./index\";\n\nexport interface SyncStateSvelteOptions extends SyncStateChannelOptions {\n bridge?: SyncStateBridge;\n}\n\ninterface RemoteUpdateTracker<StateValue> {\n applyRemoteValue: (value: StateValue) => void;\n shouldSkipLocalSync: () => boolean;\n}\n\nexport interface SyncStateStore<StateValue> extends Writable<StateValue> {\n isSynced: Readable<boolean>;\n}\n\nconst createChannelOptions = (options: SyncStateSvelteOptions): SyncStateChannelOptions => {\n const globalConfig = getGlobalConfig();\n return {\n baseChannel: options.baseChannel ?? globalConfig.baseChannel,\n name: options.name,\n };\n};\n\nconst createRemoteUpdateTracker = <StateValue>(\n setStoreValue: (value: StateValue) => void,\n isSynced: Writable<boolean>,\n): RemoteUpdateTracker<StateValue> => {\n let isRemoteUpdate = false;\n\n const applyRemoteValue = (value: StateValue): void => {\n isRemoteUpdate = true;\n setStoreValue(value);\n isSynced.set(true);\n // Reset immediately since Svelte doesn't have a watch that consumes this synchronously\n isRemoteUpdate = false;\n };\n\n const shouldSkipLocalSync = (): boolean => {\n if (!isRemoteUpdate) {\n return false;\n }\n isRemoteUpdate = false;\n return true;\n };\n\n return {\n applyRemoteValue,\n shouldSkipLocalSync,\n };\n};\n\nexport const useSyncState = <StateValue>(\n initialValue: StateValue,\n options: SyncStateSvelteOptions,\n): SyncStateStore<StateValue> => {\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = createChannelOptions(options);\n const isSynced = writable(false);\n let tracker: RemoteUpdateTracker<StateValue> | undefined = undefined;\n\n const store = writable(initialValue, (setStoreValue) => {\n tracker = createRemoteUpdateTracker(setStoreValue, isSynced);\n const unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);\n void bridge.get<StateValue>(channelOptions).then(tracker.applyRemoteValue);\n\n return () => {\n unsubscribe();\n tracker = undefined;\n };\n });\n\n const set = (value: StateValue): void => {\n if (tracker?.shouldSkipLocalSync()) {\n return;\n }\n\n store.set(value);\n void bridge.set(channelOptions, value);\n };\n\n const update = (updater: Updater<StateValue>): void => {\n const nextValue = updater(get(store));\n set(nextValue);\n };\n\n return {\n isSynced,\n set,\n subscribe: store.subscribe,\n update,\n };\n};\n\n// Backward compatibility alias\nexport { useSyncState as createSyncStateStore };\n"],"mappings":";;;;AAoBA,MAAM,wBAAwB,YAA6D;CACzF,MAAM,eAAe,iBAAiB;AACtC,QAAO;EACL,aAAa,QAAQ,eAAe,aAAa;EACjD,MAAM,QAAQ;EACf;;AAGH,MAAM,6BACJ,eACA,aACoC;CACpC,IAAI,iBAAiB;CAErB,MAAM,oBAAoB,UAA4B;AACpD,mBAAiB;AACjB,gBAAc,MAAM;AACpB,WAAS,IAAI,KAAK;AAElB,mBAAiB;;CAGnB,MAAM,4BAAqC;AACzC,MAAI,CAAC,eACH,QAAO;AAET,mBAAiB;AACjB,SAAO;;AAGT,QAAO;EACL;EACA;EACD;;AAGH,MAAa,gBACX,cACA,YAC+B;CAC/B,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,qBAAqB,QAAQ;CACpD,MAAM,WAAW,SAAS,MAAM;CAChC,IAAI,UAAuD;CAE3D,MAAM,QAAQ,SAAS,eAAe,kBAAkB;AACtD,YAAU,0BAA0B,eAAe,SAAS;EAC5D,MAAM,cAAc,OAAO,UAAU,gBAAgB,QAAQ,iBAAiB;AAC9E,EAAK,OAAO,IAAgB,eAAe,CAAC,KAAK,QAAQ,iBAAiB;AAE1E,eAAa;AACX,gBAAa;AACb,aAAU;;GAEZ;CAEF,MAAM,OAAO,UAA4B;AACvC,MAAI,SAAS,qBAAqB,CAChC;AAGF,QAAM,IAAI,MAAM;AAChB,EAAK,OAAO,IAAI,gBAAgB,MAAM;;CAGxC,MAAM,UAAU,YAAuC;AAErD,MADkB,QAAQ,IAAI,MAAM,CAAC,CACvB;;AAGhB,QAAO;EACL;EACA;EACA,WAAW,MAAM;EACjB;EACD"}
@@ -0,0 +1,37 @@
1
+ //#region src/channels.d.ts
2
+ interface SyncStateChannelOptions {
3
+ name: string;
4
+ baseChannel?: string;
5
+ }
6
+ interface SyncStateChannels {
7
+ getChannel: string;
8
+ setChannel: string;
9
+ subscribeChannel: string;
10
+ unsubscribeChannel: string;
11
+ updateChannel: string;
12
+ }
13
+ declare const createSyncStateChannels: (options: SyncStateChannelOptions) => SyncStateChannels;
14
+ //#endregion
15
+ //#region src/types.d.ts
16
+ type SyncStateListener<StateValue> = (value: StateValue) => void;
17
+ type SyncStateErrorCode = "RENDERER_READONLY" | "RENDERER_INVALID_VALUE";
18
+ declare class SyncStateError extends Error {
19
+ readonly code: SyncStateErrorCode;
20
+ readonly stateName?: string;
21
+ readonly baseChannel?: string;
22
+ readonly cause?: Error;
23
+ constructor(code: SyncStateErrorCode, message: string, context?: {
24
+ stateName?: string;
25
+ baseChannel?: string;
26
+ cause?: Error;
27
+ });
28
+ getFullMessage(): string;
29
+ }
30
+ interface SyncStateBridge {
31
+ get: <StateValue>(options: SyncStateChannelOptions) => Promise<StateValue>;
32
+ set: <StateValue>(options: SyncStateChannelOptions, value: StateValue) => Promise<void>;
33
+ subscribe: <StateValue>(options: SyncStateChannelOptions, listener: SyncStateListener<StateValue>) => () => void;
34
+ }
35
+ //#endregion
36
+ export { SyncStateChannelOptions as a, SyncStateListener as i, SyncStateError as n, SyncStateChannels as o, SyncStateErrorCode as r, createSyncStateChannels as s, SyncStateBridge as t };
37
+ //# sourceMappingURL=types-7wPPX0ty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-7wPPX0ty.d.ts","names":[],"sources":["../src/channels.ts","../src/types.ts"],"sourcesContent":[],"mappings":";UAAiB,uBAAA;EAAA,IAAA,EAAA,MAAA;EAKA,WAAA,CAAA,EAAA,MAAiB;AAQlC;UARiB,iBAAA;;;ECHL,gBAAA,EAAA,MAAiB;EAEjB,kBAAA,EAAA,MAAkB;EAEjB,aAAA,EAAA,MAAe;;AAIF,cDGb,uBCHa,EAAA,CAAA,OAAA,EDGuB,uBCHvB,EAAA,GDGiD,iBCHjD;;;ADVT,KCEL,iBDFK,CAAuB,UAAA,CAAA,GAAA,CAAA,KAAA,ECEY,UDFZ,EAAA,GAAA,IAAA;AAKvB,KCDL,kBAAA,GDCsB,mBAAA,GAAA,wBAAA;AAQrB,cCPA,cAAA,SAAuB,KAAA,CDOa;iBCNzB;;;EALZ,SAAA,KAAA,CAAA,EAQc,KARG;EAEjB,WAAA,CAAA,IAAA,EASF,kBAToB,EAAA,OAAA,EAAA,MAAA,EAAA,OASpB,CAToB,EAAA;IAEjB,SAAA,CAAA,EAAA,MAAe;IACJ,WAAA,CAAA,EAAA,MAAA;IAGE,KAAA,CAAA,EAKwC,KALxC;EAGhB,CAAA;EAEwD,cAAA,CAAA,CAAA,EAAA,MAAA;;AATzB,UAsCxB,eAAA,CAtCwB;EAsCxB,GAAA,EAAA,CAAA,UAAA,CAAA,CAAe,OAAA,EACH,uBADG,EAAA,GACyB,OADzB,CACiC,UADjC,CAAA;EACH,GAAA,EAAA,CAAA,UAAA,CAAA,CAAA,OAAA,EACA,uBADA,EAAA,KAAA,EACgC,UADhC,EAAA,GAC+C,OAD/C,CAAA,IAAA,CAAA;EAAoC,SAAA,EAAA,CAAA,UAAA,CAAA,CAAA,OAAA,EAGpD,uBAHoD,EAAA,QAAA,EAInD,iBAJmD,CAIjC,UAJiC,CAAA,EAAA,GAAA,GAAA,GAAA,IAAA"}
@@ -0,0 +1,37 @@
1
+ //#region src/channels.d.ts
2
+ interface SyncStateChannelOptions {
3
+ name: string;
4
+ baseChannel?: string;
5
+ }
6
+ interface SyncStateChannels {
7
+ getChannel: string;
8
+ setChannel: string;
9
+ subscribeChannel: string;
10
+ unsubscribeChannel: string;
11
+ updateChannel: string;
12
+ }
13
+ declare const createSyncStateChannels: (options: SyncStateChannelOptions) => SyncStateChannels;
14
+ //#endregion
15
+ //#region src/types.d.ts
16
+ type SyncStateListener<StateValue> = (value: StateValue) => void;
17
+ type SyncStateErrorCode = "RENDERER_READONLY" | "RENDERER_INVALID_VALUE";
18
+ declare class SyncStateError extends Error {
19
+ readonly code: SyncStateErrorCode;
20
+ readonly stateName?: string;
21
+ readonly baseChannel?: string;
22
+ readonly cause?: Error;
23
+ constructor(code: SyncStateErrorCode, message: string, context?: {
24
+ stateName?: string;
25
+ baseChannel?: string;
26
+ cause?: Error;
27
+ });
28
+ getFullMessage(): string;
29
+ }
30
+ interface SyncStateBridge {
31
+ get: <StateValue>(options: SyncStateChannelOptions) => Promise<StateValue>;
32
+ set: <StateValue>(options: SyncStateChannelOptions, value: StateValue) => Promise<void>;
33
+ subscribe: <StateValue>(options: SyncStateChannelOptions, listener: SyncStateListener<StateValue>) => () => void;
34
+ }
35
+ //#endregion
36
+ export { SyncStateChannelOptions as a, SyncStateListener as i, SyncStateError as n, SyncStateChannels as o, SyncStateErrorCode as r, createSyncStateChannels as s, SyncStateBridge as t };
37
+ //# sourceMappingURL=types-C18dHgLI.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-C18dHgLI.d.cts","names":[],"sources":["../src/channels.ts","../src/types.ts"],"sourcesContent":[],"mappings":";UAAiB,uBAAA;EAAA,IAAA,EAAA,MAAA;EAKA,WAAA,CAAA,EAAA,MAAiB;AAQlC;UARiB,iBAAA;;;ECHL,gBAAA,EAAA,MAAiB;EAEjB,kBAAA,EAAA,MAAkB;EAEjB,aAAA,EAAA,MAAe;;AAIF,cDGb,uBCHa,EAAA,CAAA,OAAA,EDGuB,uBCHvB,EAAA,GDGiD,iBCHjD;;;ADVT,KCEL,iBDFK,CAAuB,UAAA,CAAA,GAAA,CAAA,KAAA,ECEY,UDFZ,EAAA,GAAA,IAAA;AAKvB,KCDL,kBAAA,GDCsB,mBAAA,GAAA,wBAAA;AAQrB,cCPA,cAAA,SAAuB,KAAA,CDOa;iBCNzB;;;EALZ,SAAA,KAAA,CAAA,EAQc,KARG;EAEjB,WAAA,CAAA,IAAA,EASF,kBAToB,EAAA,OAAA,EAAA,MAAA,EAAA,OASpB,CAToB,EAAA;IAEjB,SAAA,CAAA,EAAA,MAAe;IACJ,WAAA,CAAA,EAAA,MAAA;IAGE,KAAA,CAAA,EAKwC,KALxC;EAGhB,CAAA;EAEwD,cAAA,CAAA,CAAA,EAAA,MAAA;;AATzB,UAsCxB,eAAA,CAtCwB;EAsCxB,GAAA,EAAA,CAAA,UAAA,CAAA,CAAe,OAAA,EACH,uBADG,EAAA,GACyB,OADzB,CACiC,UADjC,CAAA;EACH,GAAA,EAAA,CAAA,UAAA,CAAA,CAAA,OAAA,EACA,uBADA,EAAA,KAAA,EACgC,UADhC,EAAA,GAC+C,OAD/C,CAAA,IAAA,CAAA;EAAoC,SAAA,EAAA,CAAA,UAAA,CAAA,CAAA,OAAA,EAGpD,uBAHoD,EAAA,QAAA,EAInD,iBAJmD,CAIjC,UAJiC,CAAA,EAAA,GAAA,GAAA,GAAA,IAAA"}
package/dist/vue.cjs ADDED
@@ -0,0 +1,69 @@
1
+ const require_renderer = require('./renderer-D3YziJ_U.cjs');
2
+ let vue = require("vue");
3
+
4
+ //#region src/renderer/vue.ts
5
+ const createChannelOptions = (options) => {
6
+ const globalConfig = require_renderer.getGlobalConfig();
7
+ return {
8
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
9
+ name: options.name
10
+ };
11
+ };
12
+ const resolveSyncValue = (value) => {
13
+ if (value !== null && typeof value === "object" && (0, vue.isProxy)(value)) return (0, vue.toRaw)(value);
14
+ return value;
15
+ };
16
+ const createRemoteUpdateTracker = (stateRef, isSynced) => {
17
+ let isApplyingRemoteValue = false;
18
+ let lastRemoteValue = void 0;
19
+ const applyRemoteValue = (value) => {
20
+ const resolvedValue = resolveSyncValue(value);
21
+ isApplyingRemoteValue = true;
22
+ lastRemoteValue = resolvedValue;
23
+ stateRef.value = resolvedValue;
24
+ isSynced.value = true;
25
+ isApplyingRemoteValue = false;
26
+ };
27
+ const shouldSkipLocalSync = (currentValue) => isApplyingRemoteValue && resolveSyncValue(currentValue) === lastRemoteValue;
28
+ return {
29
+ applyRemoteValue,
30
+ shouldSkipLocalSync
31
+ };
32
+ };
33
+ const createStateWatcher = ({ bridge, channelOptions, deep, stateRef, tracker }) => (0, vue.watch)(stateRef, (nextValue) => {
34
+ if (tracker.shouldSkipLocalSync(nextValue)) return;
35
+ bridge.set(channelOptions, resolveSyncValue(nextValue));
36
+ }, {
37
+ deep: Boolean(deep),
38
+ flush: "sync"
39
+ });
40
+ const useSyncState = (initialValue, options) => {
41
+ const stateRef = (0, vue.ref)(initialValue);
42
+ const isSynced = (0, vue.ref)(false);
43
+ const globalConfig = require_renderer.getGlobalConfig();
44
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
45
+ const channelOptions = createChannelOptions(options);
46
+ const tracker = createRemoteUpdateTracker(stateRef, isSynced);
47
+ const stopWatcher = createStateWatcher({
48
+ bridge,
49
+ channelOptions,
50
+ deep: options.deep,
51
+ stateRef,
52
+ tracker
53
+ });
54
+ let unsubscribe = void 0;
55
+ (0, vue.onMounted)(() => {
56
+ unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);
57
+ bridge.get(channelOptions).then(tracker.applyRemoteValue);
58
+ });
59
+ (0, vue.onBeforeUnmount)(() => {
60
+ stopWatcher();
61
+ unsubscribe?.();
62
+ unsubscribe = void 0;
63
+ });
64
+ stateRef.isSynced = isSynced;
65
+ return stateRef;
66
+ };
67
+
68
+ //#endregion
69
+ exports.useSyncState = useSyncState;
package/dist/vue.d.cts ADDED
@@ -0,0 +1,15 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-C18dHgLI.cjs";
2
+ import { Ref } from "vue";
3
+
4
+ //#region src/renderer/vue.d.ts
5
+ interface UseSyncStateOptions extends SyncStateChannelOptions {
6
+ bridge?: SyncStateBridge;
7
+ deep?: boolean;
8
+ }
9
+ interface SyncStateRef<StateValue> extends Ref<StateValue> {
10
+ isSynced: Ref<boolean>;
11
+ }
12
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: UseSyncStateOptions) => SyncStateRef<StateValue>;
13
+ //#endregion
14
+ export { SyncStateRef, UseSyncStateOptions, useSyncState };
15
+ //# sourceMappingURL=vue.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.d.cts","names":[],"sources":["../src/renderer/vue.ts"],"sourcesContent":[],"mappings":";;;;UAOiB,mBAAA,SAA4B;EAA5B,MAAA,CAAA,EACN,eAD0B;EAqFpB,IAAA,CAAA,EAAA,OAAA;;AACL,UADK,YACL,CAAA,UAAA,CAAA,SADsC,GACtC,CAD0C,UAC1C,CAAA,CAAA;EADsC,QAAA,EACtC,GADsC,CAAA,OAAA,CAAA;;AAIrC,cAAA,YAkCZ,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAjCe,UAiCf,EAAA,OAAA,EAhCU,mBAgCV,EAAA,GA/BE,YA+BF,CA/Be,UA+Bf,CAAA"}
package/dist/vue.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-7wPPX0ty.js";
2
+ import { Ref } from "vue";
3
+
4
+ //#region src/renderer/vue.d.ts
5
+ interface UseSyncStateOptions extends SyncStateChannelOptions {
6
+ bridge?: SyncStateBridge;
7
+ deep?: boolean;
8
+ }
9
+ interface SyncStateRef<StateValue> extends Ref<StateValue> {
10
+ isSynced: Ref<boolean>;
11
+ }
12
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: UseSyncStateOptions) => SyncStateRef<StateValue>;
13
+ //#endregion
14
+ export { SyncStateRef, UseSyncStateOptions, useSyncState };
15
+ //# sourceMappingURL=vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.d.ts","names":[],"sources":["../src/renderer/vue.ts"],"sourcesContent":[],"mappings":";;;;UAOiB,mBAAA,SAA4B;EAA5B,MAAA,CAAA,EACN,eAD0B;EAqFpB,IAAA,CAAA,EAAA,OAAA;;AACL,UADK,YACL,CAAA,UAAA,CAAA,SADsC,GACtC,CAD0C,UAC1C,CAAA,CAAA;EADsC,QAAA,EACtC,GADsC,CAAA,OAAA,CAAA;;AAIrC,cAAA,YAkCZ,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAjCe,UAiCf,EAAA,OAAA,EAhCU,mBAgCV,EAAA,GA/BE,YA+BF,CA/Be,UA+Bf,CAAA"}
package/dist/vue.js ADDED
@@ -0,0 +1,70 @@
1
+ import { a as resolveSyncStateBridge, t as getGlobalConfig } from "./renderer-C7zF3UQm.js";
2
+ import { isProxy, onBeforeUnmount, onMounted, ref, toRaw, watch } from "vue";
3
+
4
+ //#region src/renderer/vue.ts
5
+ const createChannelOptions = (options) => {
6
+ const globalConfig = getGlobalConfig();
7
+ return {
8
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
9
+ name: options.name
10
+ };
11
+ };
12
+ const resolveSyncValue = (value) => {
13
+ if (value !== null && typeof value === "object" && isProxy(value)) return toRaw(value);
14
+ return value;
15
+ };
16
+ const createRemoteUpdateTracker = (stateRef, isSynced) => {
17
+ let isApplyingRemoteValue = false;
18
+ let lastRemoteValue = void 0;
19
+ const applyRemoteValue = (value) => {
20
+ const resolvedValue = resolveSyncValue(value);
21
+ isApplyingRemoteValue = true;
22
+ lastRemoteValue = resolvedValue;
23
+ stateRef.value = resolvedValue;
24
+ isSynced.value = true;
25
+ isApplyingRemoteValue = false;
26
+ };
27
+ const shouldSkipLocalSync = (currentValue) => isApplyingRemoteValue && resolveSyncValue(currentValue) === lastRemoteValue;
28
+ return {
29
+ applyRemoteValue,
30
+ shouldSkipLocalSync
31
+ };
32
+ };
33
+ const createStateWatcher = ({ bridge, channelOptions, deep, stateRef, tracker }) => watch(stateRef, (nextValue) => {
34
+ if (tracker.shouldSkipLocalSync(nextValue)) return;
35
+ bridge.set(channelOptions, resolveSyncValue(nextValue));
36
+ }, {
37
+ deep: Boolean(deep),
38
+ flush: "sync"
39
+ });
40
+ const useSyncState = (initialValue, options) => {
41
+ const stateRef = ref(initialValue);
42
+ const isSynced = ref(false);
43
+ const globalConfig = getGlobalConfig();
44
+ const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
45
+ const channelOptions = createChannelOptions(options);
46
+ const tracker = createRemoteUpdateTracker(stateRef, isSynced);
47
+ const stopWatcher = createStateWatcher({
48
+ bridge,
49
+ channelOptions,
50
+ deep: options.deep,
51
+ stateRef,
52
+ tracker
53
+ });
54
+ let unsubscribe = void 0;
55
+ onMounted(() => {
56
+ unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);
57
+ bridge.get(channelOptions).then(tracker.applyRemoteValue);
58
+ });
59
+ onBeforeUnmount(() => {
60
+ stopWatcher();
61
+ unsubscribe?.();
62
+ unsubscribe = void 0;
63
+ });
64
+ stateRef.isSynced = isSynced;
65
+ return stateRef;
66
+ };
67
+
68
+ //#endregion
69
+ export { useSyncState };
70
+ //# sourceMappingURL=vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.js","names":[],"sources":["../src/renderer/vue.ts"],"sourcesContent":["import { isProxy, onBeforeUnmount, onMounted, ref, toRaw, watch, type Ref } from \"vue\";\n\nimport type { SyncStateChannelOptions } from \"../channels\";\nimport type { SyncStateBridge } from \"../types\";\nimport { resolveSyncStateBridge } from \"./bridge\";\nimport { getGlobalConfig } from \"./index\";\n\nexport interface UseSyncStateOptions extends SyncStateChannelOptions {\n bridge?: SyncStateBridge;\n deep?: boolean;\n}\n\ninterface RemoteUpdateTracker<StateValue> {\n applyRemoteValue: (value: StateValue) => void;\n shouldSkipLocalSync: (currentValue: StateValue) => boolean;\n}\n\nconst createChannelOptions = (options: UseSyncStateOptions): SyncStateChannelOptions => {\n const globalConfig = getGlobalConfig();\n return {\n baseChannel: options.baseChannel ?? globalConfig.baseChannel,\n name: options.name,\n };\n};\n\n// Convert Vue Proxy to serializable raw value\nconst resolveSyncValue = <StateValue>(value: StateValue): StateValue => {\n if (value !== null && typeof value === \"object\" && isProxy(value)) {\n return toRaw(value) as StateValue;\n }\n\n return value;\n};\n\nconst createRemoteUpdateTracker = <StateValue>(\n stateRef: Ref<StateValue>,\n isSynced: Ref<boolean>,\n): RemoteUpdateTracker<StateValue> => {\n let isApplyingRemoteValue = false;\n // Record the last raw value synced from main process\n let lastRemoteValue: StateValue | undefined = undefined;\n\n const applyRemoteValue = (value: StateValue): void => {\n // Convert remote synced value to raw object\n const resolvedValue = resolveSyncValue(value);\n isApplyingRemoteValue = true;\n lastRemoteValue = resolvedValue;\n stateRef.value = resolvedValue;\n isSynced.value = true;\n isApplyingRemoteValue = false;\n };\n\n const shouldSkipLocalSync = (currentValue: StateValue): boolean =>\n // Skip sync if we're currently applying a remote value AND it matches\n // This prevents infinite loops while allowing all local updates to sync\n isApplyingRemoteValue && resolveSyncValue(currentValue) === lastRemoteValue;\n\n return {\n applyRemoteValue,\n shouldSkipLocalSync,\n };\n};\n\ninterface StateWatcherOptions<StateValue> {\n bridge: SyncStateBridge;\n channelOptions: SyncStateChannelOptions;\n stateRef: Ref<StateValue>;\n tracker: RemoteUpdateTracker<StateValue>;\n deep?: boolean;\n}\n\nconst createStateWatcher = <StateValue>({\n bridge,\n channelOptions,\n deep,\n stateRef,\n tracker,\n}: StateWatcherOptions<StateValue>): (() => void) =>\n watch(\n stateRef,\n (nextValue: StateValue) => {\n if (tracker.shouldSkipLocalSync(nextValue)) {\n return;\n }\n void bridge.set(channelOptions, resolveSyncValue(nextValue));\n },\n {\n deep: Boolean(deep),\n flush: \"sync\",\n },\n );\n\nexport interface SyncStateRef<StateValue> extends Ref<StateValue> {\n isSynced: Ref<boolean>;\n}\n\nexport const useSyncState = <StateValue>(\n initialValue: StateValue,\n options: UseSyncStateOptions,\n): SyncStateRef<StateValue> => {\n const stateRef = ref(initialValue) as unknown as SyncStateRef<StateValue>;\n const isSynced = ref(false);\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = createChannelOptions(options);\n const tracker = createRemoteUpdateTracker(stateRef, isSynced);\n const stopWatcher = createStateWatcher({\n bridge,\n channelOptions,\n deep: options.deep,\n stateRef,\n tracker,\n });\n\n let unsubscribe: (() => void) | undefined = undefined;\n\n onMounted(() => {\n unsubscribe = bridge.subscribe(channelOptions, tracker.applyRemoteValue);\n void bridge.get<StateValue>(channelOptions).then(tracker.applyRemoteValue);\n });\n\n onBeforeUnmount(() => {\n stopWatcher();\n unsubscribe?.();\n unsubscribe = undefined;\n });\n\n stateRef.isSynced = isSynced;\n\n return stateRef;\n};\n"],"mappings":";;;;AAiBA,MAAM,wBAAwB,YAA0D;CACtF,MAAM,eAAe,iBAAiB;AACtC,QAAO;EACL,aAAa,QAAQ,eAAe,aAAa;EACjD,MAAM,QAAQ;EACf;;AAIH,MAAM,oBAAgC,UAAkC;AACtE,KAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,QAAQ,MAAM,CAC/D,QAAO,MAAM,MAAM;AAGrB,QAAO;;AAGT,MAAM,6BACJ,UACA,aACoC;CACpC,IAAI,wBAAwB;CAE5B,IAAI,kBAA0C;CAE9C,MAAM,oBAAoB,UAA4B;EAEpD,MAAM,gBAAgB,iBAAiB,MAAM;AAC7C,0BAAwB;AACxB,oBAAkB;AAClB,WAAS,QAAQ;AACjB,WAAS,QAAQ;AACjB,0BAAwB;;CAG1B,MAAM,uBAAuB,iBAG3B,yBAAyB,iBAAiB,aAAa,KAAK;AAE9D,QAAO;EACL;EACA;EACD;;AAWH,MAAM,sBAAkC,EACtC,QACA,gBACA,MACA,UACA,cAEA,MACE,WACC,cAA0B;AACzB,KAAI,QAAQ,oBAAoB,UAAU,CACxC;AAEF,CAAK,OAAO,IAAI,gBAAgB,iBAAiB,UAAU,CAAC;GAE9D;CACE,MAAM,QAAQ,KAAK;CACnB,OAAO;CACR,CACF;AAMH,MAAa,gBACX,cACA,YAC6B;CAC7B,MAAM,WAAW,IAAI,aAAa;CAClC,MAAM,WAAW,IAAI,MAAM;CAC3B,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,qBAAqB,QAAQ;CACpD,MAAM,UAAU,0BAA0B,UAAU,SAAS;CAC7D,MAAM,cAAc,mBAAmB;EACrC;EACA;EACA,MAAM,QAAQ;EACd;EACA;EACD,CAAC;CAEF,IAAI,cAAwC;AAE5C,iBAAgB;AACd,gBAAc,OAAO,UAAU,gBAAgB,QAAQ,iBAAiB;AACxE,EAAK,OAAO,IAAgB,eAAe,CAAC,KAAK,QAAQ,iBAAiB;GAC1E;AAEF,uBAAsB;AACpB,eAAa;AACb,iBAAe;AACf,gBAAc;GACd;AAEF,UAAS,WAAW;AAEpB,QAAO"}
@@ -0,0 +1,193 @@
1
+ const require_renderer = require('./renderer-D3YziJ_U.cjs');
2
+ let react = require("react");
3
+ let zustand_vanilla = require("zustand/vanilla");
4
+
5
+ //#region src/renderer/zustand.ts
6
+ const createChannelOptions = (options) => {
7
+ const globalConfig = require_renderer.getGlobalConfig();
8
+ return {
9
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
10
+ name: options.name
11
+ };
12
+ };
13
+ /**
14
+ * Zustand middleware that syncs store state with Electron main process
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { create } from 'zustand';
19
+ * import { syncStateMiddleware } from 'electron-state-sync/zustand';
20
+ *
21
+ * const useStore = create(
22
+ * syncStateMiddleware({ name: 'counter' })((set) => ({
23
+ * count: 0,
24
+ * increment: () => set((state) => ({ count: state.count + 1 }))
25
+ * }))
26
+ * );
27
+ * ```
28
+ */
29
+ const syncStateMiddleware = (options) => (config) => (set, get, api) => {
30
+ const globalConfig = require_renderer.getGlobalConfig();
31
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
32
+ const channelOptions = createChannelOptions(options);
33
+ let isApplyingRemoteValue = false;
34
+ const originalSetState = api.setState;
35
+ api.setState = (partial, replace) => {
36
+ const currentState = get();
37
+ if (isApplyingRemoteValue) {
38
+ isApplyingRemoteValue = false;
39
+ return originalSetState(partial, replace);
40
+ }
41
+ let nextState;
42
+ if (typeof partial === "function") nextState = partial(currentState);
43
+ else if (replace) nextState = partial;
44
+ else nextState = {
45
+ ...currentState,
46
+ ...partial
47
+ };
48
+ const dataOnlyState = Object.fromEntries(Object.entries(nextState).filter(([_, v]) => typeof v !== "function"));
49
+ bridge.set(channelOptions, dataOnlyState);
50
+ return originalSetState(partial, replace);
51
+ };
52
+ const applyRemoteValue = (value) => {
53
+ isApplyingRemoteValue = true;
54
+ const currentState = get();
55
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) api.setState({
56
+ ...currentState,
57
+ ...value
58
+ }, true);
59
+ else {
60
+ const keys = Object.keys(currentState).filter((k) => typeof currentState[k] !== "function");
61
+ if (keys.length === 1) api.setState({
62
+ ...currentState,
63
+ [keys[0]]: value
64
+ }, true);
65
+ else api.setState(value, true);
66
+ }
67
+ };
68
+ const unsubscribe = bridge.subscribe(channelOptions, applyRemoteValue);
69
+ bridge.get(channelOptions).then(applyRemoteValue);
70
+ const store = config(set, get, api);
71
+ const storeApi = api;
72
+ if (storeApi.destroy) {
73
+ const originalDestroy = storeApi.destroy;
74
+ storeApi.destroy = () => {
75
+ unsubscribe();
76
+ originalDestroy();
77
+ };
78
+ }
79
+ return store;
80
+ };
81
+ /**
82
+ * Hook to access sync state for a Zustand store
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * import { useSyncState } from 'electron-state-sync/zustand';
87
+ *
88
+ * function App() {
89
+ * const { state, isSynced } = useSyncState({ name: 'counter' });
90
+ * return <div>{state?.count}</div>;
91
+ * }
92
+ * ```
93
+ */
94
+ const useSyncState = (options) => {
95
+ const [isSynced, setIsSynced] = (0, react.useState)(false);
96
+ const [state, setState] = (0, react.useState)();
97
+ const globalConfig = require_renderer.getGlobalConfig();
98
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
99
+ const channelOptions = (0, react.useMemo)(() => createChannelOptions(options), [options.baseChannel, options.name]);
100
+ (0, react.useEffect)(() => {
101
+ const unsubscribe = bridge.subscribe(channelOptions, (value) => {
102
+ setState(value);
103
+ setIsSynced(true);
104
+ });
105
+ bridge.get(channelOptions).then((value) => {
106
+ setState(value);
107
+ setIsSynced(true);
108
+ });
109
+ return () => {
110
+ unsubscribe();
111
+ };
112
+ }, [bridge, channelOptions]);
113
+ return {
114
+ isSynced,
115
+ state
116
+ };
117
+ };
118
+ /**
119
+ * Create a synced Zustand store (hook-less version for vanilla JS)
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * import { createSyncedStore } from 'electron-state-sync/zustand';
124
+ *
125
+ * const store = createSyncedStore(
126
+ * { count: 0 },
127
+ * { name: 'counter' },
128
+ * (set) => ({
129
+ * increment: () => set((state) => ({ count: state.count + 1 }))
130
+ * })
131
+ * );
132
+ * ```
133
+ */
134
+ const createSyncedStore = (initialState, options) => {
135
+ const globalConfig = require_renderer.getGlobalConfig();
136
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
137
+ const channelOptions = createChannelOptions(options);
138
+ let isApplyingRemoteValue = false;
139
+ const store = (0, zustand_vanilla.createStore)()(() => initialState);
140
+ const originalSetState = store.setState.bind(store);
141
+ store.setState = (partial, replace) => {
142
+ const currentState = store.getState();
143
+ if (isApplyingRemoteValue) {
144
+ isApplyingRemoteValue = false;
145
+ return originalSetState(partial, replace);
146
+ }
147
+ let nextState;
148
+ if (typeof partial === "function") nextState = partial(currentState);
149
+ else if (replace) nextState = partial;
150
+ else nextState = {
151
+ ...currentState,
152
+ ...partial
153
+ };
154
+ const dataOnlyState = Object.fromEntries(Object.entries(nextState).filter(([_, v]) => typeof v !== "function"));
155
+ bridge.set(channelOptions, dataOnlyState);
156
+ return originalSetState(partial, replace);
157
+ };
158
+ const applyRemoteValue = (value) => {
159
+ isApplyingRemoteValue = true;
160
+ const currentState = store.getState();
161
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) store.setState({
162
+ ...currentState,
163
+ ...value
164
+ });
165
+ else {
166
+ const keys = Object.keys(currentState).filter((k) => typeof currentState[k] !== "function");
167
+ if (keys.length === 1) store.setState({
168
+ ...currentState,
169
+ [keys[0]]: value
170
+ });
171
+ else store.setState(value);
172
+ }
173
+ };
174
+ const unsubscribe = bridge.subscribe(channelOptions, applyRemoteValue);
175
+ bridge.get(channelOptions).then(applyRemoteValue);
176
+ const storeWithCleanup = store;
177
+ if (storeWithCleanup.destroy) {
178
+ const originalDestroy = storeWithCleanup.destroy;
179
+ storeWithCleanup.destroy = () => {
180
+ unsubscribe();
181
+ originalDestroy();
182
+ };
183
+ } else storeWithCleanup.destroy = () => {
184
+ unsubscribe();
185
+ };
186
+ return store;
187
+ };
188
+
189
+ //#endregion
190
+ exports.createSyncedStore = createSyncedStore;
191
+ exports.syncStateMiddleware = syncStateMiddleware;
192
+ exports.useSyncState = useSyncState;
193
+ exports.useZustandSyncState = useSyncState;