{"id":24423918,"url":"https://github.com/mopp/tracke","last_synced_at":"2025-04-12T07:51:12.377Z","repository":{"id":149753650,"uuid":"146878267","full_name":"mopp/tracke","owner":"mopp","description":"Trackable error library for Erlang","archived":false,"fork":false,"pushed_at":"2019-03-13T09:29:32.000Z","size":21,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T03:04:29.893Z","etag":null,"topics":["erlang","erlang-library","tracking"],"latest_commit_sha":null,"homepage":null,"language":"Erlang","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/mopp.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-31T10:36:14.000Z","updated_at":"2023-03-18T19:12:20.000Z","dependencies_parsed_at":"2023-04-18T11:06:54.775Z","dependency_job_id":null,"html_url":"https://github.com/mopp/tracke","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopp%2Ftracke","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopp%2Ftracke/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopp%2Ftracke/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mopp%2Ftracke/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mopp","download_url":"https://codeload.github.com/mopp/tracke/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248537003,"owners_count":21120688,"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":["erlang","erlang-library","tracking"],"created_at":"2025-01-20T10:48:17.541Z","updated_at":"2025-04-12T07:51:12.370Z","avatar_url":"https://github.com/mopp.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"## tracke\nTrackable error library.\n\n### features\n- Make errors trackable\n- Support OTP-18 and the laters\n- Embed error reasons in the type `tracke/1`\n    * e.g., `tracke(your_error_atom)`\n\n### API\n- `-spec tracke:new(Reason) -\u003e tracke:tracke(Reason)`\n    * Make `tracke` object.\n    * Define your error as the `Reason`.\n- `-spec tracke:new(Reason, Aux :: term()) -\u003e tracke:tracke(Reason)`\n    * This function works same as `tracke:new/1`.\n    * The `Aux` is embedded to history.\n- `-spec tracke:chain(tracke(Reason)) -\u003e tracke(Reason)`\n    * Append history to `tracke(Reason)` and keep the reason.\n    * This function works same as `tracke:new/1` if `Reason` is NOT `tracke(Reason)`\n- `-spec tracke:chain(tracke(Reason), Aux :: term()) -\u003e tracke(Reason)`\n    * This function works same as `tracke:chain/1`.\n    * The `Aux` is embedded to history.\n- `-spec tracke:extend(NewReason, tracke(Reason :: term())) -\u003e tracke(NewReason)`\n    * Set new reason and keep the histories.\n    * The old reason is stored into `Aux` field.\n- `-spec tracke:reason(tracke(Reason)) -\u003e Reason`\n    * Extract error reason from `tracke`.\n    * Return it without doing anythings if not `tracke` object is given.\n- `-spec tracke:format(tracke(Reason)) -\u003e binary()`\n    * Build human readable error reason and its history.\n- `-spec tracke:is_tracke(term()) -\u003e boolean()`\n    * Return true if the argument is `tracke()`.\n    * Return false otherwise.\n\n### Constrains\n- You can ONLY use a variable as the arugment of `tracke:chain/1`, `tracke:chain/1` and `tracke:reason/1`.\n    * This measn a forms of `tracke:chain(Reason)` is acceptable.\n    * `tracke:chain(tracke:new(not_work))` is NOT supported because this library uses `parse_transform/2`.\n\n### Error hints\nResolving some dialyzer errors relates to tracke is not easy because it uses `parse_transform/2`.  \nWe show you the hints to solve them here.\n\n- `Matching of pattern {'tracke', _, _} tagged with a record name violates the declared type of XXX`\n    * You may give NOT `tracke(Reason)` to `tracke:chain/1`.\n    * Check your return types of specs.\n\n\n### Example\nSee [src/tracke_example.erl](src/tracke_example.erl) for details.\n\n```erlang\n-spec normal_usage(integer()) -\u003e ok.\nnormal_usage(X) -\u003e\n    case func1(X) of\n        {ok, V} -\u003e\n            io:format(\"Ok: ~p~n\", [V]);\n        {error, Reason} -\u003e\n            io:format(\"~s~n\", [tracke:format(Reason)]),\n            case tracke:reason(Reason) of\n                zero -\u003e\n                    io:format(\"Your input is zero.~n\", []);\n                negative -\u003e\n                    io:format(\"Your input is negative.~n\", []);\n                boring_number -\u003e\n                    io:format(\"Your input is boring.~n\", [])\n            end\n    end,\n    ok.\n\n-spec func1(integer()) -\u003e {ok, binary()} | {error, tracke(zero | negative | boring_number)}.\nfunc1(0) -\u003e\n    {error, tracke:new(zero)};\nfunc1(X) when X \u003c 0 -\u003e\n    {error, tracke:new(negative)};\nfunc1(X) -\u003e\n    case fizzbuzz(X) of\n        {ok, _} = Ok -\u003e\n            Ok;\n        {error, Reason} -\u003e\n            {error, tracke:chain(Reason)}\n    end.\n\n-spec fizzbuzz(integer()) -\u003e {ok, binary()} | {error, tracke(boring_number)}.\nfizzbuzz(X) -\u003e\n    case {X rem 5 =:= 0, X rem 3 =:= 0} of\n        {true, true} -\u003e\n            {ok, \u003c\u003c\"fizzbuzz\"\u003e\u003e};\n        {true, false} -\u003e\n            {ok, \u003c\u003c\"fizz\"\u003e\u003e};\n        {false, true} -\u003e\n            {ok, \u003c\u003c\"buzz\"\u003e\u003e};\n        {false, false} -\u003e\n            {error, tracke:new(boring_number)}\n    end.\n```\n\nThe result is the following:\n```console\n1\u003e tracke_example:normal_usage(0).\nReason: zero, History:tracke_example:func1/1 at L39\nYour input is zero.\nok\n\n\n2\u003e tracke_example:normal_usage(-100).\nReason: negative, History:tracke_example:func1/1 at L41\nYour input is negative.\nok\n\n\n3\u003e tracke_example:normal_usage(127).\nReason: boring_number, History:tracke_example:fizzbuzz/1 at L60 -\u003e tracke_example:func1/1 at L47\nYour input is boring.\nok\n\n\n4\u003e tracke_example:normal_usage(15).\nOk: \u003c\u003c\"fizzbuzz\"\u003e\u003e\nok\n\n11\u003e tracke_example:deep_chain().\nReason: bottom_reason, History:tracke_example:deep_chain1/1 at L113 -\u003e tracke_example:deep_chain2/2 at L119 (Aux: \"hi\") -\u003e tracke_example:deep_chain3/3 at L126\nok\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmopp%2Ftracke","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmopp%2Ftracke","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmopp%2Ftracke/lists"}