@shiftbloom-studio/symphony-state 0.0.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 (59) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +198 -0
  3. package/dist/adapters/atom.cjs +36 -0
  4. package/dist/adapters/atom.cjs.map +1 -0
  5. package/dist/adapters/atom.d.cts +8 -0
  6. package/dist/adapters/atom.d.ts +8 -0
  7. package/dist/adapters/atom.js +34 -0
  8. package/dist/adapters/atom.js.map +1 -0
  9. package/dist/adapters/external.cjs +16 -0
  10. package/dist/adapters/external.cjs.map +1 -0
  11. package/dist/adapters/external.d.cts +13 -0
  12. package/dist/adapters/external.d.ts +13 -0
  13. package/dist/adapters/external.js +14 -0
  14. package/dist/adapters/external.js.map +1 -0
  15. package/dist/adapters/query.cjs +17 -0
  16. package/dist/adapters/query.cjs.map +1 -0
  17. package/dist/adapters/query.d.cts +16 -0
  18. package/dist/adapters/query.d.ts +16 -0
  19. package/dist/adapters/query.js +15 -0
  20. package/dist/adapters/query.js.map +1 -0
  21. package/dist/adapters/redux.cjs +20 -0
  22. package/dist/adapters/redux.cjs.map +1 -0
  23. package/dist/adapters/redux.d.cts +15 -0
  24. package/dist/adapters/redux.d.ts +15 -0
  25. package/dist/adapters/redux.js +18 -0
  26. package/dist/adapters/redux.js.map +1 -0
  27. package/dist/adapters/url.cjs +39 -0
  28. package/dist/adapters/url.cjs.map +1 -0
  29. package/dist/adapters/url.d.cts +13 -0
  30. package/dist/adapters/url.d.ts +13 -0
  31. package/dist/adapters/url.js +37 -0
  32. package/dist/adapters/url.js.map +1 -0
  33. package/dist/adapters/zustand.cjs +16 -0
  34. package/dist/adapters/zustand.cjs.map +1 -0
  35. package/dist/adapters/zustand.d.cts +10 -0
  36. package/dist/adapters/zustand.d.ts +10 -0
  37. package/dist/adapters/zustand.js +14 -0
  38. package/dist/adapters/zustand.js.map +1 -0
  39. package/dist/devtools.cjs +159 -0
  40. package/dist/devtools.cjs.map +1 -0
  41. package/dist/devtools.d.cts +9 -0
  42. package/dist/devtools.d.ts +9 -0
  43. package/dist/devtools.js +157 -0
  44. package/dist/devtools.js.map +1 -0
  45. package/dist/index.cjs +560 -0
  46. package/dist/index.cjs.map +1 -0
  47. package/dist/index.d.cts +20 -0
  48. package/dist/index.d.ts +20 -0
  49. package/dist/index.js +552 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/react.cjs +576 -0
  52. package/dist/react.cjs.map +1 -0
  53. package/dist/react.d.cts +40 -0
  54. package/dist/react.d.ts +40 -0
  55. package/dist/react.js +569 -0
  56. package/dist/react.js.map +1 -0
  57. package/dist/types-B1uzdpYH.d.cts +67 -0
  58. package/dist/types-B1uzdpYH.d.ts +67 -0
  59. package/package.json +127 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) YEAR YOUR_NAME
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # Symphony State
2
+
3
+ [![npm](https://img.shields.io/npm/v/@shiftbloom-studio/symphony-state)](https://www.npmjs.com/package/@shiftbloom-studio/symphony-state)
4
+ [![CI](https://img.shields.io/github/actions/workflow/status/shiftbloom-studio/symphony-state/ci.yml)](https://github.com/shiftbloom-studio/symphony-state/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/@shiftbloom-studio/symphony-state)](LICENSE)
6
+
7
+ **Orchestrate multiple state sources without a monolithic global store.**
8
+
9
+ Symphony State coordinates local state, React Context, external stores (Zustand/Redux), server state libraries (TanStack Query/SWR), URL params, and browser persistence without taking ownership of those sources. It focuses on deterministic, dependency-driven propagation and atomic transactions so you can keep cross-domain state consistent.
10
+
11
+ ## Why Symphony State?
12
+
13
+ - **Mixed sources drift**: local state, URL params, and external stores can diverge.
14
+ - **Update storms**: independent updates trigger multiple re-renders.
15
+ - **Cross-domain dependencies**: cart state depends on auth/pricing, etc.
16
+
17
+ Symphony State provides an orchestration layer that schedules updates in a single wave and keeps dependencies consistent.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @shiftbloom-studio/symphony-state
23
+ ```
24
+
25
+ ## Quickstart (AtomAdapter)
26
+
27
+ ```tsx
28
+ import {
29
+ createConductor,
30
+ defineSection,
31
+ createAtomAdapter
32
+ } from "@shiftbloom-studio/symphony-state";
33
+ import { SymphonyProvider, useSection } from "@shiftbloom-studio/symphony-state/react";
34
+
35
+ const auth = defineSection({
36
+ key: "auth",
37
+ source: createAtomAdapter({ userId: null as string | null })
38
+ });
39
+
40
+ const conductor = createConductor({ sections: [auth] });
41
+
42
+ function AuthPanel() {
43
+ const authSection = useSection<{ userId: string | null }>("auth");
44
+ return (
45
+ <button onClick={() => authSection.set({ userId: "42" })}>
46
+ {authSection.value.userId ?? "Login"}
47
+ </button>
48
+ );
49
+ }
50
+
51
+ export function App() {
52
+ return (
53
+ <SymphonyProvider conductor={conductor}>
54
+ <AuthPanel />
55
+ </SymphonyProvider>
56
+ );
57
+ }
58
+ ```
59
+
60
+ ## Quickstart (Zustand + Redux adapters)
61
+
62
+ ```ts
63
+ import { createZustandAdapter } from "@shiftbloom-studio/symphony-state/adapters/zustand";
64
+ import { createReduxAdapter } from "@shiftbloom-studio/symphony-state/adapters/redux";
65
+
66
+ const zustandSection = defineSection({
67
+ key: "filters",
68
+ source: createZustandAdapter(zustandStore)
69
+ });
70
+
71
+ const reduxSection = defineSection({
72
+ key: "cart",
73
+ source: createReduxAdapter(reduxStore, {
74
+ select: (state) => state.cart,
75
+ update: (next) => ({ type: "cart/replace", payload: next }),
76
+ patch: (partial) => ({ type: "cart/patch", payload: partial })
77
+ })
78
+ });
79
+ ```
80
+
81
+ ## Transactions
82
+
83
+ ```ts
84
+ conductor.transaction(() => {
85
+ conductor.getSection("auth").set({ userId: "42" });
86
+ conductor.getSection("cart").patch({ ownerId: "42" });
87
+ }, "login");
88
+ ```
89
+
90
+ All section updates are staged, resolved in dependency order, committed atomically, and only then are subscribers notified.
91
+
92
+ ## Derived sections
93
+
94
+ ```ts
95
+ import { defineDerivedSection } from "@shiftbloom-studio/symphony-state";
96
+
97
+ const pricing = defineDerivedSection({
98
+ key: "pricing",
99
+ inputs: ["cart", "auth"],
100
+ compute: (cart, auth) => ({
101
+ total: cart.items.length * (auth.isPremium ? 0.8 : 1)
102
+ })
103
+ });
104
+ ```
105
+
106
+ Derived sections are read-only and recompute only when their inputs change.
107
+
108
+ ## Next.js patterns
109
+
110
+ ### App Router
111
+
112
+ ```tsx
113
+ // app/layout.tsx
114
+ "use client";
115
+ import { SymphonyProvider } from "@shiftbloom-studio/symphony-state/react";
116
+ import { conductor } from "./symphony";
117
+
118
+ export default function RootLayout({ children }) {
119
+ return <SymphonyProvider conductor={conductor}>{children}</SymphonyProvider>;
120
+ }
121
+ ```
122
+
123
+ ### Pages Router
124
+
125
+ ```tsx
126
+ // pages/_app.tsx
127
+ import { SymphonyProvider } from "@shiftbloom-studio/symphony-state/react";
128
+ import { conductor } from "../symphony";
129
+
130
+ export default function App({ Component, pageProps }) {
131
+ return (
132
+ <SymphonyProvider conductor={conductor}>
133
+ <Component {...pageProps} />
134
+ </SymphonyProvider>
135
+ );
136
+ }
137
+ ```
138
+
139
+ ### Hydration helper
140
+
141
+ ```tsx
142
+ import { SymphonyScript } from "@shiftbloom-studio/symphony-state/react";
143
+
144
+ <SymphonyScript state={{ auth: { userId: "42" } }} />;
145
+ ```
146
+
147
+ ## Persistence
148
+
149
+ ```ts
150
+ import { createStorageSink } from "@shiftbloom-studio/symphony-state";
151
+
152
+ const auth = defineSection({
153
+ key: "auth",
154
+ source: createAtomAdapter({ userId: null }),
155
+ persist: createStorageSink({
156
+ key: "symphony-auth",
157
+ throttleMs: 200
158
+ })
159
+ });
160
+ ```
161
+
162
+ ## DevTools (optional)
163
+
164
+ ```tsx
165
+ import { SymphonyDevTools } from "@shiftbloom-studio/symphony-state/devtools";
166
+
167
+ <SymphonyDevTools maxTransactions={10} />;
168
+ ```
169
+
170
+ DevTools are dev-only, tree-shakeable, and unstyled apart from minimal CSS variables.
171
+
172
+ ## API Reference
173
+
174
+ | API | Description |
175
+ | ----------------------------------- | ---------------------------------------------- |
176
+ | `createConductor(config)` | Create a conductor instance. |
177
+ | `defineSection(def)` | Define a section backed by a source adapter. |
178
+ | `defineDerivedSection(def)` | Define a derived, read-only section. |
179
+ | `createAtomAdapter(initial)` | Built-in minimal store. |
180
+ | `createExternalStoreAdapter(store)` | Wrap an external get/set/subscribe store. |
181
+ | `createUrlParamsAdapter(options)` | Sync with URL search params. |
182
+ | `createStorageSink(options)` | Persist section values to storage. |
183
+ | `SymphonyProvider` | React context provider. |
184
+ | `useSection(key)` | React hook for section read/write. |
185
+ | `useSelector(key, selector)` | Selector hook with equality. |
186
+ | `createSymphony(config)` | Typed helper that wires a conductor and hooks. |
187
+ | `SymphonyDevTools` | Optional devtools panel. |
188
+
189
+ ## Design principles
190
+
191
+ - **Orchestration, not ownership**: Symphony State coordinates existing stores.
192
+ - **Predictable updates**: deterministic, dependency-ordered commit waves.
193
+ - **Tree-shakeable**: optional adapters and devtools ship as separate entrypoints.
194
+ - **SSR-safe**: no unguarded `window` usage in core.
195
+
196
+ ## License
197
+
198
+ MIT
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/atom.ts
4
+ var createAtomAdapter = (initial) => {
5
+ let current = initial;
6
+ const subscribers = /* @__PURE__ */ new Set();
7
+ const notify = () => {
8
+ subscribers.forEach((cb) => cb());
9
+ };
10
+ return {
11
+ kind: "atom",
12
+ get: () => current,
13
+ set: (next) => {
14
+ if (Object.is(current, next)) {
15
+ return;
16
+ }
17
+ current = next;
18
+ notify();
19
+ },
20
+ patch: (partial) => {
21
+ if (typeof current !== "object" || current === null) {
22
+ throw new Error("AtomAdapter patch requires object state.");
23
+ }
24
+ current = { ...current, ...partial };
25
+ notify();
26
+ },
27
+ subscribe: (cb) => {
28
+ subscribers.add(cb);
29
+ return () => subscribers.delete(cb);
30
+ }
31
+ };
32
+ };
33
+
34
+ exports.createAtomAdapter = createAtomAdapter;
35
+ //# sourceMappingURL=atom.cjs.map
36
+ //# sourceMappingURL=atom.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/atom.ts"],"names":[],"mappings":";;;AAMO,IAAM,iBAAA,GAAoB,CAAI,OAAA,KAA+B;AAClE,EAAA,IAAI,OAAA,GAAU,OAAA;AACd,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAgB;AAExC,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,WAAA,CAAY,OAAA,CAAQ,CAAC,EAAA,KAAO,EAAA,EAAI,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IACN,KAAK,MAAM,OAAA;AAAA,IACX,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,IAAI,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,IAAI,CAAA,EAAG;AAC5B,QAAA;AAAA,MACF;AACA,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,IACA,KAAA,EAAO,CAAC,OAAA,KAAY;AAClB,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,QAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,MAC5D;AACA,MAAA,OAAA,GAAU,EAAE,GAAI,OAAA,EAAqC,GAAG,OAAA,EAAQ;AAChE,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,EAAA,KAAgC;AAC1C,MAAA,WAAA,CAAY,IAAI,EAAE,CAAA;AAClB,MAAA,OAAO,MAAM,WAAA,CAAY,MAAA,CAAO,EAAE,CAAA;AAAA,IACpC;AAAA,GACF;AACF","file":"atom.cjs","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type AtomAdapter<T> = SourceAdapter<T> & {\n patch: (partial: Partial<T>) => void;\n};\n\nexport const createAtomAdapter = <T>(initial: T): AtomAdapter<T> => {\n let current = initial;\n const subscribers = new Set<Subscriber>();\n\n const notify = () => {\n subscribers.forEach((cb) => cb());\n };\n\n return {\n kind: \"atom\",\n get: () => current,\n set: (next) => {\n if (Object.is(current, next)) {\n return;\n }\n current = next;\n notify();\n },\n patch: (partial) => {\n if (typeof current !== \"object\" || current === null) {\n throw new Error(\"AtomAdapter patch requires object state.\");\n }\n current = { ...(current as Record<string, unknown>), ...partial } as T;\n notify();\n },\n subscribe: (cb: Subscriber): Unsubscribe => {\n subscribers.add(cb);\n return () => subscribers.delete(cb);\n }\n };\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import { d as SourceAdapter } from '../types-B1uzdpYH.cjs';
2
+
3
+ type AtomAdapter<T> = SourceAdapter<T> & {
4
+ patch: (partial: Partial<T>) => void;
5
+ };
6
+ declare const createAtomAdapter: <T>(initial: T) => AtomAdapter<T>;
7
+
8
+ export { type AtomAdapter, createAtomAdapter };
@@ -0,0 +1,8 @@
1
+ import { d as SourceAdapter } from '../types-B1uzdpYH.js';
2
+
3
+ type AtomAdapter<T> = SourceAdapter<T> & {
4
+ patch: (partial: Partial<T>) => void;
5
+ };
6
+ declare const createAtomAdapter: <T>(initial: T) => AtomAdapter<T>;
7
+
8
+ export { type AtomAdapter, createAtomAdapter };
@@ -0,0 +1,34 @@
1
+ // src/adapters/atom.ts
2
+ var createAtomAdapter = (initial) => {
3
+ let current = initial;
4
+ const subscribers = /* @__PURE__ */ new Set();
5
+ const notify = () => {
6
+ subscribers.forEach((cb) => cb());
7
+ };
8
+ return {
9
+ kind: "atom",
10
+ get: () => current,
11
+ set: (next) => {
12
+ if (Object.is(current, next)) {
13
+ return;
14
+ }
15
+ current = next;
16
+ notify();
17
+ },
18
+ patch: (partial) => {
19
+ if (typeof current !== "object" || current === null) {
20
+ throw new Error("AtomAdapter patch requires object state.");
21
+ }
22
+ current = { ...current, ...partial };
23
+ notify();
24
+ },
25
+ subscribe: (cb) => {
26
+ subscribers.add(cb);
27
+ return () => subscribers.delete(cb);
28
+ }
29
+ };
30
+ };
31
+
32
+ export { createAtomAdapter };
33
+ //# sourceMappingURL=atom.js.map
34
+ //# sourceMappingURL=atom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/atom.ts"],"names":[],"mappings":";AAMO,IAAM,iBAAA,GAAoB,CAAI,OAAA,KAA+B;AAClE,EAAA,IAAI,OAAA,GAAU,OAAA;AACd,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAgB;AAExC,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,WAAA,CAAY,OAAA,CAAQ,CAAC,EAAA,KAAO,EAAA,EAAI,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IACN,KAAK,MAAM,OAAA;AAAA,IACX,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,IAAI,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,IAAI,CAAA,EAAG;AAC5B,QAAA;AAAA,MACF;AACA,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,IACA,KAAA,EAAO,CAAC,OAAA,KAAY;AAClB,MAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,QAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,MAC5D;AACA,MAAA,OAAA,GAAU,EAAE,GAAI,OAAA,EAAqC,GAAG,OAAA,EAAQ;AAChE,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,EAAA,KAAgC;AAC1C,MAAA,WAAA,CAAY,IAAI,EAAE,CAAA;AAClB,MAAA,OAAO,MAAM,WAAA,CAAY,MAAA,CAAO,EAAE,CAAA;AAAA,IACpC;AAAA,GACF;AACF","file":"atom.js","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type AtomAdapter<T> = SourceAdapter<T> & {\n patch: (partial: Partial<T>) => void;\n};\n\nexport const createAtomAdapter = <T>(initial: T): AtomAdapter<T> => {\n let current = initial;\n const subscribers = new Set<Subscriber>();\n\n const notify = () => {\n subscribers.forEach((cb) => cb());\n };\n\n return {\n kind: \"atom\",\n get: () => current,\n set: (next) => {\n if (Object.is(current, next)) {\n return;\n }\n current = next;\n notify();\n },\n patch: (partial) => {\n if (typeof current !== \"object\" || current === null) {\n throw new Error(\"AtomAdapter patch requires object state.\");\n }\n current = { ...(current as Record<string, unknown>), ...partial } as T;\n notify();\n },\n subscribe: (cb: Subscriber): Unsubscribe => {\n subscribers.add(cb);\n return () => subscribers.delete(cb);\n }\n };\n};\n"]}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/external.ts
4
+ var createExternalStoreAdapter = (store, options) => {
5
+ return {
6
+ kind: options?.kind ?? "external",
7
+ get: store.get,
8
+ set: store.set,
9
+ patch: options?.patch,
10
+ subscribe: store.subscribe
11
+ };
12
+ };
13
+
14
+ exports.createExternalStoreAdapter = createExternalStoreAdapter;
15
+ //# sourceMappingURL=external.cjs.map
16
+ //# sourceMappingURL=external.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/external.ts"],"names":[],"mappings":";;;AAQO,IAAM,0BAAA,GAA6B,CACxC,KAAA,EACA,OAAA,KACqB;AACrB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAS,IAAA,IAAQ,UAAA;AAAA,IACvB,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,OAAO,OAAA,EAAS,KAAA;AAAA,IAChB,WAAW,KAAA,CAAM;AAAA,GACnB;AACF","file":"external.cjs","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type ExternalStore<T> = {\n get: () => T;\n set: (next: T) => void;\n subscribe: (cb: Subscriber) => Unsubscribe;\n};\n\nexport const createExternalStoreAdapter = <T>(\n store: ExternalStore<T>,\n options?: { kind?: string; patch?: (partial: Partial<T>) => void }\n): SourceAdapter<T> => {\n return {\n kind: options?.kind ?? \"external\",\n get: store.get,\n set: store.set,\n patch: options?.patch,\n subscribe: store.subscribe\n };\n};\n"]}
@@ -0,0 +1,13 @@
1
+ import { e as Subscriber, U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.cjs';
2
+
3
+ type ExternalStore<T> = {
4
+ get: () => T;
5
+ set: (next: T) => void;
6
+ subscribe: (cb: Subscriber) => Unsubscribe;
7
+ };
8
+ declare const createExternalStoreAdapter: <T>(store: ExternalStore<T>, options?: {
9
+ kind?: string;
10
+ patch?: (partial: Partial<T>) => void;
11
+ }) => SourceAdapter<T>;
12
+
13
+ export { type ExternalStore, createExternalStoreAdapter };
@@ -0,0 +1,13 @@
1
+ import { e as Subscriber, U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.js';
2
+
3
+ type ExternalStore<T> = {
4
+ get: () => T;
5
+ set: (next: T) => void;
6
+ subscribe: (cb: Subscriber) => Unsubscribe;
7
+ };
8
+ declare const createExternalStoreAdapter: <T>(store: ExternalStore<T>, options?: {
9
+ kind?: string;
10
+ patch?: (partial: Partial<T>) => void;
11
+ }) => SourceAdapter<T>;
12
+
13
+ export { type ExternalStore, createExternalStoreAdapter };
@@ -0,0 +1,14 @@
1
+ // src/adapters/external.ts
2
+ var createExternalStoreAdapter = (store, options) => {
3
+ return {
4
+ kind: options?.kind ?? "external",
5
+ get: store.get,
6
+ set: store.set,
7
+ patch: options?.patch,
8
+ subscribe: store.subscribe
9
+ };
10
+ };
11
+
12
+ export { createExternalStoreAdapter };
13
+ //# sourceMappingURL=external.js.map
14
+ //# sourceMappingURL=external.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/external.ts"],"names":[],"mappings":";AAQO,IAAM,0BAAA,GAA6B,CACxC,KAAA,EACA,OAAA,KACqB;AACrB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAS,IAAA,IAAQ,UAAA;AAAA,IACvB,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,KAAK,KAAA,CAAM,GAAA;AAAA,IACX,OAAO,OAAA,EAAS,KAAA;AAAA,IAChB,WAAW,KAAA,CAAM;AAAA,GACnB;AACF","file":"external.js","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type ExternalStore<T> = {\n get: () => T;\n set: (next: T) => void;\n subscribe: (cb: Subscriber) => Unsubscribe;\n};\n\nexport const createExternalStoreAdapter = <T>(\n store: ExternalStore<T>,\n options?: { kind?: string; patch?: (partial: Partial<T>) => void }\n): SourceAdapter<T> => {\n return {\n kind: options?.kind ?? \"external\",\n get: store.get,\n set: store.set,\n patch: options?.patch,\n subscribe: store.subscribe\n };\n};\n"]}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/query.ts
4
+ var createQueryAdapter = (options) => {
5
+ return {
6
+ kind: "query",
7
+ get: () => options.queryClient.getQueryData(options.queryKey),
8
+ set: (next) => {
9
+ options.queryClient.setQueryData(options.queryKey, next);
10
+ },
11
+ subscribe: (cb) => options.queryClient.getQueryCache().subscribe(cb)
12
+ };
13
+ };
14
+
15
+ exports.createQueryAdapter = createQueryAdapter;
16
+ //# sourceMappingURL=query.cjs.map
17
+ //# sourceMappingURL=query.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/query.ts"],"names":[],"mappings":";;;AAaO,IAAM,kBAAA,GAAqB,CAAI,OAAA,KAAmD;AACvF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,KAAK,MAAM,OAAA,CAAQ,WAAA,CAAY,YAAA,CAAa,QAAQ,QAAQ,CAAA;AAAA,IAC5D,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,OAAA,CAAQ,WAAA,CAAY,YAAA,CAAa,OAAA,CAAQ,QAAA,EAAU,IAAI,CAAA;AAAA,IACzD,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,EAAA,KAAmB,OAAA,CAAQ,YAAY,aAAA,EAAc,CAAE,UAAU,EAAE;AAAA,GACjF;AACF","file":"query.cjs","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type QueryClientLike = {\n getQueryData: (key: unknown) => unknown;\n setQueryData: (key: unknown, updater: unknown) => void;\n getQueryCache: () => { subscribe: (listener: () => void) => Unsubscribe };\n};\n\nexport type QueryAdapterOptions = {\n queryClient: QueryClientLike;\n queryKey: unknown;\n};\n\nexport const createQueryAdapter = <T>(options: QueryAdapterOptions): SourceAdapter<T> => {\n return {\n kind: \"query\",\n get: () => options.queryClient.getQueryData(options.queryKey) as T,\n set: (next) => {\n options.queryClient.setQueryData(options.queryKey, next);\n },\n subscribe: (cb: Subscriber) => options.queryClient.getQueryCache().subscribe(cb)\n };\n};\n"]}
@@ -0,0 +1,16 @@
1
+ import { U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.cjs';
2
+
3
+ type QueryClientLike = {
4
+ getQueryData: (key: unknown) => unknown;
5
+ setQueryData: (key: unknown, updater: unknown) => void;
6
+ getQueryCache: () => {
7
+ subscribe: (listener: () => void) => Unsubscribe;
8
+ };
9
+ };
10
+ type QueryAdapterOptions = {
11
+ queryClient: QueryClientLike;
12
+ queryKey: unknown;
13
+ };
14
+ declare const createQueryAdapter: <T>(options: QueryAdapterOptions) => SourceAdapter<T>;
15
+
16
+ export { type QueryAdapterOptions, type QueryClientLike, createQueryAdapter };
@@ -0,0 +1,16 @@
1
+ import { U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.js';
2
+
3
+ type QueryClientLike = {
4
+ getQueryData: (key: unknown) => unknown;
5
+ setQueryData: (key: unknown, updater: unknown) => void;
6
+ getQueryCache: () => {
7
+ subscribe: (listener: () => void) => Unsubscribe;
8
+ };
9
+ };
10
+ type QueryAdapterOptions = {
11
+ queryClient: QueryClientLike;
12
+ queryKey: unknown;
13
+ };
14
+ declare const createQueryAdapter: <T>(options: QueryAdapterOptions) => SourceAdapter<T>;
15
+
16
+ export { type QueryAdapterOptions, type QueryClientLike, createQueryAdapter };
@@ -0,0 +1,15 @@
1
+ // src/adapters/query.ts
2
+ var createQueryAdapter = (options) => {
3
+ return {
4
+ kind: "query",
5
+ get: () => options.queryClient.getQueryData(options.queryKey),
6
+ set: (next) => {
7
+ options.queryClient.setQueryData(options.queryKey, next);
8
+ },
9
+ subscribe: (cb) => options.queryClient.getQueryCache().subscribe(cb)
10
+ };
11
+ };
12
+
13
+ export { createQueryAdapter };
14
+ //# sourceMappingURL=query.js.map
15
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/query.ts"],"names":[],"mappings":";AAaO,IAAM,kBAAA,GAAqB,CAAI,OAAA,KAAmD;AACvF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,KAAK,MAAM,OAAA,CAAQ,WAAA,CAAY,YAAA,CAAa,QAAQ,QAAQ,CAAA;AAAA,IAC5D,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,OAAA,CAAQ,WAAA,CAAY,YAAA,CAAa,OAAA,CAAQ,QAAA,EAAU,IAAI,CAAA;AAAA,IACzD,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,EAAA,KAAmB,OAAA,CAAQ,YAAY,aAAA,EAAc,CAAE,UAAU,EAAE;AAAA,GACjF;AACF","file":"query.js","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type QueryClientLike = {\n getQueryData: (key: unknown) => unknown;\n setQueryData: (key: unknown, updater: unknown) => void;\n getQueryCache: () => { subscribe: (listener: () => void) => Unsubscribe };\n};\n\nexport type QueryAdapterOptions = {\n queryClient: QueryClientLike;\n queryKey: unknown;\n};\n\nexport const createQueryAdapter = <T>(options: QueryAdapterOptions): SourceAdapter<T> => {\n return {\n kind: \"query\",\n get: () => options.queryClient.getQueryData(options.queryKey) as T,\n set: (next) => {\n options.queryClient.setQueryData(options.queryKey, next);\n },\n subscribe: (cb: Subscriber) => options.queryClient.getQueryCache().subscribe(cb)\n };\n};\n"]}
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/redux.ts
4
+ var createReduxAdapter = (store, options) => {
5
+ return {
6
+ kind: "redux",
7
+ get: () => options.select(store.getState()),
8
+ set: (next) => {
9
+ store.dispatch(options.update(next));
10
+ },
11
+ patch: options.patch ? (partial) => {
12
+ store.dispatch(options.patch?.(partial));
13
+ } : void 0,
14
+ subscribe: (cb) => store.subscribe(cb)
15
+ };
16
+ };
17
+
18
+ exports.createReduxAdapter = createReduxAdapter;
19
+ //# sourceMappingURL=redux.cjs.map
20
+ //# sourceMappingURL=redux.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/redux.ts"],"names":[],"mappings":";;;AAcO,IAAM,kBAAA,GAAqB,CAChC,KAAA,EACA,OAAA,KACyB;AACzB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,KAAK,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA;AAAA,IAC1C,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IACrC,CAAA;AAAA,IACA,KAAA,EAAO,OAAA,CAAQ,KAAA,GACX,CAAC,OAAA,KAAY;AACX,MAAA,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,KAAA,GAAQ,OAAO,CAAC,CAAA;AAAA,IACzC,CAAA,GACA,MAAA;AAAA,IACJ,SAAA,EAAW,CAAC,EAAA,KAAmB,KAAA,CAAM,UAAU,EAAE;AAAA,GACnD;AACF","file":"redux.cjs","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type ReduxStore<State> = {\n getState: () => State;\n dispatch: (action: unknown) => unknown;\n subscribe: (listener: () => void) => Unsubscribe;\n};\n\nexport type ReduxAdapterOptions<State, Slice> = {\n select: (state: State) => Slice;\n update: (next: Slice) => unknown;\n patch?: (partial: Partial<Slice>) => unknown;\n};\n\nexport const createReduxAdapter = <State, Slice>(\n store: ReduxStore<State>,\n options: ReduxAdapterOptions<State, Slice>\n): SourceAdapter<Slice> => {\n return {\n kind: \"redux\",\n get: () => options.select(store.getState()),\n set: (next) => {\n store.dispatch(options.update(next));\n },\n patch: options.patch\n ? (partial) => {\n store.dispatch(options.patch?.(partial));\n }\n : undefined,\n subscribe: (cb: Subscriber) => store.subscribe(cb)\n };\n};\n"]}
@@ -0,0 +1,15 @@
1
+ import { U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.cjs';
2
+
3
+ type ReduxStore<State> = {
4
+ getState: () => State;
5
+ dispatch: (action: unknown) => unknown;
6
+ subscribe: (listener: () => void) => Unsubscribe;
7
+ };
8
+ type ReduxAdapterOptions<State, Slice> = {
9
+ select: (state: State) => Slice;
10
+ update: (next: Slice) => unknown;
11
+ patch?: (partial: Partial<Slice>) => unknown;
12
+ };
13
+ declare const createReduxAdapter: <State, Slice>(store: ReduxStore<State>, options: ReduxAdapterOptions<State, Slice>) => SourceAdapter<Slice>;
14
+
15
+ export { type ReduxAdapterOptions, type ReduxStore, createReduxAdapter };
@@ -0,0 +1,15 @@
1
+ import { U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.js';
2
+
3
+ type ReduxStore<State> = {
4
+ getState: () => State;
5
+ dispatch: (action: unknown) => unknown;
6
+ subscribe: (listener: () => void) => Unsubscribe;
7
+ };
8
+ type ReduxAdapterOptions<State, Slice> = {
9
+ select: (state: State) => Slice;
10
+ update: (next: Slice) => unknown;
11
+ patch?: (partial: Partial<Slice>) => unknown;
12
+ };
13
+ declare const createReduxAdapter: <State, Slice>(store: ReduxStore<State>, options: ReduxAdapterOptions<State, Slice>) => SourceAdapter<Slice>;
14
+
15
+ export { type ReduxAdapterOptions, type ReduxStore, createReduxAdapter };
@@ -0,0 +1,18 @@
1
+ // src/adapters/redux.ts
2
+ var createReduxAdapter = (store, options) => {
3
+ return {
4
+ kind: "redux",
5
+ get: () => options.select(store.getState()),
6
+ set: (next) => {
7
+ store.dispatch(options.update(next));
8
+ },
9
+ patch: options.patch ? (partial) => {
10
+ store.dispatch(options.patch?.(partial));
11
+ } : void 0,
12
+ subscribe: (cb) => store.subscribe(cb)
13
+ };
14
+ };
15
+
16
+ export { createReduxAdapter };
17
+ //# sourceMappingURL=redux.js.map
18
+ //# sourceMappingURL=redux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/redux.ts"],"names":[],"mappings":";AAcO,IAAM,kBAAA,GAAqB,CAChC,KAAA,EACA,OAAA,KACyB;AACzB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,KAAK,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA;AAAA,IAC1C,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,MAAA,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IACrC,CAAA;AAAA,IACA,KAAA,EAAO,OAAA,CAAQ,KAAA,GACX,CAAC,OAAA,KAAY;AACX,MAAA,KAAA,CAAM,QAAA,CAAS,OAAA,CAAQ,KAAA,GAAQ,OAAO,CAAC,CAAA;AAAA,IACzC,CAAA,GACA,MAAA;AAAA,IACJ,SAAA,EAAW,CAAC,EAAA,KAAmB,KAAA,CAAM,UAAU,EAAE;AAAA,GACnD;AACF","file":"redux.js","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type ReduxStore<State> = {\n getState: () => State;\n dispatch: (action: unknown) => unknown;\n subscribe: (listener: () => void) => Unsubscribe;\n};\n\nexport type ReduxAdapterOptions<State, Slice> = {\n select: (state: State) => Slice;\n update: (next: Slice) => unknown;\n patch?: (partial: Partial<Slice>) => unknown;\n};\n\nexport const createReduxAdapter = <State, Slice>(\n store: ReduxStore<State>,\n options: ReduxAdapterOptions<State, Slice>\n): SourceAdapter<Slice> => {\n return {\n kind: \"redux\",\n get: () => options.select(store.getState()),\n set: (next) => {\n store.dispatch(options.update(next));\n },\n patch: options.patch\n ? (partial) => {\n store.dispatch(options.patch?.(partial));\n }\n : undefined,\n subscribe: (cb: Subscriber) => store.subscribe(cb)\n };\n};\n"]}
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ // src/adapters/url.ts
4
+ var defaultGetParams = () => {
5
+ if (typeof window === "undefined") {
6
+ return new URLSearchParams();
7
+ }
8
+ return new URLSearchParams(window.location.search);
9
+ };
10
+ var defaultSetParams = (params) => {
11
+ if (typeof window === "undefined") {
12
+ return;
13
+ }
14
+ const url = `${window.location.pathname}?${params.toString()}${window.location.hash}`;
15
+ window.history.replaceState({}, "", url);
16
+ };
17
+ var defaultSubscribe = (cb) => {
18
+ if (typeof window === "undefined") {
19
+ return () => void 0;
20
+ }
21
+ const handler = () => cb();
22
+ window.addEventListener("popstate", handler);
23
+ return () => window.removeEventListener("popstate", handler);
24
+ };
25
+ var createUrlParamsAdapter = (options) => {
26
+ const getParams = options.getSearchParams ?? defaultGetParams;
27
+ const setParams = options.setSearchParams ?? defaultSetParams;
28
+ const subscribe = options.subscribe ?? defaultSubscribe;
29
+ return {
30
+ kind: options.kind ?? "url",
31
+ get: () => options.parse(getParams()),
32
+ set: (next) => setParams(options.serialize(next)),
33
+ subscribe
34
+ };
35
+ };
36
+
37
+ exports.createUrlParamsAdapter = createUrlParamsAdapter;
38
+ //# sourceMappingURL=url.cjs.map
39
+ //# sourceMappingURL=url.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/url.ts"],"names":[],"mappings":";;;AAWA,IAAM,mBAAmB,MAAM;AAC7B,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,IAAI,eAAA,EAAgB;AAAA,EAC7B;AACA,EAAA,OAAO,IAAI,eAAA,CAAgB,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA;AACnD,CAAA;AAEA,IAAM,gBAAA,GAAmB,CAAC,MAAA,KAA4B;AACpD,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,EAAU,CAAA,EAAG,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,CAAA;AACnF,EAAA,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAa,EAAC,EAAG,IAAI,GAAG,CAAA;AACzC,CAAA;AAEA,IAAM,gBAAA,GAAmB,CAAC,EAAA,KAAgC;AACxD,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,IAAA,OAAO,MAAM,MAAA;AAAA,EACf;AACA,EAAA,MAAM,OAAA,GAAU,MAAM,EAAA,EAAG;AACzB,EAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,OAAO,CAAA;AAC3C,EAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,UAAA,EAAY,OAAO,CAAA;AAC7D,CAAA;AAEO,IAAM,sBAAA,GAAyB,CACpC,OAAA,KACqB;AACrB,EAAA,MAAM,SAAA,GAAY,QAAQ,eAAA,IAAmB,gBAAA;AAC7C,EAAA,MAAM,SAAA,GAAY,QAAQ,eAAA,IAAmB,gBAAA;AAC7C,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,gBAAA;AAEvC,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAQ,IAAA,IAAQ,KAAA;AAAA,IACtB,GAAA,EAAK,MAAM,OAAA,CAAQ,KAAA,CAAM,WAAW,CAAA;AAAA,IACpC,KAAK,CAAC,IAAA,KAAS,UAAU,OAAA,CAAQ,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IAChD;AAAA,GACF;AACF","file":"url.cjs","sourcesContent":["import type { SourceAdapter, Subscriber, Unsubscribe } from \"../core/types\";\n\nexport type UrlAdapterOptions<T> = {\n parse: (params: URLSearchParams) => T;\n serialize: (value: T) => URLSearchParams;\n getSearchParams?: () => URLSearchParams;\n setSearchParams?: (params: URLSearchParams) => void;\n subscribe?: (cb: Subscriber) => Unsubscribe;\n kind?: string;\n};\n\nconst defaultGetParams = () => {\n if (typeof window === \"undefined\") {\n return new URLSearchParams();\n }\n return new URLSearchParams(window.location.search);\n};\n\nconst defaultSetParams = (params: URLSearchParams) => {\n if (typeof window === \"undefined\") {\n return;\n }\n const url = `${window.location.pathname}?${params.toString()}${window.location.hash}`;\n window.history.replaceState({}, \"\", url);\n};\n\nconst defaultSubscribe = (cb: Subscriber): Unsubscribe => {\n if (typeof window === \"undefined\") {\n return () => undefined;\n }\n const handler = () => cb();\n window.addEventListener(\"popstate\", handler);\n return () => window.removeEventListener(\"popstate\", handler);\n};\n\nexport const createUrlParamsAdapter = <T>(\n options: UrlAdapterOptions<T>\n): SourceAdapter<T> => {\n const getParams = options.getSearchParams ?? defaultGetParams;\n const setParams = options.setSearchParams ?? defaultSetParams;\n const subscribe = options.subscribe ?? defaultSubscribe;\n\n return {\n kind: options.kind ?? \"url\",\n get: () => options.parse(getParams()),\n set: (next) => setParams(options.serialize(next)),\n subscribe\n };\n};\n"]}
@@ -0,0 +1,13 @@
1
+ import { e as Subscriber, U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.cjs';
2
+
3
+ type UrlAdapterOptions<T> = {
4
+ parse: (params: URLSearchParams) => T;
5
+ serialize: (value: T) => URLSearchParams;
6
+ getSearchParams?: () => URLSearchParams;
7
+ setSearchParams?: (params: URLSearchParams) => void;
8
+ subscribe?: (cb: Subscriber) => Unsubscribe;
9
+ kind?: string;
10
+ };
11
+ declare const createUrlParamsAdapter: <T>(options: UrlAdapterOptions<T>) => SourceAdapter<T>;
12
+
13
+ export { type UrlAdapterOptions, createUrlParamsAdapter };
@@ -0,0 +1,13 @@
1
+ import { e as Subscriber, U as Unsubscribe, d as SourceAdapter } from '../types-B1uzdpYH.js';
2
+
3
+ type UrlAdapterOptions<T> = {
4
+ parse: (params: URLSearchParams) => T;
5
+ serialize: (value: T) => URLSearchParams;
6
+ getSearchParams?: () => URLSearchParams;
7
+ setSearchParams?: (params: URLSearchParams) => void;
8
+ subscribe?: (cb: Subscriber) => Unsubscribe;
9
+ kind?: string;
10
+ };
11
+ declare const createUrlParamsAdapter: <T>(options: UrlAdapterOptions<T>) => SourceAdapter<T>;
12
+
13
+ export { type UrlAdapterOptions, createUrlParamsAdapter };