Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert to have both commjs and esm compat #537

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ tmp/
npm-debug.log
npm-error.log
yarn-debug.log
yarn-error.log
yarn-error.log

lib
types
dist
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist/*
2 changes: 1 addition & 1 deletion benchmarks/clinic-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fastify = require('fastify')()

const { createSigner, createVerifier } = require('../src')
import { createSigner, createVerifier } from '../src/index.ts'
const key = 'secretsecretsecret'

const { sign: signerJwt, verify: verifierJwt } = require('jsonwebtoken')
Expand Down
6 changes: 3 additions & 3 deletions benchmarks/keys/generate-keys.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env node

const { generateKeyPair } = require('node:crypto')
const { writeFileSync } = require('node:fs')
const { resolve } = require('node:path')
import { generateKeyPair } from 'node:crypto'
import { writeFileSync } from 'node:fs'
import { resolve } from 'node:path'

const passProtectedKeyPassphrase = 'secret'
const configurations = {
Expand Down
6 changes: 3 additions & 3 deletions benchmarks/keys/generate-tokens.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use strict'

const { readFileSync } = require('node:fs')
const { resolve } = require('node:path')
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'

const { createSigner } = require('../../src')
import { createSigner } from '../../src'

const privateKeys = {
HS: 'secretsecretsecret',
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import jwt from 'jsonwebtoken'

import { JWK as JWKJose, JWT as JWTJose } from 'jose'

import { createDecoder, createSigner, createVerifier } from '../src/index.js'
import { createDecoder, createSigner, createVerifier } from '../src/index.mjs'

const __dirname = dirname(fileURLToPath(import.meta.url))

Expand Down
22 changes: 18 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,26 @@
"bugs": {
"url": "https://github.com/nearform/fast-jwt/issues"
},
"main": "src/index.js",
"typings": "src/index.d.ts",
"types": "src/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./src/index.d.ts",
"exports": {
"import": {
"types": "./src/index.d.ts",
"import": "./dist/index.mjs"
},
"require": {
"types": "./src/index.d.ts",
"require": "./dist/index.js"
}
},
"sideEffects": false,
"files": [
"src"
"dist/**",
"./src/index.d.ts"
],
"scripts": {
"build": "tsup src/index.mjs --format cjs,esm --clean --minify --sourcemap",
"postpublish": "git push origin && git push origin -f --tags",
"lint": "eslint .",
"test": "node --test --experimental-test-coverage && tsd",
Expand Down Expand Up @@ -71,6 +84,7 @@
"jsonwebtoken": "^9.0.2",
"prettier": "^3.4.2",
"tsd": "^0.31.2",
"tsup": "~8.3.5",
"typescript": "^5.7.2",
"typescript-eslint": "^8.18.0"
},
Expand Down
64 changes: 26 additions & 38 deletions src/crypto.js → src/crypto.mjs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
'use strict'

const asn = require('asn1.js')
const {
import { default as asn } from 'asn1.js'
import {
createHmac,
createVerify,
createSign,
timingSafeEqual,
createPublicKey,
constants: {
RSA_PKCS1_PSS_PADDING,
RSA_PSS_SALTLEN_DIGEST,
RSA_PKCS1_PADDING,
RSA_PSS_SALTLEN_MAX_SIGN,
RSA_PSS_SALTLEN_AUTO
}
} = require('node:crypto')
const { sign: directSign, verify: directVerify } = require('node:crypto')
const { joseToDer, derToJose } = require('ecdsa-sig-formatter')
const Cache = require('mnemonist/lru-cache')
const { TokenError } = require('./error')

const base64UrlMatcher = /[=+/]/g
constants as cryptoConstants
} from 'node:crypto'
const {
RSA_PKCS1_PSS_PADDING,
RSA_PSS_SALTLEN_DIGEST,
RSA_PKCS1_PADDING,
RSA_PSS_SALTLEN_MAX_SIGN,
RSA_PSS_SALTLEN_AUTO
} = cryptoConstants
import { sign as directSign, verify as directVerify } from 'node:crypto'
import { joseToDer, derToJose } from 'ecdsa-sig-formatter'
import { default as Cache } from 'mnemonist/lru-cache.js'
import { TokenError } from './error.mjs'

export const base64UrlMatcher = /[=+/]/g
const encoderMap = { '=': '', '+': '-', '/': '_' }

const privateKeyPemMatcher = /^-----BEGIN(?: (RSA|EC|ENCRYPTED))? PRIVATE KEY-----/
Expand All @@ -29,10 +30,10 @@ const publicKeyX509CertMatcher = '-----BEGIN CERTIFICATE-----'
const privateKeysCache = new Cache(1000)
const publicKeysCache = new Cache(1000)

const hsAlgorithms = ['HS256', 'HS384', 'HS512']
const esAlgorithms = ['ES256', 'ES384', 'ES512']
const rsaAlgorithms = ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512']
const edAlgorithms = ['EdDSA']
export const hsAlgorithms = ['HS256', 'HS384', 'HS512']
export const esAlgorithms = ['ES256', 'ES384', 'ES512']
export const rsaAlgorithms = ['RS256', 'RS384', 'RS512', 'PS256', 'PS384', 'PS512']
export const edAlgorithms = ['EdDSA']
const ecCurves = {
'1.2.840.10045.3.1.7': { bits: '256', names: ['P-256', 'prime256v1'] },
'1.3.132.0.10': { bits: '256', names: ['secp256k1'] },
Expand Down Expand Up @@ -61,7 +62,7 @@ const ECPrivateKey = asn.define('ECPrivateKey', function () {
)
})

function base64UrlReplacer(c) {
export function base64UrlReplacer(c) {
return encoderMap[c]
}

Expand Down Expand Up @@ -166,7 +167,7 @@ function performDetectPublicKeyAlgorithms(key) {
return [`ES${curve.bits}`]
}

function detectPrivateKeyAlgorithm(key, providedAlgorithm) {
export function detectPrivateKeyAlgorithm(key, providedAlgorithm) {
if (key instanceof Buffer) {
key = key.toString('utf-8')
} else if (typeof key !== 'string') {
Expand Down Expand Up @@ -200,7 +201,7 @@ function detectPrivateKeyAlgorithm(key, providedAlgorithm) {
}
}

function detectPublicKeyAlgorithms(key) {
export function detectPublicKeyAlgorithms(key) {
if (!key) {
return 'none'
}
Expand Down Expand Up @@ -231,7 +232,7 @@ function detectPublicKeyAlgorithms(key) {
}
}

function createSignature(algorithm, key, input) {
export function createSignature(algorithm, key, input) {
try {
const type = algorithm.slice(0, 2)
const alg = `sha${algorithm.slice(2)}`
Expand Down Expand Up @@ -272,7 +273,7 @@ function createSignature(algorithm, key, input) {
}
}

function verifySignature(algorithm, key, input, signature) {
export function verifySignature(algorithm, key, input, signature) {
try {
const type = algorithm.slice(0, 2)
const alg = `SHA${algorithm.slice(2)}`
Expand Down Expand Up @@ -312,16 +313,3 @@ function verifySignature(algorithm, key, input, signature) {
throw new TokenError(TokenError.codes.verifyError, 'Cannot verify the signature.', { originalError: e })
}
}

module.exports = {
base64UrlMatcher,
base64UrlReplacer,
hsAlgorithms,
rsaAlgorithms,
esAlgorithms,
edAlgorithms,
detectPrivateKeyAlgorithm,
detectPublicKeyAlgorithms,
createSignature,
verifySignature
}
4 changes: 2 additions & 2 deletions src/decoder.js → src/decoder.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { TokenError } = require('./error')
import { TokenError } from './error.mjs'

function decode({ complete, checkTyp }, token) {
// Make sure the token is a string or a Buffer - Other cases make no sense to even try to validate
Expand Down Expand Up @@ -52,7 +52,7 @@ function decode({ complete, checkTyp }, token) {
}
}

module.exports = function createDecoder(options = {}) {
export function createDecoder(options = {}) {
const complete = options.complete || false
const checkTyp = options.checkTyp

Expand Down
9 changes: 2 additions & 7 deletions src/error.js → src/error.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const TOKEN_ERROR_CODES = {
export const TOKEN_ERROR_CODES = {
invalidType: 'FAST_JWT_INVALID_TYPE', // Invalid token type
invalidOption: 'FAST_JWT_INVALID_OPTION', // The option object is not valid
invalidAlgorithm: 'FAST_JWT_INVALID_ALGORITHM', // The token algorithm is invalid
Expand All @@ -20,7 +20,7 @@ const TOKEN_ERROR_CODES = {
missingSignature: 'FAST_JWT_MISSING_SIGNATURE' // The token signature is missing
}

class TokenError extends Error {
export class TokenError extends Error {
constructor(code, message, additional) {
super(message)
Error.captureStackTrace(this, this.constructor)
Expand All @@ -44,8 +44,3 @@ TokenError.wrap = function (originalError, code, message) {

return new TokenError(code, message, { originalError })
}

module.exports = {
TokenError,
TOKEN_ERROR_CODES
}
14 changes: 0 additions & 14 deletions src/index.js

This file was deleted.

6 changes: 6 additions & 0 deletions src/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

export { TokenError, TOKEN_ERROR_CODES } from './error.mjs'
export { createDecoder } from './decoder.mjs'
export { createVerifier } from './verifier.mjs'
export { createSigner } from './signer.mjs'
14 changes: 7 additions & 7 deletions src/signer.js → src/signer.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const {
import {
base64UrlMatcher,
base64UrlReplacer,
hsAlgorithms,
Expand All @@ -9,11 +9,11 @@ const {
edAlgorithms,
detectPrivateKeyAlgorithm,
createSignature
} = require('./crypto')
const { TokenError } = require('./error')
const { getAsyncKey, ensurePromiseCallback } = require('./utils')
const { createPrivateKey, createSecretKey } = require('node:crypto')
const { parse: parseMs } = require('@lukeed/ms')
} from './crypto.mjs'
import { TokenError } from './error.mjs'
import { getAsyncKey, ensurePromiseCallback } from './utils.mjs'
import { createPrivateKey, createSecretKey } from 'node:crypto'
import { parse as parseMs } from '@lukeed/ms'

const supportedAlgorithms = new Set([...hsAlgorithms, ...esAlgorithms, ...rsaAlgorithms, ...edAlgorithms, 'none'])

Expand Down Expand Up @@ -165,7 +165,7 @@ function sign(
return promise
}

module.exports = function createSigner(options) {
export function createSigner(options) {
let {
key,
algorithm,
Expand Down
14 changes: 4 additions & 10 deletions src/utils.js → src/utils.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict'

const { createHash } = require('node:crypto')
import { createHash } from 'node:crypto'
const algorithmMatcher = /"alg"\s*:\s*"[HERP]S(256|384)"/m
const edAlgorithmMatcher = /"alg"\s*:\s*"EdDSA"/m
const ed448CurveMatcher = /"crv"\s*:\s*"Ed448"/m

function getAsyncKey(handler, decoded, callback) {
export function getAsyncKey(handler, decoded, callback) {
const result = handler(decoded, callback)

if (result && typeof result.then === 'function') {
Expand All @@ -18,7 +18,7 @@ function getAsyncKey(handler, decoded, callback) {
}
}

function ensurePromiseCallback(callback) {
export function ensurePromiseCallback(callback) {
if (typeof callback === 'function') {
return [callback]
}
Expand All @@ -42,7 +42,7 @@ function ensurePromiseCallback(callback) {
]
}

function hashToken(token) {
export function hashToken(token) {
const rawHeader = token.split('.', 1)[0]
const header = Buffer.from(rawHeader, 'base64').toString('utf-8')
let hasher = null
Expand All @@ -57,9 +57,3 @@ function hashToken(token) {

return hasher.update(token).digest('hex')
}

module.exports = {
getAsyncKey,
ensurePromiseCallback,
hashToken
}
14 changes: 7 additions & 7 deletions src/verifier.js → src/verifier.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict'

const { createPublicKey, createSecretKey } = require('node:crypto')
const Cache = require('mnemonist/lru-cache')
import { createPublicKey, createSecretKey } from 'node:crypto'
import { default as Cache } from 'mnemonist/lru-cache.js'

const { hsAlgorithms, verifySignature, detectPublicKeyAlgorithms } = require('./crypto')
const createDecoder = require('./decoder')
const { TokenError } = require('./error')
const { getAsyncKey, ensurePromiseCallback, hashToken } = require('./utils')
import { hsAlgorithms, verifySignature, detectPublicKeyAlgorithms } from './crypto.mjs'
import { createDecoder } from './decoder.mjs'
import { TokenError } from './error.mjs'
import { getAsyncKey, ensurePromiseCallback, hashToken } from './utils.mjs'

const defaultCacheSize = 1000

Expand Down Expand Up @@ -360,7 +360,7 @@ function verify(
return promise
}

module.exports = function createVerifier(options) {
export function createVerifier(options) {
let {
key,
algorithms: allowedAlgorithms,
Expand Down
Loading
Loading