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,58 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-C18dHgLI.cjs";
2
+
3
+ //#region src/renderer/react-query.d.ts
4
+ interface SyncStateQueryOptions extends SyncStateChannelOptions {
5
+ bridge?: SyncStateBridge;
6
+ staleTime?: number;
7
+ gcTime?: number;
8
+ queryKey?: unknown[];
9
+ }
10
+ /**
11
+ * Hook for syncing state with TanStack Query
12
+ *
13
+ * Provides a query-based interface to sync state between renderer and main process.
14
+ * Automatically refetches when remote changes occur.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { useSyncState } from 'electron-state-sync/react-query';
19
+ *
20
+ * function App() {
21
+ * const { data: count, isSynced, update } = useSyncState(0, {
22
+ * name: 'counter'
23
+ * });
24
+ *
25
+ * return <div onClick={() => update(5)}>{count}</div>;
26
+ * }
27
+ * ```
28
+ */
29
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: SyncStateQueryOptions) => {
30
+ data: StateValue;
31
+ isSynced: boolean;
32
+ update: (value: StateValue) => void;
33
+ };
34
+ /**
35
+ * Hook for creating a mutation to update synced state
36
+ *
37
+ * Provides a simpler mutation-only interface for updating state.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { useSyncMutation } from 'electron-state-sync/react-query';
42
+ *
43
+ * function App() {
44
+ * const { mutate, isSynced } = useSyncMutation<number>({
45
+ * name: 'counter'
46
+ * });
47
+ *
48
+ * return <button onClick={() => mutate(10)}>Set to 10</button>;
49
+ * }
50
+ * ```
51
+ */
52
+ declare const useSyncMutation: <StateValue>(options: SyncStateQueryOptions) => {
53
+ mutate: (value: StateValue) => void;
54
+ isSynced: boolean;
55
+ };
56
+ //#endregion
57
+ export { SyncStateQueryOptions, useSyncState as useQuerySyncState, useSyncState, useSyncMutation };
58
+ //# sourceMappingURL=react-query.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-query.d.cts","names":[],"sources":["../src/renderer/react-query.ts"],"sourcesContent":[],"mappings":";;;UAYiB,qBAAA,SAA8B;EAA9B,MAAA,CAAA,EACN,eAD4B;EAkC1B,SAAA,CAAA,EAAA,MA6DZ;EA5De,MAAA,CAAA,EAAA,MAAA;EACL,QAAA,CAAA,EAAA,OAAA,EAAA;;;;AA+EX;;;;;;;;;;;;;;;;;cAjFa,yCACG,qBACL;QAEH;;kBAEU;;;;;;;;;;;;;;;;;;;;cA2EL,uCACF;kBACU"}
@@ -0,0 +1,58 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-7wPPX0ty.js";
2
+
3
+ //#region src/renderer/react-query.d.ts
4
+ interface SyncStateQueryOptions extends SyncStateChannelOptions {
5
+ bridge?: SyncStateBridge;
6
+ staleTime?: number;
7
+ gcTime?: number;
8
+ queryKey?: unknown[];
9
+ }
10
+ /**
11
+ * Hook for syncing state with TanStack Query
12
+ *
13
+ * Provides a query-based interface to sync state between renderer and main process.
14
+ * Automatically refetches when remote changes occur.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { useSyncState } from 'electron-state-sync/react-query';
19
+ *
20
+ * function App() {
21
+ * const { data: count, isSynced, update } = useSyncState(0, {
22
+ * name: 'counter'
23
+ * });
24
+ *
25
+ * return <div onClick={() => update(5)}>{count}</div>;
26
+ * }
27
+ * ```
28
+ */
29
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: SyncStateQueryOptions) => {
30
+ data: StateValue;
31
+ isSynced: boolean;
32
+ update: (value: StateValue) => void;
33
+ };
34
+ /**
35
+ * Hook for creating a mutation to update synced state
36
+ *
37
+ * Provides a simpler mutation-only interface for updating state.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { useSyncMutation } from 'electron-state-sync/react-query';
42
+ *
43
+ * function App() {
44
+ * const { mutate, isSynced } = useSyncMutation<number>({
45
+ * name: 'counter'
46
+ * });
47
+ *
48
+ * return <button onClick={() => mutate(10)}>Set to 10</button>;
49
+ * }
50
+ * ```
51
+ */
52
+ declare const useSyncMutation: <StateValue>(options: SyncStateQueryOptions) => {
53
+ mutate: (value: StateValue) => void;
54
+ isSynced: boolean;
55
+ };
56
+ //#endregion
57
+ export { SyncStateQueryOptions, useSyncState as useQuerySyncState, useSyncState, useSyncMutation };
58
+ //# sourceMappingURL=react-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-query.d.ts","names":[],"sources":["../src/renderer/react-query.ts"],"sourcesContent":[],"mappings":";;;UAYiB,qBAAA,SAA8B;EAA9B,MAAA,CAAA,EACN,eAD4B;EAkC1B,SAAA,CAAA,EAAA,MA6DZ;EA5De,MAAA,CAAA,EAAA,MAAA;EACL,QAAA,CAAA,EAAA,OAAA,EAAA;;;;AA+EX;;;;;;;;;;;;;;;;;cAjFa,yCACG,qBACL;QAEH;;kBAEU;;;;;;;;;;;;;;;;;;;;cA2EL,uCACF;kBACU"}
@@ -0,0 +1,112 @@
1
+ import { a as resolveSyncStateBridge, t as getGlobalConfig } from "./renderer-C7zF3UQm.js";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ import { useMutation, useQuery } from "@tanstack/react-query";
4
+
5
+ //#region src/renderer/react-query.ts
6
+ const DEFAULT_STALE_TIME = 1e3;
7
+ const DEFAULT_GC_TIME = 3e5;
8
+ const createChannelOptions = (options) => {
9
+ const globalConfig = getGlobalConfig();
10
+ return {
11
+ baseChannel: options.baseChannel ?? globalConfig.baseChannel,
12
+ name: options.name
13
+ };
14
+ };
15
+ /**
16
+ * Hook for syncing state with TanStack Query
17
+ *
18
+ * Provides a query-based interface to sync state between renderer and main process.
19
+ * Automatically refetches when remote changes occur.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { useSyncState } from 'electron-state-sync/react-query';
24
+ *
25
+ * function App() {
26
+ * const { data: count, isSynced, update } = useSyncState(0, {
27
+ * name: 'counter'
28
+ * });
29
+ *
30
+ * return <div onClick={() => update(5)}>{count}</div>;
31
+ * }
32
+ * ```
33
+ */
34
+ const useSyncState = (initialValue, options) => {
35
+ const [isSynced, setIsSynced] = useState(false);
36
+ const globalConfig = getGlobalConfig();
37
+ const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
38
+ const channelOptions = useMemo(() => createChannelOptions(options), [options.baseChannel, options.name]);
39
+ const query = useQuery({
40
+ gcTime: options.gcTime ?? DEFAULT_GC_TIME,
41
+ queryFn: () => bridge.get(channelOptions),
42
+ queryKey: options.queryKey ?? [
43
+ "sync-state",
44
+ channelOptions.baseChannel,
45
+ channelOptions.name
46
+ ],
47
+ refetchOnWindowFocus: false,
48
+ staleTime: options.staleTime ?? DEFAULT_STALE_TIME
49
+ });
50
+ const mutation = useMutation({ mutationFn: (value) => bridge.set(channelOptions, value) });
51
+ useEffect(() => {
52
+ const unsubscribe = bridge.subscribe(channelOptions, () => {
53
+ query.refetch();
54
+ });
55
+ return () => {
56
+ unsubscribe();
57
+ };
58
+ }, [
59
+ bridge,
60
+ channelOptions,
61
+ query
62
+ ]);
63
+ useEffect(() => {
64
+ if (!query.isLoading && !query.isFetching) setIsSynced(true);
65
+ }, [query.isLoading, query.isFetching]);
66
+ const update = useCallback((value) => {
67
+ mutation.mutate(value);
68
+ }, [mutation]);
69
+ return {
70
+ data: query.data ?? initialValue,
71
+ isSynced,
72
+ update
73
+ };
74
+ };
75
+ /**
76
+ * Hook for creating a mutation to update synced state
77
+ *
78
+ * Provides a simpler mutation-only interface for updating state.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * import { useSyncMutation } from 'electron-state-sync/react-query';
83
+ *
84
+ * function App() {
85
+ * const { mutate, isSynced } = useSyncMutation<number>({
86
+ * name: 'counter'
87
+ * });
88
+ *
89
+ * return <button onClick={() => mutate(10)}>Set to 10</button>;
90
+ * }
91
+ * ```
92
+ */
93
+ const useSyncMutation = (options) => {
94
+ const [isSynced, setIsSynced] = useState(false);
95
+ const globalConfig = getGlobalConfig();
96
+ const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
97
+ const channelOptions = useMemo(() => createChannelOptions(options), [options.baseChannel, options.name]);
98
+ useEffect(() => {
99
+ bridge.get(channelOptions).then(() => {
100
+ setIsSynced(true);
101
+ });
102
+ }, [bridge, channelOptions]);
103
+ const mutation = useMutation({ mutationFn: (value) => bridge.set(channelOptions, value) });
104
+ return {
105
+ isSynced,
106
+ mutate: (value) => mutation.mutate(value)
107
+ };
108
+ };
109
+
110
+ //#endregion
111
+ export { useSyncState as useQuerySyncState, useSyncState, useSyncMutation };
112
+ //# sourceMappingURL=react-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-query.js","names":[],"sources":["../src/renderer/react-query.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useMutation, useQuery } from \"@tanstack/react-query\";\n\nimport type { SyncStateChannelOptions } from \"../channels\";\nimport type { SyncStateBridge } from \"../types\";\nimport { resolveSyncStateBridge } from \"./bridge\";\nimport { getGlobalConfig } from \"./index\";\n\n// Default query timings\nconst DEFAULT_STALE_TIME = 1000;\nconst DEFAULT_GC_TIME = 300_000;\n\nexport interface SyncStateQueryOptions extends SyncStateChannelOptions {\n bridge?: SyncStateBridge;\n staleTime?: number;\n gcTime?: number;\n queryKey?: unknown[];\n}\n\nconst createChannelOptions = (options: SyncStateQueryOptions): SyncStateChannelOptions => {\n const globalConfig = getGlobalConfig();\n return {\n baseChannel: options.baseChannel ?? globalConfig.baseChannel,\n name: options.name,\n };\n};\n\n/**\n * Hook for syncing state with TanStack Query\n *\n * Provides a query-based interface to sync state between renderer and main process.\n * Automatically refetches when remote changes occur.\n *\n * @example\n * ```typescript\n * import { useSyncState } from 'electron-state-sync/react-query';\n *\n * function App() {\n * const { data: count, isSynced, update } = useSyncState(0, {\n * name: 'counter'\n * });\n *\n * return <div onClick={() => update(5)}>{count}</div>;\n * }\n * ```\n */\nexport const useSyncState = <StateValue>(\n initialValue: StateValue,\n options: SyncStateQueryOptions,\n): {\n data: StateValue;\n isSynced: boolean;\n update: (value: StateValue) => void;\n} => {\n const [isSynced, setIsSynced] = useState(false);\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = useMemo(\n () => createChannelOptions(options),\n [options.baseChannel, options.name],\n );\n\n // Query for fetching state from main process\n const query = useQuery({\n gcTime: options.gcTime ?? DEFAULT_GC_TIME,\n queryFn: () => bridge.get<StateValue>(channelOptions),\n queryKey: options.queryKey ?? [\"sync-state\", channelOptions.baseChannel, channelOptions.name],\n refetchOnWindowFocus: false,\n staleTime: options.staleTime ?? DEFAULT_STALE_TIME,\n });\n\n // Mutation for updating state\n const mutation = useMutation({\n mutationFn: (value: StateValue) => bridge.set(channelOptions, value),\n });\n\n // Subscribe to remote updates and refetch query\n useEffect(() => {\n const unsubscribe = bridge.subscribe<StateValue>(channelOptions, () => {\n query.refetch();\n });\n\n return () => {\n unsubscribe();\n };\n }, [bridge, channelOptions, query]);\n\n // Check sync status on mount\n useEffect(() => {\n if (!query.isLoading && !query.isFetching) {\n setIsSynced(true);\n }\n }, [query.isLoading, query.isFetching]);\n\n // Update function that mutates state\n const update = useCallback(\n (value: StateValue) => {\n mutation.mutate(value);\n },\n [mutation],\n );\n\n return {\n data: query.data ?? initialValue,\n isSynced,\n update,\n };\n};\n\n/**\n * Hook for creating a mutation to update synced state\n *\n * Provides a simpler mutation-only interface for updating state.\n *\n * @example\n * ```typescript\n * import { useSyncMutation } from 'electron-state-sync/react-query';\n *\n * function App() {\n * const { mutate, isSynced } = useSyncMutation<number>({\n * name: 'counter'\n * });\n *\n * return <button onClick={() => mutate(10)}>Set to 10</button>;\n * }\n * ```\n */\nexport const useSyncMutation = <StateValue>(\n options: SyncStateQueryOptions,\n): { mutate: (value: StateValue) => void; isSynced: boolean } => {\n const [isSynced, setIsSynced] = useState(false);\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = useMemo(\n () => createChannelOptions(options),\n [options.baseChannel, options.name],\n );\n\n // Check if synced on mount\n useEffect(() => {\n void bridge.get<StateValue>(channelOptions).then(() => {\n setIsSynced(true);\n });\n }, [bridge, channelOptions]);\n\n const mutation = useMutation({\n mutationFn: (value: StateValue) => bridge.set(channelOptions, value),\n });\n\n return {\n isSynced,\n mutate: (value: StateValue) => mutation.mutate(value),\n };\n};\n\nexport { useSyncState as useQuerySyncState };\n"],"mappings":";;;;;AASA,MAAM,qBAAqB;AAC3B,MAAM,kBAAkB;AASxB,MAAM,wBAAwB,YAA4D;CACxF,MAAM,eAAe,iBAAiB;AACtC,QAAO;EACL,aAAa,QAAQ,eAAe,aAAa;EACjD,MAAM,QAAQ;EACf;;;;;;;;;;;;;;;;;;;;;AAsBH,MAAa,gBACX,cACA,YAKG;CACH,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAC/C,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,cACf,qBAAqB,QAAQ,EACnC,CAAC,QAAQ,aAAa,QAAQ,KAAK,CACpC;CAGD,MAAM,QAAQ,SAAS;EACrB,QAAQ,QAAQ,UAAU;EAC1B,eAAe,OAAO,IAAgB,eAAe;EACrD,UAAU,QAAQ,YAAY;GAAC;GAAc,eAAe;GAAa,eAAe;GAAK;EAC7F,sBAAsB;EACtB,WAAW,QAAQ,aAAa;EACjC,CAAC;CAGF,MAAM,WAAW,YAAY,EAC3B,aAAa,UAAsB,OAAO,IAAI,gBAAgB,MAAM,EACrE,CAAC;AAGF,iBAAgB;EACd,MAAM,cAAc,OAAO,UAAsB,sBAAsB;AACrE,SAAM,SAAS;IACf;AAEF,eAAa;AACX,gBAAa;;IAEd;EAAC;EAAQ;EAAgB;EAAM,CAAC;AAGnC,iBAAgB;AACd,MAAI,CAAC,MAAM,aAAa,CAAC,MAAM,WAC7B,aAAY,KAAK;IAElB,CAAC,MAAM,WAAW,MAAM,WAAW,CAAC;CAGvC,MAAM,SAAS,aACZ,UAAsB;AACrB,WAAS,OAAO,MAAM;IAExB,CAAC,SAAS,CACX;AAED,QAAO;EACL,MAAM,MAAM,QAAQ;EACpB;EACA;EACD;;;;;;;;;;;;;;;;;;;;AAqBH,MAAa,mBACX,YAC+D;CAC/D,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAC/C,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,cACf,qBAAqB,QAAQ,EACnC,CAAC,QAAQ,aAAa,QAAQ,KAAK,CACpC;AAGD,iBAAgB;AACd,EAAK,OAAO,IAAgB,eAAe,CAAC,WAAW;AACrD,eAAY,KAAK;IACjB;IACD,CAAC,QAAQ,eAAe,CAAC;CAE5B,MAAM,WAAW,YAAY,EAC3B,aAAa,UAAsB,OAAO,IAAI,gBAAgB,MAAM,EACrE,CAAC;AAEF,QAAO;EACL;EACA,SAAS,UAAsB,SAAS,OAAO,MAAM;EACtD"}
package/dist/react.cjs ADDED
@@ -0,0 +1,46 @@
1
+ const require_renderer = require('./renderer-D3YziJ_U.cjs');
2
+ let react = require("react");
3
+
4
+ //#region src/renderer/react.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 useSyncState = (initialValue, options) => {
13
+ const [stateValue, setStateValue] = (0, react.useState)(initialValue);
14
+ const [isSynced, setIsSynced] = (0, react.useState)(false);
15
+ const globalConfig = require_renderer.getGlobalConfig();
16
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
17
+ const channelOptions = (0, react.useMemo)(() => createChannelOptions(options), [options.baseChannel, options.name]);
18
+ const applyRemoteValue = (0, react.useCallback)((value) => {
19
+ setStateValue(value);
20
+ setIsSynced(true);
21
+ }, []);
22
+ const setAndSync = (0, react.useCallback)((value) => {
23
+ setStateValue(value);
24
+ bridge.set(channelOptions, value);
25
+ }, [bridge, channelOptions]);
26
+ (0, react.useEffect)(() => {
27
+ const unsubscribe = bridge.subscribe(channelOptions, applyRemoteValue);
28
+ bridge.get(channelOptions).then(applyRemoteValue);
29
+ return () => {
30
+ unsubscribe();
31
+ };
32
+ }, [
33
+ applyRemoteValue,
34
+ bridge,
35
+ channelOptions
36
+ ]);
37
+ return [
38
+ stateValue,
39
+ setAndSync,
40
+ isSynced
41
+ ];
42
+ };
43
+
44
+ //#endregion
45
+ exports.useSyncState = useSyncState;
46
+ exports.useSyncStateReact = useSyncState;
@@ -0,0 +1,11 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-C18dHgLI.cjs";
2
+
3
+ //#region src/renderer/react.d.ts
4
+ interface UseSyncStateReactOptions extends SyncStateChannelOptions {
5
+ bridge?: SyncStateBridge;
6
+ }
7
+ type UseSyncStateReactResult<StateValue> = readonly [StateValue, (value: StateValue) => void, boolean];
8
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: UseSyncStateReactOptions) => UseSyncStateReactResult<StateValue>;
9
+ //#endregion
10
+ export { UseSyncStateReactOptions, UseSyncStateReactResult, useSyncState, useSyncState as useSyncStateReact };
11
+ //# sourceMappingURL=react.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.cts","names":[],"sources":["../src/renderer/react.ts"],"sourcesContent":[],"mappings":";;;UAOiB,wBAAA,SAAiC;EAAjC,MAAA,CAAA,EACN,eADM;AAIjB;AAca,KAdD,uBAkDX,CAAA,UAAA,CAAA,GAAA,SAAA,CAjDC,UAcc,EACL,CAAA,KAAA,EAdD,UAcC,EAAA,GAAA,IAAA,EACgB,OAAA,CAAxB;AAAuB,cAHb,YAGa,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAFV,UAEU,EAAA,OAAA,EADf,wBACe,EAAA,GAAvB,uBAAuB,CAAC,UAAD,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-7wPPX0ty.js";
2
+
3
+ //#region src/renderer/react.d.ts
4
+ interface UseSyncStateReactOptions extends SyncStateChannelOptions {
5
+ bridge?: SyncStateBridge;
6
+ }
7
+ type UseSyncStateReactResult<StateValue> = readonly [StateValue, (value: StateValue) => void, boolean];
8
+ declare const useSyncState: <StateValue>(initialValue: StateValue, options: UseSyncStateReactOptions) => UseSyncStateReactResult<StateValue>;
9
+ //#endregion
10
+ export { UseSyncStateReactOptions, UseSyncStateReactResult, useSyncState, useSyncState as useSyncStateReact };
11
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","names":[],"sources":["../src/renderer/react.ts"],"sourcesContent":[],"mappings":";;;UAOiB,wBAAA,SAAiC;EAAjC,MAAA,CAAA,EACN,eADM;AAIjB;AAca,KAdD,uBAkDX,CAAA,UAAA,CAAA,GAAA,SAAA,CAjDC,UAcc,EACL,CAAA,KAAA,EAdD,UAcC,EAAA,GAAA,IAAA,EACgB,OAAA,CAAxB;AAAuB,cAHb,YAGa,EAAA,CAAA,UAAA,CAAA,CAAA,YAAA,EAFV,UAEU,EAAA,OAAA,EADf,wBACe,EAAA,GAAvB,uBAAuB,CAAC,UAAD,CAAA"}
package/dist/react.js ADDED
@@ -0,0 +1,46 @@
1
+ import { a as resolveSyncStateBridge, t as getGlobalConfig } from "./renderer-C7zF3UQm.js";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+
4
+ //#region src/renderer/react.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 useSyncState = (initialValue, options) => {
13
+ const [stateValue, setStateValue] = useState(initialValue);
14
+ const [isSynced, setIsSynced] = useState(false);
15
+ const globalConfig = getGlobalConfig();
16
+ const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
17
+ const channelOptions = useMemo(() => createChannelOptions(options), [options.baseChannel, options.name]);
18
+ const applyRemoteValue = useCallback((value) => {
19
+ setStateValue(value);
20
+ setIsSynced(true);
21
+ }, []);
22
+ const setAndSync = useCallback((value) => {
23
+ setStateValue(value);
24
+ bridge.set(channelOptions, value);
25
+ }, [bridge, channelOptions]);
26
+ useEffect(() => {
27
+ const unsubscribe = bridge.subscribe(channelOptions, applyRemoteValue);
28
+ bridge.get(channelOptions).then(applyRemoteValue);
29
+ return () => {
30
+ unsubscribe();
31
+ };
32
+ }, [
33
+ applyRemoteValue,
34
+ bridge,
35
+ channelOptions
36
+ ]);
37
+ return [
38
+ stateValue,
39
+ setAndSync,
40
+ isSynced
41
+ ];
42
+ };
43
+
44
+ //#endregion
45
+ export { useSyncState, useSyncState as useSyncStateReact };
46
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/renderer/react.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\n\nimport type { SyncStateChannelOptions } from \"../channels\";\nimport type { SyncStateBridge } from \"../types\";\nimport { resolveSyncStateBridge } from \"./bridge\";\nimport { getGlobalConfig } from \"./index\";\n\nexport interface UseSyncStateReactOptions extends SyncStateChannelOptions {\n bridge?: SyncStateBridge;\n}\n\nexport type UseSyncStateReactResult<StateValue> = readonly [\n StateValue,\n (value: StateValue) => void,\n boolean,\n];\n\nconst createChannelOptions = (options: UseSyncStateReactOptions): SyncStateChannelOptions => {\n const globalConfig = getGlobalConfig();\n return {\n baseChannel: options.baseChannel ?? globalConfig.baseChannel,\n name: options.name,\n };\n};\n\nexport const useSyncState = <StateValue>(\n initialValue: StateValue,\n options: UseSyncStateReactOptions,\n): UseSyncStateReactResult<StateValue> => {\n const [stateValue, setStateValue] = useState(initialValue);\n const [isSynced, setIsSynced] = useState(false);\n const globalConfig = getGlobalConfig();\n const bridge = resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);\n const channelOptions = useMemo(\n () => createChannelOptions(options),\n [options.baseChannel, options.name],\n );\n\n const applyRemoteValue = useCallback((value: StateValue): void => {\n setStateValue(value);\n setIsSynced(true);\n }, []);\n\n const setAndSync = useCallback(\n (value: StateValue): void => {\n setStateValue(value);\n void bridge.set(channelOptions, value);\n },\n [bridge, channelOptions],\n );\n\n useEffect(() => {\n const unsubscribe = bridge.subscribe(channelOptions, applyRemoteValue);\n void bridge.get<StateValue>(channelOptions).then(applyRemoteValue);\n\n return () => {\n unsubscribe();\n };\n }, [applyRemoteValue, bridge, channelOptions]);\n\n return [stateValue, setAndSync, isSynced] as const;\n};\n\n// Backward compatibility alias\nexport { useSyncState as useSyncStateReact };\n"],"mappings":";;;;AAiBA,MAAM,wBAAwB,YAA+D;CAC3F,MAAM,eAAe,iBAAiB;AACtC,QAAO;EACL,aAAa,QAAQ,eAAe,aAAa;EACjD,MAAM,QAAQ;EACf;;AAGH,MAAa,gBACX,cACA,YACwC;CACxC,MAAM,CAAC,YAAY,iBAAiB,SAAS,aAAa;CAC1D,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAC/C,MAAM,eAAe,iBAAiB;CACtC,MAAM,SAAS,uBAAuB,QAAQ,UAAU,aAAa,OAAO;CAC5E,MAAM,iBAAiB,cACf,qBAAqB,QAAQ,EACnC,CAAC,QAAQ,aAAa,QAAQ,KAAK,CACpC;CAED,MAAM,mBAAmB,aAAa,UAA4B;AAChE,gBAAc,MAAM;AACpB,cAAY,KAAK;IAChB,EAAE,CAAC;CAEN,MAAM,aAAa,aAChB,UAA4B;AAC3B,gBAAc,MAAM;AACpB,EAAK,OAAO,IAAI,gBAAgB,MAAM;IAExC,CAAC,QAAQ,eAAe,CACzB;AAED,iBAAgB;EACd,MAAM,cAAc,OAAO,UAAU,gBAAgB,iBAAiB;AACtE,EAAK,OAAO,IAAgB,eAAe,CAAC,KAAK,iBAAiB;AAElE,eAAa;AACX,gBAAa;;IAEd;EAAC;EAAkB;EAAQ;EAAe,CAAC;AAE9C,QAAO;EAAC;EAAY;EAAY;EAAS"}
package/dist/redux.cjs ADDED
@@ -0,0 +1,148 @@
1
+ const require_renderer = require('./renderer-D3YziJ_U.cjs');
2
+ let react = require("react");
3
+ let react_redux = require("react-redux");
4
+
5
+ //#region src/renderer/redux.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
+ const storeRemoteUpdates = /* @__PURE__ */ new WeakMap();
14
+ const channelStores = /* @__PURE__ */ new Map();
15
+ const shouldSkipSyncAction = (action) => {
16
+ const { meta } = action;
17
+ return Boolean(meta?.syncState?.skipSync);
18
+ };
19
+ /**
20
+ * Redux middleware for syncing state with Electron main process
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { configureStore } from '@reduxjs/toolkit';
25
+ * import { syncStateMiddleware } from 'electron-state-sync/redux';
26
+ *
27
+ * const store = configureStore({
28
+ * reducer: { counter: counterReducer },
29
+ * middleware: (getDefaultMiddleware) =>
30
+ * getDefaultMiddleware().concat(
31
+ * syncStateMiddleware({
32
+ * name: 'counter',
33
+ * selector: (state) => state.counter.value
34
+ * })
35
+ * )
36
+ * });
37
+ * ```
38
+ */
39
+ const syncStateMiddleware = (options) => {
40
+ const globalConfig = require_renderer.getGlobalConfig();
41
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
42
+ const channelOptions = createChannelOptions(options);
43
+ return (storeAPI) => (next) => (action) => {
44
+ const channelKey = `${channelOptions.baseChannel}:${channelOptions.name}`;
45
+ channelStores.set(channelKey, storeAPI);
46
+ const result = next(action);
47
+ const nextState = storeAPI.getState();
48
+ if (storeRemoteUpdates.get(storeAPI)) {
49
+ storeRemoteUpdates.set(storeAPI, false);
50
+ return result;
51
+ }
52
+ if (shouldSkipSyncAction(action)) return result;
53
+ const selectedState = options.selector ? options.selector(nextState) : nextState;
54
+ bridge.set(channelOptions, selectedState);
55
+ return result;
56
+ };
57
+ };
58
+ /**
59
+ * Hook for accessing synced state in React components
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * import { useSyncState } from 'electron-state-sync/redux';
64
+ *
65
+ * function App() {
66
+ * const { state: count, isSynced } = useSyncState<number>({
67
+ * name: 'counter',
68
+ * selector: (state) => state.counter.value
69
+ * });
70
+ *
71
+ * return <div>{count}</div>;
72
+ * }
73
+ * ```
74
+ */
75
+ const useSyncState = (options) => {
76
+ const [isSynced, setIsSynced] = (0, react.useState)(false);
77
+ const globalConfig = require_renderer.getGlobalConfig();
78
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
79
+ const channelOptions = (0, react.useMemo)(() => createChannelOptions(options), [options.baseChannel, options.name]);
80
+ const actionType = (0, react.useMemo)(() => options.actionType || `${channelOptions.baseChannel}/${channelOptions.name}/set`, [
81
+ options.actionType,
82
+ channelOptions.baseChannel,
83
+ channelOptions.name
84
+ ]);
85
+ const state = (0, react_redux.useSelector)((state$1) => options.selector ? options.selector(state$1) : state$1);
86
+ const dispatch = (0, react_redux.useDispatch)();
87
+ (0, react.useEffect)(() => {
88
+ const channelKey = `${channelOptions.baseChannel}:${channelOptions.name}`;
89
+ const unsubscribe = bridge.subscribe(channelOptions, (value) => {
90
+ const store = channelStores.get(channelKey);
91
+ if (store) storeRemoteUpdates.set(store, true);
92
+ dispatch({
93
+ payload: value,
94
+ type: actionType
95
+ });
96
+ });
97
+ bridge.get(channelOptions).then(() => {
98
+ setIsSynced(true);
99
+ });
100
+ return () => {
101
+ unsubscribe();
102
+ };
103
+ }, [
104
+ bridge,
105
+ channelOptions,
106
+ dispatch,
107
+ actionType
108
+ ]);
109
+ return {
110
+ isSynced,
111
+ state
112
+ };
113
+ };
114
+ /**
115
+ * Hook to create an action creator that syncs with main process
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * import { createSyncActionCreator } from 'electron-state-sync/redux';
120
+ *
121
+ * const setCount = createSyncActionCreator<number>('counter/set', {
122
+ * name: 'counter'
123
+ * });
124
+ *
125
+ * // In component
126
+ * const dispatch = useDispatch();
127
+ * dispatch(setCount(42));
128
+ * ```
129
+ */
130
+ const createSyncActionCreator = (actionType, options) => {
131
+ const globalConfig = require_renderer.getGlobalConfig();
132
+ const bridge = require_renderer.resolveSyncStateBridge(options.bridge ?? globalConfig.bridge);
133
+ const channelOptions = createChannelOptions(options);
134
+ return (value) => {
135
+ bridge.set(channelOptions, value);
136
+ return {
137
+ meta: { syncState: { skipSync: true } },
138
+ payload: value,
139
+ type: actionType
140
+ };
141
+ };
142
+ };
143
+
144
+ //#endregion
145
+ exports.createSyncActionCreator = createSyncActionCreator;
146
+ exports.syncStateMiddleware = syncStateMiddleware;
147
+ exports.useReduxSyncState = useSyncState;
148
+ exports.useSyncState = useSyncState;
@@ -0,0 +1,80 @@
1
+ import { a as SyncStateChannelOptions, t as SyncStateBridge } from "./types-C18dHgLI.cjs";
2
+ import { Middleware, UnknownAction } from "@reduxjs/toolkit";
3
+
4
+ //#region src/renderer/redux.d.ts
5
+ interface SyncStateReduxOptions extends SyncStateChannelOptions {
6
+ bridge?: SyncStateBridge;
7
+ selector?: (state: unknown) => unknown;
8
+ actionType?: string;
9
+ }
10
+ interface SyncStateActionMeta {
11
+ syncState?: {
12
+ skipSync?: boolean;
13
+ };
14
+ }
15
+ interface SyncStateAction<StateValue> extends UnknownAction {
16
+ payload: StateValue;
17
+ meta: SyncStateActionMeta;
18
+ }
19
+ /**
20
+ * Redux middleware for syncing state with Electron main process
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * import { configureStore } from '@reduxjs/toolkit';
25
+ * import { syncStateMiddleware } from 'electron-state-sync/redux';
26
+ *
27
+ * const store = configureStore({
28
+ * reducer: { counter: counterReducer },
29
+ * middleware: (getDefaultMiddleware) =>
30
+ * getDefaultMiddleware().concat(
31
+ * syncStateMiddleware({
32
+ * name: 'counter',
33
+ * selector: (state) => state.counter.value
34
+ * })
35
+ * )
36
+ * });
37
+ * ```
38
+ */
39
+ declare const syncStateMiddleware: (options: SyncStateReduxOptions) => Middleware<object, any, never>;
40
+ /**
41
+ * Hook for accessing synced state in React components
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { useSyncState } from 'electron-state-sync/redux';
46
+ *
47
+ * function App() {
48
+ * const { state: count, isSynced } = useSyncState<number>({
49
+ * name: 'counter',
50
+ * selector: (state) => state.counter.value
51
+ * });
52
+ *
53
+ * return <div>{count}</div>;
54
+ * }
55
+ * ```
56
+ */
57
+ declare const useSyncState: <StateValue>(options: SyncStateReduxOptions) => {
58
+ state: StateValue;
59
+ isSynced: boolean;
60
+ };
61
+ /**
62
+ * Hook to create an action creator that syncs with main process
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * import { createSyncActionCreator } from 'electron-state-sync/redux';
67
+ *
68
+ * const setCount = createSyncActionCreator<number>('counter/set', {
69
+ * name: 'counter'
70
+ * });
71
+ *
72
+ * // In component
73
+ * const dispatch = useDispatch();
74
+ * dispatch(setCount(42));
75
+ * ```
76
+ */
77
+ declare const createSyncActionCreator: <StateValue>(actionType: string, options: SyncStateReduxOptions) => ((value: StateValue) => SyncStateAction<StateValue>);
78
+ //#endregion
79
+ export { SyncStateReduxOptions, createSyncActionCreator, syncStateMiddleware, useSyncState as useReduxSyncState, useSyncState };
80
+ //# sourceMappingURL=redux.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redux.d.cts","names":[],"sources":["../src/renderer/redux.ts"],"sourcesContent":[],"mappings":";;;;UAUiB,qBAAA,SAA8B;EAA9B,MAAA,CAAA,EACN,eAD4B;EAqB7B,QAAA,CAAA,EAAA,CAAA,KAAA,EAAA,OAAmB,EAAA,GAAA,OAAA;EAOnB,UAAA,CAAA,EAAA,MAAe;;UAPf,mBAAA,CASF;EAFsC,SAAA,CAAA,EAAA;IAAa,QAAA,CAAA,EAAA,OAAA;EA+B9C,CAAA;AAqDb;AAkEA,UAtJU,eAsJG,CAAA,UAqBZ,CAAA,SA3K6C,aA2K7C,CAAA;EAnBU,OAAA,EAvJA,UAuJA;EACC,IAAA,EAvJJ,mBAuJI;;;;;;;;;;;;;;;;;;;;;;cA1HC,+BACF,0BACR;;;;;;;;;;;;;;;;;;cAmDU,oCACF;SACC;;;;;;;;;;;;;;;;;;;cAgEC,mEAEF,mCACC,eAAe,gBAAgB"}