Skip to content

Commit 04af5e3

Browse files
authored
Expand UUID versions (#91)
* update uuid stuff + start datatypes tests * reexport bignumber * some datatype tests
1 parent adab55d commit 04af5e3

File tree

12 files changed

+606
-228
lines changed

12 files changed

+606
-228
lines changed

etc/astra-db-ts.api.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,10 @@ export interface CollCodecSerDesFns {
394394
}
395395

396396
// @public (undocumented)
397-
export type CollDesCtx = BaseDesCtx<CollCodecSerDesFns>;
397+
export interface CollDesCtx extends BaseDesCtx<CollCodecSerDesFns> {
398+
// (undocumented)
399+
bigNumsEnabled: boolean;
400+
}
398401

399402
// @public
400403
export class Collection<WSchema extends SomeDoc = SomeDoc, RSchema extends WithId<SomeDoc> = FoundDoc<WSchema>> {
@@ -663,7 +666,10 @@ export interface CollectionVectorOptions {
663666
}
664667

665668
// @public (undocumented)
666-
export type CollSerCtx = BaseSerCtx<CollCodecSerDesFns>;
669+
export interface CollSerCtx extends BaseSerCtx<CollCodecSerDesFns> {
670+
// (undocumented)
671+
bigNumsEnabled: boolean;
672+
}
667673

668674
// @public
669675
export abstract class CommandEvent extends DataAPIClientEvent {
@@ -2084,17 +2090,19 @@ export class UUID implements CollCodec<typeof UUID>, TableCodec<typeof UUID> {
20842090
$uuid: string;
20852091
} | undefined)?];
20862092
[$SerializeForTable](ctx: TableSerCtx): readonly [0, (string | undefined)?];
2087-
constructor(uuid: string, validate?: boolean);
2093+
constructor(uuid: string, validate?: boolean, version?: number);
20882094
equals(other: unknown): boolean;
20892095
getTimestamp(): Date | undefined;
20902096
toString(): string;
2097+
static v1(msecs?: number, nsecs?: number): UUID;
20912098
static v4(): UUID;
2092-
static v7(): UUID;
2099+
static v6(msecs?: number, nsecs?: number): UUID;
2100+
static v7(msecs?: number): UUID;
20932101
readonly version: number;
20942102
}
20952103

20962104
// @public
2097-
export const uuid: (uuid: string | 4 | 7) => UUID;
2105+
export const uuid: (uuid: string | 1 | 4 | 6 | 7) => UUID;
20982106

20992107
// @public
21002108
export const vector: (v: DataAPIVectorLike) => DataAPIVector;
@@ -2147,6 +2155,9 @@ export interface WithTimeout<Timeouts extends keyof TimeoutDescriptor> {
21472155
timeout?: number | Pick<Partial<TimeoutDescriptor>, 'requestTimeoutMs' | Timeouts>;
21482156
}
21492157

2158+
2159+
export * from "bignumber.js";
2160+
21502161
// (No @packageDocumentation comment for this package)
21512162

21522163
```

package-lock.json

Lines changed: 20 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
"json-bigint": "^1.0.0",
7474
"safe-stable-stringify": "^2.4.3",
7575
"typed-emitter": "^2.1.0",
76-
"uuidv7": "^0.6.3"
76+
"uuid": "^11.0.3"
7777
},
7878
"engines": {
7979
"node": ">=18.0.0"

src/documents/collections/ser-des/ser-des.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,21 @@ import { BaseDesCtx, BaseSerCtx, CONTINUE } from '@/src/lib/api/ser-des/ctx';
1717
import { CollCodecs, CollCodecSerDesFns } from '@/src/documents/collections/ser-des/codecs';
1818
import { $SerializeForCollection } from '@/src/documents/collections/ser-des/constants';
1919
import { stringArraysEqual } from '@/src/lib/utils';
20+
import BigNumber from 'bignumber.js';
2021

2122
/**
2223
* @public
2324
*/
24-
export type CollSerCtx = BaseSerCtx<CollCodecSerDesFns>
25+
export interface CollSerCtx extends BaseSerCtx<CollCodecSerDesFns> {
26+
bigNumsEnabled: boolean,
27+
}
2528

2629
/**
2730
* @public
2831
*/
29-
export type CollDesCtx = BaseDesCtx<CollCodecSerDesFns>
32+
export interface CollDesCtx extends BaseDesCtx<CollCodecSerDesFns> {
33+
bigNumsEnabled: boolean,
34+
}
3035

3136
/**
3237
* @public
@@ -47,10 +52,12 @@ export class CollectionSerDes extends SerDes<CollCodecSerDesFns, CollSerCtx, Col
4752
}
4853

4954
public override adaptSerCtx(ctx: CollSerCtx): CollSerCtx {
55+
ctx.bigNumsEnabled = this._cfg?.enableBigNumbers === true;
5056
return ctx;
5157
}
5258

5359
public override adaptDesCtx(ctx: CollDesCtx): CollDesCtx {
60+
ctx.bigNumsEnabled = this._cfg?.enableBigNumbers === true;
5461
return ctx;
5562
}
5663

@@ -101,6 +108,10 @@ const DefaultCollectionSerDesCfg = {
101108
}
102109
}
103110
}
111+
112+
if (ctx.bigNumsEnabled && value instanceof BigNumber) {
113+
return ctx.done();
114+
}
104115
}
105116

106117
for (const codec of codecs.customGuard) {

src/documents/datatypes/uuid.ts

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,33 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { UUID as UUIDv7, uuidv4, uuidv7 } from 'uuidv7';
15+
import * as _uuid from 'uuid';
1616
import { $CustomInspect } from '@/src/lib/constants';
17-
import {
18-
CollCodec,
19-
type CollDesCtx,
20-
type CollSerCtx,
21-
TableCodec, TableDesCtx,
22-
TableSerCtx,
23-
} from '@/src/documents';
17+
import { CollCodec, type CollDesCtx, type CollSerCtx, TableCodec, TableDesCtx, TableSerCtx } from '@/src/documents';
2418
import { $DeserializeForCollection, $SerializeForCollection } from '@/src/documents/collections/ser-des/constants';
2519
import { $DeserializeForTable, $SerializeForTable } from '@/src/documents/tables/ser-des/constants';
2620

27-
const uuidRegex = new RegExp('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$');
28-
2921
/**
3022
* A shorthand function for `new UUID(uuid)`
3123
*
3224
* `uuid(4)` and `uuid(7)` are equivalent to `UUID.v4()` and `UUID.v7()`, respectively.
3325
*
3426
* @public
3527
*/
36-
export const uuid = (uuid: string | 4 | 7) =>
37-
(typeof uuid === 'string')
38-
? new UUID(uuid) :
39-
(uuid === 7)
40-
? UUID.v7()
41-
: UUID.v4();
28+
export const uuid = (uuid: string | 1 | 4 | 6 | 7) => {
29+
switch (uuid) {
30+
case 1:
31+
return UUID.v1();
32+
case 4:
33+
return UUID.v4();
34+
case 6:
35+
return UUID.v6();
36+
case 7:
37+
return UUID.v7();
38+
default:
39+
return new UUID(uuid);
40+
}
41+
};
4242

4343
/**
4444
* Represents a UUID that can be used as an _id in the DataAPI.
@@ -124,22 +124,23 @@ export class UUID implements CollCodec<typeof UUID>, TableCodec<typeof UUID> {
124124
*
125125
* @param uuid - The UUID string.
126126
* @param validate - Whether to validate the UUID string. Defaults to `true`.
127+
* @param version - The version of the UUID. If not provided, it is inferred from the UUID string.
127128
*/
128-
constructor(uuid: string, validate = true) {
129+
constructor(uuid: string, validate = true, version = 0) {
129130
if (validate) {
130131
if (typeof <unknown>uuid !== 'string') {
131-
throw new Error('UUID must be a string');
132+
throw new Error(`UUID '${uuid}' must be a string`);
132133
}
133134

134-
if (uuid.length !== 36 || !uuidRegex.test(uuid)) {
135-
throw new Error('UUID must be a 36-character hex string');
135+
if (!_uuid.validate(uuid)) {
136+
throw new Error(`UUID '${uuid}' is not valid`);
136137
}
137138
}
138139

139140
this.#raw = uuid.toLowerCase();
140141

141142
Object.defineProperty(this, 'version', {
142-
value: parseInt(this.#raw[14], 16),
143+
value: version || parseInt(this.#raw[14], 16),
143144
});
144145

145146
Object.defineProperty(this, $CustomInspect, {
@@ -169,12 +170,19 @@ export class UUID implements CollCodec<typeof UUID>, TableCodec<typeof UUID> {
169170
}
170171

171172
/**
172-
* Returns the timestamp of a v7 UUID. If the UUID is not a v7 UUID, this method returns `undefined`.
173+
* Returns the timestamp of a v1 or v7 UUID. If the UUID is not a v1 or v7 UUID, this method returns `undefined`.
173174
*
174-
* @returns The timestamp of the UUID, or `undefined` if the UUID is not a v7 UUID.
175+
* @returns The timestamp of the UUID, or `undefined` if the UUID is not a v1 or v7 UUID.
175176
*/
176177
public getTimestamp(): Date | undefined {
177-
return timestampFromUUID(this);
178+
switch (this.version) {
179+
case 1:
180+
return uuidV1Timestamp(this);
181+
case 7:
182+
return uuidV7Timestamp(this);
183+
default:
184+
return undefined;
185+
}
178186
}
179187

180188
/**
@@ -184,29 +192,47 @@ export class UUID implements CollCodec<typeof UUID>, TableCodec<typeof UUID> {
184192
return this.#raw;
185193
}
186194

195+
/**
196+
* Creates a new v1 UUID.
197+
*/
198+
public static v1(msecs?: number, nsecs?: number): UUID {
199+
return new UUID(_uuid.v1({ msecs, nsecs }), false, 1);
200+
}
201+
187202
/**
188203
* Creates a new v4 UUID.
189204
*/
190205
public static v4(): UUID {
191-
return new UUID(uuidv4(), false);
206+
return new UUID(_uuid.v4(), false, 4);
207+
}
208+
209+
/**
210+
* Creates a new v6 UUID.
211+
*/
212+
public static v6(msecs?: number, nsecs?: number): UUID {
213+
return new UUID(_uuid.v6({ msecs, nsecs }), false, 6);
192214
}
193215

194216
/**
195217
* Creates a new v7 UUID.
196218
*/
197-
public static v7(): UUID {
198-
return new UUID(uuidv7(), false);
219+
public static v7(msecs?: number): UUID {
220+
return new UUID(_uuid.v7({ msecs }), false, 7);
199221
}
200222
}
201223

202-
function timestampFromUUID(uuid: UUID): Date | undefined {
203-
if (uuid.version !== 7) {
204-
return undefined;
205-
}
224+
const MAGIC_NUMBER = 1221929280000000 * 100;
206225

226+
function uuidV1Timestamp(uuid: UUID): Date | undefined {
227+
const arr = uuid.toString().split('-');
228+
const timeStr = [arr[2].substring(1), arr[1], arr[0]].join('');
229+
const timeInt = parseInt(timeStr, 16);
230+
return new Date(~~((timeInt - MAGIC_NUMBER) / 10000));
231+
}
232+
233+
function uuidV7Timestamp(uuid: UUID): Date | undefined {
207234
const timestampBytes = new Uint8Array(8);
208-
timestampBytes.set(new Uint8Array(UUIDv7.parse(uuid.toString()).bytes.buffer.slice(0, 6)), 2);
235+
timestampBytes.set(new Uint8Array(_uuid.parse(uuid.toString()).buffer.slice(0, 6)), 2);
209236
const timestampMs = new DataView(timestampBytes.buffer).getBigUint64(0);
210-
211237
return new Date(Number(timestampMs));
212238
}

src/documents/datatypes/vector.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,6 @@ export class DataAPIVector implements CollCodec<typeof DataAPIVector>, TableCode
9898
? vector.raw()
9999
: vector;
100100

101-
// this[$SerializeForTable] = () => serialize(this.#vector);
102-
// this[$SerializeForCollection] = this[$SerializeForTable];
103-
104101
Object.defineProperty(this, $CustomInspect, {
105102
value: this.toString,
106103
});

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ export * from './db';
1717
export * from './documents';
1818
export * from './administration';
1919
export * from './lib';
20+
export * from 'bignumber.js';

0 commit comments

Comments
 (0)