UNPKG

tiny-ulid

Version:
182 lines (181 loc) • 6.62 kB
#!/usr/bin/env node import { decodeUlid, getUlidBufferTime, isUlid, makeUlid, toUlidBuffer, ulidBufferToString } from "../default.js" import { createConsola } from "consola" const consola = createConsola({ stdout: process.stderr }) try { const options = new Map(), commands = [] function fatal(message) { consola.fatal(message) process.exit(1) } for (const argument of process.argv.slice(2)) if ("-" == argument[0]) { const argumentEqualsIndex = argument.indexOf("=") let key, value if (-1 == argumentEqualsIndex) key = argument else { key = argument.slice(0, argumentEqualsIndex) value = argument.slice(argumentEqualsIndex + 1) } if ("-" == argument[1]) { const name = key.slice(2) options.has(name) && fatal(`Option --${name} specified twice.`) options.set(name, value) } else for (const name of key.slice(1)) { options.has(name) && fatal(`Option -${name} specified twice.`) options.set(name, value) } } else { options.size && fatal("Options must come last.") commands.push(argument) } consola.debug(commands) consola.debug(options) if ("version" == commands[0] || options.has("version")) { console.log("1.0.0") process.exit() } const poppedOptions = new Set() let complainedAboutUnrecognisedOptions = !1 const popOption = (name, { requirePresence = !1, requireValue = !1 } = {}) => { if (complainedAboutUnrecognisedOptions) { consola.error(Error("Tried to pop option after already complaining")) process.exit(2) } if (poppedOptions.has(name)) { consola.error(Error(`Tried to pop option --${name} twice.`)) process.exit(2) } poppedOptions.add(name) if (options.has(name)) { const value = options.get(name) requireValue && null == value && fatal(`Option --${name} missing value.`) options.delete(name) return value } requirePresence && fatal(`Option --${name} missing.`) }, popFlagOption = name => { if (complainedAboutUnrecognisedOptions) { consola.error(Error("Tried to pop option after already complaining")) process.exit(2) } if (poppedOptions.has(name)) { consola.error(Error(`Tried to pop option --${name} twice.`)) process.exit(2) } poppedOptions.add(name) if (options.has(name)) { null != options.get(name) && fatal(`Option --${name} must not have value.`) options.delete(name) return !0 } return !1 }, complainAboutUnrecognisedOptions = () => { complainedAboutUnrecognisedOptions = !0 options.size && fatal(`Unknown option: --${options.keys().next().value}.`) } if (commands.length) { if ("get-time" == commands[0]) { commands.length < 2 && fatal("Missing argument.") commands.length > 2 && fatal("Too many arguments.") const ulid = commands[1] isUlid(ulid) || fatal("Invalid ULID.") const time = getUlidBufferTime(decodeUlid(ulid)), formatOption = popOption("format", { requireValue: !0 }) complainAboutUnrecognisedOptions() "locale" == formatOption || null == formatOption ? console.log(new Date(time).toLocaleString()) : "locale-full" == formatOption ? console.log(new Date(time).toLocaleString(void 0, { dateStyle: "full", timeStyle: "full" })) : "iso" == formatOption ? console.log(new Date(time).toISOString()) : "epoch-milliseconds" == formatOption ? console.log(time + "") : fatal( `Unrecognised format ${JSON.stringify(formatOption)}.\nValid formats are "locale", "locale-full", "iso", and "epoch-milliseconds".` ) process.exit() } if ("to-hex" == commands[0]) { commands.length < 2 && fatal("Missing argument.") commands.length > 2 && fatal("Too many arguments.") const ulid = commands[1] isUlid(ulid) || fatal("Invalid ULID.") const ulidBuffer = decodeUlid(ulid) consola.debug(ulidBuffer) const lowercaseOption = popFlagOption("lowercase"), seperator = popOption("seperator", { requireValue: !0 }) ?? " " complainAboutUnrecognisedOptions() const result = [...new Uint8Array(ulidBuffer)] .map(byte => { let result = byte.toString(16) lowercaseOption || (result = result.toUpperCase()) return result.padStart(2, "0") }) .join(seperator) console.log(result) process.exit() } if ("to-base64" == commands[0]) { commands.length < 2 && fatal("Missing argument.") commands.length > 2 && fatal("Too many arguments.") const urlOption = popFlagOption("url") complainAboutUnrecognisedOptions() const ulid = commands[1] isUlid(ulid) || fatal("Invalid ULID.") const ulidBuffer = decodeUlid(ulid) consola.debug(ulidBuffer) const result = Buffer.from(ulidBuffer).toString(urlOption ? "base64url" : "base64") console.log(result) process.exit() } if ("from-hex" == commands[0]) { commands.length < 2 && fatal("Missing argument.") commands.length > 2 && fatal("Too many arguments.") const hex = commands[1].replace(/\s/g, "") hex.length < 32 && fatal("Hex too short, expected 32 hex characters.") hex.length > 32 && fatal("Hex too long, expected 32 hex characters.") ;/^[\da-f]+$/i.test(hex) || fatal("Invalid hex.") const buffer = Buffer.from(hex, "hex") if (!(buffer.buffer instanceof ArrayBuffer)) { consola.error(Error("Got " + buffer.buffer)) process.exit(2) } const ulidBuffer = toUlidBuffer(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.length)) console.log(ulidBufferToString(ulidBuffer)) process.exit() } if ("from-base64" == commands[0]) { commands.length < 2 && fatal("Missing argument.") commands.length > 2 && fatal("Too many arguments.") const base64 = commands[1].replace(/[\s=]/g, "") base64.length < 22 && fatal("Base64 too short, expected 22 base64 characters.") base64.length > 22 && fatal("Base64 too long, expected 22 base64 characters.") ;/^[a-f\d+/-_]+$/i.test(base64) || fatal("Invalid Base64.") "A" != base64[21] && "Q" != base64[21] && "g" != base64[21] && "w" != base64[21] && fatal('Last character of base64 can only be one of "AQgw".') const buffer = Buffer.from(base64, "base64") if (!(buffer.buffer instanceof ArrayBuffer)) { consola.error(Error("Got " + buffer.buffer)) process.exit(2) } const ulidBuffer = toUlidBuffer(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.length)) console.log(ulidBufferToString(ulidBuffer)) process.exit() } fatal(`Unknown command: ${commands[0]}.`) } complainAboutUnrecognisedOptions() console.log(makeUlid()) process.exit() } catch (error) { consola.error(error) process.exit(2) }