UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

56 lines (44 loc) 1.78 kB
import {createWriteStream} from 'node:fs' import path from 'node:path' import {pipeline} from 'node:stream/promises' import {getIt} from 'get-it' import {keepAlive, promise} from 'get-it/middleware' import debug from './debug' import withRetry from './withRetry' const CONNECTION_TIMEOUT = 15 * 1000 // 15 seconds const READ_TIMEOUT = 3 * 60 * 1000 // 3 minutes const request = getIt([keepAlive(), promise()]) async function downloadAsset( url: string, fileName: string, fileType: string, outDir: string, ): Promise<void> { // File names that contain a path to file (e.g. sanity-storage/assets/file-name.tar.gz) fail when archive is // created due to missing parent dir (e.g. sanity-storage/assets), so we want to handle them by taking // the base name as file name. const normalizedFileName = path.basename(fileName) const assetFilePath = getAssetFilePath(normalizedFileName, fileType, outDir) await withRetry(async () => { const response = await request({ url: url, maxRedirects: 5, timeout: {connect: CONNECTION_TIMEOUT, socket: READ_TIMEOUT}, stream: true, }) debug('Received asset %s with status code %d', normalizedFileName, response?.statusCode) await pipeline(response.body, createWriteStream(assetFilePath)) }) } function getAssetFilePath(fileName: string, fileType: string, outDir: string): string { // Set assetFilePath if we are downloading an asset file. // If it's a JSON document, assetFilePath will be an empty string. let assetFilePath = '' if (fileType === 'image') { assetFilePath = path.join(outDir, 'images', fileName) } else if (fileType === 'file') { assetFilePath = path.join(outDir, 'files', fileName) } return assetFilePath } export default downloadAsset