mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 04:22:12 +00:00
* remove prefix from codeowners * remove references from ignore files * Remove prefix from package json and tests * Add run js without prefixes * Rename package folders * Delete auto generated test files * Remove now-node in integration test * Put back deleted vercel json files * Remove eol * Add styfle suggestion to comment in utils/run.js Co-authored-by: Steven <steven@ceriously.com>
104 lines
2.4 KiB
TypeScript
104 lines
2.4 KiB
TypeScript
import assert from 'assert';
|
|
import fs from 'fs-extra';
|
|
import multiStream from 'multistream';
|
|
import path from 'path';
|
|
import Sema from 'async-sema';
|
|
import { File } from './types';
|
|
|
|
const semaToPreventEMFILE = new Sema(20);
|
|
|
|
interface FileFsRefOptions {
|
|
mode?: number;
|
|
contentType?: string;
|
|
fsPath: string;
|
|
}
|
|
|
|
interface FromStreamOptions {
|
|
mode: number;
|
|
contentType?: string;
|
|
stream: NodeJS.ReadableStream;
|
|
fsPath: string;
|
|
}
|
|
|
|
class FileFsRef implements File {
|
|
public type: 'FileFsRef';
|
|
public mode: number;
|
|
public fsPath: string;
|
|
public contentType: string | undefined;
|
|
|
|
constructor({ mode = 0o100644, contentType, fsPath }: FileFsRefOptions) {
|
|
assert(typeof mode === 'number');
|
|
assert(typeof fsPath === 'string');
|
|
this.type = 'FileFsRef';
|
|
this.mode = mode;
|
|
this.contentType = contentType;
|
|
this.fsPath = fsPath;
|
|
}
|
|
|
|
static async fromFsPath({
|
|
mode,
|
|
contentType,
|
|
fsPath,
|
|
}: FileFsRefOptions): Promise<FileFsRef> {
|
|
let m = mode;
|
|
if (!m) {
|
|
const stat = await fs.lstat(fsPath);
|
|
m = stat.mode;
|
|
}
|
|
return new FileFsRef({ mode: m, contentType, fsPath });
|
|
}
|
|
|
|
static async fromStream({
|
|
mode = 0o100644,
|
|
contentType,
|
|
stream,
|
|
fsPath,
|
|
}: FromStreamOptions): Promise<FileFsRef> {
|
|
assert(typeof mode === 'number');
|
|
assert(typeof stream.pipe === 'function'); // is-stream
|
|
assert(typeof fsPath === 'string');
|
|
await fs.mkdirp(path.dirname(fsPath));
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
|
const dest = fs.createWriteStream(fsPath, {
|
|
mode: mode & 0o777,
|
|
});
|
|
stream.pipe(dest);
|
|
stream.on('error', reject);
|
|
dest.on('finish', resolve);
|
|
dest.on('error', reject);
|
|
});
|
|
|
|
return new FileFsRef({ mode, contentType, fsPath });
|
|
}
|
|
|
|
async toStreamAsync(): Promise<NodeJS.ReadableStream> {
|
|
await semaToPreventEMFILE.acquire();
|
|
const release = () => semaToPreventEMFILE.release();
|
|
const stream = fs.createReadStream(this.fsPath);
|
|
stream.on('close', release);
|
|
stream.on('error', release);
|
|
return stream;
|
|
}
|
|
|
|
toStream(): NodeJS.ReadableStream {
|
|
let flag = false;
|
|
|
|
// eslint-disable-next-line consistent-return
|
|
return multiStream(cb => {
|
|
if (flag) return cb(null, null);
|
|
flag = true;
|
|
|
|
this.toStreamAsync()
|
|
.then(stream => {
|
|
cb(null, stream);
|
|
})
|
|
.catch(error => {
|
|
cb(error, null);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
export = FileFsRef;
|