Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

smoke

Package Overview
Dependencies
Maintainers
2
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

smoke - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

lib/convert.js

7

CHANGELOG.md

@@ -0,1 +1,8 @@

# 2.1.0
- Add `--collection` option to allow recording to a mock collection
- Add `--save-query` option to save query parameters when recording
- Add `--depth` option for mock conversion
- Change shorthand param for `--ignore` from `-g` to `-i`
- Fix `--ignore` param for `smoke-conv` tool
# 2.0.0

@@ -2,0 +9,0 @@ - Add support for single file mock collections

3

lib/mock.js

@@ -30,3 +30,3 @@ const path = require('path');

if (data !== undefined) {
ext = typeof data === 'function' ? 'js' : ext !== null && typeof data === 'object' ? 'json' : ext;
ext = typeof data === 'function' ? 'js' : !ext && typeof data === 'object' ? 'json' : ext;
}

@@ -82,3 +82,2 @@

return {
originalFile: file,
file: path.join(basePath, file),

@@ -85,0 +84,0 @@ ext,

@@ -5,2 +5,5 @@ const path = require('path');

const {getMocksFromCollections} = require('./mock');
const mockCollectionExt = '.mocks.js';
const stringTypes = [

@@ -19,18 +22,2 @@ 'application/json',

async function record(req, res, data, options) {
let file = req.method.toLowerCase() + '_';
const pathComponents = req.path
.substring(1)
.split('/')
.filter(c => c);
if (options.depth > 0) {
file = path.join(pathComponents.splice(0, options.depth).join(path.sep), file);
}
file += pathComponents.join('#');
if (options.set) {
file += '__' + options.set;
}
const contentTypeHeader = Object.keys(res.headers).find(h => h.toLowerCase() === 'content-type');

@@ -54,15 +41,17 @@ const contentType = contentTypeHeader && res.headers[contentTypeHeader].toLowerCase();

if (ext) {
file += '.' + ext;
}
file = path.join(options.basePath, file);
try {
await fs.mkdirp(path.dirname(file));
const mock = {
reqPath: req.path,
methods: [req.method.toLowerCase()],
params: options.saveQueryParams ? req.query : null,
set: options.set,
isTemplate: false,
ext,
data
};
if (isCustomMock) {
await fs.writeJSON(file, data, {spaces: 2});
if (options.collection) {
await appendToMockCollection(mock, path.join(options.basePath, options.collection));
} else {
await fs.writeFile(file, data);
await writeMock(mock, options.basePath, options.depth);
}

@@ -74,5 +63,125 @@ } catch (error) {

async function appendToMockCollection(mock, outputFile) {
if (!outputFile.endsWith(mockCollectionExt)) {
outputFile += mockCollectionExt;
}
const mocks = (await fs.pathExists(outputFile)) ? await getMocksFromCollections(process.cwd(), [outputFile]) : [];
return writeMockCollection(mocks.concat(mock), outputFile);
}
async function writeMock(mock, outputFolder, depth) {
let content = mock.data;
if (content === null) {
content = '';
} else if (typeof content === 'function') {
content = `module.exports = ${content.toString()};`;
} else if (typeof content === 'object' && !(content instanceof Buffer)) {
content = JSON.stringify(content, null, 2);
}
const outputFile = path.join(outputFolder, buildFile(mock, depth));
await fs.mkdirp(path.dirname(outputFile));
await fs.writeFile(outputFile, content);
}
async function writeMockCollection(mocks, outputFile) {
if (!outputFile.endsWith(mockCollectionExt)) {
outputFile += mockCollectionExt;
}
mocks.forEach(mock => {
// Fix string content types
if (mock.ext && isStringContent(mime.lookup(mock.ext)) && mock.data instanceof Buffer) {
mock.data = mock.data.toString('utf8');
}
});
let collection = indent(mocks.map(mock => `"${buildFile(mock, 0)}": ${stringifyMockData(mock)}`).join(',\n'));
collection = `module.exports = {\n${collection}\n};\n`;
await fs.mkdirp(path.dirname(outputFile));
await fs.writeFile(outputFile, collection);
}
function stringifyMockData(mock) {
if (!mock.data) {
return 'null';
}
if (typeof mock.data === 'string') {
return mock.ext !== 'json' || mock.isTemplate ? `"${escapeString(mock.data)}"` : mock.data.trim();
}
if (mock.data instanceof Buffer) {
return JSON.stringify(
{
statusCode: 200,
body: mock.data.toString('base64'),
buffer: true
},
null,
2
);
}
if (typeof mock.data === 'object') {
return JSON.stringify(mock.data, null, 2).trim();
}
return mock.data;
}
function escapeString(str) {
return JSON.stringify(str).slice(1, -1);
}
function indent(str) {
const regex = /^(?!\s*$)/gm;
return str.replace(regex, ' ');
}
function buildFile(mock, depth) {
let file = '';
if (mock.methods && mock.methods.length > 0) {
file += mock.methods.join('+') + '_';
}
const reqPath = mock.reqPath[0] === '/' ? mock.reqPath.substring(1) : mock.reqPath;
const pathComponents = reqPath.split('/').filter(c => c);
if (depth > 0) {
file = path.join(pathComponents.splice(0, depth).join(path.sep), file);
}
file += pathComponents.join('#');
if (mock.params) {
Object.entries(mock.params).forEach(([key, value], index) => {
file += `${index === 0 ? '$' : '&'}${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
});
}
if (mock.set) {
file += '__' + mock.set;
}
if (mock.ext) {
file += '.' + mock.ext;
if (mock.isTemplate) {
file += '_';
}
}
return file;
}
module.exports = {
isStringContent,
mockCollectionExt,
writeMock,
writeMockCollection,
record
};
{
"name": "smoke",
"version": "2.0.0",
"version": "2.1.0",
"description": "Simple yet powerful file-based mock server with recording abilities",
"main": "smoke.js",
"main": "lib/smoke.js",
"bin": {

@@ -44,4 +44,4 @@ "smoke": "./bin/smoke",

"devDependencies": {
"jest": "^23.6.0",
"supertest": "^3.4.1",
"jest": "^24.1.0",
"supertest": "^3.4.2",
"xo": "^0.24.0"

@@ -68,2 +68,6 @@ },

},
"prettier": {
"singleQuote": true,
"bracketSpacing": false
},
"engines": {

@@ -70,0 +74,0 @@ "node": ">=8.0.0"

@@ -59,3 +59,3 @@ # :dash: smoke

-n, --not-found <glob> Mocks for 404 errors [default: "404.*"]
-g, --ignore <glob> Files to ignore [default: none]
-i, --ignore <glob> Files to ignore [default: none]
-k, --hooks <file> Middleware hooks [default: none]

@@ -71,2 +71,3 @@ -x, --proxy <host> Fallback proxy if no mock found

-a, --save-headers Save response headers
-q, --save-query Save query parameters
```

@@ -232,3 +233,3 @@

In addition, you can define dynamic mocks using JavaScript by using the `.js` extension, that will be loaded as a regular
NodeJS module.
Node.js module.

@@ -273,4 +274,4 @@ In that case, your JS module is expected to export a function that take an input data object with the

Note that by default response headers are not saved and simple mocks are generated. To change this behavior, you can
enable the `--save-headers` option.
Note that by default response headers and request query parameters are not saved. To change this behavior, you can
use the `--save-headers` and `--save-query` options.

@@ -337,3 +338,3 @@ ### Middleware hooks

If you cannot find what you need here, you might want to check out one of these other NodeJS mock servers:
If you cannot find what you need here, you might want to check out one of these other Node.js mock servers:

@@ -340,0 +341,0 @@ - [JSON Server](https://github.com/typicode/json-server)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc