prettier-plugin-jsdoc
Version:
Prettier plugin for format comment blocks and convert to standard Match with Visual studio and other IDE which support jsdoc and comments as markdown.
130 lines (129 loc) • 4.67 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCachedValue = void 0;
const fs_1 = __importDefault(require("fs"));
const make_dir_1 = __importDefault(require("make-dir"));
const object_hash_1 = __importDefault(require("object-hash"));
const path_1 = require("path");
const serialize_error_1 = require("serialize-error");
const temp_dir_1 = __importDefault(require("temp-dir"));
const cacheDir = process.env.PRETTIER_PLUGIN_ELM_CACHE_DIR
? path_1.resolve(process.env.PRETTIER_PLUGIN_ELM_CACHE_DIR)
: path_1.resolve(temp_dir_1.default, "prettier-plugin-elm");
const cacheMax = process.env.PRETTIER_PLUGIN_ELM_CACHE_MAX
? parseInt(process.env.PRETTIER_PLUGIN_ELM_CACHE_MAX, 10)
: 1000;
const cacheGCInterval = process.env.PRETTIER_PLUGIN_ELM_CACHE_GC_INTERVAL
? parseInt(process.env.PRETTIER_PLUGIN_ELM_CACHE_GC_INTERVAL, 10)
: 1000 * 60;
/* istanbul ignore next */
const noop = () => {
//
};
const getCachedValue = (fn, ...args) => {
var _a;
const cacheKey = object_hash_1.default({ args });
const recordFilePath = path_1.resolve(cacheDir, `${cacheKey}.json`);
let record;
let recordIsFromCache = false;
// load value or error from cache
try {
record = JSON.parse(fs_1.default.readFileSync(recordFilePath, "utf8"));
recordIsFromCache = true;
}
catch (e) {
// a failure to load from cache implies calling fn
try {
record = {
value: fn(...args),
};
}
catch (fnError) {
const serializedError = serialize_error_1.serializeError(fnError);
delete serializedError.stack;
record = {
error: serializedError,
};
}
}
try {
make_dir_1.default.sync(cacheDir);
fs_1.default.writeFileSync(`${recordFilePath}.touchfile`, "");
if (!recordIsFromCache) {
fs_1.default.writeFileSync(recordFilePath, JSON.stringify(record), "utf8");
}
collectGarbageIfNeeded();
}
catch (e) {
// a failure to save record into cache or clean garbage
// should not affect the result of the function
/* istanbul ignore next */
if (process.env.NODE_ENV === "test") {
throw e;
}
}
if (record.error) {
const errorToThrow = new Error();
for (const errorProperty in record.error) {
/* istanbul ignore else */
if ((_a = record.error) === null || _a === void 0 ? void 0 : _a.hasOwnProperty(errorProperty)) {
errorToThrow[errorProperty] = record.error.property;
}
}
throw errorToThrow;
}
else {
return record.value;
}
};
exports.getCachedValue = getCachedValue;
function collectGarbageIfNeeded() {
const pathToGCTouchfile = path_1.resolve(cacheDir, `gc.touchfile`);
try {
const lastGCTime = fs_1.default.statSync(pathToGCTouchfile).mtimeMs;
if (lastGCTime + cacheGCInterval > +new Date()) {
// no need to collect garbage
return;
}
}
catch (e) {
// a failure to read modification time for the GC touchfile
// means that GC needs to be done for the first time
}
fs_1.default.writeFileSync(pathToGCTouchfile, "");
const recordInfos = [];
fs_1.default.readdirSync(cacheDir).map((recordFileName) => {
if (!recordFileName.endsWith(".json")) {
return;
}
const recordFilePath = path_1.resolve(cacheDir, recordFileName);
const recordInfo = {
path: recordFilePath,
touchedAt: 0,
};
try {
recordInfo.touchedAt = fs_1.default.statSync(`${recordFilePath}.touchfile`).mtimeMs;
}
catch (e) {
// fs.statSync may fail if another GC process has just deleted it;
// this is not critical
/* istanbul ignore next */
if (process.env.NODE_ENV === "test") {
throw e;
}
}
recordInfos.push(recordInfo);
});
recordInfos.sort((a, b) => {
return b.touchedAt - a.touchedAt;
});
const recordInfosToDelete = recordInfos.slice(cacheMax);
recordInfosToDelete.forEach((recordInfo) => {
// files are deleted asynchronously and possible errors are ignored
fs_1.default.unlink(recordInfo.path, noop);
fs_1.default.unlink(`${recordInfo.path}.touchfile`, noop);
});
}