fetch-text-by-line.ts 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import type { BunFile } from 'bun';
  2. import { fetchWithRetry, defaultRequestInit } from './fetch-retry';
  3. import { fsCache } from './cache-filesystem';
  4. import picocolors from 'picocolors';
  5. // import { TextLineStream } from './text-line-transform-stream';
  6. // import { PolyfillTextDecoderStream } from './text-decoder-stream';
  7. // export function readFileByLine(file: string | BunFile) {
  8. // if (typeof file === 'string') {
  9. // file = Bun.file(file);
  10. // }
  11. // return file.stream().pipeThrough(new PolyfillTextDecoderStream()).pipeThrough(new TextLineStream());
  12. // }
  13. // export function createReadlineInterfaceFromResponse(resp: Response) {
  14. // if (!resp.body) {
  15. // throw new Error('Failed to fetch remote text');
  16. // }
  17. // if (resp.bodyUsed) {
  18. // throw new Error('Body has already been consumed.');
  19. // }
  20. // return (resp.body as ReadableStream<Uint8Array>).pipeThrough(new PolyfillTextDecoderStream()).pipeThrough(new TextLineStream());
  21. // }
  22. const decoder = new TextDecoder('utf-8');
  23. export async function *readFileByLine(file: string | URL | BunFile): AsyncGenerator<string> {
  24. if (typeof file === 'string') {
  25. file = Bun.file(file);
  26. } else if (!('writer' in file)) {
  27. file = Bun.file(file);
  28. }
  29. let buf = '';
  30. for await (const chunk of file.stream()) {
  31. const chunkStr = decoder.decode(chunk).replaceAll('\r\n', '\n');
  32. for (let i = 0, len = chunkStr.length; i < len; i++) {
  33. const char = chunkStr[i];
  34. if (char === '\n') {
  35. yield buf;
  36. buf = '';
  37. } else {
  38. buf += char;
  39. }
  40. }
  41. }
  42. if (buf) {
  43. yield buf;
  44. }
  45. }
  46. export async function *createReadlineInterfaceFromResponse(resp: Response): AsyncGenerator<string> {
  47. if (!resp.body) {
  48. throw new Error('Failed to fetch remote text');
  49. }
  50. if (resp.bodyUsed) {
  51. throw new Error('Body has already been consumed.');
  52. }
  53. let buf = '';
  54. for await (const chunk of resp.body) {
  55. const chunkStr = decoder.decode(chunk).replaceAll('\r\n', '\n');
  56. for (let i = 0, len = chunkStr.length; i < len; i++) {
  57. const char = chunkStr[i];
  58. if (char === '\n') {
  59. yield buf;
  60. buf = '';
  61. } else {
  62. buf += char;
  63. }
  64. }
  65. }
  66. if (buf) {
  67. yield buf;
  68. }
  69. }
  70. export function fetchRemoteTextByLine(url: string | URL) {
  71. return fetchWithRetry(url, defaultRequestInit).then(res => createReadlineInterfaceFromResponse(res as Response));
  72. }