mirror of
https://github.com/denoland/std.git
synced 2024-11-22 04:59:05 +00:00
feat(ulid): add single-export endpoints (#5426)
This commit is contained in:
parent
94fff63978
commit
0f4ff71948
2
.github/typos.toml
vendored
2
.github/typos.toml
vendored
@ -16,5 +16,5 @@ extend-exclude = [
|
||||
"media_types/vendor",
|
||||
"http/testdata",
|
||||
"http/user_agent.ts",
|
||||
"ulid/mod.ts"
|
||||
"ulid/*.ts"
|
||||
]
|
||||
|
53
ulid/decode_time.ts
Normal file
53
ulid/decode_time.ts
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// Copyright 2023 Yoshiya Hinosawa. All rights reserved. MIT license.
|
||||
// Copyright 2017 Alizain Feerasta. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import {
|
||||
ENCODING,
|
||||
ENCODING_LEN,
|
||||
TIME_LEN,
|
||||
TIME_MAX,
|
||||
ULID_LEN,
|
||||
} from "./_util.ts";
|
||||
|
||||
/**
|
||||
* Extracts the number of milliseconds since the Unix epoch that had passed when
|
||||
* the ULID was generated. If the ULID is malformed, an error will be thrown.
|
||||
*
|
||||
* @example Decode the time from a ULID
|
||||
* ```ts
|
||||
* import { decodeTime, ulid } from "@std/ulid";
|
||||
* import { assertEquals } from "@std/assert";
|
||||
*
|
||||
* const timestamp = 150_000;
|
||||
* const ulidString = ulid(timestamp);
|
||||
*
|
||||
* assertEquals(decodeTime(ulidString), timestamp);
|
||||
* ```
|
||||
*
|
||||
* @param ulid The ULID to extract the timestamp from.
|
||||
* @returns The number of milliseconds since the Unix epoch that had passed when the ULID was generated.
|
||||
*/
|
||||
export function decodeTime(ulid: string): number {
|
||||
if (ulid.length !== ULID_LEN) {
|
||||
throw new Error(`ULID must be exactly ${ULID_LEN} characters long`);
|
||||
}
|
||||
const time = ulid
|
||||
.substring(0, TIME_LEN)
|
||||
.split("")
|
||||
.reverse()
|
||||
.reduce((carry, char, index) => {
|
||||
const encodingIndex = ENCODING.indexOf(char);
|
||||
if (encodingIndex === -1) {
|
||||
throw new Error(`Invalid ULID character found: ${char}`);
|
||||
}
|
||||
return (carry += encodingIndex * Math.pow(ENCODING_LEN, index));
|
||||
}, 0);
|
||||
if (time > TIME_MAX) {
|
||||
throw new RangeError(
|
||||
`ULID timestamp component exceeds maximum value of ${TIME_MAX}`,
|
||||
);
|
||||
}
|
||||
return time;
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
{
|
||||
"name": "@std/ulid",
|
||||
"version": "1.0.0-rc.3",
|
||||
"exports": "./mod.ts"
|
||||
"exports": {
|
||||
".": "./mod.ts",
|
||||
"./decoce-time": "./decode_time.ts",
|
||||
"./monotonic-ulid": "./monotonic_ulid.ts",
|
||||
"./ulid": "./ulid.ts"
|
||||
}
|
||||
}
|
||||
|
135
ulid/mod.ts
135
ulid/mod.ts
@ -44,135 +44,6 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import {
|
||||
encodeRandom,
|
||||
encodeTime,
|
||||
ENCODING,
|
||||
ENCODING_LEN,
|
||||
monotonicFactory,
|
||||
TIME_LEN,
|
||||
TIME_MAX,
|
||||
ULID_LEN,
|
||||
} from "./_util.ts";
|
||||
|
||||
/**
|
||||
* Extracts the number of milliseconds since the Unix epoch that had passed when
|
||||
* the ULID was generated. If the ULID is malformed, an error will be thrown.
|
||||
*
|
||||
* @example Decode the time from a ULID
|
||||
* ```ts
|
||||
* import { decodeTime, ulid } from "@std/ulid";
|
||||
* import { assertEquals } from "@std/assert";
|
||||
*
|
||||
* const timestamp = 150_000;
|
||||
* const ulidString = ulid(timestamp);
|
||||
*
|
||||
* assertEquals(decodeTime(ulidString), timestamp);
|
||||
* ```
|
||||
*
|
||||
* @param ulid The ULID to extract the timestamp from.
|
||||
* @returns The number of milliseconds since the Unix epoch that had passed when the ULID was generated.
|
||||
*/
|
||||
export function decodeTime(ulid: string): number {
|
||||
if (ulid.length !== ULID_LEN) {
|
||||
throw new Error(`ULID must be exactly ${ULID_LEN} characters long`);
|
||||
}
|
||||
const time = ulid
|
||||
.substring(0, TIME_LEN)
|
||||
.split("")
|
||||
.reverse()
|
||||
.reduce((carry, char, index) => {
|
||||
const encodingIndex = ENCODING.indexOf(char);
|
||||
if (encodingIndex === -1) {
|
||||
throw new Error(`Invalid ULID character found: ${char}`);
|
||||
}
|
||||
return (carry += encodingIndex * Math.pow(ENCODING_LEN, index));
|
||||
}, 0);
|
||||
if (time > TIME_MAX) {
|
||||
throw new RangeError(
|
||||
`ULID timestamp component exceeds maximum value of ${TIME_MAX}`,
|
||||
);
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
const defaultMonotonicUlid = monotonicFactory();
|
||||
|
||||
/**
|
||||
* Generate a ULID that monotonically increases even for the same millisecond,
|
||||
* optionally passing the current time. If the current time is not passed, it
|
||||
* will default to `Date.now()`.
|
||||
*
|
||||
* Unlike the {@linkcode ulid} function, this function is guaranteed to return
|
||||
* strictly increasing ULIDs, even for the same seed time, but only if the seed
|
||||
* time only ever increases. If the seed time ever goes backwards, the ULID will
|
||||
* still be generated, but it will not be guaranteed to be monotonic with
|
||||
* previous ULIDs for that same seed time.
|
||||
*
|
||||
* @example Generate a monotonic ULID
|
||||
* ```ts no-assert
|
||||
* import { monotonicUlid } from "@std/ulid";
|
||||
*
|
||||
* monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAS
|
||||
* monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAT
|
||||
* monotonicUlid(); // 01HYFKHHX8H4BRY8BYHAV1BZ2T
|
||||
* ```
|
||||
*
|
||||
* @example Generate a monotonic ULID with a seed time
|
||||
* ```ts no-assert
|
||||
* import { monotonicUlid } from "@std/ulid";
|
||||
*
|
||||
* // Strict ordering for the same timestamp, by incrementing the least-significant random bit by 1
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1Q
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1R
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1S
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1T
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1U
|
||||
*
|
||||
* // A different timestamp will reset the random bits
|
||||
* monotonicUlid(150001); // 0000004JFHJJ2Z7X64FN2B4F1P
|
||||
*
|
||||
* // A previous seed time will not guarantee ordering, and may result in a
|
||||
* // ULID lower than one with the same seed time generated previously
|
||||
* monotonicUlid(150000); // 0000004JFJ7XF6D76ES95SZR0X
|
||||
* ```
|
||||
*
|
||||
* @param seedTime The time to base the ULID on, in milliseconds since the Unix epoch. Defaults to `Date.now()`.
|
||||
* @returns A ULID that is guaranteed to be strictly increasing for the same seed time.
|
||||
*/
|
||||
export function monotonicUlid(seedTime: number = Date.now()): string {
|
||||
return defaultMonotonicUlid(seedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a ULID, optionally based on a given timestamp. If the timestamp is
|
||||
* not passed, it will default to `Date.now()`.
|
||||
*
|
||||
* Multiple calls to this function with the same seed time will not guarantee
|
||||
* that the ULIDs will be strictly increasing, even if the seed time is the
|
||||
* same. For that, use the {@linkcode monotonicUlid} function.
|
||||
*
|
||||
* @example Generate a ULID
|
||||
* ```ts no-assert
|
||||
* import { ulid } from "@std/ulid";
|
||||
*
|
||||
* ulid(); // 01HYFKMDF3HVJ4J3JZW8KXPVTY
|
||||
* ulid(); // 01HYFKMDF3D2P7G502B9Z2VKV0
|
||||
* ulid(); // 01HYFKMDZQ7JD17CRKDXQSZ3Z4
|
||||
* ```
|
||||
*
|
||||
* @example Generate a ULID with a seed time
|
||||
* ```ts no-assert
|
||||
* import { ulid } from "@std/ulid";
|
||||
*
|
||||
* ulid(150000); // 0000004JFG3EKDRE04TVVDJW7K
|
||||
* ulid(150000); // 0000004JFGN0KHBH0447AK895X
|
||||
* ulid(150000); // 0000004JFGMRDH0PN7SM8BZN06
|
||||
* ```
|
||||
*
|
||||
* @param seedTime The time to base the ULID on, in milliseconds since the Unix epoch. Defaults to `Date.now()`.
|
||||
* @returns A ULID.
|
||||
*/
|
||||
export function ulid(seedTime: number = Date.now()): string {
|
||||
return encodeTime(seedTime) + encodeRandom();
|
||||
}
|
||||
export * from "./decode_time.ts";
|
||||
export * from "./monotonic_ulid.ts";
|
||||
export * from "./ulid.ts";
|
||||
|
54
ulid/monotonic_ulid.ts
Normal file
54
ulid/monotonic_ulid.ts
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// Copyright 2023 Yoshiya Hinosawa. All rights reserved. MIT license.
|
||||
// Copyright 2017 Alizain Feerasta. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import { monotonicFactory } from "./_util.ts";
|
||||
|
||||
const defaultMonotonicUlid = monotonicFactory();
|
||||
|
||||
/**
|
||||
* Generate a ULID that monotonically increases even for the same millisecond,
|
||||
* optionally passing the current time. If the current time is not passed, it
|
||||
* will default to `Date.now()`.
|
||||
*
|
||||
* Unlike the {@linkcode ulid} function, this function is guaranteed to return
|
||||
* strictly increasing ULIDs, even for the same seed time, but only if the seed
|
||||
* time only ever increases. If the seed time ever goes backwards, the ULID will
|
||||
* still be generated, but it will not be guaranteed to be monotonic with
|
||||
* previous ULIDs for that same seed time.
|
||||
*
|
||||
* @example Generate a monotonic ULID
|
||||
* ```ts no-assert
|
||||
* import { monotonicUlid } from "@std/ulid";
|
||||
*
|
||||
* monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAS
|
||||
* monotonicUlid(); // 01HYFKHG5F8RHM2PM3D7NSTDAT
|
||||
* monotonicUlid(); // 01HYFKHHX8H4BRY8BYHAV1BZ2T
|
||||
* ```
|
||||
*
|
||||
* @example Generate a monotonic ULID with a seed time
|
||||
* ```ts no-assert
|
||||
* import { monotonicUlid } from "@std/ulid";
|
||||
*
|
||||
* // Strict ordering for the same timestamp, by incrementing the least-significant random bit by 1
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1Q
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1R
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1S
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1T
|
||||
* monotonicUlid(150000); // 0000004JFHJJ2Z7X64FN2B4F1U
|
||||
*
|
||||
* // A different timestamp will reset the random bits
|
||||
* monotonicUlid(150001); // 0000004JFHJJ2Z7X64FN2B4F1P
|
||||
*
|
||||
* // A previous seed time will not guarantee ordering, and may result in a
|
||||
* // ULID lower than one with the same seed time generated previously
|
||||
* monotonicUlid(150000); // 0000004JFJ7XF6D76ES95SZR0X
|
||||
* ```
|
||||
*
|
||||
* @param seedTime The time to base the ULID on, in milliseconds since the Unix epoch. Defaults to `Date.now()`.
|
||||
* @returns A ULID that is guaranteed to be strictly increasing for the same seed time.
|
||||
*/
|
||||
export function monotonicUlid(seedTime: number = Date.now()): string {
|
||||
return defaultMonotonicUlid(seedTime);
|
||||
}
|
39
ulid/ulid.ts
Normal file
39
ulid/ulid.ts
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// Copyright 2023 Yoshiya Hinosawa. All rights reserved. MIT license.
|
||||
// Copyright 2017 Alizain Feerasta. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import { encodeRandom, encodeTime } from "./_util.ts";
|
||||
|
||||
/**
|
||||
* Generate a ULID, optionally based on a given timestamp. If the timestamp is
|
||||
* not passed, it will default to `Date.now()`.
|
||||
*
|
||||
* Multiple calls to this function with the same seed time will not guarantee
|
||||
* that the ULIDs will be strictly increasing, even if the seed time is the
|
||||
* same. For that, use the {@linkcode monotonicUlid} function.
|
||||
*
|
||||
* @example Generate a ULID
|
||||
* ```ts no-assert
|
||||
* import { ulid } from "@std/ulid";
|
||||
*
|
||||
* ulid(); // 01HYFKMDF3HVJ4J3JZW8KXPVTY
|
||||
* ulid(); // 01HYFKMDF3D2P7G502B9Z2VKV0
|
||||
* ulid(); // 01HYFKMDZQ7JD17CRKDXQSZ3Z4
|
||||
* ```
|
||||
*
|
||||
* @example Generate a ULID with a seed time
|
||||
* ```ts no-assert
|
||||
* import { ulid } from "@std/ulid";
|
||||
*
|
||||
* ulid(150000); // 0000004JFG3EKDRE04TVVDJW7K
|
||||
* ulid(150000); // 0000004JFGN0KHBH0447AK895X
|
||||
* ulid(150000); // 0000004JFGMRDH0PN7SM8BZN06
|
||||
* ```
|
||||
*
|
||||
* @param seedTime The time to base the ULID on, in milliseconds since the Unix epoch. Defaults to `Date.now()`.
|
||||
* @returns A ULID.
|
||||
*/
|
||||
export function ulid(seedTime: number = Date.now()): string {
|
||||
return encodeTime(seedTime) + encodeRandom();
|
||||
}
|
Loading…
Reference in New Issue
Block a user