@waiting/base64
Version:
Base64 encoding/decoding in pure JS on both modern Browsers and Node.js. Also supports URL-safe base64
160 lines (153 loc) • 4.55 kB
JavaScript
import { ErrMsg } from './config'
export function parseEncodeInputString(input) {
const ret = typeof input === 'string'
? input
// tslint:disable-next-line: valid-typeof
: (typeof input === 'number' || typeof input === 'bigint' ? input.toString() : null)
if (ret === null) {
throw new TypeError(ErrMsg.encodeInvalidParam)
}
return ret
}
export function parseDecodeInputBase64(base64) {
if (typeof base64 !== 'string') {
throw new TypeError(ErrMsg.notString)
}
else if (!validB64Chars(base64)) {
throw new TypeError(ErrMsg.notValidB64String)
}
return base64
}
export function parseTextEncoder(textEncoder) {
if (typeof textEncoder === 'function') {
return textEncoder
}
else if (typeof TextEncoder === 'function') {
return TextEncoder
}
else {
throw new TypeError(ErrMsg.textEncoderUndefined)
}
}
export function parseTextDecoder(textDecoder) {
if (typeof textDecoder === 'function') {
return textDecoder
}
else if (typeof TextDecoder === 'function') {
return TextDecoder
}
else {
throw new TypeError(ErrMsg.textDecoderUndefined)
}
}
/** Whether string contains valid base64 characters */
export function validB64Chars(input) {
return /^[a-zA-Z0-9+/_-]+={0,2}$/.test(input)
}
/** Whether string contains valid URL-safe base64 characters */
export function validB64URLChars(input) {
return /^[a-zA-Z0-9_-]+$/.test(input)
}
/** Validate input is valid base64 string or throw error */
export function validateB64(input) {
const status = testB64(input)
if (status !== true) {
throw new Error(status)
}
}
/** Validate input is valid URL-safe base64 string or throw error */
export function validateB64URL(input) {
const status = testB64URL(input)
if (status !== true) {
throw new Error(status)
}
}
/** Return true for valid base64 input, error message for invalid */
export function testB64(input) {
if (typeof input !== 'string') {
return ErrMsg.notString
}
else if (!validB64Chars(input)) {
return ErrMsg.notValidB64String
}
else if (input.length < 4) {
return ErrMsg.notValidB64Length
}
else if (input.length % 4 !== 0) {
return ErrMsg.base64Invalidlength
}
return true
}
/** Return true for valid URL-safe base64 input, error message for invalid */
export function testB64URL(input) {
if (typeof input !== 'string') {
return ErrMsg.notString
}
else if (!validB64URLChars(input)) {
return ErrMsg.notValidB64URLString
}
else if (input.length < 2) { // URL-safe at least 2
return ErrMsg.notValidB64URLLength
}
return true
}
/** Whether running in Node.js */
export function isRunningInNodejs() {
// Buffer exists under karma testing
/* istanbul ignore next */
return typeof process === 'object' && typeof Buffer === 'function' && typeof window === 'undefined'
? true
: false
}
/** Whether input is instance of ArrayBuffer */
export function isArrayBuffer(buffer) {
return buffer && buffer instanceof ArrayBuffer ? true : false
}
/** Whether input is instance of Uint8Array */
export function isUint8Array(buffer) {
return ArrayBuffer.isView(buffer) && (buffer instanceof Uint8Array)
? true
: false
}
/**
* Convert base64 string to URL-safe base64 string.
* Replace "+" to "-" and "/" to "_", and Remove "="
*
* @see https://en.wikipedia.org/wiki/Base64#URL_applications
*/
export function b64toURLSafe(base64) {
validateB64(base64)
const pos = base64.indexOf('=')
return pos > 0
? base64.slice(0, pos).replace(/\+/g, '-').replace(/\//g, '_')
: base64.replace(/\+/g, '-').replace(/\//g, '_')
}
/**
* Convert URL-safe base64 string to base64 string.
* Replace "-" to "+" and "_" to "/", and pad with "="
*
* @see https://en.wikipedia.org/wiki/Base64#URL_applications
*/
export function b64fromURLSafe(base64) {
validateB64URL(base64)
const str = base64.replace(/-/g, '+').replace(/_/g, '/')
return b64PadSuffix(str)
}
export function b64PadSuffix(input) {
let num = 0
const mo = input.length % 4
switch (mo) {
case 3:
num = 1
break
case 2:
num = 2
break
case 0:
num = 0
break
default:
throw new Error(ErrMsg.notValidB64URLLength)
}
return input + '='.repeat(num)
}