Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add maxInt in options #38

Merged
merged 2 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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')
}
})
Loading