diff --git a/.changeset/mighty-snails-report.md b/.changeset/mighty-snails-report.md new file mode 100644 index 0000000..08133c4 --- /dev/null +++ b/.changeset/mighty-snails-report.md @@ -0,0 +1,5 @@ +--- +"@hsblabs/web-stream-extras": patch +--- + +refactor: consolidate shared module exports and reorganize internal file structure diff --git a/.vscode/settings.json b/.vscode/settings.json index e46280a..d0c86c4 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.biome": "explicit", - "source.organizeImports.biome": "explicit" + "source.organizeImports.biome": "explicit", + "source.organizeImports": "never" } } diff --git a/package.json b/package.json index 8211f90..a0575d5 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,12 @@ ], "exports": { ".": "./dist/index.js", - "./base64": "./dist/base64.js", - "./cobs": "./dist/cobs.js", - "./encryption": "./dist/encryption.js", - "./jsonl": "./dist/jsonl.js", - "./png": "./dist/png.js", - "./text": "./dist/text.js", + "./base64": "./dist/base64/index.js", + "./cobs": "./dist/cobs/index.js", + "./encryption": "./dist/encryption/index.js", + "./jsonl": "./dist/jsonl/index.js", + "./png": "./dist/png/index.js", + "./text": "./dist/text/index.js", "./package.json": "./package.json" }, "types": "./dist/index.d.ts", diff --git a/src/base64.ts b/src/base64.ts deleted file mode 100644 index 9d11a95..0000000 --- a/src/base64.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type { - Base64DecodeStreamOptions, - Base64EncodeStreamOptions, - Base64InputChunk, - Base64Variant, -} from "./base64/public"; - -export { - Base64DecodeStream, - Base64EncodeStream, - decodeBase64Stream, - decodeBase64UrlStream, - encodeBase64Stream, - encodeBase64UrlStream, -} from "./base64/public"; diff --git a/src/base64.test.ts b/src/base64/index.test.ts similarity index 99% rename from src/base64.test.ts rename to src/base64/index.test.ts index 531c879..1c2956a 100644 --- a/src/base64.test.ts +++ b/src/base64/index.test.ts @@ -1,4 +1,11 @@ import { describe, expect, it } from "vitest"; +import { + binaryToString, + readAllBytes, + readAllChunks, + readableFromChunks, + stringToBinary, +} from "../shared"; import { Base64DecodeStream, Base64EncodeStream, @@ -6,13 +13,6 @@ import { decodeBase64UrlStream, encodeBase64Stream, encodeBase64UrlStream, -} from "./base64"; -import { - binaryToString, - readAllBytes, - readAllChunks, - readableFromChunks, - stringToBinary, } from "./index"; describe("base64", () => { diff --git a/src/base64/public.ts b/src/base64/index.ts similarity index 100% rename from src/base64/public.ts rename to src/base64/index.ts diff --git a/src/cobs.ts b/src/cobs.ts deleted file mode 100644 index 6be67b3..0000000 --- a/src/cobs.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { - createCOBSDecoderStream, - createCOBSEncoderStream, - decodeCOBSFrame, - encodeCOBSFrame, - readCOBS, - writeCOBS, -} from "./cobs/public"; diff --git a/src/cobs.test.ts b/src/cobs/index.test.ts similarity index 97% rename from src/cobs.test.ts rename to src/cobs/index.test.ts index c642ccf..eda14d5 100644 --- a/src/cobs.test.ts +++ b/src/cobs/index.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; -import * as cobsApi from "./cobs"; +import { readAllBytes, readAllChunks, readableFromChunks } from "../shared"; +import * as cobsApi from "./index"; import { createCOBSDecoderStream, createCOBSEncoderStream, @@ -7,8 +8,7 @@ import { encodeCOBSFrame, readCOBS, writeCOBS, -} from "./cobs"; -import { readAllBytes, readAllChunks, readableFromChunks } from "./readable"; +} from "./index"; describe("cobs public API", () => { it("exports the supported cobs helpers", () => { diff --git a/src/cobs/public.ts b/src/cobs/index.ts similarity index 100% rename from src/cobs/public.ts rename to src/cobs/index.ts diff --git a/src/encryption.ts b/src/encryption.ts deleted file mode 100644 index e0ba5a1..0000000 --- a/src/encryption.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type { - EncryptionStreamOptions, - WebCryptoStream, -} from "./encryption/public"; -export { - DecryptionStream, - decryptStream, - EncryptionStream, - encryptStream, - webCryptoStream, -} from "./encryption/public"; diff --git a/src/encryption.test.ts b/src/encryption/index.test.ts similarity index 99% rename from src/encryption.test.ts rename to src/encryption/index.test.ts index 3a1f309..182a267 100644 --- a/src/encryption.test.ts +++ b/src/encryption/index.test.ts @@ -1,18 +1,18 @@ import { describe, expect, it } from "vitest"; -import { - DecryptionStream, - decryptStream, - EncryptionStream, - encryptStream, - webCryptoStream, -} from "./encryption"; -import { HEADER_SIZE, TAG_LENGTH } from "./encryption/constants"; import { binaryToString, randomBytes, readAllBytes, readableFromChunks, stringToBinary, +} from "../shared"; +import { HEADER_SIZE, TAG_LENGTH } from "./constants"; +import { + DecryptionStream, + decryptStream, + EncryptionStream, + encryptStream, + webCryptoStream, } from "./index"; const TEST_RECORD_SIZE = 64; diff --git a/src/encryption/public.ts b/src/encryption/index.ts similarity index 97% rename from src/encryption/public.ts rename to src/encryption/index.ts index b6f3683..f9571f5 100644 --- a/src/encryption/public.ts +++ b/src/encryption/index.ts @@ -2,9 +2,9 @@ import { toArrayBuffer } from "../shared/array-buffer"; import { decodeBase64Url, encodeBase64Url } from "../shared/base64url"; import { randomBytes } from "../shared/binary"; import { throwError } from "../shared/error"; +import type { BinaryReadableStream } from "../shared/stream"; +import { ByteTransformStream } from "../shared/stream"; import { concatU8Arrays, toU8Array } from "../shared/uint8array"; -import type { BinaryReadableStream } from "../stream-types"; -import { ByteTransformStream } from "../transform-stream"; import { AES_GCM_BIT_LENGTH, ALGORITHM_AES_GCM, diff --git a/src/index.ts b/src/index.ts index 4605970..545ca84 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,17 @@ -export { readAllBytes, readAllChunks, readableFromChunks } from "./readable"; +export * from "./base64"; +export * from "./byte-queue"; +export * from "./cobs"; +export * from "./encryption"; +export * from "./jsonl"; +export * from "./png"; export { binaryToString, randomBytes, stringToBinary, } from "./shared/binary"; +export { + readAllBytes, + readAllChunks, + readableFromChunks, +} from "./shared/readable"; +export * from "./text"; diff --git a/src/jsonl.ts b/src/jsonl.ts deleted file mode 100644 index f684f6a..0000000 --- a/src/jsonl.ts +++ /dev/null @@ -1,15 +0,0 @@ -export type { - JSONLInputChunk, - JSONLParseStreamOptions, - JSONLStringifyStreamOptions, -} from "./jsonl/public"; - -export { - encodeJSONLStream, - JSONLEncodeStream, - JSONLParseError, - JSONLParseStream, - JSONLStringifyStream, - parseJSONLStream, - stringifyJSONLStream, -} from "./jsonl/public"; diff --git a/src/jsonl.test.ts b/src/jsonl/index.test.ts similarity index 99% rename from src/jsonl.test.ts rename to src/jsonl/index.test.ts index 18c1914..70ce3cb 100644 --- a/src/jsonl.test.ts +++ b/src/jsonl/index.test.ts @@ -5,7 +5,7 @@ import { readAllChunks, readableFromChunks, stringToBinary, -} from "./index"; +} from "../shared"; import { encodeJSONLStream, JSONLEncodeStream, @@ -14,7 +14,7 @@ import { JSONLStringifyStream, parseJSONLStream, stringifyJSONLStream, -} from "./jsonl"; +} from "./index"; type Event = { id: string; diff --git a/src/jsonl/public.ts b/src/jsonl/index.ts similarity index 100% rename from src/jsonl/public.ts rename to src/jsonl/index.ts diff --git a/src/png.ts b/src/png.ts deleted file mode 100644 index e5d60f3..0000000 --- a/src/png.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type { - PNGTextChunkWriteOptions, - PNGTextChunkWriter, -} from "./png/public"; -export { - createPNGTextChunkWriter, - extractPNGTextChunk, - streamPNGTextChunk, -} from "./png/public"; diff --git a/src/png/framing.ts b/src/png/framing.ts index 93a3022..0b578db 100644 --- a/src/png/framing.ts +++ b/src/png/framing.ts @@ -1,4 +1,4 @@ -import { decodeCOBSFrame, encodeCOBSFrame } from "../cobs/public"; +import { decodeCOBSFrame, encodeCOBSFrame } from "../cobs"; import { throwError } from "../shared/error"; import { concatU8Arrays } from "../shared/uint8array"; import { diff --git a/src/png.test.ts b/src/png/index.test.ts similarity index 99% rename from src/png.test.ts rename to src/png/index.test.ts index c979e66..0d17829 100644 --- a/src/png.test.ts +++ b/src/png/index.test.ts @@ -1,14 +1,14 @@ import { describe, expect, it } from "vitest"; -import { decodeCOBSFrame, encodeCOBSFrame } from "./cobs"; -import * as pngApi from "./png"; +import { decodeCOBSFrame, encodeCOBSFrame } from "../cobs"; +import { readAllBytes, readableFromChunks } from "../shared"; import { PNG_INTERNAL_TEXT_CHUNK_KEYWORD, PNG_PAYLOAD_MAGIC, PNG_PAYLOAD_SEGMENT_DATA_MAX_LENGTH, PNG_PAYLOAD_VERSION, PNG_SIGNATURE, -} from "./png/constants"; -import { crc32 } from "./png/crc32"; +} from "./constants"; +import { crc32 } from "./crc32"; import { createChunk, createPayloadDataSegment, @@ -18,13 +18,13 @@ import { isInternalTextChunk, parsePayloadSegment, parsePNGBytes, -} from "./png/framing"; +} from "./framing"; +import * as pngApi from "./index"; import { createPNGTextChunkWriter, extractPNGTextChunk, streamPNGTextChunk, -} from "./png/public"; -import { readAllBytes, readableFromChunks } from "./readable"; +} from "./index"; const MINIMAL_PNG = concatBytes( PNG_SIGNATURE, diff --git a/src/png/public.ts b/src/png/index.ts similarity index 100% rename from src/png/public.ts rename to src/png/index.ts diff --git a/src/png/transformers.ts b/src/png/transformers.ts index 13337d8..2c68211 100644 --- a/src/png/transformers.ts +++ b/src/png/transformers.ts @@ -1,6 +1,7 @@ import { type ByteQueue, createByteQueue } from "../byte-queue"; import { throwError } from "../shared/error"; import { concatU8Arrays } from "../shared/uint8array"; +import type { PNGTextChunkWriteOptions, PNGTextChunkWriter } from "."; import { PNG_IEND_CHUNK_TYPE, PNG_PAYLOAD_SEGMENT_DATA_MAX_LENGTH, @@ -18,7 +19,6 @@ import { parsePNGChunk, parsePNGChunkHeader, } from "./framing"; -import type { PNGTextChunkWriteOptions, PNGTextChunkWriter } from "./public"; interface Deferred { promise: Promise; diff --git a/src/public-api.test.ts b/src/public-api.test.ts deleted file mode 100644 index cc8f800..0000000 --- a/src/public-api.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { describe, expect, it } from "vitest"; -import * as base64Api from "./base64"; -import * as rootApi from "./index"; -import * as jsonlApi from "./jsonl"; -import * as textApi from "./text"; - -describe("root public API", () => { - it("only exports the supported high-level helpers", () => { - expect(Object.keys(rootApi).sort()).toEqual([ - "binaryToString", - "randomBytes", - "readAllBytes", - "readAllChunks", - "readableFromChunks", - "stringToBinary", - ]); - }); -}); - -describe("jsonl public API", () => { - it("only exports the supported JSONL stream helpers", () => { - expect(Object.keys(jsonlApi).sort()).toEqual([ - "JSONLEncodeStream", - "JSONLParseError", - "JSONLParseStream", - "JSONLStringifyStream", - "encodeJSONLStream", - "parseJSONLStream", - "stringifyJSONLStream", - ]); - }); -}); - -describe("text public API", () => { - it("only exports the supported text stream helpers", () => { - expect(Object.keys(textApi).sort()).toEqual([ - "LineJoinStream", - "LineSplitStream", - "TextDecodeStream", - "TextEncodeStream", - "decodeTextStream", - "encodeTextStream", - "joinLinesStream", - "splitLinesStream", - ]); - }); -}); - -describe("base64 public API", () => { - it("only exports the supported base64 stream helpers", () => { - expect(Object.keys(base64Api).sort()).toEqual([ - "Base64DecodeStream", - "Base64EncodeStream", - "decodeBase64Stream", - "decodeBase64UrlStream", - "encodeBase64Stream", - "encodeBase64UrlStream", - ]); - }); -}); diff --git a/src/readable.ts b/src/readable.ts deleted file mode 100644 index 696e62a..0000000 --- a/src/readable.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { concatU8Arrays } from "./shared/uint8array"; -import type { BinaryReadableStream } from "./stream-types"; - -export function readableFromChunks(chunks: T | T[]): ReadableStream { - const queue = Array.isArray(chunks) ? chunks : [chunks]; - - return new ReadableStream({ - start(controller) { - for (const chunk of queue) { - controller.enqueue(chunk); - } - controller.close(); - }, - }); -} - -export async function readAllChunks( - stream: ReadableStream, -): Promise { - const reader = stream.getReader(); - const chunks: T[] = []; - - while (true) { - const { done, value } = await reader.read(); - if (done) { - return chunks; - } - chunks.push(value); - } -} - -export async function readAllBytes( - stream: BinaryReadableStream, -): Promise { - return concatU8Arrays(...(await readAllChunks(stream))); -} diff --git a/src/shared/index.ts b/src/shared/index.ts new file mode 100644 index 0000000..a76ad20 --- /dev/null +++ b/src/shared/index.ts @@ -0,0 +1,13 @@ +export { toArrayBuffer } from "./array-buffer"; + +export { + binaryToString, + randomBytes, + stringToBinary, +} from "./binary"; + +export { + readAllBytes, + readAllChunks, + readableFromChunks, +} from "./readable"; diff --git a/src/shared/readable.ts b/src/shared/readable.ts index 538b708..3b4ad65 100644 --- a/src/shared/readable.ts +++ b/src/shared/readable.ts @@ -1,4 +1,6 @@ import { isInstance } from "./is"; +import type { BinaryReadableStream } from "./stream"; +import { concatU8Arrays } from "./uint8array"; export function toReadableStream( input: ReadableStream | Iterable | AsyncIterable, @@ -32,6 +34,40 @@ export function toReadableStream( }); } +export function readableFromChunks(chunks: T | T[]): ReadableStream { + const queue = Array.isArray(chunks) ? chunks : [chunks]; + + return new ReadableStream({ + start(controller) { + for (const chunk of queue) { + controller.enqueue(chunk); + } + controller.close(); + }, + }); +} + +export async function readAllChunks( + stream: ReadableStream, +): Promise { + const reader = stream.getReader(); + const chunks: T[] = []; + + while (true) { + const { done, value } = await reader.read(); + if (done) { + return chunks; + } + chunks.push(value); + } +} + +export async function readAllBytes( + stream: BinaryReadableStream, +): Promise { + return concatU8Arrays(...(await readAllChunks(stream))); +} + async function* toAsyncIterator(iterator: Iterator): AsyncGenerator { while (true) { const result = iterator.next(); diff --git a/src/transform-stream.ts b/src/shared/stream.ts similarity index 57% rename from src/transform-stream.ts rename to src/shared/stream.ts index ab2bcb5..f57d2dd 100644 --- a/src/transform-stream.ts +++ b/src/shared/stream.ts @@ -1,3 +1,5 @@ +export type BinaryReadableStream = ReadableStream; + export class ByteTransformStream extends TransformStream< Uint8Array, Uint8Array diff --git a/src/stream-types.ts b/src/stream-types.ts deleted file mode 100644 index f3d6c2f..0000000 --- a/src/stream-types.ts +++ /dev/null @@ -1 +0,0 @@ -export type BinaryReadableStream = ReadableStream; diff --git a/src/text.ts b/src/text.ts deleted file mode 100644 index 99916f6..0000000 --- a/src/text.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type { - LineJoinStreamOptions, - LineSplitStreamOptions, - TextDecodeStreamOptions, - TextInputChunk, -} from "./text/public"; - -export { - decodeTextStream, - encodeTextStream, - joinLinesStream, - LineJoinStream, - LineSplitStream, - splitLinesStream, - TextDecodeStream, - TextEncodeStream, -} from "./text/public"; diff --git a/src/text.test.ts b/src/text/index.test.ts similarity index 99% rename from src/text.test.ts rename to src/text/index.test.ts index f0b15d4..b25e20e 100644 --- a/src/text.test.ts +++ b/src/text/index.test.ts @@ -5,7 +5,7 @@ import { readAllChunks, readableFromChunks, stringToBinary, -} from "./index"; +} from "../shared"; import { decodeTextStream, encodeTextStream, @@ -14,7 +14,7 @@ import { splitLinesStream, TextDecodeStream, TextEncodeStream, -} from "./text"; +} from "./index"; describe("text", () => { it("decodes UTF-8 chunks split inside a multibyte character", async () => { diff --git a/src/text/public.ts b/src/text/index.ts similarity index 100% rename from src/text/public.ts rename to src/text/index.ts diff --git a/tsdown.config.ts b/tsdown.config.ts index cf0349a..966d84e 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,12 +3,12 @@ import { defineConfig } from "tsdown"; export default defineConfig({ entry: [ "src/index.ts", - "src/base64.ts", - "src/encryption.ts", - "src/jsonl.ts", - "src/text.ts", - "src/png.ts", - "src/cobs.ts", + "src/base64/index.ts", + "src/encryption/index.ts", + "src/jsonl/index.ts", + "src/text/index.ts", + "src/png/index.ts", + "src/cobs/index.ts", ], outDir: "dist", target: "es2022",