mirror of
https://github.com/zkitter/json-rpc-engine.git
synced 2026-01-09 15:17:56 -05:00
Improve module template compliance (#100)
This PR updates various repository features for module template compliance. This repository should be fully compliant as of this PR, except for tests, which will be addressed in a follow-up. Notable changes include: - Updates the ESLint config and related dependencies - Adds `@lavamoat/allow-scripts` and the `setup` package script - Migrates from CircleCI to GitHub Actions - Bumps the minimum Node version to 14
This commit is contained in:
@@ -1,86 +0,0 @@
|
||||
version: 2.1
|
||||
|
||||
workflows:
|
||||
build-test:
|
||||
jobs:
|
||||
- prep-deps
|
||||
- prep-build:
|
||||
requires:
|
||||
- prep-deps
|
||||
- test-lint:
|
||||
requires:
|
||||
- prep-deps
|
||||
- prep-build
|
||||
- test-unit:
|
||||
requires:
|
||||
- prep-deps
|
||||
- prep-build
|
||||
- all-tests-pass:
|
||||
requires:
|
||||
- test-lint
|
||||
- test-unit
|
||||
|
||||
jobs:
|
||||
prep-deps:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install deps
|
||||
command: |
|
||||
.circleci/scripts/deps-install.sh
|
||||
- run:
|
||||
name: Collect yarn install HAR logs
|
||||
command: |
|
||||
.circleci/scripts/collect-har-artifact.sh
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- node_modules
|
||||
- build-artifacts
|
||||
|
||||
test-lint:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Lint
|
||||
command: yarn lint
|
||||
|
||||
prep-build:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Build project
|
||||
command: yarn build
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- dist
|
||||
|
||||
test-unit:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Unit tests
|
||||
command: yarn coverage
|
||||
|
||||
all-tests-pass:
|
||||
docker:
|
||||
- image: circleci/node:12
|
||||
steps:
|
||||
- run:
|
||||
name: All tests passed
|
||||
command: echo 'Great success'
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
mkdir -p build-artifacts/yarn-install-har
|
||||
mv ./*.har build-artifacts/yarn-install-har/
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
yarn --frozen-lockfile --ignore-scripts --har
|
||||
@@ -1,13 +1,9 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
|
||||
20
.eslintrc.js
20
.eslintrc.js
@@ -1,22 +1,28 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
|
||||
plugins: ['import'],
|
||||
|
||||
extends: ['@metamask/eslint-config', '@metamask/eslint-config-nodejs'],
|
||||
|
||||
rules: {
|
||||
'prefer-object-spread': 'off',
|
||||
},
|
||||
extends: ['@metamask/eslint-config'],
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts'],
|
||||
extends: ['@metamask/eslint-config-typescript'],
|
||||
},
|
||||
|
||||
{
|
||||
files: ['*.js'],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
},
|
||||
extends: ['@metamask/eslint-config-nodejs'],
|
||||
},
|
||||
|
||||
{
|
||||
files: ['test/*'],
|
||||
extends: ['@metamask/eslint-config-mocha'],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
|
||||
15
.github/dependabot.yml
vendored
Normal file
15
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: 'npm'
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
time: '06:00'
|
||||
allow:
|
||||
- dependency-name: '@metamask/*'
|
||||
target-branch: 'main'
|
||||
versioning-strategy: 'increase-if-necessary'
|
||||
open-pull-requests-limit: 10
|
||||
56
.github/workflows/build-test.yml
vendored
Normal file
56
.github/workflows/build-test.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Build, Lint, and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-lint-test:
|
||||
name: Build, Lint, and Test
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Get Yarn cache directory
|
||||
run: echo "::set-output name=YARN_CACHE_DIR::$(yarn cache dir)"
|
||||
id: yarn-cache-dir
|
||||
- name: Get Yarn version
|
||||
run: echo "::set-output name=YARN_VERSION::$(yarn --version)"
|
||||
id: yarn-version
|
||||
- name: Cache yarn dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir.outputs.YARN_CACHE_DIR }}
|
||||
key: yarn-cache-${{ runner.os }}-${{ steps.yarn-version.outputs.YARN_VERSION }}-${{ hashFiles('yarn.lock') }}
|
||||
- run: yarn --frozen-lockfile
|
||||
- run: yarn allow-scripts
|
||||
- run: yarn build
|
||||
- run: yarn lint
|
||||
- run: yarn test
|
||||
- name: Validate RC changelog
|
||||
if: ${{ startsWith(github.head_ref, 'release/') }}
|
||||
run: yarn auto-changelog validate --rc
|
||||
- name: Validate changelog
|
||||
if: ${{ !startsWith(github.head_ref, 'release/') }}
|
||||
run: yarn auto-changelog validate
|
||||
- name: Require clean working directory
|
||||
shell: bash
|
||||
run: |
|
||||
if ! git diff --exit-code; then
|
||||
echo "Working tree dirty after building"
|
||||
exit 1
|
||||
fi
|
||||
all-jobs-pass:
|
||||
name: All jobs pass
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- build-lint-test
|
||||
steps:
|
||||
- run: echo "Great success!"
|
||||
50
.github/workflows/create-release-pr.yml
vendored
Normal file
50
.github/workflows/create-release-pr.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Create Release Pull Request
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
base-branch:
|
||||
description: 'The base branch for git operations and the pull request.'
|
||||
default: 'main'
|
||||
required: true
|
||||
release-type:
|
||||
description: 'A SemVer version diff, i.e. major, minor, patch, prerelease etc. Mutually exclusive with "release-version".'
|
||||
required: false
|
||||
release-version:
|
||||
description: 'A specific version to bump to. Mutually exclusive with "release-type".'
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
create-release-pr:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# This is to guarantee that the most recent tag is fetched.
|
||||
# This can be configured to a more reasonable value by consumers.
|
||||
fetch-depth: 0
|
||||
# We check out the specified branch, which will be used as the base
|
||||
# branch for all git operations and the release PR.
|
||||
ref: ${{ github.event.inputs.base-branch }}
|
||||
- name: Get Node.js version
|
||||
id: nvm
|
||||
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ steps.nvm.outputs.NODE_VERSION }}
|
||||
- uses: MetaMask/action-create-release-pr@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
release-type: ${{ github.event.inputs.release-type }}
|
||||
release-version: ${{ github.event.inputs.release-version }}
|
||||
artifacts-path: gh-action__release-authors
|
||||
# Upload the release author artifact for use in subsequent workflows
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-authors
|
||||
path: gh-action__release-authors
|
||||
if-no-files-found: error
|
||||
29
.github/workflows/publish-release.yml
vendored
Normal file
29
.github/workflows/publish-release.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Publish Release
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
publish-release:
|
||||
permissions:
|
||||
contents: write
|
||||
if: |
|
||||
github.event.pull_request.merged == true &&
|
||||
startsWith(github.event.pull_request.head.ref, 'release/')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# We check out the release pull request's base branch, which will be
|
||||
# used as the base branch for all git operations.
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
- name: Get Node.js version
|
||||
id: nvm
|
||||
run: echo ::set-output name=NODE_VERSION::$(cat .nvmrc)
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ steps.nvm.outputs.NODE_VERSION }}
|
||||
- uses: MetaMask/action-publish-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
29
.github/workflows/require-additional-reviewer.yml
vendored
Normal file
29
.github/workflows/require-additional-reviewer.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Require Additional Reviewer for Releases
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_review:
|
||||
|
||||
jobs:
|
||||
require-additional-reviewer:
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: read
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# If the base branch has been merged into the release branch, we
|
||||
# need to find the earliest common ancestor commit of the base and
|
||||
# release branches.
|
||||
fetch-depth: 0
|
||||
# We want the head / feature branch to be checked out, and we will
|
||||
# compare it to the base branch in the action.
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
- uses: MetaMask/action-require-additional-reviewer@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
read-org-token: ${{ secrets.ORG_READER }}
|
||||
8
.prettierrc.js
Normal file
8
.prettierrc.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// All of these are defaults except singleQuote, but we specify them
|
||||
// for explicitness
|
||||
module.exports = {
|
||||
quoteProps: 'as-needed',
|
||||
singleQuote: true,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'all',
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
quoteProps: consistent
|
||||
singleQuote: true
|
||||
trailingComma: all
|
||||
tabWidth: 2
|
||||
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,41 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- `isJsonRpcSuccess` and `isJsonRpcFailure` type guard utilities ([#91](https://github.com/MetaMask/json-rpc-engine/pull/91))
|
||||
- JSON-RPC ID validation utility and type guard, via `getJsonRpcIdValidator` ([#91](https://github.com/MetaMask/json-rpc-engine/pull/91))
|
||||
|
||||
### Changed
|
||||
|
||||
- **(BREAKING)** Return a `null` instead of `undefined` response `id` for malformed request objects ([#91](https://github.com/MetaMask/json-rpc-engine/pull/91))
|
||||
- This is very unlikely to be breaking in practice, but the behavior could have been relied on.
|
||||
|
||||
## [6.1.0] - 2020-11-20
|
||||
|
||||
### Added
|
||||
|
||||
- Add `PendingJsonRpcResponse` interface for use in middleware ([#75](https://github.com/MetaMask/json-rpc-engine/pull/75))
|
||||
|
||||
### Changed
|
||||
|
||||
- Use `async`/`await` and `try`/`catch` instead of Promise methods everywhere ([#74](https://github.com/MetaMask/json-rpc-engine/pull/74))
|
||||
- Consumers may notice improved stack traces on certain platforms.
|
||||
|
||||
## [6.0.0] - 2020-11-19
|
||||
|
||||
### Added
|
||||
|
||||
- Add docstrings for public `JsonRpcEngine` methods ([#70](https://github.com/MetaMask/json-rpc-engine/pull/70))
|
||||
|
||||
### Changed
|
||||
|
||||
- **(BREAKING)** Refactor exports ([#69](https://github.com/MetaMask/json-rpc-engine/pull/69))
|
||||
- All exports are now named, and available via the package entry point.
|
||||
- All default exports have been removed.
|
||||
@@ -50,43 +40,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Make some internal `JsonRpcEngine` methods `static` ([#71](https://github.com/MetaMask/json-rpc-engine/pull/71))
|
||||
|
||||
## [5.4.0] - 2020-11-07
|
||||
|
||||
### Changed
|
||||
|
||||
- Make the TypeScript types not terrible ([#66](https://github.com/MetaMask/json-rpc-engine/pull/66), [#67](https://github.com/MetaMask/json-rpc-engine/pull/67))
|
||||
|
||||
## [5.3.0] - 2020-07-30
|
||||
|
||||
### Changed
|
||||
|
||||
- Response object errors no longer include a `stack` property
|
||||
|
||||
## [5.2.0] - 2020-07-24
|
||||
|
||||
### Added
|
||||
|
||||
- Promise signatures for `engine.handle` ([#55](https://github.com/MetaMask/json-rpc-engine/pull/55))
|
||||
- So, in addition to `engine.handle(request, callback)`, you can do e.g. `await engine.handle(request)`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove `async` and `promise-to-callback` dependencies
|
||||
- These dependencies were used internally for middleware flow control.
|
||||
They have been replaced with Promises and native `async`/`await`, which means that some operations are _no longer_ eagerly executed.
|
||||
This change may affect consumers that depend on the eager execution of middleware _during_ request processing, _outside of_ middleware functions and request handlers.
|
||||
- In general, it is a bad practice to work with state that depends on middleware execution, while the middleware are executing.
|
||||
|
||||
[unreleased]: https://github.com/MetaMask/json-rpc-engine/compare/v6.1.0...HEAD
|
||||
[Unreleased]: https://github.com/MetaMask/json-rpc-engine/compare/v6.1.0...HEAD
|
||||
[6.1.0]: https://github.com/MetaMask/json-rpc-engine/compare/v6.0.0...v6.1.0
|
||||
[6.0.0]: https://github.com/MetaMask/json-rpc-engine/compare/v5.4.0...v6.0.0
|
||||
[5.4.0]: https://github.com/MetaMask/json-rpc-engine/compare/v5.3.0...v5.4.0
|
||||
[5.3.0]: https://github.com/MetaMask/json-rpc-engine/compare/v5.2.0...v5.3.0
|
||||
[5.2.0]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.8...v5.2.0
|
||||
[5.1.8]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.6...v5.1.8
|
||||
[5.1.6]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.5...v5.1.6
|
||||
[5.1.5]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.4...v5.1.5
|
||||
[5.1.4]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.3...v5.1.4
|
||||
[5.1.3]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.1...v5.1.3
|
||||
[5.1.1]: https://github.com/MetaMask/json-rpc-engine/compare/v5.1.0...v5.1.1
|
||||
[5.1.0]: https://github.com/MetaMask/json-rpc-engine/compare/v5.0.0...v5.1.0
|
||||
[5.0.0]: https://github.com/MetaMask/json-rpc-engine/compare/v4.0.0...v5.0.0
|
||||
[5.2.0]: https://github.com/MetaMask/json-rpc-engine/releases/tag/v5.2.0
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2020 MetaMask
|
||||
Copyright (c) 2022 MetaMask
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
||||
71
package.json
71
package.json
@@ -2,62 +2,69 @@
|
||||
"name": "json-rpc-engine",
|
||||
"version": "6.1.0",
|
||||
"description": "A tool for processing JSON-RPC messages.",
|
||||
"homepage": "https://github.com/MetaMask/json-rpc-engine#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MetaMask/json-rpc-engine/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MetaMask/json-rpc-engine.git"
|
||||
},
|
||||
"license": "ISC",
|
||||
"author": "kumavis",
|
||||
"main": "dist/index.js",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc --project .",
|
||||
"lint:eslint": "eslint . --cache --ext js,ts",
|
||||
"lint:misc": "prettier '**/*.json' '**/*.md' '**/*.yml' --single-quote --ignore-path .gitignore",
|
||||
"build:clean": "rimraf dist && yarn build",
|
||||
"lint": "yarn lint:eslint && yarn lint:misc --check",
|
||||
"lint:eslint": "eslint . --cache --ext js,ts",
|
||||
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",
|
||||
"lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' '**/*.yml' --ignore-path .gitignore --no-error-on-unmatched-pattern",
|
||||
"prepublishOnly": "yarn build:clean && yarn lint && yarn test:coverage",
|
||||
"setup": "yarn install && yarn allow-scripts",
|
||||
"test": "mocha ./test",
|
||||
"coverage": "nyc --check-coverage yarn test",
|
||||
"prepublishOnly": "yarn && yarn lint && yarn build && yarn coverage"
|
||||
"test:coverage": "nyc --check-coverage yarn test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@metamask/safe-event-emitter": "^2.0.0",
|
||||
"eth-rpc-errors": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@metamask/eslint-config": "^6.0.0",
|
||||
"@lavamoat/allow-scripts": "^1.0.5",
|
||||
"@metamask/auto-changelog": "^2.3.0",
|
||||
"@metamask/eslint-config": "^9.0.0",
|
||||
"@metamask/eslint-config-mocha": "^6.0.0",
|
||||
"@metamask/eslint-config-nodejs": "^6.0.0",
|
||||
"@metamask/eslint-config-typescript": "^6.0.0",
|
||||
"@types/node": "^14.14.7",
|
||||
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||
"@typescript-eslint/parser": "^4.24.0",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.23.2",
|
||||
"@metamask/eslint-config-nodejs": "^9.0.0",
|
||||
"@metamask/eslint-config-typescript": "^9.0.1",
|
||||
"@types/node": "^17.0.23",
|
||||
"@typescript-eslint/eslint-plugin": "^4.21.0",
|
||||
"@typescript-eslint/parser": "^4.21.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsdoc": "^36.1.0",
|
||||
"eslint-plugin-mocha": "^8.1.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"mocha": "^7.1.1",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.3.0",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-plugin-packagejson": "^2.2.11",
|
||||
"rimraf": "^3.0.2",
|
||||
"sinon": "^9.0.2",
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/MetaMask/json-rpc-engine.git"
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/MetaMask/json-rpc-engine/issues"
|
||||
},
|
||||
"homepage": "https://github.com/MetaMask/json-rpc-engine#readme",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"contributors": [
|
||||
"kumavis <aaron@kumavis.me>",
|
||||
"Erik Marks <rekmarks@protonmail.com>"
|
||||
]
|
||||
"lavamoat": {
|
||||
"allowScripts": {
|
||||
"@lavamoat/preinstall-always-fail": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,35 +133,33 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
/**
|
||||
* Handle a JSON-RPC request, and return a response.
|
||||
*
|
||||
* @param request - The request to handle.
|
||||
* @returns A promise that resolves with the response, or rejects with an
|
||||
* error.
|
||||
* @param request - The JSON-RPC request to handle.
|
||||
* @returns The JSON-RPC response.
|
||||
*/
|
||||
handle<T, U>(request: JsonRpcRequest<T>): Promise<JsonRpcResponse<U>>;
|
||||
|
||||
/**
|
||||
* Handle an array of JSON-RPC requests, and return an array of responses.
|
||||
*
|
||||
* @param request - The requests to handle.
|
||||
* @returns A promise that resolves with the array of responses, or rejects
|
||||
* with an error.
|
||||
* @param request - The JSON-RPC requests to handle.
|
||||
* @returns An array of JSON-RPC responses.
|
||||
*/
|
||||
handle<T, U>(requests: JsonRpcRequest<T>[]): Promise<JsonRpcResponse<U>[]>;
|
||||
|
||||
handle(req: unknown, cb?: any) {
|
||||
if (cb && typeof cb !== 'function') {
|
||||
handle(req: unknown, callback?: any) {
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error('"callback" must be a function if provided.');
|
||||
}
|
||||
|
||||
if (Array.isArray(req)) {
|
||||
if (cb) {
|
||||
return this._handleBatch(req, cb);
|
||||
if (callback) {
|
||||
return this._handleBatch(req, callback);
|
||||
}
|
||||
return this._handleBatch(req);
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
return this._handle(req as JsonRpcRequest<unknown>, cb);
|
||||
if (callback) {
|
||||
return this._handle(req as JsonRpcRequest<unknown>, callback);
|
||||
}
|
||||
return this._promiseHandle(req as JsonRpcRequest<unknown>);
|
||||
}
|
||||
@@ -209,12 +207,20 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
*/
|
||||
private _handleBatch(
|
||||
reqs: JsonRpcRequest<unknown>[],
|
||||
cb: (error: unknown, responses?: JsonRpcResponse<unknown>[]) => void,
|
||||
callback: (error: unknown, responses?: JsonRpcResponse<unknown>[]) => void,
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* Handles a batch of JSON-RPC requests, either in `async` or callback
|
||||
* fashion.
|
||||
*
|
||||
* @param reqs - The request objects to process.
|
||||
* @param callback - The completion callback.
|
||||
* @returns The array of responses, or nothing if a callback was specified.
|
||||
*/
|
||||
private async _handleBatch(
|
||||
reqs: JsonRpcRequest<unknown>[],
|
||||
cb?: (error: unknown, responses?: JsonRpcResponse<unknown>[]) => void,
|
||||
callback?: (error: unknown, responses?: JsonRpcResponse<unknown>[]) => void,
|
||||
): Promise<JsonRpcResponse<unknown>[] | void> {
|
||||
// The order here is important
|
||||
try {
|
||||
@@ -226,13 +232,13 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
);
|
||||
|
||||
// 3. Return batch response
|
||||
if (cb) {
|
||||
return cb(null, responses);
|
||||
if (callback) {
|
||||
return callback(null, responses);
|
||||
}
|
||||
return responses;
|
||||
} catch (error) {
|
||||
if (cb) {
|
||||
return cb(error);
|
||||
if (callback) {
|
||||
return callback(error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
@@ -241,6 +247,9 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
|
||||
/**
|
||||
* A promise-wrapped _handle.
|
||||
*
|
||||
* @param req - The JSON-RPC request.
|
||||
* @returns The JSON-RPC response.
|
||||
*/
|
||||
private _promiseHandle(
|
||||
req: JsonRpcRequest<unknown>,
|
||||
@@ -259,10 +268,14 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
* error and the response object to the given callback.
|
||||
*
|
||||
* Does not reject.
|
||||
*
|
||||
* @param callerReq - The request object from the caller.
|
||||
* @param callback - The callback function.
|
||||
* @returns Nothing.
|
||||
*/
|
||||
private async _handle(
|
||||
callerReq: JsonRpcRequest<unknown>,
|
||||
cb: (error: unknown, response: JsonRpcResponse<unknown>) => void,
|
||||
callback: (error: unknown, response: JsonRpcResponse<unknown>) => void,
|
||||
): Promise<void> {
|
||||
if (
|
||||
!callerReq ||
|
||||
@@ -274,7 +287,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
`Requests must be plain objects. Received: ${typeof callerReq}`,
|
||||
{ request: callerReq },
|
||||
);
|
||||
return cb(error, { id: null, jsonrpc: '2.0', error });
|
||||
return callback(error, { id: null, jsonrpc: '2.0', error });
|
||||
}
|
||||
|
||||
if (typeof callerReq.method !== 'string') {
|
||||
@@ -283,7 +296,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
`Must specify a string method. Received: ${typeof callerReq.method}`,
|
||||
{ request: callerReq },
|
||||
);
|
||||
return cb(error, { id: callerReq.id, jsonrpc: '2.0', error });
|
||||
return callback(error, { id: callerReq.id, jsonrpc: '2.0', error });
|
||||
}
|
||||
|
||||
const req: JsonRpcRequest<unknown> = { ...callerReq };
|
||||
@@ -309,13 +322,16 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
return cb(error, res as JsonRpcResponse<unknown>);
|
||||
return callback(error, res as JsonRpcResponse<unknown>);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given request and response, runs all middleware and their return
|
||||
* handlers, if any, and ensures that internal request processing semantics
|
||||
* are satisfied.
|
||||
*
|
||||
* @param req - The request object.
|
||||
* @param res - The response object.
|
||||
*/
|
||||
private async _processRequest(
|
||||
req: JsonRpcRequest<unknown>,
|
||||
@@ -342,6 +358,9 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
/**
|
||||
* Serially executes the given stack of middleware.
|
||||
*
|
||||
* @param req - The request object.
|
||||
* @param res - The response object.
|
||||
* @param middlewareStack - The stack of middleware functions to execute.
|
||||
* @returns An array of any error encountered during middleware execution,
|
||||
* a boolean indicating whether the request was completed, and an array of
|
||||
* middleware-defined return handlers.
|
||||
@@ -369,6 +388,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
middleware,
|
||||
returnHandlers,
|
||||
);
|
||||
|
||||
if (isComplete) {
|
||||
break;
|
||||
}
|
||||
@@ -377,8 +397,12 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs an individual middleware.
|
||||
* Runs an individual middleware function.
|
||||
*
|
||||
* @param req - The request object.
|
||||
* @param res - The response object.
|
||||
* @param middleware - The middleware function to execute.
|
||||
* @param returnHandlers - The return handlers array for the current request.
|
||||
* @returns An array of any error encountered during middleware exection,
|
||||
* and a boolean indicating whether the request should end.
|
||||
*/
|
||||
@@ -436,6 +460,8 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
/**
|
||||
* Serially executes array of return handlers. The request and response are
|
||||
* assumed to be in their scope.
|
||||
*
|
||||
* @param handlers - The return handlers to execute.
|
||||
*/
|
||||
private static async _runReturnHandlers(
|
||||
handlers: JsonRpcEngineReturnHandler[],
|
||||
@@ -450,6 +476,11 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
/**
|
||||
* Throws an error if the response has neither a result nor an error, or if
|
||||
* the "isComplete" flag is falsy.
|
||||
*
|
||||
* @param req - The request object.
|
||||
* @param res - The response object.
|
||||
* @param isComplete - Boolean from {@link JsonRpcEngine._runAllMiddleware}
|
||||
* indicating whether a middleware ended the request.
|
||||
*/
|
||||
private static _checkForCompletion(
|
||||
req: JsonRpcRequest<unknown>,
|
||||
@@ -465,6 +496,7 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
{ request: req },
|
||||
);
|
||||
}
|
||||
|
||||
if (!isComplete) {
|
||||
throw new EthereumRpcError(
|
||||
errorCodes.rpc.internal,
|
||||
@@ -475,6 +507,12 @@ export class JsonRpcEngine extends SafeEventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON-stringifies a request object.
|
||||
*
|
||||
* @param request - The request object to JSON-stringify.
|
||||
* @returns The JSON-stringified request object.
|
||||
*/
|
||||
function jsonify(request: JsonRpcRequest<unknown>): string {
|
||||
return JSON.stringify(request, null, 2);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ type ReturnHandlerCallback = (error: null | Error) => void;
|
||||
*
|
||||
* The return handler will always be called. Its resolution of the promise
|
||||
* enables the control flow described above.
|
||||
*
|
||||
* @param asyncMiddleware - The asynchronous middleware function to wrap.
|
||||
* @returns The wrapped asynchronous middleware function, ready to be consumed
|
||||
* by JsonRpcEngine.
|
||||
*/
|
||||
export function createAsyncMiddleware<T, U>(
|
||||
asyncMiddleware: AsyncJsonrpcMiddleware<T, U>,
|
||||
|
||||
@@ -2,6 +2,15 @@ import { Json, JsonRpcMiddleware, JsonRpcSuccess } from './JsonRpcEngine';
|
||||
|
||||
type ScaffoldMiddlewareHandler<T, U> = JsonRpcMiddleware<T, U> | Json;
|
||||
|
||||
/**
|
||||
* Creates a middleware function from an object of RPC method handler functions,
|
||||
* keyed to particular method names. If a method corresponding to a key of this
|
||||
* object is requested, this middleware will pass it to the corresponding
|
||||
* handler and return the result.
|
||||
*
|
||||
* @param handlers - The RPC method handler functions.
|
||||
* @returns The scaffold middleware function.
|
||||
*/
|
||||
export function createScaffoldMiddleware(handlers: {
|
||||
[methodName: string]: ScaffoldMiddlewareHandler<unknown, unknown>;
|
||||
}): JsonRpcMiddleware<unknown, unknown> {
|
||||
@@ -11,6 +20,7 @@ export function createScaffoldMiddleware(handlers: {
|
||||
if (handler === undefined) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// if handler is fn, call as middleware
|
||||
if (typeof handler === 'function') {
|
||||
return handler(req, res, next, end);
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
// uint32 (two's complement) max
|
||||
// more conservative than Number.MAX_SAFE_INTEGER
|
||||
const MAX = 4294967295;
|
||||
const MAX = 4_294_967_295;
|
||||
let idCounter = Math.floor(Math.random() * MAX);
|
||||
|
||||
/**
|
||||
* Gets an ID that is guaranteed to be unique so long as no more than
|
||||
* 4_294_967_295 (uint32 max) IDs are created, or the IDs are rapidly turned
|
||||
* over.
|
||||
*
|
||||
* @returns The unique ID.
|
||||
*/
|
||||
export function getUniqueId(): number {
|
||||
idCounter = (idCounter + 1) % MAX;
|
||||
return idCounter;
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { getUniqueId } from './getUniqueId';
|
||||
import { JsonRpcMiddleware } from './JsonRpcEngine';
|
||||
|
||||
/**
|
||||
* Returns a middleware function that overwrites the `id` property of each
|
||||
* request with an ID that is guaranteed to be unique, and restores the original
|
||||
* ID in a return handler.
|
||||
*
|
||||
* If used, should be the first middleware in the stack.
|
||||
*
|
||||
* @returns The ID remap middleware function.
|
||||
*/
|
||||
export function createIdRemapMiddleware(): JsonRpcMiddleware<unknown, unknown> {
|
||||
return (req, res, next, _end) => {
|
||||
const originalId = req.id;
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { JsonRpcEngine, JsonRpcMiddleware } from './JsonRpcEngine';
|
||||
|
||||
/**
|
||||
* Takes a stack of middleware and joins them into a single middleware function.
|
||||
*
|
||||
* @param middlewareStack - The middleware stack to merge.
|
||||
* @returns The merged middleware function.
|
||||
*/
|
||||
export function mergeMiddleware(
|
||||
middlewareStack: JsonRpcMiddleware<unknown, unknown>[],
|
||||
) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import type {
|
||||
} from './JsonRpcEngine';
|
||||
|
||||
/**
|
||||
* **ATTN:** Assumes that only one of the `result` and `error` properties is
|
||||
* ATTN: Assumes that only one of the `result` and `error` properties is
|
||||
* present on the `response`, as guaranteed by e.g. `JsonRpcEngine.handle`.
|
||||
*
|
||||
* Type guard to narrow a JsonRpcResponse object to a success (or failure).
|
||||
@@ -22,7 +22,7 @@ export function isJsonRpcSuccess<T>(
|
||||
}
|
||||
|
||||
/**
|
||||
* **ATTN:** Assumes that only one of the `result` and `error` properties is
|
||||
* ATTN: Assumes that only one of the `result` and `error` properties is
|
||||
* present on the `response`, as guaranteed by e.g. `JsonRpcEngine.handle`.
|
||||
*
|
||||
* Type guard to narrow a JsonRpcResponse object to a failure (or success).
|
||||
@@ -79,6 +79,8 @@ export function getJsonRpcIdValidator(options?: JsonRpcValidatorOptions) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Type guard for {@link JsonRpcId}.
|
||||
*
|
||||
* @param id - The JSON-RPC ID value to check.
|
||||
* @returns Whether the given ID is valid per the options given to the
|
||||
* factory.
|
||||
|
||||
@@ -40,6 +40,7 @@ describe('createScaffoldMiddleware', function () {
|
||||
'method3',
|
||||
'should have expected error',
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
response4.result,
|
||||
'passthrough',
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('idRemapMiddleware', function () {
|
||||
});
|
||||
|
||||
const payload = { id: 1, jsonrpc: '2.0', method: 'hello' };
|
||||
const payloadCopy = Object.assign({}, payload);
|
||||
const payloadCopy = { ...payload };
|
||||
|
||||
engine.handle(payload, function (err, res) {
|
||||
assert.ifError(err, 'did not error');
|
||||
@@ -47,6 +47,7 @@ describe('idRemapMiddleware', function () {
|
||||
observedIds.after.req,
|
||||
'ids are different',
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
observedIds.before.req,
|
||||
res.id,
|
||||
|
||||
@@ -148,6 +148,7 @@ describe('mergeMiddleware', function () {
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
engine.push((_req, res, _next, end) => {
|
||||
res.result = true;
|
||||
end();
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
"strict": true,
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": ["./src/*.ts"]
|
||||
"exclude": ["./test"],
|
||||
"include": ["./src/**/*.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user