UNPKG

@strapi/data-transfer

Version:

Data transfer capabilities for Strapi

129 lines (126 loc) 5.52 kB
import { join } from 'path'; import { getFileStatsForTransfer, signUploadFileForTransfer } from './assets.mjs'; /** Strapi stores byte size on each file record; use for remote totals to avoid per-URL HTTP. */ function hasReliableDbSize(size) { return typeof size === 'number' && Number.isFinite(size) && size >= 0; } /** When every main + format has a DB size, remote rows need no signing or HTTP stat. */ function remoteRowCanUseDbOnly(file) { if (!hasReliableDbSize(file.size)) { return false; } if (!file.formats) { return true; } for (const key of Object.keys(file.formats)){ if (!hasReliableDbSize(file.formats[key].size)) { return false; } } return true; } /** * Sum sizes and counts for the same asset rows `createAssetsStream` would yield (main + formats), * skipping missing files with ENOENT like the stream does. Used for transfer progress totals / ETA. * * - **Local (`provider === 'local'`):** `stat` on disk (source of truth; matches ENOENT skips). * - **Remote:** sum `size` from DB when present on main and every format; otherwise sign + `fetch` / `Content-Length` like before. */ async function estimateAssetTotals(strapi) { let totalBytes = 0; let totalCount = 0; const stream = strapi.db.queryBuilder('plugin::upload.file').select('*').stream(); for await (const file of stream){ const isLocalProvider = file.provider === 'local'; if (isLocalProvider) { const filepath = join(strapi.dirs.static.public, file.url); try { const stats = await getFileStatsForTransfer(filepath, strapi, true); totalBytes += stats.size; totalCount += 1; } catch (err) { const code = err && typeof err === 'object' && 'code' in err ? err.code : undefined; if (code === 'ENOENT') { strapi.log.warn(`[Data transfer] Skipping missing asset file: ${filepath}`); continue; } throw err; } if (file.formats) { for (const format of Object.keys(file.formats)){ const fileFormat = file.formats[format]; const fileFormatFilepath = join(strapi.dirs.static.public, fileFormat.url); try { const fileFormatStats = await getFileStatsForTransfer(fileFormatFilepath, strapi, true); totalBytes += fileFormatStats.size; totalCount += 1; } catch (err) { const code = err && typeof err === 'object' && 'code' in err ? err.code : undefined; if (code === 'ENOENT') { strapi.log.warn(`[Data transfer] Skipping missing asset file: ${fileFormatFilepath}`); continue; } throw err; } } } continue; } // Remote: prefer DB sizes (fast); fall back to signed URL + HTTP where `size` is missing. if (remoteRowCanUseDbOnly(file)) { totalBytes += file.size; totalCount += 1; if (file.formats) { for (const format of Object.keys(file.formats)){ totalBytes += file.formats[format].size; totalCount += 1; } } continue; } await signUploadFileForTransfer(strapi, file); if (hasReliableDbSize(file.size)) { totalBytes += file.size; totalCount += 1; } else { try { const stats = await getFileStatsForTransfer(file.url, strapi, false); totalBytes += stats.size; totalCount += 1; } catch (err) { const code = err && typeof err === 'object' && 'code' in err ? err.code : undefined; if (code === 'ENOENT') { strapi.log.warn(`[Data transfer] Skipping missing asset file: ${file.url}`); continue; } throw err; } } if (file.formats) { for (const format of Object.keys(file.formats)){ const fileFormat = file.formats[format]; const fileFormatFilepath = fileFormat.url; if (hasReliableDbSize(fileFormat.size)) { totalBytes += fileFormat.size; totalCount += 1; } else { try { const fileFormatStats = await getFileStatsForTransfer(fileFormatFilepath, strapi, false); totalBytes += fileFormatStats.size; totalCount += 1; } catch (err) { const code = err && typeof err === 'object' && 'code' in err ? err.code : undefined; if (code === 'ENOENT') { strapi.log.warn(`[Data transfer] Skipping missing asset file: ${fileFormatFilepath}`); continue; } throw err; } } } } } return { totalBytes, totalCount }; } export { estimateAssetTotals }; //# sourceMappingURL=estimate-asset-totals.mjs.map