sourcemap-parse.js 2.08 KB
const sourceMap = require('source-map');
const lru = require('lru-cache');
const rp = require('request-promise');
const url = require('url');
const logger = global.yoho.logger;
const config = global.yoho.config;

const cache = lru({
    max: 500
});

const loadFileSourceMap = (fileUrl) => {
    const cacheItem = cache.get(fileUrl);

    if (cacheItem) {
        logger.info('cache');
        return Promise.resolve(cacheItem);
    } else {
        if (!/\.js(\?.*?)?$/.test(fileUrl)) {
            return Promise.resolve();
        }
        const urlPath = url.parse(fileUrl).pathname;

        try {
            return rp(`${config.sourceMap.domain}/api/sourcemap/load?path=${urlPath}`, {
                json: true,
                resolveWithFullResponse: true
            }).then(res => {
                const data = res.toJSON();

                if (data.headers.sourcemap) {
                    cache.set(fileUrl, data.body);
                    return data.body;
                }
                return void 0;
            }, () => {
                logger.error(`${fileUrl}.map file request failure!`);
            });
        } catch (e) {
            logger.error(`${fileUrl}.map file request failure!`, e);
            return Promise.resolve();
        }
    }
};

const parse = ({fileUrl, line, column}) => {
    if (!/\.js(\?[^\?]*)?$/.test(fileUrl) || !line) {
        return Promise.resolve({
            source: fileUrl,
            line,
            column
        });
    }
    return loadFileSourceMap(fileUrl).then(source => {
        if (!source || !line) {
            return void 0;
        }
        try {
            const consumer = new sourceMap.SourceMapConsumer(source);
            const origin = consumer.originalPositionFor({
                line: line,
                column: column
            });

            return origin;
        } catch (e) {
            if (cache.get(fileUrl)) {
                cache.del(fileUrl);
            }
            logger.error(e);
        }
        return void 0;
    }, err => {
        logger.error(err);
    });
};

module.exports = {
    parse
};