{"id":20504893,"url":"https://github.com/oxidizing/conformist","last_synced_at":"2025-04-13T20:52:10.707Z","repository":{"id":45067273,"uuid":"297048612","full_name":"oxidizing/conformist","owner":"oxidizing","description":"Schema definition and validation with support for decoding to bridge the gap between runtime types and static types.","archived":false,"fork":false,"pushed_at":"2022-04-06T11:46:22.000Z","size":164,"stargazers_count":35,"open_issues_count":1,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-27T11:21:08.506Z","etag":null,"topics":["decoder","ocaml","schema","schema-definitions","schema-validation"],"latest_commit_sha":null,"homepage":"https://v3.ocaml.org/p/conformist","language":"OCaml","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/oxidizing.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.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":"2020-09-20T10:07:31.000Z","updated_at":"2024-11-05T00:28:11.000Z","dependencies_parsed_at":"2022-09-03T02:43:38.484Z","dependency_job_id":null,"html_url":"https://github.com/oxidizing/conformist","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidizing%2Fconformist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidizing%2Fconformist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidizing%2Fconformist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxidizing%2Fconformist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxidizing","download_url":"https://codeload.github.com/oxidizing/conformist/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248782280,"owners_count":21160716,"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":["decoder","ocaml","schema","schema-definitions","schema-validation"],"created_at":"2024-11-15T19:41:04.774Z","updated_at":"2025-04-13T20:52:10.685Z","avatar_url":"https://github.com/oxidizing.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003c!-- \u003ca href=\"https://github.com/oxidizing/conformist\"\u003e --\u003e\n  \u003c!--   \u003cimg src=\"images/logo.jpg\" alt=\"Logo\" width=\"400\" height=\"240\"\u003e --\u003e\n  \u003c!-- \u003c/a\u003e --\u003e\n  \u003ch3 align=\"center\"\u003eConformist\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    Schema definition and validation with support for decoding to bridge the gap between runtime types and static types.\n    \u003cbr /\u003e\n    \u003ca href=\"https://oxidizing.github.io/conformist/conformist/Conformist/index.html\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n## Table of Contents\n\n* [About](#about)\n* [Installation](#installation)\n* [Usage](#usage)\n* [Documentation](#documentation)\n* [License](#license)\n* [Acknowledgements](#acknowledgements)\n\n## About\n\nConformist allows you to define schemas to decode, validate and sanitize input data declaratively. It comes with runtime types for primitive OCaml types such as `int`, `string`, `bool`, `float` and `Ptime.t`, `option` and custom types. Re-use business rules in validators and run it on the client side with [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml/). Arbitrary meta data can be stored in schemas which is useful to build functionality on top of conformist.\n\nTypical use cases are enforcing invariants of models or user input sanitization.\n\nIn essence, conformist helps you to keep your runtime types/contracts in sync with your static types.\n\n## Installation\n\n```sh\nopam install conformist\n```\n\nIn your `dune` file:\n\n```\n(executable\n  (name app)\n  (libraries\n   ...\n   conformist))\n```\n\n## Usage\n\nLet's look at an example.\n\n```ocaml\ntype occupation =\n  | Mathematician\n  | Engineer\n\ntype user =\n  { occupation : occupation\n  ; email : string\n  ; birthday : Ptime.t\n  ; nr_of_siblings : int\n  ; comment : string option\n  ; favorite_shows : string list\n  ; wants_premium : bool\n  }\n\nlet user\n    occupation\n    email\n    birthday\n    nr_of_siblings\n    comment\n    favorite_shows\n    wants_premium\n  =\n  { occupation\n  ; email\n  ; birthday\n  ; nr_of_siblings\n  ; comment\n  ; favorite_shows\n  ; wants_premium\n  }\n;;\n\nlet occupation_decoder = function\n  | [ \"mathematician\" ] -\u003e Ok Mathematician\n  | [ \"engineer\" ] -\u003e Ok Engineer\n  | _ -\u003e Error \"Unknown occupation provided\"\n;;\n\nlet occupation_encoder = function\n  | Mathematician -\u003e [ \"mathematician\" ]\n  | Engineer -\u003e [ \"engineer\" ]\n;;\n\n(* This is for example purpose only. \n   Please use emile (https://github.com/dinosaure/emile) instead *)\nlet validate_email value =\n  if String.index value '@' \u003e 0 then None\n  else Some \"This doesn't look like an email\"\n  \nlet user_schema =\n  Conformist.(\n    make\n      [ custom occupation_decoder occupation_encoder \"occupation\" ~meta:()\n      ; string \"email\" ~validator: validate_email\n      ; datetime \"birthday\"\n      ; int ~default:0 \"nr_of_siblings\"\n      ; optional (string \"comment\")\n      ; list (string \"favorite_shows\")\n      ; bool \"wants_premium\"\n      ]\n      user)\n;;\n\nlet input =\n  [ \"occupation\", [ \"engineer\" ]\n  ; \"email\", [ \"test@example.com\" ]\n  ; \"birthday\", [ \"2020-12-01T00:00:00.00Z\" ]\n  ; \"nr_of_siblings\", [ \"3\" ]\n  ; \"comment\", [ \"hello\" ]\n  ; \"favorite_shows\", [ \"Iron Man\"; \"Avengers\" ]\n  ; \"wants_premium\", [ \"true\" ]\n  ]\n;;\n\nlet user = Conformist.decode user_schema input\nlet validation_errors = Conformist.validate user_schema input\n```\n\nTry to delete/swap some lines of the list of fields, to change the constructor or the user type. The compiler forces you to keep these three things in sync.\n\nDecoding doesn't validate the data, it just makes sure that the types are correct and translates strings to the correct static types.\n\nNote that if decoding of a field fails, validation fails as well. Before a field is validated, it gets decoded.\n\nSince we are shadowing the list `[]`, dune warnings might fail compilation depending on the configuration. Suppress warning `-40` can help.\n\n## Documentation\n\nThe documentation for the latest released version can be found [here](https://v3.ocaml.org/p/conformist/0.6.0).\n\n## License\n\nCopyright (c) 2020 [Oxidizing Systems](https://oxidizing.io/)\n\nDistributed under the MIT License. See `LICENSE` for more information.\n\n## Acknowledgements\n\nThe implementation of this project was inspired by [archi](https://github.com/anmonteiro/archi) and [re-web](https://github.com/yawaramin/re-web).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidizing%2Fconformist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxidizing%2Fconformist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxidizing%2Fconformist/lists"}