Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
cache.js 5.00 KiB
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const debugFactory = require("debug");
const NodeCache = require("node-cache");
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const endpoint_1 = require("./endpoint");
const debug = debugFactory('decap:cache');
class Register {
    constructor(storage, name) {
        this.storage = storage;
        this.name = name;
        this.cacheRegister = {};
        this.get = (name) => {
            if (!this.cacheRegister[name])
                throw new Error(`no endpoint registered for "${name}"`);
            return this.cacheRegister[name];
        };
        this.add = (name, serverUrl) => {
            const endpoint = new endpoint_1.Endpoint(serverUrl);
            const nodeCache = new NodeCache();
            this.cacheRegister[name] = new Cache();
            this.cacheRegister[name].setCache(nodeCache).setEndpoint(endpoint);
        };
        this.save = () => {
            const data = Object.keys(this.cacheRegister).map((name) => {
                return {
                    name: name,
                    data: this.cacheRegister[name].toObject()
                };
            });
            fs.writeFileSync(path.resolve(this.storage, this.name), JSON.stringify(data), { encoding: 'utf8', flag: 'w' });
            debug('register ${this.name} saved to ${this.storage}');
        };
        this.restore = () => __awaiter(this, void 0, void 0, function* () {
            const data = JSON.parse(fs.readFileSync(path.resolve(this.storage, this.name), { encoding: 'utf8' }));
            data.map((cache) => {
                this.cacheRegister[cache.name] = new Cache();
                this.cacheRegister[cache.name].fromObject(cache.data);
            });
            debug('register ${this.name} restored from ${this.storage}');
        });
        fs.existsSync(storage) || fs.mkdirSync(storage);
    }
}
exports.Register = Register;
class Cache {
    constructor(endpoint, realCache) {
        this.endpoint = endpoint;
        this.realCache = realCache;
    }
    setEndpoint(endpoint) {
        this.endpoint = endpoint;
        return this;
    }
    setCache(realCache) {
        this.realCache = realCache;
        return this;
    }
    get(hash, path) {
        return __awaiter(this, void 0, void 0, function* () {
            let value = this.realCache.get(hash);
            if (value == undefined) {
                debug(`no cache hit. fetching ${path}`);
                value = {
                    contentType: '',
                    data: ''
                };
                try {
                    yield this.endpoint.request(path, value);
                    this.realCache.set(hash, value);
                }
                catch (err) {
                    console.error(err);
                }
            }
            return value;
        });
    }
    toObject() {
        const data = {
            endPoint: this.endpoint.toObject(),
            cache: []
        };
        this.realCache.keys().map((hash) => {
            data.cache.push({
                hash: hash,
                data: this.realCache.get(hash)
            });
        });
        return data;
    }
    fromObject(data) {
        const endpoint = new endpoint_1.Endpoint();
        const realCache = new NodeCache();
        endpoint.fromObject(data.endPoint);
        this.setEndpoint(endpoint);
        data.cache.map((item) => {
            realCache.set(item.hash, item.data);
        });
        this.setCache(realCache);
    }
}
exports.Cache = Cache;
function Middleware(register) {
    return function (req, res, next) {
        return __awaiter(this, void 0, void 0, function* () {
            const pattern = new RegExp('^/([^/]+)(.*)$');
            const match = req.url.match(pattern);
            try {
                const cache = register.get(match[1]);
                const uniQueryString = Object.keys(req.query).sort().map(function (key) { return `${key}=${req.query[key]}`; }).join('&');
                const hash = crypto.createHash('sha1').update(req.path + uniQueryString).digest('base64');
                const value = yield cache.get(hash, match[2]);
                res.setHeader('content-type', value.contentType);
                res.send(value.data);
            }
            catch (err) {
                next(err);
            }
        });
    };
}
exports.Middleware = Middleware;
//# sourceMappingURL=cache.js.map