{"_id":"@bonsai-ts/state","_rev":"2-3ddf9cb3fa04fb51f5030d97e50452c1","name":"@bonsai-ts/state","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@bonsai-ts/state","version":"1.0.0","keywords":["state-management","react","typescript","middleware","devtools"],"author":{"url":"Akarikev","name":"Prince Elorm"},"license":"MIT","_id":"@bonsai-ts/state@1.0.0","maintainers":[{"name":"akarikev","email":"princeelorm17@gmail.com"}],"homepage":"https://github.com/Akarikev/bonsai#readme","bugs":{"url":"https://github.com/Akarikev/bonsai/issues"},"dist":{"shasum":"fc9a5c1723d994781c43cf8540f2284d71a8fefb","tarball":"https://registry.npmjs.org/@bonsai-ts/state/-/state-1.0.0.tgz","fileCount":20,"integrity":"sha512-/E+USGJ6VN0ceW3DGfh5JzfY4gnqJGRSqRpqV6YnKiSw1MylS70GQ12A2xoYOk5J8Ut/XxgiHV185ohMfHdHnA==","signatures":[{"sig":"MEUCIHOk+tHLBY3K1JIdAjbND35e9m8y3E2u3/gJ1fJeOei2AiEAliqgJ7q/J7n29LmYSk697AFUlXOCoksY0kgHKIyJxvc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":232224},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"bun":">=1.0.0","node":">=16.0.0"},"gitHead":"86c5245da9fb4edf45eb61ba97641df3437fd0dd","scripts":{"dev":"vite","docs":"typedoc --out docs src","test":"vitest","build":"tsc && vite build","prepublishOnly":"npm run build"},"_npmUser":{"name":"akarikev","email":"princeelorm17@gmail.com"},"repository":{"url":"git+https://github.com/Akarikev/bonsai.git","type":"git"},"_npmVersion":"11.0.0","description":"A flexible state management library with tree and flat state support, middleware, and dev tools","directories":{},"_nodeVersion":"22.13.1","dependencies":{"react":"^19.1.0","react-dom":"^19.1.0"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.5","vitest":"^1.6.1","typedoc":"^0.24.8","@types/bun":"latest","typescript":"^5.8.3","@types/react":"^19.1.6","vite-plugin-dts":"^4.5.4","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.5.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/state_1.0.0_1749294352380_0.03526056786817744","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bonsai-ts/state","version":"1.1.0","description":"A flexible state management library with tree and flat state support, middleware, and dev tools","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./devtools":{"types":"./dist/devtools.d.ts","import":"./dist/devtools.mjs","require":"./dist/devtools.js"}},"scripts":{"dev":"bunx --bun vite","build":"bunx --bun tsc && bunx --bun vite build","prepublishOnly":"bun run build","test":"bunx --bun vitest","docs":"bunx --bun typedoc --out docs src","analyze":"bunx --bun vite build --mode analyze","benchmark":"bunx --bun vitest run benchmark","size":"bunx --bun size-snapshot"},"keywords":["state-management","react","typescript","middleware","devtools"],"author":{"name":"Prince Elorm","url":"Akarikev"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/Akarikev/bonsai.git"},"bugs":{"url":"https://github.com/Akarikev/bonsai/issues"},"homepage":"https://github.com/Akarikev/bonsai#readme","devDependencies":{"@types/bun":"latest","@types/react":"^19.1.6","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.5.1","ajv":"^8.17.1","ajv-draft-04":"^1.0.0","autocannon":"^7.15.0","rollup-plugin-size-snapshot":"^0.12.0","rollup-plugin-visualizer":"^5.9.2","typedoc":"^0.24.8","typescript":"^5.8.3","vite":"^6.3.5","vite-plugin-dts":"^4.5.4","vitest":"^1.6.1"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"dependencies":{},"engines":{"node":">=16.0.0","bun":">=1.0.0"},"_id":"@bonsai-ts/state@1.1.0","gitHead":"83b0dc7f4c25451a9efd78fee597a792b0020dce","_nodeVersion":"22.13.1","_npmVersion":"11.0.0","dist":{"integrity":"sha512-h+IIvCzT/NtaUyQBN489MGZi6rDc7iewnPr1EKGFudhlBc9/mpTzYbyoyk7kX04CLHRu9PGj2Ji1VBaAjoIoxQ==","shasum":"c0ba81de9a8265cf2b781f58e1dc127707841c72","tarball":"https://registry.npmjs.org/@bonsai-ts/state/-/state-1.1.0.tgz","fileCount":21,"unpackedSize":6615287,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICgYxeInN0nt9wMtbw6MmDpprUUlQ6o1JbB9uE6YbkLXAiAnrCUDrVGEYjzU4l6N4b46hcDb6ge1TV6hAtIJOqXGZg=="}]},"_npmUser":{"name":"akarikev","email":"princeelorm17@gmail.com"},"directories":{},"maintainers":[{"name":"akarikev","email":"princeelorm17@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/state_1.1.0_1754761797130_0.7236512741617354"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-07T11:05:52.323Z","modified":"2025-08-09T17:49:57.597Z","1.0.0":"2025-06-07T11:05:52.608Z","1.1.0":"2025-08-09T17:49:57.378Z"},"bugs":{"url":"https://github.com/Akarikev/bonsai/issues"},"author":{"name":"Prince Elorm","url":"Akarikev"},"license":"MIT","homepage":"https://github.com/Akarikev/bonsai#readme","keywords":["state-management","react","typescript","middleware","devtools"],"repository":{"type":"git","url":"git+https://github.com/Akarikev/bonsai.git"},"description":"A flexible state management library with tree and flat state support, middleware, and dev tools","maintainers":[{"name":"akarikev","email":"princeelorm17@gmail.com"}],"readme":"# Bonsai State Management 🌳\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.0.0-blue)](https://www.typescriptlang.org/)\n[![React](https://img.shields.io/badge/React-19.0.0-blue)](https://reactjs.org/)\n[![Bundle Size](https://img.shields.io/badge/Bundle%20Size-7KB%20gzipped-green)](https://img.shields.io/badge/Bundle%20Size-7KB%20gzipped-green)\n\nA flexible and lightweight state management library for React applications, featuring tree and flat state support, middleware system, and powerful dev tools.\n\n## Why Bonsai? 🌱\n\nBonsai offers a unique approach to state management:\n\n- **Simple Yet Powerful**: Easy to learn, but powerful enough for complex applications\n- **Type-Safe by Default**: Full TypeScript support with excellent type inference\n- **Flexible Architecture**: Choose between tree state, flat state, or scoped state\n- **Built-in DevTools**: Debug and inspect state changes in real-time\n- **Middleware System**: Extend functionality with custom middleware\n- **Zero Dependencies**: Lightweight and fast, with no external dependencies\n- **React Native Ready**: Works seamlessly with both web and mobile React applications\n\n## Features\n\n- 🌳 **Tree State**: Manage nested state with path-based access\n- 🌿 **Flat State**: Simple key-value state management\n- 🪴 **Scoped State**: Isolated state stores for components\n- 🔌 **Middleware**: Transform or block state updates\n- 🛠️ **DevTools**: Visual debugging and state inspection\n- 📦 **TypeScript**: Full type safety and autocompletion\n\n## What's new in this release\n\n- **createStore API**: one-call setup for tree state with options `{ devtools, middleware }`.\n- **Auto-mounted DevTools**: enable with `devtools: true` (no component needed).\n- **Modern DevTools UI**: tabs (State, Inspector, Logs, Settings), draggable, resizable, search, copy buttons with feedback, and a toggle hotkey.\n- **Hotkey**: Ctrl+Shift+B toggles the DevTools panel.\n- **Koa-style middleware adapter**: pass `(next) => (path, value, prev) => next(path, value)` directly.\n\n> Note: The classic API (`initTreeState`, `useTreeBonsai`, `set`, `get`, `subscribe`) is still available and supported. New projects are encouraged to use `createStore` for simpler setup and optional DevTools auto-mounting.\n\n## Prerequisites\n\n- React >= 18.2.0\n- TypeScript >= 5.0.0 (recommended)\n\n## Installation\n\n```bash\n# Using npm\nnpm install @bonsai-ts/state\n\n# Using yarn\nyarn add @bonsai-ts/state\n\n# Using pnpm\npnpm add @bonsai-ts/state\n\n# Using bun\nbun add @bonsai-ts/state\n```\n\n## Quick Start\n\n### Recommended: createStore\n\n```tsx\nimport { createStore } from \"@bonsai-ts/state\";\n\n// Initialize once with options (auto-mounts DevTools in dev when enabled)\nexport const appStore = createStore(\n  {\n    count: 0,\n    user: { name: \"elorm\", isActive: true },\n  },\n  { devtools: true }\n);\n\n// Use in components\nfunction Counter() {\n  const count = appStore.use<number>(\"count\") || 0;\n  return (\n    <button onClick={() => appStore.set(\"count\", count + 1)}>\n      Increment ({count})\n    </button>\n  );\n}\n```\n\n### Tree State (classic API)\n\n```tsx\nimport { initTreeState, useTreeBonsai, set } from \"@bonsai-ts/state\";\n\n// Initialize tree state\ninitTreeState({\n  initialState: {\n    count: 0,\n    user: {\n      name: \"elorm\",\n      isActive: true,\n    },\n  },\n});\n\n// Use in components\nfunction Counter() {\n  const count = useTreeBonsai(\"count\");\n  const name = useTreeBonsai(\"user/name\");\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <p>Name: {name}</p>\n      <button onClick={() => set(\"count\", count + 1)}>Increment</button>\n    </div>\n  );\n}\n```\n\n### Flat State\n\n```tsx\nimport { useBonsai, setState } from \"@bonsai-ts/state\";\n\nfunction UserProfile() {\n  const name = useBonsai((state) => state.name || \"\");\n  const isActive = useBonsai((state) => state.isActive || false);\n\n  return (\n    <div>\n      <p>Name: {name}</p>\n      <button onClick={() => setState({ isActive: !isActive })}>\n        Toggle Status\n      </button>\n    </div>\n  );\n}\n```\n\n### DevTools (Optional)\n\nThere are two ways to use DevTools:\n\n- Recommended: enable auto-mount via `createStore(..., { devtools: true })`.\n- Manual: render the component yourself if you want full control.\n\nManual render example:\n\n```tsx\nimport { DevPanel } from \"@bonsai-ts/state/devtools\";\n\nfunction App() {\n  return (\n    <div>\n      <Counter />\n      <UserProfile />\n      <DevPanel />\n    </div>\n  );\n}\n```\n\nThe DevPanel provides:\n\n- 🌳 **State Tree View**: Visualize your entire state tree\n- 📝 **Log Viewer**: Track all state changes in real-time\n- 🔍 **State Inspector**: Inspect and modify state values\n- ⚡ **Performance Monitor**: Track re-renders and updates\n- ✨ **Enhanced Object/Array Visualization**: Structured, collapsible, and editable views for complex data types.\n- ⌨️ **Hotkey**: Ctrl+Shift+B to toggle visibility.\n- 🧭 **Draggable & Resizable**: drag the header, resize from the bottom-right handle.\n- 📋 **Copy with feedback**: copy paths or JSON values with visual confirmation.\n\n### DevTools Screenshots\n\n![DevPanel Preview (Updated UI)](docs/devpanel-preview.gif)\n\n> **Note**: The DevPanel is only included in development builds and is automatically excluded from production builds. You only need to import and use it if you want to visualize and debug your application's state.\n\n## More Examples\n\n### Tree State with Middleware\n\n```tsx\nimport {\n  initTreeState,\n  useTreeBonsai,\n  set,\n  createLoggingMiddleware,\n  createValidationMiddleware,\n} from \"@bonsai-ts/state\";\n\n// Initialize with middleware\ninitTreeState({\n  initialState: {\n    user: {\n      name: \"\",\n      preferences: {\n        theme: \"light\",\n        notifications: true,\n      },\n    },\n  },\n  middleware: [\n    createLoggingMiddleware({ logPath: true, logValue: true }),\n    createValidationMiddleware((path, value) => {\n      if (\n        path === \"user/name\" &&\n        typeof value === \"string\" &&\n        value.length < 2\n      ) {\n        return \"Name must be at least 2 characters long\";\n      }\n      return true;\n    }),\n  ],\n});\n\nfunction UserProfile() {\n  const name = useTreeBonsai(\"user/name\");\n  const theme = useTreeBonsai(\"user/preferences/theme\");\n\n  return (\n    <div>\n      <input value={name} onChange={(e) => set(\"user/name\", e.target.value)} />\n      <button\n        onClick={() =>\n          set(\"user/preferences/theme\", theme === \"light\" ? \"dark\" : \"light\")\n        }\n      >\n        Toggle Theme\n      </button>\n    </div>\n  );\n}\n```\n\n### Flat State\n\n```tsx\nimport { useBonsai, setState } from \"@bonsai-ts/state\";\n\nfunction UserProfile() {\n  const name = useBonsai((state) => state.name || \"\");\n  const notifications = useBonsai((state) => state.notifications || false);\n\n  return (\n    <div>\n      <input\n        value={name}\n        onChange={(e) => setState({ name: e.target.value })}\n      />\n      <label>\n        <input\n          type=\"checkbox\"\n          checked={notifications}\n          onChange={(e) => setState({ notifications: e.target.checked })}\n        />\n        Enable Notifications\n      </label>\n    </div>\n  );\n}\n```\n\n### Scoped State\n\n```tsx\nimport { createBonsaiStore } from \"@bonsai-ts/state\";\n\n// Create a scoped store\nconst todoStatsStore = createBonsaiStore<{\n  totalCompleted: number;\n  totalPending: number;\n}>();\n\nfunction TodoStats() {\n  const stats = todoStatsStore.use((state) => state);\n\n  return (\n    <div>\n      <p>Total Completed: {stats.totalCompleted || 0}</p>\n      <p>Total Pending: {stats.totalPending || 0}</p>\n    </div>\n  );\n}\n\n// Update stats from tree state\nsubscribe(\"todos\", (todos) => {\n  if (!todos) return;\n\n  const totalCompleted = todos.filter((todo) => todo.completed).length;\n  const totalPending = todos.length - totalCompleted;\n\n  todoStatsStore.set({ totalCompleted, totalPending });\n});\n```\n\n### Tree Store with DevTools and Middleware (createStore)\n\n```tsx\nimport { createStore, createLoggingMiddleware } from \"@bonsai-ts/state\";\n\nexport const counterStore = createStore(\n  { count: 0 },\n  {\n    devtools: true, // auto-mounts the DevTools floating panel\n    middleware: [\n      createLoggingMiddleware({ logPath: true, logValue: true }),\n      // Or Koa-style middleware adapter\n      (next) => (path, value, prev) => {\n        console.log(`State change at ${path}:`, { prev, value });\n        return next(path, value);\n      },\n    ],\n  }\n);\n\n// Usage in components\nfunction Counter() {\n  const count = counterStore.use<number>(\"count\");\n  return (\n    <button onClick={() => counterStore.set(\"count\", (count || 0) + 1)}>\n      {count || 0}\n    </button>\n  );\n}\n```\n\n### createStore API\n\n- `createStore(initialState, options)` returns an object with:\n  - `get(path)`: read a value at a path\n  - `set(path, value)`: async update; resolves to `true | false` if blocked by middleware\n  - `subscribe(path, cb)`: listen for changes under a path\n  - `use<T>(path)`: React hook to read and subscribe to a path\n  - `addMiddleware(mw)`: add middleware after initialization\n- `options`:\n  - `devtools?: boolean` – auto-mount floating DevTools panel when `true`\n  - `middleware?: (Middleware | (next) => (path, value, prev) => any)[]` – chain of middleware; Koa-style functions are adapted automatically\n\nTips:\n\n- `set` is async; await if you need to read immediately after updating.\n- Use specific paths in `use(path)` to minimize re-renders.\n\n## Migration: initTreeState ➜ createStore\n\nIf you previously used `initTreeState`, migrating to `createStore` takes a few steps:\n\n1. Initialize once with `createStore` instead of `initTreeState`:\n   - Before:\n     ```ts\n     initTreeState({ initialState, middleware: [m1, m2] });\n     ```\n   - After:\n     ```ts\n     export const appStore = createStore(initialState, {\n       middleware: [m1, m2],\n       devtools: true,\n     });\n     ```\n2. Replace direct tree APIs in components:\n   - `useTreeBonsai(path)` ➜ `appStore.use(path)`\n   - `set(path, value)` ➜ `appStore.set(path, value)` (still async)\n   - `subscribe(path, cb)` ➜ `appStore.subscribe(path, cb)`\n   - Optional: `appStore.addMiddleware(mw)` to add later\n3. DevTools:\n   - Before: render `<DevPanel />` manually\n   - After: set `devtools: true` to auto-mount; or keep manual component render if preferred\n4. Middleware:\n   - Existing middleware works as-is; you can also pass Koa-style `(next) => (path, value, prev)` functions\n5. Type-safety & paths:\n   - Continue to use forward-slash paths like \"user/name\"\n6. Async behavior reminder:\n   - `set` is async; `await appStore.set(path, value)` when you need the updated value immediately\n\nMinimal example conversion:\n\n```tsx\n// Before\ninitTreeState({ initialState: { count: 0 } });\nfunction Counter() {\n  const count = useTreeBonsai(\"count\") || 0;\n  return <button onClick={() => set(\"count\", count + 1)}>{count}</button>;\n}\n\n// After\nexport const store = createStore({ count: 0 }, { devtools: true });\nfunction Counter() {\n  const count = store.use<number>(\"count\") || 0;\n  return <button onClick={() => store.set(\"count\", count + 1)}>{count}</button>;\n}\n```\n\n## FAQ\n\n- **How do I enable DevTools?** Use `createStore(..., { devtools: true })`. Or render `<DevPanel />` manually from `@bonsai-ts/state/devtools`.\n- **How do I disable DevTools in production?** Auto-mount is only intended for development; avoid passing `devtools: true` in production builds. The component is tree-shakeable when not imported.\n- **Does this work with Next.js/SSR?** Yes. The store APIs are isomorphic; the DevTools auto-mount only runs in the browser (checks `document`).\n- **Is `set` async now?** Yes. Await `set` if you need to read the updated value immediately after.\n- **Can I add middleware after creating the store?** Yes: `store.addMiddleware(mw)`.\n- **React Native?** Supported. DevTools auto-mount is web-only; for RN, omit `devtools: true` or build a separate debug screen using the store APIs.\n- **Hotkey conflicts?** The DevTools toggle uses Ctrl+Shift+B. You can collapse via the close button if there’s a conflict.\n\n## Troubleshooting\n\n### Common Issues\n\n1. **State Updates Not Reflecting**\n\n   ```tsx\n   // ❌ Wrong\n   set(\"user/name\", \"John\");\n   console.log(get(\"user/name\")); // Might not show updated value (set is async)\n\n   // ✅ Correct\n   await set(\"user/name\", \"John\");\n   console.log(get(\"user/name\")); // Will show updated value\n   ```\n\n2. **Middleware Not Working**\n\n   ```tsx\n   // ❌ Wrong\n   initTreeState({\n     initialState: { count: 0 },\n     middleware: myMiddleware, // Should be an array\n   });\n\n   // ✅ Correct\n   initTreeState({\n     initialState: { count: 0 },\n     middleware: [myMiddleware],\n   });\n   ```\n\n3. **Type Errors with Paths**\n\n   ```tsx\n   // ❌ Wrong\n   useTreeBonsai(\"user.name\"); // Using dot notation\n\n   // ✅ Correct\n   useTreeBonsai(\"user/name\"); // Using forward slash\n   ```\n\n### Performance Tips\n\n1. **Use Scoped State for Local State**\n\n   ```tsx\n   // For component-specific state\n   const localStore = createBonsaiStore({ count: 0 });\n   const count = localStore.use((state) => state.count);\n   ```\n\n2. **Optimize Re-renders**\n\n   ```tsx\n   // Use specific paths instead of entire objects\n   const name = useTreeBonsai(\"user/name\"); // ✅\n   const user = useTreeBonsai(\"user\"); // ❌\n   ```\n\n3. **Batch Updates**\n   ```tsx\n   // Multiple updates in one render\n   set(\"user\", {\n     name: \"John\",\n     age: 30,\n   });\n   ```\n\n## Middleware Examples\n\n### Basic Middleware Composition\n\n```tsx\nimport {\n  initTreeState,\n  createValidationMiddleware,\n  createLoggingMiddleware,\n  createPersistenceMiddleware,\n} from \"@bonsai-ts/state\";\n\n// Validation middleware\nconst positiveNumberValidator = createValidationMiddleware<number>(\n  (path, nextValue) => {\n    if (typeof nextValue !== \"number\") {\n      return \"Value must be a number\";\n    }\n    if (nextValue < 0) {\n      return \"Value must be positive\";\n    }\n    return true;\n  }\n);\n\n// Logging middleware\nconst logger = createLoggingMiddleware<number>({\n  logPath: true,\n  logValue: true,\n  logPrevValue: true,\n});\n\n// Persistence middleware\nconst persister = createPersistenceMiddleware<number>(\"counter\");\n\n// Initialize with middleware chain\ninitTreeState({\n  initialState: { counter: 0 },\n  middleware: [positiveNumberValidator, logger, persister],\n});\n```\n\n### Async Operations with Debouncing\n\n```tsx\nimport {\n  initTreeState,\n  createAsyncMiddleware,\n  createDebounceMiddleware,\n} from \"@bonsai-ts/state\";\n\n// Async middleware for API calls\nconst apiMiddleware = createAsyncMiddleware<number>(async (path, nextValue) => {\n  await new Promise((resolve) => setTimeout(resolve, 1000));\n  console.log(`[API] Updating ${path} to ${nextValue}`);\n  return nextValue;\n});\n\n// Debounce middleware\nconst debouncer = createDebounceMiddleware<number>(500);\n\ninitTreeState({\n  initialState: { searchQuery: \"\" },\n  middleware: [debouncer, apiMiddleware],\n});\n```\n\n### Rate Limiting and Time Windows\n\n```tsx\nimport {\n  initTreeState,\n  createThrottleMiddleware,\n  createTimeWindowMiddleware,\n} from \"@bonsai-ts/state\";\n\n// Throttle middleware (1 update per second)\nconst throttler = createThrottleMiddleware<number>(1);\n\n// Time window middleware (business hours only)\nconst timeWindow = createTimeWindowMiddleware<number>([\n  9, 10, 11, 12, 13, 14, 15, 16, 17,\n]);\n\ninitTreeState({\n  initialState: { apiCalls: 0 },\n  middleware: [throttler, timeWindow],\n});\n```\n\n### Complex Validation\n\n```tsx\nimport {\n  initTreeState,\n  createValidationMiddleware,\n  createAsyncMiddleware,\n} from \"@bonsai-ts/state\";\n\n// User data validation\nconst userValidator = createValidationMiddleware<{\n  name: string;\n  age: number;\n  email: string;\n}>((path, nextValue) => {\n  if (!nextValue.name || nextValue.name.length < 2) {\n    return \"Name must be at least 2 characters long\";\n  }\n  if (nextValue.age < 18) {\n    return \"User must be at least 18 years old\";\n  }\n  if (!nextValue.email.includes(\"@\")) {\n    return \"Invalid email address\";\n  }\n  return true;\n});\n\n// Async validation\nconst asyncValidator = createAsyncMiddleware<{\n  name: string;\n  age: number;\n  email: string;\n}>(async (path, nextValue) => {\n  await new Promise((resolve) => setTimeout(resolve, 500));\n  console.log(`[Validation] Checking user data for ${nextValue.name}`);\n  return nextValue;\n});\n\ninitTreeState({\n  initialState: {\n    user: {\n      name: \"\",\n      age: 0,\n      email: \"\",\n    },\n  },\n  middleware: [userValidator, asyncValidator],\n});\n```\n\n### Form Handling\n\n```tsx\nimport {\n  initTreeState,\n  createDebounceMiddleware,\n  createPersistenceMiddleware,\n  createLoggingMiddleware,\n} from \"@bonsai-ts/state\";\n\n// Form state with debouncing, persistence, and logging\ninitTreeState({\n  initialState: {\n    form: {\n      username: \"\",\n      password: \"\",\n      email: \"\",\n    },\n  },\n  middleware: [\n    createDebounceMiddleware<{\n      username: string;\n      password: string;\n      email: string;\n    }>(300),\n    createLoggingMiddleware<{\n      username: string;\n      password: string;\n      email: string;\n    }>({\n      logPath: true,\n      logValue: false, // Don't log sensitive data\n      logPrevValue: false,\n    }),\n    createPersistenceMiddleware<{\n      username: string;\n      password: string;\n      email: string;\n    }>(\"formState\"),\n  ],\n});\n```\n\n## Documentation\n\nFor detailed documentation, check out our docs:\n\n- [Core Documentation](docs/BONSAI.MD) - Learn about Bonsai's core concepts and architecture\n- [Usage Guide](docs/USEBONSAI.MD) - Comprehensive guide with examples and best practices\n\n### Key Concepts\n\n1. **Tree State**\n\n   - Path-based state access (e.g., \"user/profile/name\")\n   - Nested state management\n   - Middleware support\n   - Type-safe updates\n\n2. **Flat State**\n\n   - Simple key-value store\n   - Selector-based access\n   - Direct state updates\n   - Performance optimized\n\n3. **Scoped State**\n\n   - Component-specific state\n   - Isolated state stores\n   - Type-safe access\n   - Automatic cleanup\n\n4. **Middleware**\n\n   - Validation\n   - Logging\n   - Debouncing\n   - Persistence\n   - Custom middleware support\n\n5. **DevTools**\n   - State visualization\n   - Real-time updates\n   - Path inspection\n   - Log viewer\n   - State modification\n\n## Development\n\n```bash\n# Install dependencies\nbun install\n\n# Start development server\nbun run dev\n\n# Build library\nbun run build\n\n# Run tests\nbun test\n\n# Run bundle analysis\nbun run analyze\n\n# Run benchmarks\nbun run benchmark\n\n# Generate documentation\nbun run docs\n```\n\n## 🤝 Contributing\n\nContributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.\n\n- [GitHub Issues](https://github.com/Akarikev/bonsai/issues)\n- [Documentation](docs/BONSAI.MD)\n- [Examples](docs/USEBONSAI.MD)\n\n## Changelog\n\nSee `CHANGELOG.md` for release notes.\n\n## Support\n\n- [GitHub Issues](https://github.com/Akarikev/bonsai/issues)\n- [Documentation](docs/BONSAI.MD)\n- [Examples](docs/USEBONSAI.MD)\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n- MIT © Prince Elorm(Akarikev)\n","readmeFilename":"README.md"}