@lunarhue/store 0.1.0 → 0.3.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.
- package/README.md +19 -10
- package/dist/chunk-C5U3Q6O3.js +133 -0
- package/dist/chunk-C5U3Q6O3.js.map +1 -0
- package/dist/chunk-GHGDIRN2.js +187 -0
- package/dist/chunk-GHGDIRN2.js.map +1 -0
- package/dist/core/index.d.ts +12 -2
- package/dist/core/index.js +8 -3
- package/dist/core/index.js.map +1 -1
- package/dist/plugins/actions/index.d.ts +51 -12
- package/dist/plugins/actions/index.js +1 -3
- package/dist/plugins/actions/index.js.map +1 -1
- package/dist/plugins/persist/index.d.ts +139 -51
- package/dist/plugins/persist/index.js +149 -220
- package/dist/plugins/persist/index.js.map +1 -1
- package/dist/react/index.d.ts +76 -5
- package/dist/react/index.js +1 -1
- package/dist/types-CugArdrs.d.ts +107 -0
- package/package.json +4 -3
- package/dist/chunk-IP5Y4BHA.js +0 -103
- package/dist/chunk-IP5Y4BHA.js.map +0 -1
- package/dist/chunk-MIBJNMOV.js +0 -45
- package/dist/chunk-MIBJNMOV.js.map +0 -1
- package/dist/types-ByMGdUb-.d.ts +0 -28
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# `@lunarhue/store`
|
|
2
2
|
|
|
3
|
-
Framework-agnostic state built on top of `@tanstack/store`, with
|
|
4
|
-
|
|
3
|
+
Framework-agnostic state built on top of `@tanstack/store`, with typed plugins
|
|
4
|
+
and React bindings.
|
|
5
5
|
|
|
6
6
|
## Install
|
|
7
7
|
|
|
8
|
+
Package: <https://www.npmjs.com/package/@lunarhue/store>
|
|
9
|
+
|
|
8
10
|
```sh
|
|
9
11
|
npm install @lunarhue/store
|
|
10
12
|
```
|
|
@@ -23,18 +25,19 @@ There is no root package barrel export.
|
|
|
23
25
|
```ts
|
|
24
26
|
import { createStore } from '@lunarhue/store/core'
|
|
25
27
|
|
|
26
|
-
const CounterStore = createStore({
|
|
27
|
-
count: 0,
|
|
28
|
-
})
|
|
29
|
-
|
|
28
|
+
const CounterStore = createStore({ count: 0 })
|
|
30
29
|
const store = CounterStore.create()
|
|
31
30
|
|
|
32
31
|
store.setState((prev) => ({
|
|
33
|
-
...prev,
|
|
34
32
|
count: prev.count + 1,
|
|
35
33
|
}))
|
|
36
34
|
```
|
|
37
35
|
|
|
36
|
+
If a builder is declared without initial state, `.create()` returns an
|
|
37
|
+
uninitialized runtime store. In that case, provide `initialState` or
|
|
38
|
+
`loadInitialState` when using the React provider, or call
|
|
39
|
+
`store.setInitialState(...)` before reading or writing state directly.
|
|
40
|
+
|
|
38
41
|
## React usage
|
|
39
42
|
|
|
40
43
|
```tsx
|
|
@@ -48,7 +51,7 @@ function CounterValue() {
|
|
|
48
51
|
return <span>{count}</span>
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
function App() {
|
|
54
|
+
export function App() {
|
|
52
55
|
return (
|
|
53
56
|
<StoreProvider builder={CounterStore}>
|
|
54
57
|
<CounterValue />
|
|
@@ -57,7 +60,13 @@ function App() {
|
|
|
57
60
|
}
|
|
58
61
|
```
|
|
59
62
|
|
|
63
|
+
## Plugins
|
|
64
|
+
|
|
65
|
+
- `actions(...)` attaches typed runtime actions on `store.actions`
|
|
66
|
+
- `persist(...)` attaches `store.persist`, with runtime wiring handled by `PersistStoreProvider`
|
|
67
|
+
|
|
60
68
|
## Docs
|
|
61
69
|
|
|
62
|
-
- Repo README: https://github.com/LunarHUE/store#readme
|
|
63
|
-
- API
|
|
70
|
+
- Repo README: <https://github.com/LunarHUE/store#readme>
|
|
71
|
+
- API reference: <https://github.com/LunarHUE/store/blob/main/docs/api.md>
|
|
72
|
+
- Architecture notes: <https://github.com/LunarHUE/store/blob/main/docs/architecture.md>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createStore } from '@tanstack/store';
|
|
2
|
+
|
|
3
|
+
// src/core/store-instance.ts
|
|
4
|
+
var UNINITIALIZED = /* @__PURE__ */ Symbol("lunarhue.store.uninitialized");
|
|
5
|
+
function createStoreInstance({
|
|
6
|
+
initialState,
|
|
7
|
+
readyOnCreate
|
|
8
|
+
}) {
|
|
9
|
+
const store = createStore(
|
|
10
|
+
readyOnCreate ? initialState : UNINITIALIZED
|
|
11
|
+
);
|
|
12
|
+
const lifecycleMeta = createStore({
|
|
13
|
+
status: readyOnCreate ? "ready" : "uninitialized",
|
|
14
|
+
error: null
|
|
15
|
+
});
|
|
16
|
+
const cleanups = [];
|
|
17
|
+
let disposePromise = null;
|
|
18
|
+
const nativeStateGetter = Object.getOwnPropertyDescriptor(
|
|
19
|
+
Object.getPrototypeOf(store),
|
|
20
|
+
"state"
|
|
21
|
+
)?.get;
|
|
22
|
+
if (!nativeStateGetter) {
|
|
23
|
+
throw new Error("Failed to resolve the TanStack Store state getter.");
|
|
24
|
+
}
|
|
25
|
+
const nativeGet = () => nativeStateGetter.call(store);
|
|
26
|
+
const nativeSetState = store.setState.bind(store);
|
|
27
|
+
const nativeSubscribe = store.subscribe.bind(store);
|
|
28
|
+
const instance = store;
|
|
29
|
+
const assertReady = (value) => {
|
|
30
|
+
if (value === UNINITIALIZED) {
|
|
31
|
+
throw new Error("Store has not been initialized.");
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
const getState = () => assertReady(nativeGet());
|
|
36
|
+
const lifecycle = {
|
|
37
|
+
meta: lifecycleMeta
|
|
38
|
+
};
|
|
39
|
+
const subscribe = ((observerOrFn, error, complete) => {
|
|
40
|
+
const observer = typeof observerOrFn === "function" ? {
|
|
41
|
+
next: observerOrFn,
|
|
42
|
+
error,
|
|
43
|
+
complete
|
|
44
|
+
} : observerOrFn;
|
|
45
|
+
return nativeSubscribe((value) => {
|
|
46
|
+
if (value === UNINITIALIZED) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
observer.next?.(value);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(instance, "dispose", {
|
|
53
|
+
configurable: true,
|
|
54
|
+
enumerable: true,
|
|
55
|
+
value: async () => {
|
|
56
|
+
if (disposePromise) {
|
|
57
|
+
return disposePromise;
|
|
58
|
+
}
|
|
59
|
+
disposePromise = (async () => {
|
|
60
|
+
for (const cleanup of [...cleanups].reverse()) {
|
|
61
|
+
await cleanup();
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
return disposePromise;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
Object.defineProperties(instance, {
|
|
68
|
+
get: {
|
|
69
|
+
configurable: true,
|
|
70
|
+
enumerable: true,
|
|
71
|
+
value: () => getState()
|
|
72
|
+
},
|
|
73
|
+
state: {
|
|
74
|
+
configurable: true,
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get() {
|
|
77
|
+
return getState();
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
setState: {
|
|
81
|
+
configurable: true,
|
|
82
|
+
enumerable: true,
|
|
83
|
+
value: (updater) => {
|
|
84
|
+
nativeSetState((prev) => updater(assertReady(prev)));
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
subscribe: {
|
|
88
|
+
configurable: true,
|
|
89
|
+
enumerable: true,
|
|
90
|
+
value: subscribe
|
|
91
|
+
},
|
|
92
|
+
setInitialState: {
|
|
93
|
+
configurable: true,
|
|
94
|
+
enumerable: true,
|
|
95
|
+
value: async (nextState) => {
|
|
96
|
+
if (nativeGet() !== UNINITIALIZED) {
|
|
97
|
+
throw new Error("Store initial state has already been set.");
|
|
98
|
+
}
|
|
99
|
+
nativeSetState(() => nextState);
|
|
100
|
+
lifecycleMeta.setState(() => ({
|
|
101
|
+
status: "ready",
|
|
102
|
+
error: null
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
lifecycle: {
|
|
107
|
+
configurable: true,
|
|
108
|
+
enumerable: true,
|
|
109
|
+
value: lifecycle
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
store: instance,
|
|
114
|
+
onDispose(cleanup) {
|
|
115
|
+
cleanups.push(cleanup);
|
|
116
|
+
},
|
|
117
|
+
attachSurface(surface) {
|
|
118
|
+
for (const key of Reflect.ownKeys(surface)) {
|
|
119
|
+
if (key in instance) {
|
|
120
|
+
throw new Error(`Store plugin surface collision on "${String(key)}".`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
Object.defineProperties(
|
|
124
|
+
instance,
|
|
125
|
+
Object.getOwnPropertyDescriptors(surface)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { createStoreInstance };
|
|
132
|
+
//# sourceMappingURL=chunk-C5U3Q6O3.js.map
|
|
133
|
+
//# sourceMappingURL=chunk-C5U3Q6O3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/store-instance.ts"],"names":["createTanStackStore"],"mappings":";;;AAyBA,IAAM,aAAA,0BAAuB,8BAA8B,CAAA;AAEpD,SAAS,mBAAA,CAA4B;AAAA,EAC1C,YAAA;AAAA,EACA;AACF,CAAA,EAAgE;AAC9D,EAAA,MAAM,KAAA,GAAQA,WAAA;AAAA,IACZ,gBAAiB,YAAA,GAA0B;AAAA,GAC7C;AACA,EAAA,MAAM,gBAAgBA,WAAA,CAAwC;AAAA,IAC5D,MAAA,EAAQ,gBAAgB,OAAA,GAAU,eAAA;AAAA,IAClC,KAAA,EAAO;AAAA,GACR,CAAA;AACD,EAAA,MAAM,WAA2B,EAAC;AAClC,EAAA,IAAI,cAAA,GAAuC,IAAA;AAE3C,EAAA,MAAM,oBAAoB,MAAA,CAAO,wBAAA;AAAA,IAC/B,MAAA,CAAO,eAAe,KAAK,CAAA;AAAA,IAC3B;AAAA,GACF,EAAG,GAAA;AAEH,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AACpD,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA;AAChD,EAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA;AAClD,EAAA,MAAM,QAAA,GAAW,KAAA;AAEjB,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAiD;AACpE,IAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AAEA,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,QAAA,GAAW,MAAM,WAAA,CAAY,SAAA,EAAW,CAAA;AAC9C,EAAA,MAAM,SAAA,GAAY;AAAA,IAChB,IAAA,EAAM;AAAA,GACR;AACA,EAAA,MAAM,SAAA,IAAa,CACjB,YAAA,EACA,KAAA,EACA,QAAA,KACiB;AACjB,IAAA,MAAM,QAAA,GACJ,OAAO,YAAA,KAAiB,UAAA,GACpB;AAAA,MACE,IAAA,EAAM,YAAA;AAAA,MACN,KAAA;AAAA,MACA;AAAA,KACF,GACA,YAAA;AAEN,IAAA,OAAO,eAAA,CAAgB,CAAC,KAAA,KAAU;AAChC,MAAA,IAAI,UAAU,aAAA,EAAe;AAC3B,QAAA;AAAA,MACF;AAEA,MAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH,CAAA,CAAA;AAEA,EAAA,MAAA,CAAO,cAAA,CAAe,UAAU,SAAA,EAAW;AAAA,IACzC,YAAA,EAAc,IAAA;AAAA,IACd,UAAA,EAAY,IAAA;AAAA,IACZ,OAAO,YAAY;AACjB,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,OAAO,cAAA;AAAA,MACT;AAEA,MAAA,cAAA,GAAA,CAAkB,YAAY;AAC5B,QAAA,KAAA,MAAW,WAAW,CAAC,GAAG,QAAQ,CAAA,CAAE,SAAQ,EAAG;AAC7C,UAAA,MAAM,OAAA,EAAQ;AAAA,QAChB;AAAA,MACF,CAAA,GAAG;AAEH,MAAA,OAAO,cAAA;AAAA,IACT;AAAA,GACD,CAAA;AAED,EAAA,MAAA,CAAO,iBAAiB,QAAA,EAAU;AAAA,IAChC,GAAA,EAAK;AAAA,MACH,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,KAAA,EAAO,MAAM,QAAA;AAAS,KACxB;AAAA,IACA,KAAA,EAAO;AAAA,MACL,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,GAAA,GAAM;AACJ,QAAA,OAAO,QAAA,EAAS;AAAA,MAClB;AAAA,KACF;AAAA,IACA,QAAA,EAAU;AAAA,MACR,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,KAAA,EAAO,CAAC,OAAA,KAAsC;AAC5C,QAAA,cAAA,CAAe,CAAC,IAAA,KAAS,OAAA,CAAQ,WAAA,CAAY,IAAI,CAAC,CAAC,CAAA;AAAA,MACrD;AAAA,KACF;AAAA,IACA,SAAA,EAAW;AAAA,MACT,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,KAAA,EAAO;AAAA,KACT;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,KAAA,EAAO,OAAO,SAAA,KAAsB;AAClC,QAAA,IAAI,SAAA,OAAgB,aAAA,EAAe;AACjC,UAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,QAC7D;AAEA,QAAA,cAAA,CAAe,MAAM,SAAS,CAAA;AAC9B,QAAA,aAAA,CAAc,SAAS,OAAO;AAAA,UAC5B,MAAA,EAAQ,OAAA;AAAA,UACR,KAAA,EAAO;AAAA,SACT,CAAE,CAAA;AAAA,MACJ;AAAA,KACF;AAAA,IACA,SAAA,EAAW;AAAA,MACT,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY,IAAA;AAAA,MACZ,KAAA,EAAO;AAAA;AACT,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,QAAA;AAAA,IACP,UAAU,OAAA,EAAS;AACjB,MAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,cAAc,OAAA,EAAS;AACrB,MAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1C,QAAA,IAAI,OAAO,QAAA,EAAU;AACnB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mCAAA,EAAsC,MAAA,CAAO,GAAG,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,QACvE;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,gBAAA;AAAA,QACL,QAAA;AAAA,QACA,MAAA,CAAO,0BAA0B,OAAO;AAAA,OAC1C;AAAA,IACF;AAAA,GACF;AACF","file":"chunk-C5U3Q6O3.js","sourcesContent":["import {\n createStore as createTanStackStore,\n type Observer,\n type Store as BaseStore,\n type Subscription,\n} from '@tanstack/store'\n\nimport type {\n StoreCleanup,\n Store,\n StoreLifecycleMeta,\n ReadableStore,\n} from './types'\n\ntype StoreController<TState> = {\n store: Store<TState>\n onDispose(cleanup: StoreCleanup): void\n attachSurface(surface: object): void\n}\n\ntype CreateStoreInstanceOptions<TState> = {\n initialState?: TState\n readyOnCreate: boolean\n}\n\nconst UNINITIALIZED = Symbol('lunarhue.store.uninitialized')\n\nexport function createStoreInstance<TState>({\n initialState,\n readyOnCreate,\n}: CreateStoreInstanceOptions<TState>): StoreController<TState> {\n const store = createTanStackStore<TState | typeof UNINITIALIZED>(\n readyOnCreate ? (initialState as TState) : UNINITIALIZED,\n )\n const lifecycleMeta = createTanStackStore<StoreLifecycleMeta>({\n status: readyOnCreate ? 'ready' : 'uninitialized',\n error: null,\n })\n const cleanups: StoreCleanup[] = []\n let disposePromise: Promise<void> | null = null\n\n const nativeStateGetter = Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(store),\n 'state',\n )?.get\n\n if (!nativeStateGetter) {\n throw new Error('Failed to resolve the TanStack Store state getter.')\n }\n\n const nativeGet = () => nativeStateGetter.call(store)\n const nativeSetState = store.setState.bind(store)\n const nativeSubscribe = store.subscribe.bind(store)\n const instance = store as unknown as Store<TState>\n\n const assertReady = (value: TState | typeof UNINITIALIZED): TState => {\n if (value === UNINITIALIZED) {\n throw new Error('Store has not been initialized.')\n }\n\n return value\n }\n\n const getState = () => assertReady(nativeGet())\n const lifecycle = {\n meta: lifecycleMeta as ReadableStore<StoreLifecycleMeta>,\n }\n const subscribe = ((\n observerOrFn: Observer<TState> | ((value: TState) => void),\n error?: (error: any) => void,\n complete?: () => void,\n ): Subscription => {\n const observer =\n typeof observerOrFn === 'function'\n ? {\n next: observerOrFn,\n error,\n complete,\n }\n : observerOrFn\n\n return nativeSubscribe((value) => {\n if (value === UNINITIALIZED) {\n return\n }\n\n observer.next?.(value)\n })\n }) as BaseStore<TState>['subscribe']\n\n Object.defineProperty(instance, 'dispose', {\n configurable: true,\n enumerable: true,\n value: async () => {\n if (disposePromise) {\n return disposePromise\n }\n\n disposePromise = (async () => {\n for (const cleanup of [...cleanups].reverse()) {\n await cleanup()\n }\n })()\n\n return disposePromise\n },\n })\n\n Object.defineProperties(instance, {\n get: {\n configurable: true,\n enumerable: true,\n value: () => getState(),\n },\n state: {\n configurable: true,\n enumerable: true,\n get() {\n return getState()\n },\n },\n setState: {\n configurable: true,\n enumerable: true,\n value: (updater: (prev: TState) => TState) => {\n nativeSetState((prev) => updater(assertReady(prev)))\n },\n },\n subscribe: {\n configurable: true,\n enumerable: true,\n value: subscribe,\n },\n setInitialState: {\n configurable: true,\n enumerable: true,\n value: async (nextState: TState) => {\n if (nativeGet() !== UNINITIALIZED) {\n throw new Error('Store initial state has already been set.')\n }\n\n nativeSetState(() => nextState)\n lifecycleMeta.setState(() => ({\n status: 'ready',\n error: null,\n }))\n },\n },\n lifecycle: {\n configurable: true,\n enumerable: true,\n value: lifecycle,\n },\n })\n\n return {\n store: instance,\n onDispose(cleanup) {\n cleanups.push(cleanup)\n },\n attachSurface(surface) {\n for (const key of Reflect.ownKeys(surface)) {\n if (key in instance) {\n throw new Error(`Store plugin surface collision on \"${String(key)}\".`)\n }\n }\n\n Object.defineProperties(\n instance,\n Object.getOwnPropertyDescriptors(surface),\n )\n },\n }\n}\n"]}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { getStoreBuilder } from './chunk-PCSRXZL4.js';
|
|
2
|
+
import { useRef, useState, useEffectEvent, useEffect, useContext, createContext } from 'react';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { useStore as useStore$1 } from '@tanstack/react-store';
|
|
5
|
+
|
|
6
|
+
var contextMap = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function getStoreContext(builder) {
|
|
8
|
+
let context = contextMap.get(builder);
|
|
9
|
+
if (!context) {
|
|
10
|
+
context = createContext(void 0);
|
|
11
|
+
contextMap.set(builder, context);
|
|
12
|
+
}
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function StoreProvider(props) {
|
|
16
|
+
if (props.builder !== void 0) {
|
|
17
|
+
return /* @__PURE__ */ jsx(
|
|
18
|
+
BuilderOwnedStoreProvider,
|
|
19
|
+
{
|
|
20
|
+
builder: props.builder,
|
|
21
|
+
hasInitialState: "initialState" in props,
|
|
22
|
+
initialState: props.initialState,
|
|
23
|
+
loadInitialState: props.loadInitialState,
|
|
24
|
+
children: props.children
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return /* @__PURE__ */ jsx(ExternalStoreProvider, { store: props.store, children: props.children });
|
|
29
|
+
}
|
|
30
|
+
function updateLifecycleMeta(store, updater) {
|
|
31
|
+
store.lifecycle.meta.setState(updater);
|
|
32
|
+
}
|
|
33
|
+
function BuilderOwnedStoreProvider({
|
|
34
|
+
builder,
|
|
35
|
+
children,
|
|
36
|
+
hasInitialState,
|
|
37
|
+
initialState,
|
|
38
|
+
loadInitialState
|
|
39
|
+
}) {
|
|
40
|
+
const context = getStoreContext(builder);
|
|
41
|
+
const builderRef = useRef(null);
|
|
42
|
+
const initializeStartedRef = useRef(false);
|
|
43
|
+
const storeRef = useRef(null);
|
|
44
|
+
const [, forceRender] = useState(0);
|
|
45
|
+
if (!builderRef.current) {
|
|
46
|
+
builderRef.current = builder;
|
|
47
|
+
} else if (builderRef.current !== builder) {
|
|
48
|
+
const isDev = process.env.NODE_ENV !== "production" || typeof __DEV__ !== "undefined" && __DEV__;
|
|
49
|
+
if (isDev) {
|
|
50
|
+
console.warn("StoreProvider builder prop must remain stable.");
|
|
51
|
+
} else {
|
|
52
|
+
throw new Error("StoreProvider builder prop must remain stable.");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!storeRef.current) {
|
|
56
|
+
storeRef.current = hasInitialState ? builder.create(initialState) : builder.create();
|
|
57
|
+
}
|
|
58
|
+
const initializeStore = useEffectEvent(async () => {
|
|
59
|
+
const ownedStore2 = storeRef.current;
|
|
60
|
+
if (!ownedStore2 || !loadInitialState) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
updateLifecycleMeta(ownedStore2, (prev) => ({
|
|
64
|
+
...prev,
|
|
65
|
+
status: "initializing",
|
|
66
|
+
error: null
|
|
67
|
+
}));
|
|
68
|
+
try {
|
|
69
|
+
const nextState = await loadInitialState({ store: ownedStore2 });
|
|
70
|
+
await ownedStore2.setInitialState(nextState);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
updateLifecycleMeta(ownedStore2, () => ({
|
|
73
|
+
status: "error",
|
|
74
|
+
error
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const ownedStore2 = storeRef.current;
|
|
80
|
+
if (!ownedStore2) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const subscription = ownedStore2.lifecycle.meta.subscribe(() => {
|
|
84
|
+
forceRender((value) => value + 1);
|
|
85
|
+
});
|
|
86
|
+
return () => {
|
|
87
|
+
subscription.unsubscribe();
|
|
88
|
+
if (!ownedStore2) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
void ownedStore2.dispose();
|
|
92
|
+
};
|
|
93
|
+
}, []);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
const ownedStore2 = storeRef.current;
|
|
96
|
+
if (!ownedStore2 || initializeStartedRef.current || ownedStore2.lifecycle.meta.get().status !== "uninitialized" || !loadInitialState) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
initializeStartedRef.current = true;
|
|
100
|
+
void initializeStore();
|
|
101
|
+
}, [loadInitialState, initializeStore]);
|
|
102
|
+
const ownedStore = storeRef.current;
|
|
103
|
+
const lifecycleMeta = ownedStore.lifecycle.meta.get();
|
|
104
|
+
if (lifecycleMeta.status === "error") {
|
|
105
|
+
throw lifecycleMeta.error ?? new Error("Store initialization failed.");
|
|
106
|
+
}
|
|
107
|
+
if (lifecycleMeta.status === "uninitialized" && !loadInitialState) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
"StoreProvider requires initialState or loadInitialState when the builder has no declared initial state."
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (lifecycleMeta.status === "uninitialized" || lifecycleMeta.status === "initializing") {
|
|
113
|
+
return /* @__PURE__ */ jsx(context.Provider, { value: ownedStore, children: null });
|
|
114
|
+
}
|
|
115
|
+
const content = typeof children === "function" ? children({ store: ownedStore }) : children;
|
|
116
|
+
return /* @__PURE__ */ jsx(context.Provider, { value: ownedStore, children: content });
|
|
117
|
+
}
|
|
118
|
+
function ExternalStoreProvider({
|
|
119
|
+
children,
|
|
120
|
+
store
|
|
121
|
+
}) {
|
|
122
|
+
const builder = getStoreBuilder(store);
|
|
123
|
+
if (!builder) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"StoreProvider could not resolve a builder for the provided store. Pass a store created by @lunarhue/store."
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const context = getStoreContext(builder);
|
|
129
|
+
const content = typeof children === "function" ? children({ store }) : children;
|
|
130
|
+
return /* @__PURE__ */ jsx(context.Provider, { value: store, children: content });
|
|
131
|
+
}
|
|
132
|
+
function useLocalStore(builder, options) {
|
|
133
|
+
const initializeStartedRef = useRef(false);
|
|
134
|
+
const localStoreRef = useRef(null);
|
|
135
|
+
const hasInitialState = options !== void 0 && Object.prototype.hasOwnProperty.call(options, "initialState");
|
|
136
|
+
if (!localStoreRef.current) {
|
|
137
|
+
localStoreRef.current = hasInitialState ? builder.create(options?.initialState) : builder.create();
|
|
138
|
+
}
|
|
139
|
+
const initializeStore = useEffectEvent(async () => {
|
|
140
|
+
const localStore = localStoreRef.current;
|
|
141
|
+
if (!localStore || !options?.loadInitialState) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const nextState = await options.loadInitialState({ store: localStore });
|
|
145
|
+
await localStore.setInitialState(nextState);
|
|
146
|
+
});
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
const localStore = localStoreRef.current;
|
|
149
|
+
if (localStore && !initializeStartedRef.current && localStore.lifecycle.meta.get().status === "uninitialized" && options?.loadInitialState) {
|
|
150
|
+
initializeStartedRef.current = true;
|
|
151
|
+
void initializeStore();
|
|
152
|
+
}
|
|
153
|
+
return () => {
|
|
154
|
+
if (!localStore) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
void localStore.dispose();
|
|
158
|
+
};
|
|
159
|
+
}, [initializeStore, options?.loadInitialState]);
|
|
160
|
+
return localStoreRef.current;
|
|
161
|
+
}
|
|
162
|
+
function useSelector(store, selector, compare) {
|
|
163
|
+
return useStore$1(
|
|
164
|
+
store,
|
|
165
|
+
selector,
|
|
166
|
+
compare
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
function useStore(builder) {
|
|
170
|
+
const contextValue = useContext(getStoreContext(builder));
|
|
171
|
+
if (!contextValue) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
"useStore(builder) requires a matching <StoreProvider builder={...}> or <StoreProvider store={...}> ancestor."
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return contextValue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/react/use-store-selector.ts
|
|
180
|
+
function useStoreSelector(builder, selector, compare) {
|
|
181
|
+
const store = useStore(builder);
|
|
182
|
+
return useSelector(store, selector, compare);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export { StoreProvider, useLocalStore, useSelector, useStore, useStoreSelector };
|
|
186
|
+
//# sourceMappingURL=chunk-GHGDIRN2.js.map
|
|
187
|
+
//# sourceMappingURL=chunk-GHGDIRN2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react/context.ts","../src/react/provider.tsx","../src/react/use-local-store.ts","../src/react/use-selector.ts","../src/react/use-store.ts","../src/react/use-store-selector.ts"],"names":["ownedStore","useRef","useEffectEvent","useEffect","useTanStackStore"],"mappings":"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","file":"chunk-GHGDIRN2.js","sourcesContent":["import { createContext, type Context } from 'react'\n\nimport type { Store, StoreBuilder } from '../core'\n\nexport type StoreContext<TState, TPlugins> = Context<\n Store<TState, TPlugins> | undefined\n>\n\nconst contextMap = new WeakMap<StoreBuilder<any, any>, StoreContext<any, any>>()\n\nexport function getStoreContext<TState, TPlugins>(\n builder: StoreBuilder<TState, TPlugins>,\n): StoreContext<TState, TPlugins> {\n let context = contextMap.get(builder)\n\n if (!context) {\n context = createContext<Store<TState, TPlugins> | undefined>(undefined)\n contextMap.set(builder, context)\n }\n\n return context\n}\n","import {\n useEffect,\n useEffectEvent,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\n\nimport { getStoreBuilder } from '../core/builder-registry'\nimport { getStoreContext } from './context'\n\nimport type {\n ReadableStore,\n Store,\n StoreBuilder,\n StoreInitialStateLoader,\n StoreLifecycleMeta,\n} from '../core'\n\ntype StoreProviderChildren<TState, TPlugins> =\n | ReactNode\n | ((args: { store: Store<TState, TPlugins> }) => ReactNode)\n\ntype BuilderProviderBaseProps<TState, TPlugins> = {\n builder: StoreBuilder<TState, TPlugins>\n children?: StoreProviderChildren<TState, TPlugins>\n hasInitialState?: boolean\n store?: never\n}\n\ntype BuilderProviderWithInitialStateProps<TState, TPlugins> =\n BuilderProviderBaseProps<TState, TPlugins> & {\n initialState: TState\n loadInitialState?: never\n }\n\ntype BuilderProviderWithLoadInitialStateProps<TState, TPlugins> =\n BuilderProviderBaseProps<TState, TPlugins> & {\n initialState?: never\n loadInitialState: StoreInitialStateLoader<TState, TPlugins>\n }\n\ntype BuilderProviderWithDeclaredInitialStateProps<TState, TPlugins> =\n BuilderProviderBaseProps<TState, TPlugins> & {\n initialState?: never\n loadInitialState?: never\n }\n\ntype BuilderProviderProps<TState, TPlugins> =\n | BuilderProviderWithDeclaredInitialStateProps<TState, TPlugins>\n | BuilderProviderWithInitialStateProps<TState, TPlugins>\n | BuilderProviderWithLoadInitialStateProps<TState, TPlugins>\n\ntype BuilderOwnedStoreProviderProps<TState, TPlugins> = {\n builder: StoreBuilder<TState, TPlugins>\n children?: StoreProviderChildren<TState, TPlugins>\n hasInitialState: boolean\n initialState?: TState\n loadInitialState?: StoreInitialStateLoader<TState, TPlugins>\n}\n\ntype StoreProviderProps<TState, TPlugins> = {\n builder?: never\n children?: StoreProviderChildren<TState, TPlugins>\n store: Store<TState, TPlugins>\n}\n\n/**\n * Props for {@link StoreProvider}.\n *\n * Use either `builder` to let the provider create and own the runtime store,\n * or `store` to provide an already-created runtime store. When a builder has\n * no declared initial state, the builder-owned form must also provide either\n * `initialState` or `loadInitialState`.\n */\nexport type ProviderProps<TState, TPlugins = {}> =\n | BuilderProviderProps<TState, TPlugins>\n | StoreProviderProps<TState, TPlugins>\n\n/**\n * Provides a builder-scoped runtime store to React descendants.\n *\n * Builder-owned providers create and dispose the runtime store automatically.\n * External-store providers reuse an existing runtime store and do not own its\n * disposal. The `builder` prop must remain stable for the provider lifetime.\n * Children may be plain JSX or a render prop that receives the resolved\n * runtime store instance.\n */\nexport function StoreProvider<TState, TPlugins>(\n props: ProviderProps<TState, TPlugins>,\n) {\n if (props.builder !== undefined) {\n return (\n <BuilderOwnedStoreProvider\n builder={props.builder}\n hasInitialState={'initialState' in props}\n initialState={props.initialState}\n loadInitialState={props.loadInitialState}\n >\n {props.children}\n </BuilderOwnedStoreProvider>\n )\n }\n\n return (\n <ExternalStoreProvider store={props.store}>\n {props.children}\n </ExternalStoreProvider>\n )\n}\n\n// Native and Expo declare this globally in development mode.\ndeclare const __DEV__: boolean\n\ntype WritableReadableStore<TState> = ReadableStore<TState> & {\n setState(updater: (prev: TState) => TState): void\n}\n\nfunction updateLifecycleMeta<TState, TPlugins>(\n store: Store<TState, TPlugins>,\n updater: (prev: StoreLifecycleMeta) => StoreLifecycleMeta,\n) {\n ;(\n store.lifecycle.meta as WritableReadableStore<StoreLifecycleMeta>\n ).setState(updater)\n}\n\nfunction BuilderOwnedStoreProvider<TState, TPlugins>({\n builder,\n children,\n hasInitialState,\n initialState,\n loadInitialState,\n}: BuilderOwnedStoreProviderProps<TState, TPlugins>) {\n const context = getStoreContext(builder)\n const builderRef = useRef<StoreBuilder<TState, TPlugins> | null>(null)\n const initializeStartedRef = useRef(false)\n const storeRef = useRef<Store<TState, TPlugins> | null>(null)\n const [, forceRender] = useState(0)\n\n if (!builderRef.current) {\n builderRef.current = builder\n } else if (builderRef.current !== builder) {\n const isDev =\n process.env.NODE_ENV !== 'production' ||\n (typeof __DEV__ !== 'undefined' && __DEV__)\n\n if (isDev) {\n console.warn('StoreProvider builder prop must remain stable.')\n } else {\n throw new Error('StoreProvider builder prop must remain stable.')\n }\n }\n\n if (!storeRef.current) {\n storeRef.current = hasInitialState\n ? builder.create(initialState)\n : builder.create()\n }\n\n const initializeStore = useEffectEvent(async () => {\n const ownedStore = storeRef.current\n\n if (!ownedStore || !loadInitialState) {\n return\n }\n\n updateLifecycleMeta(ownedStore, (prev) => ({\n ...prev,\n status: 'initializing',\n error: null,\n }))\n\n try {\n const nextState = await loadInitialState({ store: ownedStore })\n await ownedStore.setInitialState(nextState)\n } catch (error) {\n updateLifecycleMeta(ownedStore, () => ({\n status: 'error',\n error,\n }))\n }\n })\n\n useEffect(() => {\n const ownedStore = storeRef.current\n\n if (!ownedStore) {\n return\n }\n\n const subscription = ownedStore.lifecycle.meta.subscribe(() => {\n forceRender((value) => value + 1)\n })\n\n return () => {\n subscription.unsubscribe()\n\n if (!ownedStore) {\n return\n }\n\n void ownedStore.dispose()\n }\n }, [])\n\n useEffect(() => {\n const ownedStore = storeRef.current\n\n if (\n !ownedStore ||\n initializeStartedRef.current ||\n ownedStore.lifecycle.meta.get().status !== 'uninitialized' ||\n !loadInitialState\n ) {\n return\n }\n\n initializeStartedRef.current = true\n void initializeStore()\n }, [loadInitialState, initializeStore])\n\n const ownedStore = storeRef.current\n const lifecycleMeta = ownedStore.lifecycle.meta.get()\n\n if (lifecycleMeta.status === 'error') {\n throw lifecycleMeta.error ?? new Error('Store initialization failed.')\n }\n\n if (lifecycleMeta.status === 'uninitialized' && !loadInitialState) {\n throw new Error(\n 'StoreProvider requires initialState or loadInitialState when the builder has no declared initial state.',\n )\n }\n\n if (\n lifecycleMeta.status === 'uninitialized' ||\n lifecycleMeta.status === 'initializing'\n ) {\n return <context.Provider value={ownedStore}>{null}</context.Provider>\n }\n\n const content =\n typeof children === 'function'\n ? children({ store: ownedStore })\n : children\n\n return <context.Provider value={ownedStore}>{content}</context.Provider>\n}\n\nfunction ExternalStoreProvider<TState, TPlugins>({\n children,\n store,\n}: StoreProviderProps<TState, TPlugins>) {\n const builder = getStoreBuilder(store)\n\n if (!builder) {\n throw new Error(\n 'StoreProvider could not resolve a builder for the provided store. Pass a store created by @lunarhue/store.',\n )\n }\n\n const context = getStoreContext(builder)\n const content =\n typeof children === 'function' ? children({ store }) : children\n\n return <context.Provider value={store}>{content}</context.Provider>\n}\n","import { useEffect, useEffectEvent, useRef } from 'react'\n\nimport type { Store, StoreBuilder, StoreInitialStateLoader } from '../core'\n\ntype LocalStoreOptionsBase = {}\n\ntype LocalStoreWithInitialStateOptions<TState> = LocalStoreOptionsBase & {\n initialState: TState\n loadInitialState?: never\n}\n\ntype LocalStoreWithLoadInitialStateOptions<TState, TPlugins> =\n LocalStoreOptionsBase & {\n initialState?: never\n loadInitialState: StoreInitialStateLoader<TState, TPlugins>\n }\n\ntype LocalStoreDeclaredInitialStateOptions = LocalStoreOptionsBase & {\n initialState?: never\n loadInitialState?: never\n}\n\ntype LocalStoreOptions<TState, TPlugins> =\n | LocalStoreDeclaredInitialStateOptions\n | LocalStoreWithInitialStateOptions<TState>\n | LocalStoreWithLoadInitialStateOptions<TState, TPlugins>\n\n/**\n * Creates and owns a local runtime store for the current hook call site.\n *\n * The returned store is disposed on unmount. Pass `initialState` to start the\n * local store ready immediately, or `loadInitialState` to initialize a builder\n * that was declared without a default value. Without a declared default or one\n * of those options, the returned runtime store begins uninitialized.\n */\nexport function useLocalStore<TState, TPlugins>(\n builder: StoreBuilder<TState, TPlugins>,\n options?: LocalStoreOptions<TState, TPlugins>,\n): Store<TState, TPlugins> {\n const initializeStartedRef = useRef(false)\n const localStoreRef = useRef<Store<TState, TPlugins> | null>(null)\n const hasInitialState =\n options !== undefined &&\n Object.prototype.hasOwnProperty.call(options, 'initialState')\n\n if (!localStoreRef.current) {\n localStoreRef.current = hasInitialState\n ? builder.create(options?.initialState)\n : builder.create()\n }\n\n const initializeStore = useEffectEvent(async () => {\n const localStore = localStoreRef.current\n\n if (!localStore || !options?.loadInitialState) {\n return\n }\n\n const nextState = await options.loadInitialState({ store: localStore })\n await localStore.setInitialState(nextState)\n })\n\n useEffect(() => {\n const localStore = localStoreRef.current\n\n if (\n localStore &&\n !initializeStartedRef.current &&\n localStore.lifecycle.meta.get().status === 'uninitialized' &&\n options?.loadInitialState\n ) {\n initializeStartedRef.current = true\n void initializeStore()\n }\n\n return () => {\n if (!localStore) {\n return\n }\n\n void localStore.dispose()\n }\n }, [initializeStore, options?.loadInitialState])\n\n return localStoreRef.current\n}\n","import { useStore as useTanStackStore } from '@tanstack/react-store'\nimport type { Store as BaseStore } from '@tanstack/store'\n\nimport type { Store, StoreState } from '../core'\n\n/**\n * Subscribes to a selected slice of a runtime store instance.\n *\n * Use this when you already have a runtime store object. For builder-scoped\n * selection through context, use {@link useStoreSelector}.\n */\nexport function useSelector<\n TStore extends Store<any, any>,\n TSelected,\n TState extends StoreState<TStore>,\n>(\n store: TStore,\n selector: (snapshot: TState) => TSelected,\n compare?: (a: TSelected, b: TSelected) => boolean,\n): TSelected {\n return useTanStackStore<BaseStore<TState>, TSelected>(\n store as BaseStore<TState>,\n selector,\n compare,\n )\n}\n","import { useContext } from 'react'\n\nimport { getStoreContext } from './context'\n\nimport type { Store, StoreBuilder } from '../core'\n\n/**\n * Returns the runtime store provided for a builder.\n *\n * This hook requires a matching {@link StoreProvider} ancestor using either\n * the same builder or a runtime store created from that builder.\n */\nexport function useStore<TState, TPlugins>(\n builder: StoreBuilder<TState, TPlugins>,\n): Store<TState, TPlugins> {\n const contextValue = useContext(getStoreContext(builder))\n\n if (!contextValue) {\n throw new Error(\n 'useStore(builder) requires a matching <StoreProvider builder={...}> or <StoreProvider store={...}> ancestor.',\n )\n }\n\n return contextValue\n}\n","import { useStore } from './use-store'\nimport { useSelector } from './use-selector'\n\nimport type { StoreBuilder, StoreState } from '../core'\n\n/**\n * Convenience hook that resolves a builder-scoped runtime store from context\n * and subscribes to a selected slice of its state.\n *\n * This has the same matching-provider requirement as {@link useStore}.\n */\nexport function useStoreSelector<\n TState,\n TPlugins,\n TSelected,\n TBuilder extends StoreBuilder<TState, TPlugins>,\n>(\n builder: TBuilder,\n selector: (snapshot: StoreState<ReturnType<TBuilder['create']>>) => TSelected,\n compare?: (a: TSelected, b: TSelected) => boolean,\n): TSelected {\n const store = useStore(builder)\n\n return useSelector(store, selector, compare)\n}\n"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import { S as StoreBuilder } from '../types-
|
|
2
|
-
export {
|
|
1
|
+
import { S as StoreBuilder } from '../types-CugArdrs.js';
|
|
2
|
+
export { R as ReadableStore, a as Store, b as StoreCleanup, c as StoreInitialStateLoader, d as StoreLifecycleMeta, e as StoreLifecycleStatus, f as StorePlugin, g as StorePluginContext, h as StoreState } from '../types-CugArdrs.js';
|
|
3
3
|
import '@tanstack/store';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Declares a reusable store builder.
|
|
7
|
+
*
|
|
8
|
+
* The returned builder is immutable: each call to {@link StoreBuilder.extend}
|
|
9
|
+
* returns a new builder, and each call to {@link StoreBuilder.create} returns a
|
|
10
|
+
* fresh runtime store instance. If neither a declaration-time default nor a
|
|
11
|
+
* create-time override is provided, the runtime store starts uninitialized and
|
|
12
|
+
* must receive {@link Store.setInitialState} before reads or writes are valid.
|
|
13
|
+
*/
|
|
14
|
+
declare function createStore<TState>(): StoreBuilder<TState>;
|
|
5
15
|
declare function createStore<TState>(initialState: TState): StoreBuilder<TState>;
|
|
6
16
|
|
|
7
17
|
export { StoreBuilder, createStore };
|
package/dist/core/index.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { createStoreInstance } from '../chunk-
|
|
1
|
+
import { createStoreInstance } from '../chunk-C5U3Q6O3.js';
|
|
2
2
|
import { registerStoreBuilder } from '../chunk-PCSRXZL4.js';
|
|
3
3
|
|
|
4
4
|
// src/core/create-store.ts
|
|
5
5
|
function createStore(initialState) {
|
|
6
|
+
const hasDeclaredInitialState = arguments.length > 0;
|
|
6
7
|
const createBuilder = (plugins) => {
|
|
7
8
|
const builder = {
|
|
8
|
-
create() {
|
|
9
|
-
const
|
|
9
|
+
create(overrideInitialState) {
|
|
10
|
+
const hasOverrideInitialState = arguments.length > 0;
|
|
11
|
+
const controller = createStoreInstance({
|
|
12
|
+
initialState: hasOverrideInitialState ? overrideInitialState : initialState,
|
|
13
|
+
readyOnCreate: hasOverrideInitialState || hasDeclaredInitialState
|
|
14
|
+
});
|
|
10
15
|
for (const plugin of plugins) {
|
|
11
16
|
const surface = plugin({
|
|
12
17
|
store: controller.store,
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/create-store.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"sources":["../../src/core/create-store.ts"],"names":[],"mappings":";;;;AAiBO,SAAS,YACd,YAAA,EACsB;AACtB,EAAA,MAAM,uBAAA,GAA0B,UAAU,MAAA,GAAS,CAAA;AAGnD,EAAA,MAAM,aAAA,GAAgB,CACpB,OAAA,KACmC;AACnC,IAAA,MAAM,OAAA,GAA0C;AAAA,MAC9C,OAAO,oBAAA,EAA+B;AACpC,QAAA,MAAM,uBAAA,GAA0B,UAAU,MAAA,GAAS,CAAA;AACnD,QAAA,MAAM,aAAa,mBAAA,CAAoB;AAAA,UACrC,YAAA,EAAc,0BACV,oBAAA,GACA,YAAA;AAAA,UACJ,eAAe,uBAAA,IAA2B;AAAA,SAC3C,CAAA;AAED,QAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,UAAA,MAAM,UAAU,MAAA,CAAO;AAAA,YACrB,OAAO,UAAA,CAAW,KAAA;AAAA,YAClB,SAAA,EAAW,CAAC,OAAA,KAAY,UAAA,CAAW,UAAU,OAAO;AAAA,WACrD,CAAA;AAED,UAAA,UAAA,CAAW,cAAc,OAAO,CAAA;AAAA,QAClC;AAEA,QAAA,MAAM,QAAQ,UAAA,CAAW,KAAA;AACzB,QAAA,oBAAA,CAAqB,OAAO,OAAO,CAAA;AAEnC,QAAA,OAAO,KAAA;AAAA,MACT,CAAA;AAAA,MACA,OACE,MAAA,EACA;AACA,QAAA,OAAO,aAAA,CAAuC,CAAC,GAAG,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,MACpE;AAAA,KACF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AAEA,EAAA,OAAO,aAAA,CAAkB,EAAE,CAAA;AAC7B","file":"index.js","sourcesContent":["\nimport { createStoreInstance } from './store-instance'\nimport { registerStoreBuilder } from './builder-registry'\n\nimport type { Store, StoreBuilder, StorePlugin } from './types'\n\n/**\n * Declares a reusable store builder.\n *\n * The returned builder is immutable: each call to {@link StoreBuilder.extend}\n * returns a new builder, and each call to {@link StoreBuilder.create} returns a\n * fresh runtime store instance. If neither a declaration-time default nor a\n * create-time override is provided, the runtime store starts uninitialized and\n * must receive {@link Store.setInitialState} before reads or writes are valid.\n */\nexport function createStore<TState>(): StoreBuilder<TState>\nexport function createStore<TState>(initialState: TState): StoreBuilder<TState>\nexport function createStore<TState>(\n initialState?: TState,\n): StoreBuilder<TState> {\n const hasDeclaredInitialState = arguments.length > 0\n type PluginList = ReadonlyArray<StorePlugin<TState, any, any>>\n\n const createBuilder = <TPlugins>(\n plugins: PluginList,\n ): StoreBuilder<TState, TPlugins> => {\n const builder: StoreBuilder<TState, TPlugins> = {\n create(overrideInitialState?: TState) {\n const hasOverrideInitialState = arguments.length > 0\n const controller = createStoreInstance({\n initialState: hasOverrideInitialState\n ? overrideInitialState\n : initialState,\n readyOnCreate: hasOverrideInitialState || hasDeclaredInitialState,\n })\n\n for (const plugin of plugins) {\n const surface = plugin({\n store: controller.store as Store<TState, any>,\n onDispose: (cleanup) => controller.onDispose(cleanup),\n })\n\n controller.attachSurface(surface)\n }\n\n const store = controller.store as Store<TState, TPlugins>\n registerStoreBuilder(store, builder)\n\n return store\n },\n extend<TNextPlugins>(\n plugin: StorePlugin<TState, TPlugins, TNextPlugins>,\n ) {\n return createBuilder<TPlugins & TNextPlugins>([...plugins, plugin])\n },\n }\n\n return builder\n }\n\n return createBuilder<{}>([])\n}\n"]}
|
|
@@ -1,33 +1,72 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { f as StorePlugin, a as Store } from '../../types-CugArdrs.js';
|
|
2
2
|
import '@tanstack/store';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
type
|
|
8
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Runtime store surface attached by the actions plugin.
|
|
6
|
+
*/
|
|
7
|
+
type ActionsStoreSurface<TState, TActions> = {
|
|
8
|
+
/**
|
|
9
|
+
* Bound actions for the current runtime store instance.
|
|
10
|
+
*/
|
|
9
11
|
readonly actions: BoundActions<TState, TActions>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Plugin type returned by {@link actions}.
|
|
15
|
+
*/
|
|
16
|
+
type ActionsPlugin<TState, TActions> = StorePlugin<TState, any, ActionsStoreSurface<TState, TActions>>;
|
|
17
|
+
/**
|
|
18
|
+
* Helpers exposed to action builders and reusable action definitions.
|
|
19
|
+
*/
|
|
12
20
|
type ActionsBuilderHelpers<TState> = {
|
|
21
|
+
/**
|
|
22
|
+
* Reads the current runtime store state.
|
|
23
|
+
*/
|
|
13
24
|
getState: () => TState;
|
|
25
|
+
/**
|
|
26
|
+
* Updates the runtime store state.
|
|
27
|
+
*/
|
|
14
28
|
setState: (updater: (prev: TState) => TState) => void;
|
|
15
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Callback shape used by {@link createAction}.
|
|
32
|
+
*/
|
|
16
33
|
type ActionCallback<TState, TArgs extends unknown[] = [], TReturn = void> = (helpers: ActionsBuilderHelpers<TState>, ...args: TArgs) => TReturn;
|
|
34
|
+
/**
|
|
35
|
+
* Reusable action definition returned by {@link createAction}.
|
|
36
|
+
*/
|
|
17
37
|
type ActionDefinition<TState, TArgs extends unknown[] = [], TReturn = void> = {
|
|
18
|
-
readonly
|
|
19
|
-
readonly [bindActionDefinition]: (helpers: ActionsBuilderHelpers<TState>) => (...args: TArgs) => TReturn;
|
|
38
|
+
readonly __actionDefinition: (helpers: ActionsBuilderHelpers<TState>, ...args: TArgs) => TReturn;
|
|
20
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Resolves reusable action definitions to callable functions while preserving
|
|
42
|
+
* inline actions as-is.
|
|
43
|
+
*/
|
|
21
44
|
type BoundActions<TState, TActions> = {
|
|
22
45
|
[TKey in keyof TActions]: TActions[TKey] extends ActionDefinition<TState, infer TArgs, infer TReturn> ? (...args: TArgs) => TReturn : TActions[TKey];
|
|
23
46
|
};
|
|
24
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Declares a reusable typed action definition.
|
|
50
|
+
*
|
|
51
|
+
* The returned definition is inert until the actions plugin binds it to a
|
|
52
|
+
* runtime store during store creation.
|
|
53
|
+
*/
|
|
25
54
|
declare function createAction<TState, TArgs extends unknown[] = [], TReturn = void>(callback: ActionCallback<TState, TArgs, TReturn>): ActionDefinition<TState, TArgs, TReturn>;
|
|
55
|
+
/**
|
|
56
|
+
* Attaches typed actions to `store.actions`.
|
|
57
|
+
*
|
|
58
|
+
* Inline action functions and reusable definitions created with
|
|
59
|
+
* {@link createAction} can be mixed in the same surface. All actions receive
|
|
60
|
+
* `getState` and `setState` helpers bound to the runtime store instance.
|
|
61
|
+
*/
|
|
26
62
|
declare function actions<TState, TActions>(builder: (helpers: {
|
|
27
63
|
getState: () => TState;
|
|
28
64
|
setState: (updater: (prev: TState) => TState) => void;
|
|
29
65
|
}) => TActions): ActionsPlugin<TState, TActions>;
|
|
30
66
|
|
|
31
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Returns the typed `store.actions` surface attached by the actions plugin.
|
|
69
|
+
*/
|
|
70
|
+
declare function useActions<TState, TActions>(store: Store<TState, ActionsStoreSurface<TState, TActions>>): ActionsStoreSurface<TState, TActions>['actions'];
|
|
32
71
|
|
|
33
|
-
export {
|
|
72
|
+
export { actions, createAction, useActions };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/plugins/actions/types.ts
|
|
2
|
-
var actionsBrand = /* @__PURE__ */ Symbol("lunarhue.store.actions");
|
|
3
2
|
var actionDefinitionBrand = /* @__PURE__ */ Symbol("lunarhue.store.actionDefinition");
|
|
4
3
|
var bindActionDefinition = /* @__PURE__ */ Symbol("lunarhue.store.bindActionDefinition");
|
|
5
4
|
|
|
@@ -30,7 +29,6 @@ function actions(builder) {
|
|
|
30
29
|
setState: (updater) => store.setState(updater)
|
|
31
30
|
};
|
|
32
31
|
return {
|
|
33
|
-
[actionsBrand]: true,
|
|
34
32
|
actions: bindActions(builder(helpers), helpers)
|
|
35
33
|
};
|
|
36
34
|
};
|
|
@@ -41,6 +39,6 @@ function useActions(store) {
|
|
|
41
39
|
return store.actions;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
export {
|
|
42
|
+
export { actions, createAction, useActions };
|
|
45
43
|
//# sourceMappingURL=index.js.map
|
|
46
44
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/actions/types.ts","../../../src/plugins/actions/plugin.ts","../../../src/plugins/actions/react.tsx"],"names":[],"mappings":";AAEO,IAAM,
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/actions/types.ts","../../../src/plugins/actions/plugin.ts","../../../src/plugins/actions/react.tsx"],"names":[],"mappings":";AAEO,IAAM,qBAAA,0BAA+B,iCAAiC,CAAA;AACtE,IAAM,oBAAA,0BAA8B,qCAAqC,CAAA;;;ACWhF,SAAS,mBACP,KAAA,EAC+D;AAC/D,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,UAAU,IAAA,IACV,qBAAA,IAAyB,SACzB,oBAAA,IAAwB,KAAA;AAE5B;AAEA,SAAS,WAAA,CACP,iBACA,OAAA,EACgC;AAChC,EAAA,MAAM,eAAe,EAAC;AAEtB,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,OAAA,CAAQ,eAAyB,CAAA,EAExD;AACD,IAAA,MAAM,MAAA,GAAS,gBAAgB,GAAG,CAAA;AAElC,IAAA,YAAA,CAAa,GAAG,IACd,kBAAA,CAA2B,MAAM,IAC7B,MAAA,CAAO,oBAAoB,CAAA,CAAE,OAAO,CAAA,GACpC,MAAA;AAAA,EAER;AAEA,EAAA,OAAO,YAAA;AACT;AAQO,SAAS,aAKd,QAAA,EAC0C;AAC1C,EAAA,OAAO;AAAA,IACL,CAAC,qBAAqB,GAAG,IAAA;AAAA,IACzB,CAAC,oBAAoB,CAAA,CAAE,OAAA,EAAS;AAC9B,MAAA,OAAO,CAAA,GAAI,IAAA,KAAS,QAAA,CAAS,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,IAC/C;AAAA,GACF;AACF;AASO,SAAS,QACd,OAAA,EAIiC;AACjC,EAAA,OAAO,CAAC,EAAE,KAAA,EAAM,KAAM;AACpB,IAAA,MAAM,OAAA,GAAU;AAAA,MACd,QAAA,EAAU,MAAM,KAAA,CAAM,GAAA,EAAI;AAAA,MAC1B,QAAA,EAAU,CAAC,OAAA,KAAsC,KAAA,CAAM,SAAS,OAAO;AAAA,KACzE;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,WAAA,CAAY,OAAA,CAAQ,OAAO,GAAG,OAAO;AAAA,KAChD;AAAA,EACF,CAAA;AACF;;;ACnFO,SAAS,WACd,KAAA,EACkD;AAClD,EAAA,OAAO,KAAA,CAAM,OAAA;AACf","file":"index.js","sourcesContent":["import type { StorePlugin } from '../../core'\n\nexport const actionDefinitionBrand = Symbol('lunarhue.store.actionDefinition')\nexport const bindActionDefinition = Symbol('lunarhue.store.bindActionDefinition')\n\n/**\n * Runtime store surface attached by the actions plugin.\n */\nexport type ActionsStoreSurface<TState, TActions> = {\n /**\n * Bound actions for the current runtime store instance.\n */\n readonly actions: BoundActions<TState, TActions>\n}\n\n/**\n * Plugin type returned by {@link actions}.\n */\nexport type ActionsPlugin<TState, TActions> = StorePlugin<\n TState,\n any,\n ActionsStoreSurface<TState, TActions>\n>\n\n/**\n * Helpers exposed to action builders and reusable action definitions.\n */\nexport type ActionsBuilderHelpers<TState> = {\n /**\n * Reads the current runtime store state.\n */\n getState: () => TState\n /**\n * Updates the runtime store state.\n */\n setState: (updater: (prev: TState) => TState) => void\n}\n\n/**\n * Callback shape used by {@link createAction}.\n */\nexport type ActionCallback<\n TState,\n TArgs extends unknown[] = [],\n TReturn = void,\n> = (\n helpers: ActionsBuilderHelpers<TState>,\n ...args: TArgs\n) => TReturn\n\n/**\n * Reusable action definition returned by {@link createAction}.\n */\nexport type ActionDefinition<\n TState,\n TArgs extends unknown[] = [],\n TReturn = void,\n> = {\n readonly __actionDefinition: (\n helpers: ActionsBuilderHelpers<TState>,\n ...args: TArgs\n ) => TReturn\n}\n\n/**\n * Resolves reusable action definitions to callable functions while preserving\n * inline actions as-is.\n */\nexport type BoundActions<TState, TActions> = {\n [TKey in keyof TActions]: TActions[TKey] extends ActionDefinition<\n TState,\n infer TArgs,\n infer TReturn\n >\n ? (...args: TArgs) => TReturn\n : TActions[TKey]\n}\n\nexport type InternalActionDefinition<\n TState,\n TArgs extends unknown[] = [],\n TReturn = void,\n> = ActionDefinition<TState, TArgs, TReturn> & {\n readonly [actionDefinitionBrand]: true\n readonly [bindActionDefinition]: (\n helpers: ActionsBuilderHelpers<TState>,\n ) => (...args: TArgs) => TReturn\n}\n","import {\n actionDefinitionBrand,\n bindActionDefinition,\n} from './types'\n\nimport type {\n ActionCallback,\n ActionDefinition,\n ActionsBuilderHelpers,\n ActionsPlugin,\n BoundActions,\n InternalActionDefinition,\n} from './types'\n\nfunction isActionDefinition<TState>(\n value: unknown,\n): value is InternalActionDefinition<TState, unknown[], unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n actionDefinitionBrand in value &&\n bindActionDefinition in value\n )\n}\n\nfunction bindActions<TState, TActions>(\n declaredActions: TActions,\n helpers: ActionsBuilderHelpers<TState>,\n): BoundActions<TState, TActions> {\n const boundActions = {} as BoundActions<TState, TActions>\n\n for (const key of Reflect.ownKeys(declaredActions as object) as Array<\n keyof TActions\n >) {\n const action = declaredActions[key]\n\n boundActions[key] = (\n isActionDefinition<TState>(action)\n ? action[bindActionDefinition](helpers)\n : action\n ) as BoundActions<TState, TActions>[typeof key]\n }\n\n return boundActions\n}\n\n/**\n * Declares a reusable typed action definition.\n *\n * The returned definition is inert until the actions plugin binds it to a\n * runtime store during store creation.\n */\nexport function createAction<\n TState,\n TArgs extends unknown[] = [],\n TReturn = void,\n>(\n callback: ActionCallback<TState, TArgs, TReturn>,\n): ActionDefinition<TState, TArgs, TReturn> {\n return {\n [actionDefinitionBrand]: true,\n [bindActionDefinition](helpers) {\n return (...args) => callback(helpers, ...args)\n },\n } as InternalActionDefinition<TState, TArgs, TReturn>\n}\n\n/**\n * Attaches typed actions to `store.actions`.\n *\n * Inline action functions and reusable definitions created with\n * {@link createAction} can be mixed in the same surface. All actions receive\n * `getState` and `setState` helpers bound to the runtime store instance.\n */\nexport function actions<TState, TActions>(\n builder: (helpers: {\n getState: () => TState\n setState: (updater: (prev: TState) => TState) => void\n }) => TActions,\n): ActionsPlugin<TState, TActions> {\n return ({ store }) => {\n const helpers = {\n getState: () => store.get(),\n setState: (updater: (prev: TState) => TState) => store.setState(updater),\n }\n\n return {\n actions: bindActions(builder(helpers), helpers),\n }\n }\n}\n","import type { Store } from '../../core'\n\nimport type { ActionsStoreSurface } from './types'\n\n/**\n * Returns the typed `store.actions` surface attached by the actions plugin.\n */\nexport function useActions<TState, TActions>(\n store: Store<TState, ActionsStoreSurface<TState, TActions>>,\n): ActionsStoreSurface<TState, TActions>['actions'] {\n return store.actions\n}\n"]}
|