@calvin_von/proxy-plugin-cache
Version:
A dalao-proxy plugin for cache response
230 lines (198 loc) • 6.25 kB
JavaScript
const chalk = require('chalk');
const readline = require('readline');
const fs = require('fs');
const path = require('path');
const { checkAndCreateFolder, urlMapFS, HTTP_METHODS } = require('../utils');
const moment = require('moment');
const HEADERS_FIELD_TEXT = '[[headers]]';
const MOCK_FIELD_TEXT = '[[mock]]';
const STATUS_FIELD_TEXT = '[[status]]';
const ContentWrapper = {
useObject: content => {
return `module.exports = ${content};`;
},
usePromise: (content, time) => {
return `const data = ${content};
module.exports = new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, ${time});
});`
},
useFunction: content => {
return `const data = ${content};
module.exports = function(context) {
return data;
}`;
},
useFunctionReturnPromise: (content, time) => {
return `const data = ${content};
module.exports = function(context) {
const { request, response } = context;
return new Promise(resolve => {
setTimeout(() => {
resolve(data);
}, ${time});
});
}`;
}
};
let validators;
exports.HEADERS_FIELD_TEXT = HEADERS_FIELD_TEXT;
exports.MOCK_FIELD_TEXT = MOCK_FIELD_TEXT;
exports.STATUS_FIELD_TEXT = STATUS_FIELD_TEXT;
exports.ContentWrapper = ContentWrapper;
exports.MockFileGenerator = async function MockFileGenerator(method, url, options, config) {
validators = {
method: method => {
if (!new RegExp(`^${HTTP_METHODS.join('|')}$`, 'i').test(method)) {
console.error(chalk.red(method + ' is not a valid HTTP method'));
return false;
}
return true;
},
url: url => {
const mockUrl = config.mock.prefix + url;
if (!/^\/\S*$/i.test(mockUrl)) {
console.error(chalk.red(mockUrl + ' is not a valid url'));
return false;
}
return true;
}
};
validators[0] = validators.method;
validators[1] = validators.url;
if (method && url) {
if (validators.method.call(null, method) && validators.url.call(null, url)) {
await generateFile(method, url, options, config);
}
process.exit(0);
}
else {
questionUrl(method, options, config);
}
};
function questionUrl(method, options, config) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('close', () => {
process.exit();
});
const questions = [
chalk.yellow('[Mock] Method: '),
chalk.yellow('[Mock] Url: ') + config.mock.prefix,
];
const answers = [];
let index = 0;
if (method) {
if (validators.method.call(null, method)) {
index++;
answers.push(method);
}
else {
process.exit(-1);
}
}
function askQuestion() {
rl.question(
questions[index],
async value => {
if (validators[index].call(null, value)) {
answers.push(value);
if (index === questions.length - 1) {
await generateFile(...answers, options, config);
process.exit(0);
}
else {
index++;
askQuestion();
}
}
else {
askQuestion();
}
}
);
}
askQuestion();
}
async function generateFile(method, url, options, config) {
const mockUrl = config.mock.prefix + url;
const isInJsFile = options.program;
const mockFileName = path.resolve(
process.cwd(),
`./${config.mock.dirname}/${urlMapFS(
mockUrl,
method,
'',
config.cache,
).fullPath
}`) + (isInJsFile ? '.js' : '.json');
const json = {
CACHE_INFO: 'Mocked by Dalao-Proxy Plugin Cache',
CACHE_TIME_TXT: moment().format('llll'),
CACHE_REQUEST_DATA: {
url: mockUrl,
method
},
[HEADERS_FIELD_TEXT]: {},
[MOCK_FIELD_TEXT]: true,
[STATUS_FIELD_TEXT]: 200
};
applyFilter(config.cache.filters, json);
let fileContent = JSON.stringify(json, null, 2);
if (isInJsFile) {
const fileWrapper = content => {
const {
time: useDelay,
function: useFunction
} = options;
let useWrapper;
if (useDelay && useFunction) {
useWrapper = ContentWrapper.useFunctionReturnPromise.bind(null, content, useDelay);
}
else if (useDelay) {
useWrapper = ContentWrapper.usePromise.bind(null, content, useDelay);
}
else if (useFunction) {
useWrapper = ContentWrapper.useFunction.bind(null, content);
}
else {
useWrapper = ContentWrapper.useObject.bind(null, content);
}
return useWrapper();
};
fileContent = fileWrapper(fileContent);
}
await checkAndCreateFolder(path.dirname(mockFileName));
await fs.promises.writeFile(
mockFileName,
fileContent,
{
encoding: 'utf8',
flag: 'w'
}
);
console.log(chalk.yellow(`Mock file created in ${mockFileName}\n`));
}
function applyFilter(filters, data) {
filters.forEach(filter => {
// find matched route filter
if (filter.custom) return;
if (filter.when === 'request') return;
if (filter.applyRoute !== '*' && data.CACHE_REQUEST_DATA.url.indexOf(filter.applyRoute) === -1) return;
if (filter.field) {
if (filter.where === 'headers') {
data[HEADERS_FIELD_TEXT][filter.field] = filter.value;
}
else if (filter.where === 'data') {
data[filter.field] = filter.value;
}
else if (filter.where === 'body') {
data[filter.field] = filter.value;
}
}
});
}