Skip to content

Commit

Permalink
✨ Import personal project (#4)
Browse files Browse the repository at this point in the history
* ✨ Import personal project

* 📝 Update package.json with new keywords

* ✨ Add base36Uuid function and update package.json
  • Loading branch information
NatoBoram authored Jan 6, 2024
1 parent 333a65a commit e74acba
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 6 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@

Change between bases.

## Installation
## Usage

```sh
pnpm i -D @natoboram/based.ts
```

```ts
import { base36Uuid } from "@natoboram/based.ts"

const uuid = base36Uuid()
console.log("Base 36 UUID:", uuid)
```
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.0",
"description": "Change between bases",
"keywords": [
"base64",
"base16"
"base36",
"uuid"
],
"homepage": "https://github.com/NatoBoram/based.ts",
"bugs": {
Expand All @@ -31,7 +31,9 @@
],
"main": "dist/index.js",
"module": "dist/index.js",
"bin": "dist/main.js",
"bin": {
"basedts": "dist/main.js"
},
"repository": "github:NatoBoram/based.ts",
"scripts": {
"build": "tsc",
Expand Down
92 changes: 92 additions & 0 deletions src/base36-uuid.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { describe, test } from "vitest"
import {
base36ToBigInt,
bigIntToBase36,
bigIntToBytes,
bytesToBigInt,
get128Bits,
} from "./base36-uuid.js"

test("get128Bits", ({ expect }) => {
const bits = get128Bits()

expect(bits).toBeInstanceOf(Uint8ClampedArray)
expect(bits.length).toBe(16)
})

describe("bitsToBigInt", () => {
test("256n", ({ expect }) => {
const bits = new Uint8ClampedArray([1, 0])
const bigInt = bytesToBigInt(bits)

expect(bigInt).toBe(256n)
})
})

describe("bigIntToBytes", () => {
test("256n", ({ expect }) => {
const bigInt = 256n
const bytes = bigIntToBytes(bigInt)

expect(bytes).toMatchObject(new Uint8ClampedArray([1, 0]))
})
})

describe("bigIntToBase36", () => {
test("a", ({ expect }) => {
const bigInt = BigInt(10)
const base36 = bigIntToBase36(bigInt)

expect(base36).toBe("a")
})

test("uuid", ({ expect }) => {
const bits = get128Bits()
const bigInt = bytesToBigInt(bits)
const base36 = bigIntToBase36(bigInt)

expect(base36).toBeTypeOf("string")
expect(base36.length).greaterThanOrEqual(24)
expect(base36.length).lessThanOrEqual(25)
})

test("max safe integer", ({ expect }) => {
const bigInt = BigInt(Number.MAX_SAFE_INTEGER)
const base36 = bigIntToBase36(bigInt)
expect(base36).toBe("2gosa7pa2gv")
})

test("max uuid", ({ expect }) => {
const array = new Array(16).fill(255)
const bits = new Uint8ClampedArray(array)
const bigInt = bytesToBigInt(bits)
const base36 = bigIntToBase36(bigInt)

expect(base36).toBe("f5lxx1zz5pnorynqglhzmsp33")
expect(base36).toHaveLength(25)
})
})

describe("base36ToBigInt", () => {
test("a", ({ expect }) => {
const base36 = "a"
const bigInt = base36ToBigInt(base36)

expect(bigInt).toBe(10n)
})

test("uuid", ({ expect }) => {
const bits = get128Bits()
const bigInt = bytesToBigInt(bits)

const base36 = bigIntToBase36(bigInt)
const back = base36ToBigInt(base36)

expect(back).toBe(bigInt)
})

test("max safe integer", ({ expect }) => {
const bigInt = base36ToBigInt("2gosa7pa2gv")
expect(bigInt).toBe(BigInt(Number.MAX_SAFE_INTEGER))
})
})
55 changes: 55 additions & 0 deletions src/base36-uuid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export function stringToBits(str: string) {
return new TextEncoder().encode(str)
}

export function get128Bits() {
const bytes = new Uint8ClampedArray(16)
crypto.getRandomValues(bytes)
return bytes
}

export function bytesToBigInt(bytes: Uint8ClampedArray) {
const hexes = bytes.reduce((hexes, byte) => {
/** A single hexadecimal number. Because the byte is 8 bits, the hex ranges
* from `00` to `FF`. */
const hex = byte.toString(16).padStart(2, "0")

hexes.push(hex)
return hexes
}, new Array<string>(16))

return BigInt(`0x${hexes.join("")}`)
}

export function bigIntToBytes(bn: bigint) {
let hexes = bn.toString(16)
if (hexes.length % 2) hexes = `0${hexes}`

const length = hexes.length / 2
const bytes = new Uint8ClampedArray(length)

for (let index = 0; index < length; index++) {
const hex = hexes.slice(index * 2, index * 2 + 2)
bytes[index] = parseInt(hex, 16)
}

return bytes
}

export function bigIntToBase36(bigInt: bigint) {
return bigInt.toString(36)
}

export function base36ToBigInt(base36: string) {
return Array.from(base36).reduce(
(bigInt, digit) => bigInt * 36n + BigInt(parseInt(digit, 36)),
0n,
)
}

export function base36Uuid() {
const bytes = get128Bits()
const bigInt = bytesToBigInt(bytes)
const base36 = bigIntToBase36(bigInt)
return base36
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./main.js"
export * from "./base36-uuid.js"
5 changes: 4 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/usr/bin/env node

console.log("Hello, world!")
import { base36Uuid } from "./base36-uuid.js"

const uuid = base36Uuid()
console.log("Base 36 UUID:", uuid)

0 comments on commit e74acba

Please sign in to comment.