UNPKG

sflow

Version:

sflow is a powerful and highly-extensible library designed for processing and manipulating streams of data effortlessly. Inspired by the functional programming paradigm, it provides a rich set of utilities for transforming streams, including chunking, fil

94 lines (88 loc) 2.68 kB
//#region src/chunkIfs.ts /** chunk items if condition is true */ function chunkIfs(predicate, { inclusive = false } = {}) { const chunks = []; let i = 0; return new TransformStream({ transform: async (chunk, ctrl) => { const cond = await predicate(chunk, i++, chunks); if (!inclusive && !cond) { if (chunks.length) ctrl.enqueue(chunks.splice(0, Infinity)); } chunks.push(chunk); if (!cond) ctrl.enqueue(chunks.splice(0, Infinity)); }, flush: async (ctrl) => { if (chunks.length) ctrl.enqueue(chunks); } }); } //#endregion //#region src/maps.ts function maps(fn, options) { const concurrency = options?.concurrency ?? 1; if (concurrency === 1) { let i = 0; return new TransformStream({ transform: async (chunk, ctrl) => { const ret = fn(chunk, i++); const val = ret instanceof Promise ? await ret : ret; ctrl.enqueue(val); } }); } let i = 0; const promises = []; return new TransformStream({ transform: async (chunk, ctrl) => { promises.push(fn(chunk, i++)); if (promises.length >= concurrency) ctrl.enqueue(await promises.shift()); }, flush: async (ctrl) => { while (promises.length) ctrl.enqueue(await promises.shift()); } }); } //#endregion //#region src/flatMaps.ts function flatMaps(fn) { let i = 0; return new TransformStream({ transform: async (chunk, ctrl) => { const ret = fn(chunk, i++); (ret instanceof Promise ? await ret : ret).map((e) => ctrl.enqueue(e)); } }); } //#endregion //#region src/throughs.ts /** pipe upstream through a transform stream */ const throughs = (arg) => { if (!arg) return new TransformStream(); if (typeof arg !== "function") return throughs((s) => s.pipeThrough(arg)); const fn = arg; const { writable, readable } = new TransformStream(); return { writable, readable: fn(readable) }; }; //#endregion //#region src/lines.ts /** split string stream into lines stream, handy to concat LLM's tokens stream into line by line stream or split a long string by lines */ const lines = ({ EOL = "KEEP" } = {}) => { const CRLFMap = { KEEP: "$1", LF: "\n", CRLF: "\r\n", NONE: "" }; return throughs((r) => r.pipeThrough(flatMaps((s) => s.split(/(?<=\n)/g))).pipeThrough(chunkIfs((ch) => ch.indexOf("\n") === -1, { inclusive: true })).pipeThrough(maps((chunks) => chunks.join("").replace(/(\r?\n?)$/, CRLFMap[EOL])))); }; //#endregion //#region src/skips.ts function skips(n = 1) { return new TransformStream({ transform: async (chunk, ctrl) => { if (n <= 0) ctrl.enqueue(chunk); else n--; } }); } //#endregion export { maps as a, flatMaps as i, lines as n, chunkIfs as o, throughs as r, skips as t }; //# sourceMappingURL=skips-o3ebh_7B.js.map