code is now typescript. Some minor fixes

This commit is contained in:
Juanra Dikal 2021-03-24 14:04:30 +01:00
parent ff9f8afd61
commit fd780cb3ec
88 changed files with 11573 additions and 4644 deletions

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [11, 12, 13]
node-version: [10, 12, 14]
steps:
- uses: actions/checkout@v2
@ -49,7 +49,7 @@ jobs:
- uses: actions/setup-node@v1
if: steps.check.outputs.changed == 'true'
with:
node-version: 12
node-version: 14
registry-url: https://registry.npmjs.org/
- name: install

8
.gitignore vendored
View File

@ -12,9 +12,9 @@ node_modules
# Visual Studio Code
.vscode
# IntelliJ
.idea
# MYC output
.nyc_output
coverage/*
coverage
# Test temporal files
.mocha-ts

View File

@ -1,8 +1,9 @@
# Build scripts
build/*
build
# Source files
src/*
# Test files
test
**/*.spec.ts
# Logs
logs
@ -20,10 +21,16 @@ npm-debug.log*
# MYC output
.nyc_output
coverage/*
# Travis
.travis.yml
coverage
# GitHub
.github
.github
# tsconfig
tsconfig.json
# SRC docs
src/docs
# Test temporal files
.mocha-ts

221
README.md
View File

@ -1,6 +1,6 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
![Node CI](https://github.com/juanelas/bigint-mod-arith/workflows/Node%20CI/badge.svg)
[![Node CI](https://github.com/juanelas/bigint-mod-arith/workflows/Node%20CI/badge.svg)](https://github.com/juanelas/bigint-mod-arith/actions?query=workflow%3A%22Node+CI%22)
[![Coverage Status](https://coveralls.io/repos/github/juanelas/bigint-mod-arith/badge.svg?branch=master)](https://coveralls.io/github/juanelas/bigint-mod-arith?branch=master)
# bigint-mod-arith
@ -9,57 +9,33 @@ Some extra functions to work with modular arithmetic using native JS ([ES-2020](
> The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
## Installation
## Usage
bigint-mod-arith is distributed for [web browsers and/or webviews supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) as an ES6 module or an IIFE file; and for Node.js (>=10.4.0), as a CJS module.
`bigint-mod-arith` can be imported to your project with `npm`:
bigint-mod-arith can be imported to your project with `npm`:
```bash
```console
npm install bigint-mod-arith
```
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js. For web browsers, you can also directly download the [IIFE bundle](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/lib/index.browser.bundle.iife.js) or the [ESM bundle](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/lib/index.browser.bundle.mod.js) from the repository.
Then either require (Node.js CJS):
```javascript
const bigintModArith = require('bigint-mod-arith')
```
## Usage example
or import (JavaScript ES module):
Import your module as :
```javascript
import * as bigintModArith from 'bigint-mod-arith'
```
- Node.js
```javascript
const bigintModArith = require('bigint-mod-arith')
... // your code here
```
- JavaScript native or TypeScript project (including React and Angular)
```javascript
import * as bigintModArith from 'bigint-mod-arith'
... // your code here
```
- JavaScript native browser ES module
```html
<script type="module">
import * as bigintModArith from 'lib/index.browser.bundle.mod.js' // Use you actual path to the broser mod bundle
... // your code here
</script>
```
- JavaScript native browser IIFE
```html
<head>
...
<script src="../../lib/index.browser.bundle.iife.js"></script> <!-- Use you actual path to the browser bundle -->
</head>
<body>
...
<script>
... // your code here
</script>
</body>
```
The appropriate version for browser or node is automatically exported.
You can also download the [IIFE bundle](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bundles/bigint-mod-arith.iife.js), the [ESM bundle](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bundles/bigint-mod-arith.esm.js) or the [UMD bundle](https://raw.githubusercontent.com/juanelas/bigint-mod-arith/master/dist/bundles/bigint-mod-arith.umd.js) and manually add it to your project, or, if you have already imported `bigint-mod-arith` to your project, just get the bundles from `node_modules/bigint-mod-arith/dist/bundles/`.
An example of usage could be:
```javascript
```typescript
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
or the shorter syntax 666n.
Notice that you can also pass a number, e.g. BigInt(666), but it is not
@ -75,171 +51,8 @@ console.log(bigintModArith.modPow(a, b, n)) // prints 6
console.log(bigintModArith.modInv(2n, 5n)) // prints 3
console.log(bigintModArith.modInv(BigInt('3'), BigInt('5'))) // prints 2
```
## API reference documentation
<a name="module_bigint-mod-arith"></a>
### bigint-mod-arith
Some common functions for modular arithmetic using native JS implementation of BigInt
* [bigint-mod-arith](#module_bigint-mod-arith)
* [~abs(a)](#module_bigint-mod-arith..abs) ⇒ <code>bigint</code>
* [~bitLength(a)](#module_bigint-mod-arith..bitLength) ⇒ <code>number</code>
* [~eGcd(a, b)](#module_bigint-mod-arith..eGcd) ⇒ <code>egcdReturn</code>
* [~gcd(a, b)](#module_bigint-mod-arith..gcd) ⇒ <code>bigint</code>
* [~lcm(a, b)](#module_bigint-mod-arith..lcm) ⇒ <code>bigint</code>
* [~max(a, b)](#module_bigint-mod-arith..max) ⇒ <code>bigint</code>
* [~min(a, b)](#module_bigint-mod-arith..min) ⇒ <code>bigint</code>
* [~modInv(a, n)](#module_bigint-mod-arith..modInv) ⇒ <code>bigint</code> \| <code>NaN</code>
* [~modPow(b, e, n)](#module_bigint-mod-arith..modPow) ⇒ <code>bigint</code>
* [~toZn(a, n)](#module_bigint-mod-arith..toZn) ⇒ <code>bigint</code>
* [~egcdReturn](#module_bigint-mod-arith..egcdReturn) : <code>Object</code>
<a name="module_bigint-mod-arith..abs"></a>
#### bigint-mod-arith~abs(a) ⇒ <code>bigint</code>
Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - the absolute value of a
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..bitLength"></a>
#### bigint-mod-arith~bitLength(a) ⇒ <code>number</code>
Returns the bitlength of a number
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>number</code> - - the bit length
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..eGcd"></a>
#### bigint-mod-arith~eGcd(a, b) ⇒ <code>egcdReturn</code>
An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>egcdReturn</code> - A triple (g, x, y), such that ax + by = g = gcd(a, b).
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..gcd"></a>
#### bigint-mod-arith~gcd(a, b) ⇒ <code>bigint</code>
Greatest-common divisor of two integers based on the iterative binary algorithm.
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - The greatest common divisor of a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..lcm"></a>
#### bigint-mod-arith~lcm(a, b) ⇒ <code>bigint</code>
The least common multiple computed as abs(a*b)/gcd(a,b)
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - The least common multiple of a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..max"></a>
#### bigint-mod-arith~max(a, b) ⇒ <code>bigint</code>
Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - maximum of numbers a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..min"></a>
#### bigint-mod-arith~min(a, b) ⇒ <code>bigint</code>
Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - minimum of numbers a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="module_bigint-mod-arith..modInv"></a>
#### bigint-mod-arith~modInv(a, n) ⇒ <code>bigint</code> \| <code>NaN</code>
Modular inverse.
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> \| <code>NaN</code> - the inverse modulo n or NaN if it does not exist
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | The number to find an inverse for |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
<a name="module_bigint-mod-arith..modPow"></a>
#### bigint-mod-arith~modPow(b, e, n) ⇒ <code>bigint</code>
Modular exponentiation b**e mod n. Currently using the right-to-left binary method
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - b**e mod n
| Param | Type | Description |
| --- | --- | --- |
| b | <code>number</code> \| <code>bigint</code> | base |
| e | <code>number</code> \| <code>bigint</code> | exponent |
| n | <code>number</code> \| <code>bigint</code> | modulo |
<a name="module_bigint-mod-arith..toZn"></a>
#### bigint-mod-arith~toZn(a, n) ⇒ <code>bigint</code>
Finds the smallest positive element that is congruent to a in modulo n
**Kind**: inner method of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | An integer |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
<a name="module_bigint-mod-arith..egcdReturn"></a>
#### bigint-mod-arith~egcdReturn : <code>Object</code>
A triple (g, x, y), such that ax + by = g = gcd(a, b).
**Kind**: inner typedef of [<code>bigint-mod-arith</code>](#module_bigint-mod-arith)
**Properties**
| Name | Type |
| --- | --- |
| g | <code>bigint</code> |
| x | <code>bigint</code> |
| y | <code>bigint</code> |
[Check the API](./docs/API.md)

73
build/bin/mocha-ts.js Normal file
View File

@ -0,0 +1,73 @@
#! /usr/bin/env node
const path = require('path')
const childProcess = require('child_process')
const rootDir = path.join(__dirname, '../..')
const mochaTsRelativeDir = '.mocha-ts'
const minimatch = require('minimatch')
const glob = require('glob')
// First let us prepare the args to pass to mocha.
// ts.files will be replaced by their js-transpiled counterparts
// a watch file to our semaphore will be added
const processedArgs = processArgs(process.argv.slice(2))
// Now we can run a script and invoke a callback when complete, e.g.
runScript(path.join(rootDir, 'node_modules/.bin/mocha'), processArgs(processedArgs))
function processArgs (args) {
args = process.argv.slice(2).map(arg => {
const filenames = glob.sync(arg, { cwd: rootDir, matchBase: true })
if (filenames.length > 0) {
return filenames.map(file => {
const isTsTestFile = minimatch(file, '{test/**/*.ts,src/**/*.spec.ts}', { matchBase: true })
if (isTsTestFile) {
return `${mochaTsRelativeDir}/${file.slice(0, -3)}.js`
}
return file
})
}
return arg
})
const processedArgs = []
let addSemaphore = false
let semaphoreAdded = false
for (const arg of args) {
if (Array.isArray(arg)) {
processedArgs.push(...arg)
} else {
processedArgs.push(arg)
if (arg === '--watch' || arg === '-w') {
addSemaphore = true
} else if (arg === '--watch-files') {
processedArgs.push(`${mochaTsRelativeDir}/semaphore`)
semaphoreAdded = true
}
}
}
if (addSemaphore === true || semaphoreAdded === false) {
processedArgs.push('--watch-files')
processedArgs.push(`${mochaTsRelativeDir}/semaphore`)
}
return processedArgs
}
function runScript (scriptPath, args) {
const mochaCmd = childProcess.fork(path.join(rootDir, 'node_modules/.bin/mocha'), processedArgs, {
cwd: rootDir
})
mochaCmd.on('error', (error) => {
throw error
})
// execute the callback once the process has finished running
mochaCmd.on('exit', function (code) {
if (code !== 0) {
throw new Error('exit code ' + code)
}
})
}

View File

@ -1,7 +1,7 @@
'use strict'
const fs = require('fs')
const jsdoc2md = require('jsdoc-to-markdown')
const TypeDoc = require('typedoc')
const path = require('path')
const pkgJson = require('../package.json')
@ -14,6 +14,33 @@ function camelise (str) {
})
}
async function typedoc () {
const app = new TypeDoc.Application()
// If you want TypeDoc to load tsconfig.json / typedoc.json files
app.options.addReader(new TypeDoc.TSConfigReader())
app.options.addReader(new TypeDoc.TypeDocReader())
app.bootstrap({
// typedoc options here
entryPoints: ['src/index.ts'],
plugin: ['typedoc-plugin-markdown'],
includeVersion: true,
entryDocument: 'API.md',
readme: 'none'
})
const project = app.convert()
if (project) {
// Project may not have converted correctly
const output = path.join(rootDir, './docs')
// Rendered docs
await app.generateDocs(project, output)
}
}
function getRepositoryData () {
if (typeof pkgJson.repository === 'string') {
const repodata = pkgJson.repository.split(/[:/]/)
@ -30,39 +57,45 @@ function getRepositoryData () {
const { repoProvider, repoUsername, repoName } = getRepositoryData() || { repoProvider: null, repoUsername: null, repoName: null }
let iifeBundle, esmBundle, workflowBadget, coverallsBadge
if (repoProvider && repoProvider === 'github') {
iifeBundle = `[IIFE bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/lib/index.browser.bundle.iife.js)`
esmBundle = `[ESM bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/lib/index.browser.bundle.mod.js)`
workflowBadget = `![Node CI](https://github.com/${repoUsername}/${repoName}/workflows/Node%20CI/badge.svg)`
coverallsBadge = `[![Coverage Status](https://coveralls.io/repos/github/${repoUsername}/${repoName}/badge.svg?branch=master)](https://coveralls.io/github/${repoUsername}/${repoName}?branch=master)`
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const camelCaseName = camelise(name)
let iifeBundle, esmBundle, umdBundle, workflowBadget, coverallsBadge
if (repoProvider) {
switch (repoProvider) {
case 'github':
iifeBundle = `[IIFE bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.iife.js)`
esmBundle = `[ESM bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.esm.js)`
umdBundle = `[UMD bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.umd.js)`
workflowBadget = `[![Node CI](https://github.com/${repoUsername}/${repoName}/workflows/Node%20CI/badge.svg)](https://github.com/${repoUsername}/${repoName}/actions?query=workflow%3A%22Node+CI%22)`
coverallsBadge = `[![Coverage Status](https://coveralls.io/repos/github/${repoUsername}/${repoName}/badge.svg?branch=master)](https://coveralls.io/github/${repoUsername}/${repoName}?branch=master)`
break
case 'gitlab':
iifeBundle = `[IIFE bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.iife.js?inline=false)`
esmBundle = `[ESM bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.esm.js?inline=false)`
umdBundle = `[IIFE bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.umd.js?inline=false)`
break
default:
break
}
}
const templateFile = path.join(rootDir, pkgJson.directories.src, 'doc', 'readme-template.md')
const templateFile = path.join(rootDir, pkgJson.directories.src, 'docs/index.md')
let template = fs.readFileSync(templateFile, { encoding: 'UTF-8' })
.replace(/\{\{PKG_NAME\}\}/g, pkgJson.name)
.replace(/\{\{PKG_CAMELCASE\}\}/g, camelise(pkgJson.name))
.replace(/\{\{PKG_CAMELCASE\}\}/g, camelCaseName)
.replace(/\{\{IIFE_BUNDLE\}\}/g, iifeBundle || 'IIFE bundle')
.replace(/\{\{ESM_BUNDLE\}\}/g, esmBundle || 'ESM bundle')
.replace(/\{\{UMD_BUNDLE\}\}/g, umdBundle || 'UMD bundle')
if (repoProvider && repoProvider === 'github') {
template = template.replace(/\{\{GITHUB_ACTIONS_BADGES\}\}/g, workflowBadget + '\n' + coverallsBadge)
}
const input = path.join(rootDir, pkgJson.browser)
// Let us replace bigint literals by standard numbers to avoid issues with bigint
const source = fs.readFileSync(input, { encoding: 'UTF-8' }).replace(/([0-9]+)n([,\s\n)])/g, '$1$2')
const readmeFile = path.join(rootDir, 'README.md')
fs.writeFileSync(readmeFile, template)
const options = {
source,
template,
'heading-depth': 3, // The initial heading depth. For example, with a value of 2 the top-level markdown headings look like "## The heading"
'global-index-format': 'none' // none, grouped, table, dl.
}
jsdoc2md.clear().then(() => {
const readmeContents = jsdoc2md.renderSync(options)
const readmeFile = path.join(rootDir, 'README.md')
fs.writeFileSync(readmeFile, readmeContents)
})
typedoc()

View File

@ -1,25 +0,0 @@
const fs = require('fs')
const ts = require('typescript')
const path = require('path')
const pkgJson = require('../package.json')
const rootDir = path.join(__dirname, '..')
const jsFile = path.join(rootDir, pkgJson.browser)
const dtsFile = path.join(rootDir, pkgJson.types)
const compilerOptions = {
declaration: true,
noEmit: false,
emitDeclarationOnly: true,
allowJs: true
}
const host = ts.createCompilerHost(compilerOptions)
host.writeFile = (fileName, contents) => {
fs.writeFileSync(dtsFile, contents)
}
// Prepare and emit the d.ts files
const program = ts.createProgram([jsFile], compilerOptions, host)
program.emit()

View File

@ -1,15 +1,18 @@
'use strict'
const resolve = require('@rollup/plugin-node-resolve')
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('@rollup/plugin-replace')
const { terser } = require('rollup-plugin-terser')
const typescriptPlugin = require('@rollup/plugin-typescript')
const commonjs = require('@rollup/plugin-commonjs')
const path = require('path')
const fs = require('fs')
const pkgJson = require('../package.json')
const rootDir = path.join(__dirname, '..')
const srcDir = path.join(rootDir, pkgJson.directories.src)
const dstDir = path.join(rootDir, pkgJson.directories.lib)
const dstDir = path.join(rootDir, pkgJson.directories.dist)
const srcDir = path.join(rootDir, 'src')
function camelise (str) {
return str.replace(/-([a-z])/g,
@ -18,61 +21,113 @@ function camelise (str) {
})
}
const pkgName = pkgJson.name
const pkgCamelisedName = camelise(pkgName)
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const pkgCamelisedName = camelise(name)
const input = path.join(srcDir, 'js', 'index.js')
const input = path.join(srcDir, 'index.ts')
if (fs.existsSync(input) !== true) throw new Error('The entry point should be index.ts')
const tsBundleOptions = {
exclude: ['test/**/*', 'src/**/*.spec.ts', './build/typings/global-this-pkg.d.ts']
}
const external = [...Object.keys(pkgJson.dependencies || {}), ...Object.keys(pkgJson.peerDependencies || {})]
const sourcemapOutputOptions = {
sourcemap: 'inline',
sourcemapExcludeSources: true
}
module.exports = [
{ // Native JS
{ // ESM for browsers
input: input,
output: [
{
file: path.join(rootDir, pkgJson.browser),
file: path.join(rootDir, pkgJson.exports['.'].default),
...sourcemapOutputOptions,
format: 'es'
}
],
plugins: [
replace({
'process.browser': true
})
]
// external: ['bigint-crypto-utils']
IS_BROWSER: true,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions)
],
external
},
{ // Browser bundles
input: input,
output: [
{
file: path.join(dstDir, 'index.browser.bundle.iife.js'),
file: path.join(dstDir, `bundles/${name}.iife.js`),
format: 'iife',
name: pkgCamelisedName
},
{
file: path.join(dstDir, 'index.browser.bundle.mod.js'),
file: path.join(dstDir, `bundles/${name}.esm.js`),
format: 'es'
},
{
file: path.join(dstDir, `bundles/${name}.umd.js`),
format: 'umd',
name: pkgCamelisedName
}
],
plugins: [
replace({
'process.browser': true
IS_BROWSER: true,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions),
resolve({
browser: true
browser: true,
exportConditions: ['browser', 'module', 'import', 'default']
}),
terser()
]
},
{ // Node
{ // Node ESM
input: input,
output: {
file: path.join(rootDir, pkgJson.main),
dir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import)),
entryFileNames: path.basename(pkgJson.exports['.'].node.import),
...sourcemapOutputOptions,
format: 'es'
},
plugins: [
replace({
IS_BROWSER: false,
preventAssignment: true
}),
typescriptPlugin({
...tsBundleOptions,
declaration: true,
outDir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import)),
declarationDir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import), 'types'),
declarationMap: true
}),
commonjs({ extensions: ['.js', '.ts'] }) // the ".ts" extension is required
],
external
},
{ // Node CJS with declaration files
input: input,
output: {
dir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.require)),
entryFileNames: path.basename(pkgJson.exports['.'].node.require),
...sourcemapOutputOptions,
format: 'cjs'
},
plugins: [
replace({
'process.browser': false
})
IS_BROWSER: false,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions),
commonjs({ extensions: ['.js', '.ts'] }) // the ".ts" extension is required
]
// external: ['bigint-crypto-utils']
}
]

View File

@ -1,62 +0,0 @@
'use strict'
const resolve = require('@rollup/plugin-node-resolve')
const replace = require('@rollup/plugin-replace')
const commonjs = require('@rollup/plugin-commonjs')
const multi = require('@rollup/plugin-multi-entry')
const fs = require('fs')
const path = require('path')
const pkgJson = require('../package.json')
const pkgJsonLock = require('../package-lock.json')
const mochaVersion = pkgJsonLock.dependencies.mocha.version
const chaiVersion = pkgJsonLock.dependencies.chai.version
const pkgName = pkgJson.name
const rootDir = path.join(__dirname, '..')
// Let's first create the appropriate html file loading mocha, chai and a bundle of the tests
const templatePath = path.join(rootDir, pkgJson.directories.src, 'browser', 'tests-template.html')
const dstDir = path.join(rootDir, pkgJson.directories.test, 'browser')
const dstFileName = path.join(dstDir, 'index.html')
const template = fs.readFileSync(templatePath, 'utf-8')
const bundleFile = path.join(rootDir, pkgJson.directories.lib, 'index.browser.bundle.mod.js')
const testsJs = `
<script type="module">
import * as _pkg from '${path.relative(templatePath, bundleFile)}'
window._pkg = _pkg;
import './tests.js';
mocha.run();
</script>`
fs.writeFileSync(dstFileName,
template.replace(/{{TESTS}}/g, testsJs).replace(/{{PKG_NAME}}/g, pkgName).replace(/{{MOCHA_VERSION}}/g, mochaVersion).replace(/{{CHAI_VERSION}}/g, chaiVersion)
)
const input = path.join(rootDir, pkgJson.directories.test, '*.js')
console.log(input)
module.exports = [
{
input: input,
plugins: [
multi({ exports: false }),
replace({
'const _pkg = require(\'../lib/index.node\')': '',
'const chai = require(\'chai\')': '',
delimiters: ['', ''],
'process.browser': true
}),
resolve({
browser: true
}),
commonjs()
],
output: {
file: path.join(rootDir, pkgJson.directories.test, 'browser', 'tests.js'),
format: 'esm'
},
external: [pkgName]
}
]

View File

@ -0,0 +1,66 @@
const puppeteer = require('puppeteer')
const browserTests = async ({ logWarnings = false, serverPort = 38000, keepServerRunning = false, puppeteerOptions = {} }) => {
const server = require('./server.js').server
await server.init()
await server.listen(serverPort)
const browser = await puppeteer.launch(puppeteerOptions)
const page = await browser.newPage()
page.on('console', function (message) {
let ignore = message.type() === 'warning' && !logWarnings
if (message.type() === 'error' && message.location()) {
if (message.location().url.includes('favicon.ico')) {
ignore = true
}
}
if (ignore) return
let text = (message.args().length > 0) ? message.args()[0]._remoteObject.value : message.text()
const args = []
if (message.args() !== undefined && message.args().length > 1) {
for (let i = 1; i < message.args().length; i++) {
args.push(message.args()[i]._remoteObject.value)
}
}
if (message.type() === 'error' && message.location()) {
text = `${message.location().url} : ${text}`
}
let consoleType = 'log'
switch (message.type()) {
case 'error':
consoleType = 'error'
break
case 'warning':
consoleType = 'warn'
break
default:
break
}
console[consoleType](text, ...args)
})
page.on('error', function (err) { page.emit(new Error(err)) })
await page.goto('http://localhost:38000/')
const watchDog = page.waitForFunction('_mocha.state === \'stopped\'')
await watchDog
if (keepServerRunning === false) {
await page.close()
await browser.close()
await server.close()
}
}
const opts = {
// puppeteer options
puppeteerOptions: {
headless: true
// slowMo: 100,
// timeout: 10000
},
doNotLogWarnings: true,
keepServerRunning: false, // keep server running until manually closed with ctrl-c. In combination with puppeteerOptions.headless (or just connecting any browser to the test page) allows debugging in browser
serverPort: 38000
}
browserTests(opts)

View File

@ -0,0 +1,141 @@
'use strict'
const fs = require('fs')
const http = require('http')
const path = require('path')
const pkgJson = require('../../../package.json')
const rollup = require('rollup')
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('@rollup/plugin-replace')
const multi = require('@rollup/plugin-multi-entry')
const typescript = require('@rollup/plugin-typescript')
const commonjs = require('@rollup/plugin-commonjs')
const rootDir = path.join(__dirname, '..', '..', '..')
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const indexHtml = `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>${name}</title>
<script src="/mocha.js"></script>
<script src="/chai.js"></script>
</head>
<body>
</body>
<div id="mocha"></div>
<script>
mocha.setup({
ui: 'bdd',
reporter: 'spec',
color: 'true',
timeout: 90000
})
</script>
<script type="module">
import * as _pkg from './${name}.esm.js'
self._pkg = _pkg
import './tests.js'
window._mocha = mocha.run()
</script>
</html>`
async function buildTests () {
// create a bundle
const inputOptions = {
input: [path.join(rootDir, pkgJson.directories.test, '**/*.ts'), path.join(rootDir, pkgJson.directories.src, '**/*.spec.ts')],
plugins: [
multi({ exports: true }),
replace({
IS_BROWSER: true,
preventAssignment: true
}),
typescript(),
resolve({
browser: true,
exportConditions: ['browser', 'module', 'import', 'default']
}),
commonjs()
]
}
const bundle = await rollup.rollup(inputOptions)
const { output } = await bundle.generate({ format: 'esm' })
await bundle.close()
return output[0].code
}
class TestServer {
constructor () {
this.server = http.createServer()
}
async init () {
const tests = await buildTests()
this.server.on('request', function (req, res) {
if (req.url === `/${name}.esm.js`) {
fs.readFile(path.join(rootDir, pkgJson.directories.dist, `bundles/${name}.esm.js`), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else if (req.url === '/index.html' || req.url === '/') {
res.writeHead(200)
res.end(indexHtml)
} else if (req.url === '/tests.js') {
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(tests)
} else if (req.url === '/mocha.js') {
fs.readFile(path.join(rootDir, 'node_modules/mocha/mocha.js'), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else if (req.url === '/chai.js' || req.url === '/chai') {
fs.readFile(path.join(rootDir, 'node_modules/chai/chai.js'), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else {
res.writeHead(404)
res.end()
}
})
}
listen (port = 38080) {
return new Promise((resolve, reject) => {
this.server.listen(port, error => {
if (error) return reject(error)
console.log(`Testing server listenning at http://localhost:${port}`)
return resolve()
})
})
}
close () {
return new Promise((resolve, reject) => {
this.server.close(error => (error) ? reject(error) : resolve())
})
}
}
exports.server = new TestServer()

View File

@ -0,0 +1,59 @@
const EventEmitter = require('events')
const fs = require('fs')
const path = require('path')
module.exports = class Builder extends EventEmitter {
constructor (semaphoreFile, name = 'builder') {
super()
this.name = name
this.firstBuild = true
fs.mkdirSync(path.dirname(semaphoreFile), { recursive: true })
this.semaphoreFile = semaphoreFile
this._ready = false
this.on('message', (...message) => {
if (message !== undefined) {
console.log(`\x1b[33m [${this.name}]`, ...message, '\x1b[0m')
}
})
this.on('error', (...error) => {
if (error !== undefined) {
console.error(`\x1b[31m❗ [${this.name}]`, ...error, '\x1b[0m')
}
})
this.on('ready', () => {
if (this.firstBuild === false) {
fs.writeFileSync(this.semaphoreFile, '', 'utf-8')
} else {
this.firstBuild = false
}
this._ready = true
})
this.on('busy', () => {
this._ready = false
})
}
ready () {
return new Promise(resolve => {
if (this._ready === true) return resolve()
this.once('ready', () => {
resolve()
})
})
}
async start () {
}
async close () {}
clean () {
fs.rmSync(this.semaphoreFile, { force: true })
}
}

View File

@ -0,0 +1,122 @@
const EventEmitter = require('events')
const fs = require('fs')
const path = require('path')
const rollup = require('rollup')
const loadAndParseConfigFile = require('rollup/dist/loadConfigFile')
const Builder = require('./Builder.js')
const rootDir = path.join(__dirname, '../../../../')
const pkgJson = require(path.join(rootDir, 'package.json'))
module.exports = class RollupBuilder extends Builder {
constructor ({ name = 'rollup', configPath = path.join(rootDir, 'rollup.config.js'), tempDir = path.join(rootDir, '.mocha-ts'), watch = false }) {
super(path.join(tempDir, 'semaphore'), name)
this.configPath = configPath
this.watch = watch
}
async start () {
await super.start()
const { options } = await loadAndParseConfigFile(this.configPath)
// Watch only the Node CJS module, that is the one we are going to use with mocha
const rollupOptions = options.filter(bundle => {
const file = (bundle.output[0].dir !== undefined)
? path.join(bundle.output[0].dir, bundle.output[0].entryFileNames)
: bundle.output[0].file
return file === path.join(rootDir, pkgJson.main)
})[0]
this.builder = new RollupBundler(rollupOptions, this.watch)
this.builder.on('event', event => {
switch (event.code) {
case 'START':
this.emit('busy')
if (this.firstBuild === true) {
this.emit('message', 'building your module...')
} else {
this.emit('message', 'file changes detected. Rebuilding module files...')
}
break
case 'BUNDLE_END':
if (event.result) event.result.close()
break
case 'END':
if (event.result) event.result.close()
this.emit('ready')
break
case 'ERROR':
if (event.result) event.result.close()
this.emit('error', event.error)
fs.writeFileSync(path.join(rootDir, pkgJson.main), '', 'utf8')
this.emit('ready')
break
default:
this.emit('busy')
break
}
})
this.builder.start()
return await this.ready()
}
async close () {
await super.close()
this.builder.close()
}
}
class RollupBundler extends EventEmitter {
constructor (rollupOptions, watch = false) {
super()
this.rollupOptions = rollupOptions
this.watch = watch
}
async start () {
if (this.watch === true) {
this.watcher = rollup.watch(this.rollupOptions)
this.watcher.on('event', event => {
this.emit('event', event)
})
} else {
if (fs.existsSync(path.join(rootDir, pkgJson.main)) === false) {
await this._bundle()
} else {
this.emit('event', { code: 'END', noBuild: true })
}
}
}
async _bundle () {
this.emit('event', { code: 'START' })
for (const optionsObj of [].concat(this.rollupOptions)) {
try {
const bundle = await rollup.rollup(optionsObj)
try {
await Promise.all(optionsObj.output.map(bundle.write))
this.emit('event', { code: 'BUNDLE_END' })
} catch (error) {
this.emit('event', { code: 'ERROR', error })
}
} catch (error) {
this.emit('event', { code: 'ERROR', error })
}
}
this.emit('event', { code: 'END' })
}
close () {
if (this.watcher !== undefined) this.watcher.close()
}
}

View File

@ -0,0 +1,95 @@
const path = require('path')
const fs = require('fs')
const ts = require('typescript')
const JSON5 = require('json5')
const Builder = require('./Builder.js')
const rootDir = path.join(__dirname, '../../../../')
const mochaTsRelativeDir = '.mocha-ts'
const mochaTsDir = path.join(rootDir, mochaTsRelativeDir)
const formatHost = {
getCanonicalFileName: path => path,
getCurrentDirectory: ts.sys.getCurrentDirectory,
getNewLine: () => ts.sys.newLine
}
module.exports = class TestsBuilder extends Builder {
constructor ({ name = 'tsc', configPath = path.join(rootDir, 'tsconfig.json'), tempDir = mochaTsDir }) {
super(path.join(tempDir, 'semaphore'), name)
if (fs.existsSync(configPath) !== true) throw new Error(`Couldn't find a tsconfig file at ${configPath}`)
this.tempDir = tempDir
const readFileAndMangle = (path) => { // We need to change the include or file in the original file to only compile the tests
const fileStr = fs.readFileSync(path, 'utf8')
const config = JSON5.parse(fileStr)
if (config.file) delete config.file
config.include = ['build/typings/**/*.ts', 'test/**/*.ts', 'src/**/*.spec.ts']
return JSON.stringify(config)
}
const configFile = ts.readJsonConfigFile(configPath, readFileAndMangle)
const parsedTsConfig = ts.parseJsonSourceFileConfigFileContent(configFile, ts.sys, path.dirname(configPath))
const createProgram = ts.createSemanticDiagnosticsBuilderProgram
const reportDiagnostic = (diagnostic) => {
const filePath = path.relative(rootDir, diagnostic.file.fileName)
const tranpiledJsPath = `${path.join(tempDir, filePath).slice(0, -3)}.js`
const errorLine = diagnostic.file.text.slice(0, diagnostic.start).split(/\r\n|\r|\n/).length
if (fs.existsSync(tranpiledJsPath)) {
fs.writeFileSync(tranpiledJsPath, '', 'utf8')
}
this.emit('error', `[Error ${diagnostic.code}]`, `${filePath}:${errorLine}`, ':', ts.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine()))
}
const reportWatchStatusChanged = (diagnostic, newLine, options, errorCount) => {
if (errorCount !== undefined) {
this.emit('ready')
} else {
this.emit('busy')
if (diagnostic.code === 6031) {
this.emit('message', 'transpiling your tests...')
} else if (diagnostic.code === 6032) {
this.emit('message', 'file changes detected. Transpiling your tests...')
}
}
}
// Note that there is another overload for `createWatchCompilerHost` that takes
// a set of root files.
this.host = ts.createWatchCompilerHost(
parsedTsConfig.fileNames,
{
...parsedTsConfig.options,
rootDir,
outDir: this.tempDir,
module: 'commonjs',
noEmit: false,
noResolve: true,
sourceMap: true
},
ts.sys,
createProgram,
reportDiagnostic,
reportWatchStatusChanged
)
}
async start () {
await super.start()
// `createWatchProgram` creates an initial program, watches files, and updates
// the program over time.
this.watcher = ts.createWatchProgram(this.host)
return await this.ready()
}
async close () {
await super.close()
this.watcher.close()
}
}

View File

@ -0,0 +1,52 @@
'use strict'
const path = require('path')
const chai = require('chai')
const rimraf = require('rimraf')
const RollupBuilder = require('./builders/RollupBuilder.js')
const TestsBuilder = require('./builders/TestsBuilder.js')
const rootDir = path.join(__dirname, '../../../')
global.chai = chai
const watch = process.argv.includes('--watch') || process.argv.includes('-w')
const tempDir = path.join(rootDir, '.mocha-ts')
const rollupBuilder = new RollupBuilder({ name: 'rollup', configPath: path.join(rootDir, 'build/rollup.config.js'), tempDir, watch })
const testBuilder = new TestsBuilder({ name: 'tsc', tempDir })
rollupBuilder.start() // This should be in exports.mochaGlobalSetup but mocha fails when not in watch mode (DIRT...)
testBuilder.start() // This should be in exports.mochaGlobalSetup but mocha fails when not in watch mode (DIRT...)
exports.mochaHooks = {
beforeAll: [
async function () {
// Just in case our module had been modified. Reload it when the tests are repeated (for mocha watch mode).
delete require.cache[require.resolve(rootDir)]
global._pkg = require(rootDir)
},
async function () {
this.timeout('120000')
await Promise.all([rollupBuilder.ready(), testBuilder.ready()])
}
]
}
// exports.mochaGlobalSetup = async function () {
// await rollupBuilder.start()
// await testBuilder.start()
// }
exports.mochaGlobalTeardown = async function () {
await testBuilder.close()
await rollupBuilder.close()
// I use the sync version of rimraf precisely because it blocks the
// main thread and thus the mocha watcher, which otherwise would complain
// about files being deleted
rimraf.sync(tempDir, { disableGlob: true })
}

5
build/typings/global-this-pkg.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import * as _pkgModule from '../..'
export as namespace _pkg
export = _pkgModule

1
build/typings/is-browser.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare const IS_BROWSER: boolean

1
dist/bundles/bigint-mod-arith.esm.js vendored Normal file
View File

@ -0,0 +1 @@
function n(n){return n>=0?n:-n}function t(n){if(1n===(n=BigInt(n)))return 1;let t=1;do{t++}while((n>>=1n)>1n);return t}function r(n,t){let r=BigInt(n),i=BigInt(t);if(r<=0n||i<=0n)throw new RangeError("a and b MUST be > 0");let e=0n,u=1n,o=1n,f=0n;for(;0n!==r;){const n=i/r,t=i%r,c=e-o*n,g=u-f*n;i=r,r=t,e=o,u=f,o=c,f=g}return{g:i,x:e,y:u}}function i(t,r){let i=BigInt(n(t)),e=BigInt(n(r));if(0n===i)return e;if(0n===e)return i;let u=0n;for(;0n===(1n&(i|e));)i>>=1n,e>>=1n,u++;for(;0n===(1n&i);)i>>=1n;do{for(;0n===(1n&e);)e>>=1n;if(i>e){const n=i;i=e,e=n}e-=i}while(0n!==e);return i<<u}function e(t,r){const e=BigInt(t),u=BigInt(r);return 0n===e&&0n===u?BigInt(0):n(e*u)/i(e,u)}function u(n,t){return n>=t?n:t}function o(n,t){return n>=t?t:n}function f(n,t){const r=BigInt(t);if(t<=0)return NaN;const i=BigInt(n)%r;return i<0n?i+r:i}function c(n,t){try{const i=r(f(n,t),t);return 1n!==i.g?NaN:f(i.x,t)}catch(n){return NaN}}function g(t,r,i){const e=BigInt(i);if(e<=0n)return NaN;if(1n===e)return BigInt(0);let u=f(t,e);if((r=BigInt(r))<0n)return c(g(u,n(r),e),e);let o=1n;for(;r>0;)r%2n===1n&&(o=o*u%e),r/=2n,u=u**2n%e;return o}export{n as abs,t as bitLength,r as eGcd,i as gcd,e as lcm,u as max,o as min,c as modInv,g as modPow,f as toZn};

1
dist/bundles/bigint-mod-arith.iife.js vendored Normal file
View File

@ -0,0 +1 @@
var bigintModArith=function(n){"use strict";function t(n){return n>=0?n:-n}function r(n,t){let r=BigInt(n),i=BigInt(t);if(r<=0n||i<=0n)throw new RangeError("a and b MUST be > 0");let e=0n,o=1n,u=1n,f=0n;for(;0n!==r;){const n=i/r,t=i%r,c=e-u*n,g=o-f*n;i=r,r=t,e=u,o=f,u=c,f=g}return{g:i,x:e,y:o}}function i(n,r){let i=BigInt(t(n)),e=BigInt(t(r));if(0n===i)return e;if(0n===e)return i;let o=0n;for(;0n===(1n&(i|e));)i>>=1n,e>>=1n,o++;for(;0n===(1n&i);)i>>=1n;do{for(;0n===(1n&e);)e>>=1n;if(i>e){const n=i;i=e,e=n}e-=i}while(0n!==e);return i<<o}function e(n,t){const r=BigInt(t);if(t<=0)return NaN;const i=BigInt(n)%r;return i<0n?i+r:i}function o(n,t){try{const i=r(e(n,t),t);return 1n!==i.g?NaN:e(i.x,t)}catch(n){return NaN}}return n.abs=t,n.bitLength=function(n){if(1n===(n=BigInt(n)))return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.eGcd=r,n.gcd=i,n.lcm=function(n,r){const e=BigInt(n),o=BigInt(r);return 0n===e&&0n===o?BigInt(0):t(e*o)/i(e,o)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modInv=o,n.modPow=function n(r,i,u){const f=BigInt(u);if(f<=0n)return NaN;if(1n===f)return BigInt(0);let c=e(r,f);if((i=BigInt(i))<0n)return o(n(c,t(i),f),f);let g=1n;for(;i>0;)i%2n===1n&&(g=g*c%f),i/=2n,c=c**2n%f;return g},n.toZn=e,Object.defineProperty(n,"__esModule",{value:!0}),n}({});

1
dist/bundles/bigint-mod-arith.umd.js vendored Normal file
View File

@ -0,0 +1 @@
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n="undefined"!=typeof globalThis?globalThis:n||self).bigintModArith={})}(this,(function(n){"use strict";function t(n){return n>=0?n:-n}function e(n,t){let e=BigInt(n),r=BigInt(t);if(e<=0n||r<=0n)throw new RangeError("a and b MUST be > 0");let i=0n,o=1n,f=1n,u=0n;for(;0n!==e;){const n=r/e,t=r%e,c=i-f*n,g=o-u*n;r=e,e=t,i=f,o=u,f=c,u=g}return{g:r,x:i,y:o}}function r(n,e){let r=BigInt(t(n)),i=BigInt(t(e));if(0n===r)return i;if(0n===i)return r;let o=0n;for(;0n===(1n&(r|i));)r>>=1n,i>>=1n,o++;for(;0n===(1n&r);)r>>=1n;do{for(;0n===(1n&i);)i>>=1n;if(r>i){const n=r;r=i,i=n}i-=r}while(0n!==i);return r<<o}function i(n,t){const e=BigInt(t);if(t<=0)return NaN;const r=BigInt(n)%e;return r<0n?r+e:r}function o(n,t){try{const r=e(i(n,t),t);return 1n!==r.g?NaN:i(r.x,t)}catch(n){return NaN}}n.abs=t,n.bitLength=function(n){if(1n===(n=BigInt(n)))return 1;let t=1;do{t++}while((n>>=1n)>1n);return t},n.eGcd=e,n.gcd=r,n.lcm=function(n,e){const i=BigInt(n),o=BigInt(e);return 0n===i&&0n===o?BigInt(0):t(i*o)/r(i,o)},n.max=function(n,t){return n>=t?n:t},n.min=function(n,t){return n>=t?t:n},n.modInv=o,n.modPow=function n(e,r,f){const u=BigInt(f);if(u<=0n)return NaN;if(1n===u)return BigInt(0);let c=i(e,u);if((r=BigInt(r))<0n)return o(n(c,t(r),u),u);let g=1n;for(;r>0;)r%2n===1n&&(g=g*c%u),r/=2n,c=c**2n%u;return g},n.toZn=i,Object.defineProperty(n,"__esModule",{value:!0})}));

231
dist/cjs/index.node.cjs vendored Normal file

File diff suppressed because one or more lines are too long

218
dist/esm/index.browser.js vendored Normal file

File diff suppressed because one or more lines are too long

218
dist/esm/index.node.js vendored Normal file

File diff suppressed because one or more lines are too long

16
dist/esm/types/index.d.ts vendored Normal file