import crypto from 'node:crypto'; import { createReadStream } from 'node:fs'; import { readFile, writeFile } from 'node:fs/promises'; import { PassThrough } from 'node:stream'; import jwt from 'jsonwebtoken'; import { v4 as uuidv4 } from 'uuid'; import { __dirname } from './constants.js'; async function combineWithPassthrough(sources: any[], destination: any) { for (const stream of sources) { await new Promise((resolve, reject) => { let s = stream; if (typeof stream === 'function') { s = stream(); } if (typeof s === 'string') { destination.push(s); destination.push(null); resolve(true); return; } s.pipe(destination, { end: false }); s.on('end', resolve); s.on('error', reject); }); } destination.emit('end'); } export function combineStreams(streams: any[]) { const stream = new PassThrough(); combineWithPassthrough(streams, stream).catch((err) => stream.destroy(err)); return stream; } /** * * @param userId * @param secret * @returns */ export const generateAccessToken = (userId: string, secret = '') => jwt.sign({ id: userId }, secret, { expiresIn: '10m' }); /** * * @param val * @returns */ export const generateEtag = (val: string) => crypto.createHash('sha256').update(val).digest('hex'); /** * * @param userId * @param secret * @param extendRefresh * @returns */ export const generateRefreshToken = ( userId: string, secret = '', extendRefresh = false ) => { const tokenId = uuidv4(); // unique ID for the refresh token const token = jwt.sign({ id: userId, tokenId }, secret, { expiresIn: extendRefresh ? '7d' : '1h', }); return token; }; /** * * @param value * @returns */ export const getQueryParameterArray = (value: unknown | unknown[] = []) => Array.isArray(value) ? value.map((val) => `${val}`.trim()) : [`${value}`.trim()]; /** * * @param pathToFile * @returns */ export const getReadStream = (pathToFile: string) => { const theStream = createReadStream(pathToFile); theStream.on('error', (err) => { console.error(err); theStream.close(); theStream.push(null); }); return theStream; }; /** * * @param value * @returns */ export const getValueOrFirstEntry = (value: string | string[]) => Array.isArray(value) && value.length ? value[0] : value; /** * * @param filePath * @returns */ export const loadObjectFromJson = async (filePath: string) => { const contents = await readFile(filePath, { encoding: 'utf8' }); return JSON.parse(contents); }; /** * * @param contents * @param filePath */ export const saveToJson = async ( contents: object | string, filePath: string ) => { const stringContents = typeof contents === 'string' ? contents : JSON.stringify(contents, null, 2); await writeFile(filePath, stringContents, { encoding: 'utf8', flag: 'w', }); };