{"id":43786111,"url":"https://github.com/coditory/quark-config","last_synced_at":"2026-02-05T19:04:04.764Z","repository":{"id":57718391,"uuid":"285748413","full_name":"coditory/quark-config","owner":"coditory","description":"Coditory Quark Config is a lightweight and single purpose java library for loading and manipulating configurations","archived":false,"fork":false,"pushed_at":"2026-02-01T06:14:41.000Z","size":585,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-01T16:59:33.168Z","etag":null,"topics":["coditory-quark","configuration-management","java-configuration"],"latest_commit_sha":null,"homepage":"","language":"Java","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/coditory.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["coditory"]}},"created_at":"2020-08-07T05:48:56.000Z","updated_at":"2026-02-01T06:14:44.000Z","dependencies_parsed_at":"2023-11-06T14:27:16.549Z","dependency_job_id":"f4e93093-2d0e-493b-a640-4ccf0038a00f","html_url":"https://github.com/coditory/quark-config","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/coditory/quark-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coditory%2Fquark-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coditory%2Fquark-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coditory%2Fquark-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coditory%2Fquark-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coditory","download_url":"https://codeload.github.com/coditory/quark-config/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coditory%2Fquark-config/sbom","scorecard":{"id":298342,"data":{"date":"2025-08-11","repo":{"name":"github.com/coditory/quark-config","commit":"5b7136e956bde1cbcd7c1bbd654466e049fd525f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/dependabot.yml:1","Warn: no topLevel permission defined: .github/workflows/labeler.yml:1","Warn: no topLevel permission defined: .github/workflows/release-auto.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/upgrade-gradle-wrapper.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/dependabot.yml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/dependabot.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/labeler.yml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/labeler.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-auto.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/release-auto.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/upgrade-gradle-wrapper.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/coditory/quark-config/upgrade-gradle-wrapper.yml/main?enable=pin","Info:   0 out of   6 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":9,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/coditory/.github/SECURITY.md:1","Info: Found linked content: github.com/coditory/.github/SECURITY.md:1","Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy","Info: Found text in security policy: github.com/coditory/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":8,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Info: 'stale review dismissal' is required to merge on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Info: codeowner review is required on branch 'main'","Info: 'last push approval' is required to merge on branch 'main'","Info: 'up-to-date branches' is required to merge on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T20:05:55.791Z","repository_id":57718391,"created_at":"2025-08-17T20:05:55.791Z","updated_at":"2025-08-17T20:05:55.791Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29130113,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T18:55:47.139Z","status":"ssl_error","status_checked_at":"2026-02-05T18:55:04.010Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["coditory-quark","configuration-management","java-configuration"],"created_at":"2026-02-05T19:04:04.697Z","updated_at":"2026-02-05T19:04:04.752Z","avatar_url":"https://github.com/coditory.png","language":"Java","readme":"# Quark Config\n[![Build](https://github.com/coditory/quark-config/actions/workflows/build.yml/badge.svg)](https://github.com/coditory/quark-config/actions/workflows/build.yml)\n[![Coverage](https://codecov.io/gh/coditory/quark-config/branch/master/graph/badge.svg?token=G4B3UCSDN7)](https://codecov.io/gh/coditory/quark-config)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.coditory.quark/quark-config/badge.svg)](https://mvnrepository.com/artifact/com.coditory.quark/quark-config)\n\n\u003e Lightweight and single purpose java library for loading and manipulating configurations\n\nA configuration library,\nsimilar to the one created in [Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config)\nof [typesafe](https://github.com/lightbend/config), that is:\n- lightweight, without a burden of a framework (has exactly two dependencies gson and snakeyaml)\n- loads configuration from multiple sources: arguments, classpath, file system\n- supports multiple formats YAML, JSON, properties\n- provides a collection of parsers for values such as `java.util.Duration`\n- hides secrets when formatted to string\n- provides basic expressions for references and default values\n- public API annotated with `@NotNull` and `@Nullable` for better [kotlin integration](https://kotlinlang.org/docs/java-to-kotlin-nullability-guide.html#platform-types)\n\n## Installation\n\nAdd to your `build.gradle`:\n\n```gradle\ndependencies {\n    implementation \"com.coditory.quark:quark-config:0.1.27\"\n}\n```\n\n## Usage\n\n### Load application configuration\n\n```java\nConfig config = new ConfigLoader()\n    .defaultProfiles(\"local\")\n    .configPath(\"configs\")\n    .args(args)\n    .loadConfig();\n```\n\nLoads configuration files:\n- from classpath directory: `config`\n- with config base name: `application` (it's a default value)\n- with default profile: `local` (can be overridden with args `--profile=$PROFILE`)\n- overrides configuration values using args `--config-value.$NAME=$VALUE`\n\n```\n// Sample config files layout:\nsrc/main/resources/config\n  application.yml\n  application-local.yml\n  application-prod.yml\n```\n\nExplore the API, there is much more to configure.\n\n#### Config merging order\n\nApplication configuration sources are merged into a single config object\naccording to the following order:\n\n- base config\n  - base config from classpath, by default: `application.{yml,json,properties}`\n- profile config\n  - profile based config from classpath, by default: `application-${profile}.{yml,json,properties}`\n  - profiles are enabled in arguments: `--profile=$PROFILE` or `--profile=$PROFILE1,$PROFILE2`\n  - by default profile configs are optional\n- external config\n  - config file from system\n  - passed as an argument `--config=$PATH_TO_CONFIG`\n- config values from arguments\n  - all arguments passed as arguments `--config-value.\u003cconfig_key\u003e=$VALUE`\n\nExample:\n```yml\n# file: application.yml\napplication:\n  name: \"best-app\"\n  port: ${_env.PORT ? _args.port ? 7070}\n\n# file: application-local.yml\napplication:\n  port: 8080\n\n# file: application-prod.yml\napplication:\n  port: 80\n```\n\n```java\nConfig config = new ConfigLoader().loadConfig();\n// loads base config only\n// Output: {application={port=7070, name=best-app}}\n\nConfig config = new ConfigLoader()\n    .args(\"--profile\", \"prod\")\n    .loadConfig();\n// loads config with prod profile\n// Output: {application={port=80, name=best-app}}\n\nConfig config = new ConfigLoader()\n    .aArgs(\"--port\", \"7071\")\n    .loadConfig();\n// resolves config with expression\n// Output: {application={port=7071, name=best-app}}\n\nConfig config = new ConfigLoader()\n    .args(\"--config-value.application.port\", \"8081\")\n    .loadConfig();\n// loads config with config value passed as an argument\n// Output: {application={port=8081, name=best-app}}\n```\n\nFor more examples see the [test cases](src/integrationTest/groovy/com/coditory/quark/config/LoadApplicationConfigSpec.groovy).\n\n#### Config resolution variables\n\nYou can use the following expression variables to resolve an application config:\n- `${_profiles.*}` - profiles arsed from args\n- `${_env.*}` - all system variables from `System.getenv()`\n- `${_system.*}` - all system variables from `System.getProperties()`\n- `${_args.*}` - all arguments\n\n### Creating a config\n\nYou can create a config object in multiple ways:\n\n```java\n// Create from var args\nConfig.of(\n    \"application.name\", \"best-app\",\n    \"application.port\", 8080\n);\n\n// Create from a map\nConfig.of(Map.of(\"application.port\", 8080));\n\n// Create empty config and add value\nConfig.builder()\n    .put(\"application.port\", 8080)\n    .build();\n\n// Build own config with customizations\nConfig.builder()\n    .put(\"application.name\", \"best-app\")\n    .put(\"application.port\", 8080)\n    .setSecretHidingValueMapper(customSecretHider)\n    .setValueParser(customParser)\n    .build();\n\n// Create config from strings, files or system properties\nConfigFactory.buildFromSystemProperties();\nConfigFactory.buildFromSystemEnvironment();\nConfigFactory.buildFromArgs(args);\nConfigFactory.loadFromClasspath(path);\nConfigFactory.loadFromFileSystem(path);\nConfigFactory.parseJson(json);\nConfigFactory.parseYaml(yaml);\nConfigFactory.parseProperties(properties);\n\n// Load config from classpath files with some validation and profiles passed in args\n// (typical setup for web application, that is deployable to dev, test and prod environemnts)\nnew ConfigLoader()\n    .addArgsMapping([\"--prod\"], [\"--profile\", \"prod\"])\n    .addArgsMapping([\"--test\"], [\"--profile\", \"test\"])\n    .addArgsMapping([\"--dev\"], [\"--profile\", \"dev\"])\n    .addArgsAlias(\"p\", \"profile\")\n    .minProfileCount(1)\n    .exclusiveProfiles(mainProfiles)\n    .firstIfNoneMatch(mainProfiles)\n    .configPath(\"config\")\n    .args(args)\n    .loadConfig();\n```\n\n### Resolving a config value\n```java\n// throws if config value is not defined\nconfig.getInteger(\"application.port\");\n\n// returns a default value if config value is not defined\nconfig.getInteger(\"application.port\", 8080);\n\n// returns null if config value is not defined\nconfig.getIntegerOrNull(\"application.port\");\n\n// returns an Optional from config value\nconfig.getIntegerAsOptional(\"application.port\");\n```\n\nQuark Config provides a lot of parsers\nso String values may be retrieved as a non String objects:\n```java\nConfig.of(\n    \"port\", \"8080\",\n    \"timeout\", \"1s\",\n    \"locale\", \"pl-PL\",\n    \"currency\", \"PLN\",\n    \"timestamp\", \"2007-12-03T10:15:30.00Z\"\n)\nassert config.getInteger(\"port\") == 8080\nassert config.getDuration(\"timeout\") == Duration.parse(\"PT1S\")\nassert config.getLocale(\"locale\") == new Locale(\"pl\", \"PL\")\nassert config.getCurrency(\"currency\") == Currency.getInstance(\"PLN\")\nassert config.getInstant(\"timestamp\") == Instant.parse(\"2007-12-03T10:15:30.00Z\")\n```\n\nResolving a sub-config:\n```java\nConfig applicationConfig = config.getSubConfig(\"application\");\napplicationConfig.getInteger(\"port\");\n```\n\n### Merging configs\nTwo config objects can be merged:\n\n```java\nConfig config = Config.of(\n    \"a\", \"A\",\n    \"b\", \"B\"\n);\nConfig other = Config.of(\n   \"b\", \"X\",\n   \"c\", \"Y\"\n);\n\nconfig.withDefaults(other);\n// {a=A, b=B, c=Y}\n\nconfig.withValues(other);\n// {a=A, b=X, c=Y}\n```\n\n### Config expressions\n\nConfig values can use some basic expressions:\n```java\n// Config with references to other value\nConfig.builder()\n    .put(\"a\", \"${b}\")\n    .put(\"b\", \"B\")\n    .resolveExpressions()\n    .build();\n// {a=B, b=B}\n\n// Config with a fallback value\nConfig.builder()\n    .withValue(\"a\", \"${b ? X}\")\n    .resolveExpressions()\n    .build();\n// {a=X}\n\n// Config with a double fallback value\nConfig.builder()\n    .put(\"a\", \"${b ? c ? X}\")\n    .resolveExpressions()\n    .build();\n// {a=X}\n\n// Config with expression values\nConfig.builder()\n    .put(\"a\", \"${b ? c ? X}\")\n    .resolveExpressions(Config.of(c, \"C\"))\n    .build();\n// {a=C}\n```\n\n### Load config from file\n\nThe config can be loaded from:\n- classpath file\n- file from the file system\n\nYou don't need to specify an extension of the configuration file.\nQuark Config will automatically look for: `*.yml`, `*.yaml`, `*.json`, `*.properties`\n\n```java\nConfigFactory.loadFromClasspath(\"custom-config\");\nConfigFactory.loadFromFileSystem(\"custom-config\");\n```\n\n### Parsing and formatting a config\n\nQuark Config supports the following formats:\n- yaml\n- json\n- properties\n\n```java\n// parsing a config\nConfigFactory.parseYaml(yaml);\nConfigFactory.parseJson(json);\nConfigFactory.parseProperties(properties);\n\n// formatting a config\nConfigFormatter.toYaml(config);\nConfigFormatter.toJson(config);\nConfigFormatter.toProperties(config);\n\n// formatting a config with exposed secrets\nConfigFormatter.toYamlWithExposedSecrets(config);\nConfigFormatter.toJsonWithExposedSecrets(config);\nConfigFormatter.toPropertiesWithExposedSecrets(config);\n\n// config.toString() method uses output of a Map with hidden secrets\nconfig.toString();\n```\n","funding_links":["https://github.com/sponsors/coditory"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoditory%2Fquark-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoditory%2Fquark-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoditory%2Fquark-config/lists"}