From 58673115e27773cf49b9f5d6680e1135d03fc613 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:59:57 +0000 Subject: [PATCH 1/9] Convert streams.js to TypeScript --- app/declarations/index.d.ts | 3 ++ app/util/streams.ts | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 app/util/streams.ts diff --git a/app/declarations/index.d.ts b/app/declarations/index.d.ts index 094baa70c44..db975491594 100644 --- a/app/declarations/index.d.ts +++ b/app/declarations/index.d.ts @@ -8,6 +8,9 @@ declare module 'react-native-fade-in-image'; declare module 'react-native-fast-crypto'; +declare module 'through2'; + +declare module 'pump'; declare module 'react-native-minimizer'; declare module 'xhr2'; diff --git a/app/util/streams.ts b/app/util/streams.ts new file mode 100644 index 00000000000..7bf46505faf --- /dev/null +++ b/app/util/streams.ts @@ -0,0 +1,60 @@ +/* eslint-disable import/no-commonjs */ +import Through from 'through2'; +import ObjectMultiplex from '@metamask/object-multiplex'; +import pump from 'pump'; + +type TransformCallback = (error?: Error | null, data?: unknown) => void; + +interface TransformStream extends NodeJS.ReadWriteStream { + push(chunk: unknown, encoding?: BufferEncoding): boolean; +} + +/** + * Returns a stream transform that parses JSON strings passing through + * @return {NodeJS.ReadWriteStream} + */ +function jsonParseStream(): NodeJS.ReadWriteStream { + return Through.obj(function ( + this: TransformStream, + serialized: string, + _: string, + cb: TransformCallback + ) { + this.push(JSON.parse(serialized)); + cb(); + }); +} + +/** + * Returns a stream transform that calls {@code JSON.stringify} + * on objects passing through + * @return {NodeJS.ReadWriteStream} the stream transform + */ +function jsonStringifyStream(): NodeJS.ReadWriteStream { + return Through.obj(function ( + this: TransformStream, + obj: unknown, + _: string, + cb: TransformCallback + ) { + this.push(JSON.stringify(obj)); + cb(); + }); +} + +/** + * Sets up stream multiplexing for the given stream + * @param {NodeJS.ReadWriteStream} connectionStream - the stream to mux + * @return {NodeJS.ReadWriteStream} the multiplexed stream + */ +function setupMultiplex(connectionStream: NodeJS.ReadWriteStream): NodeJS.ReadWriteStream { + const mux = new ObjectMultiplex(); + pump(connectionStream, mux, connectionStream, (err: Error | null) => { + if (err) { + console.warn(err); + } + }); + return mux as unknown as NodeJS.ReadWriteStream; +} + +export { jsonParseStream, jsonStringifyStream, setupMultiplex }; From 67e439af08ebc041a8128bcdff0ca3a7c935a273 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:00:03 +0000 Subject: [PATCH 2/9] Remove old streams.js file --- app/util/streams.js | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 app/util/streams.js diff --git a/app/util/streams.js b/app/util/streams.js deleted file mode 100644 index 1130d58a6d3..00000000000 --- a/app/util/streams.js +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable import/no-commonjs */ -const Through = require('through2'); -const ObjectMultiplex = require('@metamask/object-multiplex'); -const pump = require('pump'); - -/** - * Returns a stream transform that parses JSON strings passing through - * @return {stream.Transform} - */ -function jsonParseStream() { - return Through.obj(function (serialized, _, cb) { - this.push(JSON.parse(serialized)); - cb(); - }); -} - -/** - * Returns a stream transform that calls {@code JSON.stringify} - * on objects passing through - * @return {stream.Transform} the stream transform - */ -function jsonStringifyStream() { - return Through.obj(function (obj, _, cb) { - this.push(JSON.stringify(obj)); - cb(); - }); -} - -/** - * Sets up stream multiplexing for the given stream - * @param {any} connectionStream - the stream to mux - * @return {stream.Stream} the multiplexed stream - */ -function setupMultiplex(connectionStream) { - const mux = new ObjectMultiplex(); - pump(connectionStream, mux, connectionStream, (err) => { - if (err) { - console.warn(err); - } - }); - return mux; -} - -export { jsonParseStream, jsonStringifyStream, setupMultiplex }; From 1568ce800d9f82aefad43a2fa517a83dac4edc6a Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:01:58 +0000 Subject: [PATCH 3/9] Remove DEVIN_TODO comments and finalize TypeScript conversion --- app/util/streams.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/util/streams.ts b/app/util/streams.ts index 7bf46505faf..93dd1dbb87d 100644 --- a/app/util/streams.ts +++ b/app/util/streams.ts @@ -1,4 +1,3 @@ -/* eslint-disable import/no-commonjs */ import Through from 'through2'; import ObjectMultiplex from '@metamask/object-multiplex'; import pump from 'pump'; From e9ed7e205a4a9d75f03e6d1927684fc78e2f3099 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:16:04 +0000 Subject: [PATCH 4/9] chore: add @types/pump and @types/through2 as dev dependencies --- package.json | 2 ++ yarn.lock | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/package.json b/package.json index 3f6ab81ce81..73bb03d9ebc 100644 --- a/package.json +++ b/package.json @@ -416,6 +416,7 @@ "@types/jest": "^29.5.12", "@types/lodash": "^4.14.184", "@types/node": "^20.12.8", + "@types/pump": "^1.1.3", "@types/qs": "^6.9.15", "@types/react": "^17.0.11", "@types/react-native": "^0.64.10", @@ -427,6 +428,7 @@ "@types/react-native-vector-icons": "^6.4.13", "@types/react-native-video": "^5.0.14", "@types/redux-mock-store": "^1.0.3", + "@types/through2": "^2.0.41", "@types/url-parse": "^1.4.8", "@types/valid-url": "^1.0.4", "@typescript-eslint/eslint-plugin": "^7.10.0", diff --git a/yarn.lock b/yarn.lock index 2530ce065b8..3db92511f33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9814,6 +9814,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== +"@types/pump@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@types/pump/-/pump-1.1.3.tgz#127eeed2f416f89ef60697003486ae27c7f0b49e" + integrity sha512-ZyooTTivmOwPfOwLVaszkF8Zq6mvavgjuHYitZhrIjfQAJDH+kIP3N+MzpG1zDAslsHvVz6Q8ECfivix3qLJaQ== + dependencies: + "@types/node" "*" + "@types/punycode@^2.1.0": version "2.1.4" resolved "https://registry.yarnpkg.com/@types/punycode/-/punycode-2.1.4.tgz#96f8a47f1ee9fb0d0def5557fe80fac532f966fa" @@ -10087,6 +10094,13 @@ dependencies: "@types/node" "*" +"@types/through2@^2.0.41": + version "2.0.41" + resolved "https://registry.yarnpkg.com/@types/through2/-/through2-2.0.41.tgz#3e5e1720d71ffdfa03c22f2aad6593d12a47034f" + integrity sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ== + dependencies: + "@types/node" "*" + "@types/through@*": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" From ee832ffa000b99ed9341f83627f1e0d77ed0b31a Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:37:54 +0000 Subject: [PATCH 5/9] Add unit tests for streams.ts --- app/util/streams.test.ts | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 app/util/streams.test.ts diff --git a/app/util/streams.test.ts b/app/util/streams.test.ts new file mode 100644 index 00000000000..298904a62b4 --- /dev/null +++ b/app/util/streams.test.ts @@ -0,0 +1,88 @@ +import { jsonParseStream, jsonStringifyStream, setupMultiplex } from './streams'; +import Through from 'through2'; +import ObjectMultiplex from '@metamask/object-multiplex'; +import pump from 'pump'; + +jest.mock('through2'); +jest.mock('@metamask/object-multiplex'); +jest.mock('pump'); + +describe('streams', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('jsonParseStream', () => { + it('should parse JSON strings', (done) => { + const mockThrough = { + push: jest.fn(), + }; + (Through.obj as jest.Mock).mockImplementation((callback) => { + callback.call(mockThrough, '{"key":"value"}', null, () => {}); + return mockThrough; + }); + + const stream = jsonParseStream(); + expect(Through.obj).toHaveBeenCalled(); + expect(mockThrough.push).toHaveBeenCalledWith({ key: 'value' }); + done(); + }); + }); + + describe('jsonStringifyStream', () => { + it('should stringify objects', (done) => { + const mockThrough = { + push: jest.fn(), + }; + (Through.obj as jest.Mock).mockImplementation((callback) => { + callback.call(mockThrough, { key: 'value' }, null, () => {}); + return mockThrough; + }); + + const stream = jsonStringifyStream(); + expect(Through.obj).toHaveBeenCalled(); + expect(mockThrough.push).toHaveBeenCalledWith('{"key":"value"}'); + done(); + }); + }); + + describe('setupMultiplex', () => { + it('should set up stream multiplexing', () => { + const mockConnectionStream = {} as NodeJS.ReadWriteStream; + const mockMux = {} as NodeJS.ReadWriteStream; + + (ObjectMultiplex as jest.Mock).mockReturnValue(mockMux); + (pump as jest.Mock).mockImplementation((stream1, stream2, stream3, callback) => { + callback(null); + }); + + const result = setupMultiplex(mockConnectionStream); + + expect(ObjectMultiplex).toHaveBeenCalled(); + expect(pump).toHaveBeenCalledWith( + mockConnectionStream, + mockMux, + mockConnectionStream, + expect.any(Function) + ); + expect(result).toBe(mockMux); + }); + + it('should handle errors in pump', () => { + const mockConnectionStream = {} as NodeJS.ReadWriteStream; + const mockMux = {} as NodeJS.ReadWriteStream; + const mockError = new Error('Pump error'); + + (ObjectMultiplex as jest.Mock).mockReturnValue(mockMux); + (pump as jest.Mock).mockImplementation((stream1, stream2, stream3, callback) => { + callback(mockError); + }); + + console.warn = jest.fn(); + + setupMultiplex(mockConnectionStream); + + expect(console.warn).toHaveBeenCalledWith(mockError); + }); + }); +}); From e63514696bd7fb2f8f8a579be2eb4140191d1142 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:25:49 +0000 Subject: [PATCH 6/9] commit to trigger CI From 0b97956f58bc35daf8127d10d28a325cb1d59192 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:30:05 +0000 Subject: [PATCH 7/9] commit to trigger CI From 8cf744772bc92ef4c9a7d65a14f299c9a1de9e95 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:35:16 +0000 Subject: [PATCH 8/9] chore: Add error handling to streams and update tests --- app/util/streams.test.ts | 34 +++++++++++++++++++++++++++++++++- app/util/streams.ts | 20 ++++++++++++++------ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/app/util/streams.test.ts b/app/util/streams.test.ts index 298904a62b4..669a8bd40cb 100644 --- a/app/util/streams.test.ts +++ b/app/util/streams.test.ts @@ -27,6 +27,21 @@ describe('streams', () => { expect(mockThrough.push).toHaveBeenCalledWith({ key: 'value' }); done(); }); + + it('should handle JSON parse errors', (done) => { + const mockThrough = { + push: jest.fn(), + }; + const mockCallback = jest.fn(); + (Through.obj as jest.Mock).mockImplementation((callback) => { + callback.call(mockThrough, 'invalid json', null, mockCallback); + return mockThrough; + }); + + jsonParseStream(); + expect(mockCallback).toHaveBeenCalledWith(expect.any(Error)); + done(); + }); }); describe('jsonStringifyStream', () => { @@ -44,6 +59,23 @@ describe('streams', () => { expect(mockThrough.push).toHaveBeenCalledWith('{"key":"value"}'); done(); }); + + it('should handle stringify errors', (done) => { + const mockThrough = { + push: jest.fn(), + }; + const mockCallback = jest.fn(); + const circularObj: any = {}; + circularObj.circular = circularObj; + (Through.obj as jest.Mock).mockImplementation((callback) => { + callback.call(mockThrough, circularObj, null, mockCallback); + return mockThrough; + }); + + jsonStringifyStream(); + expect(mockCallback).toHaveBeenCalledWith(expect.any(Error)); + done(); + }); }); describe('setupMultiplex', () => { @@ -82,7 +114,7 @@ describe('streams', () => { setupMultiplex(mockConnectionStream); - expect(console.warn).toHaveBeenCalledWith(mockError); + expect(console.warn).toHaveBeenCalledWith('Multiplexing error:', mockError); }); }); }); diff --git a/app/util/streams.ts b/app/util/streams.ts index 93dd1dbb87d..d598ed1c866 100644 --- a/app/util/streams.ts +++ b/app/util/streams.ts @@ -19,8 +19,12 @@ function jsonParseStream(): NodeJS.ReadWriteStream { _: string, cb: TransformCallback ) { - this.push(JSON.parse(serialized)); - cb(); + try { + this.push(JSON.parse(serialized)); + cb(); + } catch (error) { + cb(error as Error); + } }); } @@ -36,8 +40,12 @@ function jsonStringifyStream(): NodeJS.ReadWriteStream { _: string, cb: TransformCallback ) { - this.push(JSON.stringify(obj)); - cb(); + try { + this.push(JSON.stringify(obj)); + cb(); + } catch (error) { + cb(error as Error); + } }); } @@ -50,10 +58,10 @@ function setupMultiplex(connectionStream: NodeJS.ReadWriteStream): NodeJS.ReadWr const mux = new ObjectMultiplex(); pump(connectionStream, mux, connectionStream, (err: Error | null) => { if (err) { - console.warn(err); + console.warn('Multiplexing error:', err); } }); - return mux as unknown as NodeJS.ReadWriteStream; + return mux; } export { jsonParseStream, jsonStringifyStream, setupMultiplex }; From 043e2ca02bfce92108360c5a14fc43380dce7d5a Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:58:02 +0000 Subject: [PATCH 9/9] fixing lint --- app/util/streams.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/util/streams.ts b/app/util/streams.ts index d598ed1c866..cbfd086ad0b 100644 --- a/app/util/streams.ts +++ b/app/util/streams.ts @@ -56,7 +56,7 @@ function jsonStringifyStream(): NodeJS.ReadWriteStream { */ function setupMultiplex(connectionStream: NodeJS.ReadWriteStream): NodeJS.ReadWriteStream { const mux = new ObjectMultiplex(); - pump(connectionStream, mux, connectionStream, (err: Error | null) => { + pump(connectionStream, mux, connectionStream, (err: Error | undefined) => { if (err) { console.warn('Multiplexing error:', err); }