diff options
| author | netop://ウィビ <paul@webb.page> | 2026-04-11 15:01:41 -0700 |
|---|---|---|
| committer | netop://ウィビ <paul@webb.page> | 2026-04-11 15:01:41 -0700 |
| commit | 3f7f5dc1b5ca4ba6a9acaf101d2e52b64edd2705 (patch) | |
| tree | 9c496baae8c825b548fbec43f198006856ee30c6 /README.md | |
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5f8615 --- /dev/null +++ b/README.md @@ -0,0 +1,404 @@ + + + +**[ChronVer](https://chronver.org) (Chronological Versioning) is calendar‑based versioning.** In the age of rapid software releases, knowing _when_ something released is more important than arbitrary numbers from an outdated versioning system that most people never adhere to anyway. Finally, versioning for the rest of us. + + + +## Why ChronVer? + +``` +2025.07.21 ← You know exactly when this was released +v3.2.1 ← You have no idea when this happened +``` + +Semantic versioning is great for large systems like libraries and computers. Most software would benefit from **time‑based versioning** that's immediately understandable to everyone on a team, not just the technical‑minded. + + + +## Format + +``` +YYYY.MM.DD[.CHANGESET][-FEATURE|-break] +``` + +### Examples + +| Version | Description | +|------------------------|-------------------------------| +| `2025.07.21` | Released July 21st, 2025 | +| `2025.07.21.1` | First hotfix that day | +| `2025.07.21.3` | Third change that day | +| `2025.07.21-feature` | Feature branch for that date | +| `2025.07.21.1-feature` | Feature branch with changeset | +| `2025.07.21.1-break` | Breaking change | + + + +## Installation + +### Deno + +```sh +# install +deno add jsr:@chronver/chronver + +# import in your code +import { ChronVer } from "jsr:@chronver/chronver"; + +# install CLI globally +# "resolver diagnostics" will appear when using this method but it's fine +deno install --allow-read --allow-write --global --name chronver https://raw.githubusercontent.com/ChronVer/chronver/refs/heads/primary/cli.ts --import-map https://raw.githubusercontent.com/ChronVer/chronver/refs/heads/primary/deno.json +``` + +### npm/bun + +```sh +# install via npm +npx jsr add @chronver/chronver + +# install via bun +bunx jsr add @chronver/chronver + +# import in your code +import { ChronVer } from "@chronver/chronver"; +``` + +ChronVer is especially powerful with [husky](https://typicode.github.io/husky/). Here's how I use it in my Node projects (using [bun](https://bun.sh)): + +```js +// package.json + "devDependencies": { + "del-cli": "^6.0.0", + "husky": "^9.1.7" + }, + "scripts": { + "build": "bun run clean && vite build", + "clean": "del './build'", + "increment": "chronver increment", + "pre-commit": "bun run build && bun run increment && git add -A :/", + "prepare": "husky" + } +``` + +Now every time you push a commit, the `version` in `package.json` gets updated. Please note that you'll need to install the `chronver` CLI globally using the Deno method above or the path method below (recommended). + +### macOS/Linux + +You can find releases of the CLI on the [releases page](https://github.com/ChronVer/chronver/releases) of this repo. + +```sh +# create personal bin directory if it doesn't exist +mkdir -p ~/.local/bin + +# add to PATH in your shell profile (~/.bashrc, ~/.zshrc, etc.) +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc +source ~/.zshrc + +# move binary there +mv chronver ~/.local/bin/ +``` + + + +## Usage + +### Basic API + +```ts +import { ChronVer } from "jsr:@chronver/chronver"; + +// create new version with today's date +const version = new ChronVer(); +console.log(version.toString()); // "2025.07.21" + +// parse existing version +const parsed = new ChronVer("2024.04.03.1"); +console.log(parsed.year); // 2024 +console.log(parsed.month); // 4 +console.log(parsed.day); // 3 +console.log(parsed.changeset); // 1 + +// compare versions +const v1 = new ChronVer("2024.04.03"); +const v2 = new ChronVer("2024.04.04"); +console.log(v1.isOlderThan(v2)); // true +console.log(v2.isNewerThan(v1)); // true + +// increment version +const incremented = version.increment(); +console.log(incremented.toString()); // "2024.07.19.1" (if same day) +``` + +### Static Methods + +```ts +// validation +ChronVer.isValid("2024.04.03"); // true +ChronVer.isValid("invalid"); // false + +// comparison +ChronVer.compare("2024.04.03", "2024.04.04"); // -1 + +// parsing +const parsed = ChronVer.parseVersion("2024.04.03.1-feature"); +// { +// changeset: 1, +// date: "2024.04.03", +// feature: "feature", +// isBreaking: false, +// version: "2024.04.03.1-feature" +// } + +// sorting +const versions = ["2024.04.05", "2024.04.03", "2024.04.04"]; +ChronVer.sort(versions); // ["2024.04.03", "2024.04.04", "2024.04.05"] + +// create from Date +const date = new Date(2024, 3, 3); // April 3, 2024 +const version = ChronVer.fromDate(date, 5); // "2024.04.03.5" +``` + +### File Operations + +```ts +// update package.json version +const newVersion = await ChronVer.incrementInFile("package.json"); +console.log(newVersion); // "2025.07.21.1" + +// works with any JSON file +await ChronVer.incrementInFile("deno.json"); +``` + + + +## CLI Usage + +```bash +# create new version +chronver create # 2024.07.19 + +# validate versions +chronver validate "2024.04.03.1" # ✅ Valid: 2024.04.03.1 + +# compare versions +chronver compare "2024.04.03" "2024.04.04" # 2024.04.03 < 2024.04.04 (-1) + +# increment package.json +chronver increment # 📦 Updated to: 2025.07.21.1 +chronver increment deno.json # 📦 Updated to: 2025.07.21.1 + +# parse version details +chronver parse "2024.04.03.1-feature" +# 📋 Version: 2024.04.03.1-feature +# 📅 Date: 2024.04.03 +# 🔢 Changeset: 1 +# 💥 Breaking: no +# 🚀 Feature: feature +# 📆 Day of week: Wednesday +# ⏪ Released 107 days ago + +# sort versions +chronver sort "2024.04.03" "2024.04.01" "2024.04.05" +# 📊 Sorted (ascending): +# 🔼 1. 2024.04.01 +# 🔼 2. 2024.04.03 +# 🔼 3. 2024.04.05 + +chronver --sort-desc "2024.04.03" "2024.04.01" "2024.04.05" +# 📊 Sorted (descending): +# 🔽 1. 2024.04.05 +# 🔽 2. 2024.04.03 +# 🔽 3. 2024.04.01 + +# create from specific date +chronver format "2024-04-03" 5 # 2024.04.03.5 + +# help +chronver --help +``` + + + +## When to Use ChronVer + +### ✅ Perfect For + +- **SaaS platforms** with regular feature rollouts +- **Mobile apps** with app store schedules +- **Enterprise software** with quarterly releases +- **Security tools** where timing matters +- **Marketing‑driven releases** tied to campaigns +- **Compliance software** with regulatory deadlines + +### ❌ Less Ideal For + +- **Libraries** consumed by other developers +- **APIs** where breaking changes need clear signaling +- **Projects** with irregular, feature‑driven releases +- **Tools** where semantic compatibility matters more than timing + + + +## Comparison with SemVer + +| Aspect | ChronVer | SemVer | +|-------------------|---------------------------------|---------------------------| +| **Clarity** | Immediately shows when released | Requires lookup | +| **Planning** | Aligns with calendar schedules | Feature‑driven | +| **Communication** | "The April release" | "Version 3.2.1" | +| **Sorting** | Chronological by default | Arbitrary without context | +| **Compatibility** | Time‑based breaking changes | API contract based | +| **Best for** | Time‑sensitive releases | Library compatibility | + + + +## Advanced Features + +### Feature Branches + +```ts +const feature = new ChronVer("2024.04.03-new-ui"); +console.log(feature.feature); // "new-ui" +console.log(feature.toString()); // "2024.04.03-new-ui" +``` + +### Breaking Changes + +```ts +const breaking = new ChronVer("2024.04.03.1-break"); +console.log(breaking.isBreaking); // true +``` + +### Date Validation + +ChronVer validates actual calendar dates: + +```ts +ChronVer.isValid("2024.02.29"); // true (2024 was a leap year) +ChronVer.isValid("2023.02.29"); // false (2023 was not a leap year) +ChronVer.isValid("2024.04.31"); // false (April has 30 days) +``` + + + +## Real-World Examples + +### `package.json` integration + +```json +{ + "name": "my-app", + "scripts": { + "version": "chronver increment" + }, + "version": "2025.07.21.3" +} +``` + +### CI/CD Pipeline + +```yaml +# GitHub Actions example +- name: Update version + run: | + chronver increment + git add package.json + git commit -m "chore: bump version to $(cat package.json | jq -r .version)" +``` + +### Release Notes + +```md +## Release 2025.07.21 - Summer Feature Drop + +### New Features + +- Dark mode support +- Mobile‑responsive dashboard +- Advanced search filters + +### Bug Fixes + +- Fixed login timeout issue +- Improved performance on large datasets + +### Breaking Changes + +None in this release. +``` + + + +## Development + +```sh +# clone project +git clone https://github.com/chronver/chronver.git && cd $_ + +# lint +deno check && deno lint + +# run tests +deno test --allow-read --allow-write --fail-fast + +# run CLI locally +deno run --allow-read --allow-write cli.ts --help +``` + +If you have [Just](https://just.systems/man/en/) installed: + +```sh +just lint +# deno check && deno lint + +just test +# deno test --allow-read --allow-write --fail-fast + +just build +# compile CLI to an executable +``` + + + +## Ports + +### Rust + +- https://github.com/dnaka91/chronver / https://crates.io/crates/chronver + + + +## License + +[Creative Commons ― CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) + + + +## FAQ + +### Why not just use dates? + +ChronVer **is** dates, but with a structured format that supports multiple releases per day, feature branches, and breaking change indicators. + +### What about semantic compatibility? + +ChronVer can indicate breaking changes with the `-break` suffix. For situations where semantic versioning is **crucial**, stick with SemVer. + +### How do I migrate from SemVer? + +1. Choose your first ChronVer date (usually next release) +2. Update your build tools to use `chronver increment` +3. Update documentation to explain the new format +4. Consider keeping a mapping in your `CHANGELOG` + +### Can I use both ChronVer and SemVer? + +Absolutely! Here's how your project could use ChronVer for releases and SemVer for API versions: + +```json +{ + "apiVersion": "v2.1.0", + "version": "2024.07.19.1" +} +``` |
