{"id":31550003,"url":"https://github.com/cullophid/barely-functional","last_synced_at":"2025-10-04T17:32:35.542Z","repository":{"id":84263780,"uuid":"47858117","full_name":"cullophid/barely-functional","owner":"cullophid","description":"tiny (2.7kb) functional programming library using native es5/6 operations","archived":false,"fork":false,"pushed_at":"2017-10-26T14:09:18.000Z","size":395,"stargazers_count":107,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-03T09:25:20.561Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cullophid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-12-12T00:40:31.000Z","updated_at":"2025-02-15T00:17:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"51efbd5e-9869-4e6d-a9ac-97c8a3708cc4","html_url":"https://github.com/cullophid/barely-functional","commit_stats":{"total_commits":58,"total_committers":5,"mean_commits":11.6,"dds":0.2931034482758621,"last_synced_commit":"52aab7771318e630d95de8b224d7141c770d04c2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cullophid/barely-functional","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cullophid%2Fbarely-functional","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cullophid%2Fbarely-functional/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cullophid%2Fbarely-functional/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cullophid%2Fbarely-functional/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cullophid","download_url":"https://codeload.github.com/cullophid/barely-functional/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cullophid%2Fbarely-functional/sbom","scorecard":{"id":312569,"data":{"date":"2025-08-11","repo":{"name":"github.com/cullophid/barely-functional","commit":"52aab7771318e630d95de8b224d7141c770d04c2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/27 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":"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"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":"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":"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"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":"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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-17T23:26:42.074Z","repository_id":84263780,"created_at":"2025-08-17T23:26:42.074Z","updated_at":"2025-08-17T23:26:42.074Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278346458,"owners_count":25972102,"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","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-10-04T17:31:17.017Z","updated_at":"2025-10-04T17:32:35.488Z","avatar_url":"https://github.com/cullophid.png","language":"JavaScript","readme":"# Barely Functional\n*A tiny functional programming library*\n\n**barely-functional** is a small, highly modular library for doing functional programming. It includes `curry`\nand `compose`, and wraps several native ES5 methods including `.map()` `.reduce()` and `.filter()` and several ES6\nmethods such as `.every()` and `.find()` with an iteratee first, autocurried API. Several \nnon-native functions inspired by (READ: stolen from) [ramdajs](http://ramdajs.com/) are also included.\n\n**barely-functional** also attempts to guard against unsafe operations by \nreturning a [`Maybe`](https://downloads.haskell.org/~ghc/7.4-latest/docs/html/libraries/base-4.5.1.0/Data-Maybe.html) for operations \nthat can fail. The `Maybe` type returned is compliant with the [Fantasy Land]\n(https://github.com/fantasyland/fantasy-land) specification. \n\nAll functions may be imported individually, thus reducing the footprint of the library even further:\n\n```js\nconst map = require('barely-functional/map')\n```\n\n\n## Installing\n\n`npm i barely-functional`\n\n## Using\n```js\nconst _ = require('barely-functional')\n\nconst sumOfEven = _.compose(_.sum, _.filter((e) =\u003e e % 2 === 0))\n```\n\n*Barely functional is written in es6. It will run on node.js v4.0 and up. If you wish to use it in the browser you need to use babel and (webpack/browserify)*\n\n\n## But ramda is way better...\nYes, it is, but it is also a lot bigger. If you a writing a small module, you might not want to include all of [Ramda](http://ramdajs.com).\n\n## API\n\n### append :: a -\u003e [a] -\u003e [a]\nAdds the specified value to the end of the supplied array.\n```js\n_.append(5, [1, 2, 3, 4]);\n// =\u003e [1, 2, 3, 4, 5]\n```\n\n### compose :: ((y -\u003e z), (x -\u003e y) ... (o -\u003e p)(a, b, ..., n -\u003e o)) -\u003e (a, b, ..., n -\u003e z)\nPerforms right-to-left function composition. The rightmost function may have any arity; the remaining functions must be unary.\n\n```js\nconst add1  =  (n) =\u003e n + 1\nconst double  =  (n) =\u003e n * 2\n\nconst add1AndDouble = _.compose(double, add1)\n\nadd1AndDouble(5)\n// =\u003e 12\n\n```\n\n### concat :: [a] -\u003e [a] - [a]\nConcatenates two arrays.\n```js\n_.concat([1, 2, 3], [4, 5, 6]);\n// =\u003e [1, 2, 3, 4, 5, 6];\n```\n\n### curry :: (\\* -\u003e a) -\u003e (\\s* -\u003e a)\nReturns a curried equivalent of the provided function. The curried function has two unusual capabilities. First, its arguments needn't be provided one at a time. If `f` is a ternary function and `g` is `_.curry(f)`, the following are equivalent:\n\n```js\nconst sum3 = _.curry((a, b, c) =\u003e a + b + c)\nsum3(1)(2)(3)\n// =\u003e 6\nsum3(1)(2, 3)\n// =\u003e 6\nsum3(1, 2)(3)\n// =\u003e 6\nsum3(1, 2, 3)\n// =\u003e 6\n```\n\n### drop :: Int -\u003e [a] -\u003e [a]\nReturns a new list without the first `n` elements\n\n```js\n_.drop(2, [1, 2, 3, 4])\n// =\u003e [3, 4]\n```\n\n### every :: (a -\u003e Boolean) -\u003e [a] -\u003e Boolean\nReturns true if every element in the list satisfies the predicate function.\n\n```js\n_.every(n =\u003e n \u003e 2, [2, 3, 4])\n// =\u003e false\n\n_.every(n =\u003e n \u003e 2, [3, 4, 5])\n// =\u003e true\n```\n\n### filter :: (a -\u003e Boolean) -\u003e [a] -\u003e [a]\nReturns a new list containing only the elements in the list that satisfy the predicate function.\n\n```js\n_.filter(n =\u003e n \u003e 2, [1, 2, 3, 4])\n// =\u003e [3, 4]\n```\n\n### find :: (a -\u003e Boolean) -\u003e [a] -\u003e Maybe a\nReturns `Just` the first element satisfying the predicate function. If no \nelement can be found it returns `Nothing()`.\n```js\n_.find(n =\u003e n % 2 === 0, [1, 2, 3, 4])\n// =\u003e Just(2)\n_.find(n =\u003e n % 2 === 0, [1, 3, 5])\n// =\u003e Nothing()\n```\n\n### findIndex :: (a -\u003e Boolean) -\u003e [a] -\u003e Maybe Int\nReturns `Just` the index of first element satisfying the predicate function. \nIf no element can be found it returns `Nothing()`.\n```js\n_.findIndex(n =\u003e n % 2 === 0, [1, 2, 3, 4])\n// =\u003e Just(1)\n_.findIndex(n =\u003e n % 2 === 0, [1, 3, 5])\n// =\u003e Nothing()\n```\n\n### fromMaybe :: a -\u003e Maybe a -\u003e a\nReturns a default if second argument is Nothing(); otherwise unwraps the Just.\n\n```js\n_.fromMaybe(5, Just(1))\n// =\u003e Just(1)\n_.fromMaybe(5, Nothing())\n// =\u003e 5\n```\n\n### has :: String -\u003e Object -\u003e Boolean\nReturns `true` if the given object has a property with the specified name; `false` otherwise.\n```js\n_.has('a', {a:2})\n// =\u003e true\n_.has('b', {a:2})\n// =\u003e false\n```\n\n### head :: [a] -\u003e a\nReturns the first element of a list.\n```js\n_.head([1, 2, 3])\n// =\u003e 1\n```\n\n### includes :: a -\u003e [a] -\u003e Boolean\nReturns `true` if the list includes the given element; `false` otherwise.\n```js\n_.includes('a', ['a', 'b', 'c'])\n// =\u003e true\n```\n\n### indexOf :: a -\u003e [a] -\u003e Maybe Int\nReturns `Just` the index of the specified element in the list. Returns \n`Nothing()` if the element is not in the list.\n```js\n_.indexOf(1, [0, 1, 2, 3])\n// =\u003e Just(1)\n_.indexOf(5, [0, 1, 2, 3])\n// =\u003e Nothing()\n```\n\n### init :: [a] -\u003e [a]\nReturns all elements of the list except the last.\n```js\n_.init([1, 2, 3, 4]])\n// =\u003e [1, 2, 3]\n```\n\n### join :: String -\u003e [a] -\u003e String\nReturns a string by concatenating all elements of the list interlaced with the specified string.\n\n```js\n_.join('|', ['a', 'b', 'c'])\n// =\u003e \"a|b|c\"\n```\n\n### keys :: Object -\u003e [String]\nReturns a list of the given object's keys.\n\n```js\n_.keys({a: 1, b: 2, c: 3})\n// =\u003e [\"a\", \"b\", \"c\"]\n```\n\n### last :: [a] -\u003e a\nReturns the last element of the list.\n\n```js\n_.last([1, 2, 3])\n// =\u003e 3\n```\n\n### length :: [a] | String | Function -\u003e Int\nReturns the length of a list / function / string.\n\n```js\n_.length([1, 2, 3])\n// =\u003e 3\n```\n\n### map :: (a -\u003e b) -\u003e [a] -\u003e [b]\nReturns a new list, constructed by applying the supplied unary function to every \nelement of the supplied list.\n\n```js\n_.map(n =\u003e n + 1, [1, 2, 3])\n // =\u003e [2, 3, 4]\n```\n\n### match :: RegExp -\u003e String -\u003e [String | void 0]\nTests a regular expression against a string and returns a list of matches.\n\n```js\n_.match(/a./g, 'falafel')\n// =\u003e ['al', 'af']\n```\n\n### merge :: Object -\u003e Object -\u003e Object\nMerges two objects into a new object; duplicate keys are resolved as last in wins. As per\n`Object.assign`, nested arrays and objects are copied by reference.\n\n```js\n_.merge({a: 1}, {b: 2});\n// =\u003e {a: 1, b: 2}\n\n_.merge({a: 1, b: 1}, {b: 2});\n// =\u003e {a: 1, b: 2}\n```\n\n### mergeAll :: [Object] -\u003e Object\nMerges a list of objects into a new object; duplicate keys are resolved as last in wins. As per\n`Object.assign`, nested arrays and objects are copied by reference.\n\n```js\n_.mergeAll([{a: 1}, {b: 2}, {c: 3}]);\n// =\u003e {a: 1, b: 2, c: 3}\n\n_.mergeAll([{a: 1}, {b: 2}, {b: 3}]);\n// =\u003e {a: 1, b: 3}\n```\n\n### nth :: Int -\u003e [a] -\u003e Maybe a\nReturns `Just` the `nth` element of a list. If the index queried is greater than\nthe length of the list then return `Nothing()`.\n```js\n_.nth(3, [1, 2, 3, 4, 5])\n// =\u003e Just(4)\n_.nth(10, [1, 2, 3, 4, 5])\n// =\u003e Nothing()\n```\n\n### pluck :: String -\u003e [Object] -\u003e [a | void 0]\nReturns the values associated with the provided key from each object in list of objects.\n\n```js\n_.pluck('a', [{a:1}, {a: 2}, {a: 3}])\n// =\u003e [1, 2, 3]\n```\n\n### prop :: String -\u003e Object -\u003e a\nReturns the value of the specified property from the given object.\n\n```js\n\n_.prop('msg', {msg: 'hello wold'})\n// =\u003e 'hello world'\n\n```\n### props :: [String] -\u003e Object -\u003e [a | void 0]\nReturns a list of values related to the specified properties.\n\n```js\n_.props(['a', 'b', 'c'], {a:1 b: 2, c: 3})\n// =\u003e [1, 2, 3]\n```\n\n### range :: Int -\u003e Int -\u003e [Int]\nReturns a list of all integers between the two specified numbers.\nThe last number is not included.\n\n```js\n_.range(3, 7)\n//=\u003e [3, 4, 5, 6]\n```\n\n### reduce :: (a -\u003e b -\u003e a) -\u003e a -\u003e [b] -\u003e a\nReturns a single item by iterating through the list, successively calling the iterator function and passing it an accumulator value and the current value from the array, and then passing the result to the next call.\nThe iterator function receives two values: (acc, value).\n\n```js\n_.reduce((a, b) =\u003e a + b, 10, [1, 2, 3])\n//=\u003e 16\n```\n\n### reduceRight :: (a -\u003e b -\u003e a) -\u003e a -\u003e [b] -\u003e a\nReturns a single item by iterating through the list, successively calling the iterator function and passing it an accumulator value and the current value from the array, and then passing the result to the next call.\n\nSimilar to reduce, except moves through the input list from the right to the left.\n\nThe iterator function receives two values: (acc, value)\n\n```js\n_.reduceRight((acc, value) =\u003e acc.concat(value), [], [1, 2, 3, 4, 5])\n// =\u003e [5, 4, 3, 2, 1]\n```\n\n\n### replace :: RegExp | String -\u003e String -\u003e String\nReturns a new string by replacing each substring or regex match with a replacement.\nWhen given a string as the first argument, only the first occurance of the substring will be replaced.\n\n```js\n_.replace(/\\d/g, 5, '1, 2, 3, 4')\n// =\u003e '5, 5, 5, 5'\n```\n### reverse :: [a] -\u003e [a]\nReturns a new list with the same elements in reverse order.\n\n```js\n_.reverse([1, 2, 3])\n// =\u003e [3, 2, 1]\n```\n\n### slice :: Int -\u003e Int -\u003e [a] -\u003e [a]\nReturns a new list containing only the elements from the first index (inclusive) to the last index (exclusive).\n\n```js\n_.slice(1, 4, [1, 2, 3, 4, 5])\n// =\u003e [2, 3, 4]\n```\n\n\n### some :: (a -\u003e Boolean) -\u003e [a] -\u003e Boolean\nReturns `true` if any of the elements in the list satisfy the predicate function.\n\n```js\n_.some(n =\u003e n \u003e 2, [0, 1, 2, 3])\n// =\u003e true\n_.some(n =\u003e n \u003e 2, [0, 1, 2])\n// =\u003e false\n```\n\n### sort :: [a] -\u003e [a]\nReturns a lexigraphically sorted copy of the given list.\n\n```js\n_.sort(['z', 'a', 'h', 'd'])\n// =\u003e ['a', 'd', 'h', 'z']\n```\n\n### sortBy :: (a -\u003e Int) -\u003e [a] -\u003e [a]\nReturns a sorted copy of the given list based on the sorting function.\n\n```js\n_.sortBy((a, b) =\u003e a - b, [2, 3, 1, 4])\n// =\u003e [1, 2, 3, 4]\n```\n\n### split :: String | RegExp -\u003e String -\u003e [String]\nReturns a list of strings based on the given separator.\n\n```js\n_.split(/\\d/, \"I have 3 apples and 2 oranges\")\n//=\u003e [\"I have \", \" apples and \", \" oranges\"]\n```\n\n### sum :: [Number] -\u003e Number\nReturns the sum of all numbers in the list.\n\n```js\n_.sum([1, 2, 3])\n// =\u003e 6\n```\n\n### tail :: [a] -\u003e [a]\nReturns a copy of the list without the first element.\n```js\n_.tail([1, 2, 3])\n//=\u003e [2, 3]\n```\n\n### take :: Int -\u003e [a] -\u003e [a]\nReturns the first `n` elements of a list.\n\n```js\n_.take(2, [1, 2, 3, 4])\n// =\u003e [1, 2]\n```\n\n### test :: RegExp -\u003e String -\u003e Boolean\nReturns `true` if the RegExp matches the string; `false` otherwise.\n\n```js\n_.test(/\\d/, 'I have 3 Apples')\n// =\u003e true\n_.test(/\\d/, 'I have three Apples')\n// =\u003e false\n```\n\n### toLowerCase :: String -\u003e String\nReturns a new string where all letters are lower case.\n\n```js\n_.toLowerCase('I have a dream')\n// =\u003e 'i have a dream'\n```\n\n### toMaybe :: a | null | void 0 -\u003e Maybe a\nReturns a Nothing if the supplied value is null; A Just otherwise.\n\n```js\n_.toMaybe(1)\n// =\u003e Just(1)\n_.toMaybe(null)\n// =\u003e Nothing\n```\n\n### toUpperCase :: String -\u003e String\nReturns a new string where all letters are upper case.\n\n```js\n_.toLowerCase('I have a dream')\n// =\u003e 'I HAVE A DREAM'\n```\n\n### trim :: String -\u003e String\nReturns a new string where all leading and trailing spaces have been removed.\n\n```js\n_.trim(' I have a dream   ')\n// =\u003e 'I have a dream'\n```\n\n### values :: Object -\u003e [a]\nReturns a list of all values in the given object.\n\n```js\n_.values({x: 1, y: 2, x: 3})\n// =\u003e [1, 2, 3]\n```\n\n## 2.2Kb is too big!\nbasic.js is just 1.1KB. It contains all the native es5/es6 functions as well as curry and compose.\n\n```js\nconst _ = require('barely-functional/basic')\n```\n","funding_links":[],"categories":["Libraries"],"sub_categories":["[Javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcullophid%2Fbarely-functional","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcullophid%2Fbarely-functional","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcullophid%2Fbarely-functional/lists"}