Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add uuidv7 #910

Merged
merged 3 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ node_modules/
.*.sw*
*.bak
*.bak.*

# other
.DS_Store
desktop.ini
.directory
115 changes: 115 additions & 0 deletions uuidv7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
title: uuidv7
homepage: https://github.com/coolaj86/uuidv7
tagline: |
uuidv7: generate UUID v7 strings, command line edition
---

To update or switch versions, run `webi uuidv7@stable`.

## Cheat Sheet

> `uuidv7` exists because _somebody_ was tired of searching "UUID v7 generator"
> just to get a test value for a little ditty now and then. Though, the time
> spent creating it will probably never be recouped...
```sh
uuidv7
```

```text
01928d73-d8ed-7211-a314-7081d763271d
```

## Table of Contents

- Files
- Generating Many `UUIDv7`s
- Roll Your Own UUID v7 Generator
- Understanding the UUID v7 spec
- UUID v7, by the String
- UUID v7, by the Byte

### Files

These are the files / directories that are created and/or modified with this
install:

```text
~/.config/envman/PATH.env
~/.local/bin/uuidv7
~/.local/opt/uuidv7/
```

### How to Generate Many v7 UUIDs at Once

```sh
uuidv7 ; uuidv7 ; uuidv7
```

```text
01928d74-3ff7-796f-8417-0fee6da50a5a
01928d74-3ff9-73f7-8ce1-71e741cfa56f
01928d74-3ffb-7e06-abe9-3fe20e5cb5f2
```

### How could I roll my own UUID v7 generator?

It's not that hard. There are examples in many languages here:

- https://github.com/coolaj86/uuidv7

See the simplified spec examples below.

### What's the UUID v7 spec, in simple terms?

See the explanation here:

- https://github.com/coolaj86/uuidv7

A snapshot of that is copied here, for convenience:

### UUID v7, by the Characters

There are 36 characters total: 32 hex (`0123456789abcdef`) + 4 dashes (`-`)

```text
8 time 4 time 1v + 3ra ½v + 3½rb 12 random b
019212d3 - 87f4 - 7d25 - 902e - b8d39fe07f08
```

- 8ch hex time high
- `-`
- 4ch hex time low
- `-`
- 4ch hex version + "random a"
- 1ch hex version: `7`
- 3ch hex "random a"
- `-`
- 4ch hex variant + "random b"
- 1ch hex version: `8`, `9`, `a`, `b`
- 3ch hex "random b"
- `-`
- 12ch hex randam a
- 4ch hex random a
- 8ch hex random a

### UUID v7, by the Bits

There are 128 bits total: \
48 time and 80 random, with 4 version and 2 variant bits substituted

```text
48 time 4ver, 12ra 2var, 14rb random b
019212d3-87f4 - 7d25 - 902e - b8d39fe07f08
```

- 48 bits of timestamp
- 32-bit high (minutes to years)
- 16-bit low (seconds & milliseconds)
- 16 bits of version + random
- 4-bit version (`0b0111`)
- 12-bit random
- 64-bits variant + random
- 2-bit variant (`0b10`)
- 62-bit random
55 changes: 55 additions & 0 deletions uuidv7/install.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env pwsh

##################
# Install uuidv7 #
##################

# Every package should define these variables
$pkg_cmd_name = "uuidv7"

$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\uuidv7.exe"
$pkg_dst = "$pkg_dst_cmd"

$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\uuidv7-v$Env:WEBI_VERSION\bin\uuidv7.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\uuidv7-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\uuidv7-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"

New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | Out-Null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"

# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) {
Write-Output "Downloading uuidv7 from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& Move-Item "$pkg_download.part" "$pkg_download"
}

IF (!(Test-Path -Path "$pkg_src_cmd")) {
Write-Output "Installing uuidv7"

# TODO: create package-specific temp directory
# Enter tmp
Push-Location .local\tmp

# Remove any leftover tmp cruft
Remove-Item -Path ".\uuidv7-v*" -Recurse -ErrorAction Ignore
Remove-Item -Path ".\uuidv7.exe" -Recurse -ErrorAction Ignore

# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
Write-Output "Unpacking $pkg_download"
& tar xf "$pkg_download"

# Settle unpacked archive into place
Write-Output "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | Out-Null
Move-Item -Path ".\uuidv7.exe" -Destination "$pkg_src_bin"

# Exit tmp
Pop-Location
}

Write-Output "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | Out-Null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
40 changes: 40 additions & 0 deletions uuidv7/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh
# shellcheck disable=SC2034

__init_uuidv7() {
set -e
set -u

##################
# Install uuidv7 #
##################

# Every package should define these 6 variables
pkg_cmd_name="uuidv7"

pkg_dst_cmd="${HOME}/.local/bin/uuidv7"
pkg_dst="${pkg_dst_cmd}"

pkg_src_cmd="${HOME}/.local/opt/uuidv7-v${WEBI_VERSION}/bin/uuidv7"
pkg_src_dir="${HOME}/.local/opt/uuidv7-v${WEBI_VERSION}"
pkg_src="${pkg_src_cmd}"

pkg_install() {
# $HOME/.local/opt/uuidv7-v1.0.1/bin
mkdir -p "$(dirname "${pkg_src_cmd}")"

# mv ./uuidv7* "$HOME/.local/opt/uuidv7-v1.0.1/bin/uuidv7"
mv ./"${pkg_cmd_name}"* "${pkg_src_cmd}"

# chmod a+x "$HOME/.local/opt/uuidv7-v1.0.1/bin/uuidv7"
chmod a+x "${pkg_src_cmd}"
}

pkg_get_current_version() {
# TODO https://github.com/coolaj86/uuidv7/issues/10
echo '1.0.1'
}

}

__init_uuidv7
41 changes: 41 additions & 0 deletions uuidv7/releases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';

let Releases = module.exports;

let GitHub = require('../_common/github.js');
let owner = 'coolaj86';
let repo = 'uuidv7';

Releases.latest = async function () {
let all = await GitHub.getDistributables(null, owner, repo);
let distributables = [];
for (let dist of all.releases) {
// TODO update classifier to make thumb armv5
// and gnueabi armeb, not gnu
// and loongarch64 not arch64
let isSpecial =
dist.name.includes('-thumb') ||
dist.name.includes('-armeb') ||
dist.name.includes('-loong') ||
dist.name.includes('-gnux32') ||
dist.name.includes('-risc');
if (isSpecial) {
continue;
}

distributables.push(dist);
}
all.releases = distributables;
return all;
};

if (module === require.main) {
(async function () {
let normalize = require('../_webi/normalize.js');
let all = await Releases.latest();
all = normalize(all);
// just select the first 5 for demonstration
all.releases = all.releases.slice(0, 5);
console.info(JSON.stringify(all, null, 2));
})();
}
Loading