UNPKG

@sanity/export

Version:

Export Sanity documents and assets

85 lines 3.5 kB
import { Transform } from 'node:stream'; import { debug } from './debug.js'; import { getUserAgent } from './getUserAgent.js'; import { requestStream } from './requestStream.js'; import { getSource } from './options.js'; // same regex as split2 is using by default: https://github.com/mcollina/split2/blob/53432f54bd5bf422bd55d91d38f898b6c9496fc1/index.js#L86 const splitRegex = /\r?\n/; export async function getDocumentCursorStream(options) { let streamsInflight = 0; function decrementInflight(stream) { streamsInflight--; if (streamsInflight === 0) { stream.end(); } } const stream = new Transform({ transform(chunk, encoding, callback) { if (encoding !== 'buffer' && encoding !== 'string') { callback(null, chunk); return; } this.push(chunk, encoding); let parsedChunk = null; for (const chunkStr of chunk.toString().split(splitRegex)) { if (chunkStr.trim() === '') { continue; } try { parsedChunk = JSON.parse(chunkStr); } catch { // Ignore JSON parse errors // this can happen if the chunk is not a JSON object. We just pass it through and let the caller handle it. debug('Failed to parse JSON chunk, ignoring', chunkStr); } if (parsedChunk !== null && typeof parsedChunk === 'object' && 'nextCursor' in parsedChunk && typeof parsedChunk.nextCursor === 'string' && !('_id' in parsedChunk)) { debug('Got next cursor "%s", fetching next stream', parsedChunk.nextCursor); streamsInflight++; void startStream(options, parsedChunk.nextCursor).then((reqStream) => { reqStream.on('end', () => decrementInflight(this)); reqStream.pipe(this, { end: false }); }); } } callback(); }, }); streamsInflight++; const reqStream = await startStream(options, ''); reqStream.on('end', () => decrementInflight(stream)); reqStream.pipe(stream, { end: false }); return stream; } function startStream(options, nextCursor) { const source = getSource(options); const baseUrl = options.client.getUrl(source.type === 'dataset' ? `/data/export/${source.id}` : `/media-libraries/${source.id}/export`); const url = new URL(baseUrl); url.searchParams.set('nextCursor', nextCursor); if (options.types && options.types.length > 0) { url.searchParams.set('types', options.types.join()); } const token = options.client.config().token; const headers = { 'User-Agent': getUserAgent(), ...(token ? { Authorization: `Bearer ${token}` } : {}), }; debug('Starting stream with cursor "%s"', nextCursor); return requestStream({ url: url.toString(), headers, maxRetries: options.maxRetries, ...(options.retryDelayMs !== undefined ? { retryDelayMs: options.retryDelayMs } : {}), readTimeout: options.readTimeout, }).then((res) => { debug('Got stream with HTTP %d', res.statusCode); return res; }); } //# sourceMappingURL=getDocumentCursorStream.js.map