Giter Site home page Giter Site logo

uuidv7's Introduction

uuidv7: A JavaScript implementation of UUID version 7

npm License

import { uuidv7 } from "uuidv7";

const result = uuidv7(); // e.g., "017fe537-bb13-7c35-b52a-cb5490cce7be"

On browsers and Deno:

import { uuidv7 } from "https://unpkg.com/uuidv7@^1";

const result = uuidv7(); // e.g., "017fe537-bb13-7c35-b52a-cb5490cce7be"

Command-line interface:

$ npx uuidv7
0189f7e5-c883-7106-8272-ccb7fcba0575
$
$ npx uuidv7 -n 4
0189f7ea-ae2c-7809-8aeb-b819cf5e9e7f
0189f7ea-ae2f-72b9-9be8-9c3c5a60214f
0189f7ea-ae2f-72b9-9be8-9c3d224082ef
0189f7ea-ae2f-72b9-9be8-9c3e3e8abae8

See RFC 9562.

Field and bit layout

This implementation produces identifiers with the following bit layout:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          unix_ts_ms                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          unix_ts_ms           |  ver  |        counter        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|                        counter                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             rand                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Where:

  • The 48-bit unix_ts_ms field is dedicated to the Unix timestamp in milliseconds.
  • The 4-bit ver field is set at 0111.
  • The 42-bit counter field accommodates a counter that ensures the increasing order of IDs generated within a millisecond. The counter is incremented by one for each new ID and is reset to a random number when the unix_ts_ms changes.
  • The 2-bit var field is set at 10.
  • The remaining 32 rand bits are filled with a cryptographically strong random number.

The 42-bit counter is sufficiently large, so you do not usually need to worry about overflow, but in an extremely rare circumstance where it overflows, this library increments the unix_ts_ms field to continue instant monotonic generation. As a result, the unix_ts_ms may have a greater value than that of the system's real-time clock.

UUIDv7, by design, relies on the system clock to guarantee the monotonically increasing order of generated IDs. A generator may not be able to produce a monotonic sequence if the system clock goes backwards. This library ignores a clock rollback and reuses the previous unix_ts_ms unless the clock rollback is considered significant (by default, more than ten seconds). If such a significant rollback takes place, this library resets the generator by default and thus breaks the increasing order of generated IDs.

Other features

This library also supports the generation of UUID version 4:

import { uuidv4 } from "uuidv7";

const result = uuidv4(); // e.g., "83229083-75c3-4da5-8378-f88ef1a2bcd1"

uuidv7obj() and uuidv4obj() return an object that represents a UUID as a 16-byte byte array:

import { uuidv7obj } from "uuidv7";

const object = uuidv7obj();
console.log(object.bytes); // Uint8Array(16) [ ... ]
console.log(String(object)); // e.g., "017fea6b-b877-7aef-b422-57db9ed15e9d"

console.assert(object.getVariant() === "VAR_10");
console.assert(object.getVersion() === 7);

console.assert(object.clone().equals(object));
console.assert(object.compareTo(uuidv7obj()) < 0);

The V7Generator primitive allows to utilize a separate counter state from that of the global generator. It also provides a fallible variant of the generator function to give an absolute guarantee of the increasing order of UUIDs despite a significant rollback of the system timestamp source.

import { V7Generator } from "uuidv7";

const g = new V7Generator();
const x = g.generate();
const y = g.generateOrAbort();
if (y === undefined) {
  throw new Error("The clock went backwards by ten seconds!");
}
console.assert(x.compareTo(y) < 0);

See the API documentation for details.

CommonJS support

The CommonJS entry point is deprecated and provided for backward compatibility purposes only. The entry point is no longer tested and will be removed in the future.

License

Licensed under the Apache License, Version 2.0.

Related project

Uuid25 provides the conversion to/from a condensed, sortable, case-insensitive, 25-digit Base36 representation of UUID as well as other well-known textual representations. Uuid25 is available in several languages including Go, JavaScript, Python, Rust, and Swift.

import { uuidv7obj } from "uuidv7";
import { Uuid25 } from "uuid25";

const uuid25 = Uuid25.fromBytes(uuidv7obj().bytes);

console.log(uuid25.value);
// e.g., "03a2s63x4x0b9mev9e88i7gpm"

console.log(uuid25.toHex());
// e.g., "0189f8068f1a79b6bb21123c6accc25a"
console.log(uuid25.toHyphenated());
// e.g., "0189f806-8f1a-79b6-bb21-123c6accc25a"
console.log(uuid25.toBraced());
// e.g., "{0189f806-8f1a-79b6-bb21-123c6accc25a}"
console.log(uuid25.toUrn());
// e.g., "urn:uuid:0189f806-8f1a-79b6-bb21-123c6accc25a"

uuidv7's People

Contributors

liosk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

uuidv7's Issues

Export CommonJS in addition to ES Modules

Currently this project exports ESM packages on NPM. It would be useful to have CJS exported as well for projects that rely on that format.

Our Use Case

In our setup, we transpile our Typescript code into CJS. After installing uuidv7 from NPM the transpilation works fine (tsc), but we couldn't make our Jest to work.

We get SyntaxError: Unexpected token 'export' because out setup is for CJS, but the imported source from uuidv7 is ESM.

image

If we take the route to adjust our setup to ESM [1, 2] this goes away, but a bunch of other stuff break.

Proposed Solution

  1. Create separate tsconfig files, one for CJS and another for ESM;
  2. Update the build script to transpile twice, once for each tsconfig;
  3. Update package.json to export imports to the ESM dist folder and requires to the CJS dist folder.

Source: https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html

Test case failing because of uuidv7

TypeError: (0 , _uuidv7.uuidv7) is not a function

      16 |           return (
    > 17 |             <Tag key={uuidv7()} color="blue">
         |                             ^
      18 |               {rule.operator === 'between'
      19 |                 ? `${rule.value && rule.value.split(',')[0]} - ${rule.value && rule.value.split(',')[1]}`
      20 |                 : rule.value}


following test case is failing due to uuidv7

it('it should render search result tags fine with between operator', async () => {
    const rule = { field: 'firstName', operator: 'between', value: 'Stev' };
    render(
      <Provider store={store(rule)}>
        <SearchResultTags />
      </Provider>
    );

    expect(screen.getByText('Stev - undefined')).toBeInTheDocument();
    expect(screen.getByText('Stev - undefined')).toHaveClass('ant-tag-blue');
  });

How experimental is this library?

Hey!

I'm interested in using uuidv7 in my postgres database, but my cloud provider does not support it so I'm thinking I can generate them in the app layer. This library was the first hit but the readme mentions experimental, how experimental is it? Can I use it in production?

Cheers

how to access the UUID class?

I thought it might be possible to use https://liosk.github.io/uuidv7/classes/UUID.html#getVersion to know if a value is a uuid v7.

Is that so ad if true, how do I access UUID?

It does not seem te be exported as using:

import { UUID } from '@kripod/uuidv7'

give me this error:

getLastIdFromUrl.ts:2 Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/@kripod_uuidv7.js?v=674f4bc2' does not provide an export named 'UUID'

I am a bit surprised to get this error seeing https://github.com/LiosK/uuidv7/blob/v0.6.3/src/index.ts#L12C1-L12C8 though.

UUID Timestamp reported as Mar 1983?

I generated UUID 018e3f04-0218-7f62-8f86-6a3cfe5a42fb on 2024-03-14 22:02:48 however, when using the validator on https://uuid7.com/ it reports: UUIDv7 is valid with time: Sun, 27 Mar 1983 05:36:00 GMT

image

Is this a problem with this lib or a problem with uuidv7.com ?

[Feature request] create uuidv7 for a specific time

I want to migrate from uuidv4 to uuidv7, but I want to keep the timestamp info that uuidv7 has.
I have objects with createdAt timestamp, and I want to use those to migrate.
I think this would be a great addition to this package, and seems to be simple (not really sure about this :))

The signature could be something like uuidFromDate(new Date(2020-10-02)) and it could internally call the function UUID.fromFieldsV7. I tried to implement it with that function but failed miserably to understand the parameters.

This might be also useful for testing purposes

Thanks for the library, I'm using it in a project, very useful!!

Why do we allow rollback at all?

Thank you for writing up this library. I was reading through the library and everything looks good in my eyes except these few lines seemed very confusing to me. I thought the point of uuidv7 is it's always created in monotonically increasing order based on time and when time is equal then on count. Having rollback breaks that ordering and from my understanding would then break uuidv7. Why was this added then? Should the function instead be fallible (maybe throw an error) and force the user to retry?

Thanks

uuidv7/src/index.ts

Lines 354 to 364 in f30b7a7

if (unixTsMs > this.timestamp) {
this.timestamp = unixTsMs;
this.resetCounter();
} else if (unixTsMs + rollbackAllowance >= this.timestamp) {
// go on with previous timestamp if new one is not much smaller
this.counter++;
if (this.counter > MAX_COUNTER) {
// increment timestamp at counter overflow
this.timestamp++;
this.resetCounter();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.