@ganbarodigital/ts-lib-base-n
v0.1.0
Published
Support for various baseN encoding/decoding
Downloads
1
Readme
BaseN Library for Typescript
Introduction
This TypeScript library will convert to/from various base-N encodings.
We've built this to use in shortening UUIDs in a URL-friendly way. There's nothing stopping you from using it to encode anything you want.
Quick Start
# run this from your Terminal
npm install @ganbarodigital/ts-lib-base-n
// add this import to your Typescript code
import { base64UrlEncode } from "@ganbarodigital/ts-lib-base-n/lib/v1"
VS Code users: once you've added a single import anywhere in your project, you'll then be able to auto-import anything else that this library exports.
V1 API
Comparision Of Transforms
This library's original use-case is to help with encoding a UUID into something smaller. A UUID is 16 bytes (in binary form), and 36 bytes (as a well-formatted string with the '-' characters).
Working with binary fields in a database isn't fun, especially if they're primary keys or foreign keys. But how small can we make these UUIDs, and still store them as a string?
import {
base64UrlEncodeFromBuffer,
base36UrlEncodeFromBuffer,
base32UrlEncodeFromBuffer,
} from "@ganbarodigital/ts-lib-base-n/lib/v1";
// get rid of the hyphens from the UUID
//
// this gets us from 36 bytes to 32 bytes
const uuid = "306af19c-41a4-4b21-8572-32308e6c03ea".split("-").join();
// store the UUID as binary data in a Buffer
//
// this gets us from 32 bytes to 16 bytes
const buf = Buffer.from(uuid, "hex");
// let's see how small we can go
console.log(base64UrlEncodeFromBuffer(buf).length);
console.log(base36UrlEncodeFromBuffer(buf).length);
console.log(base32UrlEncodeFromBuffer(buf).length);
Here's a table showing the output sizes each function achieves, along with the rough performance difference between each algorithm (based on our benchmark script).
function | output size | reduction | performance ----------------------------------------------------------|-------------|---------- | ------------ base64UrlEncodeFromBuffer() | 22 | 31% | *4 base36UrlEncodeFromBuffer() | 25 | 22% | *1 base32UrlEncodeFromBuffer() | 26 | 19% | *2
base64UrlEncodeFromBuffer()
is both the fastest, and it produces the smallest result. The result is case-sensitive though, and that doesn't suit everyone's needs.
base32UrlEncodeFromBuffer()
is the next fastest (about twice as slow as base64UrlEncodeFromBuffer()
). It produces the largest result - 4 characters more than base64UrlEncodeFromBuffer()
. The result is case-insensitive, and therefore safe to use just about anywhere.
In the middle, we have base36UrlEncodeFromBuffer()
. It's the slowest algorithm (about four times slower than base64UrlEncodeFromBuffer()
), and the result is only one character shorter than what base32UrlEncodeFromBuffer()
produces. The result is also case-insensitive.
Which one is right for you?
- Use
base64UrlEncodeFromBuffer()
when:- you need both max performance and minimum storage, and
- when the result does NOT need to be case-insensitive
- Use
base36UrlEncodeFromBuffer()
when:- you need minimum storage, and
- when the result DOES need to be case-insensitive
- Use
base32UrlEncodeFromBuffer()
when:base36UrlEncodeFromBuffer()
is too slow for your needs, and- when the result DOES need to be case-insensitive
base64UrlEncodeFromBuffer()
/**
* converts the given input into RFC-4648 base64 URL-safe encoding
* (aka base64url), with padding characters removed (you can add them
* back with a flag, if you really need them)
*
* optimised for both small (eg UUID) and large (embedded images) input
*
* @param flags
* any combination of the BaseNFlags
*/
export function base64UrlEncodeFromBuffer(
input: Buffer,
flags: number = BaseNFlags.default,
): string;
base64UrlEncodeFromBuffer()
is a data transform. It will take the binary data in the input
buffer, and encode it using the base64url alphabet from RFC 4648.
base36UrlEncodeFromBuffer()
/**
* converts the given input into a base36 encoding, suitable for use
* in URLs and on case-insensitive filesystems
*
* `base32UrlEncodeFromBuffer()` will perform about twice as fast,
* if performance is more important than reducing storage
*/
export function base36UrlEncodeFromBuffer(input: Buffer): string;
base36UrlEncodeFromBuffer()
is a data transform. It will take the binary data in the input
buffer, and encode it using a 36-character alphabet (0-9, a-z).
This function uses JavaScript's BigInt
type to do the heavy lifting. Different implementations of BigInt
may produce different results for the exact same input
buffer.
base32UrlEncodeFromBuffer()
/**
* converts the given input into a base32 encoding, suitable for use
* in URLs and on case-insensitive filesystems
*
* this function does NOT use the RFC-4648 algorithm
*
* `base64UrlEncodeFromBuffer()` will perform about twice as fast,
* and give you a smaller result (but the result is NOT case-insensitive)
*/
export function base32UrlEncodeFromBuffer(input: Buffer): string;
base32UrlEncodeFromBuffer()
is a data transform. It will take the binary data in the input
buffer, and encode it using a 32-character alphabet (0-9, a-v);
This function uses JavaScript's BigInt
type to do the heavy lifting. Different implementations of BigInt
may produce different results for the exact same input
buffer.
isBase32UrlData()
function isBase32UrlData(input: string): boolean
isBase32UrlData()
is a data guard.
- Returns
true
if theinput
only contains valid base32url characters (0-9, a-v). - Returns
false
otherwise.
isBase36UrlData()
function isBase36UrlData(input: string): boolean
isBase36UrlData()
is a data guard.
- Returns
true
if theinput
only contains valid base36url characters (0-9, a-z). - Returns
false
otherwise.
isBase64UrlData()
function isBase64UrlData(input: string): boolean
isBase64UrlData()
is a data guard.
- Returns
true
if theinput
only contains valid base64url characters. - Returns
false
otherwise.
mustBeBase32UrlData()
import { OnError, THROW_THE_ERROR } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
function mustBeBase32UrlData(input: string, onError: OnError = THROW_THE_ERROR): void
mustBeBase32UrlData()
is a data guarantee.
- If the
input
string is valid base32url-encoded data, it will return. - Otherwise, it will call the supplied
onError
error callback.
mustBeBase36UrlData()
import { OnError, THROW_THE_ERROR } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
function mustBeBase36UrlData(input: string, onError: OnError = THROW_THE_ERROR): void
mustBeBase36UrlData()
is a data guarantee.
- If the
input
string is valid base36url-encoded data, it will return. - Otherwise, it will call the supplied
onError
error callback.
mustBeBase64UrlData()
import { OnError, THROW_THE_ERROR } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
function mustBeBase64UrlData(input: string, onError: OnError = THROW_THE_ERROR): void
mustBeBase64UrlData()
is a data guarantee.
- If the
input
string is valid base64url-encoded data, it will return. - Otherwise, it will call the supplied
onError
error callback.
V1 Error API
InvalidBase32UrlError
import { AppError } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
class InvalidBase32UrlError extends AppError;
JavaScript Error. Thrown when we encounter a string that does not contain valid base32url data.
InvalidBase36UrlError
import { AppError } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
class InvalidBase36UrlError extends AppError;
JavaScript Error. Thrown when we encounter a string that does not contain valid base36url data.
InvalidBase64UrlError
import { AppError } from "@ganbarodigital/ts-lib-error-reporting/lib/v1";
class InvalidBase64UrlError extends AppError;
JavaScript Error. Thrown when we encounter a string that does not contain valid base64url data.
NPM Scripts
npm run clean
Use npm run clean
to delete all of the compiled code.
npm run build
Use npm run build
to compile the Typescript into plain Javascript. The compiled code is placed into the lib/
folder.
npm run build
does not compile the unit test code.
npm run test
Use npm run test
to compile and run the unit tests. The compiled code is placed into the lib/
folder.
npm run cover
Use npm run cover
to compile the unit tests, run them, and see code coverage metrics.
Metrics are written to the terminal, and are also published as HTML into the coverage/
folder.
npm run benchmark
Use npm run benchmark
to see how well our functions perform against other options.