{"_id":"@bekoden/interval-manager","name":"@bekoden/interval-manager","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bekoden/interval-manager","publishConfig":{"access":"public"},"version":"0.1.0","description":"Shared global interval manager for TypeScript and React apps.","license":"MIT","type":"module","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.cjs"}},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"devDependencies":{"@types/react":"^19.0.12","react":"^19.0.0","tsup":"^8.3.5","typescript":"^5.8.2","vitest":"^3.0.8"},"_id":"@bekoden/interval-manager@0.1.0","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-QXyzVfn6HyQMRPc4wgQexvu+Cr2/W+E66sn9nrjteUtB8fA8W1aPfHfRl3chtnYAKkvt2KmdOupYWHCt+jvSAg==","shasum":"9e866ec871709b1ada2985eebf0ddd5fe13a1b32","tarball":"https://registry.npmjs.org/@bekoden/interval-manager/-/interval-manager-0.1.0.tgz","fileCount":16,"unpackedSize":58788,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGdeUmp+LOTLydIfmbsgR3UhQ/sNebEXRPoAMsXWLIhnAiEAtI3fc3jFOTKPTzCASLf7b4/kfOYmjK1mLy4K9iZh42c="}]},"_npmUser":{"name":"cyberpolin","email":"cyberpolin@gmail.com"},"directories":{},"maintainers":[{"name":"cyberpolin","email":"cyberpolin@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/interval-manager_0.1.0_1771972147692_0.4286468403654058"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-24T22:29:07.624Z","0.1.0":"2026-02-24T22:29:07.846Z","modified":"2026-02-24T22:29:08.031Z"},"maintainers":[{"name":"cyberpolin","email":"cyberpolin@gmail.com"}],"description":"Shared global interval manager for TypeScript and React apps.","license":"MIT","readme":"# @koden/interval-manager\n\nShared interval ticker for TypeScript apps, with optional React bindings.\n\n## Install\n\n```bash\nnpm install @koden/interval-manager\n```\n\nReact bindings (if needed):\n\n```bash\nnpm install react\n```\n\n## Quick usage (core)\n\n```ts\nimport { createIntervalManager } from \"@koden/interval-manager\";\n\nconst manager = createIntervalManager();\n\nconst unsubscribe = manager.subscribe(({ nowMs, tickCount }) => {\n  console.log(\"tick\", tickCount, nowMs);\n});\n\nmanager.start();\n\n// later\nunsubscribe();\nmanager.stop();\nmanager.dispose();\n```\n\n## React usage\n\n```tsx\nimport React from \"react\";\nimport {\n  IntervalManagerProvider,\n  useIntervalNow,\n  useIntervalCountdown,\n} from \"@koden/interval-manager/react\";\n\nfunction Clock() {\n  const nowMs = useIntervalNow();\n  return <p>{new Date(nowMs).toLocaleTimeString()}</p>;\n}\n\nfunction OfferCountdown() {\n  const targetMs = Date.now() + 60_000;\n  const remainingMs = useIntervalCountdown(targetMs);\n  return <p>{Math.ceil(remainingMs / 1000)}s left</p>;\n}\n\nexport function App() {\n  return (\n    <IntervalManagerProvider>\n      <Clock />\n      <OfferCountdown />\n    </IntervalManagerProvider>\n  );\n}\n```\n\n## Environment defaults\n\nThe manager reads these environment values when created:\n\n- `USE_INTERVAL_KODEN=true|false`\n- `USE_INTERVAL_SECONDS_KODEN=<seconds>`\n\nParsing rules:\n\n- `USE_INTERVAL_KODEN` is case-insensitive and trimmed.\n- Only `\"true\"` and `\"false\"` are accepted. Any other value falls back to default (`true`).\n- `USE_INTERVAL_SECONDS_KODEN` must be a finite positive number.\n- Missing/invalid seconds fall back to `1`.\n- Valid seconds are clamped to a minimum of `1`.\n- Programmatic config (`enabled`, `intervalSeconds`) overrides env values.\n- Runtime API can still update values via `setEnabled(...)` and `setIntervalSeconds(...)`.\n\nExample:\n\n```ts\nconst manager = createIntervalManager({\n  enabled: false,\n  intervalSeconds: 5,\n});\n```\n\n## SSR notes\n\n- `createIntervalManager` safely checks for `process.env` only when available.\n- `useIntervalNow` uses `useSyncExternalStore` and provides a server snapshot.\n- Prefer creating one manager instance per request boundary in SSR frameworks.\n\n## Migration notes\n\nReplace many component-level `setInterval` calls with one shared manager:\n\n1. Create one manager during app bootstrap.\n2. Subscribe from places that need a periodic update.\n3. Remove local timer setup/cleanup from components.\n4. In React, expose it via `IntervalManagerProvider` and use hooks.\n\nThis reduces duplicate timers and keeps ticking behavior centralized.\n\n## API\n\nCore:\n\n- `createIntervalManager(config?)`\n- `start()`\n- `stop()`\n- `isRunning()`\n- `getNow()`\n- `subscribe(listener)`\n- `setIntervalSeconds(seconds)`\n- `setEnabled(enabled)`\n- `dispose()`\n\nReact:\n\n- `IntervalManagerProvider`\n- `useIntervalManager()`\n- `useIntervalNow()`\n- `useIntervalCountdown(targetMs)`\n","readmeFilename":"README.md","_rev":"1-07c12d2469c6f7e164e5b7a07c55bd59"}