{"id":13727253,"url":"https://github.com/phenax/algebraic-effects","last_synced_at":"2025-04-06T22:06:11.430Z","repository":{"id":34304342,"uuid":"165419394","full_name":"phenax/algebraic-effects","owner":"phenax","description":"Manage side-effects in your javascript application cleanly with algebraic effects","archived":false,"fork":false,"pushed_at":"2023-01-26T05:44:21.000Z","size":3063,"stargazers_count":208,"open_issues_count":29,"forks_count":13,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T21:14:27.682Z","etag":null,"topics":["algebraic-effects","effects","functional-programming","generators","javascript","side-effects"],"latest_commit_sha":null,"homepage":"https://phenax.github.io/algebraic-effects","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phenax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"phenax","custom":["https://www.buymeacoffee.com/phenax"]}},"created_at":"2019-01-12T18:05:26.000Z","updated_at":"2025-02-26T03:59:17.000Z","dependencies_parsed_at":"2023-02-14T14:31:30.740Z","dependency_job_id":null,"html_url":"https://github.com/phenax/algebraic-effects","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phenax%2Falgebraic-effects","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phenax%2Falgebraic-effects/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phenax%2Falgebraic-effects/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phenax%2Falgebraic-effects/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phenax","download_url":"https://codeload.github.com/phenax/algebraic-effects/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247557767,"owners_count":20958047,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algebraic-effects","effects","functional-programming","generators","javascript","side-effects"],"created_at":"2024-08-03T01:03:46.335Z","updated_at":"2025-04-06T22:06:11.412Z","avatar_url":"https://github.com/phenax.png","language":"TypeScript","readme":"\n# Algebraic Effects\nManage your effects in a pure and composible way using algebraic effects with multiple continuations. [https://phenax.github.io/algebraic-effects](https://phenax.github.io/algebraic-effects)\n\n[![CircleCI](https://img.shields.io/circleci/project/github/phenax/algebraic-effects/master.svg?style=for-the-badge)](https://circleci.com/gh/phenax/algebraic-effects)\n[![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@algebraic-effects/core.svg?style=for-the-badge)](https://www.npmjs.com/package/@algebraic-effects/core)\n[![Codecov](https://img.shields.io/codecov/c/github/phenax/algebraic-effects.svg?style=for-the-badge)](https://codecov.io/gh/phenax/algebraic-effects)\n\n\n\u003ca href=\"https://liberapay.com/phenax/donate\"\u003e\u003cimg alt=\"Donate using Liberapay\" src=\"https://liberapay.com/assets/widgets/donate.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.buymeacoffee.com/phenax\"\u003e\u003cimg src=\"https://img.shields.io/badge/buy%20me%20a%20coffee-yellow.svg?style=for-the-badge\" alt=\"Buy Me A Coffee donate button\" /\u003e\u003c/a\u003e\n\n[Documentation](https://phenax.github.io/algebraic-effects)\n\n\n## Install\n\n### To add the project to your project\n```bash\nyarn add @algebraic-effects/core\n```\n\nIf you want effects like Exception, State, Random, etc.\n```bash\nyarn add @algebraic-effects/core @algebraic-effects/effects\n```\n\n\n## Usage\n\n### Import it to your file\n```js\nimport { createEffect, func } from '@algebraic-effects/core';\nimport { sleep } from '@algebraic-effects/core/generic';\n```\n\n\n### State effect counter example\n\n```js\nimport { State } from '@algebraic-effects/effects';\nimport { call, sleep } from '@algebraic-effects/core/generic';\n\nconst countdown = function*() {\n  const count = yield State.get();\n\n  if(count \u003e 0) {\n    yield State.set(count - 1); // Decrement count\n    yield sleep(1000); // Add a delay of 1 second\n    yield call(countdown); // Recursively call the program again.\n  }\n}\n\nState.of(10)(countdown)\n  .fork(() =\u003e {}, () =\u003e alert('HAPPY NEW YEAR!!!!'));\n```\n\n\n### Creating your own effects\n\n* Declare your effects\n```js\nimport { createEffect, func } from '@algebraic-effects/core';\n\nexport const ConsoleEffect = createEffect('ConsoleEffect', {\n  log: func(['...data']),\n});\n\nexport const ApiEffect = createEffect('ApiEffect', {\n  fetchUser: func(['userid'], 'user'),\n  markUserAsViewed: func(['userid']),\n});\n```\n`func` function allows you to document the operation signature.\n\n\n\n* Write your program\n```js\nconst fetchProfile = function*(uid) {\n  const user = yield ApiEffect.fetchUser(uid);\n\n  yield ConsoleEffect.log('\u003e\u003e Fetched user user', uid);\n\n  if(user.isPublic) {\n    yield ApiEffect.markUserAsViewed(user.id);\n    yield ConsoleEffect.log('\u003e\u003e Marked', uid, 'as viewed');\n    return user;\n  }\n\n  return { id: uid, name: user.name, isPrivate: true };\n}\n```\n\n\n* Implement effect operation behavior\n```js\nconst logger = ConsoleEffect.handler({\n  log: ({ resume }) =\u003e (...args) =\u003e {\n    console.log(...args);\n    resume();\n  },\n});\n\nconst api = ApiEffect.handler({\n  markUserAsViewed: ({ resume, throwError }) =\u003e\n    uid =\u003e fetchJson(`/user/${uid}/mark-as-viewed`).then(resume).catch(throwError),\n  fetchUser: ({ promise }) =\u003e uid =\u003e promise(fetchJson(`/user/${uid}`)),\n});\n```\n`promise` is a shorthand for doing `.then(resume).catch(throwError)`\n\n\n* Calling your program\n```js\napi.with(logger) // Compose your effect handlers together and run them\n  .run(fetchProfile)\n  .fork(\n    e =\u003e { /* Handle error */ },\n    user =\u003e { /* Handle success */ }\n  )\n```\n\n\n\n### Multiple continuations\nYou can call resume multiple times from your operation synchronously.\n\n```js\nfunction flipCoins() {\n  const isHead1 = yield Random.flipCoin(2);\n  const isHead2 = yield Random.flipCoin(2);\n  return [isHead1 ? 'H' : 'T', isHead2 ? 'H' : 'T'];\n}\n\n// // runMulti method will start your program in multiple continuations mode\nRandom.seed(10)\n  .runMulti(flipCoins)\n  .fork(identity, data =\u003e {\n    console.log(data); // Probably [[H, T], [H, T], [T, H], [T, T]]\n  });\n```\n\n\n##### Writing custom effect with multiple continuations\n\n```js\nconst ListEffect = createEffect('ListEffect', {\n  takeItem: func(['list'], '*', { isMulti: true }), // isMulti flag indicates that this operation resumes multiple times\n});\n\n// Program will resolve with [3, 4, 6, 7]\nfunction *program() {\n  const item1 = yield ListEffect.takeItem([ 1, 4 ]);\n  const item2 = yield ListEffect.takeItem([ 2, 3 ]);\n\n  return item1 + item2;\n}\n\nconst looper = ListEffect.handler({\n  takeItem: ({ resume }) =\u003e list =\u003e list.forEach(resume),\n});\n\n// runMulti method will start your program in multiple continuations mode\nlooper.runMulti(program).fork(\n  handleError,\n  data =\u003e {\n    console.log(data); // [3, 4, 6, 7]\n  }\n);\n```\n\n\n## Contributing\n\n* [Code of Conduct](./CODE_OF_CONDUCT.md)\n\n* [Contributing Guide](./CONTRIBUTING.md)\n\n* [Good first issues/Help wanted](https://github.com/phenax/algebraic-effects/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+label%3A%22help+wanted%22)\n\n\n### License\nAlgebraic effects is under [MIT licensed](./LICENSE).\n","funding_links":["https://github.com/sponsors/phenax","https://www.buymeacoffee.com/phenax","https://liberapay.com/phenax/donate"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphenax%2Falgebraic-effects","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphenax%2Falgebraic-effects","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphenax%2Falgebraic-effects/lists"}