{"id":48162175,"url":"https://github.com/hbel/tsmonads","last_synced_at":"2026-04-04T17:26:14.297Z","repository":{"id":19155331,"uuid":"85592001","full_name":"hbel/tsmonads","owner":"hbel","description":"Monads in TypeScript","archived":false,"fork":false,"pushed_at":"2025-01-14T15:14:23.000Z","size":571,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-09T17:55:41.342Z","etag":null,"topics":["monad-types","monads","typescript"],"latest_commit_sha":null,"homepage":null,"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/hbel.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-20T15:14:32.000Z","updated_at":"2025-01-14T15:14:27.000Z","dependencies_parsed_at":"2025-01-11T15:44:58.682Z","dependency_job_id":null,"html_url":"https://github.com/hbel/tsmonads","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hbel/tsmonads","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hbel%2Ftsmonads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hbel%2Ftsmonads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hbel%2Ftsmonads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hbel%2Ftsmonads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hbel","download_url":"https://codeload.github.com/hbel/tsmonads/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hbel%2Ftsmonads/sbom","scorecard":{"id":458398,"data":{"date":"2025-08-11","repo":{"name":"github.com/hbel/tsmonads","commit":"fc0e0fcbc02a713d141a6b91f16f99e432e53163"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.1,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/15 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yaml:12","Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Warn: no topLevel permission defined: .github/workflows/release.yaml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/ci.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/ci.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/release.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yaml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/release.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yaml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/hbel/tsmonads/release.yaml/master?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release.yaml:9"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'master'","Warn: could not determine whether codeowners review is allowed","Warn: no status checks found to merge onto branch 'master'","Warn: PRs are not required to make changes on branch 'master'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T10:23:57.274Z","repository_id":19155331,"created_at":"2025-08-19T10:23:57.274Z","updated_at":"2025-08-19T10:23:57.274Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31407644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["monad-types","monads","typescript"],"created_at":"2026-04-04T17:26:13.632Z","updated_at":"2026-04-04T17:26:14.283Z","avatar_url":"https://github.com/hbel.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tsmonads\n\n### Monads in TypeScript\n\n_tsmonads_ provides some basic, strictly typed monadic data types for use with TypeScript, namely MayBe, Try and Either monads. It's API is heavily inspired by the according types in the Scala lanaguge API. It has **no** dependencies and can even be used (although without most of it's benefits) in JavaScript.\n\n# Install\n\ndeno: `deno add jsr:@itu/tsmonads`\n\nNPM: `npm install tsmonads`\n\nYarn: `yarn add tsmonads`\n\n# Usage\n\nSimply `import` the needed functions and classes from `\"tsmonad`.\n\n# Breaking changes in 4.x\n\n-   Several utitily functions are now more strict and may accept fewer input types.\n-   Overridden utility functions for specific monads (like empty, chain, and flatten) where moved into the monad's respective namespace to make them more usable.\n\n# Breaking changes in 3.x\n\n-   We improved statical type analysis in 3.0. This might lead to incompatibilities when using the library without checking the return values correctly.\n-   Global functions (map, flatMap) now return the correct type inferred from the incoming monad's type and the mapping function\n-   `unsafeLift()` was removed from all monads to ensure type safety\n-   Where default types are set for `Either::Left`, `Error` is now used instead of `string`\n\n# Application\n\n## Maybe\n\nA Maybe either contains _just_ a value or _nothing_. You can easily create new Maybe instances using the _maybe_ factory function:\n\n```\nimport {maybe} from \"tsmonads\";\n\nconst five = maybe(5); // Type of Maybe is infereed to be \"number\"\nconst n?: number;\n[...]\nconst maybeANumber = maybe(n); // maybeANumber will be a Maybe\u003cnumber\u003e. Wether it contains a value depends on n being a number or undefined.\nconst nothingAtAll = maybe\u003cnumber\u003e(null); // nothingAtAll is Nothing. The generic type has to given explicitly because it cannot be inferred from the argument.\n```\n\nYou can use _map()_ and _forEach()_ to transform the Maybe into another contained type or to perform side-effects on it's value. If the maybe is nothing, this is\na no-op.\n\n```\nimport {maybe} from \"tsmonads\";\nconst m = maybe(5);\nconst seven = m.map(x =\u003e x + 2);\nconst show = m.forEach(x =\u003e console.log(x));\n```\n\nYou can extract the value from a maybe safely by supplying a default to its _orElse()_-function. If you need more control, you can use _match()_ and suppy functions to handle the value and nothing case explicitly:\n\n```\nimport {maybe} from \"tsmonads\";\nconst m: Maybe\u003cnumber\u003e;\n[...]\nconst extractedValueOrZero = m.orElse(0);\nconst doSomethingWithTheValue = m.match(x =\u003e 2*x, () =\u003e -1);\n```\n\n## Try\n\nUse _Try_ to safely encapsulate a function call that may throw an exception. Try will either be a _Success_ wrapping the return value of the function or a _Failure_. Use try via the _call_ factory function.\n\n```\nimport {call} from \"tsmonads\";\nconst retVal = call(() =\u003e 2+5); // retVal is Success\u003cnumber\u003e(7)\nconst fail = call(() =\u003e throw \"Error\"); // retVal is Failure(\"Error\");\n```\n\nLike a Maybe, you can use map() and forEach() on a Try. For more control, supply functions to its _onSuccess()_ and _onFailure()_ handlers:\n\n```\nimport {call} from \"tsmonads\";\nconst retVal = call(() =\u003e 2+5);\nretVal.onSuccess(s =\u003e console.log(s)).onFailure(e =\u003e console.log(\"An error occured\"));\n```\n\nIf the Error encapsulated by the Failure doesn't matter to you, you can also convert the Try into a Maybe using its _toMaybe()_ method.\n\n## Either\n\nAn Either holds either a left or a right value. Usually, the left value denotes an error an the right value represents a successful result. Construct\nit using the _left()_ and _right()_ factory functions.\n\n## Further utility functions\n\nBesides the above functions, we also provide some utilities you can use when working with arrays of Monads. The `clean()` function will extract all values\nfrom the monads, throw away any non-values (Nothing, Failure, Left) and return an array of the extracted values. The `flatten()` function will turn an `Array\u003cMonad\u003cT\u003e\u003e` into a `Monad\u003cArray\u003cT\u003e\u003e`. Note that you will receive a \"negatively typed\" array if even single value in the original array is Nothing/Failure/Left. Otherwise, you'll get a `Just\u003cArray\u003cT\u003e\u003e`, `Success\u003cArray\u003cT\u003e\u003e` or `Right\u003cArray\u003cT\u003e\u003e`. All monad types provide a typed wrapper\nof flatten as a static method so you don't need to type-cast any results of the flatten method.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhbel%2Ftsmonads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhbel%2Ftsmonads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhbel%2Ftsmonads/lists"}