UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

87 lines (85 loc) • 2.99 kB
import { createUploadClient } from "../../apps/upload/src/client.mjs"; import { join, relative, sep } from "node:path"; import { readFile, readdir, stat } from "node:fs/promises"; //#region src/services/deploy/storage.ts async function walkDist(dir, baseDir) { const entries = await readdir(dir, { withFileTypes: true }); const files = []; for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) { const fullPath = join(dir, entry.name); if (entry.isDirectory()) { files.push(...await walkDist(fullPath, baseDir)); continue; } if (!(await stat(fullPath)).isFile()) continue; files.push({ path: relative(baseDir, fullPath).split(sep).join("/"), bytes: new Uint8Array(await readFile(fullPath)) }); } return files; } async function collectDistFiles(distDir) { return walkDist(distDir, distDir); } async function uploadBundle(input) { return await createUploadClient({ origin: input.origin, apiKey: input.apiKey, fetchImpl: input.fetchImpl }).uploadBundle({ account: input.account, gateway: input.gateway, workspace: input.workspace, files: input.files.map((file) => ({ path: file.path, contentBase64: Buffer.from(file.bytes).toString("base64") })) }); } /** Per-request file-count cap for `uploadWorkspaceDist`: each file costs the * server a stat+put round trip against object storage, so request count — not * byte size — is what keeps a batch inside the CDN proxy's response timeout. */ const DEFAULT_MAX_FILES_PER_REQUEST = 100; async function uploadWorkspaceDist(input) { const maxRequestBytes = input.maxRequestBytes ?? (Number(process.env.BOS_MAX_BUNDLE_UPLOAD_BYTES) || 67108864); const maxFilesPerRequest = input.maxFilesPerRequest ?? 100; const merged = { stored: 0, totalBytes: 0, integrity: {} }; let batch = []; let batchBytes = 0; const overheadPerFile = (file) => Math.ceil(file.bytes.byteLength / 3) * 4 + file.path.length + 64; const flush = async () => { if (batch.length === 0) return; const result = await uploadBundle({ origin: input.origin, apiKey: input.apiKey, account: input.account, gateway: input.gateway, workspace: input.workspace, files: batch }); merged.stored += result.stored; merged.totalBytes += result.totalBytes; merged.unchanged = (merged.unchanged ?? 0) + (result.unchanged ?? 0); Object.assign(merged.integrity, result.integrity); merged.storage = result.storage; batch = []; batchBytes = 0; }; for (const file of input.files) { const cost = overheadPerFile(file); if (cost > maxRequestBytes) throw new Error(`[publish] ${input.workspace}/${file.path} (${file.bytes.byteLength} bytes) exceeds the per-request upload ceiling`); if (batchBytes + cost > maxRequestBytes || batch.length >= maxFilesPerRequest) await flush(); batch.push(file); batchBytes += cost; } await flush(); return merged; } //#endregion export { collectDistFiles, uploadBundle, uploadWorkspaceDist }; //# sourceMappingURL=storage.mjs.map