Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackGlory committed Dec 1, 2018
1 parent 0853c46 commit 1a751db
Show file tree
Hide file tree
Showing 16 changed files with 4,411 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ typings/

# next.js build output
.next

# Build
lib
dist
61 changes: 61 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
language: node_js
node_js:
- "9"
after_success:
- 'cat ./coverage/lcov.info | ./node_modules/.bin/coveralls'
17 changes: 17 additions & 0 deletions jest.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"transform": {
"^.+\\.tsx?$": "ts-jest"
}
, "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$"
, "coveragePathIgnorePatterns": [
"<rootDir>/test/"
]
, "moduleFileExtensions": [
"ts"
, "tsx"
, "js"
, "jsx"
, "json"
, "node"
]
}
30 changes: 30 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "json-rpc-proxy",
"version": "0.1.0",
"description": "Quickly create JSON-RPC using Proxy",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"repository": "git@github.com:BlackGlory/json-rpc-proxy.git",
"author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
"license": "MIT",
"scripts": {
"precommit": "yarn lint && yarn test",
"prepublishOnly": "yarn precommit && yarn build",
"test": "node ./node_modules/jest/bin/jest.js --coverage --config jest.config.json",
"build": "rm -r lib && tsc --outDir lib",
"lint": "tslint -t codeFrame 'src/**/*.ts' 'test/**/*.ts'"
},
"devDependencies": {
"@types/jest": "^23.3.10",
"coveralls": "^3.0.2",
"husky": "^1.2.0",
"immer": "^1.8.0",
"jest": "^23.6.0",
"ts-jest": "^23.10.5",
"tslint": "^5.11.0",
"typescript": "^3.2.1"
},
"dependencies": {
"json-rpc-creator": "^1.0.0"
}
}
11 changes: 11 additions & 0 deletions src/create-call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { JsonRpc2Notification, JsonRpc2Request } from 'json-rpc-creator'

export function createCall(target: any) {
return (notificationOrRequest: JsonRpc2Notification | JsonRpc2Request) => {
if ('params' in notificationOrRequest) {
return Reflect.apply(target[notificationOrRequest.method], target, Array.isArray(notificationOrRequest.params) ? notificationOrRequest.params : [notificationOrRequest.params])
} else {
return Reflect.apply(target[notificationOrRequest.method], target, [])
}
}
}
44 changes: 44 additions & 0 deletions src/create-request-proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
JsonRpc2Id
, JsonRpc2Params
, request
, notification
} from 'json-rpc-creator'

function bakeProxy<T>(methodInjector: (method: string) => T) {
return new Proxy(Object.create(null), {
get(_, method) {
if (typeof method === 'string') {
return methodInjector(method)
} else {
throw new TypeError('method should be string')
}
}
})
}

export function createRequestProxy(): any
export function createRequestProxy(idCreator: () => JsonRpc2Id): any
export function createRequestProxy(idIterator: Iterator<JsonRpc2Id>): any
export function createRequestProxy(idCreatorOrIdIterator?: (() => JsonRpc2Id) | Iterator<JsonRpc2Id>) {
if (idCreatorOrIdIterator === undefined) {
return bakeProxy((method: string) => (...params: JsonRpc2Params[]) => notification(method, params))
} else {
if (typeof idCreatorOrIdIterator === 'function') {
return bakeProxy((method: string) => (...params: JsonRpc2Params[]) => {
const idCreator = idCreatorOrIdIterator as () => JsonRpc2Id
return request(idCreator(), method, params)
})
} else {
return bakeProxy((method: string) => (...params: JsonRpc2Params[]) => {
const idIterator = idCreatorOrIdIterator as Iterator<JsonRpc2Id>
const { done, value } = idIterator.next()
if (done) {
throw new Error('iterator is exhausted.')
} else {
return request(value, method, params)
}
})
}
}
}
30 changes: 30 additions & 0 deletions src/create-response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
JsonRpc2Request
, JsonTypes
, JsonRpc2Response
, JsonRpc2SuccessResponse
, JsonRpc2Error
, success
, error
} from 'json-rpc-creator'

export function createResponse(request: JsonRpc2Request, result: JsonTypes): JsonRpc2SuccessResponse
export function createResponse(request: JsonRpc2Request, handler: (request: JsonRpc2Request) => JsonTypes): JsonRpc2SuccessResponse
export function createResponse(request: JsonRpc2Request, handler: (request: JsonRpc2Request) => JsonTypes, errorHandler: (error: any) => JsonRpc2Error): JsonRpc2Response
export function createResponse(request: JsonRpc2Request, resultOrHandler: JsonTypes | ((request: JsonRpc2Request) => JsonTypes), errorHandler?: (error: any) => JsonRpc2Error) {
if (typeof resultOrHandler === 'function') {
const handler = resultOrHandler as (request: JsonRpc2Request) => JsonTypes
if (typeof errorHandler === 'function') {
try {
return success(request.id, handler(request))
} catch (e) {
return error(request.id, errorHandler(e))
}
} else {
return success(request.id, handler(request))
}
} else {
const result = resultOrHandler as JsonTypes
return success(request.id, result)
}
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './create-request-proxy'
export * from './create-call'
export * from './create-response'
34 changes: 34 additions & 0 deletions test/create-call.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createCall } from '../src/create-call'

test('createCall(target)', () => {
const target = {
hello(who: string) {
return who
}
, bye() {
return 'bye'
}
, exit(code: number) {
return code
}
}

const call = createCall(target)

expect(call({
jsonrpc: '2.0'
, method: 'hello'
, params: 'world'
})).toEqual('world')

expect(call({
jsonrpc: '2.0'
, method: 'bye'
})).toEqual('bye')

expect(call({
jsonrpc: '2.0'
, method: 'exit'
, params: [0]
})).toEqual(0)
})
117 changes: 117 additions & 0 deletions test/create-request-proxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { createRequestProxy } from '../src/create-request-proxy'

describe('createRequestProxy', () => {
test('createRequestProxy()', () => {
const proxy = createRequestProxy()

expect(() => proxy[Symbol()]()).toThrow()

expect(proxy.hello()).toStrictEqual({
jsonrpc: '2.0'
, method: 'hello'
, params: []
})

expect(proxy.hello('world')).toStrictEqual({
jsonrpc: '2.0'
, method: 'hello'
, params: ['world']
})
})

test('createRequestProxy(idCreator)', () => {
const autoIncreaseCreator = (i = 0) => () => i++
const proxy = createRequestProxy(autoIncreaseCreator())

expect(() => proxy[Symbol()]()).toThrow()

expect(proxy.hello()).toStrictEqual({
jsonrpc: '2.0'
, id: 0
, method: 'hello'
, params: []
})

expect(proxy.hello('world')).toStrictEqual({
jsonrpc: '2.0'
, id: 1
, method: 'hello'
, params: ['world']
})

expect(proxy.good('bye')).toStrictEqual({
jsonrpc: '2.0'
, id: 2
, method: 'good'
, params: ['bye']
})
})

test('createRequestProxy(idIterator)', () => {
function* autoIncreaseGenerator() {
let i = 0
while (true) {
yield i++
}
}
const proxy = createRequestProxy(autoIncreaseGenerator())

expect(() => proxy[Symbol()]()).toThrow()

expect(proxy.hello()).toStrictEqual({
jsonrpc: '2.0'
, id: 0
, method: 'hello'
, params: []
})

expect(proxy.hello('world')).toStrictEqual({
jsonrpc: '2.0'
, id: 1
, method: 'hello'
, params: ['world']
})

expect(proxy.good('bye')).toStrictEqual({
jsonrpc: '2.0'
, id: 2
, method: 'good'
, params: ['bye']
})
})

test('createRequestProxy(oneShotNullIterator)', () => {
function* oneShotNullGenerator() {
yield null
}
const proxy = createRequestProxy(oneShotNullGenerator())

expect(proxy.hello()).toStrictEqual({
jsonrpc: '2.0'
, id: null
, method: 'hello'
, params: []
})

expect(() => proxy.hello('world')).toThrow()
})

test('createRequestProxy(nullCreator)', () => {
const nullCreator = () => null
const proxy = createRequestProxy(nullCreator)

expect(proxy.hello()).toStrictEqual({
jsonrpc: '2.0'
, id: null
, method: 'hello'
, params: []
})

expect(proxy.hello('world')).toStrictEqual({
jsonrpc: '2.0'
, id: null
, method: 'hello'
, params: ['world']
})
})
})

0 comments on commit 1a751db

Please sign in to comment.