{"id":20509735,"url":"https://github.com/aminnairi/lemonade","last_synced_at":"2026-05-21T16:06:40.977Z","repository":{"id":42887615,"uuid":"254158129","full_name":"aminnairi/lemonade","owner":"aminnairi","description":":lemon: Node.js implementation of some monads found in Elm.","archived":false,"fork":false,"pushed_at":"2023-01-06T03:12:19.000Z","size":438,"stargazers_count":0,"open_issues_count":10,"forks_count":0,"subscribers_count":3,"default_branch":"latest","last_synced_at":"2025-01-16T08:37:01.772Z","etag":null,"topics":["err","just","maybe","monad","nothing","ok","result","task"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/aminnairi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-08T17:39:01.000Z","updated_at":"2020-04-12T11:04:49.000Z","dependencies_parsed_at":"2023-02-05T04:45:41.912Z","dependency_job_id":null,"html_url":"https://github.com/aminnairi/lemonade","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminnairi%2Flemonade","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminnairi%2Flemonade/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminnairi%2Flemonade/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminnairi%2Flemonade/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aminnairi","download_url":"https://codeload.github.com/aminnairi/lemonade/tar.gz/refs/heads/latest","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242112360,"owners_count":20073572,"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":["err","just","maybe","monad","nothing","ok","result","task"],"created_at":"2024-11-15T20:26:16.964Z","updated_at":"2026-05-21T16:06:35.942Z","avatar_url":"https://github.com/aminnairi.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# :lemon: lemonade\n\nNode.js implementation of some monads found in Elm.\n\n## :package: Requirements\n\n- [Node.js](https://nodejs.org/en/)\n\n## :arrow_down: Installation\n\n```console\n$ npm install aminnairi/lemonade\n```\n\n## :sparkles: Examples\n\n### :thinking: Maybe\n\n```javascript\nconst { Maybe: { Nothing, Just } } = require(\"@aminnairi/lemonade\");\n\nconst divide = (a, b) =\u003e b === 0 ? Nothing() : Just(a / b);\n\nconst goodDivision = divide(1, 2)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 2))\n    .map(x =\u003e x + 1)\n    .withDefault(0);\n\nconst badDivision = divide(1, 0)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 2))\n    .map(x =\u003e x + 1)\n    .withDefault(0);\n\nconst anotherBadDivision = divide(1, 2)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 0))\n    .map(x =\u003e x + 1)\n    .withDefault(0);\n\nconsole.log(goodDivision);          // 1.75\nconsole.log(badDivision);           // 0\nconsole.log(anotherBadDivision);    // 0\n```\n\n### :ok_hand: Result\n\n```javascript\nconst { Result: { Ok, Err } } = require(\"@aminnairi/lemonade\");\n\nconst divide = (a, b) =\u003e b === 0 ? Err(\"division by zero\") : Ok(a / b);\n\ndivide(1, 2)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 2))\n    .map(x =\u003e x + 1)\n    .when({ Ok: console.log, Err: console.error })\n    // 1.75\n\ndivide(1, 2)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 0))\n    .map(x =\u003e x + 1)\n    .when({ Ok: console.log, Err: console.error })\n    // division by zero\n\ndivide(1, 0)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 0))\n    .map(x =\u003e x + 1)\n    .when({ Ok: console.log, Err: console.error })\n    // division by zero\n\ndivide(1, 0)\n    .map(x =\u003e x + 1)\n    .andThen(x =\u003e divide(x, 0))\n    .map(x =\u003e x + 1)\n    .withDefault(-1);\n    // -1\n```\n\n### :construction_worker: Task\n\n```javascript\nconst { Task: { Task } } = require(\"@aminnairi/lemonade\");\n\nTask(() =\u003e fetch(\"https://jsonplaceholder.typicode.com/users/1\"))\n    .map(response =\u003e response.json())\n    .andThen(({ id }) =\u003e Task(() =\u003e fetch(`https://jsonplaceholder.typicode.com/posts?userId=${id}`)))\n    .map(response =\u003e response.json())\n    .map(([ post ]) =\u003e post.title)\n    .when({ Ok: console.log, Err: console.error })\n    // sunt aut facere repellat provident occaecati excepturi optio reprehenderit\n\nTask(() =\u003e \"Hello\")\n    .map(string =\u003e string + \" world\")\n    .andThen((string) =\u003e Task(() =\u003e string + \"!\"))\n    .when({ Ok: console.log, Err: console.error });\n    // \"Hello world!\"\n\nTask(() =\u003e \"Hello\")\n    .map(string =\u003e string + \" world\")\n    .andThen(string =\u003e Task(() =\u003e string + \"!\"))\n    .perform();\n    // Promise { \u003cpending\u003e }\n\nTask(() =\u003e 1)\n    .fork([\n        task =\u003e task.map(x =\u003e x + 1).when({Err: console.error, Ok: console.log}), // 2\n        task =\u003e task.map(x =\u003e x + 2).when({Err: console.error, Ok: console.log}) // 3\n    ])\n    .when({Err: console.error, Ok: console.log}); // 1\n```\n\n### Task X Express\n\n```javascript\n\"use strict\";\n\nconst {Task: {Task}} = require(\"@aminnairi/lemonade\");\nconst express = require(\"express\");\nconst fetch = require(\"node-fetch\");\n\nconst application = express();\nconst user = id =\u003e Task(() =\u003e fetch(`https://jsonplaceholder.typicode.com/users/${id}`));\nconst postsByUser = id =\u003e Task(() =\u003e fetch(`https://jsonplaceholder.typicode.com/posts?userId=${id}`));\nconst responseToJson = response =\u003e response.json();\n\napplication.get(\"/users/:id/posts\", (request, response) =\u003e {\n    user(request.params.id)\n        .map(responseToJson)\n        .andThen(({id}) =\u003e postsByUser(id))\n        .map(responseToJson)\n        .when({\n            Err: error =\u003e response.status(404).send(error),\n            Ok: posts =\u003e response.json(posts)\n        });\n});\n\napplication.listen(8080, () =\u003e console.log(\"http://localhost:8080\"));\n\n// curl localhost:8080/users/1/posts\n// [{...}, {...}, ...]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faminnairi%2Flemonade","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faminnairi%2Flemonade","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faminnairi%2Flemonade/lists"}