From 257adec36da713c0016c20abde81b25c01f02fc1 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 15 Oct 2024 00:07:35 +0000 Subject: [PATCH] feat: add uuidv7 --- uuidv7/README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++ uuidv7/install.ps1 | 55 ++++++++++++++++++++++ uuidv7/install.sh | 40 ++++++++++++++++ uuidv7/releases.js | 41 ++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 uuidv7/README.md create mode 100644 uuidv7/install.ps1 create mode 100644 uuidv7/install.sh create mode 100644 uuidv7/releases.js diff --git a/uuidv7/README.md b/uuidv7/README.md new file mode 100644 index 00000000..71f0bf83 --- /dev/null +++ b/uuidv7/README.md @@ -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 diff --git a/uuidv7/install.ps1 b/uuidv7/install.ps1 new file mode 100644 index 00000000..e2904fb1 --- /dev/null +++ b/uuidv7/install.ps1 @@ -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 diff --git a/uuidv7/install.sh b/uuidv7/install.sh new file mode 100644 index 00000000..f911b2e7 --- /dev/null +++ b/uuidv7/install.sh @@ -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 diff --git a/uuidv7/releases.js b/uuidv7/releases.js new file mode 100644 index 00000000..da385121 --- /dev/null +++ b/uuidv7/releases.js @@ -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)); + })(); +}