Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

snapstub

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

snapstub - npm Package Compare versions

Comparing version
5.0.0
to
5.0.1
+112
commands//add.js
'use strict';
const fs = require('fs');
const got = require('got');
const out = require('simple-output');
const parseHeaders = require('parse-headers');
const {parse} = require('query-string');
const saveCmd = require('./save');
function addCmd({addOptions, mockFolderName, url}) {
const customHeaders = [].concat(addOptions.header).join('\n');
function getData() {
let data = addOptions.data;
let body;
let type;
let form = false;
let json = false;
try {
data = fs.readFileSync(data).toString();
} catch (e) {
}
try {
body = JSON.parse(data);
type = 'application/json';
json = true;
} catch (e) {
try {
body = parse(data);
type = 'application/x-www-form-urlencoded';
form = true;
} catch (e) {
body = data;
type = 'text/plain';
}
}
return {
body,
form,
json,
type
};
}
function getOpts(method) {
let opts = {
headers: parseHeaders(customHeaders),
json: !addOptions.nojson,
method: method.trim().toLowerCase()
};
// Set body data, skips only TRACE method
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
if (method !== 'trace' && addOptions.data) {
let data = getData();
const baseOpts = Object.assign({}, opts, {
form: data.form,
json: data.json && !addOptions.nojson
});
// If no method was set using data, defaults to post
if (!addOptions.method) {
baseOpts.method = 'post';
}
// Sets data and content-type for request
opts = Object.assign({}, baseOpts, {
body: data.body,
headers: Object.assign({
'content-type': data.type
}, baseOpts.headers)
});
}
return opts;
}
const reqs = (addOptions.method || 'get')
.split(',')
.filter(Boolean)
.map(name => getOpts(name));
Promise.all(
reqs.map(opts => got(url, opts))
)
.then(results => {
reqs.forEach((opts, index) => saveCmd({
mockFolderName,
url: url,
stdin: results[index].body,
saveOptions: {
hashAlgorithm: addOptions.hashAlgorithm,
hashHeaders: addOptions.hashHeaders,
hashCookies: addOptions.hashCookies,
data: opts.body,
headers: opts.headers,
method: opts.method,
nohash: addOptions.nohash,
nojson: addOptions.nojson
}
}));
})
.catch(out.error);
}
module.exports = addCmd;
'use strict';
function helpCmd() {
console.log(`
Usage:
snapstub [command]
Available commands:
help Output usage info
version Get current version number
save Saves data from stdin straight to a url location
start Starts the built-in static mock server
add <url> Takes a snapshot of a given url and stores in the local fs
Options:
--data Request payload body to be send along with add|save command
--method Specifies http method to use along with add|save command
--header Adds a custom header to the request for add|save command
--nohash Don't generate hashed-filenames on add|save command
--nojson Allow for saving html|text only on add|save command
--hashAlgorithm Algorithm to be used for deterministic responses
--hashHeaders Comma-separated list of header keys to be used on hash
--hashCookies Comma-separated list of cookies keys to be used on hash
--verbose Output debug info when used along with the start command
--silent Mutes output when used along with the start command
More info:
https://github.com/ruyadorno/snapstub
`);
}
module.exports = helpCmd;
const fs = require('fs');
const path = require('path');
const {parse: urlParse} = require('url');
const mkdirp = require('mkdirp');
const out = require('simple-output');
const requestHash = require('request-hash');
function saveCmd(opts) {
const {saveOptions, url} = opts;
const stdin = typeof opts.stdin === 'string' ? opts.stdin : JSON.stringify(opts.stdin, undefined, 2);
const getOpts = arr => (arr && arr.split(',').filter(Boolean).map(i => i.trim())) || [];
const {query, pathname} = urlParse(url || '', true);
const {data, headers, hashAlgorithm, hashHeaders, hashCookies, method, nohash, nojson} = saveOptions;
const hashHeadersOpts = getOpts(hashHeaders);
const hashCookiesOpts = getOpts(hashCookies);
const shouldHash = data ||
Object.keys(query).length > 0 ||
(headers && Object.keys(headers).length > 0 && (
(hashHeadersOpts && hashHeadersOpts.length > 0) ||
(hashCookiesOpts && hashCookiesOpts.length > 0)
));
const methods = (method || 'get').split(',');
const mockFolderName = opts.mockFolderName || '__mocks__';
const rootPath = opts.rootPath || path.join(process.cwd(), mockFolderName);
const folderPath = path.join(rootPath, pathname);
const fileExt = nojson ? '.js' : '.json';
methods.forEach(method => {
const hashSuffix = !nohash && shouldHash ?
'-' + requestHash({
algorithm: hashAlgorithm,
headers: hashHeadersOpts,
cookies: hashCookiesOpts
})({
method,
url,
body: data,
headers
}) :
'';
const fileName = path.join(
folderPath,
method.toLowerCase().trim() + hashSuffix + fileExt
);
const fileContent = nojson ?
`module.exports = (req, res) => { res.send('${stdin}'); };` :
stdin;
// Creates mocks folder
mkdirp.sync(folderPath);
// Writes mock file
fs.writeFileSync(fileName, fileContent);
out.success(`Successfully added: ${fileName}`);
});
}
module.exports = saveCmd;
'use strict';
const out = require('simple-output');
const globby = require('globby');
const methods = require('methods');
const hashLoader = require('stubborn-server-hash-loader');
function startCmd(opts) {
const mockFolderName = opts.mockFolderName || '__mocks__';
const port = opts.port || 8059;
try {
opts.stubborn.start({
logMode: opts.verbose ? 'all' : 'warn',
namespace: '',
pathToMocks: mockFolderName,
servePort: port,
fallbacks: [],
plugins: [
{
loader: hashLoader({
algorithm: opts.hashAlgorithm,
headers: opts.hashHeaders || [],
cookies: opts.hashCookies || []
})
}
]
});
if (!opts.silent) {
out.success('Successfully launched snapstub server on: ' +
'http://localhost:' + port);
printRoutes(mockFolderName, port);
}
} catch (e) {
out.error('Failed to launch snapstub server');
}
}
function printRoutes(srcPath, port) {
const patterns = methods.map(m => `**/${m}.+(json|js)`);
globby(patterns, {cwd: srcPath})
.then(paths => {
const routes = paths.map(p => {
// Remove filename from path
const directoryPath = p.substring(0, p.lastIndexOf('/'));
return `http://localhost:${port}/${directoryPath}`;
});
for (let route of new Set(routes)) {
out.info(route);
}
});
}
module.exports = startCmd;
'use strict';
function versionCmd() {
console.log(require('../package.json').version);
}
module.exports = versionCmd;
+5
-3
{
"name": "snapstub",
"version": "5.0.0",
"version": "5.0.1",
"description": "Snapshot-based stub/mocking of APIs",
"main": "index.js",
"bin": "cli.js",
"bin": {
"snapstub": "cli.js"
},
"engines": {

@@ -60,3 +62,3 @@ "node": ">=10"

"methods": "^1.1.2",
"minimist": "^1.2.0",
"minimist": "^1.2.5",
"mkdirp": "^0.5.1",

@@ -63,0 +65,0 @@ "parse-headers": "^2.0.1",

'use strict';
const fs = require('fs');
const got = require('got');
const out = require('simple-output');
const parseHeaders = require('parse-headers');
const {parse} = require('query-string');
const saveCmd = require('./save');
function addCmd({addOptions, mockFolderName, url}) {
const customHeaders = [].concat(addOptions.header).join('\n');
function getData() {
let data = addOptions.data;
let body;
let type;
let form = false;
let json = false;
try {
data = fs.readFileSync(data).toString();
} catch (e) {
}
try {
body = JSON.parse(data);
type = 'application/json';
json = true;
} catch (e) {
try {
body = parse(data);
type = 'application/x-www-form-urlencoded';
form = true;
} catch (e) {
body = data;
type = 'text/plain';
}
}
return {
body,
form,
json,
type
};
}
function getOpts(method) {
let opts = {
headers: parseHeaders(customHeaders),
json: !addOptions.nojson,
method: method.trim().toLowerCase()
};
// Set body data, skips only TRACE method
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
if (method !== 'trace' && addOptions.data) {
let data = getData();
const baseOpts = Object.assign({}, opts, {
form: data.form,
json: data.json && !addOptions.nojson
});
// If no method was set using data, defaults to post
if (!addOptions.method) {
baseOpts.method = 'post';
}
// Sets data and content-type for request
opts = Object.assign({}, baseOpts, {
body: data.body,
headers: Object.assign({
'content-type': data.type
}, baseOpts.headers)
});
}
return opts;
}
const reqs = (addOptions.method || 'get')
.split(',')
.filter(Boolean)
.map(name => getOpts(name));
Promise.all(
reqs.map(opts => got(url, opts))
)
.then(results => {
reqs.forEach((opts, index) => saveCmd({
mockFolderName,
url: url,
stdin: results[index].body,
saveOptions: {
hashAlgorithm: addOptions.hashAlgorithm,
hashHeaders: addOptions.hashHeaders,
hashCookies: addOptions.hashCookies,
data: opts.body,
headers: opts.headers,
method: opts.method,
nohash: addOptions.nohash,
nojson: addOptions.nojson
}
}));
})
.catch(out.error);
}
module.exports = addCmd;
'use strict';
function helpCmd() {
console.log(`
Usage:
snapstub [command]
Available commands:
help Output usage info
version Get current version number
save Saves data from stdin straight to a url location
start Starts the built-in static mock server
add <url> Takes a snapshot of a given url and stores in the local fs
Options:
--data Request payload body to be send along with add|save command
--method Specifies http method to use along with add|save command
--header Adds a custom header to the request for add|save command
--nohash Don't generate hashed-filenames on add|save command
--nojson Allow for saving html|text only on add|save command
--hashAlgorithm Algorithm to be used for deterministic responses
--hashHeaders Comma-separated list of header keys to be used on hash
--hashCookies Comma-separated list of cookies keys to be used on hash
--verbose Output debug info when used along with the start command
--silent Mutes output when used along with the start command
More info:
https://github.com/ruyadorno/snapstub
`);
}
module.exports = helpCmd;
const fs = require('fs');
const path = require('path');
const {parse: urlParse} = require('url');
const mkdirp = require('mkdirp');
const out = require('simple-output');
const requestHash = require('request-hash');
function saveCmd(opts) {
const {saveOptions, url} = opts;
const stdin = typeof opts.stdin === 'string' ? opts.stdin : JSON.stringify(opts.stdin, undefined, 2);
const getOpts = arr => (arr && arr.split(',').filter(Boolean).map(i => i.trim())) || [];
const {query, pathname} = urlParse(url || '', true);
const {data, headers, hashAlgorithm, hashHeaders, hashCookies, method, nohash, nojson} = saveOptions;
const hashHeadersOpts = getOpts(hashHeaders);
const hashCookiesOpts = getOpts(hashCookies);
const shouldHash = data ||
Object.keys(query).length > 0 ||
(headers && Object.keys(headers).length > 0 && (
(hashHeadersOpts && hashHeadersOpts.length > 0) ||
(hashCookiesOpts && hashCookiesOpts.length > 0)
));
const methods = (method || 'get').split(',');
const mockFolderName = opts.mockFolderName || '__mocks__';
const rootPath = opts.rootPath || path.join(process.cwd(), mockFolderName);
const folderPath = path.join(rootPath, pathname);
const fileExt = nojson ? '.js' : '.json';
methods.forEach(method => {
const hashSuffix = !nohash && shouldHash ?
'-' + requestHash({
algorithm: hashAlgorithm,
headers: hashHeadersOpts,
cookies: hashCookiesOpts
})({
method,
url,
body: data,
headers
}) :
'';
const fileName = path.join(
folderPath,
method.toLowerCase().trim() + hashSuffix + fileExt
);
const fileContent = nojson ?
`module.exports = (req, res) => { res.send('${stdin}'); };` :
stdin;
// Creates mocks folder
mkdirp.sync(folderPath);
// Writes mock file
fs.writeFileSync(fileName, fileContent);
out.success(`Successfully added: ${fileName}`);
});
}
module.exports = saveCmd;
'use strict';
const out = require('simple-output');
const globby = require('globby');
const methods = require('methods');
const hashLoader = require('stubborn-server-hash-loader');
function startCmd(opts) {
const mockFolderName = opts.mockFolderName || '__mocks__';
const port = opts.port || 8059;
try {
opts.stubborn.start({
logMode: opts.verbose ? 'all' : 'warn',
namespace: '',
pathToMocks: mockFolderName,
servePort: port,
fallbacks: [],
plugins: [
{
loader: hashLoader({
algorithm: opts.hashAlgorithm,
headers: opts.hashHeaders || [],
cookies: opts.hashCookies || []
})
}
]
});
if (!opts.silent) {
out.success('Successfully launched snapstub server on: ' +
'http://localhost:' + port);
printRoutes(mockFolderName, port);
}
} catch (e) {
out.error('Failed to launch snapstub server');
}
}
function printRoutes(srcPath, port) {
const patterns = methods.map(m => `**/${m}.+(json|js)`);
globby(patterns, {cwd: srcPath})
.then(paths => {
const routes = paths.map(p => {
// Remove filename from path
const directoryPath = p.substring(0, p.lastIndexOf('/'));
return `http://localhost:${port}/${directoryPath}`;
});
for (let route of new Set(routes)) {
out.info(route);
}
});
}
module.exports = startCmd;
'use strict';
function versionCmd() {
console.log(require('../package.json').version);
}
module.exports = versionCmd;