97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import os from 'node:os';
|
|
import fs from 'node:fs';
|
|
import { createId } from '@paralleldrive/cuid2';
|
|
import { Readable } from 'stream';
|
|
import { finished } from 'stream/promises';
|
|
import { dirname, basename, join, isAbsolute } from 'node:path';
|
|
import { fileURLToPath } from 'url';
|
|
import { createHash } from 'node:crypto';
|
|
export const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const ua0 = 'Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0'
|
|
|
|
export function getPackageVersion(packageJsonPath: string): string {
|
|
if (!packageJsonPath) throw new Error('getPackageVersion requires packageJsonPath as first argument, but it was undefined.');
|
|
if (!isAbsolute(packageJsonPath)) {
|
|
packageJsonPath = join(__dirname, packageJsonPath)
|
|
}
|
|
try {
|
|
const raw = fs.readFileSync(packageJsonPath, { encoding: 'utf-8' })
|
|
const json = JSON.parse(raw)
|
|
return json.version
|
|
} catch (e) {
|
|
console.error('failed to getPackageVersion')
|
|
console.error(e)
|
|
return 'IDK'
|
|
}
|
|
}
|
|
|
|
|
|
export function getTmpFile(str: string): string {
|
|
return join(os.tmpdir(), `${createId()}_${basename(str)}`);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {String} url
|
|
* @returns {String} filePath
|
|
*
|
|
* @see https://stackoverflow.com/a/74722818/1004931
|
|
*/
|
|
export async function download({
|
|
url,
|
|
filePath,
|
|
}: {
|
|
url: string;
|
|
filePath?: string;
|
|
}): Promise<string> {
|
|
if (!url) throw new Error(`The 'url' parameter is required and must be a string.`);
|
|
|
|
const fileBaseName = basename(url);
|
|
filePath = filePath || join(os.tmpdir(), `${createId()}_${fileBaseName}`);
|
|
const stream = fs.createWriteStream(filePath);
|
|
|
|
const requestData = async () => {
|
|
const response = await fetch(url, {
|
|
headers: {
|
|
'user-agent': ua0,
|
|
},
|
|
});
|
|
|
|
const { body } = response;
|
|
if (!body) throw new Error('Response body was null.');
|
|
|
|
// Convert the Fetch API ReadableStream to a Node.js Readable stream
|
|
const nodeStream = Readable.from(body as any);
|
|
|
|
await finished(nodeStream.pipe(stream));
|
|
|
|
// Abort retrying if the resource doesn't exist
|
|
if (response.status === 404) {
|
|
throw new Error('Resource not found (404).');
|
|
}
|
|
};
|
|
|
|
await requestData();
|
|
|
|
return filePath;
|
|
}
|
|
|
|
export const tmpFileRegex = /^\/tmp\/.*\.jpg$/;
|
|
|
|
|
|
|
|
/**
|
|
* getFileChecksum
|
|
* @see https://stackoverflow.com/a/44643479/1004931
|
|
*/
|
|
export async function getFileChecksum(filePath: string, algorithm = 'md5') {
|
|
return new Promise((resolve, reject) => {
|
|
const hash = createHash(algorithm);
|
|
const stream = fs.createReadStream(filePath);
|
|
stream.on('error', err => reject(err));
|
|
stream.on('data', chunk => hash.update(chunk));
|
|
stream.on('end', () => resolve(hash.digest('hex')));
|
|
});
|
|
}
|