Skip to content

Commit

Permalink
Capture mode and verbose mode added
Browse files Browse the repository at this point in the history
  • Loading branch information
muratcorlu committed Feb 6, 2018
1 parent c3e510f commit 3ff990b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 36 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.0.4 (2018-02-06)

### Features:

- **Capture Mode**: Now you can automatically generate mock files from your api responses.
- **Verbose Mode**: `--verbose` cli parameter added to use verbose mode of connect-api-mocker.

## 1.0.3 (2018-01-12)

### Features:
Expand Down
29 changes: 25 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ That command will start to serve your mocks on port `9090` by default.

## Arguments

`mockit` command has 3 available arguments.
`mockit` command has 4 available arguments.

[-p | --port] with default value `9090`,
[-p | --port] with default value `9090`,
[-f | --fromPath] with default value `/`,
[-t | --toPath] with default value ``
[-c | --capture] with default value `false`
[-v | --verbose] with default value `false`

These arguments are optional. You can use `mockit` command with any one of them or any combination of them.

Expand All @@ -36,9 +38,9 @@ You can see usage examples below:

Or you can combine any of them like:

`mockit --port=8989 --fromPath=/api --toPath=/mapi`
`mockit --port=8989 --fromPath=/api --toPath=/mapi`

Or
Or

`mockit -p 8989 -f '/api -t '/mapi'`

Expand Down Expand Up @@ -96,3 +98,22 @@ module.exports = {
}
```

### Capture mode

With capture mode, you can automatically create mock files from your api origin responses over proxy. You can enable capture mode by `--capture` (or `-c`) command line parameter or `capture` property in config file:

```js
module.exports = {
port: 9090,
map: {
'/api': {
target: 'mocks/api',
proxy: 'https://api.yourdomain.com',
capture: true
}
}
}
```

When capture mode enabled, if you don't have a mock file for a request and if you have a proxy definition, a mock file will automatically generated for you for successful responses from your origin.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{
"name": "cli-api-mocker",
"version": "1.0.3",
"version": "1.0.4",
"description": "CLI wrapper for connect-api-mocker",
"main": "src/index.js",
"dependencies": {
"command-line-args": "^4.0.7",
"connect-api-mocker": "^1.3.5",
"connect-api-mocker": "^1.3.6",
"cors": "^2.8.4",
"express": "^4.15.4",
"http-proxy-middleware": "^0.17.4"
"http-proxy-middleware": "^0.17.4",
"mkdirp": "^0.5.1"
},
"devDependencies": {},
"scripts": {
Expand Down
114 changes: 85 additions & 29 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,127 @@ var apiMocker = require('connect-api-mocker');
var bodyParser = require('body-parser')
var proxy = require('http-proxy-middleware');
var cors = require('cors');
var fs = require('fs');
var pth = require('path');
var mkdirp = require('mkdirp');
var commandLineArgs = require('command-line-args');
var defaultPortValue = 9090;
var defaultFromPathValue = '/';
var defaultToPathValue = '';
var optionDefinitions = [
{ name: 'port', alias: 'p', type: Number, defaultValue: defaultPortValue },
{ name: 'fromPath', alias: 'f', type: String, defaultValue: defaultFromPathValue },
{ name: 'toPath', alias: 't', type: String, defaultValue: defaultToPathValue }
{ name: 'toPath', alias: 't', type: String, defaultValue: defaultToPathValue },
{ name: 'capture', alias: 'c', type: Boolean, defaultValue: false },
{ name: 'verbose', alias: 'v', type: Boolean, defaultValue: false }
];

function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}

var options = commandLineArgs(optionDefinitions);

var app = express();

var mapping = {};

mapping[options.fromPath] = options.toPath;
mapping[options.fromPath] = {
target: options.toPath
};

var defaultConfig = {
port: options.port,
map: mapping
port: options.port,
map: mapping
};
var config = defaultConfig;

try {
var loadedConfig = require(path.resolve(process.cwd() , 'mock.config.js'));
console.log('Config file found mocking!');
var loadedConfig = require(path.resolve(process.cwd() , 'mock.config.js'));
console.log('Config file found mocking!');

if (config.port === defaultPortValue && loadedConfig.port) {
config.port = loadedConfig.port;
}
if (config.port === defaultPortValue && loadedConfig.port) {
config.port = loadedConfig.port;
}

var mapKeys = Object.keys(config.map);
if (loadedConfig.map) {
mapKeys.forEach(function (mapKey) {
loadedConfig.map[mapKey] = config.map[mapKey];
});
config.map = loadedConfig.map;
}
var mapKeys = Object.keys(config.map);
if (loadedConfig.map) {
mapKeys.forEach(function (mapKey) {
loadedConfig.map[mapKey] = config.map[mapKey];
});
config.map = loadedConfig.map;
}
} catch (error) {
// there is no config
// there is no config
}

app.use(cors())
if (options.verbose) {
Object.keys(config.map).forEach(function (key) {
config.map[key].verbose = true;
});
}

for(var path in config.map) {
app.use(cors());

var conf = config.map[path];
for(var path in config.map) {
(function (basePath) {
var conf = config.map[basePath];

if (conf.proxy) {
conf.nextOnNotFound = true;
conf.nextOnNotFound = true;
}

app.use(path, apiMocker(conf));
console.log(`Mocking enabled: ${path} => ${conf}`);
app.use(basePath, apiMocker(conf));
console.log(`Mocking enabled: ${basePath} => ${conf.target || conf}`);

if (conf.proxy) {
console.log(`Proxy enabled: ${path} => ${conf.proxy}`);
if (typeof conf.proxy == 'string') {
config.proxy = {
target: conf.proxy
}
console.log(`Proxy enabled: ${basePath} => ${conf.proxy}`);
if (typeof conf.proxy == 'string') {
conf.proxy = {
target: conf.proxy
}
app.use(path, proxy(conf.proxy));
}

if (conf.capture || options.capture) {
console.log('Capture Mode enabled for mocks!');

conf.proxy.onProxyRes = function(proxyRes, req, res) {
var body = "";
if (proxyRes.statusCode < 404) {
proxyRes.on('data', function(data) {
data = data.toString('utf-8');
body += data;
});

proxyRes.on('end', function() {
var requestedFilePath = req.path.replace(new RegExp('^(\/)?' + escapeRegExp(basePath)), '')
var targetPath = pth.join(conf.target || conf, requestedFilePath);

var contentType = 'json';
if (proxyRes.headers['content-type'].indexOf('xml') > -1) {
contentType = 'xml';
}

mkdirp.sync(targetPath);

var targetFile = pth.join(targetPath, req.method + '.' + contentType);

if (!fs.existsSync(targetFile)) {
fs.writeFileSync(targetFile, body);
console.log('[Capture Mode] New mock file saved to ' + targetFile);
}
});
}
}
}

app.use(basePath, proxy(conf.proxy));
} else {
if (conf.capture || options.capture) {
console.error('You can not use capture mode without defining a proxy.');
}
}
})(path);
}

app.listen(config.port, function () {
Expand Down

0 comments on commit 3ff990b

Please sign in to comment.