Skip to content

Commit

Permalink
add maxInt in options (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
balaji-atoa committed Aug 31, 2024
1 parent 0e6a232 commit 6177aa4
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 4 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ If `{ urlSafe: true }` is passed in, the function will generate url safe ids acc
If `{ startFrom: <int> }` is passed in, the first counter will start from that
number, which must be between 0 and 2147483647. Fractions are discarded, only the
integer part matters.
If `{ maxInt: <int> }` is passed in, the uuid will be re-generated once the *maxInt* is reached. The lesser the *maxInt*, higher the performance because of SMI (a V8 optimization).

### instance()

Expand All @@ -75,8 +76,7 @@ Returns an unique id.
### instance.uuid

The uuid used to generate the ids, it will change over time.
It is regenerated every `Math.pow(2, 31) - 1` to keep the integer a SMI
(a V8 optimization).
If `maxInt` is provided in options, then it will regenerated every `maxInt`, else it will be regenerated every `Math.pow(2, 31) - 1` to keep the integer a SMI (a V8 optimization).

### hyperid.decode(id, [options])

Expand Down
6 changes: 6 additions & 0 deletions benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const napiRsUuid = require('@napi-rs/uuid').v4
const hyperIdSafeUrlInstance = hyperid({
urlSafe: true
})
const hyperIdMaxIntInstance = hyperid({
maxInt: 10000 // lesser the maxInt, faster the performance.
})
const hyperIdInstance = hyperid()

const suite = new benchmark.Suite()
Expand Down Expand Up @@ -73,6 +76,9 @@ suite.add('hyperid - fixed length', function () {
suite.add('hyperid - fixed length, url safe', function () {
hyperIdSafeUrlInstance(true)
})
suite.add('hyperid - max int', function () {
hyperIdMaxIntInstance()
})

suite.on('cycle', cycle)

Expand Down
6 changes: 5 additions & 1 deletion hyperid.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const uuidv4 = require('./uuid-node')
const parser = require('uuid-parse')
const maxInt = Math.pow(2, 31) - 1
const Buffer = loadBuffer()
function loadBuffer () {
const b = require('buffer')
Expand All @@ -16,10 +15,13 @@ const base64Padding = Buffer.from('==', 'base64')
function hyperid (opts) {
let fixedLength = false
let urlSafe = false
// gaurd if instantiated using boolean for fixedLength or with no args
let maxInt = Math.pow(2, 31) - 1
if (typeof opts === 'boolean') {
fixedLength = opts
} else {
opts = opts || {}
maxInt = opts.maxInt || Math.pow(2, 31) - 1
urlSafe = !!opts.urlSafe
fixedLength = !!opts.fixedLength
}
Expand All @@ -30,6 +32,8 @@ function hyperid (opts) {
let id = baseId(generate.uuid, urlSafe)
let count = Math.floor(opts.startFrom || 0)

if (isNaN(maxInt)) throw new Error(`maxInt must be a number. recieved ${opts.maxInt}`)

if (isNaN(count) || !(maxInt > count && count >= 0)) {
throw new Error([
`when passed, opts.startFrom must be a number between 0 and ${maxInt}.`,
Expand Down
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ declare namespace hyperid {
urlSafe?: boolean
fixedLength?: boolean
startFrom?: number
maxInt?: number
}

interface Instance {
Expand Down
5 changes: 4 additions & 1 deletion test/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import * as hyperid from '..'
const urlSafeInstance = hyperid({ fixedLength: false, urlSafe: true })
const fixedLengthInstance = hyperid(true)
const startFromInstance = hyperid({ startFrom: 9 })
const maxIntInstance = hyperid({ maxInt: 10000 })

const urlSafeId = urlSafeInstance()
const fixedLengthId = fixedLengthInstance()
const startFromId = startFromInstance()
const maxIntId = maxIntInstance()

// decode
console.log(hyperid.decode(urlSafeId))
console.log(fixedLengthInstance.decode(fixedLengthId))
console.log(startFromInstance.decode(startFromId))
console.log(startFromInstance.decode(startFromId))
console.log(maxIntInstance.decode(maxIntId))
61 changes: 61 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,64 @@ test('opts.fixedLength - passed invalid value - throws a friendly error', functi
: t.fail('this is not the error you\'re looking for')
}
})

test('opts.maxInt - pass valid value', function (t) {
t.plan(1)

const instance = hyperid({
maxInt: 1
})

let firstId = instance()
let secondId = instance()

// trimming the uuid and comparing for inequality as maxInt is 1.
firstId = firstId.substring(0, firstId.length - 1)
secondId = secondId.substring(0, secondId.length - 1)

t.doesNotEqual(firstId, secondId)
})

test('opts.maxInt - pass Invalid Value, throws friendly error', function (t) {
t.plan(1)

try {
hyperid({ maxInt: 'not a number' })
t.fail('did not throw an expected error')
} catch (e) {
e.message.match(/maxInt must be a number. recieved/)
? t.pass('thrown as expected')
: t.fail('this is not the error you\'re looking for')
}
})

test('opts.maxInt - pass valid value with startsFrom EDGE CASE', function (t) {
t.plan(1)

const instance = hyperid({
startFrom: 99999,
maxInt: 100000
})

let firstId = instance()
let secondId = instance()

// trimming the uuid and comparing for inequality as maxInt is 1.
firstId = firstId.substring(0, firstId.length - 1)
secondId = secondId.substring(0, secondId.length - 1)

t.doesNotEqual(firstId, secondId)
})

test.only('opts.maxInt - pass valid value, both startFrom and maxInt are equal, throws friendly error EDGE CASE', function (t) {
t.plan(1)

try {
hyperid({ startFrom: 100000, maxInt: 100000 })
t.fail('did not throw an expected error')
} catch (e) {
e.message.match(/startFrom must be a number between 0 and 100000/)
? t.pass('thrown as expected')
: t.fail('this is not the error you\'re looking for')
}
})

0 comments on commit 6177aa4

Please sign in to comment.