@thi.ng/ksuid
Advanced tools
Comparing version 0.1.10 to 0.2.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/ksuid@0.1.10...@thi.ng/ksuid@0.2.0) (2021-03-28) | ||
### Features | ||
* **ksuid:** add .parse() & .timeOnly() ([80a0f70](https://github.com/thi-ng/umbrella/commit/80a0f70a2593af1c4e77a33dd3f98e36d9231c1c)) | ||
## [0.1.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/ksuid@0.1.9...@thi.ng/ksuid@0.1.10) (2021-03-24) | ||
@@ -8,0 +19,0 @@ |
@@ -58,2 +58,16 @@ import { BaseN } from "@thi.ng/base-n"; | ||
/** | ||
* Returns a new baseN encoded ID string for given `epoch` (default: current | ||
* time) and with all random payload bytes set to 0. | ||
* | ||
* @param epoch | ||
*/ | ||
timeOnly(epoch?: number): string; | ||
/** | ||
* Binary version of {@link KSUI.timeOnly}, but returns byte array. The | ||
* first 4 bytes will contain the timestamp. | ||
* | ||
* @param epoch | ||
*/ | ||
timeOnlyBinary(epoch?: number): Uint8Array; | ||
/** | ||
* Returns baseN encoded version of given binary ID (generated via | ||
@@ -63,2 +77,16 @@ * `.nextBinary()`). | ||
format(buf: Uint8Array): string; | ||
/** | ||
* Takes a KSUID string (assumed to be generated with the same config as | ||
* this instance) and parses it into an object of: `{ epoch, id }`, where | ||
* `epoch` is the Unix epoch of the ID and `id` the random bytes. | ||
* | ||
* @remarks | ||
* This operation requires `bigint` support by the host environment. | ||
* | ||
* @param id | ||
*/ | ||
parse(id: string): { | ||
epoch: number; | ||
id: Uint8Array; | ||
}; | ||
} | ||
@@ -65,0 +93,0 @@ /** |
48
index.js
@@ -18,3 +18,3 @@ import { assert } from "@thi.ng/api"; | ||
next() { | ||
return this.pad(this.base.encodeBytes(this.nextBinary())); | ||
return this.format(this.nextBinary()); | ||
} | ||
@@ -25,5 +25,3 @@ /** | ||
nextBinary() { | ||
const buf = new Uint8Array(this.size); | ||
const t = (Date.now() / 1000 - this.epoch) & 0xffffffff; | ||
buf.set([t >>> 24, (t >>> 16) & 0xff, (t >>> 8) & 0xff, t & 0xff]); | ||
const buf = this.timeOnlyBinary(); | ||
return this.rnd | ||
@@ -34,2 +32,24 @@ ? randomBytesFrom(this.rnd, buf, 4) | ||
/** | ||
* Returns a new baseN encoded ID string for given `epoch` (default: current | ||
* time) and with all random payload bytes set to 0. | ||
* | ||
* @param epoch | ||
*/ | ||
timeOnly(epoch) { | ||
return this.format(this.timeOnlyBinary(epoch)); | ||
} | ||
/** | ||
* Binary version of {@link KSUI.timeOnly}, but returns byte array. The | ||
* first 4 bytes will contain the timestamp. | ||
* | ||
* @param epoch | ||
*/ | ||
timeOnlyBinary(epoch = Date.now()) { | ||
const buf = new Uint8Array(this.size); | ||
let t = epoch / 1000 - this.epoch; | ||
assert(t >= 0, "configured base epoch must be in the past"); | ||
buf.set([t >>> 24, (t >>> 16) & 0xff, (t >>> 8) & 0xff, t & 0xff]); | ||
return buf; | ||
} | ||
/** | ||
* Returns baseN encoded version of given binary ID (generated via | ||
@@ -42,2 +62,22 @@ * `.nextBinary()`). | ||
} | ||
/** | ||
* Takes a KSUID string (assumed to be generated with the same config as | ||
* this instance) and parses it into an object of: `{ epoch, id }`, where | ||
* `epoch` is the Unix epoch of the ID and `id` the random bytes. | ||
* | ||
* @remarks | ||
* This operation requires `bigint` support by the host environment. | ||
* | ||
* @param id | ||
*/ | ||
parse(id) { | ||
const buf = new Uint8Array(this.size); | ||
this.base.decodeBytes(id, buf); | ||
return { | ||
epoch: (((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) + | ||
this.epoch) * | ||
1000, | ||
id: buf.slice(4), | ||
}; | ||
} | ||
} | ||
@@ -44,0 +84,0 @@ /** |
@@ -20,8 +20,6 @@ 'use strict'; | ||
next() { | ||
return this.pad(this.base.encodeBytes(this.nextBinary())); | ||
return this.format(this.nextBinary()); | ||
} | ||
nextBinary() { | ||
const buf = new Uint8Array(this.size); | ||
const t = (Date.now() / 1000 - this.epoch) & 0xffffffff; | ||
buf.set([t >>> 24, (t >>> 16) & 0xff, (t >>> 8) & 0xff, t & 0xff]); | ||
const buf = this.timeOnlyBinary(); | ||
return this.rnd | ||
@@ -31,2 +29,12 @@ ? random.randomBytesFrom(this.rnd, buf, 4) | ||
} | ||
timeOnly(epoch) { | ||
return this.format(this.timeOnlyBinary(epoch)); | ||
} | ||
timeOnlyBinary(epoch = Date.now()) { | ||
const buf = new Uint8Array(this.size); | ||
let t = epoch / 1000 - this.epoch; | ||
api.assert(t >= 0, "configured base epoch must be in the past"); | ||
buf.set([t >>> 24, (t >>> 16) & 0xff, (t >>> 8) & 0xff, t & 0xff]); | ||
return buf; | ||
} | ||
format(buf) { | ||
@@ -36,2 +44,12 @@ api.assert(buf.length == this.size, `illegal KSUID size, expected ${this.size} bytes`); | ||
} | ||
parse(id) { | ||
const buf = new Uint8Array(this.size); | ||
this.base.decodeBytes(id, buf); | ||
return { | ||
epoch: (((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]) + | ||
this.epoch) * | ||
1000, | ||
id: buf.slice(4), | ||
}; | ||
} | ||
} | ||
@@ -38,0 +56,0 @@ const defKSUID = (opts) => new KSUID(opts); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@thi.ng/api"),require("@thi.ng/base-n"),require("@thi.ng/random"),require("@thi.ng/strings")):"function"==typeof define&&define.amd?define(["exports","@thi.ng/api","@thi.ng/base-n","@thi.ng/random","@thi.ng/strings"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).thi=e.thi||{},e.thi.ng=e.thi.ng||{},e.thi.ng.ksuid={}),e.thi.ng.api,e.thi.ng.baseN,e.thi.ng.random,e.thi.ng.strings)}(this,(function(e,t,i,s,n){"use strict";class h{constructor(e){e=Object.assign({base:i.BASE62,epoch:16e8,bytes:16},e),this.base=e.base,this.rnd=e.rnd,this.epoch=e.epoch,this.size=4+e.bytes,this.pad=n.padLeft(this.base.size(2**(8*this.size)-1),this.base.base[0])}next(){return this.pad(this.base.encodeBytes(this.nextBinary()))}nextBinary(){const e=new Uint8Array(this.size),t=Date.now()/1e3-this.epoch&4294967295;return e.set([t>>>24,t>>>16&255,t>>>8&255,255&t]),this.rnd?s.randomBytesFrom(this.rnd,e,4):s.randomBytes(e,4)}format(e){return t.assert(e.length==this.size,`illegal KSUID size, expected ${this.size} bytes`),this.pad(this.base.encodeBytes(e))}}e.KSUID=h,e.defKSUID=e=>new h(e),Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@thi.ng/api"),require("@thi.ng/base-n"),require("@thi.ng/random"),require("@thi.ng/strings")):"function"==typeof define&&define.amd?define(["exports","@thi.ng/api","@thi.ng/base-n","@thi.ng/random","@thi.ng/strings"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).thi=e.thi||{},e.thi.ng=e.thi.ng||{},e.thi.ng.ksuid={}),e.thi.ng.api,e.thi.ng.baseN,e.thi.ng.random,e.thi.ng.strings)}(this,(function(e,t,i,s,n){"use strict";class r{constructor(e){e=Object.assign({base:i.BASE62,epoch:16e8,bytes:16},e),this.base=e.base,this.rnd=e.rnd,this.epoch=e.epoch,this.size=4+e.bytes,this.pad=n.padLeft(this.base.size(2**(8*this.size)-1),this.base.base[0])}next(){return this.format(this.nextBinary())}nextBinary(){const e=this.timeOnlyBinary();return this.rnd?s.randomBytesFrom(this.rnd,e,4):s.randomBytes(e,4)}timeOnly(e){return this.format(this.timeOnlyBinary(e))}timeOnlyBinary(e=Date.now()){const i=new Uint8Array(this.size);let s=e/1e3-this.epoch;return t.assert(s>=0,"configured base epoch must be in the past"),i.set([s>>>24,s>>>16&255,s>>>8&255,255&s]),i}format(e){return t.assert(e.length==this.size,`illegal KSUID size, expected ${this.size} bytes`),this.pad(this.base.encodeBytes(e))}parse(e){const t=new Uint8Array(this.size);return this.base.decodeBytes(e,t),{epoch:1e3*((t[0]<<24|t[1]<<16|t[2]<<8|t[3])+this.epoch),id:t.slice(4)}}}e.KSUID=r,e.defKSUID=e=>new r(e),Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "@thi.ng/ksuid", | ||
"version": "0.1.10", | ||
"version": "0.2.0", | ||
"description": "Configurable K-sortable unique identifiers, binary & base-N encoded", | ||
@@ -93,3 +93,3 @@ "module": "./index.js", | ||
}, | ||
"gitHead": "0db78c0f3d09e085dd790d7d677ce85126ce4750" | ||
"gitHead": "eb961d221997bb8585ba08eab5d0d8a7920c58dd" | ||
} |
@@ -34,3 +34,5 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
- Epoch start time offset | ||
- RNG source (default: `window.crypto`) | ||
- Time-only base ID generation (optional) | ||
- KSUID parsing / decomposition | ||
- Configurable RNG source (default: `window.crypto` or `Math.random`) | ||
@@ -70,3 +72,3 @@ KSUIDs generated w/ this package consist of the lower 32bits of an Unix epoch | ||
Package sizes (gzipped, pre-treeshake): ESM: 447 bytes / CJS: 503 bytes / UMD: 627 bytes | ||
Package sizes (gzipped, pre-treeshake): ESM: 563 bytes / CJS: 620 bytes / UMD: 743 bytes | ||
@@ -104,2 +106,15 @@ ## Dependencies | ||
// '05XCZ32AaDZfZt0SWE2C22o6cqK' | ||
id.parse("05XCZ32AaDZfZt0SWE2C22o6cqK") | ||
// { | ||
// epoch: 1610498125000, | ||
// id: Uint8Array(16) [ | ||
// 101, 251, 244, 17, 155, 97, | ||
// 24, 101, 70, 71, 207, 23, | ||
// 32, 21, 244, 116 | ||
// ] | ||
// } | ||
new Date(1610498125000).toISOString() | ||
// '2021-01-13T00:35:25.000Z' | ||
``` | ||
@@ -106,0 +121,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34492
231
175