@thi.ng/ksuid 3.2.19 → 3.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/aksuid.js +59 -64
- package/api.js +0 -1
- package/ksuid32.js +30 -32
- package/ksuid64.js +36 -38
- package/package.json +12 -9
- package/ulid.js +37 -44
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
package/aksuid.js
CHANGED
|
@@ -2,68 +2,63 @@ import { BASE62 } from "@thi.ng/base-n/62";
|
|
|
2
2
|
import { assert } from "@thi.ng/errors/assert";
|
|
3
3
|
import { randomBytes, randomBytesFrom } from "@thi.ng/random/random-bytes";
|
|
4
4
|
import { padLeft } from "@thi.ng/strings/pad-left";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
size;
|
|
12
|
-
encodedSize;
|
|
13
|
-
base;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
u32(buf, i = 0) {
|
|
63
|
-
return (((buf[i] << 24) |
|
|
64
|
-
(buf[i + 1] << 16) |
|
|
65
|
-
(buf[i + 2] << 8) |
|
|
66
|
-
buf[i + 3]) >>>
|
|
67
|
-
0);
|
|
68
|
-
}
|
|
5
|
+
class AKSUID {
|
|
6
|
+
constructor(epochSize, opts) {
|
|
7
|
+
this.epochSize = epochSize;
|
|
8
|
+
this.base = opts.base || BASE62;
|
|
9
|
+
this.rnd = opts.rnd;
|
|
10
|
+
this.epoch = opts.epoch;
|
|
11
|
+
this.size = this.epochSize + opts.bytes;
|
|
12
|
+
this.encodedSize = this.base.size(2 ** (this.size * 8) - 1);
|
|
13
|
+
this.pad = padLeft(this.encodedSize, this.base.base[0]);
|
|
14
|
+
this.tmp = new Uint8Array(this.size);
|
|
15
|
+
}
|
|
16
|
+
size;
|
|
17
|
+
encodedSize;
|
|
18
|
+
base;
|
|
19
|
+
epoch;
|
|
20
|
+
tmp;
|
|
21
|
+
rnd;
|
|
22
|
+
pad;
|
|
23
|
+
next() {
|
|
24
|
+
return this.format(this.nextBinary(this.tmp));
|
|
25
|
+
}
|
|
26
|
+
nextBinary(buf) {
|
|
27
|
+
buf = this.timeOnlyBinary(void 0, buf);
|
|
28
|
+
return this.rnd ? randomBytesFrom(this.rnd, buf, this.epochSize) : randomBytes(buf, this.epochSize);
|
|
29
|
+
}
|
|
30
|
+
timeOnly(epoch) {
|
|
31
|
+
return this.format(
|
|
32
|
+
this.timeOnlyBinary(epoch, this.tmp.fill(0, this.epochSize))
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
fromEpoch(epoch) {
|
|
36
|
+
return this.format(this.fromEpochBinary(epoch, this.tmp));
|
|
37
|
+
}
|
|
38
|
+
fromEpochBinary(epoch, buf) {
|
|
39
|
+
buf = this.timeOnlyBinary(epoch, buf);
|
|
40
|
+
return this.rnd ? randomBytesFrom(this.rnd, buf, this.epochSize) : randomBytes(buf, this.epochSize);
|
|
41
|
+
}
|
|
42
|
+
format(buf) {
|
|
43
|
+
this.ensureSize(buf);
|
|
44
|
+
return this.pad(this.base.encodeBytes(buf));
|
|
45
|
+
}
|
|
46
|
+
ensureSize(buf) {
|
|
47
|
+
assert(
|
|
48
|
+
buf.length == this.size,
|
|
49
|
+
`illegal KSUID size, expected ${this.size} bytes`
|
|
50
|
+
);
|
|
51
|
+
return buf;
|
|
52
|
+
}
|
|
53
|
+
ensureTime(t, max) {
|
|
54
|
+
assert(t >= 0, "configured base epoch must be in the past");
|
|
55
|
+
max && assert(t <= max, `given epoch is out of range ([0...${max}])`);
|
|
56
|
+
return t;
|
|
57
|
+
}
|
|
58
|
+
u32(buf, i = 0) {
|
|
59
|
+
return (buf[i] << 24 | buf[i + 1] << 16 | buf[i + 2] << 8 | buf[i + 3]) >>> 0;
|
|
60
|
+
}
|
|
69
61
|
}
|
|
62
|
+
export {
|
|
63
|
+
AKSUID
|
|
64
|
+
};
|
package/api.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/ksuid32.js
CHANGED
|
@@ -1,35 +1,33 @@
|
|
|
1
1
|
import { AKSUID } from "./aksuid.js";
|
|
2
2
|
const MAX_EPOCH = -1 >>> 0;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
3
|
+
class KSUID32 extends AKSUID {
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
super(4, {
|
|
6
|
+
epoch: 16e11,
|
|
7
|
+
bytes: 16,
|
|
8
|
+
...opts
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
timeOnlyBinary(epoch = Date.now(), buf) {
|
|
12
|
+
buf = buf || new Uint8Array(this.size);
|
|
13
|
+
const t = this.ensureTime((epoch - this.epoch) / 1e3, MAX_EPOCH) >>> 0;
|
|
14
|
+
buf[0] = t >>> 24;
|
|
15
|
+
buf[1] = t >> 16 & 255;
|
|
16
|
+
buf[2] = t >> 8 & 255;
|
|
17
|
+
buf[3] = t & 255;
|
|
18
|
+
return buf;
|
|
19
|
+
}
|
|
20
|
+
parse(id) {
|
|
21
|
+
const buf = this.tmp;
|
|
22
|
+
this.base.decodeBytes(id, buf);
|
|
23
|
+
return {
|
|
24
|
+
epoch: this.u32(buf) * 1e3 + this.epoch,
|
|
25
|
+
id: buf.slice(4)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
export const defKSUID32 = (opts) => new KSUID32(opts);
|
|
29
|
+
const defKSUID32 = (opts) => new KSUID32(opts);
|
|
30
|
+
export {
|
|
31
|
+
KSUID32,
|
|
32
|
+
defKSUID32
|
|
33
|
+
};
|
package/ksuid64.js
CHANGED
|
@@ -1,40 +1,38 @@
|
|
|
1
1
|
import { AKSUID } from "./aksuid.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
2
|
+
class KSUID64 extends AKSUID {
|
|
3
|
+
constructor(opts) {
|
|
4
|
+
super(8, {
|
|
5
|
+
epoch: 16e11,
|
|
6
|
+
bytes: 12,
|
|
7
|
+
...opts
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
timeOnlyBinary(epoch = Date.now(), buf) {
|
|
11
|
+
buf = buf || new Uint8Array(this.size);
|
|
12
|
+
const t = this.ensureTime(epoch - this.epoch);
|
|
13
|
+
const h = t / 4294967296 >>> 0;
|
|
14
|
+
const l = (t & 4294967295) >>> 0;
|
|
15
|
+
buf[0] = h >>> 24;
|
|
16
|
+
buf[1] = h >> 16 & 255;
|
|
17
|
+
buf[2] = h >> 8 & 255;
|
|
18
|
+
buf[3] = h & 255;
|
|
19
|
+
buf[4] = l >>> 24;
|
|
20
|
+
buf[5] = l >> 16 & 255;
|
|
21
|
+
buf[6] = l >> 8 & 255;
|
|
22
|
+
buf[7] = l & 255;
|
|
23
|
+
return buf;
|
|
24
|
+
}
|
|
25
|
+
parse(id) {
|
|
26
|
+
const buf = this.tmp;
|
|
27
|
+
this.base.decodeBytes(id, buf);
|
|
28
|
+
return {
|
|
29
|
+
epoch: this.u32(buf) * 4294967296 + this.u32(buf, 4) + this.epoch,
|
|
30
|
+
id: buf.slice(8)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
*/
|
|
40
|
-
export const defKSUID64 = (opts) => new KSUID64(opts);
|
|
34
|
+
const defKSUID64 = (opts) => new KSUID64(opts);
|
|
35
|
+
export {
|
|
36
|
+
KSUID64,
|
|
37
|
+
defKSUID64
|
|
38
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/ksuid",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.21",
|
|
4
4
|
"description": "Configurable K-sortable unique IDs, ULIDs, binary & base-N encoded, 32/48/64bit time resolutions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -25,8 +25,10 @@
|
|
|
25
25
|
"author": "Karsten Schmidt (https://thi.ng)",
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"scripts": {
|
|
28
|
-
"bench": "
|
|
29
|
-
"build": "yarn
|
|
28
|
+
"bench": "bun bench/index.ts",
|
|
29
|
+
"build": "yarn build:esbuild && yarn build:decl",
|
|
30
|
+
"build:decl": "tsc --declaration --emitDeclarationOnly",
|
|
31
|
+
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
|
|
30
32
|
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
|
|
31
33
|
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
|
|
32
34
|
"doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
|
|
@@ -35,13 +37,14 @@
|
|
|
35
37
|
"test": "bun test"
|
|
36
38
|
},
|
|
37
39
|
"dependencies": {
|
|
38
|
-
"@thi.ng/base-n": "^2.5.
|
|
39
|
-
"@thi.ng/errors": "^2.4.
|
|
40
|
-
"@thi.ng/random": "^3.6.
|
|
41
|
-
"@thi.ng/strings": "^3.7.
|
|
40
|
+
"@thi.ng/base-n": "^2.5.21",
|
|
41
|
+
"@thi.ng/errors": "^2.4.7",
|
|
42
|
+
"@thi.ng/random": "^3.6.19",
|
|
43
|
+
"@thi.ng/strings": "^3.7.4"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@microsoft/api-extractor": "^7.38.3",
|
|
47
|
+
"esbuild": "^0.19.8",
|
|
45
48
|
"rimraf": "^5.0.5",
|
|
46
49
|
"tools": "^0.0.1",
|
|
47
50
|
"typedoc": "^0.25.4",
|
|
@@ -73,7 +76,7 @@
|
|
|
73
76
|
"access": "public"
|
|
74
77
|
},
|
|
75
78
|
"engines": {
|
|
76
|
-
"node": ">=
|
|
79
|
+
"node": ">=18"
|
|
77
80
|
},
|
|
78
81
|
"files": [
|
|
79
82
|
"./*.js",
|
|
@@ -112,5 +115,5 @@
|
|
|
112
115
|
"status": "stable",
|
|
113
116
|
"year": 2020
|
|
114
117
|
},
|
|
115
|
-
"gitHead": "
|
|
118
|
+
"gitHead": "25a42a81fac8603a1e440a7aa8bc343276211ff4\n"
|
|
116
119
|
}
|
package/ulid.js
CHANGED
|
@@ -1,47 +1,40 @@
|
|
|
1
1
|
import { BASE32_CROCKFORD } from "@thi.ng/base-n/32";
|
|
2
2
|
import { AKSUID } from "./aksuid.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
}
|
|
3
|
+
class ULID extends AKSUID {
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
super(6, {
|
|
6
|
+
epoch: 0,
|
|
7
|
+
bytes: 10,
|
|
8
|
+
base: BASE32_CROCKFORD,
|
|
9
|
+
...opts
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
timeOnlyBinary(epoch = Date.now()) {
|
|
13
|
+
const buf = new Uint8Array(this.size);
|
|
14
|
+
const t = this.ensureTime(epoch - this.epoch);
|
|
15
|
+
const h = t / 4294967296 >>> 0;
|
|
16
|
+
const l = (t & 4294967295) >>> 0;
|
|
17
|
+
buf.set([
|
|
18
|
+
h >> 8 & 255,
|
|
19
|
+
h & 255,
|
|
20
|
+
l >>> 24,
|
|
21
|
+
l >> 16 & 255,
|
|
22
|
+
l >> 8 & 255,
|
|
23
|
+
l & 255
|
|
24
|
+
]);
|
|
25
|
+
return buf;
|
|
26
|
+
}
|
|
27
|
+
parse(id) {
|
|
28
|
+
const buf = new Uint8Array(this.size);
|
|
29
|
+
this.base.decodeBytes(id, buf);
|
|
30
|
+
return {
|
|
31
|
+
epoch: (buf[0] << 8 | buf[1]) * 4294967296 + this.u32(buf, 2) + this.epoch,
|
|
32
|
+
id: buf.slice(6)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
37
35
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* https://github.com/ulid/spec
|
|
44
|
-
*
|
|
45
|
-
* @param opts -
|
|
46
|
-
*/
|
|
47
|
-
export const defULID = (opts) => new ULID(opts);
|
|
36
|
+
const defULID = (opts) => new ULID(opts);
|
|
37
|
+
export {
|
|
38
|
+
ULID,
|
|
39
|
+
defULID
|
|
40
|
+
};
|