{"id":13428895,"url":"https://github.com/z4kn4fein/kotlin-semver","last_synced_at":"2025-04-05T04:09:32.391Z","repository":{"id":36975592,"uuid":"444514222","full_name":"z4kn4fein/kotlin-semver","owner":"z4kn4fein","description":"Semantic Versioning library for Kotlin Multiplatform.","archived":false,"fork":false,"pushed_at":"2025-03-01T23:06:11.000Z","size":969,"stargazers_count":116,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T03:04:41.740Z","etag":null,"topics":["kotlin","kotlin-library","kotlin-multiplatform","semantic-version","semantic-versioning","semver"],"latest_commit_sha":null,"homepage":"https://z4kn4fein.github.io/kotlin-semver","language":"Kotlin","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/z4kn4fein.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":"2022-01-04T17:53:14.000Z","updated_at":"2025-03-24T15:22:47.000Z","dependencies_parsed_at":"2023-12-25T10:46:42.006Z","dependency_job_id":"94929a2e-01e7-41d3-a937-bbcbd3476a79","html_url":"https://github.com/z4kn4fein/kotlin-semver","commit_stats":{"total_commits":185,"total_committers":2,"mean_commits":92.5,"dds":0.2324324324324324,"last_synced_commit":"f98e7414eebde9a0dc6919bb6db3e22ee1e9d99b"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z4kn4fein%2Fkotlin-semver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z4kn4fein%2Fkotlin-semver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z4kn4fein%2Fkotlin-semver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/z4kn4fein%2Fkotlin-semver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/z4kn4fein","download_url":"https://codeload.github.com/z4kn4fein/kotlin-semver/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284949,"owners_count":20913704,"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":["kotlin","kotlin-library","kotlin-multiplatform","semantic-version","semantic-versioning","semver"],"created_at":"2024-07-31T01:01:08.136Z","updated_at":"2025-04-05T04:09:32.333Z","avatar_url":"https://github.com/z4kn4fein.png","language":"Kotlin","funding_links":[],"categories":["Libraries","版本控制系统"],"sub_categories":["Utility","🔧 Utils","语音合成"],"readme":"# kotlin-semver\n\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.z4kn4fein/semver?label=maven%20central)](https://search.maven.org/artifact/io.github.z4kn4fein/semver/)\n[![Snapshot](https://img.shields.io/nexus/s/io.github.z4kn4fein/semver?label=snapshot\u0026server=https%3A%2F%2Fs01.oss.sonatype.org)](https://s01.oss.sonatype.org/content/repositories/snapshots/io/github/z4kn4fein/semver/)\n[![Build](https://img.shields.io/github/actions/workflow/status/z4kn4fein/kotlin-semver/semver-ci.yml?logo=GitHub\u0026branch=main)](https://github.com/z4kn4fein/kotlin-semver/actions/workflows/semver-ci.yml)\n[![Quality Gate Status](https://img.shields.io/sonar/quality_gate/z4kn4fein_kotlin-semver?logo=SonarCloud\u0026server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/project/overview?id=z4kn4fein_kotlin-semver)\n[![SonarCloud Coverage](https://img.shields.io/sonar/coverage/z4kn4fein_kotlin-semver?logo=SonarCloud\u0026server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/project/overview?id=z4kn4fein_kotlin-semver)\n[![Kotlin](https://img.shields.io/badge/kotlin-1.9-blueviolet.svg?logo=kotlin)](http://kotlinlang.org)\n\nSemantic Versioning library for [Kotlin Multiplatform](https://kotlinlang.org/docs/mpp-intro.html).\nIt implements the full [semantic version 2.0.0](https://semver.org/spec/v2.0.0.html) specification and \nprovides the ability to **parse**, **compare**, and **increment** semantic versions along with validation against **constraints**.\n\nThe API Documentation is available [here](https://z4kn4fein.github.io/kotlin-semver/).\n\n## Install with Gradle\nThis library is available in Maven Central, so you have to add it to your repositories.\n```kotlin\nrepositories {\n    mavenCentral()\n}\n```\nThen, you can add the package to your dependencies.\n```kotlin\nval semverVersion: String by project\n\ndependencies {\n    implementation(\"io.github.z4kn4fein:semver:$semverVersion\")\n}\n```\nIn case of a multiplatform project, you can simply reference the package in your `commonMain` source set.\n```kotlin\nval semverVersion: String by project\n\nkotlin {\n    sourceSets {\n        val commonMain by getting {\n            dependencies { \n                implementation(\"io.github.z4kn4fein:semver:$semverVersion\")\n            }\n        }\n    }\n}\n```\nYou can also use platform-specific packages that you can find [here](https://repo1.maven.org/maven2/io/github/z4kn4fein) for each supported platform.\n\n## Usage\nThe following options are available to construct a [`Version`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/-version/index.html):\n1. Building part by part.\n\n   ```kotlin\n   Version(major = 3, minor = 5, patch = 2, preRelease = \"alpha\", buildMetadata = \"build\")\n   ```\n   \n2. Parsing from a string with [`Version.parse()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/-version/-companion/parse.html).\n\n   ```kotlin\n   Version.parse(\"3.5.2-alpha+build\")\n   ```\n   \n3. Using the [`toVersion()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/to-version.html) or [`toVersionOrNull()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/to-version-or-null.html) extension method on a string.\n\n   ```kotlin\n   \"3.5.2-alpha+build\".toVersion()\n   ```\n\nThe constructed `Version` object provides the following information:\n```kotlin\nval version = \"3.5.2-alpha.2+build\".toVersion()\nversion.major           // 3\nversion.minor           // 5\nversion.patch           // 2\nversion.preRelease      // \"alpha.2\"\nversion.buildMetadata   // \"build\"\n\nversion.isPreRelease    // true\nversion.isStable        // false\nversion.toString()      // \"3.5.2-alpha.2+build\"\n\nversion.withoutSuffixes().toString()   // \"3.5.2\"\n```\n\n### Destructuring\n`Version` supports destructuring by its public properties.\n```kotlin\nval version = \"2.3.1-alpha.2+build\".toVersion()\nval (major, minor, patch, preRelease, buildMetadata) = version\n\n// major: 2\n// minor: 3\n// patch: 1\n// preRelease: \"alpha.2\"\n// buildMetadata: \"build\"\n```\n\n### Strict vs. Loose Parsing\nBy default, the version parser considers partial versions like `1.0` and versions starting with the `v` prefix invalid.\nThis behaviour can be turned off by setting the `strict` parameter to `false`.\n```kotlin\n\"v2.3-alpha\".toVersion()                    // exception\n\"2.1\".toVersion()                           // exception\n\"v3\".toVersion()                            // exception\n\n\"v2.3-alpha\".toVersion(strict = false)      // 2.3.0-alpha\n\"2.1\".toVersion(strict = false)             // 2.1.0\n\"v3\".toVersion(strict = false)              // 3.0.0\n```\n\n## Compare\n\nIt is possible to compare two `Version` objects with [comparison operators](https://kotlinlang.org/docs/operator-overloading.html#comparison-operators) or with the `.compareTo()` method.\n```kotlin\n\"0.1.0\".toVersion() \u003c \"0.1.1\".toVersion()                   // true\n\"0.1.1\".toVersion() \u003c= \"0.1.1\".toVersion()                  // true\n\"0.1.0-alpha.3\".toVersion() \u003c \"0.1.0-alpha.4\".toVersion()   // true\n\n\"0.1.1\".toVersion().compareTo(\"0.1.0\".toVersion())          //  1\n\"0.1.0\".toVersion().compareTo(\"0.1.1\".toVersion())          // -1\n\"0.1.1\".toVersion().compareTo(\"0.1.1\".toVersion())          //  0\n```\n\nThe equality of two `Version` objects can be determined with [equality operators](https://kotlinlang.org/docs/operator-overloading.html#equality-and-inequality-operators) or with the `equals()` method.\n```kotlin\n\"0.1.1\".toVersion() == \"0.1.1\".toVersion()       // true\n\"0.1.1\".toVersion() != \"0.1.1\".toVersion()       // false\n\n\"0.1.1\".toVersion().equals(\"0.1.1\".toVersion())  // true\n\"0.1.0\".toVersion().equals(\"0.1.1\".toVersion())  // false\n```\n\n### Sort\nAs `Version` objects are comparable, you can get a sorted collection from them.\n```kotlin\nval list: List\u003cVersion\u003e = listOf(\n    \"1.0.1\".toVersion(),\n    \"1.0.1-alpha\".toVersion(),\n    \"1.0.1-alpha.beta\".toVersion(),\n    \"1.0.1-alpha.3\".toVersion(),\n    \"1.0.1-alpha.2\".toVersion(),\n    \"1.1.0\".toVersion(),\n    \"1.1.0+build\".toVersion(),\n).sorted()\n\n// The result:\n//   \"1.0.1-alpha\"\n//   \"1.0.1-alpha.2\"\n//   \"1.0.1-alpha.3\"\n//   \"1.0.1-alpha.beta\"\n//   \"1.0.1\"\n//   \"1.1.0\"\n//   \"1.1.0+build\"\n```\n\n### Range\nHaving an order provides the ability to determine whether a `Version` is in the range between two other versions.\n```kotlin\nval range = \"1.0.0\".toVersion()..\"1.1.0\".toVersion()\n\n\"1.0.1\".toVersion() in range     // true\n\"1.1.1\".toVersion() in range     // false\n```\n\n## Constraints\nWith constraints, it's possible to validate whether a version satisfies a set of rules or not.\nA constraint can be described as one or more conditions combined with logical `OR` and `AND` operators.\n\n### Conditions\nConditions are usually composed of a comparison operator and a version like `\u003e=1.2.0`.\nThe condition `\u003e=1.2.0` would be met by any version that greater than or equal to `1.2.0`.\n\nSupported comparison operators:\n- `=` Equal (equivalent to no operator: `1.2.0` means `=1.2.0`)\n- `!=` Not equal\n- `\u003c` Less than\n- `\u003c=` Less than or equal\n- `\u003e` Greater than\n- `\u003e=` Greater than or equal\n\nConditions can be joined together with whitespace, representing the `AND` logical operator between them.\nThe `OR` operator can be expressed with `||` or `|` between condition sets.\n\nFor example, the constraint `\u003e=1.2.0 \u003c3.0.0 || \u003e4.0.0` translates to: *Only those versions are allowed that are either greater than or \nequal to `1.2.0` {**AND**} less than `3.0.0` {**OR**} greater than `4.0.0`*.\n\nWe can notice that the first part of the previous constraint (`\u003e=1.2.0 \u003c3.0.0`) is a simple semantic version range.\nThere are more ways to express version ranges; the following section will go through all the available options.\n\n### Range Conditions\nThere are particular range indicators which are sugars for more extended range expressions.\n\n- **X-Range**: The `x`, `X`, and `*` characters can be used as a wildcard for the numeric parts of a version.\n   - `1.2.x` translates to `\u003e=1.2.0 \u003c1.3.0-0`\n   - `1.x` translates to `\u003e=1.0.0 \u003c2.0.0-0`\n   - `*` translates to `\u003e=0.0.0`\n\n  In partial version expressions, the missing numbers are treated as wildcards.\n   - `1.2` means `1.2.x` which finally translates to `\u003e=1.2.0 \u003c1.3.0-0`\n   - `1` means `1.x` or `1.x.x` which finally translates to `\u003e=1.0.0 \u003c2.0.0-0`\n\n- **Hyphen Range**: Describes an inclusive version range. Wildcards are evaluated and taken into account in the final range.\n   - `1.0.0 - 1.2.0` translates to `\u003e=1.0.0 \u003c=1.2.0`\n   - `1.1 - 1.4.0` means `\u003e=(\u003e=1.1.0 \u003c1.2.0-0) \u003c=1.4.0` which finally translates to `\u003e=1.1.0 \u003c=1.4.0`\n   - `1.1.0 - 2` means `\u003e=1.1.0 \u003c=(\u003e=2.0.0 \u003c3.0.0-0)` which finally translates to `\u003e=1.1.0 \u003c3.0.0-0`\n\n- **Tilde Range (`~`)**: Describes a patch level range when the minor version is specified or a minor level range when it's not.\n   - `~1.0.1` translates to `\u003e=1.0.1 \u003c1.1.0-0`\n   - `~1.0` translates to `\u003e=1.0.0 \u003c1.1.0-0`\n   - `~1` translates to `\u003e=1.0.0 \u003c2.0.0-0`\n   - `~1.0.0-alpha.1` translates to `\u003e=1.0.1-alpha.1 \u003c1.1.0-0`\n\n- **Caret Range (`^`)**: Describes a range with regard to the most left non-zero part of the version.\n   - `^1.1.2` translates to `\u003e=1.1.2 \u003c2.0.0-0`\n   - `^0.1.2` translates to `\u003e=0.1.2 \u003c0.2.0-0`\n   - `^0.0.2` translates to `\u003e=0.0.2 \u003c0.0.3-0`\n   - `^1.2` translates to `\u003e=1.2.0 \u003c2.0.0-0`\n   - `^1` translates to `\u003e=1.0.0 \u003c2.0.0-0`\n   - `^0.1.2-alpha.1` translates to `\u003e=0.1.2-alpha.1 \u003c0.2.0-0`\n\n### Validation\nThe following options are available to construct a [`Constraint`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/-constraint/index.html):\n- Parsing from a string with [`Constraint.parse()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/-constraint/-companion/parse.html).\n   ```kotlin\n   Constraint.parse(\"\u003e=1.2.0\")\n   ```\n\n- Using the [`toConstraint()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/to-constraint.html) or [`toConstraintOrNull()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/to-constraint-or-null.html) extension method on a string.\n   ```kotlin\n   \"\u003e=1.2.0\".toConstraint()\n   ```\n\nLet's see how we can determine whether a version [`satisfies`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/satisfies.html) a constraint or not.\n```kotlin\nval constraint = \"\u003e=1.2.0\".toConstraint()\nval version = \"1.2.1\".toVersion()\n\nversion satisfies constraint        // true\nconstraint satisfiedBy version      // true\n```\n\nIt's also possible to validate against a collection of constraints.\n```kotlin\nval constraints = listOf(\"\u003e=1.2.0\", \"\u003c2.0.0\").map { it.toConstraint() }\nval version = \"1.2.1\".toVersion()\n\nversion satisfiesAll constraints       // true\nversion satisfiesAny constraints       // true\n```\n\u003e [!NOTE]\\\n\u003e With [`satisfiesAll`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/satisfies-all.html) the version must satisfy each constraint within the collection. \n\u003e With [`satisfiesAny`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/satisfies-any.html) it must satisfy at least one constraint to pass the validation.\n\nOr to validate a collection of versions.\n```kotlin\nval constraint = \"\u003e=1.2.0\".toConstraint()\nval versions = listOf(\"1.2.1\", \"1.1.0\").map { it.toVersion() }\n\nconstraint satisfiedByAll versions       // false\nconstraint satisfiedByAny versions       // true\n```\n\u003e [!NOTE]\\\n\u003e With [`satisfiedByAll`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/satisfied-by-all.html) the constraint must be satisfied by each version within the collection. \n\u003e With [`satisfiedByAny`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/satisfied-by-any.html) it must be satisfied by at least one version to pass the validation.\n\n## Increment\n`Version` objects can produce incremented versions of themselves with the [`nextMajor()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/next-major.html),\n[`nextMinor()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/next-minor.html),\n[`nextPatch()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/next-patch.html),\n[`nextPreRelease()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/next-pre-release.html),\nand [`inc()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/inc.html) methods.\nThese methods can be used to determine the next version in order by increasing the appropriate identifier.\n`Version` objects are **immutable**, so each incrementing function creates a new `Version`.\n\nThis example shows how the incrementation works on a stable version:\n```kotlin\nval stableVersion = \"1.0.0\".toVersion()\n\nval nextMajor = stableVersion.nextMajor()                               // 2.0.0\nval nextMinor = stableVersion.nextMinor()                               // 1.1.0\nval nextPatch = stableVersion.nextPatch()                               // 1.0.1\nval nextPreRelease = stableVersion.nextPreRelease()                     // 1.0.1-0\n\n// or with the inc() method:\nval incrementedByMajor = stableVersion.inc(by = Inc.MAJOR)              // 2.0.0\nval incrementedByMinor = stableVersion.inc(by = Inc.MINOR)              // 1.1.0\nval incrementedByPatch = stableVersion.inc(by = Inc.PATCH)              // 1.0.1\nval incrementedByPreRelease = stableVersion.inc(by = Inc.PRE_RELEASE)   // 1.0.1-0\n```\n\nIn case of an unstable version:\n```kotlin\nval unstableVersion = \"1.0.0-alpha.2+build.1\".toVersion()\n\nval nextMajor = unstableVersion.nextMajor()                               // 2.0.0\nval nextMinor = unstableVersion.nextMinor()                               // 1.1.0\nval nextPatch = unstableVersion.nextPatch()                               // 1.0.0\nval nextPreRelease = unstableVersion.nextPreRelease()                     // 1.0.0-alpha.3\n\n// or with the inc() method:\nval incrementedByMajor = unstableVersion.inc(by = Inc.MAJOR)              // 2.0.0\nval incrementedByMinor = unstableVersion.inc(by = Inc.MINOR)              // 1.1.0\nval incrementedByPatch = unstableVersion.inc(by = Inc.PATCH)              // 1.0.0\nval incrementedByPreRelease = unstableVersion.inc(by = Inc.PRE_RELEASE)   // 1.0.0-alpha.3\n```\n\nEach incrementing function provides the option to set a pre-release identity on the incremented version.\n```kotlin\nval version = \"1.0.0-alpha.1\".toVersion()\n\nval nextPreMajor = version.nextMajor(preRelease = \"beta\")           // 2.0.0-beta\nval nextPreMinor = version.nextMinor(preRelease = \"\")               // 1.1.0-0\nval nextPrePatch = version.nextPatch(preRelease = \"alpha\")          // 1.0.1-alpha\nval nextPreRelease = version.nextPreRelease(preRelease = \"alpha\")   // 1.0.0-alpha.2\n\n// or with the inc() method:\nval incrementedByMajor = version.inc(by = Inc.MAJOR, preRelease = \"beta\")               // 2.0.0-beta\nval incrementedByMinor = version.inc(by = Inc.MINOR, preRelease = \"\")                   // 1.1.0-0\nval incrementedByPatch = version.inc(by = Inc.PATCH, preRelease = \"alpha\")              // 1.0.1-alpha\nval incrementedByPreRelease = version.inc(by = Inc.PRE_RELEASE, preRelease = \"alpha\")   // 1.0.0-alpha.2\n```\n\n## Copy\nIt's possible to create a copy of a version with its [`copy()`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/-version/copy.html) method.\nIt allows altering the copied version's properties with optional parameters.\n```kotlin\nval version = \"1.0.0-alpha.2+build.1\".toVersion()\n\nval exactCopy = version.copy()                                            // 1.0.0-alpha.2+build.1\nval withDifferentMajor = version.copy(major = 3)                          // 3.0.0-alpha.2+build.1\nval withDifferentMinor = version.copy(minor = 4)                          // 1.4.0-alpha.2+build.1\nval withDifferentPatch = version.copy(patch = 5)                          // 1.0.5-alpha.2+build.1\nval withDifferentPreRelease = version.copy(preRelease = \"alpha.4\")        // 1.0.0-alpha.4+build.1\nval withDifferentBuildMetadata = version.copy(buildMetadata = \"build.3\")  // 1.0.0-alpha.2+build.3\nval withDifferentNumbers = version.copy(major = 3, minor = 4, patch = 5)  // 3.4.5-alpha.2+build.1\n```\n\u003e [!NOTE]\\\n\u003e Without setting any optional parameter, the `copy()` method will produce an exact copy of the original version.\n\n## Exceptions\nWhen the version parsing fails due to an invalid format, the library throws a specific [`VersionFormatException`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver/-version-format-exception/index.html).\nSimilarly, when the constraint parsing fails, the library throws a [`ConstraintFormatException`](https://z4kn4fein.github.io/kotlin-semver/semver/io.github.z4kn4fein.semver.constraints/-constraint-format-exception/index.html).\n\u003e [!NOTE]\\\n\u003e The `toVersionOrNull()` and `toConstraintOrNull()` methods can be used for exception-less conversions as they return `null` when the parsing fails.\n\n## Contact \u0026 Support\n- Create an [issue](https://github.com/z4kn4fein/kotlin-semver/issues) for bug reports and feature requests.\n- Start a [discussion](https://github.com/z4kn4fein/kotlin-semver/discussions) for your questions and ideas.\n- Add a ⭐️ to support the project!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz4kn4fein%2Fkotlin-semver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fz4kn4fein%2Fkotlin-semver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fz4kn4fein%2Fkotlin-semver/lists"}