@metamask-previews/json-rpc-middleware-stream 5.0.1-preview.4ae7d84 → 6.0.0-preview.eb58a59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -1
- package/dist/createEngineStream.d.ts +15 -0
- package/dist/createEngineStream.d.ts.map +1 -0
- package/dist/createEngineStream.js +39 -0
- package/dist/createEngineStream.js.map +1 -0
- package/dist/createStreamMiddleware.d.ts +23 -0
- package/dist/createStreamMiddleware.d.ts.map +1 -0
- package/dist/createStreamMiddleware.js +122 -0
- package/dist/createStreamMiddleware.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [6.0.0]
|
|
10
|
+
### Added
|
|
11
|
+
- Migrate `@metamask/json-rpc-engine` into the core monorepo ([#1762](https://github.com/MetaMask/core/pull/1762))
|
|
12
|
+
|
|
13
|
+
## Changed
|
|
14
|
+
- **BREAKING**: Rename package from `json-rpc-middleware-stream` to `@metamask/json-rpc-middleware-stream` ([#1762](https://github.com/MetaMask/core/pull/1762))
|
|
15
|
+
- Bump `@metamask/json-rpc-engine` from `^7.1.0` to `^7.2.0` ([#1762](https://github.com/MetaMask/core/pull/1762))
|
|
16
|
+
- Bump `@metamask/utils` from `^8.1.0` to `^8.2.0` ([#1762](https://github.com/MetaMask/core/pull/1762))
|
|
17
|
+
|
|
9
18
|
## [5.0.1]
|
|
10
19
|
### Changed
|
|
11
20
|
- Upgrade typescript version to 4.8.4 ([#68](https://github.com/MetaMask/json-rpc-middleware-stream/pull/68))
|
|
@@ -53,7 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
53
62
|
### Added
|
|
54
63
|
- TypeScript typings ([#11](https://github.com/MetaMask/json-rpc-middleware-stream/pull/11))
|
|
55
64
|
|
|
56
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/json-rpc-middleware-stream@
|
|
65
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/json-rpc-middleware-stream@6.0.0...HEAD
|
|
66
|
+
[6.0.0]: https://github.com/MetaMask/core/compare/json-rpc-middleware-stream@5.0.1...@metamask/json-rpc-middleware-stream@6.0.0
|
|
57
67
|
[5.0.1]: https://github.com/MetaMask/core/compare/json-rpc-middleware-stream@5.0.0...json-rpc-middleware-stream@5.0.1
|
|
58
68
|
[5.0.0]: https://github.com/MetaMask/core/compare/json-rpc-middleware-stream@4.2.3...json-rpc-middleware-stream@5.0.0
|
|
59
69
|
[4.2.3]: https://github.com/MetaMask/core/compare/json-rpc-middleware-stream@4.2.2...json-rpc-middleware-stream@4.2.3
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JsonRpcEngine } from '@metamask/json-rpc-engine';
|
|
2
|
+
import { Duplex } from 'readable-stream';
|
|
3
|
+
declare type EngineStreamOptions = {
|
|
4
|
+
engine: JsonRpcEngine;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Takes a JsonRpcEngine and returns a Duplex stream wrapping it.
|
|
8
|
+
*
|
|
9
|
+
* @param opts - Options bag.
|
|
10
|
+
* @param opts.engine - The JsonRpcEngine to wrap in a stream.
|
|
11
|
+
* @returns The stream wrapping the engine.
|
|
12
|
+
*/
|
|
13
|
+
export default function createEngineStream(opts: EngineStreamOptions): Duplex;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=createEngineStream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createEngineStream.d.ts","sourceRoot":"","sources":["../src/createEngineStream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,aAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAgC5E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const readable_stream_1 = require("readable-stream");
|
|
4
|
+
/**
|
|
5
|
+
* Takes a JsonRpcEngine and returns a Duplex stream wrapping it.
|
|
6
|
+
*
|
|
7
|
+
* @param opts - Options bag.
|
|
8
|
+
* @param opts.engine - The JsonRpcEngine to wrap in a stream.
|
|
9
|
+
* @returns The stream wrapping the engine.
|
|
10
|
+
*/
|
|
11
|
+
function createEngineStream(opts) {
|
|
12
|
+
if (!(opts === null || opts === void 0 ? void 0 : opts.engine)) {
|
|
13
|
+
throw new Error('Missing engine parameter!');
|
|
14
|
+
}
|
|
15
|
+
const { engine } = opts;
|
|
16
|
+
const stream = new readable_stream_1.Duplex({ objectMode: true, read: () => undefined, write });
|
|
17
|
+
// forward notifications
|
|
18
|
+
if (engine.on) {
|
|
19
|
+
engine.on('notification', (message) => {
|
|
20
|
+
stream.push(message);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return stream;
|
|
24
|
+
/**
|
|
25
|
+
* Write a JSON-RPC request to the stream.
|
|
26
|
+
*
|
|
27
|
+
* @param req - The JSON-rpc request.
|
|
28
|
+
* @param _encoding - The stream encoding, not used.
|
|
29
|
+
* @param streamWriteCallback - The stream write callback.
|
|
30
|
+
*/
|
|
31
|
+
function write(req, _encoding, streamWriteCallback) {
|
|
32
|
+
engine.handle(req, (_err, res) => {
|
|
33
|
+
stream.push(res);
|
|
34
|
+
});
|
|
35
|
+
streamWriteCallback();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.default = createEngineStream;
|
|
39
|
+
//# sourceMappingURL=createEngineStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createEngineStream.js","sourceRoot":"","sources":["../src/createEngineStream.ts"],"names":[],"mappings":";;AAEA,qDAAyC;AAMzC;;;;;;GAMG;AACH,SAAwB,kBAAkB,CAAC,IAAyB;IAClE,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,CAAA,EAAE;QACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;KAC9C;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,IAAI,wBAAM,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,wBAAwB;IACxB,IAAI,MAAM,CAAC,EAAE,EAAE;QACb,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE;YACpC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;KACJ;IACD,OAAO,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,SAAS,KAAK,CACZ,GAAmB,EACnB,SAAkB,EAClB,mBAAmD;QAEnD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,mBAAmB,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAhCD,qCAgCC","sourcesContent":["import type { JsonRpcEngine } from '@metamask/json-rpc-engine';\nimport type { JsonRpcRequest } from '@metamask/utils';\nimport { Duplex } from 'readable-stream';\n\ntype EngineStreamOptions = {\n engine: JsonRpcEngine;\n};\n\n/**\n * Takes a JsonRpcEngine and returns a Duplex stream wrapping it.\n *\n * @param opts - Options bag.\n * @param opts.engine - The JsonRpcEngine to wrap in a stream.\n * @returns The stream wrapping the engine.\n */\nexport default function createEngineStream(opts: EngineStreamOptions): Duplex {\n if (!opts?.engine) {\n throw new Error('Missing engine parameter!');\n }\n\n const { engine } = opts;\n const stream = new Duplex({ objectMode: true, read: () => undefined, write });\n // forward notifications\n if (engine.on) {\n engine.on('notification', (message) => {\n stream.push(message);\n });\n }\n return stream;\n\n /**\n * Write a JSON-RPC request to the stream.\n *\n * @param req - The JSON-rpc request.\n * @param _encoding - The stream encoding, not used.\n * @param streamWriteCallback - The stream write callback.\n */\n function write(\n req: JsonRpcRequest,\n _encoding: unknown,\n streamWriteCallback: (error?: Error | null) => void,\n ) {\n engine.handle(req, (_err, res) => {\n stream.push(res);\n });\n streamWriteCallback();\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine';
|
|
2
|
+
import SafeEventEmitter from '@metamask/safe-event-emitter';
|
|
3
|
+
import type { JsonRpcParams } from '@metamask/utils';
|
|
4
|
+
import { Duplex } from 'readable-stream';
|
|
5
|
+
declare type Options = {
|
|
6
|
+
retryOnMessage?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Creates a JsonRpcEngine middleware with an associated Duplex stream and
|
|
10
|
+
* EventEmitter. The middleware, and by extension stream, assume that middleware
|
|
11
|
+
* parameters are properly formatted. No runtime type checking or validation is
|
|
12
|
+
* performed.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Configuration options for middleware.
|
|
15
|
+
* @returns The event emitter, middleware, and stream.
|
|
16
|
+
*/
|
|
17
|
+
export default function createStreamMiddleware(options?: Options): {
|
|
18
|
+
events: SafeEventEmitter;
|
|
19
|
+
middleware: JsonRpcMiddleware<JsonRpcParams, JsonRpcParams>;
|
|
20
|
+
stream: Duplex;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=createStreamMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStreamMiddleware.d.ts","sourceRoot":"","sources":["../src/createStreamMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,gBAAgB,MAAM,8BAA8B,CAAC;AAC5D,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAczC,aAAK,OAAO,GAAG;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,OAAO,GAAE,OAAY;;;;EA2HnE"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const safe_event_emitter_1 = __importDefault(require("@metamask/safe-event-emitter"));
|
|
7
|
+
const readable_stream_1 = require("readable-stream");
|
|
8
|
+
/**
|
|
9
|
+
* Creates a JsonRpcEngine middleware with an associated Duplex stream and
|
|
10
|
+
* EventEmitter. The middleware, and by extension stream, assume that middleware
|
|
11
|
+
* parameters are properly formatted. No runtime type checking or validation is
|
|
12
|
+
* performed.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Configuration options for middleware.
|
|
15
|
+
* @returns The event emitter, middleware, and stream.
|
|
16
|
+
*/
|
|
17
|
+
function createStreamMiddleware(options = {}) {
|
|
18
|
+
const idMap = {}; // TODO: replace with actual Map
|
|
19
|
+
const stream = new readable_stream_1.Duplex({
|
|
20
|
+
objectMode: true,
|
|
21
|
+
read: () => undefined,
|
|
22
|
+
write: processMessage,
|
|
23
|
+
});
|
|
24
|
+
const events = new safe_event_emitter_1.default();
|
|
25
|
+
const middleware = (req, res, next, end) => {
|
|
26
|
+
// register request on id map *before* sending it to the stream, to avoid race issues
|
|
27
|
+
idMap[req.id] = { req, res, next, end };
|
|
28
|
+
// write req to stream
|
|
29
|
+
sendToStream(req);
|
|
30
|
+
};
|
|
31
|
+
return { events, middleware, stream };
|
|
32
|
+
/**
|
|
33
|
+
* Forwards JSON-RPC request to the stream.
|
|
34
|
+
*
|
|
35
|
+
* @param req - The JSON-RPC request object.
|
|
36
|
+
*/
|
|
37
|
+
function sendToStream(req) {
|
|
38
|
+
// TODO: limiting retries could be implemented here
|
|
39
|
+
stream.push(req);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Writes a JSON-RPC object to the stream.
|
|
43
|
+
*
|
|
44
|
+
* @param res - The JSON-RPC response object.
|
|
45
|
+
* @param _encoding - The stream encoding, not used.
|
|
46
|
+
* @param streamWriteCallback - The stream write callback.
|
|
47
|
+
*/
|
|
48
|
+
function processMessage(res, _encoding, streamWriteCallback) {
|
|
49
|
+
let errorObj = null;
|
|
50
|
+
try {
|
|
51
|
+
const isNotification = !res.id;
|
|
52
|
+
if (isNotification) {
|
|
53
|
+
processNotification(res);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
processResponse(res);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (_err) {
|
|
60
|
+
errorObj = _err;
|
|
61
|
+
}
|
|
62
|
+
// continue processing stream
|
|
63
|
+
streamWriteCallback(errorObj);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Processes a JSON-RPC response.
|
|
67
|
+
*
|
|
68
|
+
* @param res - The response to process.
|
|
69
|
+
*/
|
|
70
|
+
function processResponse(res) {
|
|
71
|
+
const { id: responseId } = res;
|
|
72
|
+
if (responseId === null) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const context = idMap[responseId];
|
|
76
|
+
if (!context) {
|
|
77
|
+
console.warn(`StreamMiddleware - Unknown response id "${responseId}"`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
delete idMap[responseId];
|
|
81
|
+
// copy whole res onto original res
|
|
82
|
+
Object.assign(context.res, res);
|
|
83
|
+
// run callback on empty stack,
|
|
84
|
+
// prevent internal stream-handler from catching errors
|
|
85
|
+
// TODO: remove eslint-disable once issue #1989 is resolved.
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
87
|
+
setTimeout(context.end);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Processes a JSON-RPC notification.
|
|
91
|
+
*
|
|
92
|
+
* @param notif - The notification to process.
|
|
93
|
+
*/
|
|
94
|
+
function processNotification(notif) {
|
|
95
|
+
if ((options === null || options === void 0 ? void 0 : options.retryOnMessage) && notif.method === options.retryOnMessage) {
|
|
96
|
+
retryStuckRequests();
|
|
97
|
+
}
|
|
98
|
+
events.emit('notification', notif);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Retry pending requests.
|
|
102
|
+
*/
|
|
103
|
+
function retryStuckRequests() {
|
|
104
|
+
Object.values(idMap).forEach(({ req, retryCount = 0 }) => {
|
|
105
|
+
// Avoid retrying requests without an id - they cannot have matching responses so retry logic doesn't apply
|
|
106
|
+
// Check for retry count below ensure that a request is not retried more than 3 times
|
|
107
|
+
if (!req.id) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (retryCount >= 3) {
|
|
111
|
+
throw new Error(`StreamMiddleware - Retry limit exceeded for request id "${req.id}"`);
|
|
112
|
+
}
|
|
113
|
+
const idMapObject = idMap[req.id];
|
|
114
|
+
if (idMapObject) {
|
|
115
|
+
idMapObject.retryCount = retryCount + 1;
|
|
116
|
+
}
|
|
117
|
+
sendToStream(req);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.default = createStreamMiddleware;
|
|
122
|
+
//# sourceMappingURL=createStreamMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStreamMiddleware.js","sourceRoot":"","sources":["../src/createStreamMiddleware.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n JsonRpcEngineNextCallback,\n JsonRpcEngineEndCallback,\n JsonRpcMiddleware,\n} from '@metamask/json-rpc-engine';\nimport SafeEventEmitter from '@metamask/safe-event-emitter';\nimport type {\n JsonRpcNotification,\n JsonRpcParams,\n JsonRpcRequest,\n PendingJsonRpcResponse,\n} from '@metamask/utils';\nimport { Duplex } from 'readable-stream';\n\ntype IdMapValue = {\n req: JsonRpcRequest;\n res: PendingJsonRpcResponse<JsonRpcParams>;\n next: JsonRpcEngineNextCallback;\n end: JsonRpcEngineEndCallback;\n retryCount?: number;\n};\n\ntype IdMap = {\n [requestId: string]: IdMapValue;\n};\n\ntype Options = {\n retryOnMessage?: string;\n};\n\n/**\n * Creates a JsonRpcEngine middleware with an associated Duplex stream and\n * EventEmitter. The middleware, and by extension stream, assume that middleware\n * parameters are properly formatted. No runtime type checking or validation is\n * performed.\n *\n * @param options - Configuration options for middleware.\n * @returns The event emitter, middleware, and stream.\n */\nexport default function createStreamMiddleware(options: Options = {}) {\n const idMap: IdMap = {}; // TODO: replace with actual Map\n const stream = new Duplex({\n objectMode: true,\n read: () => undefined,\n write: processMessage,\n });\n\n const events = new SafeEventEmitter();\n\n const middleware: JsonRpcMiddleware<JsonRpcParams, JsonRpcParams> = (\n req,\n res,\n next,\n end,\n ) => {\n // register request on id map *before* sending it to the stream, to avoid race issues\n idMap[req.id as unknown as string] = { req, res, next, end };\n // write req to stream\n sendToStream(req);\n };\n\n return { events, middleware, stream };\n\n /**\n * Forwards JSON-RPC request to the stream.\n *\n * @param req - The JSON-RPC request object.\n */\n function sendToStream(req: JsonRpcRequest) {\n // TODO: limiting retries could be implemented here\n stream.push(req);\n }\n\n /**\n * Writes a JSON-RPC object to the stream.\n *\n * @param res - The JSON-RPC response object.\n * @param _encoding - The stream encoding, not used.\n * @param streamWriteCallback - The stream write callback.\n */\n function processMessage(\n res: PendingJsonRpcResponse<JsonRpcParams>,\n _encoding: unknown,\n streamWriteCallback: (error?: Error | null) => void,\n ) {\n let errorObj: Error | null = null;\n try {\n const isNotification = !res.id;\n if (isNotification) {\n processNotification(res as unknown as JsonRpcNotification);\n } else {\n processResponse(res);\n }\n } catch (_err) {\n errorObj = _err as Error;\n }\n // continue processing stream\n streamWriteCallback(errorObj);\n }\n\n /**\n * Processes a JSON-RPC response.\n *\n * @param res - The response to process.\n */\n function processResponse(res: PendingJsonRpcResponse<JsonRpcParams>) {\n const { id: responseId } = res;\n if (responseId === null) {\n return;\n }\n\n const context = idMap[responseId];\n if (!context) {\n console.warn(`StreamMiddleware - Unknown response id \"${responseId}\"`);\n return;\n }\n\n delete idMap[responseId];\n // copy whole res onto original res\n Object.assign(context.res, res);\n // run callback on empty stack,\n // prevent internal stream-handler from catching errors\n // TODO: remove eslint-disable once issue #1989 is resolved.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n setTimeout(context.end);\n }\n\n /**\n * Processes a JSON-RPC notification.\n *\n * @param notif - The notification to process.\n */\n function processNotification(notif: JsonRpcNotification) {\n if (options?.retryOnMessage && notif.method === options.retryOnMessage) {\n retryStuckRequests();\n }\n events.emit('notification', notif);\n }\n\n /**\n * Retry pending requests.\n */\n function retryStuckRequests() {\n Object.values(idMap).forEach(({ req, retryCount = 0 }) => {\n // Avoid retrying requests without an id - they cannot have matching responses so retry logic doesn't apply\n // Check for retry count below ensure that a request is not retried more than 3 times\n if (!req.id) {\n return;\n }\n\n if (retryCount >= 3) {\n throw new Error(\n `StreamMiddleware - Retry limit exceeded for request id \"${req.id}\"`,\n );\n }\n const idMapObject = idMap[req.id];\n if (idMapObject) {\n idMapObject.retryCount = retryCount + 1;\n }\n sendToStream(req);\n });\n }\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,sBAAsB,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createStreamMiddleware = exports.createEngineStream = void 0;
|
|
7
|
+
const createEngineStream_1 = __importDefault(require("./createEngineStream"));
|
|
8
|
+
exports.createEngineStream = createEngineStream_1.default;
|
|
9
|
+
const createStreamMiddleware_1 = __importDefault(require("./createStreamMiddleware"));
|
|
10
|
+
exports.createStreamMiddleware = createStreamMiddleware_1.default;
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,8EAAsD;AAG7C,6BAHF,4BAAkB,CAGE;AAF3B,sFAA8D;AAEjC,iCAFtB,gCAAsB,CAEsB","sourcesContent":["import createEngineStream from './createEngineStream';\nimport createStreamMiddleware from './createStreamMiddleware';\n\nexport { createEngineStream, createStreamMiddleware };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/json-rpc-middleware-stream",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0-preview.eb58a59",
|
|
4
4
|
"description": "A small toolset for streaming JSON-RPC data and matching requests and responses",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"MetaMask",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test:watch": "jest --watch"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@metamask/json-rpc-engine": "^7.
|
|
33
|
+
"@metamask/json-rpc-engine": "^7.3.0",
|
|
34
34
|
"@metamask/safe-event-emitter": "^3.0.0",
|
|
35
35
|
"@metamask/utils": "^8.2.0",
|
|
36
36
|
"readable-stream": "^3.6.2"
|