UNPKG

@blocklet/uploader-server

Version:

blocklet upload server

157 lines (156 loc) 4.7 kB
import { existsSync } from "fs"; import { join, basename } from "path"; import config from "@blocklet/sdk/lib/config"; import { getResources } from "@blocklet/sdk/lib/component"; import joinUrl from "url-join"; import component from "@blocklet/sdk/lib/component"; import { setPDFDownloadHeader, logger, calculateCacheControl, serveResource, scanDirectory, getFileNameFromReq } from "../utils.js"; import { ImageBinDid } from "../constants.js"; const ImgResourceType = "imgpack"; let skipRunningCheck = false; let resourceTypes = [ { type: ImgResourceType, did: ImageBinDid, folder: "" // can be string or string[] } ]; let resourcesMap = /* @__PURE__ */ new Map(); let canUseResources = []; export const getCanUseResources = () => canUseResources; export const mappingResource = async () => { try { const resources = getResources({ types: resourceTypes, skipRunningCheck }); canUseResources = resources.map((resource) => { const originDir = resource.path; const resourceType = resourceTypes.find(({ type }) => originDir.endsWith(type)); if (!existsSync(originDir) || !resourceType) { return false; } const folders = Array.isArray(resourceType.folder) ? resourceType.folder : [resourceType.folder || ""]; return folders.map((folder) => ({ originDir, dir: join(originDir, folder), blockletInfo: resource, whitelist: resourceType.whitelist, blacklist: resourceType.blacklist })); }).filter(Boolean).flat(); resourcesMap.clear(); for (const resource of canUseResources) { const { dir, whitelist, blacklist, originDir, blockletInfo } = resource; if (existsSync(dir)) { try { const dirResourceMap = scanDirectory(dir, { whitelist, blacklist, originDir, blockletInfo }); for (const [key, value] of dirResourceMap.entries()) { resourcesMap.set(key, value); } } catch (err) { logger.error(`Error scanning directory ${dir}:`, err); } } } logger.info("Mapping resources: files count:", resourcesMap.size, "directories count:", canUseResources.length); return canUseResources; } catch (error) { logger.error(error); } return false; }; const { events, Events } = config; events.on(Events.componentAdded, () => mappingResource()); events.on(Events.componentRemoved, () => mappingResource()); events.on(Events.componentStarted, () => mappingResource()); events.on(Events.componentStopped, () => mappingResource()); events.on(Events.componentUpdated, () => mappingResource()); export const initStaticResourceMiddleware = ({ options = {}, resourceTypes: _resourceTypes = resourceTypes, express, skipRunningCheck: _skipRunningCheck } = {}) => { skipRunningCheck = !!_skipRunningCheck; const { cacheControl, cacheControlImmutable } = calculateCacheControl( options.maxAge || "365d", options.immutable !== false ); if (_resourceTypes?.length > 0) { resourceTypes = _resourceTypes.map((item) => { if (typeof item === "string") { return { type: item, did: ImageBinDid, // not set did, default is ImageBinDid folder: "" // not set folder, default is root }; } return item; }); } mappingResource(); return (req, res, next) => { const fileName = getFileNameFromReq(req); try { const resource = resourcesMap.get(fileName); if (resource) { serveResource(req, res, next, resource, { ...options, cacheControl, cacheControlImmutable }); } else { next(); } } catch (error) { logger.error("Error serving static file:", error); next(); } }; }; export const initProxyToMediaKitUploadsMiddleware = ({ options, express } = {}) => { return async (req, res, next) => { if (!component.getComponentWebEndpoint(ImageBinDid)) { return next(); } setPDFDownloadHeader(req, res); try { const { data, status, headers } = await component.call({ name: ImageBinDid, path: joinUrl("/uploads", basename(req.url)), responseType: "stream", method: "GET" }); if (data && status >= 200 && status < 400) { Object.keys(headers).forEach((key) => { res.set(key, headers[key]); }); data.on("error", (err) => { next(); }).pipe(res).on("error", (err) => { next(); }); } else { next(); } } catch (error) { next(); } }; };