{"_id":"@abuhasanrumi/state-sync","_rev":"2-ef1331762d0e4e78fcc9b078e05da671","name":"@abuhasanrumi/state-sync","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@abuhasanrumi/state-sync","version":"1.0.0","keywords":["state","sync","browser","tabs","broadcastchannel"],"author":{"name":"Abu Hasan Rumi"},"license":"MIT","_id":"@abuhasanrumi/state-sync@1.0.0","maintainers":[{"name":"abuhasanrumi","email":"abu.hasan.rumi@gmail.com"}],"dist":{"shasum":"9d08ec5a96989c2fe9acbe6f5a0b528a14896f06","tarball":"https://registry.npmjs.org/@abuhasanrumi/state-sync/-/state-sync-1.0.0.tgz","fileCount":8,"integrity":"sha512-2RAwq4vLyYwubHGFrk2XYnu+rpqEi+khJYZR5BC2kRiHX2LMzo+fh8owgCZR2ULeU0clDziNX3kEQMa3+we7ag==","signatures":[{"sig":"MEUCIDBj0+RPXex5TQgEN1Hc0fSz+zAk6rMWefTr8RfhVGv8AiEAl/VHVZXBeH2J7hLqVjJJ5eGrj2YUN3qhKjjQdSnGi0c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6263},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"e52c173873f54e0cb9298a5f24177f2e12fcd119","scripts":{"test":"jest","build":"tsc --emitDeclarationOnly && rollup -c && terser dist/index.js -o dist/index.js --compress --mangle","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"abuhasanrumi","email":"abu.hasan.rumi@gmail.com"},"_npmVersion":"10.9.2","description":"A tiny (~400B) library to sync state across browser tabs/windows","directories":{},"_nodeVersion":"23.6.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^29.3.1","tslib":"^2.8.1","rollup":"^2.60.0","terser":"^5.10.0","ts-jest":"^29.0.3","typescript":"^4.5.4","@types/jest":"^29.2.4","jest-environment-jsdom":"^29.3.1","@rollup/plugin-typescript":"^8.3.0"},"_npmOperationalInternal":{"tmp":"tmp/state-sync_1.0.0_1744446977127_0.48559670736288196","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@abuhasanrumi/state-sync","version":"1.0.1","description":"A tiny library (1kb) to sync state across browser tabs/windows","main":"dist/index.js","types":"dist/index.d.ts","type":"module","scripts":{"build":"tsc --emitDeclarationOnly && rollup -c && terser dist/index.js -o dist/index.js --compress --mangle","test":"jest","prepublishOnly":"npm test && npm run build"},"keywords":["state","sync","browser","tabs","broadcastchannel"],"author":{"name":"Abu Hasan Rumi"},"license":"MIT","devDependencies":{"@rollup/plugin-typescript":"^8.3.0","@types/jest":"^29.2.4","jest":"^29.3.1","jest-environment-jsdom":"^29.3.1","rollup":"^2.60.0","terser":"^5.10.0","ts-jest":"^29.0.3","tslib":"^2.8.1","typescript":"^4.5.4"},"_id":"@abuhasanrumi/state-sync@1.0.1","gitHead":"f4bcdd822e6fec4b114677d098c9ad7f5cf98a60","_nodeVersion":"23.6.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-IVhhMP5noReapWE7NE/4opG4lMgA94VCLeigXl9qbTotWPYPRv+HLujckHKZtFLfN6quzG8zAURKIKduKC/N5Q==","shasum":"0a4cf256a8bc88366520ad84e9eda357aa1b27f2","tarball":"https://registry.npmjs.org/@abuhasanrumi/state-sync/-/state-sync-1.0.1.tgz","fileCount":8,"unpackedSize":7123,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIB2cTbLNrGWdOCMDGMpaWU2RleSjYYi8YwhpU5WqSdG/AiA0VuZSLqknJX1q3fKp0+97qfRiRyY9f45eb8MSrU8PPg=="}]},"_npmUser":{"name":"abuhasanrumi","email":"abu.hasan.rumi@gmail.com"},"directories":{},"maintainers":[{"name":"abuhasanrumi","email":"abu.hasan.rumi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/state-sync_1.0.1_1744461056958_0.11187800639318723"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-12T08:36:17.067Z","modified":"2025-04-12T12:30:57.353Z","1.0.0":"2025-04-12T08:36:17.335Z","1.0.1":"2025-04-12T12:30:57.170Z"},"author":{"name":"Abu Hasan Rumi"},"license":"MIT","keywords":["state","sync","browser","tabs","broadcastchannel"],"description":"A tiny library (1kb) to sync state across browser tabs/windows","maintainers":[{"name":"abuhasanrumi","email":"abu.hasan.rumi@gmail.com"}],"readme":"A tiny (~1KB) JavaScript utility to sync state across browser tabs and windows using `BroadcastChannel` with a `localStorage` fallback. Perfect for SPAs, PWAs, and collaborative apps needing seamless, real-time updates.\n\n## Installation\n\n```bash\nnpm install @abuhasanrumi/state-sync\n```\n\n## Live Demo\n\nCheck it out:\n\n[Live Demo on CodeSandbox](https://codesandbox.io/p/sandbox/state-sync-demo-abc123)\n\nOpen the demo in multiple tabs to see a todo list sync instantly!\n\n## Usage\n\nCreate a reactive state that syncs across tabs:\n\n```javascript\nimport { syncState } from '@abuhasanrumi/state-sync'\n\nconst state = syncState({\n  key: 'counter',\n  initialState: { count: 0 },\n  persist: true,\n  onChange: (state) => console.log('State:', state)\n})\n\nstate.count += 1 // Updates all open tabs\n```\n\n### Options\n\n- `key` (string): Unique identifier for the state.\n- `initialState` (object/array): Initial state to sync.\n- `persist` (boolean, optional): Save state to `localStorage` (default: `false`).\n- `onChange` (function, optional): Callback triggered on state changes.\n\n### Example: Todo List\n\nBuild a synced todo list:\n\n```javascript\nimport { syncState } from '@abuhasanrumi/state-sync'\n\nconst todos = syncState({\n  key: 'todos',\n  initialState: [],\n  persist: true,\n  onChange: (state) => {\n    document.getElementById('list').innerHTML = state\n      .map((todo) => `<li>${todo}</li>`)\n      .join('')\n  }\n})\n\ndocument.getElementById('add').onclick = () => {\n  const input = document.getElementById('input')\n  if (input.value.trim()) {\n    todos.push(input.value.trim())\n    input.value = ''\n  }\n}\n\n// Initial render\ndocument.getElementById('list').innerHTML = todos\n  .map((todo) => `<li>${todo}</li>`)\n  .join('')\n```\n\n## Notes\n\n- `initialState` must be an object or array. For primitives (numbers, strings), wrap them:\n  ```javascript\n  const count = syncState({ key: 'count', initialState: { value: 0 } })\n  count.value += 1\n  ```\n- Nested updates require replacing properties:\n  ```javascript\n  state.nested = { ...state.nested, prop: value }\n  ```\n- Persisted state must match `initialState` type, or clear `localStorage[key]`.\n\n## Error Handling\n\n- Throws `Error('initialState must be object/array')` if `initialState` is `null`, `undefined`, or a primitive.\n- Warns in console if persisted state fails to parse.\n\n## Why I Built This\n\nI wanted to tackle a common web dev challenge: keeping state consistent across browser tabs. Whether it’s a shared shopping cart, a live form, or a collaborative tool, users expect tabs to stay in sync without lag or complexity. I created `state-sync` to deliver that experience in a lightweight ~1KB package, using browser-native APIs to keep it fast and dependency-free.\n\n## Why It’s Different Than Others\n\nUnlike heavy state management libraries like Redux or Zustand, or sync solutions like y-js and localforage, `state-sync` is hyper-focused on cross-tab synchronization. At just ~1KB, it’s a fraction of the size of alternatives, leveraging `BroadcastChannel` for instant updates and `localStorage` for broader compatibility. It’s not a full store—just a minimal, reactive utility with TypeScript support, designed to slot into any project without bloat.\n\n## Why I Came Up With This Idea\n\nWhile working on single-page apps, I noticed how often tabs fall out of sync—think adding a todo in one tab but not seeing it in another. Browser APIs like `BroadcastChannel` offered a solution, but I couldn’t find a simple, tiny library to harness them. After prototyping a todo list that synced across tabs, I was hooked on the idea of making tab-syncing effortless. That spark led to `state-sync`, a micro-tool to bring that magic to every developer.\n\n## Features\n\n- **Lightweight**: ~1KB, smaller than most scripts.\n- **Real-Time**: `BroadcastChannel` for instant sync, `localStorage` fallback for compatibility.\n- **Reactive**: Proxy-based state updates.\n- **Persistent**: Optional `localStorage` to retain state.\n- **TypeScript-Ready**: Full type definitions.\n- **Zero Dependencies**: Pure JavaScript, built for browsers.\n\n## Development\n\nGet started:\n\n```bash\ngit clone https://github.com/abuhasanrumi/state-sync.git\ncd state-sync\nnpm install\nnpm test\nnpm run build\n```\n\n## Contributing\n\nHave ideas to make `state-sync` even better? Please:\n\n1. Fork the repo.\n2. Create a branch: `git checkout -b feature/cool-idea`.\n3. Commit changes: `git commit -m 'Add cool idea'`.\n4. Push: `git push origin feature/cool-idea`.\n5. Open a Pull Request.\n\n## License\n\nMIT © [Abu Hasan Rumi](https://github.com/abuhasanrumi)\n\n## Related\n\nCheck out my other micro-utility:\n\n- [@abuhasanrumi/micro-flow](https://www.npmjs.com/package/@abuhasanrumi/micro-flow): Tiny debounce, throttle, and rate-limiting (~364B).\n\n```\n\n```\n","readmeFilename":"README.md"}