Adding stats, code, timings and size of request.
This commit is contained in:
parent
5936fe0f5f
commit
99e2cd52e8
5 changed files with 75 additions and 63 deletions
|
@ -109,7 +109,7 @@ exports.preview = async function (ctx) {
|
||||||
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { rows, keys } = await Runner.run({
|
const { rows, keys, info } = await Runner.run({
|
||||||
datasource,
|
datasource,
|
||||||
queryVerb,
|
queryVerb,
|
||||||
query: enrichedQuery,
|
query: enrichedQuery,
|
||||||
|
@ -119,6 +119,7 @@ exports.preview = async function (ctx) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
rows,
|
rows,
|
||||||
schemaFields: [...new Set(keys)],
|
schemaFields: [...new Set(keys)],
|
||||||
|
info,
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.throw(400, err)
|
ctx.throw(400, err)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export interface IntegrationBase {
|
export interface IntegrationBase {
|
||||||
create?(query: any): Promise<any[]>
|
create?(query: any): Promise<any[]|any>
|
||||||
read?(query: any): Promise<any[]>
|
read?(query: any): Promise<any[]|any>
|
||||||
update?(query: any): Promise<any[]>
|
update?(query: any): Promise<any[]|any>
|
||||||
delete?(query: any): Promise<any[]>
|
delete?(query: any): Promise<any[]|any>
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ const coreFields = {
|
||||||
|
|
||||||
module RestModule {
|
module RestModule {
|
||||||
const fetch = require("node-fetch")
|
const fetch = require("node-fetch")
|
||||||
|
const { formatBytes } = require("../utilities")
|
||||||
|
const { performance } = require("perf_hooks")
|
||||||
|
|
||||||
interface RestConfig {
|
interface RestConfig {
|
||||||
url: string
|
url: string
|
||||||
|
@ -46,6 +48,13 @@ module RestModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Request {
|
||||||
|
path: string
|
||||||
|
queryString?: string
|
||||||
|
headers?: string
|
||||||
|
json?: any
|
||||||
|
}
|
||||||
|
|
||||||
const SCHEMA: Integration = {
|
const SCHEMA: Integration = {
|
||||||
docs: "https://github.com/node-fetch/node-fetch",
|
docs: "https://github.com/node-fetch/node-fetch",
|
||||||
description:
|
description:
|
||||||
|
@ -102,17 +111,29 @@ module RestModule {
|
||||||
private headers: {
|
private headers: {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
} = {}
|
} = {}
|
||||||
|
private startTimeMs: number = performance.now()
|
||||||
|
|
||||||
constructor(config: RestConfig) {
|
constructor(config: RestConfig) {
|
||||||
this.config = config
|
this.config = config
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseResponse(response: any) {
|
async parseResponse(response: any) {
|
||||||
|
let data
|
||||||
const contentType = response.headers.get("content-type")
|
const contentType = response.headers.get("content-type")
|
||||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||||
return await response.json()
|
data = await response.json()
|
||||||
} else {
|
} else {
|
||||||
return await response.text()
|
data = await response.text()
|
||||||
|
}
|
||||||
|
const size = formatBytes(response.headers.get("content-length") || 0)
|
||||||
|
const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
info: {
|
||||||
|
code: response.status,
|
||||||
|
size,
|
||||||
|
time,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,76 +146,40 @@ module RestModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async create({ path = "", queryString = "", headers = {}, json = {} }) {
|
async _req({ path = "", queryString = "", headers = {}, json = {}, method = "GET" }) {
|
||||||
this.headers = {
|
this.headers = {
|
||||||
...this.config.defaultHeaders,
|
...this.config.defaultHeaders,
|
||||||
...headers,
|
...headers,
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
const input: any = { method, headers: this.headers }
|
||||||
method: "POST",
|
if (json && typeof json === "object" && Object.keys(json).length > 0) {
|
||||||
headers: this.headers,
|
input.body = JSON.stringify(json)
|
||||||
body: JSON.stringify(json),
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
this.startTimeMs = performance.now()
|
||||||
|
const response = await fetch(this.getUrl(path, queryString), input)
|
||||||
return await this.parseResponse(response)
|
return await this.parseResponse(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
async read({ path = "", queryString = "", headers = {} }) {
|
async create(opts: Request) {
|
||||||
this.headers = {
|
return this._req({ ...opts, method: "POST" })
|
||||||
...this.config.defaultHeaders,
|
|
||||||
...headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
|
||||||
headers: this.headers,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.parseResponse(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update({ path = "", queryString = "", headers = {}, json = {} }) {
|
async read(opts: Request) {
|
||||||
this.headers = {
|
return this._req({ ...opts, method: "GET" })
|
||||||
...this.config.defaultHeaders,
|
|
||||||
...headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
|
||||||
method: "PUT",
|
|
||||||
headers: this.headers,
|
|
||||||
body: JSON.stringify(json),
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.parseResponse(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async patch({ path = "", queryString = "", headers = {}, json = {} }) {
|
async update(opts: Request) {
|
||||||
this.headers = {
|
return this._req({ ...opts, method: "PUT" })
|
||||||
...this.config.defaultHeaders,
|
|
||||||
...headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
|
||||||
method: "PATCH",
|
|
||||||
headers: this.headers,
|
|
||||||
body: JSON.stringify(json),
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.parseResponse(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete({ path = "", queryString = "", headers = {} }) {
|
async patch(opts: Request) {
|
||||||
this.headers = {
|
return this._req({ ...opts, method: "PATCH" })
|
||||||
...this.config.defaultHeaders,
|
}
|
||||||
...headers,
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(this.getUrl(path, queryString), {
|
async delete(opts: Request) {
|
||||||
method: "DELETE",
|
return this._req({ ...opts, method: "DELETE" })
|
||||||
headers: this.headers,
|
|
||||||
})
|
|
||||||
|
|
||||||
return await this.parseResponse(response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ function formatResponse(resp) {
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasExtraData(response) {
|
||||||
|
return (
|
||||||
|
typeof response === "object" &&
|
||||||
|
!Array.isArray(response) &&
|
||||||
|
response.data &&
|
||||||
|
response.info
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async function runAndTransform(datasource, queryVerb, query, transformer) {
|
async function runAndTransform(datasource, queryVerb, query, transformer) {
|
||||||
const Integration = integrations[datasource.source]
|
const Integration = integrations[datasource.source]
|
||||||
if (!Integration) {
|
if (!Integration) {
|
||||||
|
@ -22,7 +31,13 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
||||||
}
|
}
|
||||||
const integration = new Integration(datasource.config)
|
const integration = new Integration(datasource.config)
|
||||||
|
|
||||||
let rows = formatResponse(await integration[queryVerb](query))
|
let output = formatResponse(await integration[queryVerb](query))
|
||||||
|
let rows = output,
|
||||||
|
info = undefined
|
||||||
|
if (hasExtraData(output)) {
|
||||||
|
rows = output.data
|
||||||
|
info = output.info
|
||||||
|
}
|
||||||
|
|
||||||
// transform as required
|
// transform as required
|
||||||
if (transformer) {
|
if (transformer) {
|
||||||
|
@ -47,7 +62,7 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
|
||||||
integration.end()
|
integration.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
return { rows, keys }
|
return { rows, keys, info }
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (input, callback) => {
|
module.exports = (input, callback) => {
|
||||||
|
|
|
@ -150,3 +150,14 @@ exports.doesDatabaseExist = async dbName => {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.formatBytes = bytes => {
|
||||||
|
const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
||||||
|
const byteIncrements = 1024
|
||||||
|
let unit = 0
|
||||||
|
let size = parseInt(bytes, 10) || 0
|
||||||
|
while (size >= byteIncrements && ++unit) {
|
||||||
|
size /= byteIncrements
|
||||||
|
}
|
||||||
|
return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue