{"_id":"@bananaseed/potassium","_rev":"6-e60f5b5eb015eee72fa3a98905600ddd","name":"@bananaseed/potassium","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@bananaseed/potassium","version":"1.0.0","keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","_id":"@bananaseed/potassium@1.0.0","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"homepage":"https://github.com/childsr/potassium#readme","bugs":{"url":"https://github.com/childsr/potassium/issues"},"dist":{"shasum":"f92d750569ea7031de7523e3c186b9939b269cdd","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.0.0.tgz","fileCount":10,"integrity":"sha512-fhzZNjVM3rhYRwp4Q766SIkJyUXivMKQ8LfbZtj1wEXCMqPxoGSuhJTngYs3RO4RAzkEZCdErHb4VVJ/VN8TWg==","signatures":[{"sig":"MEUCIQCbqqDCgwT44fnncjdB9bgiReDP4wOZWeamzWiCgu6NAAIgAfyr2nyhC8hdiXVWvi0Mkcxei3hlY3upOkC9J5zL3fI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87338},"main":"dist/main.js","types":"dist/main.d.ts","module":"dist/main.mjs","source":"src/index.ts","gitHead":"ba44b0ea18d9a73f6ea0a6b0324b0d49e4531879","scripts":{"test":"ts-node test/test1.ts","build":"parcel build","check":"tsc --noEmit","watch":"parcel watch"},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"repository":{"url":"git+https://github.com/childsr/potassium.git","type":"git"},"_npmVersion":"11.11.0","description":"Engine for tracking state and binding events to state changes.","directories":{},"_nodeVersion":"23.6.1","dependencies":{"@bananaseed/event_stream":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"parcel":"^2.16.3","ts-node":"^10.9.2","typescript":"^5.9.3","@types/node":"^25.3.3","@parcel/packager-ts":"^2.16.3","@parcel/transformer-typescript-types":"^2.16.3"},"_npmOperationalInternal":{"tmp":"tmp/potassium_1.0.0_1772737355270_0.4319485928496063","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bananaseed/potassium","version":"1.0.1","keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","_id":"@bananaseed/potassium@1.0.1","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"homepage":"https://github.com/childsr/potassium#readme","bugs":{"url":"https://github.com/childsr/potassium/issues"},"dist":{"shasum":"26834441ad38e6e4b88ea3f810f70a7460dce285","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.0.1.tgz","fileCount":9,"integrity":"sha512-6+rOFTzgpvkwWJ4ULxBSB35qiVkh1pQrYXRCrtKuCEtiaUI3wCIPkYQKwJwnnJBjkbltSJemMXwnYc27R7obVg==","signatures":[{"sig":"MEUCIFx97OWmfC+RqC4OZtZAE9cgsNK7lbaGUBfGaHNw0atNAiEAjzm22aaWbt/PzWUhz9Ym1dg+9fckdLzL1NKGoEYjelk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51004},"main":"dist/main.js","types":"dist/main.d.ts","module":"dist/main.mjs","source":"src/index.ts","gitHead":"07b000b8bdc381335fa56daed043fbcdd97d29ea","scripts":{"test":"ts-node test/test1.ts","build":"parcel build","check":"tsc --noEmit","watch":"parcel watch"},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"repository":{"url":"git+https://github.com/childsr/potassium.git","type":"git"},"_npmVersion":"11.11.0","description":"Engine for tracking state and binding events to state changes.","directories":{},"_nodeVersion":"23.6.1","dependencies":{"@bananaseed/event_stream":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"parcel":"^2.16.3","ts-node":"^10.9.2","typescript":"^5.9.3","@types/node":"^25.3.3","@parcel/packager-ts":"^2.16.3","@parcel/transformer-typescript-types":"^2.16.3"},"_npmOperationalInternal":{"tmp":"tmp/potassium_1.0.1_1773508330188_0.5465125692985813","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bananaseed/potassium","version":"1.1.0","keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","_id":"@bananaseed/potassium@1.1.0","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"homepage":"https://github.com/childsr/potassium#readme","bugs":{"url":"https://github.com/childsr/potassium/issues"},"dist":{"shasum":"5af7ef50f868b35353d0cfb874f90278f00deb71","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.1.0.tgz","fileCount":3,"integrity":"sha512-PzAYK/w2m0BxkgdlxBlIksmh9K6Q+3bZ9qblKRVQy9SbzRElYgv+ldT5EQiztqrEDoqPBuC0mNYAIi/pxYTt2g==","signatures":[{"sig":"MEQCIE7DTlv5IhbepFZjdYY5ivyGdUoe0FaE6dftv0v/q0uKAiAm1NVCnxZVmGZP3j+bxIu0TMvsja1XwssZ/2WKHqEDgw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":8089},"main":"dist/main.js","type":"module","types":"dist/main.d.ts","module":"dist/main.mjs","source":"src/index.ts","gitHead":"bf37aaaccd78b8f7653ef695876eb76db7ebcb68","release":{"branches":["main"]},"scripts":{"test":"vitest run","build":"vite build","check":"tsc --noEmit","watch":"vite build --watch","test:watch":"vitest"},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"repository":{"url":"git+https://github.com/childsr/potassium.git","type":"git"},"_npmVersion":"11.16.0","description":"A lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@bananaseed/event_stream":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.14","vitest":"^4.1.7","ts-node":"^10.9.2","typescript":"^6.0.3","@types/node":"^25.3.3","vite-plugin-dts":"^5.0.1","semantic-release":"^25.0.3"},"_npmOperationalInternal":{"tmp":"tmp/potassium_1.1.0_1780172612147_0.1828414430655605","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@bananaseed/potassium","version":"1.1.1","keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","_id":"@bananaseed/potassium@1.1.1","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"homepage":"https://github.com/childsr/potassium#readme","bugs":{"url":"https://github.com/childsr/potassium/issues"},"dist":{"shasum":"347fa4a5f2e2a88aa09433e7b0e6d99dcffa8ea0","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.1.1.tgz","fileCount":11,"integrity":"sha512-1fyKsBe7WWQobi0K1nAWmdCUNgDQ1yWziMP9saydi/RQKJdQ9toBjKGDJlgsE2f5Cp3S6pjyHwFtJiaUfvnEWw==","signatures":[{"sig":"MEUCIApV8TL7njmyuEjKyTWSAk6bJJOMr+gg6tRWzmFB44eIAiEAn+2x6orAW6+QSnzmPnF6w6M2/e3y4obd/iWyxJQLDCE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41132},"main":"dist/main.js","type":"module","types":"dist/main.d.ts","module":"dist/main.mjs","source":"src/index.ts","gitHead":"c43db777468dffe1b8831ac078467c8e2b69bccd","release":{"branches":["main"]},"scripts":{"test":"vitest run","build":"vite build","check":"tsc --noEmit","watch":"vite build --watch","test:watch":"vitest"},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"repository":{"url":"git+https://github.com/childsr/potassium.git","type":"git"},"_npmVersion":"11.16.0","description":"A lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@bananaseed/event_stream":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.14","vitest":"^4.1.7","ts-node":"^10.9.2","typescript":"^6.0.3","@types/node":"^25.3.3","vite-plugin-dts":"^5.0.1","semantic-release":"^25.0.3"},"_npmOperationalInternal":{"tmp":"tmp/potassium_1.1.1_1780198745188_0.7247955364812231","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bananaseed/potassium","version":"1.2.0","keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","_id":"@bananaseed/potassium@1.2.0","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"homepage":"https://github.com/childsr/potassium#readme","bugs":{"url":"https://github.com/childsr/potassium/issues"},"dist":{"shasum":"a1ccf16fbaa95cdfe0ad408fef997ecf1dd92208","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.2.0.tgz","fileCount":11,"integrity":"sha512-BujO8oxCdI6aP8o25Rs6NBp0SM/AXKQtewYp98wZQlr+oCrNR44ISevkQ1YU3nGH7zzKN/mYafw55SgukdBXgw==","signatures":[{"sig":"MEQCIFzT4iQUAYSkc+gWXcduS8cZpwXKn7ymn9e1oPKKuKBuAiAQyvBgprLLvvTAv3hGa0xNai34JzzzeF4FT2hdoD+0sA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46776},"main":"dist/main.js","type":"module","types":"dist/main.d.ts","module":"dist/main.mjs","source":"src/index.ts","gitHead":"4a0d5dfc1076de75df7c370ddf937948fe6ad963","release":{"branches":["main"]},"scripts":{"test":"vitest run","build":"vite build","check":"tsc --noEmit","watch":"vite build --watch","test:watch":"vitest"},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"repository":{"url":"git+https://github.com/childsr/potassium.git","type":"git"},"_npmVersion":"11.16.0","description":"A lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes.","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@bananaseed/event_stream":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.14","vitest":"^4.1.7","ts-node":"^10.9.2","typescript":"^6.0.3","@types/node":"^25.3.3","vite-plugin-dts":"^5.0.1","semantic-release":"^25.0.3"},"_npmOperationalInternal":{"tmp":"tmp/potassium_1.2.0_1780266457874_0.6686343304624807","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@bananaseed/potassium","version":"1.2.1","description":"A lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes.","type":"module","source":"src/index.ts","main":"dist/main.js","module":"dist/main.mjs","types":"dist/main.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/childsr/potassium.git"},"release":{"branches":["main"]},"scripts":{"watch":"vite build --watch","build":"vite build","check":"tsc --noEmit","test":"vitest run","test:watch":"vitest"},"keywords":[],"author":{"name":"Ryan Childs"},"license":"MIT","devDependencies":{"@types/node":"^25.9.1","semantic-release":"^25.0.3","ts-node":"^10.9.2","typescript":"^6.0.3","vite":"^8.0.14","vite-plugin-dts":"^5.0.1","vitest":"^4.1.7"},"dependencies":{"@bananaseed/event_stream":"^1.3.1"},"gitHead":"b2c909219897534b509c2e5b4cd3a4cc0f084901","_id":"@bananaseed/potassium@1.2.1","bugs":{"url":"https://github.com/childsr/potassium/issues"},"homepage":"https://github.com/childsr/potassium#readme","_nodeVersion":"24.16.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-yjZPLXs2w7K11vADOyD3s7mPnkNEzlryVwnrNEQrgamDoBAB+NyCo7LHRP+ecvgI2Sd7+Lp9ARB2ZoL9LNCw+Q==","shasum":"6eb060cf19544e22472820e5b1888b76d4adad10","tarball":"https://registry.npmjs.org/@bananaseed/potassium/-/potassium-1.2.1.tgz","fileCount":11,"unpackedSize":46638,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBVkXvOmBnmNoywjG4g5TrIUG7ZflwcYBJpqayAPso8CAiEA6acYpp15qfDdZHE/CbSQGp3KSatAdORc6WHRsRjOoto="}]},"_npmUser":{"name":"bananaseed","email":"bananaseedgames@gmail.com"},"directories":{},"maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/potassium_1.2.1_1780268033489_0.29029381855146896"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-05T19:02:35.162Z","modified":"2026-05-31T22:53:53.715Z","1.0.0":"2026-03-05T19:02:35.410Z","1.0.1":"2026-03-14T17:12:10.350Z","1.1.0":"2026-05-30T20:23:32.271Z","1.1.1":"2026-05-31T03:39:05.329Z","1.2.0":"2026-05-31T22:27:38.030Z","1.2.1":"2026-05-31T22:53:53.623Z"},"bugs":{"url":"https://github.com/childsr/potassium/issues"},"author":{"name":"Ryan Childs"},"license":"MIT","homepage":"https://github.com/childsr/potassium#readme","keywords":[],"repository":{"type":"git","url":"git+https://github.com/childsr/potassium.git"},"description":"A lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes.","maintainers":[{"name":"bananaseed","email":"bananaseedgames@gmail.com"}],"readme":"# Potassium 🍌\n\nA lightweight, robust, and highly predictable TypeScript-based engine for tracking state and binding reactive event streams to state changes. \n\nPotassium helps in building stateful, event-driven applications by decoupling **event sources** from **state mutations** and **side effects**. It relies on reactive streams provided by [@bananaseed/event_stream](https://www.npmjs.com/package/@bananaseed/event_stream) to coordinate interactions cleanly.\n\n---\n\n## Features\n\n- **Builder Pattern API**: Declaratively bind event sources to state mutations and side effects before starting the application runtime.\n- **Decoupled Event Handling**: Use both external event streams ([EventStream](https://www.npmjs.com/package/@bananaseed/event_stream)) and internal triggers as event sources.\n- **Context Injection**: Pass a shared, read-only context (e.g., config, database connections, I/O interfaces) to all event handlers.\n- **Type-Safe**: Built with TypeScript and designed for complete static type safety of state, context, and triggers.\n- **Modern Bundling**: Compiled into standard ESM (`.mjs`) and CommonJS (`.js`) formats using Vite, fully type-checked with TypeScript 6.0.\n\n---\n\n## Core Concepts\n\nPotassium applications are built around three main type parameters:\n\n1. **State**: The structure of your application's mutable state.\n2. **Context**: A read-only environment or dependency container (e.g., logger, API services) accessible by all handlers.\n3. **TriggerMap**: A record type of internally-triggerable named events mapped to their corresponding payload types.\n\n---\n\n## Installation\n\n```bash\nnpm install @bananaseed/potassium\n```\n\n---\n\n## Quick Start Example\n\nHere is a simple example showing how to build a stateful app using Potassium that handles keystrokes and maintains a history of input.\n\n```typescript\nimport { createApp, EventStream } from \"@bananaseed/potassium\";\n\n// 1. Define your Types\ntype State = {\n  text: string;\n};\n\ntype Context = {\n  logger: Console;\n};\n\ntype Triggers = {\n  reset: void;\n};\n\n// 2. Setup your Event Stream (e.g., listening to mock inputs)\nconst inputEvents = new EventStream<string>(listener => {\n  const timer = setInterval(() => listener(\"a\"), 1000);\n  return {\n    cancel() {\n      clearInterval(timer);\n    }\n  };\n});\n\n// 3. Instantiate the App Builder\nconst ctx: Context = { logger: console };\nconst builder = createApp<State, Context, Triggers>(ctx);\n\n// 4. Bind Handlers and Hooks\nbuilder.onStart(k => {\n  k.context.logger.log(\"Application started!\");\n});\n\n// Bind an external EventStream\nbuilder.bind(inputEvents, (k, char) => {\n  k.state.text += char;\n  k.context.logger.log(`Current Text: ${k.state.text}`);\n  \n  if (k.state.text.length >= 5) {\n    k.trigger(\"reset\");\n  }\n});\n\n// Bind an internal named trigger\nbuilder.bind(\"reset\", k => {\n  k.context.logger.log(\"Resetting state...\");\n  k.state.text = \"\";\n});\n\nbuilder.onStop(k => {\n  k.context.logger.log(\"Application stopped.\");\n});\n\n// 5. Start the Application\nconst finalState = await builder.start({ text: \"\" });\n```\n\n---\n\n## API Reference\n\n### `createApp`\n\nInitializes a new application builder.\n\n```typescript\nfunction createApp<State, TriggerMap = {}>(): Builder<State, void, TriggerMap>;\nfunction createApp<State, Context, TriggerMap = {}>(context: Context): Builder<State, Context, TriggerMap>;\n```\n\n### `Builder` Interface\n\nUse the `Builder` to configure your application prior to starting.\n\n#### `bind`\nBinds an external event stream or an internal trigger to a handler.\n```typescript\nbind<T>(eventStream: EventStream<T>, handler: Handler<App, T>): symbol;\nbind<K extends keyof TriggerMap>(triggerId: K, handler: Handler<App, TriggerMap[K]>): symbol;\n```\n- **Returns**: A unique `symbol` ID that can be passed to `unbind` to remove the handler at runtime.\n\n#### `onStart`\nRegisters a hook that is executed immediately when the app starts.\n```typescript\nonStart(handler: VoidHandler<App>): void;\n```\n\n#### `onStop`\nRegisters a hook that runs when the application is stopped.\n```typescript\nonStop(handler: VoidHandler<App>): symbol;\n```\n\n#### `start`\nStarts the runtime loop with the provided initial state. Returns a promise that resolves with the final state when the application stops.\n```typescript\nstart(initialState: State): Promise<State>;\n```\n\n---\n\n### `App` Interface\n\nPassed as the first argument to all handlers, representing the running application instance.\n\n#### `state`\nThe current mutable state of your application. Directly modify properties here to mutate state.\n```typescript\nstate: State;\n```\n\n#### `context`\nThe read-only context configuration passed into `createApp`.\n```typescript\nreadonly context: Context;\n```\n\n#### `trigger`\nTriggers a named event internally, firing all matching trigger handlers configured on the builder.\n```typescript\ntrigger<K extends keyof TriggerMap>(triggerId: K, payload: TriggerMap[K]): void;\n```\n\n#### `unbind`\nRemoves a registered handler or stream listener dynamically at runtime.\n```typescript\nunbind(id: symbol): boolean; // Unbinds event stream or onStop handler\nunbind<K extends keyof TriggerMap>(triggerId: K, id: symbol): boolean; // Unbinds trigger handler\n```\n\n#### `stop`\nStops the application, triggers all `onStop` handlers, cancels all active `EventStream` listeners, and resolves the promise returned by `start()`.\n```typescript\nstop(): void;\n```\n\n---\n\n## Development & Building\n\nThe project uses [Vite](https://vite.dev/) in Library Mode and targets modern ESM and CommonJS runtimes.\n\n### Script Commands\n\n- **Build Output**: `npm run build`\n  Compiles the project and outputs built files to `dist/`:\n  - `dist/main.js` (CommonJS build)\n  - `dist/main.mjs` (ES Module build)\n  - `dist/main.d.ts` (Bundled type declarations)\n- **Watch Mode**: `npm run watch`\n  Runs Vite in watch mode to automatically rebuild on file changes.\n- **Type Checking**: `npm run check`\n  Performs full type-checking using `tsc --noEmit` over all source and test files.\n- **Run Integration Tests**: `npm test`\n  Launches the interactive CLI REPL test application using `ts-node`.\n","readmeFilename":"README.md"}