@useoptic/cli
Advanced tools
Comparing version 0.1.1-alpha to 0.1.2-alpha
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
process.env.DEBUG = process.env.DEBUG ? `${process.env.DEBUG},optic:*` : 'optic:*'; | ||
const debug = require("debug"); | ||
const child_process_1 = require("child_process"); | ||
const fs = require("fs"); | ||
const util = require("util"); | ||
const common_1 = require("../common"); | ||
@@ -11,2 +12,4 @@ const logging_server_1 = require("../logging-server"); | ||
const report_builder_1 = require("../report-builder"); | ||
const logCli = debug('optic:cli'); | ||
const debugCliVerbose = debug('optic-debug:cli'); | ||
class OpticCli { | ||
@@ -18,3 +21,3 @@ constructor(options) { | ||
handleSample(sample) { | ||
console.log('got sample'); | ||
debugCliVerbose('got sample'); | ||
this.samples.push(sample); | ||
@@ -46,12 +49,13 @@ } | ||
const task = new Promise((resolve) => { | ||
console.log(`running $ ${command} in ${taskOptions.cwd}`); | ||
logCli(`running $ ${command}`); | ||
logCli(`in ${taskOptions.cwd}`); | ||
const child = child_process_1.spawn(command, taskOptions); | ||
child.stdout.on('data', function (data) { | ||
console.log(data.toString()); | ||
process.stdout.write(data); | ||
}); | ||
child.stderr.on('data', function (data) { | ||
console.error(data.toString()); | ||
process.stderr.write(data); | ||
}); | ||
child.on('exit', function (code) { | ||
console.log(`child process exited with code ${code.toString()}`); | ||
logCli(`child process exited with code ${code.toString()}`); | ||
resolve(code === 0); | ||
@@ -90,2 +94,3 @@ }); | ||
paths: [ | ||
'/uses', | ||
'/users', | ||
@@ -95,5 +100,5 @@ '/users/login', | ||
], | ||
security: { | ||
type: 'bearer', | ||
}, | ||
security: [{ | ||
type: 'bearer', | ||
}], | ||
documentationStrategy: { | ||
@@ -106,12 +111,11 @@ type: 'proxy', | ||
}; | ||
const options = cliOptionsForProxy; | ||
const cli = new OpticCli(options); | ||
const cliOptions = cliOptionsForProxy; | ||
const cli = new OpticCli(cliOptions); | ||
cli | ||
.run() | ||
.then((successful) => { | ||
console.log(`I observed ${cli.samples.length} API interactions!`); | ||
if (successful) { | ||
console.log('generating API spec...'); | ||
const observations = new report_builder_1.ReportBuilder().buildReport(options, cli.samples); | ||
return observations; | ||
logCli('working...'); | ||
const report = new report_builder_1.ReportBuilder().buildReport(cliOptions, cli.samples); | ||
return report; | ||
} | ||
@@ -122,9 +126,11 @@ else { | ||
}) | ||
.then((observations) => { | ||
.then((report) => { | ||
logCli('done!'); | ||
const { messages, observations } = report; | ||
messages.forEach((message) => logCli(message)); | ||
fs.writeFileSync('./optic-observations.json', JSON.stringify(observations)); | ||
const observationsToGraph = new observations_to_graph_1.ObservationsToGraph(); | ||
observationsToGraph.interpretObservations(observations); | ||
console.log(util.inspect(observationsToGraph.graph, { depth: 5, compact: false, colors: true })); | ||
console.log('\n visualize graphviz.txt on http://www.webgraphviz.com/'); | ||
fs.writeFileSync('./graphviz.txt', observationsToGraph.graph.toGraphViz()); | ||
}); | ||
//# sourceMappingURL=optic-cli.js.map |
@@ -93,3 +93,2 @@ "use strict"; | ||
const pathParameters = pathParser(url); | ||
console.log({ url, pathParameters }); | ||
const pathObservation = { | ||
@@ -136,4 +135,6 @@ type: 'PathObserved', | ||
else if (security.type === 'basic' || security.type === 'bearer') { | ||
if (requestHeaders.authorization) { | ||
const name = 'authorization'; | ||
if (requestHeaders[name]) { | ||
foundSecurityInRequest = true; | ||
additionalHeadersToIgnore.add(name); | ||
} | ||
@@ -147,2 +148,3 @@ } | ||
statusCode, | ||
security | ||
}; | ||
@@ -206,3 +208,2 @@ observations.push(securityObservation); | ||
observations.push(requestBodyObservation); | ||
console.log({ requestBodyObservation }); | ||
} | ||
@@ -225,5 +226,3 @@ Object.keys(responseHeaders) | ||
if (responseCookie) { | ||
console.log({ responseCookie }); | ||
const parsedCookie = cookie_1.parse(responseCookie.join(';')); | ||
console.log({ parsedCookie }); | ||
Object.keys(parsedCookie) | ||
@@ -254,3 +253,2 @@ .forEach((cookieKey) => { | ||
observations.push(responseBodyObservation); | ||
console.log({ responseBodyObservation }); | ||
} | ||
@@ -257,0 +255,0 @@ return observations; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const express = require("express"); | ||
const debug = require("debug"); | ||
const cookieParser = require("cookie-parser"); | ||
@@ -15,2 +16,4 @@ const bodyParser = require("body-parser"); | ||
}; | ||
const debugLoggingServer = debug('optic:server:logging-server'); | ||
const debugLoggingServerVerbose = debug('optic-debug:server:logging-server'); | ||
class LoggingServer extends EventEmitter { | ||
@@ -24,3 +27,3 @@ constructor() { | ||
start(options) { | ||
console.log('starting logging servers...'); | ||
debugLoggingServer('starting logging servers...'); | ||
const promises = [ | ||
@@ -39,7 +42,6 @@ this.startRequestLogging(options), | ||
requestLoggingServer.use((_req, _res, next) => { | ||
console.log('request logger'); | ||
console.log(_req); | ||
debugLoggingServerVerbose('receiving request'); | ||
next(); | ||
}); | ||
requestLoggingServer.all('/*', (req, res) => { | ||
requestLoggingServer.all('/', (req, res) => { | ||
const id = idGenerator.next().value.toString(); | ||
@@ -54,3 +56,3 @@ const request = common_1.packageRequest(req); | ||
this.httpInstances.push(instance); | ||
console.log(`listening for requests on port ${options.requestLoggingServerPort}`); | ||
debugLoggingServer(`listening for requests on port ${options.requestLoggingServerPort}`); | ||
resolve(); | ||
@@ -66,8 +68,7 @@ }) | ||
responseLoggingServer.use((_req, _res, next) => { | ||
console.log('response logger'); | ||
console.log(_req); | ||
debugLoggingServerVerbose('receiving response'); | ||
next(); | ||
}); | ||
responseLoggingServer.post('/request/:requestId/status/:statusCode', (req, res) => { | ||
const id = req.params.requestId; | ||
responseLoggingServer.post('/interactions/:interactionId/status/:statusCode', (req, res) => { | ||
const id = req.params.interactionId; | ||
if (!this.requests.has(id)) { | ||
@@ -97,3 +98,3 @@ return res.status(404).json({ message: `no request with id ${id} has been logged yet` }); | ||
this.httpInstances.push(instance); | ||
console.log(`listening for responses on port ${options.responseLoggingServerPort}`); | ||
debugLoggingServer(`listening for responses on port ${options.responseLoggingServerPort}`); | ||
resolve(); | ||
@@ -100,0 +101,0 @@ }) |
@@ -5,3 +5,3 @@ "use strict"; | ||
const lodash = require("lodash"); | ||
const graph_1 = require("./graph"); | ||
const graph_1 = require("./graph/graph"); | ||
const generate_schema_js_1 = require("./generate-schema.js"); | ||
@@ -47,3 +47,5 @@ const _ = deepdash(lodash); | ||
id: `(${ResponseStatusCodeNode(path, method, statusCode).id})|(${type})`, | ||
data: { count: 1 }, | ||
data: { | ||
count: 1, | ||
}, | ||
}; | ||
@@ -56,7 +58,9 @@ } | ||
id: `(${ResponseStatusCodeNode(path, method, statusCode).id})|(${type})`, | ||
data: { count: 1 }, | ||
data: { | ||
count: 1, | ||
}, | ||
}; | ||
} | ||
function SecurityNode() { | ||
const type = 'security'; | ||
function SecurityNode(security) { | ||
const type = 'securityDefinition'; | ||
return { | ||
@@ -66,2 +70,3 @@ type, | ||
data: { | ||
security, | ||
count: 1, | ||
@@ -77,2 +82,4 @@ }, | ||
data: { | ||
source, | ||
name, | ||
count: 1, | ||
@@ -98,2 +105,3 @@ }, | ||
data: { | ||
contentType, | ||
count: 1, | ||
@@ -159,3 +167,3 @@ }, | ||
this.graph = new graph_1.Graph(); | ||
this.graph.addNode('root', 'root', {}); | ||
this.graph.addNode(graph_1.rootNodeId, 'root', {}); | ||
} | ||
@@ -194,5 +202,6 @@ interpretObservations(observations) { | ||
else if (observation.type === 'SecurityObserved') { | ||
const { path, method, statusCode } = observation; | ||
const node = SecurityNode(); | ||
const { path, method, statusCode, security } = observation; | ||
const node = SecurityNode(security); | ||
if (this.graph.tryAddNode(node.id, node.type, node.data)) { | ||
this.graph.addEdge(node.id, 'root'); | ||
const requestNode = RequestNode(path, method, statusCode); | ||
@@ -199,0 +208,0 @@ this.graph.ensureEdgeExistsBetween(requestNode.id, node.id); |
@@ -7,4 +7,7 @@ "use strict"; | ||
const bodyParser = require("body-parser"); | ||
const debug = require("debug"); | ||
const common_1 = require("./common"); | ||
const EventEmitter = require("events"); | ||
const debugProxyServerVerbose = debug('optic-debug:server:proxy-server'); | ||
const debugProxyServer = debug('optic:server:proxy-server'); | ||
class ProxyServer extends EventEmitter { | ||
@@ -39,3 +42,3 @@ start(options) { | ||
server.use('/', (_req, _res, next) => { | ||
console.log('got req'); | ||
debugProxyServerVerbose('got request'); | ||
next(); | ||
@@ -46,4 +49,4 @@ }, proxyMiddleware); | ||
.listen(options.proxyPort, () => { | ||
console.log(`proxy listening on port ${options.proxyPort}`); | ||
console.log(`proxy forwarding requests to ${options.targetHost}:${options.targetPort}`); | ||
debugProxyServer(`proxy listening on port ${options.proxyPort}`); | ||
debugProxyServer(`proxy forwarding requests to ${options.targetHost}:${options.targetPort}`); | ||
resolve(); | ||
@@ -50,0 +53,0 @@ }) |
@@ -7,16 +7,36 @@ "use strict"; | ||
buildReport(options, samples) { | ||
const messages = []; | ||
if (samples.length === 0) { | ||
messages.push('I did not observe any API interactions :('); | ||
} | ||
else { | ||
messages.push(`I observed ${samples.length} API interactions!`); | ||
} | ||
const pathMatcherList = options.paths.map(common_1.pathToMatcher); | ||
const config = { | ||
pathMatcherList, | ||
security: options.security | ||
security: options.security[0], | ||
}; | ||
const observations = interactions_to_observations_1.InteractionsToObservations.getObservations(samples, config); | ||
const recognizedPathObservations = observations.filter((x) => x.type === 'PathObserved'); | ||
const recognizedPaths = new Set(recognizedPathObservations.map((x) => x.path)); | ||
const uncoveredPaths = new Set(pathMatcherList | ||
.filter(({ path }) => !recognizedPaths.has(path)) | ||
.map(({ path }) => path)); | ||
if (uncoveredPaths.size > 0) { | ||
const uncoveredPathList = [...uncoveredPaths].map((path) => ` - ${path}`).join('\n'); | ||
messages.push(`I noticed that the following paths from your configuration were not interacted with: | ||
${uncoveredPathList}`); | ||
} | ||
const unrecognizedUrlObservations = observations.filter((x) => x.type === 'UnrecognizedUrlObserved'); | ||
const unrecognizedUrls = common_1.Counter.count(unrecognizedUrlObservations, (x) => x.url); | ||
if (unrecognizedUrls.size > 0) { | ||
console.log(`I observed ${unrecognizedUrls.size} interactions with paths I did not recognize:`); | ||
console.log([...unrecognizedUrls.entries()].map(([url, count]) => `${url}: ${count}`).join('\n')); | ||
const unrecognizedUrlList = [...unrecognizedUrls.entries()].map(([url, count]) => ` - ${url}: ${count}`).join('\n'); | ||
messages.push(`I observed ${unrecognizedUrls.size} interactions with paths I did not recognize: | ||
${unrecognizedUrlList}`); | ||
} | ||
console.log(JSON.stringify(observations, null, 2)); | ||
return observations; | ||
return { | ||
messages, | ||
observations, | ||
}; | ||
} | ||
@@ -23,0 +43,0 @@ } |
{ | ||
"name": "@useoptic/cli", | ||
"version": "0.1.1-alpha", | ||
"version": "0.1.2-alpha", | ||
"description": "Optic CLI", | ||
@@ -42,2 +42,3 @@ "engines": { | ||
"cookie-parser": "^1.4.3", | ||
"debug": "^4.1.1", | ||
"deepdash": "^1.9.5", | ||
@@ -44,0 +45,0 @@ "express": "^4.16.4", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
113401
27
1461
1
12
6
+ Addeddebug@^4.1.1
+ Addeddebug@4.3.7(transitive)