{"id":31943277,"url":"https://github.com/luminus-framework/conman","last_synced_at":"2025-12-12T01:20:45.424Z","repository":{"id":35776501,"uuid":"40056322","full_name":"luminus-framework/conman","owner":"luminus-framework","description":"a helper library for managing database connections","archived":false,"fork":false,"pushed_at":"2023-08-31T10:57:07.000Z","size":121,"stargazers_count":124,"open_issues_count":3,"forks_count":26,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-10-03T00:58:20.240Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luminus-framework.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2015-08-01T18:35:34.000Z","updated_at":"2025-05-09T03:40:11.000Z","dependencies_parsed_at":"2024-06-18T20:07:05.315Z","dependency_job_id":"02921b07-86ba-4d64-bdcd-32dba4e62092","html_url":"https://github.com/luminus-framework/conman","commit_stats":{"total_commits":162,"total_committers":25,"mean_commits":6.48,"dds":"0.21604938271604934","last_synced_commit":"78eb55c992b74095bf63a3d67b0c2a27d4d620e7"},"previous_names":["luminus-framework/luminus-db"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/luminus-framework/conman","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fconman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fconman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fconman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fconman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luminus-framework","download_url":"https://codeload.github.com/luminus-framework/conman/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fconman/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018554,"owners_count":26086404,"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","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-10-14T09:50:20.143Z","updated_at":"2025-10-14T09:50:45.847Z","avatar_url":"https://github.com/luminus-framework.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# conman\n\n![status](https://circleci.com/gh/luminus-framework/conman.svg?style=shield\u0026circle-token=da462d56802b9a0ff94ecc7992d1d0caf8475d00)\n\nLuminus database connection management and SQL query generation library\n\nThe library provides pooled connections using the [HikariCP](https://github.com/brettwooldridge/HikariCP) library.\n\nThe queries are generated using [HugSQL](https://github.com/layerware/hugsql) and wrapped with\nconnection aware functions.\n\n## Usage\n\n[![Clojars Project](http://clojars.org/conman/latest-version.svg)](http://clojars.org/conman)\n\nConman relies on a dynamic variable to manage the connection. The dynamic variable allows the connection to be\nrebound contextually for transactions. When working with multiple databases, a separate var is required\nto track each database connection.\n\n### Defining Queries\n\nSQL statements should be populated in files that are accessible on the resource path.\nFor example, we could create a file `resources/sql/queries.sql` with\nthe following content:\n\n``` sql\n-- :name create-user! :! :n\n-- :doc creates a new user record\nINSERT INTO users\n(id, first_name, last_name, email, pass)\nVALUES (:id, :first_name, :last_name, :email, :pass)\n\n-- :name get-user :? :1\n-- :doc retrieve a user given the id.\nSELECT * FROM users\nWHERE id = :id\n\n-- :name get-all-users :? :*\n-- :doc retrieve all users.\nSELECT * FROM users\n```\nSee the official [HugSQL docs](http://www.hugsql.org/) for further examples.\n\n### Using `bind-connection`\n\nThe queries are bound to the connection using the `bind-connection` macro. This macro\naccepts the connection var followed by one or more strings representing SQL query files.\n\nThe lifecycle of the connection is expected to be managed using a library such as [mount](https://github.com/tolitius/mount). The full list of options that can be passed to `pool-spec` can be found [here](https://github.com/tomekw/hikari-cp#configuration-options).\n\n\n```clojure\n(ns myapp.db\n  (:require [mount.core :refer [defstate]]\n            [conman.core :as conman]))\n\n(def pool-spec\n  {:jdbc-url \"jdbc:postgresql://localhost/myapp?user=user\u0026password=pass\"})\n\n(defstate ^:dynamic *db*\n          :start (conman/connect! pool-spec)\n          :stop (conman/disconnect! *db*))\n\n(conman/bind-connection *db* \"sql/queries.sql\")\n```\n\nThe `bind-connection` generates `create-user!` and `get-user` functions\nin the current namespace. These functions can be called in four different ways:\n\n```clojure\n;; when called with no argument then the HugSQL generated function\n;; will be called with an empty parameter map and the connection specified in the *db* var\n(get-all-users)\n\n;; when a parameter map is passed as the argument, then the map and the connection specified\n;; in the *db* var will be passed to the HugSQL generated function\n(create-user! {:id \"foo\" :first_name \"Bob\" :last_name \"Bobberton\" :email nil :pass nil})\n\n;; an explicit connection and a parameter map can be\n;; passed to the function\n(get-user some-other-conn {:id \"foo\"})\n\n;; finally, an explicit connection and a parameter map, options, and optional command options\n;; can be passed to the function\n(get-user some-other-conn {:id \"foo\"} opts)\n(get-user some-other-conn {:id \"foo\"} opts cmd-opt1 cmd-opt2)\n```\n\n### Using `bind-connection-map`\n\nAlternatively, you may wish to use `bind-connection-map` to define the queries. This function will return\na map containing `:snips` and `:fns` keys that point to maps of snippets and queries respectively.\nThe `snip` and `query` helper functions are provided for accessing the connection map returned by the `bind-connection-map`\nfunction.\n\n```clojure\n;; create a connection map given the connection instance and one or more query files:\n(def queries (bind-connection-map conn \"queries.sql\"))\n\n;; a HugSQL options map can be passed as the second argument:\n(def queries (bind-connection-map conn {:quoting :ansi} \"queries.sql\"))\n\n;; run a query\n(query\n  queries\n  :add-fruit!\n  {:name       \"apple\"\n   :appearance \"red\"\n   :cost       1\n   :grade      1})\n\n;; run a query specifying the connection explicitly\n(query\n  conn\n  queries\n  :add-fruit!\n  {:name       \"apple\"\n   :appearance \"red\"\n   :cost       1\n   :grade      1})\n\n;; run a query with a snippet\n(query\n  conn\n  queries\n  :get-fruit-by\n  {:by-appearance\n   (snip queries :by-appearance {:appearance \"red\"})})\n```\n\nIf you use `:cljc` [mode of mount](https://github.com/tolitius/mount/blob/master/doc/clojurescript.md#clojure-and-clojurescript-mode),\nwhere you would need to explicitly `deref` each state, you'll need to use `conman/bind-connection-deref` instead of\n`conman/bind-connection`. Both `conman/bind-connection-deref` and `conman/with-transaction` macros still accept undereferenced state,\nwhile in every other case it has to be dereferenced:\n\n```clojure\n(mount/in-cljc-mode)\n\n(conman/bind-connection-deref *db* \"sql/queries.sql\")\n\n(conman/with-transaction [*db*]\n  (sql/db-set-rollback-only! @*db*)\n  (add-memo! {:id 123 :text \"Hello\"})\n  (sql/query @*db* [\"SELECT * FROM memos;\"]))\n\n```\n\nNext, the `connect!` function should be called to initialize the database connection.\nThe function accepts a map with the database specification.\n\n```clojure\n(def pool-spec\n  {:jdbc-url   \"jdbc:postgresql://localhost/myapp?user=user\u0026password=pass\"})\n\n(connect! pool-spec)\n```\n\nFor the complete list of configuration options refer to the official [hikari-cp](https://github.com/tomekw/hikari-cp) library documentation. Conman supports the following additional options:\n\n* `:datasource`\n* `:datasource-classname`\n\nThe connection can be terminated by running the `disconnect!` function:\n\n```clojure\n(disconnect! conn)\n```\n\nA connection can be reset using the `reconnect!` function:\n\n```clojure\n(reconnect! conn pool-spec)\n```\n\nWhen using a dynamic connection, it's possible to use the `with-transaction`\nmacro to rebind it to the transaction connection. The SQL query functions\ngenerated by the `bind-connection` macro will automatically use the transaction\nconnection in that case:\n\n```clojure\n(with-transaction [conn {:rollback-only true}]  \n  (create-user!\n    {:id         \"foo\"\n     :first_name \"Sam\"\n     :last_name  \"Smith\"\n     :email      \"sam.smith@example.com\"})\n  (get-user {:id \"foo\"}))\n```\n\nThe isolation level and readonly status of the transaction may be specified using the `:isolation`\nand `:read-only?` keys respectively:\n\n```clojure\n(with-transaction\n    [conn {:isolation :serializable}]\n    (= java.sql.Connection/TRANSACTION_SERIALIZABLE\n       (.getTransactionIsolation (sql/db-connection conn))))\n(with-transaction\n  [conn {:isolation :read-uncommitted}]\n  (= java.sql.Connection/TRANSACTION_READ_UNCOMMITTED\n     (.getTransactionIsolation (sql/db-connection conn))))\n```\n\n## License\n\nCopyright © 2015 Dmitri Sotnikov and Carousel Apps Ltd.\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluminus-framework%2Fconman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluminus-framework%2Fconman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluminus-framework%2Fconman/lists"}