valtio-define 0.4.0 → 1.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.
package/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
  [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
5
  [![bundle][bundle-src]][bundle-href]
6
6
  [![JSDocs][jsdocs-src]][jsdocs-href]
7
+ [![coverage][coverage-src]][coverage-href]
7
8
  [![License][license-src]][license-href]
8
9
 
9
10
  ⚡ Quickly create a fully functional and robust Valtio factory
@@ -76,49 +77,25 @@ function Counter() {
76
77
  }
77
78
  ```
78
79
 
79
- ### Async Actions with Status
80
+ ### Persistence
80
81
 
81
- ```tsx
82
- import { defineStore, useStatus, useStore } from 'valtio-define'
82
+ The persistence plugin allows you to persist store state to storage (e.g., localStorage).
83
83
 
84
- const store = defineStore({
85
- state: () => ({ data: null }),
86
- actions: {
87
- async fetchData() {
88
- const response = await fetch('/api/data')
89
- this.data = await response.json()
90
- },
91
- },
92
- })
84
+ First, register the persistent plugin:
93
85
 
94
- function DataComponent() {
95
- const state = useStore(store)
96
- const status = useStatus(store)
86
+ ```tsx
87
+ import valtio from 'valtio-define'
88
+ import { persistent } from 'valtio-define/plugins'
97
89
 
98
- return (
99
- <div>
100
- {status.loading && <div> Store all actions are loading...</div>}
101
- {status.finished && <div> Store all actions are finished...</div>}
102
- {status.error && <div> Store all actions are error...</div>}
103
-
104
- {status.fetchData.finished && <div> Data fetched successfully...</div>}
105
- {status.fetchData.error && (
106
- <div>
107
- {' '}
108
- Error fetching data:
109
- {status.fetchData.error.message}
110
- </div>
111
- )}
112
- {state.data && <div>{JSON.stringify(state.data)}</div>}
113
- <button onClick={store.fetchData}>Fetch Data</button>
114
- </div>
115
- )
116
- }
90
+ // Register the persistent plugin globally
91
+ valtio.use(persistent())
117
92
  ```
118
93
 
119
- ### Persistence
94
+ Then use it in your store:
120
95
 
121
96
  ```tsx
97
+ import { defineStore } from 'valtio-define'
98
+
122
99
  const store = defineStore({
123
100
  state: () => ({ count: 0 }),
124
101
  actions: {
@@ -126,11 +103,22 @@ const store = defineStore({
126
103
  this.count++
127
104
  },
128
105
  },
129
- persist: true // or { key: 'my-store', storage: localStorage, paths: ['count'] }
106
+ persist: {
107
+ key: 'my-store',
108
+ storage: localStorage,
109
+ paths: ['count'], // Only persist 'count', or omit to persist all state
110
+ },
130
111
  })
131
112
  ```
132
113
 
133
- If the persist is a boolean value, it will use `structure-id` to generate a unique key for the store.
114
+ If `persist` is `true`, it will use `structure-id` to generate a unique key for the store automatically.
115
+
116
+ ```tsx
117
+ const store = defineStore({
118
+ state: () => ({ count: 0 }),
119
+ persist: true, // Auto-generates key using structure-id
120
+ })
121
+ ```
134
122
 
135
123
  ### Subscribe to Changes
136
124
 
@@ -149,9 +137,9 @@ const unsubscribe = store.$subscribe((state) => {
149
137
  console.log('State changed:', state)
150
138
  })
151
139
 
152
- // Subscribe to status changes
153
- const unsubscribeStatus = store.$subscribe.status((status) => {
154
- console.log('Status changed:', status)
140
+ // Subscribe to specific key changes
141
+ const unsubscribeKey = store.$subscribeKey('count', (value) => {
142
+ console.log('Count changed:', value)
155
143
  })
156
144
  ```
157
145
 
@@ -173,15 +161,9 @@ store.$patch((state) => {
173
161
  function App() {
174
162
  return (
175
163
  <div>
176
- {store.$signal(state => (
177
- <div>
178
- Count:
179
- {state.count}
180
- </div>
181
- ))}
182
- {store.$signal.status(status => (
183
- status.loading && <div>Loading...</div>
184
- ))}
164
+ Count:
165
+ {' '}
166
+ {store.$signal(state => state.count)}
185
167
  </div>
186
168
  )
187
169
  }
@@ -197,7 +179,7 @@ Creates a store with state, actions, and getters.
197
179
  - `store.state`: Initial state object or factory function
198
180
  - `store.actions`: Object containing action methods
199
181
  - `store.getters`: Object containing getter methods
200
- - `store.persist`: Persistence configuration (boolean or object)
182
+ - `store.persist`: Persistence plugin configuration (boolean or object) - see [Persistence Plugin](#persistence-plugin)
201
183
 
202
184
  **Returns:** Store instance with reactive state and actions
203
185
 
@@ -210,26 +192,68 @@ React hook that returns a snapshot of the store state.
210
192
 
211
193
  **Returns:** Snapshot of the store state
212
194
 
213
- ### `useStatus(store)`
195
+ ### Plugins
214
196
 
215
- React hook that returns the status of all actions.
197
+ Plugins allow you to extend store functionality. You can use plugins globally or per-store.
216
198
 
217
- **Parameters:**
218
- - `store`: Store instance created by `defineStore`
199
+ #### Global Plugin Registration
219
200
 
220
- **Returns:** Status object with loading, finished, and error states
201
+ ```tsx
202
+ import { use } from 'valtio-define'
203
+ import { persistent } from 'valtio-define/plugins'
221
204
 
222
- ### `proxyWithPersistent(initialObject, options?)`
205
+ // Register plugin globally - applies to all stores
206
+ use(persistent())
207
+ ```
223
208
 
224
- Creates a persistent proxy state.
209
+ #### Per-Store Plugin Registration
225
210
 
226
- **Parameters:**
227
- - `initialObject`: Initial state object
228
- - `options.key`: Storage key (auto-generated if not provided)
229
- - `options.storage`: Storage instance (defaults to localStorage)
230
- - `options.paths`: Array of paths to persist (defaults to all)
211
+ ```tsx
212
+ import { defineStore } from 'valtio-define'
213
+ import { persistent } from 'valtio-define/plugins'
214
+
215
+ const store = defineStore({
216
+ state: () => ({ count: 0 }),
217
+ })
218
+
219
+ // Register plugin for this specific store
220
+ store.use(persistent())
221
+ ```
222
+
223
+ #### Creating Custom Plugins
224
+
225
+ ```tsx
226
+ import type { Plugin } from 'valtio-define'
227
+
228
+ function myPlugin() {
229
+ ({ store, options }: PluginContext) => {
230
+ // Access store methods
231
+ store.$subscribe((state) => {
232
+ console.log('State changed:', state)
233
+ })
234
+
235
+ // Access store options
236
+ if (options.someOption) {
237
+ // Do something
238
+ }
239
+ }
240
+ }
241
+
242
+ declare module 'valtio-define/types' {
243
+ export interface StoreDefine<S extends object, A extends ActionsTree, G extends Getters<any>> {
244
+ myPlugin?: {
245
+ someOption?: boolean
246
+ }
247
+ }
248
+ }
249
+
250
+ // Use the plugin
251
+ use(myPlugin)
252
+ ```
231
253
 
232
- **Returns:** Persistent proxy state
254
+ **Plugin Context:**
255
+ - `context.store`: The store instance with all methods (`$state`, `$patch`, `$subscribe`, etc.)
256
+ - `context.options`: The original store definition options
233
257
 
234
258
  ## License
235
259
 
@@ -247,3 +271,5 @@ Creates a persistent proxy state.
247
271
  [license-href]: https://github.com/hairyf/valtio-define/blob/main/LICENSE
248
272
  [jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
249
273
  [jsdocs-href]: https://www.jsdocs.io/package/valtio-define
274
+ [coverage-src]: https://codecov.io/gh/hairyf/valtio-define/graph/badge.svg?token=PG5YIEEEHJ
275
+ [coverage-href]: https://codecov.io/gh/hairyf/valtio-define
@@ -0,0 +1,23 @@
1
+ import { s as Plugin } from "./index-BxQlAvn6.mjs";
2
+ import { Awaitable } from "@hairy/utils";
3
+
4
+ //#region src/plugins/persistent/index.d.ts
5
+ declare function persistent(): Plugin;
6
+ type DeepKeys<T> = T extends object ? { [K in keyof T & string]: T[K] extends object ? K | `${K}.${DeepKeys<T[K]>}` : K }[keyof T & string] : never;
7
+ interface Storage {
8
+ getItem: (key: string) => Awaitable<any>;
9
+ setItem: (key: string, value: any) => Awaitable<void>;
10
+ [key: string]: any;
11
+ }
12
+ interface PersistentOptions<S extends object = Record<string, unknown>> {
13
+ key?: string;
14
+ storage?: Storage;
15
+ paths?: DeepKeys<S>[];
16
+ }
17
+ declare module 'valtio-define/types' {
18
+ interface StoreDefine<S extends object, A extends ActionsTree, G extends Getters<any>> {
19
+ persist?: PersistentOptions<S>;
20
+ }
21
+ }
22
+ //#endregion
23
+ export { persistent as i, PersistentOptions as n, Storage as r, DeepKeys as t };
@@ -0,0 +1,46 @@
1
+ import { ReactElement } from "react";
2
+
3
+ //#region src/types/index.d.ts
4
+ type Actions<S = any> = Record<string, (this: S, ...args: any) => any>;
5
+ type ActionsTree = Record<string, (...args: any[]) => any>;
6
+ type Getters<S = any> = Record<string, (this: S) => any>;
7
+ type ActionsOmitThisParameter<A extends Actions<any>> = { [K in keyof A]: (...args: Parameters<A[K]>) => ReturnType<A[K]> };
8
+ type GettersReturnType<G extends Getters<any>> = { [K in keyof G]: ReturnType<G[K]> };
9
+ interface StoreDefine<S extends object, A extends ActionsTree, G extends Getters<any>> {
10
+ state: (() => S) | S;
11
+ actions?: A & ThisType<A & S & GettersReturnType<G>>;
12
+ getters?: G & ThisType<S & GettersReturnType<G>>;
13
+ }
14
+ interface Signal<S, G extends Getters<S>> {
15
+ <T>(fn: (state: S & GettersReturnType<G>) => T): ReactElement;
16
+ }
17
+ type Path = (string | symbol)[];
18
+ type Op = [op: 'set', path: Path, value: unknown, prevValue: unknown] | [op: 'delete', path: Path, prevValue: unknown];
19
+ interface Subscribe<S, G extends Getters<S>> {
20
+ (listener: (state: S & GettersReturnType<G>, opts: Op) => void): () => void;
21
+ }
22
+ interface SubscribeKey<S, G extends Getters<S>> {
23
+ <T extends keyof S | keyof G>(key: T, listener: (state: (S & GettersReturnType<G>)[T]) => void): () => void;
24
+ }
25
+ interface Patch<S, G extends Getters<S>> {
26
+ (patch: Partial<S> | ((state: S & GettersReturnType<G>) => void)): void;
27
+ }
28
+ type Store<S, A extends Actions<S>, G extends Getters<S>> = {
29
+ $subscribe: Subscribe<S, G>;
30
+ $subscribeKey: SubscribeKey<S, G>;
31
+ $patch: Patch<S, G>;
32
+ $state: S & GettersReturnType<G> & ActionsOmitThisParameter<A>;
33
+ $actions: ActionsOmitThisParameter<A>;
34
+ $getters: GettersReturnType<G>;
35
+ use: (plugin: Plugin) => void;
36
+ $signal: Signal<S, G>;
37
+ } & S & GettersReturnType<G> & ActionsOmitThisParameter<A>;
38
+ interface PluginContext<S extends object = Record<string, unknown>> {
39
+ store: Store<S, Actions<S>, Getters<S>>;
40
+ options: StoreDefine<S, ActionsTree, Getters<S>>;
41
+ }
42
+ interface Plugin {
43
+ <S extends object = Record<string, unknown>>(context: PluginContext<S>): void;
44
+ }
45
+ //#endregion
46
+ export { GettersReturnType as a, PluginContext as c, StoreDefine as d, Subscribe as f, Getters as i, Signal as l, ActionsOmitThisParameter as n, Patch as o, SubscribeKey as p, ActionsTree as r, Plugin as s, Actions as t, Store as u };
package/dist/index.d.mts CHANGED
@@ -1,53 +1,11 @@
1
+ import { a as GettersReturnType, d as StoreDefine, i as Getters, r as ActionsTree, s as Plugin, t as Actions, u as Store } from "./index-BxQlAvn6.mjs";
1
2
  import { Snapshot } from "valtio";
2
3
 
3
- //#region src/types/index.d.ts
4
- type Actions<S> = Record<string, (this: S, ...args: any) => any>;
5
- type Getters<S> = Record<string, (this: S) => any>;
6
- type ActionsOmitThisParameter<A extends Actions<any>> = { [K in keyof A]: (...args: Parameters<A[K]>) => ReturnType<A[K]> };
7
- interface Status {
8
- finished: boolean;
9
- loading: boolean;
10
- error?: Error;
11
- }
12
- type ActionsStatus<A extends Actions<any>> = Status & { [K in keyof A]: Status };
13
- type GettersReturnType<G extends Getters<any>> = { [K in keyof G]: ReturnType<G[K]> };
14
- interface StoreDefine<S extends object, A extends Actions<S>, G extends Getters<S>> {
15
- state: (() => S) | S;
16
- actions?: A;
17
- getters?: G;
18
- }
19
- interface StoreOptions<S extends object = Record<string, unknown>> {
20
- persist?: boolean | PersistentOptions<S>;
21
- }
22
- interface StoreSignal<S, A extends Actions<S>, G extends Getters<S>> {
23
- <T>(fn: (state: S & GettersReturnType<G>) => T): T;
24
- status: <T>(fn: (status: ActionsStatus<A>) => T) => T;
25
- }
26
- interface StoreSubscribe<S, A extends Actions<S>, G extends Getters<S>> {
27
- (listener: (state: S & GettersReturnType<G>) => void): () => void;
28
- status: (listener: (status: ActionsStatus<A>) => void) => () => void;
29
- key: <K$1 extends keyof S | keyof G>(key: K$1, listener: (state: (S & GettersReturnType<G>)[K$1]) => void) => () => void;
30
- }
31
- interface StorePatch<S, G extends Getters<S>> {
32
- (patch: Partial<S> | ((state: S & GettersReturnType<G>) => void)): void;
33
- }
34
- type Store<S, A extends Actions<S>, G extends Getters<S>> = {
35
- $subscribe: StoreSubscribe<S, A, G>;
36
- $patch: StorePatch<S, G>;
37
- $state: S & GettersReturnType<G> & ActionsOmitThisParameter<A>;
38
- $actions: ActionsOmitThisParameter<A>;
39
- $getters: GettersReturnType<G>;
40
- $status: ActionsStatus<A>;
41
- $signal: StoreSignal<S, A, G>;
42
- } & ActionsOmitThisParameter<A>;
43
- interface PersistentOptions<S extends object = Record<string, unknown>> {
44
- key?: string;
45
- storage?: Partial<Storage> & Pick<Storage, 'getItem' | 'setItem'>;
46
- paths?: (keyof S)[];
47
- initial?: (initialState: S) => any | Promise<any>;
48
- }
4
+ //#region src/plugin.d.ts
5
+ declare const plugins: Plugin[];
6
+ declare function use(plugin: Plugin): void;
49
7
  //#endregion
50
- //#region src/define-store.d.ts
8
+ //#region src/define.d.ts
51
9
  /**
52
10
  * @description Define a store
53
11
  * @example
@@ -76,15 +34,14 @@ interface PersistentOptions<S extends object = Record<string, unknown>> {
76
34
  *
77
35
  * ```
78
36
  */
79
- declare function defineStore<S extends object, A extends Actions<S>, G extends Getters<S>>(store: StoreDefine<S, A, G> & StoreOptions<S>): Store<S, A, G>;
37
+ declare function defineStore<S extends object, A extends ActionsTree, G extends Getters<S>>(define: StoreDefine<S, A, G>): Store<S, A & Actions<S>, G>;
80
38
  //#endregion
81
- //#region src/persistent.d.ts
82
- declare function proxyWithPersistent<T extends object>(initialObject: T, options?: PersistentOptions): T;
83
- //#endregion
84
- //#region src/use-status.d.ts
85
- declare function useStatus<S extends object, A extends Actions<S>, G extends Getters<S>>(store: Store<S, A, G>): Snapshot<ActionsStatus<A>>;
86
- //#endregion
87
- //#region src/use-store.d.ts
39
+ //#region src/use.d.ts
88
40
  declare function useStore<S extends object, A extends Actions<S>, G extends Getters<S>>(store: Store<S, A, G>): Snapshot<S & GettersReturnType<G> & A>;
89
41
  //#endregion
90
- export { defineStore, proxyWithPersistent, useStatus, useStore };
42
+ //#region src/index.d.ts
43
+ declare const _default: {
44
+ use: typeof use;
45
+ };
46
+ //#endregion
47
+ export { _default as default, defineStore, plugins, use, useStore };
package/dist/index.mjs CHANGED
@@ -1,66 +1,15 @@
1
1
  import { createElement } from "react";
2
2
  import { proxy, ref, subscribe, useSnapshot } from "valtio";
3
3
  import { subscribeKey } from "valtio/utils";
4
- import { tryParseJson } from "@hairy/utils";
5
- import { generateStructureId } from "structure-id";
6
4
 
7
- //#region src/utils/index.ts
8
- function track(action, status) {
9
- let loadings = 0;
10
- const tracking = () => {
11
- loadings++ === 0 && (status.loading = true);
12
- };
13
- const done = () => {
14
- !--loadings && (status.loading = false);
15
- };
16
- const fulfilled = (value) => {
17
- status.finished = true;
18
- if (status.error) delete status.error;
19
- done();
20
- return value;
21
- };
22
- const rejected = (error) => {
23
- status.error = error;
24
- done();
25
- throw error;
26
- };
27
- return function(...args) {
28
- tracking();
29
- try {
30
- const value = action(...args);
31
- return value instanceof Promise ? value.then(fulfilled, rejected) : fulfilled(value);
32
- } catch (error) {
33
- rejected(error);
34
- }
35
- };
36
- }
37
- function get(obj, path) {
38
- return path.split(".").reduce((result, key) => result?.[key], obj);
39
- }
40
- function set(obj, path, value) {
41
- const keys = path.split(".");
42
- const lastKey = keys.pop();
43
- const target = keys.reduce((result, key) => result[key] ??= {}, obj);
44
- target[lastKey] = value;
5
+ //#region src/plugin.ts
6
+ const plugins = [];
7
+ function use(plugin) {
8
+ plugins.push(plugin);
45
9
  }
46
10
 
47
11
  //#endregion
48
- //#region src/persistent.ts
49
- function proxyWithPersistent(initialObject, options = {}) {
50
- options.key = options.key || generateStructureId(initialObject);
51
- const storage = options.storage || (typeof localStorage !== "undefined" ? localStorage : void 0);
52
- const state = proxy(tryParseJson(storage?.getItem(options.key)) || initialObject);
53
- subscribe(state, () => {
54
- const paths = options.paths || Object.keys(state);
55
- const statePaths = {};
56
- for (const key of paths) set(statePaths, key, get(state, key));
57
- storage?.setItem(options.key, JSON.stringify(statePaths));
58
- });
59
- return state;
60
- }
61
-
62
- //#endregion
63
- //#region src/define-store.ts
12
+ //#region src/define.ts
64
13
  /**
65
14
  * @description Define a store
66
15
  * @example
@@ -89,105 +38,83 @@ function proxyWithPersistent(initialObject, options = {}) {
89
38
  *
90
39
  * ```
91
40
  */
92
- function defineStore(store) {
93
- const state = typeof store.state === "function" ? store.state() : store.state;
94
- const getters = store.getters || {};
95
- const actions = store.actions || {};
96
- const status = {};
97
- status.finished = false;
98
- status.loading = false;
99
- status.error = void 0;
100
- const $status = proxy(status);
101
- const $state = store.persist ? proxyWithPersistent(state, store.persist === true ? {} : store.persist) : proxy(state);
41
+ function defineStore(define) {
42
+ const state = typeof define.state === "function" ? define.state() : define.state;
43
+ const getters = define.getters || {};
44
+ const actions = define.actions || {};
45
+ const $state = proxy(state);
102
46
  const $actions = {};
103
47
  const $getters = {};
104
- setupActions($state, actions, $actions, $status);
105
- setupGetters($state, getters, $getters);
106
- setupStatus($actions, $status);
48
+ const $plugins = [];
49
+ for (const key in actions) {
50
+ $actions[key] = ref(actions[key].bind($state));
51
+ $state[key] = $actions[key];
52
+ }
53
+ for (const key in getters) {
54
+ Object.defineProperty($state, key, {
55
+ get: () => getters[key].call($state),
56
+ enumerable: true
57
+ });
58
+ Object.defineProperty($getters, key, {
59
+ get: () => $state[key],
60
+ enumerable: true
61
+ });
62
+ }
107
63
  function $subscribe(listener) {
108
- return subscribe($state, () => listener($state));
64
+ return subscribe($state, (opts) => listener($state, opts));
65
+ }
66
+ function $subscribeKey(key, listener) {
67
+ return subscribeKey($state, key, (value) => listener(value), true);
109
68
  }
110
- $subscribe.status = function(listener) {
111
- return subscribe($status, () => listener($status));
112
- };
113
- $subscribe.key = function(key, listener) {
114
- return subscribeKey($state, key, () => listener($state));
115
- };
116
69
  function $patch(patch) {
117
- if (typeof patch === "function") patch($state);
118
- else Object.assign($state, patch);
70
+ typeof patch === "function" ? patch($state) : Object.assign($state, patch);
119
71
  }
120
72
  function $signal(fn) {
121
73
  return createElement(() => fn(useSnapshot($state)));
122
74
  }
123
- $signal.status = function(fn) {
124
- return createElement(() => fn(useSnapshot($status)));
125
- };
126
- return {
75
+ function use$1(plugin) {
76
+ plugins.push(plugin);
77
+ }
78
+ const base = {
127
79
  $subscribe,
80
+ $subscribeKey,
128
81
  $patch,
129
82
  $state,
130
- $status,
131
83
  $actions,
132
84
  $getters,
133
85
  $signal,
134
- ...$actions
86
+ use: use$1
135
87
  };
136
- }
137
- function setupActions($state, actions, $actions, $status) {
138
- for (const key in actions) {
139
- $status[key] = {
140
- finished: false,
141
- loading: false,
142
- error: void 0
143
- };
144
- $actions[key] = track(actions[key].bind($state), $status[key]);
145
- Object.defineProperty($state, key, {
146
- get: () => ref($actions[key]),
147
- enumerable: false
148
- });
149
- }
150
- }
151
- function setupGetters($state, getters, $getters) {
152
- for (const key in getters) {
153
- Object.defineProperty($getters, key, {
154
- get: () => $state[key],
155
- enumerable: true
156
- });
157
- Object.defineProperty($state, key, {
158
- get: () => getters[key].call($state),
159
- enumerable: true
160
- });
161
- }
162
- }
163
- function setupStatus($actions, $status) {
164
- Object.defineProperty($status, "loading", {
165
- get: () => Object.keys($actions).some((key) => $status[key].loading),
166
- enumerable: true
167
- });
168
- Object.defineProperty($status, "finished", {
169
- get: () => Object.keys($actions).every((key) => $status[key].finished),
170
- enumerable: true
171
- });
172
- Object.defineProperty($status, "error", {
173
- get: () => {
174
- return $status[Object.keys($actions).find((key) => $status[key].error) || ""]?.error;
88
+ const store = new Proxy(base, {
89
+ get(target, prop) {
90
+ if (prop in $actions) return $actions[prop];
91
+ if (prop in target) return target[prop];
92
+ return $state[prop];
93
+ },
94
+ has(target, prop) {
95
+ return prop in target || prop in $actions || prop in $state;
175
96
  },
176
- enumerable: true
97
+ set(target, prop, value) {
98
+ prop in $state ? $state[prop] = value : target[prop] = value;
99
+ return true;
100
+ }
177
101
  });
102
+ for (const plugin of [...plugins, ...$plugins]) plugin({
103
+ store,
104
+ options: define
105
+ });
106
+ return store;
178
107
  }
179
108
 
180
109
  //#endregion
181
- //#region src/use-status.ts
182
- function useStatus(store) {
183
- return useSnapshot(store.$status);
184
- }
185
-
186
- //#endregion
187
- //#region src/use-store.ts
110
+ //#region src/use.ts
188
111
  function useStore(store) {
189
112
  return useSnapshot(store.$state);
190
113
  }
191
114
 
192
115
  //#endregion
193
- export { defineStore, proxyWithPersistent, useStatus, useStore };
116
+ //#region src/index.ts
117
+ var src_default = { use };
118
+
119
+ //#endregion
120
+ export { src_default as default, defineStore, plugins, use, useStore };
@@ -0,0 +1,32 @@
1
+ import { subscribe } from "valtio";
2
+ import { get, set } from "@hairy/utils";
3
+ import { destr } from "destr";
4
+ import { generateStructureId } from "structure-id";
5
+
6
+ //#region src/plugins/persistent/index.ts
7
+ function persistent() {
8
+ return (context) => {
9
+ const options = context.options.persist || {};
10
+ options.key = options.key || generateStructureId(context.store.$state);
11
+ const storage = options.storage || (typeof localStorage !== "undefined" ? localStorage : void 0);
12
+ const value = storage?.getItem(options.key);
13
+ let __watch = false;
14
+ if (value instanceof Promise) value.then(initialize);
15
+ else initialize(value);
16
+ function initialize(value$1) {
17
+ Object.assign(context.store.$state, destr(value$1));
18
+ __watch = true;
19
+ }
20
+ subscribe(context.store.$state, () => {
21
+ if (!__watch) return;
22
+ const paths = options.paths || Object.keys(context.store.$state);
23
+ const statePaths = {};
24
+ for (const key of paths) set(statePaths, key, get(context.store.$state, key));
25
+ const value$1 = JSON.stringify(statePaths);
26
+ storage?.setItem(options.key, value$1);
27
+ });
28
+ };
29
+ }
30
+
31
+ //#endregion
32
+ export { persistent as t };
@@ -0,0 +1,3 @@
1
+ import "../index-BxQlAvn6.mjs";
2
+ import { i as persistent, n as PersistentOptions, r as Storage, t as DeepKeys } from "../index-3Qs1mdbd.mjs";
3
+ export { DeepKeys, PersistentOptions, Storage, persistent };
@@ -0,0 +1,3 @@
1
+ import { t as persistent } from "../persistent-CQxMybmm.mjs";
2
+
3
+ export { persistent };
@@ -0,0 +1,3 @@
1
+ import "../../index-BxQlAvn6.mjs";
2
+ import { i as persistent, n as PersistentOptions, r as Storage, t as DeepKeys } from "../../index-3Qs1mdbd.mjs";
3
+ export { DeepKeys, PersistentOptions, Storage, persistent };
@@ -0,0 +1,3 @@
1
+ import { t as persistent } from "../../persistent-CQxMybmm.mjs";
2
+
3
+ export { persistent };
@@ -0,0 +1,2 @@
1
+ import { a as GettersReturnType, c as PluginContext, d as StoreDefine, f as Subscribe, i as Getters, l as Signal, n as ActionsOmitThisParameter, o as Patch, p as SubscribeKey, r as ActionsTree, s as Plugin, t as Actions, u as Store } from "../index-BxQlAvn6.mjs";
2
+ export { Actions, ActionsOmitThisParameter, ActionsTree, Getters, GettersReturnType, Patch, Plugin, PluginContext, Signal, Store, StoreDefine, Subscribe, SubscribeKey };
@@ -0,0 +1 @@
1
+ export { };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "valtio-define",
3
3
  "type": "module",
4
- "version": "0.4.0",
4
+ "version": "1.0.0",
5
5
  "description": "⚡quickly create a fully functional and robust Valtio factory",
6
6
  "author": "Hairyf <wwu710632@gmail.com>",
7
7
  "license": "MIT",
@@ -14,6 +14,9 @@
14
14
  "keywords": [],
15
15
  "sideEffects": false,
16
16
  "publishConfig": {
17
+ "./plugins": "./dist/plugins/index.mjs",
18
+ "./plugins/persistent": "./dist/plugins/persistent/index.mjs",
19
+ "./types": "./dist/types/index.mjs",
17
20
  "access": "public"
18
21
  },
19
22
  "exports": {
@@ -30,6 +33,7 @@
30
33
  },
31
34
  "dependencies": {
32
35
  "@hairy/utils": "^1.46.0",
36
+ "destr": "^2.0.5",
33
37
  "structure-id": "^1.2.9",
34
38
  "valtio": "^2.2.0"
35
39
  },
@@ -39,6 +43,7 @@
39
43
  "@antfu/utils": "^9.3.0",
40
44
  "@types/node": "^24.10.0",
41
45
  "@types/react": "^19.2.6",
46
+ "@types/react-dom": "^19.2.3",
42
47
  "@vitejs/plugin-react": "^5.1.1",
43
48
  "@vitest/browser-playwright": "^4.0.15",
44
49
  "@vitest/coverage-v8": "^4.0.15",
@@ -47,6 +52,7 @@
47
52
  "lint-staged": "^16.2.6",
48
53
  "playwright": "^1.57.0",
49
54
  "react": "^19.2.0",
55
+ "react-dom": "^19.2.0",
50
56
  "simple-git-hooks": "^2.13.1",
51
57
  "tinyexec": "^1.0.2",
52
58
  "tsdown": "^0.16.0",
@@ -72,6 +78,7 @@
72
78
  "release": "bumpp",
73
79
  "start": "tsx src/index.ts",
74
80
  "test": "vitest",
81
+ "coverage": "vitest run --coverage",
75
82
  "typecheck": "tsc"
76
83
  }
77
84
  }