Request is green-ish.

This commit is contained in:
David Diaz 2020-11-22 16:09:25 -06:00
parent c82ee555c2
commit 164c6665bb
7 changed files with 90 additions and 59 deletions

View File

@ -1,5 +1,5 @@
const Request = require('../request') import Request from '../request'
const RequestCache = require('../requestCache') import RequestCache from '../requestCache'
const requestPromiseNativeMock = require('request-promise-native') const requestPromiseNativeMock = require('request-promise-native')
describe('Request', () => { describe('Request', () => {
@ -45,11 +45,11 @@ describe('Request', () => {
}) })
it('should load up the given request', () => { it('should load up the given request', () => {
expect(request.VERB).toBe('POST') expect(request.verb).toBe('POST')
expect(request.ENDPOINT).toBe(validRequestConfig.endpoint) expect(request.endpoint).toBe(validRequestConfig.endpoint)
expect(request.HEADERS).toBeDefined() expect(request.headers).toBeDefined()
expect(request.PAYLOAD).toBeDefined() expect(request.payload).toBeDefined()
expect(request.PARAMS).toBeDefined() expect(request.params).toBeDefined()
}) })
it('should throw if a given request is invalid', () => { it('should throw if a given request is invalid', () => {
@ -57,9 +57,9 @@ describe('Request', () => {
}) })
it('should list all of its dependencies', () => { it('should list all of its dependencies', () => {
expect(request.DEPENDENCIES.size).toBe(2) expect(request.dependencies.size).toBe(2)
expect(request.DEPENDENCIES).toContain('session') expect(request.dependencies).toContain('session')
expect(request.DEPENDENCIES).toContain('profile') expect(request.dependencies).toContain('profile')
}) })
it('should execute a request', async () => { it('should execute a request', async () => {

View File

@ -34,11 +34,11 @@ export type RequestConfig = RequestObject | RequestObject[] | string
export type UObjectString = { [key: string]: UObjectString } | string export type UObjectString = { [key: string]: UObjectString } | string
export default class Config implements BeauConfig { export default class Config implements BeauConfig {
version = moduleVersion() version: number
cookiejar = false cookiejar: boolean
endpoint = '' endpoint: string
defaults: RequestObject = {} defaults: RequestObject
plugins: Plugins plugins: Plugins
environment = {} environment = {}
host?: string = undefined host?: string = undefined

View File

@ -62,7 +62,7 @@ export default class Plugins {
}) })
} }
executeModifier(modifier, obj, orig) { executeModifier(modifier, obj, orig): typeof obj {
let result = deepmerge({}, obj, { isMergeableObject: isPlainObject }) let result = deepmerge({}, obj, { isMergeableObject: isPlainObject })
this.registry[modifier].forEach( this.registry[modifier].forEach(

View File

@ -1,59 +1,85 @@
const request = require('request-promise-native') import request = require('request-promise-native')
const RequestCache = require('./requestCache') import RequestCache from './requestCache'
const Plugins = require('./plugins') import Plugins from './plugins'
const { import {
requestRegex, requestRegex,
replacementRegex, replacementRegex,
UpperCaseKeys, UpperCaseKeys,
removeOptionalKeys, removeOptionalKeys,
isUrl isUrl
} = require('./shared') } from './shared'
import { RequestObject, UObjectString } from './config'
export default class Request { export default class Request implements RequestObject {
constructor(req, plugins = new Plugins()) { originalRequest: RequestObject
plugins: Plugins
endpoint: string
cookiejar: boolean
alias?: string
form: { [key: string]: any }
formdata: { [key: string]: any }
headers: { [key: string]: any }
params: { [key: string]: any }
payload: UObjectString
request: string
verb: string
path: string
constructor(req: RequestObject, plugins = new Plugins()) {
this.originalRequest = req this.originalRequest = req
this.plugins = plugins this.plugins = plugins
this.endpoint = req.endpoint ?? ''
this.cookiejar = req.cookiejar ?? false
this.alias = req.alias ?? undefined
this.form = req.form ?? {}
this.formdata = req.formdata ?? {}
this.payload = req.payload ?? {}
this.headers = req.headers ?? {}
this.params = req.params ?? {}
this.request = req.request ?? ''
req = UpperCaseKeys(req) if (!this.alias) {
Object.assign(this, req) throw new Error(`${this.request} is missing an alias.`)
if (!this.ALIAS) {
throw new Error(`${this.REQUEST} is missing an alias.`)
} }
const { VERB, PATH } = this.parseRequest(this.REQUEST) const { verb, path } = this.parseRequest(this.request)
this.VERB = VERB this.verb = verb
this.PATH = PATH this.path = path
this.DEPENDENCIES = this.findDependencies(req) this.dependencies = this.findDependencies(req)
} }
parseRequest(request) { parseRequest(request: string) {
const parts = request.match(requestRegex) const parts = request.match(requestRegex)
if (parts === null) {
throw new Error('Request path misformed.')
}
return { return {
VERB: parts[1], verb: parts[1],
PATH: parts[2] path: parts[2]
} }
} }
findDependencies(request, set = new Set()) { findDependencies(request: RequestObject | string, set = new Set()) {
let type = typeof request if (typeof request === 'object' && request !== null) {
if (type === 'object' && request !== null) {
Object.entries(request) Object.entries(request)
.filter(([key]) => key !== 'ALIAS') .filter(([key]) => key !== 'alias')
.forEach(([key, value]) => { .forEach(([_, value]) => {
set = this.findDependencies(value, set) set = this.findDependencies(value, set)
}) })
} else if (type === 'string') { } else if (typeof request === 'string') {
const matches = [] const matches: string[] = []
request.replace( request.replace(replacementRegex, (match, g1: any) => {
replacementRegex, if (!match.startsWith('\\')) {
(match, g1) => !match.startsWith('\\') && matches.push(g1) matches.push(g1)
) }
return ''
})
const deps = matches.map((m) => m.split('.')[0]) const deps = matches.map((m) => m.split('.')[0])
@ -66,23 +92,27 @@ export default class Request {
async exec(cache = new RequestCache()) { async exec(cache = new RequestCache()) {
let settings = cache.parse({ let settings = cache.parse({
baseUrl: '', baseUrl: '',
uri: this.PATH, uri: this.path,
method: this.VERB, method: this.verb,
jar: this.COOKIEJAR, jar: this.cookiejar,
headers: this.HEADERS, headers: this.headers,
qs: this.PARAMS, qs: this.params,
body: this.PAYLOAD, body: this.payload,
form: this.FORM, form: this.form,
formData: this.FORMDATA, formData: this.formdata,
json: true, json: true,
simple: false, simple: false,
resolveWithFullResponse: true resolveWithFullResponse: true
}) })
if (typeof settings !== 'object' || settings === null) {
throw new Error('Error parsing request.')
}
const isPathFullUrl = isUrl(settings.uri) const isPathFullUrl = isUrl(settings.uri)
settings.baseUrl = isPathFullUrl ? '' : this.ENDPOINT settings.baseUrl = isPathFullUrl ? '' : this.endpoint
settings = removeOptionalKeys(settings, [ settings = removeOptionalKeys(settings, [
'headers', 'headers',
@ -122,7 +152,7 @@ export default class Request {
this.originalRequest this.originalRequest
) )
cache.add(this.ALIAS, results) cache.add(this.alias!, results)
return results return results
} }

View File

@ -30,7 +30,9 @@ export default class RequestCache {
return result return result
} }
parse(item: UObjectString | null | undefined) { parse(
item: { [key: string]: any } | null | undefined
): string | null | { [key: string]: any } {
if (item === null) { if (item === null) {
return null return null
} }

View File

@ -1,5 +1,4 @@
import Config, { RequestObject } from './config' import Config from './config'
import Plugins from './plugins'
import Request from './request' import Request from './request'
import RequestCache from './requestCache' import RequestCache from './requestCache'