{"id":13509741,"url":"https://github.com/bobfp/skooma","last_synced_at":"2026-02-20T16:01:33.795Z","repository":{"id":57548877,"uuid":"113709455","full_name":"bobfp/skooma","owner":"bobfp","description":"Elixir data validation library","archived":false,"fork":false,"pushed_at":"2022-10-03T20:42:41.000Z","size":43,"stargazers_count":141,"open_issues_count":9,"forks_count":14,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-02-19T23:50:29.229Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","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/bobfp.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":"2017-12-09T23:44:47.000Z","updated_at":"2025-01-08T08:10:29.000Z","dependencies_parsed_at":"2022-08-28T11:31:34.010Z","dependency_job_id":null,"html_url":"https://github.com/bobfp/skooma","commit_stats":null,"previous_names":["bcoop713/skooma"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bobfp/skooma","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobfp%2Fskooma","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobfp%2Fskooma/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobfp%2Fskooma/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobfp%2Fskooma/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bobfp","download_url":"https://codeload.github.com/bobfp/skooma/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bobfp%2Fskooma/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637915,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":[],"created_at":"2024-08-01T02:01:12.199Z","updated_at":"2026-02-20T16:01:33.770Z","avatar_url":"https://github.com/bobfp.png","language":"Elixir","funding_links":[],"categories":["Validations"],"sub_categories":[],"readme":"# Skooma\n\n[![Hex.pm](https://img.shields.io/hexpm/v/skooma.svg)](https://hex.pm/packages/skooma)\n[![Build Status](https://travis-ci.org/bcoop713/skooma.svg?branch=master)](https://travis-ci.org/bcoop713/skooma)\n\n\u003e Simple data validation library for elixir.\n\nSkooma was developed to be used to describe and validate the incoming and outgoing data structures from a REST API, but it can easily be used throughout a code base. No one likes writing data schemas, so the main focus during development was to develop an API that allowed for quick and simple schema creation.\n\n## Table of Contents\n- [Installation](#installation)\n- [Overview](#overview)\n- [Basics](#basics)\n- [Complex Schemas](#complex-schemas)\n- [Error Handling](#error-handling)\n- [Validators](#validators)\n- [Custom Validators](#custom-validators)\n- [Contributions](#contributions)\n- [License](#license)\n\n## Installation\n\nThe package can be installed\nby adding `skooma` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:skooma, \"~\u003e 0.2.0\"}\n  ]\nend\n```\n\n## Overview\n\nSkooma exposes the function `valid?/2` \n\n```elixir\ndata = %{\n  :race =\u003e \"Khajiit\",\n  :name =\u003e \"Bob\",\n  :level =\u003e 6,\n  \"potions\" =\u003e [\"Skooma\", \"Fortify Health\", \"Fortify Magicka\"]\n  \n}\nschema = %{\n  :race =\u003e :string,\n  :name =\u003e :string,\n  :level =\u003e :int,\n  :gender =\u003e [:atom, :not_required]\n  \"potions\" =\u003e [:list, :string],\n}\nSkooma.valid?(data, schema)\n# :ok\n```\n\n## Basics\n\nSkooma supports all of the elixir data types:\n\n#### Boolean\n```elixir\ndata = false\nschema = :bool\nSkooma.valid?(data, schema) #:ok\n```\n\n#### String\n```elixir\ndata = \"test\"\nschema = :string\nSkooma.valid?(data, schema) #:ok\n```\n\n#### Integer\n```elixir\ndata = 7\nschema = :int\nSkooma.valid?(data, schema) #:ok\n```\n\n#### Float\n```elixir\ndata = 3.14\nschema = :float\nSkooma.valid?(data, schema) #:ok\n```\n\n#### Number\n```elixir\ndata = 1.41\nschema = :number\nSkooma.valid?(data, schema) #:ok\n```\n\n#### Atom\n```elixir\ndata = :thing\nschema = :atom\nSkooma.valid?(data, schema) #:ok\n```\n\n#### Map\n\n```elixir\ndata = %{\n  :race =\u003e \"Khajiit\",\n  \"level\" =\u003e 6,\n}\nschema = %{\n  :race =\u003e :string,\n  \"level\" =\u003e :int,\n}\nSkooma.valid?(data, schema) # :ok\n```\n\n#### List\n```elixir\ndata = [1, 2, 3]\nschema = [:list, :int]\nSkooma.valid?(data, schema) # :ok\n```\n\n#### Tuple\n```elixir\ndata = {456.89, 365.65}\nschema = {:float, :float}\nSkooma.valid?(data, schema) # :ok\n```\n\n#### Keyword List\n```elixir\ndata = [key1: \"value1\", key2: 2, key3: :atom3]\nschema = [key1: :string, key2: :int, key3: :atom]\nSkooma.valid?(data, schema) # :ok\n```\n\n## Complex Schemas\n\n#### Not Required\nSometimes, you want a field to be optional. In this case, use the `:not_required` atom.\n```elixir\ndata = %{\"key2\" =\u003e 3}\nschema = %{:key1 =\u003e [:string, :not_required], \"key2\" =\u003e :int}\nSkooma.valid?(data, schema) # :ok\n```\nA nil value will also pass if `:not_required` is invoked\n```elixir\ndata = %{:key1 =\u003e nil, \"key2\" =\u003e 3}\nschema = %{:key1 =\u003e [:string, :not_required], \"key2\" =\u003e :int}\nSkooma.valid?(data, schema) # :ok\n```\n\n#### Complex Maps\nSkooma schemas can be nested and combined to match any data strucutre.\n```elixir\nmy_hero = %{\n  race: \"Khajiit\",\n  stats: %{\n    hp: 100,\n    magicka: 60,\n    xp: 5600\n  }\n}\nschema = %{\n  race: :string,\n  stats: %{\n    hp: :int,\n    magicka: :int,\n    xp: :int\n  }\n}\nSkooma.valid?(my_hero, schema) # :ok\n```\nFor flexibilty and incase of recursive data structures, functions that return maps can also be used. In this case, the `:map` type must be explicitly used\n```elixir\nmy_hero = %{\n  name: \"Alkosh\"\n  race: \"Khajiit\",\n  friends: [ \n    %{name: \"Asurah\", race: \"Khajiit\"}, \n    %{name: \"Carlos\", race: \"Dwarf\"}\n  ]\n}\n\ndef hero_schema() do\n  %{\n    name: :string,\n    race: :string,\n    friends: [:list, :map, :not_required, \u0026hero_schema/0]\n   }\nend\nSkooma.valid?(my_hero, hero_schema) # :ok\n```\n\n#### Union Types\nSkooma also lets you supply a list of schemas to allow for flexible data structures\n```elixir\ndata1 = %{key1: \"value1\"}\ndata2 = 8\n\nschema = [:union, [%{key1: :string}, :int]]\n\nSkooma.valid?(data1, schema) # :ok\nSkooma.valid?(data2, schema) # :ok\n```\n\n## Error Handling\nIf a the data and schema passed to `valid?/2` match, an `:ok` will be returned.\n\nIf a match isn't made, `valid?/2` returns something of the form `{:error, [\"Error Mesasge 1\", \"Error Message 2\"...])`\n\nA few examples are:\n```elixir\ndata = 7\nschema = [:string]\nSkooma.valid?(data, schema) # {:error, [\"Expected STRING, got INTEGER 7\"]}\n```\n```elixir\ndata = %{\n  :key1 =\u003e \"value1\",\n  \"key2\" =\u003e %{color: \"blue\"},\n  \"things\" =\u003e [\"thing1\", 5],\n  \"stuff\" =\u003e %{key3: %{key4: 9}}\n}\nschema = %{\n  :key1 =\u003e [:string],\n  \"key2\" =\u003e [:map, %{color: [:string]}],\n  \"things\" =\u003e [:list, :string],\n  \"stuff\" =\u003e %{key3: %{key4: [:string]}}\n}\nSkooma.valid?(data, schema) # =\u003e \n# {:error, [\n#  \"Expected STRING, got INTEGER 9, at stuff -\u003e key3 -\u003e key4\",\n#  \"Expected STRING, got INTEGER 5, at things -\u003e index 1\"\n# ]}\n```\n\n## Validators\nSkooma comes with a few additional functions that can be used to perform more complex validation.\n```elixir\ndata = \"abc\"\nschema = [:string, Validators.min_length(4)]\nSkooma.valid?(data, schema) # {:error, [\"String must be longer than 4 characters\"]}\n```\n\nMultiple validators can also be used at the same time:\n```elixir\ndata = \"duck\"\nschema = [:string, Validators.regex(~r/foo/), Validators.max_length(5)]\nSkooma.valid?(data, schema) # {:error, [\"String does not match the regex pattern: ~r/foo/\"]}\n```\n\n## Custom Validators\nThere is nothing special about the validator functions that Skooma comes with. Making your own is super easy.\n\nThere are two types of custom validators. The most barebones is any function that accepts one argument and returns a boolean:\n```elixir\ndata = 8\nschema = [:int, \u0026(\u00261 == 0)]\nSkooma.valid?(data, schema) # {:error, [\"Value does not match custom validator\"]}\n```\n\nHowever, if you need more flexibility or a custom error message, instead of returning a boolean, your function should return either `:ok` or `{:error, \"Your Custom Error Message\"}`. Take the built it max_length validator as an example:\n```elixir\ndef max_length(max) do\n    fn (data) -\u003e\n      bool = String.length(data) \u003c= max\n      if bool do\n        :ok\n      else\n        {:error, \"String must be shorter than #{max} characters\"}\n      end\n    end\nend\n\ndata = \"abcdefghijk\"\nschema = [:string, Validators.max_length(7)]\nSkooma.valid?(data, schema) # {:error, [\"String must be shorter than 7 characters\"]}\n```\n\n## Contributions\nAll contributions are welcome. If there is a validator you would like to see added to the library, please create an issue!\n\n## License\n\n[MIT](LICENSE) \u0026copy; bcoop713\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobfp%2Fskooma","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbobfp%2Fskooma","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbobfp%2Fskooma/lists"}