{"id":13482772,"url":"https://github.com/luckyframework/habitat","last_synced_at":"2025-05-07T14:38:24.726Z","repository":{"id":21270079,"uuid":"92064053","full_name":"luckyframework/habitat","owner":"luckyframework","description":"Easily configure settings for Crystal projects","archived":false,"fork":false,"pushed_at":"2025-03-15T21:11:41.000Z","size":151,"stargazers_count":84,"open_issues_count":10,"forks_count":12,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-27T13:39:11.948Z","etag":null,"topics":["configuration","crystal","hacktoberfest"],"latest_commit_sha":null,"homepage":"","language":"Crystal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luckyframework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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-05-22T14:38:23.000Z","updated_at":"2025-03-15T21:11:16.000Z","dependencies_parsed_at":"2024-05-02T19:54:19.584Z","dependency_job_id":"ce60f66b-0695-41a2-8d5a-43f96ddc028d","html_url":"https://github.com/luckyframework/habitat","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckyframework%2Fhabitat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckyframework%2Fhabitat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckyframework%2Fhabitat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luckyframework%2Fhabitat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luckyframework","download_url":"https://codeload.github.com/luckyframework/habitat/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252896878,"owners_count":21821351,"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":["configuration","crystal","hacktoberfest"],"created_at":"2024-07-31T17:01:05.366Z","updated_at":"2025-05-07T14:38:24.701Z","avatar_url":"https://github.com/luckyframework.png","language":"Crystal","funding_links":[],"categories":["Configuration"],"sub_categories":[],"readme":"# Habitat\n\n[![API Documentation Website](https://img.shields.io/website?down_color=red\u0026down_message=Offline\u0026label=API%20Documentation\u0026up_message=Online\u0026url=https%3A%2F%2Fluckyframework.github.io%2Fhabitat%2F)](https://luckyframework.github.io/habitat)\n\nEasily configure settings for Crystal projects\n\n## Installation\n\nAdd this to your application's `shard.yml`:\n\n```yaml\ndependencies:\n  habitat:\n    github: luckyframework/habitat\n```\n\n## Usage\n\n```crystal\nrequire \"habitat\"\n```\n\n```crystal\nclass MyServer\n  Habitat.create do\n    setting port : Int32\n    setting debug_errors : Bool = true\n\n    # Optionally add examples to settings that appear in error messages\n    # when the value is not set.\n    #\n    # Use `String#dump` when you want the example to be wrapped in quotes\n    setting host : String, example: \"127.0.0.1\".dump\n    setting logger : Logger, example: \"Logger.new(STDOUT)\"\n\n    # If you need the value to match a specific format, you can create\n    # your own validation.\n    setting protocol : String, validation: :validate_protocol\n  end\n\n  # Read more on validations below\n  def self.validate_protocol(value : String)\n    value.match(/^http(?:s)*:$/) || Habitat.raise_validation_error(\"The protocol must be `http:` or `https:`.\")\n  end\n\n  # Access them with the `settings` method like this.\n  def start\n    start_server_on port: settings.port\n  end\nend\n\n# Configure your settings\nMyServer.configure do |settings|\n  settings.port = 8080\nend\n\n# At the very end of your program use this\n# It will raise if you forgot to set any settings\nHabitat.raise_if_missing_settings!\n```\n\nSettings can also be accessed from outside the class:\n\n```crystal\nport = MyServer.settings.port\nputs \"The server is starting on port #{port}\"\n```\n\n### Setting validations\n\nThe `validation` option takes a Symbol which matches a class method\nthat will run your custom validation. This can be useful if your\nsetting needs to be in a specific format like maybe a 4 digit code\nthat can start with a 0.\n\n```crystal\nclass Secret\n  Habitat.create do\n    setting code : String, validation: :validate_code\n  end\n\n  # The validation method will take an argument of the same type.\n  # If your setting is `Int32`, then this argument will also be `Int32`.\n  #\n  # Use any method of validation you'd like here. (i.e. regex, other custom methods, etc...)\n  # If your validation fails, you can call `Habitat.raise_validation_error` with your custom error\n  # message\n  def self.validate_code(value : String)\n    value.match(/^\\d{4}$/) || Habitat.raise_validation_error(\"Be sure the code is only 4 digits\")\n  end\nend\n\nSecret.configure do |settings|\n\n  # Even though the code is the correct type, this will still\n  # raise an error for us.\n  settings.code = \"ABCD\"\n\n  # This value will pass our validation\n  settings.code = \"0123\"\nend\n```\n\n### Temp Config\n\nThere are some cases in which you may want to temporarily change a setting value. (i.e. specs, one off jobs, etc...)\n\nHabitat comes with a built-in method `temp_config` that allows you to do this:\n\n```crystal\nclass Server\n  Habitat.create do\n    setting hostname : String\n  end\nend\n\nServer.configure do |settings|\n  settings.hostname = \"localhost\"\nend\n\nServer.settings.hostname #=\u003e \"localhost\"\n\nServer.temp_config(hostname: \"fancyhost.com\") do\n  # This seting affects the value globally while inside this block\n  Server.settings.hostname #=\u003e \"fancyhost.com\"\nend\n\n# Once the block exits, the original value is returned\nServer.settings.hostname #=\u003e \"localhost\"\n```\n\n## Contributing\n\n1. Fork it ( https://github.com/luckyframework/habitat/fork )\n2. Create your feature branch (git checkout -b my-new-feature)\n3. Commit your changes (git commit -am 'Add some feature')\n4. Push to the branch (git push origin my-new-feature)\n5. Create a new Pull Request\n\n## Contributors\n\n- [paulcsmith](https://github.com/paulcsmith) Paul Smith - creator, maintainer\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluckyframework%2Fhabitat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluckyframework%2Fhabitat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluckyframework%2Fhabitat/lists"}