{"id":35315733,"url":"https://github.com/coowry/baleen","last_synced_at":"2026-04-04T21:31:16.456Z","repository":{"id":57479236,"uuid":"97001679","full_name":"coowry/baleen","owner":"coowry","description":"Data validation in Erlang","archived":false,"fork":false,"pushed_at":"2019-05-27T08:31:40.000Z","size":1626,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"develop","last_synced_at":"2026-01-03T12:22:44.636Z","etag":null,"topics":["erlang","parsing","transformations","validation"],"latest_commit_sha":null,"homepage":"","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-4-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coowry.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","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":"2017-07-12T11:49:23.000Z","updated_at":"2024-05-31T17:21:57.000Z","dependencies_parsed_at":"2022-09-17T04:41:54.096Z","dependency_job_id":null,"html_url":"https://github.com/coowry/baleen","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/coowry/baleen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coowry%2Fbaleen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coowry%2Fbaleen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coowry%2Fbaleen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coowry%2Fbaleen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coowry","download_url":"https://codeload.github.com/coowry/baleen/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coowry%2Fbaleen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31415110,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T20:09:54.854Z","status":"ssl_error","status_checked_at":"2026-04-04T20:09:44.350Z","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":["erlang","parsing","transformations","validation"],"created_at":"2025-12-30T18:31:47.766Z","updated_at":"2026-04-04T21:31:16.426Z","avatar_url":"https://github.com/coowry.png","language":"Erlang","readme":"# Baleen\n\nData validation in Erlang\n\n## Introduction\n\nBaleen is a `rebar3` library in order to validate the content of the data that is being inputted\nto your programs.\n\n## Validators\n\nIn order to validate the data, Baleen uses validators, functions that ensures if the content is correct or not.\nOur definition of `validator`is a function that takes a data of `A` type and returns a `result(B)`,\nthis is, a tuple like `{ok, B}` or `{error, binary()}`. We'll explain later them in the Types section.\n\n## Types\n\nWe define 5 types:\n\n* result(R):\n\t\n\tIt's a tuple with the form `{ok, R}` or `{error, binary()}`, where the `binary()` is a message with a \n\tbrief explanation of why the data is invalid.\n\t\t\n* predicate(A):\n\n\tIt's a function that takes an `A` type and returns a `boolean()`.\n\n* str():\n\n\tIt's a type that can be a `binary()` or a `string()`.\n\t\n* val_map_validator(K, A, B):\n\n\tIt's a map with the next form:\n\t```erlang\n\t\t#{K =\u003e {optional | required, validator(A, B)}}\n\t```\n\twhere `K` is a `term()` type. It will be used in `val_map/2` as the first argument of the function.\n\n* val_map_result(K, B):\n\n\tIt's a map with the next form:\n\t```erlang\n\t\t#{valid =\u003e #{K =\u003e B},\n\t\t  nonvalid =\u003e #{K =\u003e binary()},\n\t\t  unexpected =\u003e [K],\n\t\t  missing =\u003e [K]}\n\t```\n\twhere the first value it's a map with the valid values, the second one it's a map with the values that couldn't be validated,\n\tthe third one it's a list where the keys that were unexpected, and the last one it's a list with the missing keys.\n\tIt will be used in `val_map/2` as the return of the function.\n\n## Functions\n\n### any(validator(A,B)) -\u003e validator(list(A), B)\n\nReturns a validator of a list of validators, the first that matches.\n\nExamples:\n```erlang\n1\u003e ValidatorList = baleen:any([baleen:invalid(), baleen:invalid(), baleen:valid()]).\n2\u003e baleen:validate(ValidatorList, 42).\n{ok, 42}\n```\n```erlang\n1\u003e Validator = baleen:any([baleen:max_length(0), baleen:to_atom(), baleen:to_float()]).\n2\u003e baleen:validate(Validator, \"Error\").\n{error,\u003c\u003c\"There isn't any valid\"\u003e\u003e}\n```\n\n### compose(nonempty_list(validator(A,A))) -\u003e validator(A,A)\n\nReturns a validator that is a composition of a list of validators.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:compose([baleen:max_length(10), baleen:to_integer(),baleen:validator(fun(I) -\u003e case is_integer(I) of true -\u003e {ok, I}; false -\u003e {error, \u003c\u003c\"Is not an integer\"\u003e\u003e} end end)]).\n2\u003e baleen:validate(Validator, \"12345\").\n{ok, 12345}\n3\u003e baleen:validate(Validator, 12345678900).\n{error,\u003c\u003c\"The size of \\\"12345678900\\\" is longer than 10\"\u003e\u003e}\n```\n\n\n### compose(validator(A, B), validator(B, C)) -\u003e validator(A, C)\n\nReturns a validator that is a composition of two validators.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:compose(baleen:max_length(140), baleen:to_atom()).\n2\u003e baleen:validate(Validator, \u003c\u003c\"Hello Mike\"\u003e\u003e).\n{ok,'Hello Mike'}\n```\n### invalid() -\u003e validator(_,_)\n\nReturns a validator that always fails.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:invalid().\n2\u003e baleen:validate(Validator, undefined).\n{error,\u003c\u003c\"Invalid term undefinded\"\u003e\u003e}\n```\n\n### list_of(validator(A,B)) -\u003e validator(list(A), list(B))\n\nReturns a validator that matches a list.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:list_of(baleen:to_integer()).\n2\u003e baleen:validate(Validator, [\"1\", \"2\", \"3\"]).\n{ok,[1,2,3]}\n3\u003e baleen:validate(Validator, [\"4\", \"Ooops\", \"6\"]).\n{error,\u003c\u003c\"Error in element \\\"Ooops\\\": \\\"Ooops\\\" is not an integer\"\u003e\u003e}\n```\n\n\n### literal(A) -\u003e validator(A, A)\n\nReturns a validator that matches only if the input is equals to `Term`.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:literal(42).\n2\u003e baleen:validate(Validator, 42).\n{ok, 42}\n```\n```erlang\n1\u003e Validator = baleen:literal(\"String\").\n2\u003e baleen:validate(Validator, \"string\").\n{error,\u003c\u003c\"\\\"String\\\" and \\\"string\\\" do not match\"\u003e\u003e}\n```\n\n\n### map_of(validator(K1, K2), validator(V1, V2)) -\u003e validator(#{K1 =\u003e V1}, #{K2 =\u003e V2})\n\nReturns a validator that validates a map, whose Keys are validated by `validator(K1, K2)`\nand Values are validated by `validator(V1, V2)`. \n\nExamples:\n```erlang\n1\u003e KeyValidator = baleen:to_atom().\n2\u003e ValueValidator = baleen:to_integer().\n3\u003e Validator = baleen:map_of(KeyValidator, ValueValidator).\n4\u003e baleen:validate(Validator, #{\u003c\u003c\"one\"\u003e\u003e =\u003e \"1\", \u003c\u003c\"two\"\u003e\u003e =\u003e \"2\", \u003c\u003c\"three\"\u003e\u003e =\u003e \"3\"}).\n{ok,#{one =\u003e 1,three =\u003e 3,two =\u003e 2}}\n5\u003e baleen:validate(Validator, #{one =\u003e \"1\", \u003c\u003c\"two\"\u003e\u003e =\u003e \"2\", \u003c\u003c\"three\"\u003e\u003e =\u003e \"3\"}).\n{error,\u003c\u003c\"Error in key one: one is not a valid string\"\u003e\u003e}\n6\u003e baleen:validate(Validator, #{\"one\" =\u003e \"1\", \u003c\u003c\"two\"\u003e\u003e =\u003e \"Two\", \u003c\u003c\"three\"\u003e\u003e =\u003e \"3\"}).\n{error,\u003c\u003c\"Error in value \\\"Two\\\": \\\"Two\\\" is not an integer\"\u003e\u003e}\n```\n\n\n### max_length(non_neg_integer()) -\u003e validator(S, S) when S :: iodata().\n\nReturns a validator that validates an input only if its length is less or equal than the integer is specified.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:max_length(50).\n2\u003e baleen:validate(Validator, \"A short message\").\n{ok,\"A short message\"}\n```\n```erlang\n1\u003e Validator = baleen:max_length(10).\n2\u003e baleen:validate(Validator, \"A long message\").\n{error,\u003c\u003c\"The size of \\\"A long message\\\" is longer than 10\"\u003e\u003e}\n```\n\n### member(list(A)) -\u003e validator(A, A)\n\nReturns a validator that matches only if the input is member of `L`.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:member([\"Hello\", 1, 0, -1, \"Bye\", atom]).\n2\u003e baleen:validate(Validator, atom).\n{ok, atom}\n3\u003e baleen:validate(Validator, 2).\n{error,\u003c\u003c\"2 is not member of [\\\"Hello\\\",1,0,-1,\\\"Bye\\\",atom]\"\u003e\u003e}\n```\n\n\n### predicate(predicate(A)) -\u003e validator(A,A)\n\nReturns a validator given a predicate of type `predicate`.\n\nExamples:\n```erlang\n1\u003e Pred = fun(X) -\u003e case is_atom(X) of true -\u003e true; false -\u003e false end end. \n2\u003e baleen:validate(baleen:predicate(Pred), atom).\n{ok, atom}\n3\u003e baleen:validate(baleen:predicate(Pred), 1).\n{error,\u003c\u003c\"Improper term 1\"\u003e\u003e}\n```\n\n\n### regex(String) -\u003e validator(String, String) when String :: str()\n\nReturns a validator given a regular expression.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:regex(\"^([0-9a-zA-Z]([-\\\\.\\\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,9})$\").\n2\u003e baleen:validate(Validator, \"user@email.com\").\n{ok, \"user@email.com\"}\n3\u003e baleen:validate(Validator, \"user.email.com\").\n{error,\u003c\u003c\"\\\"user.email.com\\\" is not matching the regular expression \\\"^([0-9a-zA-Z]([-\\\\\\\\.\\\\\\\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][\"...\u003e\u003e}\n```\n\n### to_atom() -\u003e validator(str(), atom())\n\nReturns a validator in order to cast to atom.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:to_atom().\n2\u003e baleen:validate(Validator, \u003c\u003c\"atom\"\u003e\u003e).\n{ok, atom}\n3\u003e Variable = 'String'. %% The atom must exists.\n4\u003e baleen:validate(Validator, \"String\").\n{ok, 'String'}\n5\u003e baleen:validate(Validator, \"Not a valid string\").\n{error,\u003c\u003c\"\\\"Not a valid string\\\" is not a valid string\"\u003e\u003e}\n```\n\n### to_float(str(), float())\n\nReturns a validator in order to cast to float.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:to_float().\n2\u003e baleen:validate(Validator, \u003c\u003c\"123.75646\"\u003e\u003e).\n{ok,123.75646}\n3\u003e baleen:validate(Validator, \"3.14159265359\").\n{ok,3.14159265359}\n4\u003e baleen:validate(Validator, \"Hello\").\n{error,\u003c\u003c\"\\\"\\\"Hello\\\"\\\" is not a float\"\u003e\u003e}\n```\n\n\n### to_integer() -\u003e validator(str(), integer())\n\nReturns a validator in order to cast to integer.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:to_integer().\n2\u003e baleen:validate(Validator, \"42\").\n{ok, 42}\n3\u003e baleen:validate(Validator, \u003c\u003c\"7\"\u003e\u003e).\n{ok, 7}\n4\u003e baleen:validate(Validator, \u003c\u003c\"Hello\"\u003e\u003e).\n{error,\u003c\u003c\"\u003c\u003c\\\"Hello\\\"\u003e\u003e is not an integer\"\u003e\u003e}\n```\n\n\n### transform(fun((A) -\u003e B)) -\u003e validator(A,B)\n\nReturns a validator that always success and applies `F`.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:transform(fun erlang:integer_to_list/1).\n2\u003e baleen:validate(Validator, 23).\n{ok, \"23\"}\n```\n\n### tuple_of(validator(A, B)) -\u003e validator({A}, {B})\n\nReturns a validator that matches a tuple.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:tuple_of(baleen:to_atom()).\n2\u003e baleen:validate(Validator, {\u003c\u003c\"hello\"\u003e\u003e, \u003c\u003c\"1234\"\u003e\u003e, \u003c\u003c\"bye\"\u003e\u003e}).\n{ok,{hello,'1234',bye}}\n3\u003e baleen:validate(Validator, {atom, \u003c\u003c\"1234\"\u003e\u003e, \u003c\u003c\"bye\"\u003e\u003e}).\n{error,\u003c\u003c\"Error in atom: atom is not a valid string\"\u003e\u003e}\n```\n\n\n### val_map(val_map_validator(K, A, B), #{K =\u003e A}) -\u003e val_map_result(K, B)\n\nReturns a map with the results of the validation of the maps passed as arguments.\n\nExamples:\n```erlang\n1\u003e ValidatorMap = #{msisdn =\u003e {required, baleen:regex(\"^\\\\+[1-9][0-9]{8,14}$\")},\n\t\t  email =\u003e {optional, baleen:regex(\"^([0-9a-zA-Z]([-\\\\.\\\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\\\w]*[0-9a-zA-Z]\\\\.)+[a-zA-Z]{2,9})$\")}\n\t\t }.\n2\u003e Map = #{email =\u003e \"user@email.com\", field =\u003e \"Some description\"}.\n3\u003e baleen:val_map(ValidatorMap, Map).\n#{missing =\u003e [msisdn],\n  nonvalid =\u003e #{},\n  unexpected =\u003e [field],\n  valid =\u003e #{email =\u003e \"user@email.com\"}}\n```\n\n\n### valid() -\u003e validator(_,_)\n\nReturns a validator that always success.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:valid().\n2\u003e baleen:validate(Validator, 1234).\n{ok, 1234}\n```\n\n\n### validate(validator(A,B), A) -\u003e result(B)\n\nValidates data with a validator.\n\nExamples:\n```erlang\n1\u003e baleen:validate(baleen:valid(), 42).\n{ok, 42}\n```\n\n### validator(fun((A) -\u003e result(B))) -\u003e validator(A,B)\n\nReturns a validator given a user defined function that validates.\n\nExamples:\n```erlang\n1\u003e Fun = fun(I) -\u003e case is_integer(I) of true -\u003e {ok, I}; false -\u003e {error, \u003c\u003c\"Is not an integer\"\u003e\u003e} end end.\n2\u003e Validator = baleen:validator(Fun).\n3\u003e baleen:validate(Validator, 23).\n{ok, 23}\n4\u003e baleen:validate(Validator, \"23\").\n{error, \u003c\u003c\"Is not an integer\"\u003e\u003e}\n```\n\n### to_string() -\u003e validator(str(), string())\n\nReturns a validator in order to cast to integer.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:to_string().\n2\u003e baleen:validate(Validator, \"Hello\").\n{ok, \"Hello\"}\n3\u003e baleen:validate(Validator, \u003c\u003c\"Hello\"\u003e\u003e).\n{ok, \"Hello\"}\n4\u003e baleen:validate(Validator, hello).\n{error,\u003c\u003c\"hello is not a string nor a binary\"\u003e\u003e}\n```\n\n### to_binary() -\u003e validator(str(), binary())\n\nReturns a validator in order to cast to integer.\n\nExamples:\n```erlang\n1\u003e Validator = baleen:to_binary().\n2\u003e baleen:validate(Validator, \"Hello\").\n{ok, \u003c\u003c\"Hello\"\u003e\u003e}\n3\u003e baleen:validate(Validator, \u003c\u003c\"Hello\"\u003e\u003e).\n{ok, \u003c\u003c\"Hello\"\u003e\u003e}\n4\u003e baleen:validate(Validator, hello).\n{error,\u003c\u003c\"hello is not a string nor a binary\"\u003e\u003e}\n```\n\n### between(integer(), integer()) -\u003e validator(integer(), integer())\n\nCheck if a Value is between (Min, Max).\n\nExamples:\n```erlang\n1\u003e Validator = baleen:between(1,4).\n#Fun\u003cbaleen.21.79860976\u003e\n2\u003e baleen:validate(Validator, 3).\n{ok,3}\n3\u003e baleen:validate(Validator, 1).\n{error,\u003c\u003c\"1 is not in range between (1, 4)\"\u003e\u003e}\n4\u003e baleen:validate(Validator, 4).\n{error,\u003c\u003c\"4 is not in range between (1, 4)\"\u003e\u003e}\n5\u003e baleen:validate(Validator, a).\n{error,\u003c\u003c\"a is not an integer\"\u003e\u003e}\n```\n\n### between_open_start(integer(), integer()) -\u003e validator(integer(), integer())\n\nCheck if a Value is between [Min, Max).\n\nExamples:\n```erlang\n1\u003e Validator = baleen:between_open_start(1,4).\n#Fun\u003cbaleen.22.79860976\u003e\n2\u003e baleen:validate(Validator, 2).\n{ok,2}\n3\u003e baleen:validate(Validator, 1).\n{ok,1}\n4\u003e baleen:validate(Validator, 4).\n{error,\u003c\u003c\"4 is not in range between [1, 4)\"\u003e\u003e}\n5\u003e baleen:validate(Validator, a).\n{error,\u003c\u003c\"a is not an integer\"\u003e\u003e}\n```\n\n### between_open_end(integer(), integer()) -\u003e validator(integer(), integer())\n\nCheck if a Value is between (Min, Max].\n\nExamples:\n```erlang\n1\u003e Validator = baleen:between_open_end(1,4).  \n#Fun\u003cbaleen.23.79860976\u003e\n2\u003e baleen:validate(Validator, 2).\n{ok,2}\n3\u003e baleen:validate(Validator, 4).\n{ok,4}\n4\u003e baleen:validate(Validator, 1).\n{error,\u003c\u003c\"1 is not in range between (1, 4]\"\u003e\u003e}\n5\u003e baleen:validate(Validator, a).\n{error,\u003c\u003c\"a is not an integer\"\u003e\u003e}\n```\n\n### between_open(integer(), integer()) -\u003e validator(integer(), integer())\n\nCheck if a Value is between [Min, Max].\n\nExamples:\n```erlang\n1\u003e Validator = baleen:between_open(1,4).    \n#Fun\u003cbaleen.24.79860976\u003e\n2\u003e baleen:validate(Validator, 2).       \n{ok,2}\n3\u003e baleen:validate(Validator, 1).\n{ok,1}\n4\u003e baleen:validate(Validator, 4).\n{ok,4}\n5\u003e baleen:validate(Validator, a).\n{error,\u003c\u003c\"a is not an integer\"\u003e\u003e}\n```\n\n## Installation and usage\n\nBaleen is a `rebar3` project:\n\nIf you want to use it and test it on your own, just clone the repository and type\n\n```console\nrebar3 shell\n```\n\nIf you want to use it in your code, just add the dependency in your `rebar.config` file:\n\n```erlang\n{deps, [\n\t{baleen, {git, \"https://github.com/coowry/baleen.git\"}}\n]}.\n```\n\n\n## License\n\nCopyright(c) 2017, Ángel Herranz, Miguel E. Ruiz.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n\n3. All advertising materials mentioning features or use of this software\n   must display the following acknowledgement:\n   This product includes software developed by Coowry Ltd .\n\n4. Neither the name of the copyright holders nor the names of its\n   contributors may be used to endorse or promote products derived from\n   this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS \"AS IS\" AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n## Inspiration\n\nBaleen is inspirated in [Saul](https://github.com/whatyouhide/saul), a data validation library for Elixir.\n\n## The name\n\n    Baleen is a filter-feeder system inside the mouths of baleen\n    whales. The baleen system works by a whale opening its mouth\n    underwater and taking in water.\n\n    https://en.wikipedia.org/wiki/Baleen\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoowry%2Fbaleen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoowry%2Fbaleen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoowry%2Fbaleen/lists"}