Skip to content

Commit

Permalink
feat: Use uuid v7 in stub database adapter (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-McFarlin authored Jun 3, 2024
1 parent af495a9 commit 1e8ea64
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
3 changes: 2 additions & 1 deletion packages/entity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dataloader": "^2.0.0",
"es6-error": "^4.1.1",
"invariant": "^2.2.4",
"uuid": "^8.3.0"
"uuid": "^8.3.0",
"uuidv7": "^1.0.0"
}
}
4 changes: 2 additions & 2 deletions packages/entity/src/utils/testing/StubDatabaseAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import invariant from 'invariant';
import { v4 as uuidv4 } from 'uuid';
import { uuidv7 } from 'uuidv7';

import EntityConfiguration from '../../EntityConfiguration';
import EntityDatabaseAdapter, {
Expand Down Expand Up @@ -163,7 +163,7 @@ export default class StubDatabaseAdapter<T> extends EntityDatabaseAdapter<T> {
`No schema field found for ${String(this.entityConfiguration2.idField)}`
);
if (idSchemaField instanceof StringField) {
return uuidv4();
return uuidv7();
} else if (idSchemaField instanceof IntField) {
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,26 @@ describe(StubDatabaseAdapter, () => {
databaseAdapter.getObjectCollectionForTable(testEntityConfiguration.tableName)
).toHaveLength(1);
});

it('inserts a record with valid v7 id', async () => {
const expectedTime = new Date('2024-06-03T20:16:33.761Z');

jest.useFakeTimers({
now: expectedTime,
});

const queryContext = instance(mock(EntityQueryContext));
const databaseAdapter = new StubDatabaseAdapter<TestFields>(
testEntityConfiguration,
new Map()
);
const result = await databaseAdapter.insertAsync(queryContext, {
stringField: 'hello',
});

const ts = getTimeFromUUIDv7(result.customIdField);
expect(ts).toEqual(expectedTime);
});
});

describe('updateAsync', () => {
Expand Down Expand Up @@ -506,3 +526,23 @@ describe(StubDatabaseAdapter, () => {
});
});
});

const UUIDV7_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

/**
* Returns the Date object encoded in the first 48 bits of the given UUIDv7.
* @throws TypeError if the UUID is not version 7
*/
function getTimeFromUUIDv7(uuid: string): Date {
if (!UUIDV7_REGEX.test(uuid)) {
throw new TypeError(`UUID must be version 7 to get its timestamp`);
}

// The first 48 bits = 12 hex characters of the UUID encode the timestamp in big endian
const hexCharacters = uuid.replaceAll('-', '').split('', 12);
const milliseconds = hexCharacters.reduce(
(milliseconds, character) => milliseconds * 16 + parseInt(character, 16),
0
);
return new Date(milliseconds);
}

0 comments on commit 1e8ea64

Please sign in to comment.