{"id":28530850,"url":"https://github.com/duct-framework/core","last_synced_at":"2025-07-07T08:32:27.018Z","repository":{"id":19762281,"uuid":"87817288","full_name":"duct-framework/core","owner":"duct-framework","description":"The core library of the Duct framework","archived":false,"fork":false,"pushed_at":"2024-01-23T20:23:12.000Z","size":175,"stargazers_count":77,"open_issues_count":10,"forks_count":21,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-09T14:51:11.774Z","etag":null,"topics":["clojure","duct","framework","integrant"],"latest_commit_sha":null,"homepage":"","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/duct-framework.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-10T13:59:27.000Z","updated_at":"2024-11-25T11:59:55.000Z","dependencies_parsed_at":"2024-06-19T06:11:38.566Z","dependency_job_id":"819f1e64-bbd7-4ef9-a9fa-896d0c26b9d6","html_url":"https://github.com/duct-framework/core","commit_stats":{"total_commits":148,"total_committers":14,"mean_commits":"10.571428571428571","dds":"0.10135135135135132","last_synced_commit":"74087344dc3fb1ef812222be8f441b9d1fd8c430"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/duct-framework/core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duct-framework%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duct-framework%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duct-framework%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duct-framework%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duct-framework","download_url":"https://codeload.github.com/duct-framework/core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duct-framework%2Fcore/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260465874,"owners_count":23013443,"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","duct","framework","integrant"],"created_at":"2025-06-09T14:37:39.502Z","updated_at":"2025-07-07T08:32:27.006Z","avatar_url":"https://github.com/duct-framework.png","language":"Clojure","readme":"# Duct core\n\n[![Build Status](https://travis-ci.org/duct-framework/core.svg?branch=master)](https://travis-ci.org/duct-framework/core)\n\nThe core of the next iteration of the [Duct][] framework. It extends\nthe [Integrant][] micro-framework with support for modules, asset\ncompilation and environment variables.\n\n[duct]:      https://github.com/duct-framework/duct\n[integrant]: https://github.com/weavejester/integrant\n\n## Installation\n\nTo install, add the following to your project `:dependencies`:\n\n    [duct/core \"0.8.1\"]\n\n## Usage\n\nFirst we need to read in an Integrant configuration from a file or\nresource:\n\n```clojure\n(require '[clojure.java.io :as io]\n         '[duct.core :as duct])\n\n(defn get-config []\n  (duct/read-config (io/resource \"example/config.edn\")))\n```\n\nOnce we have a configuration, we have three options. The first option\nis to `prep-config` the configuration, which will load in all relevant\nnamespaces and apply all modules.\n\nThis is ideally used with `integrant.repl`:\n\n```clojure\n(require '[integrant.repl :refer :all])\n\n(set-prep! #(duct/prep-config (get-config)))\n```\n\nAlternatively we can `prep-config` then `exec-config` the configuration. This\ninitiates the configuration, then blocks the current thread if the\nsystem includes any keys deriving from `:duct/daemon`. This is\ndesigned to be used from the `-main` function:\n\n```clojure\n(defn -main []\n  (-\u003e (get-config) (duct/prep-config) (duct/exec-config)))\n```\n\nYou can change the executed keys to anything you want by adding in an\nadditional argument. This is frequently used with the `parse-keys`\nfunction, which parses keywords from command-line arguments:\n\n```clojure\n(defn -main [\u0026 args]\n  (let [keys (or (duct/parse-keys args) [:duct/daemon])]\n    (-\u003e (get-config)\n        (duct/prep-config keys)\n        (duct/exec-config keys))))\n```\n\nThis allows other parts of the system to be selectively executed. For\nexample:\n\n```\nlein run :duct/compiler\n```\n\nWould initiate all the compiler keys. And:\n\n```\nlein run :duct/migrator\n```\n\nWould initiate the migrator and run all pending migrations. If no\narguments are supplied, the keys default to `[:duct/daemon]` in this\nexample.\n\n## Keys\n\nThis library introduces a number of Integrant components:\n\n* `:duct/const` is a component that returns its value when initialized.\n* `:duct/module` denotes a Duct module (see the modules section).\n* `:duct/profile` denotes a Duct profile (see the profiles section).\n* `:duct.core/environment` specifies the environment of the\n  configuration, and may be set to `:development` or `:production`. It\n  does nothing on its own, but may be used by modules.\n* `:duct.core/project-ns` specifies the base namespace of your\n  project. This is often used by modules for determining where to put\n  things. For example, public web resources are typically placed in the\n  `resources/\u003cproject-ns\u003e/public` directory.\n\n## Readers\n\nThis library also introduces five new reader tags that can be used in\nDuct configurations:\n\n* `#duct/env \"VARNAME\"` allows an environment variable to be\n  referenced in the configuration.\n* `#duct/include \"path\"` will include replace the tag with the\n  resource at the specified path. This allows a configuration to be\n  split up into separate files.\n* `#duct/resource \"path\"` will convert a resource path into a URL\n* `#duct/displace` is equivalent to `^:displace`, but works with\n  primitive values\n* `#duct/replace` is equivalent to `^:replace`, but works with\n  primitive values\n\n## Modules\n\nModules are Integrant components that initialize into a pure\nfunction. This function expects a configuration as its argument, and\nreturns a modified configuration.\n\nMost modules derive from `:duct/module`. This both identifies them,\nand ensures they are executed after profiles.\n\nHere's a simple example module:\n\n```clojure\n(require '[integrant.core :as ig])\n\n(derive :duct.module/example :duct/module)\n\n(defmethod ig/init-key :duct.module/example [_ {:keys [port]}]\n  (fn [config]\n    (assoc-in config [:duct.server.http/jetty :port] port)))\n```\n\nThis above module updates the port number of the `:duct.server.http/jetty`\nkey. By itself this isn't hugely useful, but modules can be made to\nupdate many different components at once.\n\nModules can also have dependencies, achieved using\n`integrant.core/prep-key`:\n\n```clojure\n(defmethod ig/prep-key :duct.module/example [_ options]\n  (assoc options ::requires (ig/ref :duct.module/parent)))\n```\n\nThis adds a reference to the module's options, ensuring that Integrant\nwill initialize the `:duct.module/parent` module before\n`:duct.module/example`.\n\nYou can also have optional dependencies with `integrant.core/refset`:\n\n```clojure\n(defmethod ig/prep-key :duct.module/example [_ options]\n  (assoc options ::requires (ig/refset #{:duct.module/parent})))\n```\n\n## Profiles\n\nA profile is (currently) a type of module that merges the value of the\nkey into the resulting configuration.\n\nThere are five profile keys included in this library:\n\n* `:duct.profile/base` is the base of all new profiles\n* `:duct.profile/dev` is a profile for development\n* `:duct.profile/local` is a profile only on your local development\n  machine\n* `:duct.profile/test` is a profile for testing\n* `:duct.profile/prod` is a profile for production\n\n## Documentation\n\n* [API Docs](https://duct-framework.github.io/core/index.html)\n\n## License\n\nCopyright © 2020 James Reeves\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduct-framework%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduct-framework%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduct-framework%2Fcore/lists"}