@foxpage/foxpage-manager
Version:
foxpage resource manager
159 lines (158 loc) • 4.79 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DiskCache = void 0;
const crypto_1 = __importDefault(require("crypto"));
const fs_extra_1 = require("fs-extra");
const globby_1 = __importDefault(require("globby"));
const lodash_1 = __importDefault(require("lodash"));
const local_1 = require("./local");
/**
* disk cache
*
* @export
* @class DiskCache
* @implements {ResourceCache<T>}
* @template T
*/
class DiskCache {
constructor(opt) {
this.diskCache = new Map();
this.appId = opt.appId;
this.type = opt.type;
this.logger = opt.logger;
}
getCurCount() {
return this.diskCache.size;
}
/**
* set disk cache
*
* @param {string} id
* @param {T} resource
* @return {*} {Promise<void>}
*/
async set(id, resource) {
var _a;
try {
const hash = this.computeMD5Hash(JSON.stringify(resource));
const filePath = this.generateFilePath(id, hash);
this.diskCache.set(id, { filePath, hash });
await (0, local_1.storeContent)(filePath, lodash_1.default.cloneDeep(resource));
await this.delete(id, false);
}
catch (e) {
const msg = e.message;
if (msg.indexOf('EEXIST') === -1) {
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.error('store content failed: ' + e);
}
}
}
/**
* get content from disk
*
* @param {string} id
* @return {*} {(Promise<T | null | undefined>)}
*/
async get(id) {
const cached = this.diskCache.get(id);
try {
let filePath = '';
if (cached) {
filePath = cached.filePath;
}
else {
const rootDir = this.getRootDir(id);
const files = await this.getFiles(rootDir);
filePath = files[0];
}
if (filePath) {
const result = await (0, fs_extra_1.readJSON)(filePath);
return result || null;
}
return null;
}
catch (e) {
// this.logger?.info('get content failed: ' + e);
return null;
}
}
/**
* check if exist the content
*
* @param {string} id
* @return {*} {Promise<boolean>}
*/
async has(id) {
return this.diskCache.has(id) || !!(await this.get(id));
}
/**
* update delete status for delete action
*
* @param {string} id
* @param {boolean} all true: remove all files of the dir, false: only remove the invalid files
* @return {*} {Promise<void>}
* @memberof DiskCache
*/
async delete(id, all = true) {
const cached = this.diskCache.get(id);
if (cached) {
try {
const rootDir = this.getRootDir(id);
if (all) {
await (0, fs_extra_1.remove)(rootDir);
this.diskCache.delete(id);
}
else {
const files = await this.getFiles(rootDir);
const doRemove = async (list) => {
for (const fileName of list) {
if (!fileName.includes(cached.hash)) {
// only remove the invalid files
await (0, fs_extra_1.remove)(fileName);
}
}
};
await doRemove(files);
}
}
catch (_e) {
// this.logger?.warn('remove content failed,' + e);
}
}
}
getRootDir(id) {
const dirs = [this.type, id];
const rootDir = (0, local_1.resolveContentDir)(this.appId, dirs);
return rootDir;
}
generateFilePath(id, hash) {
const dirs = [this.type, id, hash];
const filePath = (0, local_1.resolveContentPath)(this.appId, dirs);
return filePath;
}
computeMD5Hash(code, len = 8) {
const md5 = crypto_1.default.createHash('md5');
md5.update(code);
const hash = md5.digest('hex');
return hash.substring(0, len);
}
async getFiles(root) {
const files = await (0, globby_1.default)('**/*', {
absolute: true,
onlyFiles: true,
cwd: root,
});
return files;
}
/**
* destroy the instance
*
*/
destroy() {
this.diskCache.clear();
}
}
exports.DiskCache = DiskCache;