diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..74b5fec --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,2 @@ +# Logs +backend \ No newline at end of file diff --git a/lib/cli/generateFiles.ts b/lib/cli/generateFiles.ts new file mode 100644 index 0000000..343e8f4 --- /dev/null +++ b/lib/cli/generateFiles.ts @@ -0,0 +1,30 @@ +import { readFile } from 'fs/promises'; +import { generateOpenAPI } from "../helpers/generateOpenAPI"; +import { generateClientTemplate } from "../helpers/generateTemplate"; +import { getLogger } from '../logger/getLogger'; + +const main = async function () { + + // Read the Config in. + const config = JSON.parse( + await readFile( + './nopeconfig.json', + { + encoding: 'utf8' + } + ) + ); + + // Define a Logger + const logger = getLogger('info'); + + logger.info('Creating Dispatched API'); + + await generateClientTemplate(Object.assign(config.dispatcher, { logger })); + + logger.info('Creating Open-API'); + + await generateOpenAPI(Object.assign(config.openapi, { logger })) +} + +main().catch(e => console.error(e)); \ No newline at end of file diff --git a/lib/helpers/analyzeTypescriptFiles.ts b/lib/helpers/analyzeTypescriptFiles.ts index 0573a8e..6cd5b70 100644 --- a/lib/helpers/analyzeTypescriptFiles.ts +++ b/lib/helpers/analyzeTypescriptFiles.ts @@ -233,7 +233,10 @@ function _getType(node: Node, inputType: Type, text: string) { }; })); - } else if (Node.isFunctionDeclaration(node) || Node.isFunctionTypeNode(node) || Node.isFunctionLikeDeclaration(node)) { + } + + // The Element could be a Function. + if (Node.isFunctionDeclaration(node) || Node.isFunctionTypeNode(node) || Node.isFunctionLikeDeclaration(node)) { baseType = "function"; // Iterate over the parameter @@ -389,6 +392,11 @@ export function getDescription(declaration: PropertyDeclaration | InterfaceDecla // Extract the Parameters of the Function const params: ParameterInformation[] = declaration.getParameters().map((parameter, index) => { + + // Based on the Fact, whether the Parameter is a Function or not + // The inputs of the the _getType Function has to be adapted. + const isFunc = Node.isMethodDeclaration(parameter) + return Object.assign( { // Name of the parameter @@ -405,7 +413,7 @@ export function getDescription(declaration: PropertyDeclaration | InterfaceDecla _getType( parameter.getTypeNode(), parameter.getType(), - parameter.getText() + isFunc ? parameter.getText() : parameter.getType().getText() ) ) }); diff --git a/lib/helpers/fileHelpers.ts b/lib/helpers/fileHelpers.ts index cb788ec..f100c33 100644 --- a/lib/helpers/fileHelpers.ts +++ b/lib/helpers/fileHelpers.ts @@ -40,49 +40,52 @@ export async function createFile(fileName: string, content: string, options?: (B * @param options The options to write the file. See original docu: https://nodejs.org/dist/latest-v8.x/docs/api/fs.html#fs_fs_writefile_file_data_options_callback */ export async function createPath(path: string) { - // Based on the OS select the Path Element. - const SPLITCHAR = type() === 'Linux' ? '/' : '\\'; - // Adapt the File Pathes - path = type() === 'Linux' ? path.replace(/\\\\/g, '/') : path.replace(/\//g, '\\'); - // Split the Path into different segements. - const pathParts = path.split('/'); + return await mkdir(path, { recursive: true }) - if (pathParts.length > 0) { - /** Check if the given Path Ends with a File Name */ - if (pathParts[pathParts.length - 1].indexOf('.') !== -1) { - pathParts.pop(); - } + // // Based on the OS select the Path Element. + // const SPLITCHAR = type() === 'Linux' ? '/' : '\\'; + // // Adapt the File Pathes + // path = type() === 'Linux' ? path.replace(/\\\\/g, '/') : path.replace(/\//g, '\\'); - // Reassemble the Segments like that: - // - // C:\\Test\\SubFolder\\AnotherFolder - // Split up: - // => fileParts = [C: , Test , SubFolder, AnotherFolder] - // - // Reassemble: - // 1) C: - // 2) C:\\Test - // 3) C:\\Test\\SubFolder - // 4) ... - // - // Everytime after an assembly Check whether the assembled - // path exists, otherwise create that folder and go on. + // // Split the Path into different segements. + // const pathParts = path.split('/'); - for (const [idx, folder] of pathParts.entries()) { - // Assemble the Path. - const currentPath = pathParts.slice(0, idx + 1).join(SPLITCHAR); - // Test and create the Folder - const urlExists = await _exists(currentPath); - // Test if the provided Path exists or not. - if (currentPath && !urlExists) { - await mkdir(currentPath); - } else if (currentPath && urlExists && (await _lstat(currentPath)).isFile()) { + // if (pathParts.length > 0) { + // /** Check if the given Path Ends with a File Name */ + // if (pathParts[pathParts.length - 1].indexOf('.') !== -1) { + // pathParts.pop(); + // } - throw Error('Cant create File at the specified path. The given URL contains a File. See "' + currentPath + '"'); - } - } - } + // // Reassemble the Segments like that: + // // + // // C:\\Test\\SubFolder\\AnotherFolder + // // Split up: + // // => fileParts = [C: , Test , SubFolder, AnotherFolder] + // // + // // Reassemble: + // // 1) C: + // // 2) C:\\Test + // // 3) C:\\Test\\SubFolder + // // 4) ... + // // + // // Everytime after an assembly Check whether the assembled + // // path exists, otherwise create that folder and go on. - return path; + // for (const [idx, folder] of pathParts.entries()) { + // // Assemble the Path. + // const currentPath = pathParts.slice(0, idx + 1).join(SPLITCHAR); + // // Test and create the Folder + // const urlExists = await _exists(currentPath); + // // Test if the provided Path exists or not. + // if (currentPath && !urlExists) { + // await mkdir(currentPath); + // } else if (currentPath && urlExists && (await _lstat(currentPath)).isFile()) { + + // throw Error('Cant create File at the specified path. The given URL contains a File. See "' + currentPath + '"'); + // } + // } + // } + + // return path; } \ No newline at end of file diff --git a/lib/helpers/generateOpenAPI.ts b/lib/helpers/generateOpenAPI.ts index 93dd630..19c7555 100644 --- a/lib/helpers/generateOpenAPI.ts +++ b/lib/helpers/generateOpenAPI.ts @@ -2,11 +2,17 @@ import { copyFile, readFile } from "fs/promises"; import * as handlebars from 'handlebars'; import { join } from 'path'; import { Project } from "ts-morph"; +import { Logger } from 'winston'; +import { IJsonSchema } from "../../types/IJSONSchema"; import { IExportMethodToOpenAPIParameters } from "../openapi/nopeOpenAPIDecorators"; import { DecoratorInformation, MethodInformation } from "./analyzeTypescriptFiles"; -import { createFile } from "./fileHelpers"; +import { createFile, createPath } from "./fileHelpers"; import { generateSchemas } from "./generateSchemas"; +import { schemaGetDefinition } from "./jsonSchemaMethods"; +function generateSchema(methodName: string, schema: IJsonSchema) { + return JSON.stringify(schemaGetDefinition(schema, "#/definitions/" + methodName), undefined, 4); +} /** * Generate the Client Templates. @@ -16,8 +22,10 @@ export async function generateOpenAPI(options: { pathToSchemaTemplate: string, pathToApiTemplate: string, tempDir: string, + outputDir: string, inputDir: string, tsConfigFilePath: string, + logger?: Logger, }) { // Create the Output dir (if it doenst exists) @@ -42,10 +50,12 @@ export async function generateOpenAPI(options: { outputSchema: string })[] = [] + await createPath(join(options.outputDir)); + // Firstly copy the nopeDispatcher await copyFile( join(__dirname, '..', '..', '..', 'lib', 'dispatcher', 'nopeDispatcher.ts'), - join(options.tempDir, 'api', 'nopeDispatcher.ts') + join(options.outputDir, 'nopeDispatcher.ts') ); for (const relevantClass of analysis) { @@ -66,14 +76,15 @@ export async function generateOpenAPI(options: { customParameters: JSON.stringify(method.decoratorSettings.exportMethodToOpenAPI.parameters || [], undefined, 4), useCustomParameters: Array.isArray(method.decoratorSettings.exportMethodToOpenAPI.parameters), useDefaultParameters: method.params.length > 0, - inputSchema: JSON.stringify(schemaMapping[relevantClass.className], undefined, 4), - outputSchema: JSON.stringify(schemaMapping[relevantClass.className], undefined, 4) + inputSchema: generateSchema(method.name + 'Input', schemaMapping[relevantClass.className]), + outputSchema: generateSchema(method.name + 'Output', schemaMapping[relevantClass.className]), } const item = Object.assign( method, { - method: method.params.length > 0 ? 'POST' : 'GET' + method: method.params.length > 0 ? 'POST' : 'GET', + operationId: settings.className + method.name, }, settings, method.decoratorSettings.exportMethodToOpenAPI as IExportMethodToOpenAPIParameters @@ -81,7 +92,7 @@ export async function generateOpenAPI(options: { methods.push(item); - const fileName = join(options.tempDir, 'api', item.baseUri, item.methodUri + '.ts'); + const fileName = join(options.outputDir, item.baseUri, item.methodUri + '.ts'); // Write down the Schema: await createFile( @@ -90,6 +101,10 @@ export async function generateOpenAPI(options: { renderAPI(item) ); + if (options.logger) { + options.logger.info('Generated -> ' + fileName); + } + // Function to Determine new project files. const project = new Project({ tsConfigFilePath: options.tsConfigFilePath, diff --git a/lib/helpers/generateSchemas.ts b/lib/helpers/generateSchemas.ts index b58d5e9..42d5e47 100644 --- a/lib/helpers/generateSchemas.ts +++ b/lib/helpers/generateSchemas.ts @@ -3,9 +3,11 @@ import * as handlebars from 'handlebars'; import { join } from 'path'; import { Project } from "ts-morph"; import * as TJS from "typescript-json-schema"; +import { Logger } from 'winston'; import { IJsonSchema } from "../../types/IJSONSchema"; import { analyzeFiles, defaultClassFilter, defaultPropFilter } from "./analyzeTypescriptFiles"; import { createFile, createPath } from "./fileHelpers"; +import { flattenSchema } from "./jsonSchemaMethods"; /** @@ -17,6 +19,7 @@ export async function generateSchemas(options: { tempDir: string, inputDir: string, tsConfigFilePath: string, + logger?: Logger, }) { // Create the Output dir (if it doenst exists) @@ -75,16 +78,22 @@ export async function generateSchemas(options: { }); for (const file of files) { + + // Generate the Path. + const fileName = join(options.tempDir, 'classes', file.name + '.ts'); await createFile( - // Generate the Path. - join(options.tempDir, 'classes', file.name + '.ts'), + fileName, file.content ); + + if (options.logger) { + options.logger.info('Generated -> ' + fileName); + } } // After all files has been written => Generate the Schemas: const _settings: TJS.PartialArgs = { - required: true + required: true, }; // Options for the TJS.Compiler; @@ -103,15 +112,25 @@ export async function generateSchemas(options: { // We can either get the schema for one file and one type... const _schema = TJS.generateSchema(_program, "*", _settings); + + // Flatten the Schema. + const _flattendSchema = flattenSchema(_schema as any) + // Receive the Element - schemaMapping[file.className] = JSON.parse(JSON.stringify(_schema)) as IJsonSchema; + schemaMapping[file.className] = _flattendSchema; + + // Generate the Path. + const fileName = join(options.tempDir, 'schema', file.name + '.json') // Write down the Schema: await createFile( - // Generate the Path. - join(options.tempDir, 'schema', file.name + '.json'), - JSON.stringify(_schema, undefined, 4) + fileName, + JSON.stringify(_flattendSchema, undefined, 4) ); + + if (options.logger) { + options.logger.info('Generated -> ' + fileName); + } } return { diff --git a/lib/helpers/generateTemplate.ts b/lib/helpers/generateTemplate.ts index 2c4a397..9595381 100644 --- a/lib/helpers/generateTemplate.ts +++ b/lib/helpers/generateTemplate.ts @@ -2,6 +2,7 @@ import { copyFile, readFile } from "fs/promises"; import * as handlebars from 'handlebars'; import { join } from 'path'; import { Project } from "ts-morph"; +import { Logger } from 'winston'; import { analyzeFiles } from "./analyzeTypescriptFiles"; import { createFile, createPath } from "./fileHelpers"; @@ -14,11 +15,17 @@ export async function generateClientTemplate(options: { outputDir: string, inputDir: string, tsConfigFilePath: string, + // A Logger. + logger?: Logger }) { // Create the Output dir (if it doenst exists) await createPath(options.outputDir); + if (options.logger) { + options.logger.info('Templates will be stored in ' + options.outputDir); + } + // Firstly copy the nopeDispatcher await copyFile( join(__dirname, '..', '..', '..', 'lib', 'dispatcher', 'nopeDispatcher.ts'), @@ -62,13 +69,19 @@ export async function generateClientTemplate(options: { }); for (const file of files) { + // Define the File Name: const fileName = join(options.outputDir, 'clients', file.name); + await createFile( // Generate the Path. join(options.outputDir, 'clients', file.name), file.content ); + if (options.logger) { + options.logger.info('Generated -> ' + fileName); + } + // Function to Determine new project files. const project = new Project({ tsConfigFilePath: options.tsConfigFilePath, diff --git a/lib/helpers/jsonMethods.ts b/lib/helpers/jsonMethods.ts new file mode 100644 index 0000000..3273cea --- /dev/null +++ b/lib/helpers/jsonMethods.ts @@ -0,0 +1,76 @@ +/** + * Function to stringify an Object. This Function will stringify Functions as well. + * @param obj The Object. + */ +export function stringifyWithFunctions(obj) { + return JSON.stringify(obj, (key, value) => { + if (typeof value === "function") { + + let str: string = value.toString(); + + // Todo Parse Arrow-Functions Correctly! + // Details here: https://zendev.com/2018/10/01/javascript-arrow-functions-how-why-when.html + // Difference Cases For: + // 1) (a, b) => a + b; + // 2) array => array[0]; + // 3) (a, b) => (a + b); + // 4) (name, description) => ({name: name, description: description}) + // .... + + if (!str.startsWith('function') && !str.startsWith('(')) { + const name = str.slice(0, str.indexOf('=>')); + const func = str.slice(str.indexOf('=>(') + 3, str.length - 2) + const adaptedFunc = 'function(' + name + '){ return ' + func + '; }'; + str = adaptedFunc; + } + + return "/Function(" + str + ")/"; + } + return value; + }); +} + +/** + * Function to parse a JSON String, in which methods should be available. + * @param json A String containing the json Object + */ +export function parseWithFunctions(json: string) { + return JSON.parse(json, (key, value) => { + if (typeof value === "string" && + value.startsWith("/Function(") && + value.endsWith(")/")) { + const _value = value.substring(10, value.length - 2); + try { + return eval("(" + _value + ")"); + } catch (e) { + console.log('FAILED PARSING', value, _value) + } + + } + return value; + }); +} + +/** + * Function to stringify an Object. This Function is able to stringify Functions as well. Use the Flag withFunctions + * @param obj The Object. + * @param withFunctions Flag to Turn on / off the parsing of functions + */ +export function stringify(obj: any, withFunctions = false): string { + if (withFunctions) { + return stringifyWithFunctions(obj); + } + return JSON.stringify(obj); +} + +/** + * Function to parse a JSON String. This Function is able to parse Functions as well. Use the Flag withFunctions + * @param json A String containing the json Object + * @param withFunctions Flag to Turn on / off the parsing of functions + */ +export function parse(json: string, withFunctions = false): any { + if (withFunctions) { + return parseWithFunctions(json); + } + return JSON.parse(json); +} \ No newline at end of file diff --git a/lib/helpers/jsonSchemaMethods.ts b/lib/helpers/jsonSchemaMethods.ts new file mode 100644 index 0000000..eda3abf --- /dev/null +++ b/lib/helpers/jsonSchemaMethods.ts @@ -0,0 +1,55 @@ +import { IJsonSchema } from "../../types/IJSONSchema"; +import { flattenObject, rgetattr, rsetattr, SPLITCHAR } from "./objectMethods"; + +/** + * Function to Flatten a JSON-Schema. + * @param schema + */ +export function flattenSchema(schema: IJsonSchema) { + + let counter = 10000; + let flattenSchema = flattenObject(schema); + + const getRefKeys = (flattenSchema: Map) => { + const relevantKeys: Array<{ schemaPath: string, searchPath: string }> = [] + + for (const [key, value] of flattenSchema) { + if (key.endsWith('$ref')) { + relevantKeys.push({ + schemaPath: key, + searchPath: value.replace('#/', '').replace('/', SPLITCHAR) + }) + } + } + return relevantKeys; + } + + let refs = getRefKeys(flattenSchema); + while (refs.length > 0) { + + counter--; + + if (counter === 0) { + throw Error('Max amount of Recursions performed') + } + + for (const ref of refs) { + const subSchema = rgetattr(schema, ref.searchPath, null, '.'); + rsetattr(schema, ref.schemaPath.replace('.$ref', ''), subSchema) + } + + flattenSchema = flattenObject(schema); + refs = getRefKeys(flattenSchema); + } + + return schema; +} + +/** +* Function to get a Schemas Definition +* @param schema the JSON-Schema +* @param reference the path of the relevant definition. +*/ +export function schemaGetDefinition(schema: IJsonSchema, reference: string) { + return rgetattr(schema, reference.replace('#/', ''), null, '/'); +} \ No newline at end of file diff --git a/lib/helpers/objectMethods.ts b/lib/helpers/objectMethods.ts new file mode 100644 index 0000000..674d2a9 --- /dev/null +++ b/lib/helpers/objectMethods.ts @@ -0,0 +1,366 @@ +export const SPLITCHAR = '.'; + +const _sentinel = new Object(); + +/** + * Function to recurvely get an Attribute of the Object. + * + * @export + * @param {*} _data + * @param {string} _path + * @param {*} [_default=_sentinel] + * @returns {*} + */ +export function rgetattr(_data: any, _path: string, _default: any = _sentinel, _SPLITCHAR: string = SPLITCHAR): any | null { + // Extract the Path + let _obj = _data; + + if (_path.length > 0) { + /** Check if there is a Substring available perform the normal method */ + if (_path.indexOf(_SPLITCHAR) !== -1) { + for (const attr of _path.split(_SPLITCHAR)) { + /** Access a Map */ + if (_obj instanceof Map) { + _obj = _obj.get(attr); + } else { + /** Array or default Object */ + _obj = _obj[attr]; + } + + if ((_obj == null) && (_default === _sentinel)) { + return null; + } else if (_obj == null) { + return _default; + } + } + } else { + /** Otherwise just return the Element */ + return _obj[_path]; + } + } + return _obj; +} + +/** + * Function to Set recursely a Attribute of an Object + * + * @export + * @param {*} _data The Object, where the data should be stored + * @param {string} _path The Path of the Attribute. All are seprated by a '.'! For Instance 'a.b.0.a.c' + * @param {*} _value The Value which should be Stored in the Attribute. + */ +export function rsetattr(_data: any, _path: string, _value: any, _SPLITCHAR: string = SPLITCHAR): void { + let _obj = _data; + + + const _ptrs = _path.split(_SPLITCHAR); + + _ptrs.slice(0, -1).forEach(function (attr: string, idx: number) { + // Adapt the Object by going through a loop + let _sub = _obj[attr]; + + if (_sub === undefined || _sub === null) { + // _obj is an Array and it doesnt contain the index + + // Extract the Next Element: + const _next = _ptrs[idx + 1]; + + const _next_is_int = isInt(_next); + + if (Array.isArray(_obj)) { + if (_next_is_int) { + _obj[attr] = new Array(); + } else { + _obj[attr] = {}; + } + } else { + if (_next_is_int) { + _obj[attr] = []; + } else { + _obj[attr] = {}; + } + } + _sub = _obj[attr]; + + } + + _obj = _sub; + }); + _obj[_ptrs[_ptrs.length - 1]] = _value; +} + +/** + * Checks whether the Value is an Integer + * + * @export + * @param {*} value Value to be checked + * @returns {boolean} Result + */ +export function isInt(value: any): boolean { + return (parseInt(value) === value); +} + +/** + * Checks whether the Value is a Float + * + * @export + * @param {*} value Value to be checked + * @returns {boolean} Result + */ +export function isFloat(value: any): boolean { + return (!isNaN(Number(value))); +} + +/** + * Copys the Object. Creates a Deep-Copy + * of the Function + * + * @export + * @param {*} value The value which should be copied + * @returns {*} A Copy of the Value + */ +export function copy(value: any): any { + // TODO RING + // const _copy = {}; + + // /** Perform a Recursevly Foreach an Set an Attribute. */ + // recursiveForEach(value, '', (path: string, _data: any) => { + // rsetattr(_copy, path, _data); + // }); + + // return _copy; + return JSON.parse(JSON.stringify(value)); +} + +/** + * Function Converts a Object to a Map. + * + * @export + * @param {*} _obj The Object which should be converted. + * @returns {Map} + */ +export function objectToMap(_obj: any): Map { + /** Define the Returntype */ + const _ret = new Map(); + + /** Iterate through all properties of the Object */ + for (const _prop of Object.getOwnPropertyNames(_obj)) { + /** If isnt a function it could be added */ + if (typeof _obj !== 'function') { + _ret.set(_prop, _obj[_prop]); + } + } + + /** Return the Result */ + return _ret; +} + +/** + * Checks whether the Value is an Object + * + * @export + * @param {*} value Data to Test + * @returns {boolean} Flag showing whether the Presented Data is an Object + */ +export function isObject(value: any): boolean { + /** Verify whether the value contains some data. */ + if (value) { + if ((typeof value === 'object') && !Array.isArray(value)) { + return Object.keys(value).length > 0; + } + } + return false; +} + +/** + * Checks whether the Value is an Object + * + * @export + * @param {*} value Data to Test + * @returns {boolean} Flag showing whether the Presented Data is an Object + */ +export function isObjectOrArray(value: any): boolean { + /** Verify whether the value contains some data. */ + return isObject(value) || Array.isArray(value); +} + +/** + * Flattens an Object to a Map. + * + * For Instance: + * + * data = {a : { b : { c : 1, d: "hallo"}}} + * + * // Normal Call + * res = flatteObject(data,'') + * => res = {"a.b.c":1,"a.b.d":"hallo"} + * + * // With a Selected prefix 'additional.name' + * res = flatteObject(data,'additional.name') + * => res = {"additional.name.a.b.c":1,"additional.name.a.b.d":"hallo"} + * + * @export + * @param {*} data The Data that should be converted + * @param {string} [prefix=''] An additional prefix. + * @returns {Map} The flatten Object + */ +export function flattenObject(data: any, prefix: string = '', splitchar: string = SPLITCHAR): Map { + + const _ret = new Map(); + + if (isObject(data) || Array.isArray(data)) { + recursiveForEach(data, prefix, (path, _data) => { + _ret.set(path, _data); + }, splitchar, true); + } + return _ret; +} + + +/** + * Function which is executed on each + * + * @export + * @param {*} obj + * @param {string} [prefix=''] + * @param {(path: string, data: any) => void} dataCallback + * @returns {*} + */ +export function recursiveForEach(obj: any, prefix: string = '', dataCallback: (path: string, data: any, parent?: string, level?: number) => void, _SPLITCHAR: string = SPLITCHAR, _callOnlyOnValues = true, _parent: string = '', _level = 0): any { + /** Create an Array containing all Keys. */ + let keys = Array(); + + /** Extract Keys of the Object, only if it isnt a string */ + if (typeof obj !== 'string' && typeof obj !== 'function') { + keys = Object.getOwnPropertyNames(obj); + if (Array.isArray(obj)) { + keys.splice(keys.indexOf('length'), 1); + } + } + + let called = false; + + if (!_callOnlyOnValues) { + // Store the Element ! + dataCallback(prefix, obj, _parent, _level); + called = true; + } + + // If there are Keys => It is a List or a Default Object + if (keys.length > 0) { + for (const _key of keys) { + /** Var containing the Name */ + const _str = (prefix === '') ? _key : prefix + _SPLITCHAR + _key; + + if (obj[_key] != null) { + if (typeof obj[_key].toJSON === 'function') { + const data = obj[_key].toJSON(); + /** Recursive call the Function */ + recursiveForEach(data, _str, dataCallback, _SPLITCHAR, _callOnlyOnValues, prefix, _level + 1); + } else { + /** Recursive call the Function */ + recursiveForEach(obj[_key], _str, dataCallback, _SPLITCHAR, _callOnlyOnValues, prefix, _level + 1); + } + } + + } + } else if (!called) { + // Store the Element ! + dataCallback(prefix, obj, prefix, _level); + } +} + +/** + * Exports the used Types of an Object + * + * @export + * @param {*} data The Data considered + * @param {string} [prefix=''] + * @returns {Map} + */ +export function flattenObjectType(data: any, prefix: string = ''): Map { + const _ret = new Map(); + + if (isObject(data)) { + recursiveForEach(data, prefix, (path, _data) => { + _ret.set(path, typeof _data); + }); + } + return _ret; +} + +/** + * Deflattens an Dict Based Object. + * + * @export + * @param {Map} _flattenObject + * @returns {*} + */ +export function deflattenObject(_flattenObject: Map): any { + const _ret = {}; + + _flattenObject.forEach((_val: any, _key: string) => { + rsetattr(_ret, _key, _val); + }); + + return _ret; +} + + +/** + * Function for deeply assigning + * + * @export + * @param {*} target + * @param {*} source + * @returns + */ +export function deepAssign(target: any, source: any) { + const flattend = flattenObject(source); + + for (const [path, value] of flattend.entries()) { + rsetattr(target, path, value); + } + + return target; +} + +export function deepClone(obj: T) { + let clone: any = Object.assign({}, obj); + Object.keys(clone).forEach( + key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) + ); + return (Array.isArray(obj) && obj.length + ? (clone.length = obj.length) && Array.from(clone) + : Array.isArray(obj) + ? Array.from(obj) + : clone) as T; +} + +// export const deepEqual: (a: any, b: any) => boolean = require('deep-equal'); + +/** + * Function to adapt the Object and only return a specific amount of elements. + * @param obj The Object itself + * @param properties a list of properties/pathes to keep + */ +export function keepPropertiesOfObject(obj: any, properties: { [index: string]: () => any }) { + if (isObject(obj)) { + const ret: any = {}; + + const defaultObj = { error: true }; + + // Iterate over the Properties, get the content of the path, clone it an put it to the + // provided path + Object.getOwnPropertyNames(properties).map(path => { + const value = rgetattr(obj, path, defaultObj); + rsetattr(ret, path, value !== defaultObj ? (typeof value === 'object' ? deepClone(value) : value) : properties[path]()); + }); + + // Return the Object + return ret; + } + + // Wrong Datatype provided. + throw TypeError('Function can only create Objects'); +} \ No newline at end of file diff --git a/lib/helpers/stringMethods.ts b/lib/helpers/stringMethods.ts new file mode 100644 index 0000000..3f0ed43 --- /dev/null +++ b/lib/helpers/stringMethods.ts @@ -0,0 +1,52 @@ +/** + * Replaces all Chars in a String + * @param str base string + * @param value the value which should be replaced + * @param replacement the value which is used as replacement + */ +export function replaceAll(str: string, value: string, replacement: string): string { + return str.split(value).join(replacement); +} + +/** +* Function to Pad a String. +* @param num +* @param size +* @param maxLength +*/ +export function padString(num: number, size: number, maxLength = false) { + + let _size = size; + if (typeof maxLength === 'boolean' && maxLength) { + _size = Math.ceil(Math.log10(size)); + } + + let s = num + ""; + while (s.length < _size) s = "0" + s; + return s; +} + +/** +* Inserts a String in the String +* @param str base string +* @param index index where the content should be inserted +* @param content the content to insert +*/ +export function insert(str: string, index: number, content: string): string { + if (index > 0) { + return str.substring(0, index) + content + str.substring(index, str.length); + } else { + return content + str; + } +} + +/** + * Function to Camelize a String + * @param str The String, + * @param char A, used to determine "new words" + */ +export function camelize(str: string, char = '_') { + return replaceAll(str, char, ' ').replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) { + return index == 0 ? word.toLowerCase() : word.toUpperCase(); + }).replace(/\s+/g, ''); +} \ No newline at end of file diff --git a/lib/logger/getLogger.ts b/lib/logger/getLogger.ts new file mode 100644 index 0000000..80e73c7 --- /dev/null +++ b/lib/logger/getLogger.ts @@ -0,0 +1,32 @@ +import { createLogger, format, transports } from 'winston'; + +export type LoggerLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly' + +export function getLogger(level: LoggerLevel) { + const readableFormat = format.printf(({ level, message, timestamp }) => { + return `[${timestamp} ${level}]: ${message}`; + }); + + // Define a Logger + const logger = createLogger({ + level, + format: format.combine( + format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss-ms' + }), + format.errors({ stack: true }), + readableFormat + ), + exitOnError: false, + transports: [ + new (transports.Console)({ + format: format.combine( + format.colorize(), + readableFormat + ) + }), + ] + }); + + return logger; +} \ No newline at end of file diff --git a/lib/templates/openApiSchema.handlebars b/lib/templates/openApiSchema.handlebars index e98e81d..7614e31 100644 --- a/lib/templates/openApiSchema.handlebars +++ b/lib/templates/openApiSchema.handlebars @@ -26,8 +26,7 @@ export default function (_dispatcher: nopeDispatcher) { // Define the apiDoc for this specific Funtion POST.apiDoc = { {{#if methodDescription}}summary: '{{methodDescription}}',{{/if}} - {{#if operationId}}operationId: '{{operationId}}',{{/if}}{{#if operationId}}operationId: '{{operationId}}',{{/if}} - operationId: '{{operationId}}', + {{#if operationId}}operationId: '{{operationId}}'{{/if}}, parameters: [ {{#if useDefaultParameters}} { @@ -46,12 +45,14 @@ export default function (_dispatcher: nopeDispatcher) { {{#if hasReturnType}} 200: { {{#if resultDescription}}description: '{{resultDescription}}',{{/if}} + {{#unless resultDescription}}description: 'Not Provided', {{/unless}} schema: {{{outputSchema}}} }, {{/if}} {{#unless hasReturnType}} 200: { {{#if resultDescription}}description: '{{resultDescription}}',{{/if}} + {{#unless resultDescription}}description: 'Not Provided', {{/unless}} }, {{/unless}} default: { diff --git a/lib/templates/schema.handlebars b/lib/templates/schema.handlebars index 8456c9a..300eb86 100644 --- a/lib/templates/schema.handlebars +++ b/lib/templates/schema.handlebars @@ -16,7 +16,7 @@ export interface {{name}}Input { {{name}}{{#if isOptional}}?{{/if}}: {{{originalCode}}} {{/if}} {{#unless isBaseType}} - {{{simplifiedType}}} + {{name}}{{#if isOptional}}?{{/if}}: {{{simplifiedType}}} {{/unless}} {{/each}} } diff --git a/nopeconfig.json b/nopeconfig.json new file mode 100644 index 0000000..adcb5db --- /dev/null +++ b/nopeconfig.json @@ -0,0 +1,16 @@ +{ + "dispatcher": { + "inputDir": "./test/*.ts", + "outputDir": "./pages/backend", + "pathToTemplate": "./lib/templates/clientInterface.handlebars", + "tsConfigFilePath": "./tsconfigBackend.json" + }, + "openapi": { + "inputDir": "./test/*.ts", + "outputDir": "./api/backend", + "tempDir": "./temp/", + "pathToSchemaTemplate": "./lib/templates/schema.handlebars", + "pathToApiTemplate": "./lib/templates/openApiSchema.handlebars", + "tsConfigFilePath": "./tsconfigBackend.json" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 39f5ce9..2135dbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1296,6 +1296,15 @@ "regenerator-runtime": "^0.13.4" } }, + "@babel/runtime-corejs2": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.11.2.tgz", + "integrity": "sha512-AC/ciV28adSSpEkBglONBWq4/Lvm6GAZuxIoyVtsnUpZMl0bxLtoChEnYAkP+47KyOCayZanojtflUEUJtR/6Q==", + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", @@ -1372,6 +1381,21 @@ "to-fast-properties": "^2.0.0" } }, + "@braintree/sanitize-url": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-4.1.1.tgz", + "integrity": "sha512-epVksusKVEpwBs2vRg3SWssxn9KXs9CxEYNOcgeSRLRjq070ABj5bLPxkmtQpVeSPCHj8kfAE9J6z2WsLr4wZg==" + }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "@dsherret/to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@dsherret/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -1381,6 +1405,19 @@ "is-negated-glob": "^1.0.0" } }, + "@kyleshockey/object-assign-deep": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@kyleshockey/object-assign-deep/-/object-assign-deep-0.4.2.tgz", + "integrity": "sha1-hJAPDu/DcnmPR1G1JigwuCCJIuw=" + }, + "@kyleshockey/xml": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@kyleshockey/xml/-/xml-1.0.2.tgz", + "integrity": "sha512-iMo32MPLcI9cPxs3YL5kmKxKgDmkSZDCFEqIT5eRk7d/Ll8r4X3SwGYSigzALd6+RHWlFEmjL1QyaQ15xDZFlw==", + "requires": { + "stream": "^0.0.2" + } + }, "@next/react-dev-overlay": { "version": "9.5.2", "resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-9.5.2.tgz", @@ -2060,6 +2097,11 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -2095,6 +2137,11 @@ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz", "integrity": "sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==" }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -2105,6 +2152,11 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -2115,6 +2167,14 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "autolinker": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.14.1.tgz", + "integrity": "sha512-yvsRHIaY51EYDml6MGlbqyJGfl4n7zezGYf+R7gvM8c5LNpRGc4SISkvgAswSS8SWxk/OrGCylKV9mJyVstz7w==", + "requires": { + "tslib": "^1.9.3" + } + }, "babel-plugin-dynamic-import-node": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", @@ -2142,6 +2202,22 @@ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -2439,6 +2515,11 @@ "node-releases": "^1.1.58" } }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, "buffer": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", @@ -2559,6 +2640,21 @@ } } }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==" + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==" + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" + }, "chokidar": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", @@ -2631,6 +2727,17 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, + "clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", + "optional": true, + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -2665,6 +2772,15 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2678,6 +2794,42 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==" + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2786,6 +2938,19 @@ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, + "copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, "core-js-compat": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", @@ -2857,6 +3022,16 @@ "sha.js": "^2.4.8" } }, + "create-react-class": { + "version": "15.6.3", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", + "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", + "requires": { + "fbjs": "^0.8.9", + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, "cross-fetch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.5.tgz", @@ -3022,6 +3197,11 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -3067,6 +3247,17 @@ } } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -3148,6 +3339,11 @@ "domelementtype": "^2.0.1" } }, + "dompurify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.12.tgz", + "integrity": "sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg==" + }, "domutils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", @@ -3211,6 +3407,11 @@ } } }, + "emitter-component": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", + "integrity": "sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY=" + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3221,11 +3422,34 @@ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3357,6 +3581,17 @@ "ext": "^1.1.2" } }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escalade": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", @@ -3409,6 +3644,15 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -3699,11 +3943,31 @@ } } }, + "fast-json-patch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", + "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", + "requires": { + "fast-deep-equal": "^2.0.1" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, "fastq": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", @@ -3712,6 +3976,40 @@ "reusify": "^1.0.4" } }, + "fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "requires": { + "format": "^0.2.0" + } + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + } + } + }, + "fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + }, "figgy-pudding": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", @@ -3801,11 +4099,31 @@ "readable-stream": "^2.3.6" } }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=" + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -3940,6 +4258,15 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "optional": true, + "requires": { + "delegate": "^3.1.2" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -4060,11 +4387,32 @@ "minimalistic-assert": "^1.0.1" } }, + "hast-util-parse-selector": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.4.tgz", + "integrity": "sha512-gW3sxfynIvZApL4L07wryYF4+C9VvH3AUi7LAnVXV4MneGEgwOByXvFo18BgmTWnm7oHAe874jKbIB1YhHSIzA==" + }, + "hastscript": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.1.2.tgz", + "integrity": "sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ==", + "requires": { + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, + "highlight.js": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.1.2.tgz", + "integrity": "sha512-Q39v/Mn5mfBlMff9r+zzA+gWxRsCRKwEMvYTiisLr/XUiFI/4puWt0Ojdko3R3JCNWGdOWaA5g/Yxqa23kC5AA==" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -4075,6 +4423,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "htmlparser2": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", @@ -4145,6 +4501,11 @@ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=" + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4229,6 +4590,25 @@ } } }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==" + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -4260,6 +4640,11 @@ } } }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==" + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -4282,6 +4667,15 @@ "resolved": "https://registry.npmjs.org/is-dir/-/is-dir-1.0.0.tgz", "integrity": "sha1-QdN/SV/MrMBaR3jWboMCTCkro/8=" }, + "is-dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", + "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==", + "requires": { + "is-object": "^1.0.1", + "is-window": "^1.0.2" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -4305,6 +4699,11 @@ "is-extglob": "^2.1.1" } }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==" + }, "is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", @@ -4328,6 +4727,11 @@ } } }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -4341,6 +4745,11 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -4349,6 +4758,11 @@ "is-unc-path": "^1.0.0" } }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -4357,6 +4771,11 @@ "unc-path-regex": "^0.1.2" } }, + "is-window": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", + "integrity": "sha1-LIlspT25feRdPDMTOmXYyfVjSA0=" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -4377,6 +4796,39 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + } + } + }, + "isomorphic-form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz", + "integrity": "sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==", + "requires": { + "form-data": "^2.3.2" + } + }, "jest-worker": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", @@ -4386,6 +4838,11 @@ "supports-color": "^6.1.0" } }, + "js-file-download": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz", + "integrity": "sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4450,6 +4907,11 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -4496,6 +4958,11 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz", "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==" }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4506,6 +4973,18 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4514,6 +4993,15 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lowlight": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.14.0.tgz", + "integrity": "sha512-N2E7zTM7r1CwbzwspPxJvmjAbxljCPThTFawEX2Z7+P3NGrrvY54u8kyU16IY4qWfoVIxY8SYCS8jTkuG7TqYA==", + "requires": { + "fault": "^1.0.0", + "highlight.js": "~10.1.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4522,6 +5010,14 @@ "yallist": "^4.0.0" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -4565,6 +5061,21 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -5138,6 +5649,14 @@ "wrappy": "1" } }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, "openapi-default-setter": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/openapi-default-setter/-/openapi-default-setter-7.0.0.tgz", @@ -5328,6 +5847,19 @@ "safe-buffer": "^5.1.1" } }, + "parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -5406,6 +5938,11 @@ "sha.js": "^2.4.8" } }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -5517,6 +6054,14 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "prismjs": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.21.0.tgz", + "integrity": "sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw==", + "requires": { + "clipboard": "^2.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5527,6 +6072,14 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", @@ -5561,6 +6114,14 @@ "warning": "^4.0.0" } }, + "property-information": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.5.0.tgz", + "integrity": "sha512-RgEbCx2HLa1chNgvChcx+rrCWD0ctBmGSE0M7lVm1yyv4UbvbrWoXp/BkVLZefzjrRBGW8/Js6uh/BnlHXFyjA==", + "requires": { + "xtend": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -5649,11 +6210,36 @@ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, + "querystring-browser": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/querystring-browser/-/querystring-browser-1.0.4.tgz", + "integrity": "sha1-8uNYgYQKgZvHsb9Zf68JeeZiLcY=" + }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + }, + "dependencies": { + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + } + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5722,6 +6308,24 @@ "warning": "^4.0.3" } }, + "react-copy-to-clipboard": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz", + "integrity": "sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA==", + "requires": { + "copy-to-clipboard": "^3", + "prop-types": "^15.5.8" + } + }, + "react-debounce-input": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.2.2.tgz", + "integrity": "sha512-RIBu68Cq/gImKz/2h1cE042REDqyqj3D+7SJ3lnnIpJX0ht9D9PfH7KAnL+SgDz6hvKa9pZS2CnAxlkrLmnQlg==", + "requires": { + "lodash.debounce": "^4", + "prop-types": "^15.7.2" + } + }, "react-dom": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", @@ -5733,6 +6337,46 @@ "scheduler": "^0.19.1" } }, + "react-immutable-proptypes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz", + "integrity": "sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ=" + }, + "react-immutable-pure-component": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-1.2.3.tgz", + "integrity": "sha512-kNy2A/fDrSuR8TKwB+4ynmItmp1vgF87tWxxfmadwDYo2J3ANipHqTjDIBvJvJ7libvuh76jIbvmK0krjtKH1g==", + "requires": { + "@types/react": "16.4.6" + }, + "dependencies": { + "@types/react": { + "version": "16.4.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz", + "integrity": "sha512-9LDZdhsuKSc+DjY65SjBkA958oBWcTWSVWAd2cD9XqKBjhGw1KzAkRhWRw2eIsXvaIE/TOTjjKMFVC+JA1iU4g==", + "optional": true, + "requires": { + "csstype": "^2.2.0" + } + }, + "csstype": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.13.tgz", + "integrity": "sha512-ul26pfSQTZW8dcOnD2iiJssfXw0gdNVX9IJDH/X3K5DGPfj+fUYe3kB+swUY6BF3oZDxaID3AJt+9/ojSAE05A==", + "optional": true + } + } + }, + "react-inspector": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-2.3.1.tgz", + "integrity": "sha512-tUUK7t3KWgZEIUktOYko5Ic/oYwvjEvQUFAGC1UeMeDaQ5za2yZFtItJa2RTwBJB//NxPr000WQK6sEbqC6y0Q==", + "requires": { + "babel-runtime": "^6.26.0", + "is-dom": "^1.0.9", + "prop-types": "^15.6.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -5743,6 +6387,16 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-motion": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/react-motion/-/react-motion-0.5.2.tgz", + "integrity": "sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==", + "requires": { + "performance-now": "^0.2.0", + "prop-types": "^15.5.8", + "raf": "^3.1.0" + } + }, "react-overlays": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.0.tgz", @@ -5758,11 +6412,36 @@ "warning": "^4.0.3" } }, + "react-redux": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-4.4.10.tgz", + "integrity": "sha512-tjL0Bmpkj75Td0k+lXlF8Fc8a9GuXFv/3ahUOCXExWs/jhsKiQeTffdH0j5byejCGCRL4tvGFYlrwBF1X/Aujg==", + "requires": { + "create-react-class": "^15.5.1", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.0.0", + "lodash": "^4.17.11", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2" + } + }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" }, + "react-syntax-highlighter": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.0.tgz", + "integrity": "sha512-2nKo8spFxe9shcjbdUiqxkrf/IMDqKUZLx7JVIxEJ17P+fYFGL4CRsZZC66UPeQ2o/f29eKu31CrkKGCK1RHuA==", + "requires": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.1.1", + "lowlight": "^1.14.0", + "prismjs": "^1.21.0", + "refractor": "^3.1.0" + } + }, "react-transition-group": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", @@ -5798,11 +6477,40 @@ "readable-stream": "^2.0.2" } }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "^4.2.1", + "lodash-es": "^4.2.1", + "loose-envify": "^1.1.0", + "symbol-observable": "^1.0.3" + } + }, + "redux-immutable": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-immutable/-/redux-immutable-3.1.0.tgz", + "integrity": "sha1-yvvWhuBxEmERm5wolgk13EeknQo=", + "requires": { + "immutable": "^3.8.1" + } + }, "reflect.ownkeys": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=" }, + "refractor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.1.0.tgz", + "integrity": "sha512-bN8GvY6hpeXfC4SzWmYNQGLLF2ZakRDNBkgCL0vvl5hnpMrnyURk8Mv61v6pzn4/RBHzSWLp44SzMmVHqMGNww==", + "requires": { + "hastscript": "^5.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.21.0" + } + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -5876,6 +6584,15 @@ } } }, + "remarkable": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-2.0.1.tgz", + "integrity": "sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==", + "requires": { + "argparse": "^1.0.10", + "autolinker": "^3.11.0" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5901,6 +6618,16 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -6108,6 +6835,12 @@ "ajv-keywords": "^3.4.1" } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "optional": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -6155,6 +6888,11 @@ } } }, + "serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=" + }, "serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", @@ -6232,6 +6970,14 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -6489,6 +7235,11 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6511,6 +7262,11 @@ "minipass": "^3.1.1" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stacktrace-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", @@ -6543,6 +7299,14 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", + "integrity": "sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8=", + "requires": { + "emitter-component": "^1.1.1" + } + }, "stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -6708,11 +7472,92 @@ "has-flag": "^3.0.0" } }, + "swagger-client": { + "version": "3.10.12", + "resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.10.12.tgz", + "integrity": "sha512-h2o7axvFViMc5sxwTjjza84Rhfz+C52wgMKPOT0P05jODjZhldBK7y9EvGt4zvqgzBJHS+FDQBmOT/dGf9SWdw==", + "requires": { + "@babel/runtime-corejs2": "^7.10.4", + "btoa": "^1.2.1", + "buffer": "^5.6.0", + "cookie": "~0.4.1", + "cross-fetch": "^3.0.5", + "deep-extend": "~0.6.0", + "fast-json-patch": "^2.2.1", + "isomorphic-form-data": "~2.0.0", + "js-yaml": "^3.14.0", + "lodash": "^4.17.19", + "qs": "^6.9.4", + "querystring-browser": "^1.0.4", + "traverse": "~0.6.6", + "url": "~0.11.0" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + } + } + }, "swagger-schema-official": { "version": "2.0.0-bab6bed", "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" }, + "swagger-ui-react": { + "version": "3.32.4", + "resolved": "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-3.32.4.tgz", + "integrity": "sha512-AbdeBVIV6oM4pXKEsGY2Ijs1ySmdVYP4cHdZYu0kWghxKVqskocsfB+SsvRTh6mOxdZ2YNAEhc7RMdSqaWnGgw==", + "requires": { + "@babel/runtime-corejs2": "^7.10.4", + "@braintree/sanitize-url": "^4.0.0", + "@kyleshockey/object-assign-deep": "^0.4.2", + "@kyleshockey/xml": "^1.0.2", + "base64-js": "^1.2.0", + "classnames": "^2.2.6", + "core-js": "^2.6.11", + "css.escape": "1.5.1", + "deep-extend": "0.6.0", + "dompurify": "^2.0.7", + "ieee754": "^1.1.13", + "immutable": "^3.x.x", + "js-file-download": "^0.4.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "memoizee": "^0.4.12", + "prop-types": "^15.7.2", + "randombytes": "^2.1.0", + "react-copy-to-clipboard": "5.0.1", + "react-debounce-input": "^3.2.0", + "react-immutable-proptypes": "2.1.0", + "react-immutable-pure-component": "^1.1.1", + "react-inspector": "^2.3.0", + "react-motion": "^0.5.2", + "react-redux": "=4.4.10", + "react-syntax-highlighter": "=13.5.0", + "redux": "=3.7.2", + "redux-immutable": "3.1.0", + "remarkable": "^2.0.1", + "reselect": "^4.0.0", + "serialize-error": "^2.1.0", + "sha.js": "^2.4.11", + "swagger-client": "=3.10.12", + "url-parse": "^1.4.7", + "xml-but-prettier": "^1.0.1", + "zenscroll": "^4.0.2" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", @@ -6856,6 +7701,11 @@ } } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -6873,6 +7723,21 @@ "setimmediate": "^1.0.4" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, "to-array": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", @@ -6926,6 +7791,11 @@ "repeat-string": "^1.6.1" } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -6944,6 +7814,11 @@ "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "ts-log": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.1.4.tgz", @@ -7022,6 +7897,11 @@ } } }, + "ua-parser-js": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", + "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==" + }, "uglify-js": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.1.tgz", @@ -7180,6 +8060,15 @@ } } }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -7442,6 +8331,11 @@ "source-map": "~0.6.1" } }, + "whatwg-fetch": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz", + "integrity": "sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ==" + }, "whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", @@ -7457,6 +8351,43 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -7514,6 +8445,14 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==" }, + "xml-but-prettier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-but-prettier/-/xml-but-prettier-1.0.1.tgz", + "integrity": "sha1-9aMyZ+1CzNTjVcYlV6XjmwH7QPM=", + "requires": { + "repeat-string": "^1.5.2" + } + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -7565,6 +8504,11 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, + "zenscroll": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zenscroll/-/zenscroll-4.0.2.tgz", + "integrity": "sha1-6NV3TRwHOKR7z6hynzcS4t7d6yU=" } } } diff --git a/package.json b/package.json index 9f4422d..f566db2 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,10 @@ "rxjs": "^6.6.2", "socket.io": "^2.3.0", "socket.io-client": "^2.3.0", + "swagger-ui-react": "^3.32.4", "ts-morph": "^7.3.0", - "typescript-json-schema": "^0.43.0" + "typescript-json-schema": "^0.43.0", + "winston": "^3.3.3" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^1.0.15-4.3.1", diff --git a/pages/.gitignore b/pages/.gitignore new file mode 100644 index 0000000..74b5fec --- /dev/null +++ b/pages/.gitignore @@ -0,0 +1,2 @@ +# Logs +backend \ No newline at end of file diff --git a/pages/_app.tsx b/pages/_app.tsx index d31ff7f..462573c 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,4 +1,5 @@ import 'bootstrap/dist/css/bootstrap.min.css'; +import "swagger-ui-react/swagger-ui.css"; export default function App({ Component, pageProps }) { return diff --git a/pages/docs.tsx b/pages/docs.tsx new file mode 100644 index 0000000..3c100e3 --- /dev/null +++ b/pages/docs.tsx @@ -0,0 +1,14 @@ +import SwaggerUI from "swagger-ui-react"; +import { LocalNavbar } from './ui/navbar'; + +/** + * Default Docs. + */ +export default function Docs() { + return ( + <> + + + + ); +} \ No newline at end of file diff --git a/pages/index.tsx b/pages/index.tsx index f93e7ca..77825aa 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,6 +1,15 @@ -export default function Home(){ +import Head from 'next/head'; +import { LocalNavbar } from './ui/navbar'; + +export default function Home() { return ( -

Welcome

+ <> + + Create Next App + + + + ) } \ No newline at end of file diff --git a/pages/ui/navbar.tsx b/pages/ui/navbar.tsx new file mode 100644 index 0000000..a482fe6 --- /dev/null +++ b/pages/ui/navbar.tsx @@ -0,0 +1,24 @@ +import { Nav, Navbar, NavDropdown } from "react-bootstrap"; + +export function LocalNavbar() { + return ( + + nopeBackend + + + + {/* Navigation on the right side */} + {/* */} + + + ) +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 5c56cc3..9a26039 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +import { getLogger } from "../lib/logger/getLogger"; import { startBackend } from "./startBackend"; -startBackend({port: 3001}); \ No newline at end of file +startBackend({ port: 3001, logger: getLogger('debug') }); \ No newline at end of file diff --git a/src/startBackend.ts b/src/startBackend.ts index 0dabc64..ec985ba 100644 --- a/src/startBackend.ts +++ b/src/startBackend.ts @@ -1,14 +1,19 @@ -import { apiDoc } from '../specs/apiDoc'; -import * as express from "express"; import * as bodyParser from "body-parser"; +import * as cors from 'cors'; +import * as express from "express"; import { initialize } from "express-openapi"; -import { getBackendAccesors } from './getBackendAccessors'; import { assignIn } from 'lodash'; +import { Logger } from 'winston'; +import { EventLayer } from "../lib/communication/eventLayer"; +import { getDispatcher } from "../lib/dispatcher/nopeDispatcher"; +import { apiDoc } from '../specs/apiDoc'; +import { getBackendAccesors } from './getBackendAccessors'; export function startBackend(options: { port?: number, basePath?: string, -}= {}) { + logger?: Logger, +} = {}) { const app: express.Application = (express as any)(); // Define the Default Options @@ -20,24 +25,34 @@ export function startBackend(options: { const opts = assignIn(defaults, options); app.use(bodyParser.json()); - + app.use(cors()); + initialize({ - apiDoc: apiDoc('Test API', '0.0.1', opts.basePath), + apiDoc: apiDoc('Backend API', '1.0.0', opts.basePath), app, paths: './dist/api', routesGlob: '**/*.{ts,js}', - routesIndexFileRegExp: /(?:index)?\.[tj]s$/ + routesIndexFileRegExp: /(?:index)?\.[tj]s$/, + dependencies: { + _dispatcher: getDispatcher('backend', new EventLayer()) + }, }); - + app.use(((err, req, res, next) => { res.status(err.status).json(err); }) as express.ErrorRequestHandler); - + const server = app.listen(opts.port); const accessor = getBackendAccesors(app); - return { + if (options.logger) { + options.logger.info('Server Running on http://localhost:' + opts.port.toString() + opts.basePath); + options.logger.info('API Documentation available on http://localhost:' + opts.port.toString() + opts.basePath + '/api-docs'); + options.logger.debug('Checkout http://localhost:3000/docs') + } + + return { app, // Accessor for the Server accessor, diff --git a/test/testAnalyzer.ts b/test/testAnalyzer.ts index 23391a3..2dedd32 100644 --- a/test/testAnalyzer.ts +++ b/test/testAnalyzer.ts @@ -1,22 +1,52 @@ +import { createLogger, format, transports } from 'winston'; import { generateOpenAPI } from "../lib/helpers/generateOpenAPI"; import { generateClientTemplate } from "../lib/helpers/generateTemplate"; const main = async function () { + + const readableFormat = format.printf(({ level, message, label, timestamp }) => { + return `${timestamp} ${level}: ${message}`; + }); + + let logger = createLogger({ + level: 'info', + format: format.combine( + format.timestamp({ + format: 'YYYY-MM-DD HH:mm:ss' + }), + format.errors({ stack: true }), + readableFormat + ), + exitOnError: false, + transports: [ + new (transports.Console)({ + format: format.combine( + format.colorize(), + readableFormat + ) + }), + ] + }); + + logger.info('Creating Dispatched API'); + await generateClientTemplate({ inputDir: './test/*.ts', outputDir: './dist/generated', pathToTemplate: './lib/templates/clientInterface.handlebars', - tsConfigFilePath: './tsconfigBackend.json' + tsConfigFilePath: './tsconfigBackend.json', + logger }); - console.log('Created Files.'); + logger.info('Creating Open-API'); await generateOpenAPI({ inputDir: './test/*.ts', tempDir: './temp', pathToSchemaTemplate: './lib/templates/schema.handlebars', pathToApiTemplate: './lib/templates/openApiSchema.handlebars', - tsConfigFilePath: './tsconfigBackend.json' + tsConfigFilePath: './tsconfigBackend.json', + logger }) } diff --git a/test/testFile.ts b/test/testFile.ts index 7d0f252..e3b01f2 100644 --- a/test/testFile.ts +++ b/test/testFile.ts @@ -30,6 +30,13 @@ export class CLWithInterface { num: 0 }); + @exportMethodToOpenAPI({}) + @exportMethodToDispatcher({ + url: 'exportedFunction' + }) + async exportedFunctionShouldBeHosted(/* COMMENT */ a: IF00, b?: IF01) { + return a + b + } /** * @@ -49,12 +56,7 @@ export class CLWithInterface { return await operator(a, b); } - @exportMethodToOpenAPI({}) - @exportMethodToDispatcher({ - url: 'exportedFunction' - }) - async exportedFunctionShouldBeHosted(/* COMMENT */ a: number, b?: number) { - } + /** diff --git a/types/IJSONSchema.ts b/types/IJSONSchema.ts index b95f581..dd49fb5 100644 --- a/types/IJSONSchema.ts +++ b/types/IJSONSchema.ts @@ -1,5 +1,5 @@ export type IJsonSchemaBaseTypes = 'string' | 'number' | 'integer' | 'object' | 'array' | 'boolean' | 'null'; -export type IJsonSchemaTypes = IJsonSchemaBaseTypes | Array +export type IJsonSchemaTypes = IJsonSchemaBaseTypes | Array | { $ref: string } /**