@matrixai/rpc
Advanced tools
Comparing version 0.1.13 to 0.2.0
import type { Class } from '@matrixai/errors'; | ||
import type { JSONValue } from '@/types'; | ||
import type { JSONRPCError, JSONValue } from '@/types'; | ||
import { AbstractError } from '@matrixai/errors'; | ||
@@ -13,28 +13,20 @@ declare class ErrorRPC<T> extends AbstractError<T> { | ||
} | ||
declare const enum JSONRPCErrorCode { | ||
ParseError = -32700, | ||
InvalidRequest = -32600, | ||
MethodNotFound = -32601, | ||
InvalidParams = -32602, | ||
InternalError = -32603, | ||
HandlerNotFound = -32000, | ||
RPCStopping = -32001, | ||
RPCMessageLength = -32003, | ||
RPCMissingResponse = -32004, | ||
RPCOutputStreamError = -32005, | ||
RPCRemote = -32006, | ||
RPCStreamEnded = -32007, | ||
RPCTimedOut = -32008, | ||
RPCConnectionLocal = -32010, | ||
RPCConnectionPeer = -32011, | ||
RPCConnectionKeepAliveTimeOut = -32012, | ||
RPCConnectionInternal = -32013, | ||
MissingHeader = -32014, | ||
HandlerAborted = -32015, | ||
MissingCaller = -32016 | ||
/** | ||
* This is an internal error, it should not reach the top level. | ||
*/ | ||
declare class ErrorRPCHandlerFailed<T> extends ErrorRPC<T> { | ||
static description: string; | ||
} | ||
declare class ErrorRPCCallerFailed<T> extends ErrorRPC<T> { | ||
static description: string; | ||
} | ||
declare abstract class ErrorRPCProtocol<T> extends ErrorRPC<T> { | ||
static error: string; | ||
code: number; | ||
type: string; | ||
static fromJSON<T extends Class<any>>(json: any): InstanceType<T>; | ||
/** | ||
* The return type WILL NOT include cause, this will be handled by `fromError` | ||
* @returns | ||
*/ | ||
toJSON(): JSONRPCError; | ||
} | ||
@@ -45,17 +37,10 @@ declare class ErrorRPCParse<T> extends ErrorRPCProtocol<T> { | ||
} | ||
declare class ErrorRPCStopping<T> extends ErrorRPCProtocol<T> { | ||
declare class ErrorRPCInvalidParams<T> extends ErrorRPCProtocol<T> { | ||
static description: string; | ||
code: JSONRPCErrorCode; | ||
} | ||
/** | ||
* This is an internal error, it should not reach the top level. | ||
*/ | ||
declare class ErrorRPCHandlerFailed<T> extends ErrorRPCProtocol<T> { | ||
declare class ErrorRPCStopping<T> extends ErrorRPCProtocol<T> { | ||
static description: string; | ||
code: JSONRPCErrorCode; | ||
} | ||
declare class ErrorRPCCallerFailed<T> extends ErrorRPCProtocol<T> { | ||
static description: string; | ||
code: JSONRPCErrorCode; | ||
} | ||
declare class ErrorMissingCaller<T> extends ErrorRPCProtocol<T> { | ||
@@ -88,10 +73,4 @@ static description: string; | ||
static message: string; | ||
metadata: JSONValue | undefined; | ||
constructor({ metadata, message, options, }?: { | ||
metadata?: JSONValue; | ||
message?: string; | ||
options?: any; | ||
}); | ||
static fromJSON<T extends Class<any>>(this: T, json: any): InstanceType<T>; | ||
toJSON(): any; | ||
metadata: JSONValue; | ||
code: JSONRPCErrorCode; | ||
} | ||
@@ -130,2 +109,47 @@ declare class ErrorRPCStreamEnded<T> extends ErrorRPCProtocol<T> { | ||
} | ||
export { ErrorRPC, ErrorRPCServer, ErrorRPCServerNotRunning, ErrorRPCProtocol, ErrorRPCStopping, ErrorRPCParse, ErrorRPCHandlerFailed, ErrorRPCMessageLength, ErrorRPCMissingResponse, ErrorRPCOutputStreamError, ErrorRPCRemote, ErrorRPCStreamEnded, ErrorRPCTimedOut, ErrorUtilsUndefinedBehaviour, ErrorRPCMethodNotImplemented, ErrorRPCConnectionLocal, ErrorRPCConnectionPeer, ErrorRPCConnectionKeepAliveTimeOut, ErrorRPCConnectionInternal, ErrorMissingHeader, ErrorHandlerAborted, ErrorRPCCallerFailed, ErrorMissingCaller, JSONRPCErrorCode, }; | ||
declare class ErrorRPCUnknown<T> extends ErrorRPCProtocol<T> { | ||
static description: string; | ||
code: number; | ||
} | ||
declare const enum JSONRPCErrorCode { | ||
ParseError = -32700, | ||
InvalidRequest = -32600, | ||
MethodNotFound = -32601, | ||
InvalidParams = -32602, | ||
InternalError = -32603, | ||
HandlerNotFound = -32000, | ||
RPCStopping = -32001, | ||
RPCMessageLength = -32003, | ||
RPCMissingResponse = -32004, | ||
RPCOutputStreamError = -32005, | ||
RPCRemote = -32006, | ||
RPCStreamEnded = -32007, | ||
RPCTimedOut = -32008, | ||
RPCConnectionLocal = -32010, | ||
RPCConnectionPeer = -32011, | ||
RPCConnectionKeepAliveTimeOut = -32012, | ||
RPCConnectionInternal = -32013, | ||
MissingHeader = -32014, | ||
HandlerAborted = -32015, | ||
MissingCaller = -32016 | ||
} | ||
declare const rpcProtocolErrors: { | ||
[-32006]: typeof ErrorRPCRemote; | ||
[-32001]: typeof ErrorRPCStopping; | ||
[-32003]: typeof ErrorRPCMessageLength; | ||
[-32700]: typeof ErrorRPCParse; | ||
[-32602]: typeof ErrorRPCInvalidParams; | ||
[-32000]: typeof ErrorRPCHandlerFailed; | ||
[-32004]: typeof ErrorRPCMissingResponse; | ||
[-32005]: typeof ErrorRPCOutputStreamError; | ||
[-32008]: typeof ErrorRPCTimedOut; | ||
[-32007]: typeof ErrorRPCStreamEnded; | ||
[-32010]: typeof ErrorRPCConnectionLocal; | ||
[-32011]: typeof ErrorRPCConnectionPeer; | ||
[-32012]: typeof ErrorRPCConnectionKeepAliveTimeOut; | ||
[-32013]: typeof ErrorRPCConnectionInternal; | ||
[-32014]: typeof ErrorMissingHeader; | ||
[-32015]: typeof ErrorRPCHandlerFailed; | ||
[-32016]: typeof ErrorMissingCaller; | ||
}; | ||
export { ErrorRPC, ErrorRPCServer, ErrorRPCServerNotRunning, ErrorRPCProtocol, ErrorRPCStopping, ErrorRPCParse, ErrorRPCInvalidParams, ErrorRPCHandlerFailed, ErrorRPCMessageLength, ErrorRPCMissingResponse, ErrorRPCOutputStreamError, ErrorRPCRemote, ErrorRPCStreamEnded, ErrorRPCTimedOut, ErrorUtilsUndefinedBehaviour, ErrorRPCMethodNotImplemented, ErrorRPCConnectionLocal, ErrorRPCConnectionPeer, ErrorRPCConnectionKeepAliveTimeOut, ErrorRPCConnectionInternal, ErrorMissingHeader, ErrorHandlerAborted, ErrorRPCCallerFailed, ErrorMissingCaller, ErrorRPCUnknown, JSONRPCErrorCode, rpcProtocolErrors, }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ErrorMissingCaller = exports.ErrorRPCCallerFailed = exports.ErrorHandlerAborted = exports.ErrorMissingHeader = exports.ErrorRPCConnectionInternal = exports.ErrorRPCConnectionKeepAliveTimeOut = exports.ErrorRPCConnectionPeer = exports.ErrorRPCConnectionLocal = exports.ErrorRPCMethodNotImplemented = exports.ErrorUtilsUndefinedBehaviour = exports.ErrorRPCTimedOut = exports.ErrorRPCStreamEnded = exports.ErrorRPCRemote = exports.ErrorRPCOutputStreamError = exports.ErrorRPCMissingResponse = exports.ErrorRPCMessageLength = exports.ErrorRPCHandlerFailed = exports.ErrorRPCParse = exports.ErrorRPCStopping = exports.ErrorRPCProtocol = exports.ErrorRPCServerNotRunning = exports.ErrorRPCServer = exports.ErrorRPC = void 0; | ||
exports.rpcProtocolErrors = exports.ErrorRPCUnknown = exports.ErrorMissingCaller = exports.ErrorRPCCallerFailed = exports.ErrorHandlerAborted = exports.ErrorMissingHeader = exports.ErrorRPCConnectionInternal = exports.ErrorRPCConnectionKeepAliveTimeOut = exports.ErrorRPCConnectionPeer = exports.ErrorRPCConnectionLocal = exports.ErrorRPCMethodNotImplemented = exports.ErrorUtilsUndefinedBehaviour = exports.ErrorRPCTimedOut = exports.ErrorRPCStreamEnded = exports.ErrorRPCRemote = exports.ErrorRPCOutputStreamError = exports.ErrorRPCMissingResponse = exports.ErrorRPCMessageLength = exports.ErrorRPCHandlerFailed = exports.ErrorRPCInvalidParams = exports.ErrorRPCParse = exports.ErrorRPCStopping = exports.ErrorRPCProtocol = exports.ErrorRPCServerNotRunning = exports.ErrorRPCServer = exports.ErrorRPC = void 0; | ||
const errors_1 = require("@matrixai/errors"); | ||
@@ -18,6 +18,48 @@ class ErrorRPC extends errors_1.AbstractError { | ||
exports.ErrorRPCServerNotRunning = ErrorRPCServerNotRunning; | ||
/** | ||
* This is an internal error, it should not reach the top level. | ||
*/ | ||
class ErrorRPCHandlerFailed extends ErrorRPC { | ||
static description = 'Failed to handle stream'; | ||
} | ||
exports.ErrorRPCHandlerFailed = ErrorRPCHandlerFailed; | ||
class ErrorRPCCallerFailed extends ErrorRPC { | ||
static description = 'Failed to call stream'; | ||
} | ||
exports.ErrorRPCCallerFailed = ErrorRPCCallerFailed; | ||
class ErrorRPCProtocol extends ErrorRPC { | ||
static error = 'RPC Protocol Error'; | ||
code; | ||
type; | ||
static fromJSON(json) { | ||
if (typeof json !== 'object' || | ||
typeof json.code !== 'number' || | ||
typeof json.message !== 'string' || | ||
typeof json.data !== 'object') { | ||
return new ErrorRPCUnknown(`Cannot decode JSON to ${this.name}`); | ||
} | ||
const errorC = rpcProtocolErrors[json.code]; | ||
if (errorC == null) { | ||
return new ErrorRPCUnknown(`Unknown error.code found on RPC message`); | ||
} | ||
const e = new errorC(json.message); | ||
e.stack = json.data.stack; | ||
e.data = json.data.data; | ||
e.timestamp = new Date(json.data.timestamp); | ||
return e; | ||
} | ||
/** | ||
* The return type WILL NOT include cause, this will be handled by `fromError` | ||
* @returns | ||
*/ | ||
toJSON() { | ||
return { | ||
code: this.code, | ||
message: this.message, | ||
data: { | ||
timestamp: this.timestamp.toJSON(), | ||
data: this.data, | ||
stack: this.stack, | ||
}, | ||
}; | ||
} | ||
} | ||
@@ -30,2 +72,7 @@ exports.ErrorRPCProtocol = ErrorRPCProtocol; | ||
exports.ErrorRPCParse = ErrorRPCParse; | ||
class ErrorRPCInvalidParams extends ErrorRPCProtocol { | ||
static description = 'Invalid paramaters provided to RPC'; | ||
code = -32602 /* JSONRPCErrorCode.InvalidParams */; | ||
} | ||
exports.ErrorRPCInvalidParams = ErrorRPCInvalidParams; | ||
class ErrorRPCStopping extends ErrorRPCProtocol { | ||
@@ -36,15 +83,2 @@ static description = 'RPC is stopping'; | ||
exports.ErrorRPCStopping = ErrorRPCStopping; | ||
/** | ||
* This is an internal error, it should not reach the top level. | ||
*/ | ||
class ErrorRPCHandlerFailed extends ErrorRPCProtocol { | ||
static description = 'Failed to handle stream'; | ||
code = -32000 /* JSONRPCErrorCode.HandlerNotFound */; | ||
} | ||
exports.ErrorRPCHandlerFailed = ErrorRPCHandlerFailed; | ||
class ErrorRPCCallerFailed extends ErrorRPCProtocol { | ||
static description = 'Failed to call stream'; | ||
code = -32016 /* JSONRPCErrorCode.MissingCaller */; | ||
} | ||
exports.ErrorRPCCallerFailed = ErrorRPCCallerFailed; | ||
class ErrorMissingCaller extends ErrorRPCProtocol { | ||
@@ -83,40 +117,4 @@ static description = 'Caller is missing'; | ||
static message = 'The server responded with an error'; | ||
metadata; | ||
constructor({ metadata, message, options, } = {}) { | ||
super(message, options); | ||
this.metadata = metadata; | ||
this.code = -32006 /* JSONRPCErrorCode.RPCRemote */; | ||
this.data = options?.data; | ||
this.type = this.constructor.name; | ||
this.message = message || ErrorRPCRemote.message; | ||
} | ||
static fromJSON(json) { | ||
if (typeof json !== 'object' || | ||
json.type !== this.name || | ||
typeof json.data !== 'object' || | ||
typeof json.data.message !== 'string' || | ||
isNaN(Date.parse(json.data.timestamp)) || | ||
typeof json.data.metadata !== 'object' || | ||
typeof json.data.data !== 'object' || | ||
('stack' in json.data && typeof json.data.stack !== 'string')) { | ||
throw new TypeError(`Cannot decode JSON to ${this.name}`); | ||
} | ||
// Here, you can define your own metadata object, or just use the one from JSON directly. | ||
const parsedMetadata = json.data.metadata; | ||
const e = new this(parsedMetadata, json.data.message, { | ||
timestamp: new Date(json.data.timestamp), | ||
data: json.data.data, | ||
cause: json.data.cause, | ||
}); | ||
e.stack = json.data.stack; | ||
return e; | ||
} | ||
toJSON() { | ||
return { | ||
type: this.name, | ||
data: { | ||
description: this.description, | ||
}, | ||
}; | ||
} | ||
metadata = {}; | ||
code = -32006 /* JSONRPCErrorCode.RPCRemote */; | ||
} | ||
@@ -164,2 +162,27 @@ exports.ErrorRPCRemote = ErrorRPCRemote; | ||
exports.ErrorRPCConnectionInternal = ErrorRPCConnectionInternal; | ||
class ErrorRPCUnknown extends ErrorRPCProtocol { | ||
static description = 'RPC Unknown Error'; | ||
code = 0; | ||
} | ||
exports.ErrorRPCUnknown = ErrorRPCUnknown; | ||
const rpcProtocolErrors = { | ||
[-32006 /* JSONRPCErrorCode.RPCRemote */]: ErrorRPCRemote, | ||
[-32001 /* JSONRPCErrorCode.RPCStopping */]: ErrorRPCStopping, | ||
[-32003 /* JSONRPCErrorCode.RPCMessageLength */]: ErrorRPCMessageLength, | ||
[-32700 /* JSONRPCErrorCode.ParseError */]: ErrorRPCParse, | ||
[-32602 /* JSONRPCErrorCode.InvalidParams */]: ErrorRPCInvalidParams, | ||
[-32000 /* JSONRPCErrorCode.HandlerNotFound */]: ErrorRPCHandlerFailed, | ||
[-32004 /* JSONRPCErrorCode.RPCMissingResponse */]: ErrorRPCMissingResponse, | ||
[-32005 /* JSONRPCErrorCode.RPCOutputStreamError */]: ErrorRPCOutputStreamError, | ||
[-32008 /* JSONRPCErrorCode.RPCTimedOut */]: ErrorRPCTimedOut, | ||
[-32007 /* JSONRPCErrorCode.RPCStreamEnded */]: ErrorRPCStreamEnded, | ||
[-32010 /* JSONRPCErrorCode.RPCConnectionLocal */]: ErrorRPCConnectionLocal, | ||
[-32011 /* JSONRPCErrorCode.RPCConnectionPeer */]: ErrorRPCConnectionPeer, | ||
[-32012 /* JSONRPCErrorCode.RPCConnectionKeepAliveTimeOut */]: ErrorRPCConnectionKeepAliveTimeOut, | ||
[-32013 /* JSONRPCErrorCode.RPCConnectionInternal */]: ErrorRPCConnectionInternal, | ||
[-32014 /* JSONRPCErrorCode.MissingHeader */]: ErrorMissingHeader, | ||
[-32015 /* JSONRPCErrorCode.HandlerAborted */]: ErrorRPCHandlerFailed, | ||
[-32016 /* JSONRPCErrorCode.MissingCaller */]: ErrorMissingCaller, | ||
}; | ||
exports.rpcProtocolErrors = rpcProtocolErrors; | ||
//# sourceMappingURL=errors.js.map |
@@ -9,3 +9,5 @@ "use strict"; | ||
class ClientHandler extends Handler_1.default { | ||
async handle(input, cancel, meta, ctx) { | ||
async handle( | ||
/* eslint-disable */ | ||
input, cancel, meta, ctx) { | ||
throw new errors_1.ErrorRPCMethodNotImplemented(); | ||
@@ -12,0 +14,0 @@ } |
@@ -14,3 +14,5 @@ "use strict"; | ||
*/ | ||
async *handle(input, cancel, meta, ctx) { | ||
async *handle( | ||
/* eslint-disable */ | ||
input, cancel, meta, ctx) { | ||
throw new errors_1.ErrorRPCMethodNotImplemented('This method must be overwrtitten.'); | ||
@@ -17,0 +19,0 @@ } |
@@ -9,3 +9,5 @@ "use strict"; | ||
class RawHandler extends Handler_1.default { | ||
async handle(input, cancel, meta, ctx) { | ||
async handle( | ||
/* eslint-disable */ | ||
input, cancel, meta, ctx) { | ||
throw new errors_1.ErrorRPCMethodNotImplemented('This method must be overridden'); | ||
@@ -12,0 +14,0 @@ } |
@@ -9,3 +9,5 @@ "use strict"; | ||
class ServerHandler extends Handler_1.default { | ||
async *handle(input, cancel, meta, ctx) { | ||
async *handle( | ||
/* eslint-disable */ | ||
input, cancel, meta, ctx) { | ||
throw new errors_1.ErrorRPCMethodNotImplemented('This method must be overridden'); | ||
@@ -12,0 +14,0 @@ } |
@@ -9,3 +9,5 @@ "use strict"; | ||
class UnaryHandler extends Handler_1.default { | ||
async handle(input, cancel, meta, ctx) { | ||
async handle( | ||
/* eslint-disable */ | ||
input, cancel, meta, ctx) { | ||
throw new errors_1.ErrorRPCMethodNotImplemented('This method must be overridden'); | ||
@@ -12,0 +14,0 @@ } |
/// <reference types="node" /> | ||
import type { WritableStream, ReadableStream } from 'stream/web'; | ||
import type { ContextTimedInput } from '@matrixai/contexts'; | ||
import type { IdGen, HandlerType, JSONValue, JSONRPCRequest, JSONRPCResponse, MiddlewareFactory, MapCallers, StreamFactory, ClientManifest, RPCStream } from './types'; | ||
import type { ErrorRPC } from './errors'; | ||
import type { IdGen, HandlerType, JSONValue, JSONRPCRequest, JSONRPCResponse, MiddlewareFactory, MapCallers, StreamFactory, ClientManifest, RPCStream, ToError } from './types'; | ||
import Logger from '@matrixai/logger'; | ||
import * as utils from './utils'; | ||
declare class RPCClient<M extends ClientManifest> { | ||
@@ -13,3 +11,3 @@ protected onTimeoutCallback?: () => void; | ||
protected streamFactory: StreamFactory; | ||
protected toError?: typeof utils.toError; | ||
protected toError: ToError; | ||
protected middlewareFactory: MiddlewareFactory<Uint8Array, JSONRPCRequest, JSONRPCResponse, Uint8Array>; | ||
@@ -42,3 +40,3 @@ protected callerTypes: Record<string, HandlerType>; | ||
idGen?: IdGen; | ||
toError?: (errorData: JSONValue, metadata: Record<string, JSONValue>) => ErrorRPC<any>; | ||
toError?: ToError; | ||
}); | ||
@@ -45,0 +43,0 @@ get methods(): MapCallers<M>; |
@@ -83,3 +83,3 @@ "use strict"; | ||
*/ | ||
constructor({ manifest, streamFactory, middlewareFactory = middleware.defaultClientMiddlewareWrapper(), streamKeepAliveTimeoutTime = Infinity, logger, toError, idGen = () => Promise.resolve(null), }) { | ||
constructor({ manifest, streamFactory, middlewareFactory = middleware.defaultClientMiddlewareWrapper(), streamKeepAliveTimeoutTime = Infinity, logger, toError = utils.toError, idGen = () => Promise.resolve(null), }) { | ||
this.idGen = idGen; | ||
@@ -260,3 +260,3 @@ this.callerTypes = utils.getHandlerTypes(manifest); | ||
}; | ||
const outputMessageTransformStream = utils.clientOutputTransformStream(metadata, refreshingTimer); | ||
const outputMessageTransformStream = utils.clientOutputTransformStream(metadata, this.toError, refreshingTimer); | ||
const inputMessageTransformStream = utils.clientInputTransformStream(method, refreshingTimer); | ||
@@ -391,3 +391,11 @@ const middleware = this.middlewareFactory({ signal, timer }, rpcStream.cancel, metadata); | ||
}; | ||
throw utils.toError(messageValue.error, metadata); | ||
const e = errors.ErrorRPCProtocol.fromJSON(messageValue.error); | ||
if (e instanceof errors.ErrorRPCRemote && | ||
messageValue.error.data != null && | ||
typeof messageValue.error.data === 'object' && | ||
'cause' in messageValue.error.data) { | ||
e.metadata = metadata; | ||
e.cause = this.toError(JSON.parse(messageValue.error.data.cause)); | ||
} | ||
throw e; | ||
} | ||
@@ -394,0 +402,0 @@ leadingMessage = messageValue; |
@@ -1,6 +0,5 @@ | ||
import type { IdGen, ClientHandlerImplementation, DuplexHandlerImplementation, JSONValue, JSONRPCRequest, JSONRPCResponseResult, ServerManifest, RawHandlerImplementation, ServerHandlerImplementation, UnaryHandlerImplementation, RPCStream, MiddlewareFactory } from './types'; | ||
import type { IdGen, ClientHandlerImplementation, DuplexHandlerImplementation, JSONValue, JSONRPCRequest, JSONRPCResponseResult, ServerManifest, RawHandlerImplementation, ServerHandlerImplementation, UnaryHandlerImplementation, RPCStream, MiddlewareFactory, FromError } from './types'; | ||
import Logger from '@matrixai/logger'; | ||
import { PromiseCancellable } from '@matrixai/async-cancellable'; | ||
import { startStop } from '@matrixai/async-init'; | ||
import * as errors from './errors'; | ||
/** | ||
@@ -23,4 +22,4 @@ * You must provide a error handler `addEventListener('error')`. | ||
protected activeStreams: Set<PromiseCancellable<void>>; | ||
protected fromError: (error: errors.ErrorRPC<any>) => JSONValue; | ||
protected filterSensitive: (key: string, value: any) => any; | ||
protected fromError: FromError; | ||
protected replacer?: (key: string, value: any) => any; | ||
protected middlewareFactory: MiddlewareFactory<JSONRPCRequest, Uint8Array, Uint8Array, JSONRPCResponseResult>; | ||
@@ -44,3 +43,3 @@ registerOnTimeoutCallback(callback: () => void): void; | ||
*/ | ||
constructor({ middlewareFactory, handlerTimeoutTime, logger, idGen, fromError, filterSensitive, }: { | ||
constructor({ middlewareFactory, handlerTimeoutTime, logger, idGen, fromError, replacer, }: { | ||
middlewareFactory?: MiddlewareFactory<JSONRPCRequest, Uint8Array, Uint8Array, JSONRPCResponseResult>; | ||
@@ -50,4 +49,4 @@ handlerTimeoutTime?: number; | ||
idGen?: IdGen; | ||
fromError?: (error: errors.ErrorRPC<any>) => JSONValue; | ||
filterSensitive?: (key: string, value: any) => any; | ||
fromError?: FromError; | ||
replacer?: (key: string, value: any) => any; | ||
}); | ||
@@ -54,0 +53,0 @@ /** |
@@ -57,3 +57,3 @@ "use strict"; | ||
fromError; | ||
filterSensitive; | ||
replacer; | ||
middlewareFactory; | ||
@@ -80,8 +80,8 @@ // Function to register a callback for timeout | ||
*/ | ||
constructor({ middlewareFactory = middleware.defaultServerMiddlewareWrapper(), handlerTimeoutTime = Infinity, logger, idGen = () => Promise.resolve(null), fromError = utils.fromError, filterSensitive = utils.filterSensitive, }) { | ||
constructor({ middlewareFactory = middleware.defaultServerMiddlewareWrapper(), handlerTimeoutTime = Infinity, logger, idGen = () => Promise.resolve(null), fromError = utils.fromError, replacer, }) { | ||
this.idGen = idGen; | ||
this.middlewareFactory = middlewareFactory; | ||
this.handlerTimeoutTime = handlerTimeoutTime; | ||
this.fromError = fromError ?? utils.fromError; | ||
this.filterSensitive = filterSensitive ?? utils.filterSensitive; | ||
this.fromError = fromError; | ||
this.replacer = replacer; | ||
this.logger = logger ?? new logger_1.default(this.constructor.name); | ||
@@ -103,7 +103,11 @@ } | ||
if (manifestItem instanceof handlers_2.DuplexHandler) { | ||
this.registerDuplexStreamHandler(key, manifestItem.handle, manifestItem.timeout); | ||
this.registerDuplexStreamHandler(key, | ||
// Bind the `this` to the generator handler to make the container available | ||
manifestItem.handle.bind(manifestItem), manifestItem.timeout); | ||
continue; | ||
} | ||
if (manifestItem instanceof handlers_2.ServerHandler) { | ||
this.registerServerStreamHandler(key, manifestItem.handle, manifestItem.timeout); | ||
this.registerServerStreamHandler(key, | ||
// Bind the `this` to the generator handler to make the container available | ||
manifestItem.handle.bind(manifestItem), manifestItem.timeout); | ||
continue; | ||
@@ -132,13 +136,8 @@ } | ||
const handlerPs = new Array(); | ||
if (force) { | ||
for await (const [activeStream] of this.activeStreams.entries()) { | ||
if (force) | ||
activeStream.cancel(new errors.ErrorRPCStopping()); | ||
handlerPs.push(activeStream); | ||
} | ||
await Promise.all(handlerPs); | ||
} | ||
for await (const [activeStream] of this.activeStreams.entries()) { | ||
await activeStream; | ||
if (force) | ||
activeStream.cancel(reason); | ||
handlerPs.push(activeStream); | ||
} | ||
await Promise.allSettled(handlerPs); | ||
// Removes handlers and default timeouts registered in `RPCServer.start()` | ||
@@ -241,7 +240,19 @@ this.handlerMap.clear(); | ||
catch (e) { | ||
const rpcError = { | ||
code: e.exitCode ?? -32603 /* errors.JSONRPCErrorCode.InternalError */, | ||
message: e.description ?? '', | ||
data: JSON.stringify(this.fromError(e), this.filterSensitive), | ||
}; | ||
let rpcError; | ||
if (e instanceof errors.ErrorRPCProtocol) { | ||
rpcError = e.toJSON(); | ||
} | ||
else { | ||
rpcError = new errors.ErrorRPCRemote(e?.message).toJSON(); | ||
try { | ||
rpcError.data.cause = JSON.stringify(this.fromError(e), this.replacer); | ||
} | ||
catch (e) { | ||
rpcError.data.cause = e; | ||
// Dispatch error in the case where the thrown value could not be parsed | ||
this.dispatchEvent(new events.RPCErrorEvent({ | ||
detail: e, | ||
})); | ||
} | ||
} | ||
const rpcErrorMessage = { | ||
@@ -367,3 +378,3 @@ jsonrpc: '2.0', | ||
this.dispatchEvent(new events.RPCErrorEvent({ | ||
detail: new errors.ErrorRPCOutputStreamError(), | ||
detail: new errors.ErrorRPCOutputStreamError('Stream failed waiting for header', { cause: newErr }), | ||
})); | ||
@@ -424,7 +435,19 @@ return; | ||
catch (e) { | ||
const rpcError = { | ||
code: e.exitCode ?? -32603 /* errors.JSONRPCErrorCode.InternalError */, | ||
message: e.description ?? '', | ||
data: JSON.stringify(this.fromError(e), this.filterSensitive), | ||
}; | ||
let rpcError; | ||
if (e instanceof errors.ErrorRPCProtocol) { | ||
rpcError = e.toJSON(); | ||
} | ||
else { | ||
rpcError = new errors.ErrorRPCRemote(e?.message).toJSON(); | ||
try { | ||
rpcError.data.cause = JSON.stringify(this.fromError(e), this.replacer); | ||
} | ||
catch (e) { | ||
rpcError.data.cause = e; | ||
// Dispatch error in the case where the thrown value could not be parsed | ||
this.dispatchEvent(new events.RPCErrorEvent({ | ||
detail: e, | ||
})); | ||
} | ||
} | ||
const rpcErrorMessage = { | ||
@@ -431,0 +454,0 @@ jsonrpc: '2.0', |
@@ -213,2 +213,6 @@ /// <reference types="node" /> | ||
}; | ||
declare const brand: unique symbol; | ||
type Opaque<K, T> = T & { | ||
readonly [brand]: K; | ||
}; | ||
type JSONValue = { | ||
@@ -230,2 +234,4 @@ [key: string]: JSONValue | undefined; | ||
} : never; | ||
export type { IdGen, JSONRPCRequestMessage, JSONRPCRequestNotification, JSONRPCResponseResult, JSONRPCResponseError, JSONRPCError, JSONRPCRequest, JSONRPCResponse, JSONRPCMessage, HandlerImplementation, RawHandlerImplementation, DuplexHandlerImplementation, ServerHandlerImplementation, ClientHandlerImplementation, UnaryHandlerImplementation, ContainerType, RPCStream, StreamFactory, MiddlewareFactory, ServerManifest, ClientManifest, HandlerType, MapCallers, JSONValue, POJO, PromiseDeconstructed, HandlerTypes, }; | ||
type FromError = (error: any) => JSONValue; | ||
type ToError = (errorData: JSONValue) => any; | ||
export type { IdGen, JSONRPCRequestMessage, JSONRPCRequestNotification, JSONRPCResponseResult, JSONRPCResponseError, JSONRPCError, JSONRPCRequest, JSONRPCResponse, JSONRPCMessage, HandlerImplementation, RawHandlerImplementation, DuplexHandlerImplementation, ServerHandlerImplementation, ClientHandlerImplementation, UnaryHandlerImplementation, ContainerType, RPCStream, StreamFactory, MiddlewareFactory, ServerManifest, ClientManifest, HandlerType, MapCallers, Opaque, JSONValue, POJO, PromiseDeconstructed, HandlerTypes, FromError, ToError, }; |
@@ -5,4 +5,2 @@ /// <reference types="node" /> | ||
import { TransformStream } from 'stream/web'; | ||
import { ErrorRPC } from './errors'; | ||
import * as rpcErrors from './errors'; | ||
declare function isObject(o: unknown): o is object; | ||
@@ -19,8 +17,8 @@ declare function promise<T = void>(): PromiseDeconstructed<T>; | ||
/** | ||
* Serializes an ErrorRPC instance into a JSONValue object suitable for RPC. | ||
* @param {ErrorRPC<any>} error - The ErrorRPC instance to serialize. | ||
* @param {any} [id] - Optional id for the error object in the RPC response. | ||
* Serializes an Error instance into a JSONValue object suitable for RPC. | ||
* @param {Error} error - The Error instance to serialize. | ||
* @returns {JSONValue} The serialized ErrorRPC instance. | ||
* @throws {TypeError} If the error is an instance of {@link Symbol}, {@link BigInt} or {@link Function}. | ||
*/ | ||
declare function fromError(errorin: rpcErrors.ErrorRPCProtocol<any>, id?: any): JSONValue; | ||
declare function fromError(error: any): JSONValue; | ||
/** | ||
@@ -32,8 +30,6 @@ * The replacer function to customize the serialization process. | ||
* Deserializes an error response object into an ErrorRPCRemote instance. | ||
* @param {any} errorResponse - The error response object. | ||
* @param {any} [metadata] - Optional metadata for the deserialized error. | ||
* @returns {ErrorRPCRemote<any>} The deserialized ErrorRPCRemote instance. | ||
* @throws {TypeError} If the errorResponse object is invalid. | ||
* @param {JSONValue} errorData - The error data object. | ||
* @returns {any} The deserialized error. | ||
*/ | ||
declare function toError(errorData: any, clientMetadata?: any): ErrorRPC<any>; | ||
declare function toError(errorData: JSONValue): any; | ||
/** | ||
@@ -54,5 +50,6 @@ * This constructs a transformation stream that converts any input into a | ||
* created. | ||
* @param toError | ||
* @param timer - Timer that gets refreshed each time a message is provided. | ||
*/ | ||
declare function clientOutputTransformStream<O extends JSONValue>(clientMetadata?: JSONValue, timer?: Timer): TransformStream<JSONRPCResponse<O>, O>; | ||
declare function clientOutputTransformStream<O extends JSONValue>(clientMetadata: JSONValue, toError: (errorData: JSONValue) => any, timer?: Timer): TransformStream<JSONRPCResponse<O>, O>; | ||
declare function getHandlerTypes(manifest: ClientManifest): Record<string, HandlerType>; | ||
@@ -59,0 +56,0 @@ /** |
@@ -30,4 +30,3 @@ "use strict"; | ||
const errors_1 = require("@matrixai/errors"); | ||
const errors_2 = require("./errors"); | ||
const rpcErrors = __importStar(require("./errors")); | ||
const errors = __importStar(require("./errors")); | ||
// Importing PK funcs and utils which are essential for RPC | ||
@@ -57,9 +56,9 @@ function isObject(o) { | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
if (!('method' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`method` property must be defined'); | ||
throw new errors.ErrorRPCParse('`method` property must be defined'); | ||
} | ||
if (typeof message.method !== 'string') { | ||
throw new rpcErrors.ErrorRPCParse('`method` property must be a string'); | ||
throw new errors.ErrorRPCParse('`method` property must be a string'); | ||
} | ||
@@ -75,3 +74,3 @@ // If ('params' in message && !utils.isObject(message.params)) { | ||
if (!('id' in jsonRequest)) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be defined'); | ||
throw new errors.ErrorRPCParse('`id` property must be defined'); | ||
} | ||
@@ -81,3 +80,3 @@ if (typeof jsonRequest.id !== 'string' && | ||
jsonRequest.id !== null) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
throw new errors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
} | ||
@@ -90,3 +89,3 @@ return jsonRequest; | ||
if ('id' in jsonRequest) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must not be defined'); | ||
throw new errors.ErrorRPCParse('`id` property must not be defined'); | ||
} | ||
@@ -98,9 +97,9 @@ return jsonRequest; | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
if (!('result' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`result` property must be defined'); | ||
throw new errors.ErrorRPCParse('`result` property must be defined'); | ||
} | ||
if ('error' in message) { | ||
throw new rpcErrors.ErrorRPCParse('`error` property must not be defined'); | ||
throw new errors.ErrorRPCParse('`error` property must not be defined'); | ||
} | ||
@@ -111,3 +110,3 @@ // If (!utils.isObject(message.result)) { | ||
if (!('id' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be defined'); | ||
throw new errors.ErrorRPCParse('`id` property must be defined'); | ||
} | ||
@@ -117,3 +116,3 @@ if (typeof message.id !== 'string' && | ||
message.id !== null) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
throw new errors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
} | ||
@@ -125,13 +124,13 @@ return message; | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
if ('result' in message) { | ||
throw new rpcErrors.ErrorRPCParse('`result` property must not be defined'); | ||
throw new errors.ErrorRPCParse('`result` property must not be defined'); | ||
} | ||
if (!('error' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`error` property must be defined'); | ||
throw new errors.ErrorRPCParse('`error` property must be defined'); | ||
} | ||
parseJSONRPCError(message.error); | ||
if (!('id' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be defined'); | ||
throw new errors.ErrorRPCParse('`id` property must be defined'); | ||
} | ||
@@ -141,3 +140,3 @@ if (typeof message.id !== 'string' && | ||
message.id !== null) { | ||
throw new rpcErrors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
throw new errors.ErrorRPCParse('`id` property must be a string, number or null'); | ||
} | ||
@@ -149,15 +148,15 @@ return message; | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
if (!('code' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`code` property must be defined'); | ||
throw new errors.ErrorRPCParse('`code` property must be defined'); | ||
} | ||
if (typeof message.code !== 'number') { | ||
throw new rpcErrors.ErrorRPCParse('`code` property must be a number'); | ||
throw new errors.ErrorRPCParse('`code` property must be a number'); | ||
} | ||
if (!('message' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`message` property must be defined'); | ||
throw new errors.ErrorRPCParse('`message` property must be defined'); | ||
} | ||
if (typeof message.message !== 'string') { | ||
throw new rpcErrors.ErrorRPCParse('`message` property must be a string'); | ||
throw new errors.ErrorRPCParse('`message` property must be a string'); | ||
} | ||
@@ -171,3 +170,3 @@ // If ('data' in message && !utils.isObject(message.data)) { | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
@@ -186,3 +185,3 @@ try { | ||
} | ||
throw new rpcErrors.ErrorRPCParse('structure did not match a `JSONRPCResponse`'); | ||
throw new errors.ErrorRPCParse('structure did not match a `JSONRPCResponse`'); | ||
} | ||
@@ -192,9 +191,9 @@ exports.parseJSONRPCResponse = parseJSONRPCResponse; | ||
if (!isObject(message)) { | ||
throw new rpcErrors.ErrorRPCParse('must be a JSON POJO'); | ||
throw new errors.ErrorRPCParse('must be a JSON POJO'); | ||
} | ||
if (!('jsonrpc' in message)) { | ||
throw new rpcErrors.ErrorRPCParse('`jsonrpc` property must be defined'); | ||
throw new errors.ErrorRPCParse('`jsonrpc` property must be defined'); | ||
} | ||
if (message.jsonrpc !== '2.0') { | ||
throw new rpcErrors.ErrorRPCParse('`jsonrpc` property must be a string of "2.0"'); | ||
throw new errors.ErrorRPCParse('`jsonrpc` property must be a string of "2.0"'); | ||
} | ||
@@ -213,18 +212,50 @@ try { | ||
} | ||
throw new rpcErrors.ErrorRPCParse('Message structure did not match a `JSONRPCMessage`'); | ||
throw new errors.ErrorRPCParse('Message structure did not match a `JSONRPCMessage`'); | ||
} | ||
exports.parseJSONRPCMessage = parseJSONRPCMessage; | ||
/** | ||
* Serializes an ErrorRPC instance into a JSONValue object suitable for RPC. | ||
* @param {ErrorRPC<any>} error - The ErrorRPC instance to serialize. | ||
* @param {any} [id] - Optional id for the error object in the RPC response. | ||
* Serializes an Error instance into a JSONValue object suitable for RPC. | ||
* @param {Error} error - The Error instance to serialize. | ||
* @returns {JSONValue} The serialized ErrorRPC instance. | ||
* @throws {TypeError} If the error is an instance of {@link Symbol}, {@link BigInt} or {@link Function}. | ||
*/ | ||
function fromError(errorin, id) { | ||
const error = { | ||
errorCode: errorin.code, | ||
message: errorin.message, | ||
data: errorin.data, | ||
type: errorin.constructor.name, | ||
}; | ||
function fromError(error) { | ||
// TODO: Linked-List traversal must be done iteractively rather than recusively to prevent stack overflow. | ||
switch (typeof error) { | ||
case 'symbol': | ||
case 'bigint': | ||
case 'function': | ||
throw TypeError(`${error} cannot be serialized`); | ||
} | ||
if (error instanceof Error) { | ||
const cause = fromError(error.cause); | ||
const timestamp = (error.timestamp ?? new Date()).toJSON(); | ||
if (error instanceof errors_1.AbstractError) { | ||
return error.toJSON(); | ||
} | ||
else if (error instanceof AggregateError) { | ||
// AggregateError has an `errors` property | ||
return { | ||
type: error.constructor.name, | ||
message: error.message, | ||
data: { | ||
errors: error.errors.map(fromError), | ||
stack: error.stack, | ||
timestamp, | ||
cause, | ||
}, | ||
}; | ||
} | ||
// If it's some other type of error then only serialise the message and | ||
// stack (and the type of the error) | ||
return { | ||
type: error.name, | ||
message: error.message, | ||
data: { | ||
stack: error.stack, | ||
timestamp, | ||
cause, | ||
}, | ||
}; | ||
} | ||
return error; | ||
@@ -247,105 +278,96 @@ } | ||
AbstractError: errors_1.AbstractError, | ||
ErrorRPCRemote: errors_2.ErrorRPCRemote, | ||
ErrorRPC: errors_2.ErrorRPC, | ||
}; | ||
/** | ||
* Creates a replacer function that omits a specific key during serialization. | ||
* @returns {Function} The replacer function. | ||
* The replacer function to customize the serialization process. | ||
*/ | ||
const createReplacer = () => { | ||
return (keyToRemove) => { | ||
return (key, value) => { | ||
if (key === keyToRemove) { | ||
return undefined; | ||
const filterSensitive = (keyToRemove) => { | ||
return (key, value) => { | ||
if (key === keyToRemove) { | ||
return undefined; | ||
} | ||
if (key !== 'code') { | ||
if (value instanceof errors.ErrorRPCProtocol) { | ||
return { | ||
code: value.code, | ||
message: value.message, | ||
data: value.data, | ||
type: value.constructor.name, | ||
}; | ||
} | ||
if (key !== 'code') { | ||
if (value instanceof rpcErrors.ErrorRPCProtocol) { | ||
return { | ||
code: value.code, | ||
if (value instanceof AggregateError) { | ||
return { | ||
type: value.constructor.name, | ||
data: { | ||
errors: value.errors, | ||
message: value.message, | ||
data: value.data, | ||
type: value.constructor.name, | ||
}; | ||
} | ||
if (value instanceof AggregateError) { | ||
return { | ||
type: value.constructor.name, | ||
data: { | ||
errors: value.errors, | ||
message: value.message, | ||
stack: value.stack, | ||
}, | ||
}; | ||
} | ||
stack: value.stack, | ||
}, | ||
}; | ||
} | ||
return value; | ||
}; | ||
} | ||
return value; | ||
}; | ||
}; | ||
/** | ||
* The replacer function to customize the serialization process. | ||
*/ | ||
const filterSensitive = createReplacer(); | ||
exports.filterSensitive = filterSensitive; | ||
const ErrorCodeToErrorType = { | ||
[-32006 /* JSONRPCErrorCode.RPCRemote */]: errors_2.ErrorRPCRemote, | ||
[-32001 /* JSONRPCErrorCode.RPCStopping */]: errors_2.ErrorRPCStopping, | ||
[-32003 /* JSONRPCErrorCode.RPCMessageLength */]: errors_2.ErrorRPCMessageLength, | ||
[-32700 /* JSONRPCErrorCode.ParseError */]: errors_2.ErrorRPCParse, | ||
[-32602 /* JSONRPCErrorCode.InvalidParams */]: errors_2.ErrorRPC, | ||
[-32000 /* JSONRPCErrorCode.HandlerNotFound */]: errors_2.ErrorRPCHandlerFailed, | ||
[-32004 /* JSONRPCErrorCode.RPCMissingResponse */]: errors_2.ErrorRPCMissingResponse, | ||
[-32005 /* JSONRPCErrorCode.RPCOutputStreamError */]: errors_2.ErrorRPCOutputStreamError, | ||
[-32008 /* JSONRPCErrorCode.RPCTimedOut */]: errors_2.ErrorRPCTimedOut, | ||
[-32007 /* JSONRPCErrorCode.RPCStreamEnded */]: errors_2.ErrorRPCStreamEnded, | ||
[-32010 /* JSONRPCErrorCode.RPCConnectionLocal */]: errors_2.ErrorRPCConnectionLocal, | ||
[-32011 /* JSONRPCErrorCode.RPCConnectionPeer */]: errors_2.ErrorRPCConnectionPeer, | ||
[-32012 /* JSONRPCErrorCode.RPCConnectionKeepAliveTimeOut */]: errors_2.ErrorRPCConnectionKeepAliveTimeOut, | ||
[-32013 /* JSONRPCErrorCode.RPCConnectionInternal */]: errors_2.ErrorRPCConnectionInternal, | ||
[-32014 /* JSONRPCErrorCode.MissingHeader */]: errors_2.ErrorMissingHeader, | ||
[-32015 /* JSONRPCErrorCode.HandlerAborted */]: errors_2.ErrorRPCHandlerFailed, | ||
[-32016 /* JSONRPCErrorCode.MissingCaller */]: errors_2.ErrorMissingCaller, | ||
}; | ||
/** | ||
* Deserializes an error response object into an ErrorRPCRemote instance. | ||
* @param {any} errorResponse - The error response object. | ||
* @param {any} [metadata] - Optional metadata for the deserialized error. | ||
* @returns {ErrorRPCRemote<any>} The deserialized ErrorRPCRemote instance. | ||
* @throws {TypeError} If the errorResponse object is invalid. | ||
* @param {JSONValue} errorData - The error data object. | ||
* @returns {any} The deserialized error. | ||
*/ | ||
function toError(errorData, clientMetadata) { | ||
// Parsing if it's a string | ||
if (typeof errorData === 'string') { | ||
function toError(errorData) { | ||
// If the value is an error then reconstruct it | ||
if (errorData != null && | ||
typeof errorData === 'object' && | ||
'type' in errorData && | ||
typeof errorData.type === 'string' && | ||
'data' in errorData && | ||
typeof errorData.data === 'object') { | ||
try { | ||
errorData = JSON.parse(errorData); | ||
const eClass = standardErrors[errorData.type]; | ||
if (eClass != null) { | ||
let e; | ||
switch (eClass) { | ||
case errors_1.AbstractError: | ||
e = eClass.fromJSON(errorData); | ||
break; | ||
case AggregateError: | ||
if (errorData.data == null || | ||
!('errors' in errorData.data) || | ||
!Array.isArray(errorData.data.errors) || | ||
typeof errorData.message !== 'string' || | ||
!('stack' in errorData.data) || | ||
typeof errorData.data.stack !== 'string') { | ||
throw new TypeError(`cannot decode JSON to ${errorData.type}`); | ||
} | ||
e = new eClass(errorData.data.errors.map(toError), errorData.message); | ||
e.stack = errorData.data.stack; | ||
break; | ||
default: | ||
if (errorData.data == null || | ||
typeof errorData.message !== 'string' || | ||
!('stack' in errorData.data) || | ||
typeof errorData.data.stack !== 'string') { | ||
throw new TypeError(`Cannot decode JSON to ${errorData.type}`); | ||
} | ||
e = new eClass(errorData.message); | ||
e.stack = errorData.data.stack; | ||
break; | ||
} | ||
if (errorData.data != null && 'cause' in errorData.data) { | ||
e.cause = toError(errorData.data.cause); | ||
} | ||
return e; | ||
} | ||
} | ||
catch (e) { | ||
throw new errors_2.ErrorRPCConnectionInternal('Unable to parse string to JSON'); | ||
// If `TypeError` which represents decoding failure | ||
// then return value as-is | ||
// Any other exception is a bug | ||
if (!(e instanceof TypeError)) { | ||
throw e; | ||
} | ||
} | ||
} | ||
// Check if errorData is an object and not null | ||
if (typeof errorData !== 'object' || errorData === null) { | ||
throw new errors_2.ErrorRPCConnectionInternal('errorData should be a non-null object'); | ||
} | ||
// Define default error values, you can modify this as per your needs | ||
let errorCode = -32006; | ||
let message = 'Unknown error'; | ||
let data = {}; | ||
// Check for errorCode and update if exists | ||
if ('errorCode' in errorData) { | ||
errorCode = errorData.errorCode; | ||
} | ||
if ('message' in errorData) { | ||
message = errorData.message; | ||
} | ||
if ('data' in errorData) { | ||
data = errorData.data; | ||
} | ||
// Map errorCode to a specific Error type | ||
const ErrorType = ErrorCodeToErrorType[errorCode]; | ||
if (!ErrorType) { | ||
throw new errors_2.ErrorRPC('Unknown Error Code'); // Handle unknown error codes | ||
} | ||
const error = new ErrorType(message, { data, metadata: clientMetadata }); | ||
return error; | ||
// Other values are returned as-is | ||
return errorData; | ||
} | ||
@@ -382,5 +404,6 @@ exports.toError = toError; | ||
* created. | ||
* @param toError | ||
* @param timer - Timer that gets refreshed each time a message is provided. | ||
*/ | ||
function clientOutputTransformStream(clientMetadata, timer) { | ||
function clientOutputTransformStream(clientMetadata, toError, timer) { | ||
return new web_1.TransformStream({ | ||
@@ -391,3 +414,11 @@ transform: (chunk, controller) => { | ||
if ('error' in chunk) { | ||
throw toError(chunk.error, clientMetadata); | ||
const e = errors.ErrorRPCProtocol.fromJSON(chunk.error); | ||
if (e instanceof errors.ErrorRPCRemote && | ||
chunk.error.data != null && | ||
typeof chunk.error.data === 'object' && | ||
'cause' in chunk.error.data) { | ||
e.metadata = clientMetadata; | ||
e.cause = toError(JSON.parse(chunk.error.data.cause)); | ||
} | ||
throw e; | ||
} | ||
@@ -448,3 +479,3 @@ controller.enqueue(chunk.result); | ||
catch (e) { | ||
throw new rpcErrors.ErrorRPCParse(undefined, { | ||
throw new errors.ErrorRPCParse(undefined, { | ||
cause: e, | ||
@@ -454,3 +485,3 @@ }); | ||
if (bytesWritten > bufferByteLimit) { | ||
throw new rpcErrors.ErrorRPCMessageLength(); | ||
throw new errors.ErrorRPCMessageLength(); | ||
} | ||
@@ -473,5 +504,5 @@ } | ||
function never() { | ||
throw new errors_2.ErrorRPC('This function should never be called'); | ||
throw new errors.ErrorRPC('This function should never be called'); | ||
} | ||
exports.never = never; | ||
//# sourceMappingURL=utils.js.map |
{ | ||
"name": "@matrixai/rpc", | ||
"version": "0.1.13", | ||
"version": "0.2.0", | ||
"author": "Matrix AI", | ||
@@ -5,0 +5,0 @@ "contributors": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
307947
2888