index.cjs 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. let crypto = require('crypto')
  2. let { urlAlphabet } = require('../url-alphabet/index.cjs')
  3. let random = bytes =>
  4. new Promise((resolve, reject) => {
  5. crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
  6. if (err) {
  7. reject(err)
  8. } else {
  9. resolve(buf)
  10. }
  11. })
  12. })
  13. let customAlphabet = (alphabet, defaultSize = 21) => {
  14. let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
  15. let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
  16. let tick = (id, size = defaultSize) =>
  17. random(step).then(bytes => {
  18. let i = step
  19. while (i--) {
  20. id += alphabet[bytes[i] & mask] || ''
  21. if (id.length >= size) return id
  22. }
  23. return tick(id, size)
  24. })
  25. return (size = defaultSize) => {
  26. if (size <= 0) return Promise.resolve('')
  27. return tick('', size)
  28. }
  29. }
  30. let nanoid = (size = 21) =>
  31. random((size |= 0)).then(bytes => {
  32. let id = ''
  33. while (size--) {
  34. id += urlAlphabet[bytes[size] & 63]
  35. }
  36. return id
  37. })
  38. module.exports = { nanoid, customAlphabet, random }