diff --git a/src/__tests__/__snapshots__/plugins.spec.js.snap b/src/__tests__/__snapshots__/plugins.spec.ts.snap similarity index 100% rename from src/__tests__/__snapshots__/plugins.spec.js.snap rename to src/__tests__/__snapshots__/plugins.spec.ts.snap diff --git a/src/__tests__/beau.spec.ts b/src/__tests__/beau.spec.ts index a7f5659..b86196e 100644 --- a/src/__tests__/beau.spec.ts +++ b/src/__tests__/beau.spec.ts @@ -1,6 +1,6 @@ import Beau from '../beau' import { parseBeauConfig } from '../config' -import * as shared from '../shared' +const shared = require('../shared') const requireg = require('requireg') requireg.resolving = false diff --git a/src/__tests__/plugins.spec.js b/src/__tests__/plugins.spec.ts similarity index 96% rename from src/__tests__/plugins.spec.js rename to src/__tests__/plugins.spec.ts index 9d6f60d..d62fb7c 100644 --- a/src/__tests__/plugins.spec.js +++ b/src/__tests__/plugins.spec.ts @@ -1,6 +1,6 @@ -const Plugins = require('../plugins') -const Request = require('../request') -const RequestCache = require('../requestCache') +import Plugins from '../plugins' +import Request from '../request' +import RequestCache from '../requestCache' const requireg = require('requireg') describe(`Beau's plugin system`, () => { diff --git a/src/__tests__/shared.spec.js b/src/__tests__/shared.spec.ts similarity index 90% rename from src/__tests__/shared.spec.js rename to src/__tests__/shared.spec.ts index 1d28900..5f05dee 100644 --- a/src/__tests__/shared.spec.js +++ b/src/__tests__/shared.spec.ts @@ -1,13 +1,12 @@ -const { +import { requestRegex, replacementRegex, dynamicValueRegex, - UpperCaseKeys, removeOptionalKeys, toKebabCase, replaceInObject, expandPath -} = require('../shared') +} from '../shared' describe('Shared Utilities', () => { describe('requestRegex', () => { @@ -47,13 +46,6 @@ describe('Shared Utilities', () => { }) }) - describe('UpperCaseKeys', () => { - it('should uppercase all first-level keys in an object', () => { - let a = { test: 1, Test2: 2 } - expect(UpperCaseKeys(a)).toEqual({ TEST: 1, TEST2: 2 }) - }) - }) - describe('removeOptionalKeys', () => { it('should remove empty objects from an object', () => { let a = { b: {}, c: 2, d: {} } diff --git a/src/plugins.ts b/src/plugins.ts index 6b7690d..d3d3561 100644 --- a/src/plugins.ts +++ b/src/plugins.ts @@ -3,9 +3,22 @@ import requireg = require('requireg') import deepmerge = require('deepmerge') import { toKebabCase, dynamicValueRegex, replaceInObject } from './shared' import { isPlainObject } from 'is-plain-object' -import {UObjectString} from './config' +import { RequestObject, UObjectString } from './config' + +type IPluginRegistry = { + [key in PluginType]: Array<(arg0: any, arg1: any) => any> +} + +type PluginType = + | 'preRequestModifiers' + | 'postRequestModifiers' + | 'dynamicValues' export default class Plugins { + registry: IPluginRegistry + context: vm.Context + autoload: string[] = [] + constructor(plugins: UObjectString[] = [], autoload = ['std']) { this.registry = { preRequestModifiers: [], @@ -14,14 +27,12 @@ export default class Plugins { } this.context = {} - this.autoload = autoload - this.loadPlugins(plugins.concat(this.autoload)) } - normalizePlugins(plugins) { - let results = {} + normalizePlugins(plugins: Array) { + let results: { [key: string]: any } = {} plugins.forEach((plugin) => { let name = plugin @@ -38,14 +49,14 @@ export default class Plugins { settings = plugin[name] } - results[name] = settings + results[name as string] = settings }) return results } - loadPlugins(plugins) { - plugins = this.normalizePlugins(plugins) + loadPlugins(pluginsToLoad: Array) { + const plugins = this.normalizePlugins(pluginsToLoad) Object.keys(plugins).forEach((name) => { const module = `beau-${toKebabCase(name)}` @@ -62,17 +73,15 @@ export default class Plugins { }) } - executeModifier(modifier, obj, orig): typeof obj { - let result = deepmerge({}, obj, { isMergeableObject: isPlainObject }) + executeModifier(modifier: PluginType, obj: T, orig: RequestObject): T { + let result = deepmerge({}, obj, { isMergeableObject: isPlainObject }) - this.registry[modifier].forEach( - (modifier) => (result = modifier(result, orig)) - ) + this.registry[modifier].forEach((mod) => (result = mod(result, orig))) return result } - replaceDynamicValues(obj) { + replaceDynamicValues(obj: { [key: string]: any }) { vm.createContext(this.context) return replaceInObject(obj, (val) => { let valIsEmpty = val.trim().length === 0 @@ -86,15 +95,16 @@ export default class Plugins { val.replace(dynamicValueRegex, '').trim() === '' if (onlyHasDynamic) { - let call - val.replace(dynamicValueRegex, (match, c) => { + let call = '' + val.replace(dynamicValueRegex, (_, c) => { call = c + return '' }) return vm.runInContext(call, this.context) } - return val.replace(dynamicValueRegex, (match, call) => { + return val.replace(dynamicValueRegex, (_, call) => { return vm.runInContext(call, this.context) }) } catch (e) { diff --git a/src/request.ts b/src/request.ts index 10daf91..d0cc7e5 100644 --- a/src/request.ts +++ b/src/request.ts @@ -5,12 +5,25 @@ import Plugins from './plugins' import { requestRegex, replacementRegex, - UpperCaseKeys, removeOptionalKeys, isUrl } from './shared' import { RequestObject, UObjectString } from './config' +export interface IBeauRequestResult { + request: { + headers: { [key: string]: any } + body: { [key: string]: any } | string + endpoint: string + } + response: { + status: number + headers: { [key: string]: any } + body: { [key: string]: any } | string + } + body: { [key: string]: any } | string +} + export default class Request implements RequestObject { originalRequest: RequestObject plugins: Plugins @@ -133,7 +146,7 @@ export default class Request implements RequestObject { const response = await request(settings) - let results = { + let results: IBeauRequestResult = { request: { headers: response.request.headers, body: response.request.body, diff --git a/src/requestCache.ts b/src/requestCache.ts index 0d513ea..ce6aff4 100644 --- a/src/requestCache.ts +++ b/src/requestCache.ts @@ -26,8 +26,8 @@ export default class RequestCache { } parse( - item: { [key: string]: any } | null | undefined - ): string | null | { [key: string]: any } { + item: { [key: string]: any } | null | undefined | string + ): typeof item { if (item === null) { return null } diff --git a/src/shared.ts b/src/shared.ts index cc8d646..fd9b871 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -16,19 +16,13 @@ export const requestRegex = new RegExp(`(${httpVerbs.join('|')})\\s(.*)`, 'i') export const replacementRegex = /(?:\\?)\$([a-zA-Z\.\d\-\_\:]+)/g export const dynamicValueRegex = /\$\[(\w+\((?:.|[\n\r])*?\))\]/g -export const UpperCaseKeys = function (obj: object) { - let result = {} - Object.entries(obj).forEach(([k, v]) => (result[k.toUpperCase()] = v)) - return result -} - export const isEmptyObject = (obj: object) => Object.keys(obj).length === 0 && obj.constructor === Object export const removeOptionalKeys = function ( obj: object, optionalValues: string[] -) { +): typeof obj { let result = {} Object.entries(obj).forEach(([key, value]) => { @@ -49,10 +43,10 @@ export const toKebabCase = function (str: string) { .toLowerCase() } -export const replaceInObject = function ( - obj: object | string | undefined | null, +export const replaceInObject = function ( + obj: T, fn: (arg0: string) => string -) { +): T | null | {} | string { if (obj === null) { return null }