{"id":15010116,"url":"https://github.com/am-kantox/camarero","last_synced_at":"2025-04-09T22:41:32.835Z","repository":{"id":57481939,"uuid":"163257431","full_name":"am-kantox/camarero","owner":"am-kantox","description":"Semi-static JSON API Scaffold for Elixir","archived":false,"fork":false,"pushed_at":"2024-03-19T09:45:50.000Z","size":308,"stargazers_count":10,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-07T03:35:25.474Z","etag":null,"topics":["api-server","elixir","elixir-lang","json-api","webserver"],"latest_commit_sha":null,"homepage":"","language":"Elixir","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/am-kantox.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-27T06:41:06.000Z","updated_at":"2024-07-26T14:45:40.000Z","dependencies_parsed_at":"2024-03-17T09:25:39.513Z","dependency_job_id":"234cf862-fed6-473f-befd-b3792136ea22","html_url":"https://github.com/am-kantox/camarero","commit_stats":{"total_commits":91,"total_committers":2,"mean_commits":45.5,"dds":0.01098901098901095,"last_synced_commit":"ec4528ece6b39b531b4ecf3b630fddf0d47b6c8b"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/am-kantox%2Fcamarero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/am-kantox%2Fcamarero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/am-kantox%2Fcamarero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/am-kantox%2Fcamarero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/am-kantox","download_url":"https://codeload.github.com/am-kantox/camarero/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248124848,"owners_count":21051757,"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":["api-server","elixir","elixir-lang","json-api","webserver"],"created_at":"2024-09-24T19:30:21.828Z","updated_at":"2025-04-09T22:41:32.810Z","avatar_url":"https://github.com/am-kantox.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Camarero\n\n## [![Kantox ❤ OSS](https://img.shields.io/badge/❤-kantox_oss-informational.svg)](https://kantox.com/)  ![Test](https://github.com/am-kantox/camarero/workflows/Test/badge.svg)  ![Dialyzer](https://github.com/am-kantox/camarero/workflows/Dialyzer/badge.svg) Lightweight Json API server, embeddable into any project\n\n**Camarero** is a ready-to-use solution to add some JSON API functionality to your existing application, or to implement the read-only JSON API from the scratch when more sophisticated (read: heavy) solutions are not desirable.\n\n![Camarero Ties](https://raw.githubusercontent.com/am-kantox/camarero/master/stuff/camarero.png)\n\nIt is designed to be very simple and handy for read-only web access to the data. It might be a good candidate to replace _Redis_ or any other key-value store. **It is blazingly, deadly fast**.\n\nHere are response times for the 1M key-value storage behind.\n\n![1M key-value storage lookup: 10μs±](https://raw.githubusercontent.com/am-kantox/camarero/master/stuff/1M.png)\n\n## Implementation details\n\n**Camarero** is supposed to be plugged into the functional application. It handles the configured routes/endpoints by delegating to the configured handler modules. The simplest configuration might looks like:\n\n```elixir\nconfig :camarero,\n  carta: [Camarero.Carta.Heartbeat],\n  root: \"api/v1\"\n```\n\nThe above is the default; `/api/v1` would be the root of the web server, single `Camarero.Carta.Heartbeat` module is declared as handler. The handlers might be also added dynamically by calls to `Camarero.Catering.route!`.\n\n### Handlers\n\n_Handler_ is a module implementing `Camarero.Plato` behaviour. It consists of methods to manipulate the conteiner behind it. Any module might implement this behaviour to be used as a handler for incoming HTTP requests.\n\nThere is also `Camarero.Tapas` behaviour scaffolding the container implementation inside `Camarero.Plato`.\n\nThe default implementation using `%{}` map as a container, looks pretty simple:\n\n```elixir\ndefmodule Camarero.Carta.Heartbeat do\n  use Camarero\nend\n```\n\nThree different scaffolding implementations are currently supported with `scaffold: :impl` keyword parameter passed to `use Camarero`:\n\n- `scaffold: :full` [_default_] — the full implementation of `Camarero.Plato` is used;\n- `scaffold: :access` — `Camarero.Tapas` implementation is scaffolded only;\n- `scaffold: :none` — no scaffold is used.\n\nThis is an exact exerpt from `Heartbeat` module that comes with this package. For more complicated/sophisticated usages please refer to the [documentation](https://hexdocs.pm/camarero).\n\nAll the methods from both `Camarero.Tapas` and `Camarero.Plato` default implementations are overridable. E. g. to use the custom route for the module (default is the not fully qualified underscored module name,) as well as custom container, one might do the following:\n\n```elixir\ndefmodule Camarero.Carta.Heartbeat do\n  use Camarero, into: %MyStructWithAccessBehaviour{}\n\n  @impl Camarero.Plato\n  def plato_route(), do: \"internal/heartbeat\"\nend\n```\n\n### Web server config\n\n**Camarero** runs over _Cowboy2_ with _Plug_. To configure _Cowboy_, one might specify in the `config.exs` file:\n\n```elixir\nconfig :camarero,\n  cowboy: [port: 4001, scheme: :http, options: []]\n```\n\n## Installation\n\n```elixir\ndef deps do\n  [\n    {:camarero, \"~\u003e 1.0\"}\n  ]\nend\n```\n\n## Changelog\n\n### `1.0.2`\n\n- pass `headers` and `cookies` to `reshape/2`\n\n### `1.0.0`\n\n- correct handling of `:value` return (not relying on map keys order)\n- no more functionality expected\n\n### `0.13`\n\n- `Plato.reshape/1` to allow reshaping of any incoming data into expected `%{\"key\" =\u003e _, \"value\" =\u003e _}`\n- make sure to use `v0.13.3` with latest `Plug` library\n\n### `0.7`\n\n- Added support for `HTTP PUT` method\n\n### `0.5`\n\n- Ability to subscribe to incoming requests with `Envío.Subscriber` (see `test/envio_test.exs` for inspiration.)\n\n### `0.4`\n\n- basic CRUD (`GET /`, `GET /:id`, `POST /`, `DELETE /:id`),\n- better support for many handlers,\n- `response_as: :value` to return raw values instead of valid JSON objects.\n\n## Is it of any good?\n\nSure it is.\n\n## Benchmarks\n\nTo benchmark the application one should install [`wrk`](https://github.com/wg/wrk),\nrun the application and _then_ run the `wrk.sh` script located in `wrk` folder.\n\nHere are the results it produced on my laptop.\n\n```\n=================================================================\n NB! Make sure you have a running Camarero app:\n\n      mix clean \u0026\u0026 mix run --preload-modules --no-halt\n=================================================================\n\n Performing 10 sec POSTs and 5 sec GETs afterwards.\n This will INSERT 300K key-values approx and READ 200K approx.\n\n=================================================================\n\nRunning 10s test @ http://127.0.0.1:4001/api/v1/crud\n  24 threads and 1000 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    44.91ms   48.53ms 422.59ms   83.52%\n    Req/Sec     1.29k   212.59     3.09k    74.36%\n  311912 requests in 10.10s, 42.59MB read\nRequests/sec:  30884.14\nTransfer/sec:      4.22MB\nRunning 5s test @ http://127.0.0.1:4001/api/v1/crud\n  24 threads and 1000 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    39.35ms   45.92ms 401.63ms   84.53%\n    Req/Sec     1.48k   375.94     4.71k    79.09%\n  179565 requests in 5.10s, 30.11MB read\nRequests/sec:  35211.34\nTransfer/sec:      5.90MB\n\n=================================================================\n\n Performing 10 sec POSTs and 5 sec DELETEs afterwards.\n This will INSERT 300K key-values approx and DELETE 200K approx.\n\n=================================================================\n\nRunning 10s test @ http://127.0.0.1:4001/api/v1/crud\n  24 threads and 1000 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    46.32ms   52.38ms 457.89ms   84.01%\n    Req/Sec     1.31k   302.33     5.09k    79.26%\n  316401 requests in 10.10s, 43.20MB read\nRequests/sec:  31332.56\nTransfer/sec:      4.28MB\nRunning 5s test @ http://127.0.0.1:4001/api/v1/crud\n  24 threads and 1000 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    40.17ms   46.46ms 406.37ms   84.13%\n    Req/Sec     1.49k   360.10     6.55k    84.83%\n  179722 requests in 5.10s, 38.97MB read\nRequests/sec:  35241.01\nTransfer/sec:      7.64MB\n\n=================================================================\n```\n\n## [Documentation](http://hexdocs.pm/camarero)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fam-kantox%2Fcamarero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fam-kantox%2Fcamarero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fam-kantox%2Fcamarero/lists"}