{"id":16318532,"url":"https://github.com/vic/deco","last_synced_at":"2025-03-20T22:30:52.525Z","repository":{"id":57488850,"uuid":"124135971","full_name":"vic/deco","owner":"vic","description":"Minimalist Function Decorators for Elixir","archived":false,"fork":false,"pushed_at":"2018-03-07T07:05:42.000Z","size":21,"stargazers_count":22,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-11T22:23:52.634Z","etag":null,"topics":["ast","decorators","elixir","function-decorator","macros"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vic.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":"2018-03-06T20:42:52.000Z","updated_at":"2024-04-29T09:45:08.000Z","dependencies_parsed_at":"2022-08-29T16:40:37.963Z","dependency_job_id":null,"html_url":"https://github.com/vic/deco","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2Fdeco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2Fdeco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2Fdeco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2Fdeco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vic","download_url":"https://codeload.github.com/vic/deco/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244085006,"owners_count":20395523,"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":["ast","decorators","elixir","function-decorator","macros"],"created_at":"2024-10-10T22:23:49.650Z","updated_at":"2025-03-20T22:30:52.180Z","avatar_url":"https://github.com/vic.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deco - Minimalist function decorators and around-advice for Elixir.\n\n\u003ca href=\"https://travis-ci.org/vic/deco\"\u003e\u003cimg src=\"https://travis-ci.org/vic/deco.svg\"\u003e\u003c/a\u003e\n[hexdocs](https://hexdocs.pm/deco).\n\nYes, yet another package for decorating elixir functions :).\n\nHowever, `deco`'s [core is minimalist](https://github.com/vic/deco/blob/master/lib/deco/core.ex) in comparission to others, \nuses much less magic, does not overrides anything like `Kernel.def` \nnor any operator.\n\n`deco` has only one macro, decorators themselves are just plain functions\n`Macro.t() -\u003e Macro.t()`, and imposes no run-time overhead because\nfunction decoration is performed at compile-time.\n\n## Usage\n\n```elixir\nuse Deco\n```\n\nThe syntax is `deco DECORATORS in FORM` where decorators is a tuple of\none or more decorators, and form is tipically a function definition.\n\n`decorators` are just plain functions you write that take the AST of\n`FORM` and just return a modified AST of it. The `Deco` module has\nsome convenience functions for updating the AST.\n\nSince `deco` runs at compile time, you cannot use functions being \ndefined in the same module that is using `deco`. Normally it's better\nto define your decorators on a separate module.\n\nThe following example decorates the function with a \n[tracer](https://github.com/vic/deco/blob/master/lib/deco/trace.ex) \nthat will use `Logger` to print the arguments given before applying\nthe original function, and the its final result.\n\n```elixir\n   deco { Trace.trace() } in\n   def foo(x) do\n     x\n   end\n```\n\nDecorators can take arguments, the AST will be prepended to the list\nof arguments given by you.\n\nAlso, because decorators operate on the AST they have full access to it\nallowing them to for example, introduce new guards or remove them.\n\n```elixir\n   deco { Deco.update_guard(fn _ -\u003e nil end) } in\n   def foo(x) when is_atom(x) do\n     x\n   end\n   \n   foo(\"hey\")\n   =\u003e \"hey\"\n```\n\nDecorators can be composed, the one at the end will take the original\nAST and produce a new one for the one on top of it.\n\n```elixir\n   deco {\n     Deco.pipe_result(String.capitalize),\n     Deco.pipe_result(String.reverse),\n     Deco.pipe_result(to_string)\n   } in\n   def foo(x) do\n     x\n   end\n   \n   foo(:john)\n   =\u003e \"Nhoj\n```\n\nYou can decorate using a simple function, without having to mess with\nthe AST if you dont want to. The `Deco.around` decorator will act as\nan _around advice_ and will give you a reference to the decorated \nfunction (made private) and all the arguments given on invocation.\n\n```elixir\n   # our private around advice\n   defp bar_wrapper(decorated, name, say) do\n     \"#{say} #{decorated.(name)}\"\n   end\n\n   deco {Deco.around( bar_wrapper(\"hello\") )} in\n   def bar(name) do\n     name |\u003e String.capitalize\n   end\n\n\n   bar(\"world\")\n   =\u003e \"hello World\"\n```\n\nFor more examples, see the [tests](https://github.com/vic/deco/blob/master/test/deco_test.exs) or [use the source, Luke](https://github.com/vic/deco/blob/master/lib/deco.ex)\n\n## AuthDeco\n\nThis example was adapted from [arjan/decorator](https://github.com/arjan/decorator) to show how\nit would look like using deco. \n\n```elixir\n   defp is_authorized(decorated, conn, params) do\n      if conn.assigns.user do\n        decorated.(conn, params)\n      else\n        conn\n        |\u003e send_resp(401, \"unauthorized\")\n        |\u003e halt()\n      end\n   end\n\n   deco {Deco.around(is_authorized)} in\n   def create(conn, params) do\n     ...\n   end\n```\n\n\n## Installation\n\n```elixir\ndef deps do\n  [\n    {:deco, \"~\u003e 0.1\"}\n  ]\nend\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvic%2Fdeco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvic%2Fdeco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvic%2Fdeco/lists"}