Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | /**
* Parses JSONL from a string or iterables of strings.
* @overload
* @param {string | Iterable<string>} input - JSONL source.
* @returns {Generator<*>} generator that yields a parsed json line
* @example
* for (const row of parseCSV('{"name": "John","age": 30}\n{"name": "Jane","age": 25}')) {
* console.log(row);
* }
*
* @example
* const chunkArray = ['{"name": "John","age": 30}\n', '{"name": "Jane","age": 25}'];
* for (const row of parseCSV(chunkArray)) {
* console.log(row);
* }
*/
/**
* Parses JSONL from async string iterables.
*
* @example
* async function* chunks() {
* yield '{"name": "John","age": 30}\n{"na';
* yield 'me": "Jane","age": 25}\n';
* }
* for await (const row of parseCSV(chunks())) {
* console.log(row);
* }
* @overload
* @param {AsyncIterable<string>} input - JSONL source.
* @returns {AsyncGenerator<*>} generator that yields a parsed json line
*/
/**
* @param {string | Iterable<string> | AsyncIterable<string>} input - JSONL source.
* @returns {Generator<*> | AsyncGenerator<*>} generator that yields a parsed json line
*/
export function parseJsonLines (input) {
if (typeof input === 'string') {
return parseJsonLinesSync([input])
} else if (isAsyncIterable(input)) {
return parseJsonLinesAsync(input)
} else if (isIterable(input)) {
return parseJsonLinesSync(input)
} else {
throw new TypeError('Input must be a string, Iterable, or AsyncIterable')
}
}
/**
* @param {*} object - target object
* @returns {object is Iterable<*>} - true if iterable, false otherwise
*/
const isIterable = (object) => typeof object?.[Symbol.iterator] === 'function'
/**
* @param {*} object - target object
* @returns {object is AsyncIterable<*>} - true if iterable, false otherwise
*/
const isAsyncIterable = (object) => typeof object?.[Symbol.asyncIterator] === 'function'
/**
* Parses CSV from a synchronous iterable of strings.
*
* @param {Iterable<string>} iterable - Iterable of string chunks.
* @yields {object | null | any[] | number | string} parsed CSV row
*/
function * parseJsonLinesSync (iterable) {
let buffer = ''
for (const chunk of iterable) {
buffer += chunk.toString()
const lines = buffer.split(/\r?\n/)
buffer = lines.pop() ?? ''// keep last partial line
for (const line of lines) {
if (!line.trim()) { continue }
yield JSON.parse(line)
}
}
if (buffer.trim()) {
yield JSON.parse(buffer)
}
}
/**
* Parses JSON lines from an async iterable of string chunks.
*
* @param {AsyncIterable<string>} asyncIterable - Async iterable of chunks.
* @yields {object | null | any[] | number | string} parsed JSON line
*/
async function * parseJsonLinesAsync (asyncIterable) {
let buffer = ''
for await (const chunk of asyncIterable) {
buffer += chunk.toString()
const lines = buffer.split(/\r?\n/)
buffer = lines.pop() ?? ''// keep last partial line
for (const line of lines) {
if (!line.trim()) { continue }
yield JSON.parse(line)
}
}
if (buffer.trim()) {
yield JSON.parse(buffer)
}
}
|