{"id":16660546,"url":"https://github.com/mpenet/ex","last_synced_at":"2025-08-20T09:05:34.705Z","repository":{"id":57713341,"uuid":"140439109","full_name":"mpenet/ex","owner":"mpenet","description":"Exception net","archived":false,"fork":false,"pushed_at":"2019-10-22T12:20:31.000Z","size":20,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T20:43:48.783Z","etag":null,"topics":["clojure","exception-handling"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","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/mpenet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-10T13:49:23.000Z","updated_at":"2020-07-17T16:07:48.000Z","dependencies_parsed_at":"2022-09-05T22:40:07.029Z","dependency_job_id":null,"html_url":"https://github.com/mpenet/ex","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/mpenet%2Fex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpenet","download_url":"https://codeload.github.com/mpenet/ex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248092127,"owners_count":21046416,"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":["clojure","exception-handling"],"created_at":"2024-10-12T10:29:43.504Z","updated_at":"2025-04-09T18:50:20.068Z","avatar_url":"https://github.com/mpenet.png","language":"Clojure","funding_links":[],"categories":["Exceptions and Error Handling"],"sub_categories":[],"readme":"# ex\n\n## Deprecation notice\n\n**No longer in developement, if you want the same ideas with way better implementation, head to [exoscale/ex](https://github.com/exoscale/ex/)**\n\n\n\n[![cljdoc badge](https://cljdoc.xyz/badge/cc.qbits/ex)](https://cljdoc.xyz/d/cc.qbits/ex/CURRENT)\n\nAn exception library, drop in replacement for `try`/`catch`/`finally`,\nthat adds support for `ex-info`/`ex-data` with a custom (clojure)\nhierarchy that allows to express exceptions relations.\n\nSo we have `qbits.ex/try+`, which supports vanilla `catch`/`finally`\nclauses.\nIf you specify a `catch-data` clause with a keyword as first argument\nthings get interesting. We assume you always put a `:type` key in the\nex-info you want to use with this, and will match its value to the\nvalue of the key in the `catch-data` clause.\n\nEssentially `catch-data` takes this form:\n\n``` clj\n(catch-data :something m\n   ;; where m is a binding to the ex-data (you can destructure at that level as well)\n   )\n```\n\nSo you can do things like that.\n\n``` clj\n\n(require '[qbits.ex :as ex])\n\n(ex/try+\n\n  (throw (ex-info \"Argh\" {:type ::bar :foo \"a foo\"}))\n\n  (catch-data ::foo data\n    (prn :got-ex-data data))\n\n  (catch-data ::bar {:as data :keys [foo]}\n    ;; in that case it would hit this one\n    (prn :got-ex-data-again foo))\n\n  (catch ExceptionInfo e\n   ;; this would match an ex-info that didn't get a hit with catch-ex-info)\n\n  (catch Exception e (prn :boring))\n\n  (finally (prn :boring-too)))\n\n```\n\n\nBut there's a twist.\n\nI thought leveraging a clojure hierarchy could make sense in that\ncontext too, so you can essentially create exceptions hierachies\nwithout having to mess with Java classes directly and in a\nclojuresque\" way.\n\n``` clj\n;; so bar is a foo\n\n(ex/derive ::bar ::foo)\n\n(ex/try+\n  (throw (ex-info \"I am a bar\" {:type ::bar})\n  (catch-data ::foo d\n    (prn \"got a foo with data\" d)\n    (prn \"Original exception instance is \" (-\u003e d meta ::ex/exception))))\n\n```\n\nYou can also get the full exception instance via the metadata on the\nex-data we extract, it's under the `:qbits.ex/exception` key.\n\nSome real life examples of usage for this:\n\n* make some exceptions end-user exposable in http responses via an\n  error middleware in a declarative way .\n\n* skip sentry logging for some kind of exceptions (or the inverse)\n\n* make an exception hierachy for our query language type of errors for\n  specialized reporting per \"type\"\n\nOther than that it's largely inspired by\n[catch-data](https://github.com/gfredericks/catch-data), the\nimplementation is slightly different, we dont catch Throwable, we\ninstead generate a catch clause on clj `ex-info` and generate a cond\nthat tries to match ex-data with the :type key using `isa?` with our\nhierarchy, which arguably is closer to I would write by hand in that\ncase.\n\n## Installation\n\nex is [available on Clojars](https://clojars.org/cc.qbits/ex).\n\nAdd this to your dependencies:\n\n\n[![Clojars Project](https://img.shields.io/clojars/v/cc.qbits/ex.svg)](https://clojars.org/cc.qbits/ex)\n\n\nor you can just grab it via `deps.edn` directly\n\n\u003c!-- Please check the --\u003e\n\u003c!-- [Changelog](https://github.com/mpenet/ex/blob/master/CHANGELOG.md) --\u003e\n\u003c!-- if you are upgrading. --\u003e\n\n## License\n\nCopyright © 2018 [Max Penet](http://twitter.com/mpenet)\n\nDistributed under the\n[Eclipse Public License](http://www.eclipse.org/legal/epl-v10.html),\nthe same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpenet%2Fex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpenet%2Fex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpenet%2Fex/lists"}