From b902db686d11f76f3860bc7e52299546e0381487 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 12 Feb 2025 15:24:12 -0800 Subject: [PATCH 1/5] Speed up! --- libs/sdk-js/package.json | 1 + libs/sdk-js/src/utils/sse.ts | 89 ++++++++++++++++---------- libs/sdk-js/yarn.lock | 119 ++++++++++++++++++++++++++--------- 3 files changed, 147 insertions(+), 62 deletions(-) diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json index 8a682e772..c66e9bad0 100644 --- a/libs/sdk-js/package.json +++ b/libs/sdk-js/package.json @@ -33,6 +33,7 @@ "jest": "^29.7.0", "prettier": "^3.2.5", "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", "typedoc": "^0.26.1", "typedoc-plugin-markdown": "^4.1.0", "typescript": "^5.4.5", diff --git a/libs/sdk-js/src/utils/sse.ts b/libs/sdk-js/src/utils/sse.ts index fb1ff0f59..e585ecf86 100644 --- a/libs/sdk-js/src/utils/sse.ts +++ b/libs/sdk-js/src/utils/sse.ts @@ -15,12 +15,12 @@ const TRAILING_NEWLINE = [CR, LF]; export class BytesLineDecoder extends TransformStream { constructor() { - let buffer = new Uint8Array(); + let buffer: Uint8Array[] = []; let trailingCr = false; super({ start() { - buffer = new Uint8Array(); + buffer = []; trailingCr = false; }, @@ -43,44 +43,47 @@ export class BytesLineDecoder extends TransformStream { if (!text.length) return; const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1)!); - // Pre-allocate lines array with estimated capacity - let lines: Uint8Array[] = []; - - for (let offset = 0; offset < text.byteLength; ) { - let idx = text.indexOf(CR, offset); - if (idx === -1) idx = text.indexOf(LF, offset); - if (idx === -1) { - lines.push(text.subarray(offset)); - break; - } - - lines.push(text.subarray(offset, idx)); - if (text[idx] === CR && text[idx + 1] === LF) { - offset = idx + 2; - } else { - offset = idx + 1; - } - } + const lastIdx = text.length - 1; + const [lines] = text.reduce( + (acc, cur, idx) => { + if (cur === CR) { + if (text[idx + 1] === LF) { + acc[0].push(text.subarray(acc[1], idx)); + acc[1] = idx + 2; + } else { + acc[0].push(text.subarray(acc[1], idx)); + acc[1] = idx + 1; + } + } else if (cur === LF && text[idx - 1] !== CR) { + acc[0].push(text.subarray(acc[1], idx)); + acc[1] = idx + 1; + } + if (idx === lastIdx && acc[1] < lastIdx) { + acc[0].push(text.subarray(acc[1])); + } + return acc; + }, + [[], 0] as [Uint8Array[], number], + ); if (lines.length === 1 && !trailingNewline) { - buffer = mergeArrays(buffer, lines[0]); + buffer.push(lines[0]); return; } if (buffer.length) { // Include existing buffer in first line - buffer = mergeArrays(buffer, lines[0]); + buffer.push(lines[0]); - lines = lines.slice(1); - lines.unshift(buffer); + lines[0] = joinArrays(buffer); - buffer = new Uint8Array(); + buffer = []; } if (!trailingNewline) { // If the last segment is not newline terminated, // buffer it for the next chunk - if (lines.length) buffer = lines.pop()!; + if (lines.length) buffer = [lines.pop()!]; } // Enqueue complete lines @@ -91,7 +94,7 @@ export class BytesLineDecoder extends TransformStream { flush(controller) { if (buffer.length) { - controller.enqueue(buffer); + controller.enqueue(joinArrays(buffer)); } }, }); @@ -106,7 +109,7 @@ interface StreamPart { export class SSEDecoder extends TransformStream { constructor() { let event = ""; - let data: Uint8Array = new Uint8Array(); + let data: Uint8Array[] = []; let lastEventId = ""; let retry: number | null = null; @@ -120,12 +123,12 @@ export class SSEDecoder extends TransformStream { const sse = { event, - data: data.length ? JSON.parse(decoder.decode(data)) : null, + data: data.length ? decodeArraysToJson(decoder, data) : null, }; // NOTE: as per the SSE spec, do not reset lastEventId event = ""; - data = new Uint8Array(); + data = []; retry = null; controller.enqueue(sse); @@ -145,7 +148,7 @@ export class SSEDecoder extends TransformStream { if (fieldName === "event") { event = decoder.decode(value); } else if (fieldName === "data") { - data = mergeArrays(data, value); + data.push(value); } else if (fieldName === "id") { if (value.indexOf(NULL) === -1) lastEventId = decoder.decode(value); } else if (fieldName === "retry") { @@ -158,10 +161,32 @@ export class SSEDecoder extends TransformStream { if (event) { controller.enqueue({ event, - data: data.length ? JSON.parse(decoder.decode(data)) : null, + data: data.length ? decodeArraysToJson(decoder, data) : null, }); } }, }); } } + +function decodeArraysToJson(decoder: TextDecoder, arrays: Uint8Array[]) { + const totalLength = arrays.reduce((acc, curr) => acc + curr.length, 0); + let merged = new Uint8Array(totalLength); + let offset = 0; + for (const c of arrays) { + merged.set(c, offset); + offset += c.length; + } + return JSON.parse(decoder.decode(merged)); +} + +function joinArrays(arrays: Uint8Array[]) { + const totalLength = arrays.reduce((acc, curr) => acc + curr.length, 0); + let merged = new Uint8Array(totalLength); + let offset = 0; + for (const c of arrays) { + merged.set(c, offset); + offset += c.length; + } + return merged; +} diff --git a/libs/sdk-js/yarn.lock b/libs/sdk-js/yarn.lock index 4d4e4ccf8..b3209d5d6 100644 --- a/libs/sdk-js/yarn.lock +++ b/libs/sdk-js/yarn.lock @@ -530,7 +530,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -545,6 +545,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -860,6 +868,26 @@ mkdirp "^3.0.1" path-browserify "^1.0.1" +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@tsconfig/recommended@^1.0.2": version "1.0.6" resolved "https://registry.yarnpkg.com/@tsconfig/recommended/-/recommended-1.0.6.tgz#217b78f9601215939d566a79d202a760ae185114" @@ -1023,6 +1051,18 @@ dependencies: "@types/yargs-parser" "*" +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + anchor-markdown-header@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.6.0.tgz#908f2031281766f44ac350380ca0de77ab7065b8" @@ -1079,6 +1119,11 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1477,6 +1522,11 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.0: version "7.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.5.tgz#910aac880ff5243da96b728bc6521a5f6c2f2f82" @@ -1597,6 +1647,11 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -2992,7 +3047,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@^1.3.6: +make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -3958,16 +4013,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4013,14 +4059,7 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4150,6 +4189,25 @@ ts-morph@^21.0.1: "@ts-morph/common" "~0.22.0" code-block-writer "^12.0.0" +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -4342,6 +4400,11 @@ uuid@^9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-to-istanbul@^9.0.1: version "9.3.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" @@ -4413,16 +4476,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -4496,6 +4550,11 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 4ce387ee28a261ece764cf8f9c4473e42c0f1418 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 12 Feb 2025 15:31:40 -0800 Subject: [PATCH 2/5] test --- libs/sdk-js/src/utils/sse.ts | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/libs/sdk-js/src/utils/sse.ts b/libs/sdk-js/src/utils/sse.ts index e585ecf86..0c6ccdc92 100644 --- a/libs/sdk-js/src/utils/sse.ts +++ b/libs/sdk-js/src/utils/sse.ts @@ -44,26 +44,25 @@ export class BytesLineDecoder extends TransformStream { const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1)!); const lastIdx = text.length - 1; - const [lines] = text.reduce( + const { lines } = text.reduce( (acc, cur, idx) => { - if (cur === CR) { - if (text[idx + 1] === LF) { - acc[0].push(text.subarray(acc[1], idx)); - acc[1] = idx + 2; - } else { - acc[0].push(text.subarray(acc[1], idx)); - acc[1] = idx + 1; - } - } else if (cur === LF && text[idx - 1] !== CR) { - acc[0].push(text.subarray(acc[1], idx)); - acc[1] = idx + 1; + if (acc.from > idx) return acc; + + if (cur === CR && text[idx + 1] === LF) { + acc.lines.push(text.subarray(acc.from, idx)); + acc.from = idx + 2; + } else if (cur === CR || cur === LF) { + acc.lines.push(text.subarray(acc.from, idx)); + acc.from = idx + 1; } - if (idx === lastIdx && acc[1] < lastIdx) { - acc[0].push(text.subarray(acc[1])); + + if (idx === lastIdx && acc.from < lastIdx) { + acc.lines.push(text.subarray(acc.from)); } + return acc; }, - [[], 0] as [Uint8Array[], number], + { lines: [], from: 0 } as { lines: Uint8Array[]; from: number }, ); if (lines.length === 1 && !trailingNewline) { From 7db81d72dc6fdfad28cf86d89b2c39ca62957505 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 12 Feb 2025 15:42:59 -0800 Subject: [PATCH 3/5] Cleanup --- libs/sdk-js/src/tests/sse.test.ts | 62 ++++++++++++++----------------- libs/sdk-js/src/utils/sse.ts | 17 +++++---- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/libs/sdk-js/src/tests/sse.test.ts b/libs/sdk-js/src/tests/sse.test.ts index 51ebbbd0c..b4f7ca7d8 100644 --- a/libs/sdk-js/src/tests/sse.test.ts +++ b/libs/sdk-js/src/tests/sse.test.ts @@ -2,26 +2,21 @@ import { Readable } from "node:stream"; import { IterableReadableStream } from "../utils/stream.js"; import { BytesLineDecoder, SSEDecoder } from "../utils/sse.js"; +const gather = async (stream: ReadableStream): Promise => { + const results: T[] = []; + const iterator = IterableReadableStream.fromReadableStream(stream); + for await (const chunk of iterator) results.push(chunk); + return results; +}; + +const textEncoder = new TextEncoder(); +const textDecoder = new TextDecoder(); + describe("BytesLineDecoder", () => { const createStream = (chunks: Uint8Array[]) => { return Readable.toWeb(Readable.from(chunks)) as ReadableStream; }; - const gather = async ( - stream: ReadableStream, - ): Promise => { - const results: Uint8Array[] = []; - for await (const chunk of IterableReadableStream.fromReadableStream( - stream, - )) { - results.push(chunk); - } - return results; - }; - - const textEncoder = new TextEncoder(); - const textDecoder = new TextDecoder(); - test("handles single line with newline", async () => { const input = createStream([textEncoder.encode("hello\n")]); const decoded = input.pipeThrough(new BytesLineDecoder()); @@ -78,25 +73,22 @@ describe("BytesLineDecoder", () => { expect(textDecoder.decode(results[0])).toBe("line1"); expect(textDecoder.decode(results[1])).toBe("line2"); }); + + test("handles stale line", async () => { + const input = createStream([textEncoder.encode("hello")]); + const decoded = input.pipeThrough(new BytesLineDecoder()); + const results = await gather(decoded); + + expect(results.length).toBe(1); + expect(textDecoder.decode(results[0])).toBe("hello"); + }); }); describe("SSEDecoder", () => { const createStream = (lines: string[]) => { - const encoder = new TextEncoder(); - const chunks = lines.map((line) => encoder.encode(line)); - return Readable.toWeb(Readable.from(chunks)) as ReadableStream; - }; - - const collectResults = async ( - stream: ReadableStream, - ): Promise => { - const results: any[] = []; - for await (const chunk of IterableReadableStream.fromReadableStream( - stream, - )) { - results.push(chunk); - } - return results; + return Readable.toWeb( + Readable.from(lines.map((line) => textEncoder.encode(line))), + ) as ReadableStream; }; test("decodes simple event", async () => { @@ -109,7 +101,7 @@ describe("SSEDecoder", () => { .pipeThrough(new BytesLineDecoder()) .pipeThrough(new SSEDecoder()); - const results = await collectResults(decoded); + const results = await gather(decoded); expect(results.length).toBe(1); expect(results[0]).toEqual({ event: "test", @@ -127,7 +119,7 @@ describe("SSEDecoder", () => { .pipeThrough(new BytesLineDecoder()) .pipeThrough(new SSEDecoder()); - const results = await collectResults(decoded); + const results = await gather(decoded); expect(results.length).toBe(1); expect(results[0]).toEqual({ event: "test", @@ -148,7 +140,7 @@ describe("SSEDecoder", () => { .pipeThrough(new BytesLineDecoder()) .pipeThrough(new SSEDecoder()); - const results = await collectResults(decoded); + const results = await gather(decoded); expect(results.length).toBe(2); expect(results[0]).toEqual({ event: "test1", @@ -166,7 +158,7 @@ describe("SSEDecoder", () => { .pipeThrough(new BytesLineDecoder()) .pipeThrough(new SSEDecoder()); - const results = await collectResults(decoded); + const results = await gather(decoded); expect(results.length).toBe(1); expect(results[0]).toEqual({ event: "test", @@ -180,7 +172,7 @@ describe("SSEDecoder", () => { .pipeThrough(new BytesLineDecoder()) .pipeThrough(new SSEDecoder()); - const results = await collectResults(decoded); + const results = await gather(decoded); expect(results.length).toBe(1); expect(results[0]).toEqual({ event: "end", diff --git a/libs/sdk-js/src/utils/sse.ts b/libs/sdk-js/src/utils/sse.ts index 0c6ccdc92..2df40a1df 100644 --- a/libs/sdk-js/src/utils/sse.ts +++ b/libs/sdk-js/src/utils/sse.ts @@ -44,25 +44,26 @@ export class BytesLineDecoder extends TransformStream { const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1)!); const lastIdx = text.length - 1; - const { lines } = text.reduce( + const { lines } = text.reduce<{ lines: Uint8Array[]; from: number }>( (acc, cur, idx) => { if (acc.from > idx) return acc; - if (cur === CR && text[idx + 1] === LF) { + if (cur === CR || cur === LF) { acc.lines.push(text.subarray(acc.from, idx)); - acc.from = idx + 2; - } else if (cur === CR || cur === LF) { - acc.lines.push(text.subarray(acc.from, idx)); - acc.from = idx + 1; + if (cur === CR && text[idx + 1] === LF) { + acc.from = idx + 2; + } else { + acc.from = idx + 1; + } } - if (idx === lastIdx && acc.from < lastIdx) { + if (idx === lastIdx && acc.from <= lastIdx) { acc.lines.push(text.subarray(acc.from)); } return acc; }, - { lines: [], from: 0 } as { lines: Uint8Array[]; from: number }, + { lines: [], from: 0 }, ); if (lines.length === 1 && !trailingNewline) { From da1fae0c72ead6becf2220afab800e73e591622f Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 12 Feb 2025 15:50:36 -0800 Subject: [PATCH 4/5] Cleanup --- libs/sdk-js/src/utils/sse.ts | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/libs/sdk-js/src/utils/sse.ts b/libs/sdk-js/src/utils/sse.ts index 2df40a1df..c3c525113 100644 --- a/libs/sdk-js/src/utils/sse.ts +++ b/libs/sdk-js/src/utils/sse.ts @@ -1,10 +1,3 @@ -const mergeArrays = (a: ArrayLike, b: ArrayLike) => { - const mergedArray = new Uint8Array(a.length + b.length); - mergedArray.set(a); - mergedArray.set(b, a.length); - return mergedArray; -}; - const CR = "\r".charCodeAt(0); const LF = "\n".charCodeAt(0); const NULL = "\0".charCodeAt(0); @@ -30,7 +23,7 @@ export class BytesLineDecoder extends TransformStream { // Handle trailing CR from previous chunk if (trailingCr) { - text = mergeArrays([CR], text); + text = joinArrays([[CR], text]); trailingCr = false; } @@ -74,9 +67,7 @@ export class BytesLineDecoder extends TransformStream { if (buffer.length) { // Include existing buffer in first line buffer.push(lines[0]); - lines[0] = joinArrays(buffer); - buffer = []; } @@ -169,24 +160,17 @@ export class SSEDecoder extends TransformStream { } } -function decodeArraysToJson(decoder: TextDecoder, arrays: Uint8Array[]) { - const totalLength = arrays.reduce((acc, curr) => acc + curr.length, 0); +function joinArrays(data: ArrayLike[]) { + const totalLength = data.reduce((acc, curr) => acc + curr.length, 0); let merged = new Uint8Array(totalLength); let offset = 0; - for (const c of arrays) { - merged.set(c, offset); - offset += c.length; - } - return JSON.parse(decoder.decode(merged)); -} - -function joinArrays(arrays: Uint8Array[]) { - const totalLength = arrays.reduce((acc, curr) => acc + curr.length, 0); - let merged = new Uint8Array(totalLength); - let offset = 0; - for (const c of arrays) { + for (const c of data) { merged.set(c, offset); offset += c.length; } return merged; } + +function decodeArraysToJson(decoder: TextDecoder, data: ArrayLike[]) { + return JSON.parse(decoder.decode(joinArrays(data))); +} From 5091d5e9fe644eed67392f5b5f41e451f9374957 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Wed, 12 Feb 2025 15:56:01 -0800 Subject: [PATCH 5/5] Remove ts-node --- libs/sdk-js/package.json | 1 - libs/sdk-js/yarn.lock | 119 ++++++++++----------------------------- 2 files changed, 30 insertions(+), 90 deletions(-) diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json index c66e9bad0..8a682e772 100644 --- a/libs/sdk-js/package.json +++ b/libs/sdk-js/package.json @@ -33,7 +33,6 @@ "jest": "^29.7.0", "prettier": "^3.2.5", "ts-jest": "^29.1.2", - "ts-node": "^10.9.2", "typedoc": "^0.26.1", "typedoc-plugin-markdown": "^4.1.0", "typescript": "^5.4.5", diff --git a/libs/sdk-js/yarn.lock b/libs/sdk-js/yarn.lock index b3209d5d6..4d4e4ccf8 100644 --- a/libs/sdk-js/yarn.lock +++ b/libs/sdk-js/yarn.lock @@ -530,7 +530,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -545,14 +545,6 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -868,26 +860,6 @@ mkdirp "^3.0.1" path-browserify "^1.0.1" -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - "@tsconfig/recommended@^1.0.2": version "1.0.6" resolved "https://registry.yarnpkg.com/@tsconfig/recommended/-/recommended-1.0.6.tgz#217b78f9601215939d566a79d202a760ae185114" @@ -1051,18 +1023,6 @@ dependencies: "@types/yargs-parser" "*" -acorn-walk@^8.1.1: - version "8.3.4" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" - integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== - dependencies: - acorn "^8.11.0" - -acorn@^8.11.0, acorn@^8.4.1: - version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" - integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== - anchor-markdown-header@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.6.0.tgz#908f2031281766f44ac350380ca0de77ab7065b8" @@ -1119,11 +1079,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1522,11 +1477,6 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - cross-spawn@^7.0.0: version "7.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.5.tgz#910aac880ff5243da96b728bc6521a5f6c2f2f82" @@ -1647,11 +1597,6 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3047,7 +2992,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@^1.1.1, make-error@^1.3.6: +make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4013,7 +3958,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4059,7 +4013,14 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4189,25 +4150,6 @@ ts-morph@^21.0.1: "@ts-morph/common" "~0.22.0" code-block-writer "^12.0.0" -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -4400,11 +4342,6 @@ uuid@^9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - v8-to-istanbul@^9.0.1: version "9.3.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" @@ -4476,7 +4413,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -4550,11 +4496,6 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"