{"_id":"@molecule/app-state","_rev":"3-dd937fa29be464b7fa8aa48c9e7f4443","name":"@molecule/app-state","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@molecule/app-state","version":"1.0.0","keywords":["molecule","state","store","state-management"],"license":"Apache-2.0","_id":"@molecule/app-state@1.0.0","maintainers":[{"name":"vialoh","email":"npm@vialoh.me"}],"homepage":"https://github.com/molecule-dev/molecule/tree/main/packages/app/core/state","bugs":{"url":"https://github.com/molecule-dev/molecule/issues"},"dist":{"shasum":"18a45388c02c4af510483fb067bdb2b82d8a40b3","tarball":"https://registry.npmjs.org/@molecule/app-state/-/app-state-1.0.0.tgz","fileCount":34,"integrity":"sha512-kmUEkBKQk7F7aKZ/FTvB0j3Hdy5yTgeFmAJSqQMexj0kqpXKkroqqunZDwQKuDXVqSANxKj/SHUPP0nhlSTkjg==","signatures":[{"sig":"MEQCIHGjyajgf/KSwAYmKtF+EI9wyKpKIdm1WRr4qPTzO8lYAiBZYlezMa8szKNFvtNb/0obDQB6CNu9PJfbPyW8pLXmOQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41099},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"92623e72a527ca467963169420f4cf07533e4699","scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"vialoh","email":"npm@vialoh.me"},"repository":{"url":"git+https://github.com/molecule-dev/molecule.git","type":"git","directory":"packages/app/core/state"},"_npmVersion":"11.12.1","description":"Client state management interface for molecule.dev","directories":{},"_nodeVersion":"25.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"4.1.10","typescript":"6.0.3","@types/node":"26.1.2","@molecule/app-bond":"1.0.0","@molecule/app-logger":"1.0.0"},"peerDependencies":{"@molecule/app-bond":"^1.0.0","@molecule/app-logger":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/app-state_1.0.0_1785796143951_0.6363237040301728","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@molecule/app-state","version":"1.0.1","keywords":["molecule","state","store","state-management"],"license":"Apache-2.0","_id":"@molecule/app-state@1.0.1","maintainers":[{"name":"vialoh","email":"npm@vialoh.me"}],"homepage":"https://github.com/molecule-dev/molecule/tree/main/packages/app/core/state","bugs":{"url":"https://github.com/molecule-dev/molecule/issues"},"dist":{"shasum":"d40f5d9c3e1060af94e000ab44fb2583b868f78d","tarball":"https://registry.npmjs.org/@molecule/app-state/-/app-state-1.0.1.tgz","fileCount":35,"integrity":"sha512-ZdYRwEpglagnNEYSpHsxLStPvdQCPvhPgLSr5tTpwDMUp9BGlNrn7e110RZYn9zBqVqRgwWVh46rLltwW75HOQ==","signatures":[{"sig":"MEYCIQDbCQ+IA7K1Kx7hiU/XhgR+IgE9x01ncWCZPFQjM6ZQOwIhAP303f8rKTowCna2iHahk8gMvCvAZaINypqIGuXo9ayE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@molecule%2fapp-state@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":50856},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"8621216fd4c8c9abe863e4e4f41efd2bc866fb09","scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"_npmUser":{"name":"vialoh","email":"npm@vialoh.me"},"repository":{"url":"git+https://github.com/molecule-dev/molecule.git","type":"git","directory":"packages/app/core/state"},"_npmVersion":"12.0.2","description":"Client state management interface for molecule.dev","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"4.1.10","typescript":"6.0.3","@types/node":"26.1.2","@molecule/app-bond":"1.0.1","@molecule/app-logger":"1.0.1"},"peerDependencies":{"@molecule/app-bond":"^1.0.1","@molecule/app-logger":"^1.0.1"},"_npmOperationalInternal":{"tmp":"tmp/app-state_1.0.1_1785828291262_0.7671435581506032","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"_id":"@molecule/app-state@1.0.2","bugs":{"url":"https://github.com/molecule-dev/molecule/issues"},"dist":{"shasum":"9ef84331b1440874a7566e6bfa614591a1888476","tarball":"https://registry.npmjs.org/@molecule/app-state/-/app-state-1.0.2.tgz","fileCount":35,"integrity":"sha512-H/ocLCOMqhkBQfXu9Xq4DMXjIZH3M2UgwAr0s7R5q6Bf7cjTMGCYjFfNWSPQl2HH8wfTSY16R+94QVv9tXzB2Q==","signatures":[{"sig":"MEQCIF3vqyssj2lhQpkQkThsWZGtd/TCXKwM0i/0aJ1itcAVAiBxn1neIqFKYkao68snOKWIYa85FN67hnw24EwkVWAp8w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCr3jPKIEN29dIf1ksW9T7wcVUd+ckHAanGfeTeEkU8dQIhAP6efNQ2qnYs7613s0yG1e92aIwrGJjvXtJ/BmMn8n9c"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@molecule%2fapp-state@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":50825},"main":"dist/index.js","name":"@molecule/app-state","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"80c23a410fe0952f0800a99180ecf221de9923e6","license":"Apache-2.0","scripts":{"test":"vitest run","build":"tsc","test:watch":"vitest"},"version":"1.0.2","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d559aaa1-e872-476d-8d49-59bb461d73b7"}},"homepage":"https://www.molecule.dev/packages/app-state","keywords":["molecule","state","store","state-management"],"repository":{"url":"git+https://github.com/molecule-dev/molecule.git","type":"git","directory":"packages/app/core/state"},"_npmVersion":"12.0.2","description":"Client state management interface for molecule.dev","directories":{},"maintainers":[{"name":"vialoh","email":"npm@vialoh.me"}],"_nodeVersion":"22.23.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"4.1.11","typescript":"6.0.3","@types/node":"26.1.2","@molecule/app-bond":"1.0.2","@molecule/app-logger":"1.0.2"},"peerDependencies":{"@molecule/app-bond":"^1.0.1","@molecule/app-logger":"^1.0.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/app-state_1.0.2_1789917173491_0.6782779171095998"}}},"time":{"created":"2026-08-03T22:29:03.820Z","modified":"2026-09-20T15:12:53.901Z","1.0.0":"2026-08-03T22:29:04.089Z","1.0.1":"2026-08-04T07:24:51.385Z","1.0.2":"2026-09-20T15:12:53.580Z"},"bugs":{"url":"https://github.com/molecule-dev/molecule/issues"},"license":"Apache-2.0","homepage":"https://www.molecule.dev/packages/app-state","keywords":["molecule","state","store","state-management"],"repository":{"url":"git+https://github.com/molecule-dev/molecule.git","type":"git","directory":"packages/app/core/state"},"description":"Client state management interface for molecule.dev","maintainers":[{"name":"vialoh","email":"npm@vialoh.me"}],"readme":"<!--\nAUTO-GENERATED — DO NOT EDIT THIS FILE.\nGenerated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.\nEdits here are overwritten on the next commit (molecule's pre-commit hook regenerates).\nTo change this document, edit the module-level JSDoc in src/index.ts.\nGenerated: 2026-08-04T01:52:44.478Z\n-->\n\n# @molecule/app-state\n\n> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.\n> It is written to be read by coding agents as much as by people, and is generated from this\n> package's source — edit `src/index.ts` JSDoc, not this file.\n\nClient state management interface for molecule.dev.\n\nProvides a unified state management API that works across different\nstate management solutions (hooks, Zustand, Redux, Jotai, etc.).\n\n## Quick Start\n\n```ts\nimport { createStore } from '@molecule/app-state'\nimport { useStore } from '@molecule/app-react'\n\nconst uiStore = createStore({ initialState: { sidebarOpen: false } })\n\nfunction Sidebar() {\n  const { sidebarOpen } = useStore(uiStore) // subscribes to the store\n  const toggle = () => uiStore.setState({ sidebarOpen: !sidebarOpen })\n}\n```\n\n## Type\n\n`core`\n\n## Installation\n\n```bash\nnpm install @molecule/app-state @molecule/app-bond @molecule/app-logger\n```\n\n## API\n\n### Interfaces\n\n#### `AsyncState`\n\nAsync state tuple.\n\n```typescript\ninterface AsyncState<T> {\n  /**\n   * Current data value.\n   */\n  data: T\n\n  /**\n   * Whether the state is loading.\n   */\n  loading: boolean\n\n  /**\n   * Error if any occurred.\n   */\n  error: Error | null\n}\n```\n\n#### `AsyncStateActions`\n\nAsync state actions.\n\n```typescript\ninterface AsyncStateActions<T> {\n  /**\n   * Sets the data value.\n   */\n  setData(data: T): void\n\n  /**\n   * Sets the loading state.\n   */\n  setLoading(loading: boolean): void\n\n  /**\n   * Sets an error.\n   */\n  setError(error: Error | null): void\n\n  /**\n   * Resets to initial state.\n   */\n  reset(): void\n\n  /**\n   * Executes an async operation, handling loading/error states.\n   */\n  execute<R>(fn: () => Promise<R>): Promise<R>\n}\n```\n\n#### `PersistStorage`\n\nSimple storage adapter interface for persist middleware.\nCompatible with `localStorage`, `sessionStorage`, and\n`@molecule/app-storage` providers.\n\n```typescript\ninterface PersistStorage {\n  getItem(key: string): string | null\n  setItem(key: string, value: string): void\n}\n```\n\n#### `StateProvider`\n\nState provider interface that all state management bond packages\nmust implement. Provides the store creation factory.\n\n```typescript\ninterface StateProvider {\n  /**\n   * Creates a new store.\n   */\n  createStore<T>(config: StoreConfig<T>): Store<T>\n}\n```\n\n#### `Store`\n\nReactive state container with getState, setState, subscribe, and destroy.\n\nAll state management providers must implement this interface.\n\n```typescript\ninterface Store<T> {\n  /**\n   * Gets the current state.\n   */\n  getState(): T\n\n  /**\n   * Sets the state (partial or via updater function).\n   */\n  setState(partial: Partial<T> | ((state: T) => Partial<T>)): void\n\n  /**\n   * Subscribes to state changes.\n   * Returns an unsubscribe function.\n   */\n  subscribe(listener: StateListener<T>): () => void\n\n  /**\n   * Destroys the store and cleans up subscriptions.\n   */\n  destroy(): void\n}\n```\n\n#### `StoreConfig`\n\nConfiguration for creating a store (initial state, optional name, and middleware chain).\n\n```typescript\ninterface StoreConfig<T> {\n  /**\n   * Initial state value.\n   */\n  initialState: T\n\n  /**\n   * Optional name for debugging.\n   */\n  name?: string\n\n  /**\n   * Optional middleware functions.\n   */\n  middleware?: StoreMiddleware<T>[]\n}\n```\n\n### Types\n\n#### `EqualityFn`\n\nEquality comparator for selectors. When provided, prevents\nre-renders if the selected value is equal to the previous one.\n\n```typescript\ntype EqualityFn<T> = (a: T, b: T) => boolean\n```\n\n#### `GetState`\n\nGet state function type.\n\n```typescript\ntype GetState<T> = () => T\n```\n\n#### `Selector`\n\nSelector function that derives a value from store state.\n\n```typescript\ntype Selector<T, S> = (state: T) => S\n```\n\n#### `SetState`\n\nFunction to update store state with a partial object or updater function.\n\n```typescript\ntype SetState<T> = (partial: Partial<T> | ((state: T) => Partial<T>)) => void\n```\n\n#### `StateListener`\n\nCallback invoked whenever store state changes.\n\n```typescript\ntype StateListener<T> = (state: T, prevState: T) => void\n```\n\n#### `StoreMiddleware`\n\nStore middleware function. Wraps the `set` function to intercept\nstate updates (e.g. for logging, persistence, or devtools).\n\n```typescript\ntype StoreMiddleware<T> = (set: SetState<T>, get: GetState<T>) => SetState<T>\n```\n\n### Functions\n\n#### `combineStores(stores)`\n\nCombines multiple stores into a single composite store. Each key\nin `stores` becomes a top-level key in the combined state.\n\n```typescript\nfunction combineStores(stores: { [K in keyof T]: Store<T[K]> }): Store<T>\n```\n\n- `stores` — A record mapping keys to individual stores.\n\n**Returns:** A composite `Store` that delegates to the individual stores.\n\n#### `createAsyncState(initialData)`\n\nCreates an async state container with loading/error tracking.\n\n```typescript\nfunction createAsyncState(initialData: T): [AsyncState<T>, AsyncStateActions<T>]\n```\n\n- `initialData` — The initial data value.\n\n**Returns:** A tuple of `[state, actions]` for reading and updating the async state.\n\n#### `createSimpleStateProvider()`\n\nCreates a vanilla JavaScript state provider that manages stores\nwith simple object spreading and listener-based subscriptions.\n\n```typescript\nfunction createSimpleStateProvider(): StateProvider\n```\n\n**Returns:** A `StateProvider` implementation.\n\n#### `createStore(config)`\n\nCreates a new reactive state store using the bonded provider.\n\n```typescript\nfunction createStore(config: StoreConfig<T>): Store<T>\n```\n\n- `config` — Store configuration including initial state, actions, selectors, and middleware.\n\n**Returns:** A reactive store instance with `getState()`, `setState()`, and `subscribe()` methods.\n\n#### `getProvider()`\n\nRetrieves the bonded state provider, throwing if none is configured.\n\n```typescript\nfunction getProvider(): StateProvider\n```\n\n**Returns:** The bonded state provider.\n\n#### `hasProvider()`\n\nChecks whether a state provider is currently bonded.\n\n```typescript\nfunction hasProvider(): boolean\n```\n\n**Returns:** `true` if a state provider is bonded.\n\n#### `loggerMiddleware(name)`\n\nLogging middleware — logs previous and next state on every update.\n\n```typescript\nfunction loggerMiddleware(name?: string): StoreMiddleware<T>\n```\n\n- `name` — Optional store name for log prefix (defaults to `'store'`).\n\n**Returns:** A store middleware that logs state transitions.\n\n#### `persistMiddleware(key, storage)`\n\nPersist middleware — saves state to storage on every update and\nrestores it on initialization.\n\nAccepts any object implementing `PersistStorage` (`getItem` + `setItem`).\nDefaults to in-memory storage.\n\n```typescript\nfunction persistMiddleware(key: string, storage?: PersistStorage): StoreMiddleware<T>\n```\n\n- `key` — The storage key to persist state under.\n- `storage` — A `PersistStorage`-compatible object (defaults to in-memory).\n\n**Returns:** A store middleware that persists state to the given storage.\n\n#### `produce(state, recipe)`\n\nSimplified produce helper for immutable state updates.\nCreates a shallow copy, applies the recipe, and returns the result.\n\n```typescript\nfunction produce(state: T, recipe: (draft: T) => void): T\n```\n\n- `state` — The current state object.\n- `recipe` — A function that mutates the draft copy.\n\n**Returns:** A new state object with the recipe's mutations applied.\n\n#### `setProvider(provider)`\n\nRegisters a state provider as the active singleton. Called by bond\npackages during application startup.\n\n```typescript\nfunction setProvider(provider: StateProvider): void\n```\n\n- `provider` — The state provider implementation to bond.\n\n#### `shallowEqual(a, b)`\n\nPerforms a shallow equality comparison between two values.\nReturns `true` if both values have the same top-level keys\nwith identical values (using `Object.is`).\n\n```typescript\nfunction shallowEqual(a: T, b: T): boolean\n```\n\n- `a` — First value to compare.\n- `b` — Second value to compare.\n\n**Returns:** `true` if the values are shallowly equal.\n\n### Constants\n\n#### `simpleProvider`\n\nPre-created default state provider instance.\n\n```typescript\nconst simpleProvider: StateProvider\n```\n\n## Available Providers\n\n| Provider | Package                       |\n| -------- | ----------------------------- |\n| Jotai    | `@molecule/app-state-jotai`   |\n| Redux    | `@molecule/app-state-redux`   |\n| Zustand  | `@molecule/app-state-zustand` |\n\n## Injection Notes\n\n### Requirements\n\nPeer dependencies:\n\n- `@molecule/app-bond` ^1.0.1\n- `@molecule/app-logger` ^1.0.1\n\n### Runtime Dependencies\n\n- `@molecule/app-bond`\n- `@molecule/app-logger`\n\nDefine stores with {@link createStore} and read them through the framework hook\n(`useStore(store)` in React / the Vue composable) — do NOT `import` zustand / redux /\njotai directly in a component; that couples you to one library and breaks the swap. For a\nlarge store, pass a selector via the hook's options so a component re-renders only when the\nslice it reads changes.\n\n- This is CLIENT/UI state — NOT the source of truth for server data. Fetch server data\n  through the HTTP client (`@molecule/app-http`) and keep the store for UI/session state.\n- **{@link persistMiddleware} persists to storage — never persist a secret or auth token**\n  there (client storage is XSS-exfiltratable; the bearer token is memory-only — see\n  `@molecule/app-storage`). Persist only non-sensitive UI state, via the storage\n  ABSTRACTION, never raw `localStorage`.\n","readmeFilename":"README.md"}