-
-
Notifications
You must be signed in to change notification settings - Fork 84
/
fileReader.ts
76 lines (69 loc) · 2.64 KB
/
fileReader.ts
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
// cSpell:ignore curr
// cSpell:words zlib iconv
import * as fs from 'fs';
import * as zlib from 'zlib';
import { fetch } from './fetch';
import { FetchUrlError } from './FetchError';
import { toURL, isSupportedURL, isFileURL, isZipped } from './util';
import { fileURLToPath } from 'url';
import type { BufferEncoding } from '../../models/BufferEncoding';
const defaultEncoding: BufferEncoding = 'utf8';
export async function readFile(filename: string | URL, encoding?: BufferEncoding): Promise<string> {
const url = toURL(filename);
if (!isSupportedURL(url)) {
throw new Error('Unsupported network protocol');
}
return isFileURL(url) ? _readFile(url, encoding) : _fetchURL(url, encoding);
}
function _readFile(url: URL, encoding?: BufferEncoding): Promise<string> {
// Convert it to a string because Yarn2 cannot handle URLs.
const filename = fileURLToPath(url);
return _read(() => fs.createReadStream(filename), isZipped(filename), encoding);
}
async function _fetchURL(url: URL, encoding?: BufferEncoding): Promise<string> {
const response = await fetch(url);
if (!response.ok) {
throw FetchUrlError.create(url, response.status);
}
return _read(() => response.body, isZipped(url), encoding);
}
function _read(
getStream: () => NodeJS.ReadableStream,
isZipped: boolean,
encoding: BufferEncoding = defaultEncoding
): Promise<string> {
return new Promise((resolve, reject) => {
const data: string[] = [];
const stream = prepareFileStream(getStream, isZipped, encoding, reject);
let resolved = false;
function complete() {
resolve(data.join(''));
resolved = resolved || (resolve(data.join('')), true);
}
stream.on('error', reject);
stream.on('data', (d: string) => data.push(d));
stream.on('close', complete);
stream.on('end', complete);
});
}
function prepareFileStream(
getStream: () => NodeJS.ReadableStream,
isZipped: boolean,
encoding: BufferEncoding,
fnError: (e: Error) => void
) {
const pipes: NodeJS.ReadWriteStream[] = [];
if (isZipped) {
pipes.push(zlib.createGunzip());
}
const fileStream = getStream();
fileStream.on('error', fnError);
const stream = pipes.reduce<NodeJS.ReadableStream>((s, p) => s.pipe(p).on('error', fnError), fileStream);
stream.setEncoding(encoding);
return stream;
}
export function readFileSync(filename: string, encoding: BufferEncoding = defaultEncoding): string {
const rawData = fs.readFileSync(filename);
const data = isZipped(filename) ? zlib.gunzipSync(rawData) : rawData;
return data.toString(encoding);
}