Skip to content

Commit

Permalink
Port everything over to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
swansontec committed Sep 25, 2019
1 parent d38d73a commit a2c5d2b
Show file tree
Hide file tree
Showing 12 changed files with 387 additions and 80 deletions.
2 changes: 0 additions & 2 deletions .eslintignore

This file was deleted.

17 changes: 17 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const path = require('path')

module.exports = {
extends: [
'standard-kit/lint',
'standard-kit/lint/typescript'
],
parserOptions: {
project: path.resolve(__dirname, './tsconfig.json'),
tsconfigRootDir: __dirname
},
plugins: ['prettier'],
rules: {
'no-var': 'error',
'prettier/prettier': 'error'
}
}
7 changes: 0 additions & 7 deletions .eslintrc.json

This file was deleted.

19 changes: 15 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
.nyc_output
/coverage
/lib
/node_modules
# Build output:
.nyc_output/
coverage/
lib/

# Package managers:
node_modules/
npm-debug.log
package-lock.json
yarn-error.log

# Editors:
.DS_Store
.idea/
.vscode/
12 changes: 12 additions & 0 deletions .nycrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"include": [
"src/**/*.ts"
],
"extension": [
".ts"
],
"require": [
"sucrase/register"
],
"all": true
}
22 changes: 15 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
],
"main": "lib/index.cjs.js",
"module": "lib/index.js",
"types": "lib/src/index.d.ts",
"scripts": {
"build": "rimraf lib && rollup -c",
"format": "eslint . --fix",
"lint": "eslint .",
"precommit": "npm run lint && npm test",
"build": "rimraf lib && rollup -c && tsc",
"format": "npm run lint -- --fix",
"lint": "eslint --ignore-path .gitignore --ext .js,.ts .",
"precommit": "npm run lint && npm test && npm run build",
"prepare": "npm run build",
"pretest": "npm run build",
"test": "nyc mocha"
"test": "nyc mocha test/**/*.ts"
},
"husky": {
"hooks": {
Expand All @@ -41,6 +41,11 @@
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/preset-env": "^7.6.2",
"@babel/preset-typescript": "^7.6.0",
"@types/chai": "^4.2.3",
"@types/mocha": "^5.2.7",
"@typescript-eslint/eslint-plugin": "^2.3.1",
"@typescript-eslint/parser": "^2.3.1",
"chai": "^4.2.0",
"eslint": "^6.4.0",
"eslint-config-standard-kit": "^0.14.0",
Expand All @@ -56,6 +61,9 @@
"rollup": "^1.21.4",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-filesize": "^6.2.0",
"rollup-plugin-uglify": "^6.0.3"
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-uglify": "^6.0.3",
"sucrase": "^3.10.1",
"typescript": "^3.6.3"
}
}
16 changes: 11 additions & 5 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
import babel from 'rollup-plugin-babel'
import filesize from 'rollup-plugin-filesize'
import resolve from 'rollup-plugin-node-resolve'
import { uglify } from 'rollup-plugin-uglify'

import packageJson from './package.json'

const extensions = ['.ts']
const babelOpts = {
babelrc: false,
extensions,
include: ['src/**/*'],
presets: [
[
'@babel/preset-env',
{
exclude: ['transform-regenerator'],
loose: true
}
]
],
'@babel/typescript'
]
}
const resolveOpts = { extensions }

export default [
{
input: 'src/index.js',
input: 'src/index.ts',
output: [
{ file: packageJson.module, format: 'esm', sourceMap: true },
{ file: packageJson.main, format: 'cjs', sourceMap: true }
],
plugins: [babel(babelOpts)]
plugins: [resolve(resolveOpts), babel(babelOpts)]
},
{
input: 'src/index.js',
input: 'src/index.ts',
output: { file: 'lib/index.min.js', format: 'iife', name: 'rfc4648' },
plugins: [babel(babelOpts), uglify(), filesize()]
plugins: [resolve(resolveOpts), babel(babelOpts), uglify(), filesize()]
}
]
33 changes: 30 additions & 3 deletions src/codec.js → src/codec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
export function parse(string, encoding, opts = {}) {
/* eslint-disable @typescript-eslint/strict-boolean-expressions */

export interface Encoding {
bits: number
chars: string
codes?: { [char: string]: number }
}

export interface ParseOptions {
loose?: boolean
out?: new (size: number) => { [index: number]: number }
}

export interface StringifyOptions {
pad?: boolean
}

export function parse(
string: string,
encoding: Encoding,
opts: ParseOptions = {}
): Uint8Array {
// Build the character lookup table:
if (!encoding.codes) {
encoding.codes = {}
Expand All @@ -24,7 +45,9 @@ export function parse(string, encoding, opts = {}) {
}

// Allocate the output:
const out = new (opts.out || Uint8Array)(((end * encoding.bits) / 8) | 0)
const out = new (opts.out || Uint8Array)(
((end * encoding.bits) / 8) | 0
) as Uint8Array

// Parse the data:
let bits = 0 // Number of bits currently in the buffer
Expand Down Expand Up @@ -56,7 +79,11 @@ export function parse(string, encoding, opts = {}) {
return out
}

export function stringify(data, encoding, opts = {}) {
export function stringify(
data: ArrayLike<number>,
encoding: Encoding,
opts: StringifyOptions = {}
): string {
const { pad = true } = opts
const mask = (1 << encoding.bits) - 1
let out = ''
Expand Down
72 changes: 40 additions & 32 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,50 @@
import { parse, stringify } from './codec.js'
/* eslint-disable @typescript-eslint/strict-boolean-expressions */

const base16Encoding = {
import {
Encoding,
ParseOptions,
StringifyOptions,
parse,
stringify
} from './codec'

const base16Encoding: Encoding = {
chars: '0123456789ABCDEF',
bits: 4
}

const base32Encoding: Encoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
bits: 5
}

const base32HexEncoding: Encoding = {
chars: '0123456789ABCDEFGHIJKLMNOPQRSTUV',
bits: 5
}

const base64Encoding: Encoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
bits: 6
}

const base64UrlEncoding: Encoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
bits: 6
}

export const base16 = {
parse(string, opts) {
parse(string: string, opts?: ParseOptions): Uint8Array {
return parse(string.toUpperCase(), base16Encoding, opts)
},

stringify(data, opts) {
stringify(data: ArrayLike<number>, opts?: StringifyOptions): string {
return stringify(data, base16Encoding, opts)
}
}

const base32Encoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
bits: 5
}

export const base32 = {
parse(string, opts = {}) {
parse(string: string, opts: ParseOptions = {}): Uint8Array {
return parse(
opts.loose
? string
Expand All @@ -35,52 +58,37 @@ export const base32 = {
)
},

stringify(data, opts) {
stringify(data: ArrayLike<number>, opts?: StringifyOptions): string {
return stringify(data, base32Encoding, opts)
}
}

const base32HexEncoding = {
chars: '0123456789ABCDEFGHIJKLMNOPQRSTUV',
bits: 5
}

export const base32hex = {
parse(string, opts) {
parse(string: string, opts?: ParseOptions): Uint8Array {
return parse(string, base32HexEncoding, opts)
},

stringify(data, opts) {
stringify(data: ArrayLike<number>, opts?: StringifyOptions): string {
return stringify(data, base32HexEncoding, opts)
}
}

const base64Encoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
bits: 6
}

export const base64 = {
parse(string, opts) {
parse(string: string, opts?: ParseOptions): Uint8Array {
return parse(string, base64Encoding, opts)
},

stringify(data, opts) {
stringify(data: ArrayLike<number>, opts?: StringifyOptions): string {
return stringify(data, base64Encoding, opts)
}
}

const base64UrlEncoding = {
chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
bits: 6
}

export const base64url = {
parse(string, opts) {
parse(string: string, opts?: ParseOptions): Uint8Array {
return parse(string, base64UrlEncoding, opts)
},

stringify(data, opts) {
stringify(data: ArrayLike<number>, opts?: StringifyOptions): string {
return stringify(data, base64UrlEncoding, opts)
}
}
Expand Down
46 changes: 31 additions & 15 deletions test/tests.js → test/tests.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
/* global describe, it, require */

const { expect } = require('chai')
const {
base16,
base32,
base32hex,
base64,
base64url
} = require('../lib/index.cjs.js')

function parseAscii(string) {
/* global describe, it */

import { expect } from 'chai'
import { base16, base32, base32hex, base64, base64url } from '../src/index'

// Test for simple round-trips:
type TestVector = [number[] | string, string]

// Test for encoded string with errors:
type ErrorTestVector =
| [string, string, number[]] // Strict fails, loose parses
| [string, string, string] // Both fail differently
| [string, string] // Both fail the same way

/**
* Turns an ASCII string into a Uint8Array:
*/
function parseAscii(string: string): Uint8Array {
const out = new Uint8Array(string.length)
for (let i = 0; i < string.length; ++i) {
out[i] = string.charCodeAt(i)
}
return out
}

function generateTests(codec, vectors) {
/**
* Tests the provided codec's round-trip capabilities.
*/
function generateTests(codec: typeof base16, vectors: TestVector[]): void {
for (const [data, text] of vectors) {
it(`round-trips "${text}"`, function() {
const expected =
Expand All @@ -28,12 +37,19 @@ function generateTests(codec, vectors) {
}
}

function generateErrorTests(codec, vectors) {
/**
* Tests the provided codec's error-handling capabilities.
*/
function generateErrorTests(
codec: typeof base16,
vectors: ErrorTestVector[]
): void {
for (const [text, error, loose] of vectors) {
if (loose == null || typeof loose === 'string') {
it(`rejects "${text}"`, function() {
const looseMessage = loose == null ? error : loose
expect(() => codec.parse(text)).throws(error)
expect(() => codec.parse(text, { loose: true })).throws(loose || error)
expect(() => codec.parse(text, { loose: true })).throws(looseMessage)
})
} else {
it(`loosely parses "${text}"`, function() {
Expand Down
Loading

0 comments on commit a2c5d2b

Please sign in to comment.