{
+ operation: OperationModel;
+ additionalHeaders: object;
+ visited = new Set();
+ private consoleEditor: ConsoleEditor;
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ result: null,
+ };
+ }
+ onClickSend = async () => {
+ const ace = this.consoleEditor && this.consoleEditor.editor;
+ const { operation, additionalHeaders = {} } = this.props;
+ let value = ace && ace.editor.getValue();
+
+ const content = operation.requestBody && operation.requestBody.content;
+ const mediaType = content && content.mediaTypes[content.activeMimeIdx];
+ const endpoint = {
+ method: operation.httpVerb,
+ path: operation.servers[0].url + operation.path,
+ };
+ if (value) {
+ value = JSON.parse(value);
+ }
+ const contentType = mediaType && mediaType.name || 'application/json';
+ const contentTypeHeader = { 'Content-Type': contentType };
+ const headers = { ...additionalHeaders, ...contentTypeHeader };
+ let result;
+ try {
+ result = await this.invoke(endpoint, value, headers);
+ this.setState({
+ result,
+ });
+ } catch (error) {
+ this.setState({
+ result: error,
+ });
+ }
+ };
+
+ /*
+ * If we have a url like foo/bar/{uuid} uuid will be replaced with what user has typed in.
+ */
+ addParamsToUrl(url: string, params: FieldModel[]) {
+ const queryParamPrefix = '{';
+ const queryParamSuffix = '}';
+
+ for (const fieldModel of params) {
+ console.log(fieldModel.name + ' ' + url);
+ console.log(fieldModel.$value);
+ if (url.indexOf(`${queryParamPrefix}${fieldModel.name}${queryParamSuffix}`) > -1 && fieldModel.$value.length > 0) {
+ url = url.replace(`${queryParamPrefix}${fieldModel.name}${queryParamSuffix}`, fieldModel.$value);
+ }
+ }
+
+ if (url.split(queryParamPrefix).length > 1) {
+ console.error('** we have missing query params ** ', url);
+ throw Error(`** we have missing query params ** ${url}`);
+ }
+
+ return url;
+
+ }
+
+ async invoke(endpoint, body, headers = {}) {
+ try {
+ const { operation } = this.props;
+ let url = this.addParamsToUrl(endpoint.path, operation.parameters || []);
+ if (endpoint.method.toLocaleLowerCase() === 'get') {
+ url = url + '?' + qs.stringify(body || '');
+ }
+ const myHeaders = new Headers();
+ for (const [key, value] of Object.entries(headers)) {
+ myHeaders.append(key, `${value}`);
+ }
+
+ const request = new Request(url, {
+ method: endpoint.method,
+ credentials: 'include',
+ redirect: 'manual',
+ headers: myHeaders,
+ body: (body) ? JSON.stringify(body) : undefined,
+ });
+
+ const result = await fetch(request);
+
+ const contentType = result.headers.get('content-type');
+ if (contentType && contentType.indexOf('application/json') !== -1) {
+ const resp = await result.json();
+
+ return { json: resp, statusCode: result.status, _fetchRes: result };
+ } else if (result.status === 200 && contentType && contentType.indexOf('text/plain') !== -1) {
+ const resp = await result.text();
+ return { resp, _fetchRes: result };
+ } else {
+ if (result && result.type && result.type === 'opaqueredirect') {
+ return {
+ json: {
+ endpoint,
+ error_code: 'RECEIVED_LOGIN_REDIRECT',
+ details: 'Your session expired. Please refresh the page.',
+ severity: 'error',
+ },
+ };
+ }
+
+ return {
+ json: {
+ endpoint,
+ error_code: 'INVALID_SERVER_RESPONSE',
+ details: 'Either server not authenticated or error on server',
+ severity: 'error',
+ },
+ };
+ }
+ } catch (error) {
+ console.error(error);
+ }
+
+ }
+
+ render() {
+ const { operation } = this.props;
+ const requestBodyContent = operation.requestBody && operation.requestBody.content && operation.requestBody.content;
+ const hasBodySample = requestBodyContent && requestBodyContent.hasSample;
+ const samples = operation.codeSamples;
+ const mediaTypes = (requestBodyContent && requestBodyContent.mediaTypes) ? requestBodyContent.mediaTypes : [];
+ const { result } = this.state;
+ return (
+
+
Console
+ {hasBodySample && (
+ (this.consoleEditor = editor)}
+ />
+ )}
+ {false && samples.map(sample => (
+
+ ))}
+
+ Send Request
+
+ {result &&
+
+ }
+
+ );
+ }
+
+ getSchema() {
+ const { operation } = this.props;
+ const requestBodyContent = operation.requestBody && operation.requestBody.content && operation.requestBody.content;
+ const mediaTypes = (requestBodyContent && requestBodyContent.mediaTypes) ? requestBodyContent.mediaTypes : [];
+
+ if (!mediaTypes.length) {
+ return null;
+ }
+ const schema: Schema = {
+ };
+ for (const mediaType of mediaTypes) {
+ if (mediaType.name.indexOf('json') > -1) {
+ if (mediaType.schema) {
+ schema.rawSchema = mediaType.schema && mediaType.schema.rawSchema;
+ console.log('rawSchema : ' + JSON.stringify(schema));
+ console.log('schema : ' + JSON.stringify(mediaType.schema.schema));
+ }
+ break;
+ }
+ }
+
+ return schema;
+
+ }
+}
diff --git a/src/components/Console/index.ts b/src/components/Console/index.ts
new file mode 100644
index 00000000..129986fe
--- /dev/null
+++ b/src/components/Console/index.ts
@@ -0,0 +1,2 @@
+export * from './ConsoleEditor';
+export * from './ConsoleViewer';
\ No newline at end of file
diff --git a/src/components/Fields/Field.tsx b/src/components/Fields/Field.tsx
index e896ed2f..c9fc8ee6 100644
--- a/src/components/Fields/Field.tsx
+++ b/src/components/Fields/Field.tsx
@@ -13,7 +13,7 @@ import {
WrappedShelfIcon,
} from '../../common-elements/fields-layout';
-import { ShelfIcon } from '../../common-elements/';
+import { ShelfIcon, TextField } from '../../common-elements/';
import { FieldModel } from '../../services/models';
import { Schema, SchemaOptions } from '../Schema/Schema';
@@ -33,6 +33,12 @@ export class Field extends React.Component {
toggle = () => {
this.props.field.toggle();
};
+
+ onFieldChange = e => {
+ console.log('Textfield value is ' + e.target.placeholder + ' - ' + e.target.value);
+ this.props.field.setValue(e.target.value);
+ };
+
render() {
const { className, field, isLast } = this.props;
const { name, expanded, deprecated, required, kind } = field;
@@ -53,12 +59,12 @@ export class Field extends React.Component {
{required && required }
) : (
-
-
- {name}
- {required && required }
-
- );
+
+
+ {name}
+ {required && required }
+
+ );
return (
<>
@@ -67,6 +73,9 @@ export class Field extends React.Component {
+ {field && field.in === 'path' &&
+ |
+ }
{field.expanded && withSubSchema && (
diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx
index 1283a6ad..ef6bc251 100644
--- a/src/components/Operation/Operation.tsx
+++ b/src/components/Operation/Operation.tsx
@@ -3,11 +3,12 @@ import { SecurityRequirements } from '../SecurityRequirement/SecurityRequirement
import { observer } from 'mobx-react';
-import { Badge, DarkRightPanel, H2, MiddlePanel, Row } from '../../common-elements';
+import { Badge, ConsoleButton, DarkRightPanel, FlexLayoutReverse, H2, MiddlePanel, Row } from '../../common-elements';
import { OptionsContext } from '../OptionsProvider';
import { ShareLink } from '../../common-elements/linkify';
+import { ConsoleViewer } from '../Console/ConsoleViewer';
import { Endpoint } from '../Endpoint/Endpoint';
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
import { Markdown } from '../Markdown/Markdown';
@@ -35,13 +36,33 @@ export interface OperationProps {
operation: OperationType;
}
+export interface OperationState {
+ executeMode: boolean;
+}
+
@observer
-export class Operation extends React.Component {
+export class Operation extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ executeMode: false,
+ };
+ }
+
+ onConsoleClick = () => {
+ this.setState({
+ executeMode: !this.state.executeMode,
+ });
+ }
+
render() {
const { operation } = this.props;
+ const { executeMode } = this.state;
const { name: summary, description, deprecated, externalDocs } = operation;
const hasDescription = !!(description || externalDocs);
+ const consoleButtonLabel = (executeMode) ? 'Hide Console' : 'Show Console';
return (
@@ -52,6 +73,11 @@ export class Operation extends React.Component {
{summary} {deprecated && Deprecated }
+ {options.enableConsole &&
+
+ {consoleButtonLabel}
+
+ }
{options.pathInMiddlePanel && }
{hasDescription && (
@@ -66,8 +92,17 @@ export class Operation extends React.Component {
{!options.pathInMiddlePanel && }
-
-
+ {executeMode &&
+
+
+
+ }
+ {!executeMode &&
+
+ }
+ {!executeMode &&
+
+ }
)}
diff --git a/src/components/SecuritySchemes/SecuritySchemes.tsx b/src/components/SecuritySchemes/SecuritySchemes.tsx
index fc5f3bc0..ebae4e44 100644
--- a/src/components/SecuritySchemes/SecuritySchemes.tsx
+++ b/src/components/SecuritySchemes/SecuritySchemes.tsx
@@ -1,8 +1,10 @@
+import { observer } from 'mobx-react';
import * as React from 'react';
+import { TokenGroup } from '..';
+
+import { DarkRightPanel, H2, MiddlePanel, Row, Section, ShareLink } from '../../common-elements';
import { SecuritySchemesModel } from '../../services/models';
-
-import { H2, MiddlePanel, Row, Section, ShareLink } from '../../common-elements';
import { OpenAPISecurityScheme } from '../../types';
import { titleize } from '../../utils/helpers';
import { Markdown } from '../Markdown/Markdown';
@@ -18,11 +20,12 @@ const AUTH_TYPES = {
export interface OAuthFlowProps {
type: string;
flow: OpenAPISecurityScheme['flows'][keyof OpenAPISecurityScheme['flows']];
+ token?: string;
}
export class OAuthFlow extends React.PureComponent {
render() {
- const { type, flow } = this.props;
+ const { type, flow, token } = this.props;
return (
{type} OAuth Flow |
@@ -56,6 +59,7 @@ export class OAuthFlow extends React.PureComponent {
))}
+ {token} |
);
}
@@ -65,7 +69,31 @@ export interface SecurityDefsProps {
securitySchemes: SecuritySchemesModel;
}
-export class SecurityDefs extends React.PureComponent {
+export interface SecurityDefsState {
+ tokens: Dict;
+}
+
+@observer
+export class SecurityDefs extends React.PureComponent {
+
+ state = {
+ tokens: {},
+ };
+
+ mutateToken = (scheme, id) => {
+ return () => {
+ scheme.setToken(this.state.tokens[id]);
+ };
+ };
+
+ setToken = id => {
+ return token => {
+ const tokens = this.state.tokens;
+ tokens[id] = token;
+ this.setState({tokens});
+ };
+ };
+
render() {
return this.props.securitySchemes.schemes.map(scheme => (
@@ -82,22 +110,26 @@ export class SecurityDefs extends React.PureComponent {
Security scheme type: |
{AUTH_TYPES[scheme.type] || scheme.type} |
+ Value |
{scheme.apiKey ? (
{titleize(scheme.apiKey.in || '')} parameter name: |
{scheme.apiKey.name} |
+ {scheme.token} |
) : scheme.http ? (
[
HTTP Authorization Scheme |
{scheme.http.scheme} |
+ {scheme.token} |
,
scheme.http.scheme === 'bearer' && scheme.http.bearerFormat && (
Bearer format |
"{scheme.http.bearerFormat}" |
+ {scheme.token} |
),
]
@@ -109,16 +141,25 @@ export class SecurityDefs extends React.PureComponent {
{scheme.openId.connectUrl}
+ {scheme.token} |
) : scheme.flows ? (
Object.keys(scheme.flows).map(type => (
-
+
))
) : null}
+
+
+
));
diff --git a/src/components/TokenGroup/TokenGroup.tsx b/src/components/TokenGroup/TokenGroup.tsx
new file mode 100644
index 00000000..fd189e31
--- /dev/null
+++ b/src/components/TokenGroup/TokenGroup.tsx
@@ -0,0 +1,84 @@
+import * as React from 'react';
+import {Button, RightPanelHeader} from '../../common-elements';
+import styled from '../../styled-components';
+
+const SaveTokenButton = styled(Button)`
+ padding: 10px 30px;
+ border-radius: 0 4px 4px 0;
+ cursor: pointer;
+ text-align: center;
+ outline: none;
+ margin: 0
+ min-width: 60px;
+ max-width: 100px;
+ font-weight: bold;
+ flex: 1 1;
+ order: 2;
+`;
+
+const TokenTextField = styled.input`
+ padding: 10px 30px 10px 20px;
+ border-radius: 4px 0 0 4px;
+ background-color: ${props => props.theme.codeSample.backgroundColor};
+ color: ${props => props.theme.codeSample.textColor}
+ white-space: nowrap;
+ align-items: center;
+ border: none;
+ direction: ltr;
+ min-width: 300px;
+ flex: 4 1;
+ order: 1;
+`;
+
+const TokenGroupContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ align-items: stretch;
+ align-content: flex-start;
+`;
+
+const Description = styled.p`
+ color: white;
+`;
+
+interface TokenGroupProps {
+ title: string;
+ description?: string;
+ onSubmit: () => void;
+ onChange: (value: string) => void;
+}
+
+export class TokenGroup extends React.PureComponent {
+ constructor(props) {
+ super(props);
+ this.submit = this.submit.bind(this);
+ this.change = this.change.bind(this);
+ }
+
+ submit() {
+ this.props.onSubmit();
+ }
+
+ change(e) {
+ this.props.onChange(e.target.value);
+ }
+
+ render() {
+ return (
+ <>
+
+ {this.props.title}
+
+
+
+ Save
+
+
+ {this.props.description}
+
+ >
+ );
+ }
+}
diff --git a/src/components/index.ts b/src/components/index.ts
index 0c7c19cb..3f88edd1 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -30,3 +30,4 @@ export * from './StickySidebar/StickyResponsiveSidebar';
export * from './SearchBox/SearchBox';
export * from './SchemaDefinition/SchemaDefinition';
export * from './SourceCode/SourceCode';
+export * from './TokenGroup/TokenGroup';
diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts
index 1bcffb27..668cd7de 100644
--- a/src/services/RedocNormalizedOptions.ts
+++ b/src/services/RedocNormalizedOptions.ts
@@ -9,6 +9,8 @@ export interface RedocRawOptions {
theme?: ThemeInterface;
scrollYOffset?: number | string | (() => number);
hideHostname?: boolean | string;
+ enableConsole?: boolean;
+ additionalHeaders?: object;
expandResponses?: string | 'all';
requiredPropsFirst?: boolean | string;
sortPropsAlphabetically?: boolean | string;
@@ -25,6 +27,11 @@ export interface RedocRawOptions {
menuToggle?: boolean | string;
jsonSampleExpandLevel?: number | string | 'all';
+ providedByName?: string;
+ providedByUri?: string;
+ queryParamPrefix?: string;
+ queryParamSuffix?: string;
+
unstable_ignoreMimeParameters?: boolean;
allowedMdComponents?: Dict;
@@ -141,6 +148,12 @@ export class RedocNormalizedOptions {
menuToggle: boolean;
jsonSampleExpandLevel: number;
enumSkipQuotes: boolean;
+ enableConsole: boolean;
+ additionalHeaders: object;
+ providedByName: string;
+ providedByUri: string;
+ queryParamPrefix: string;
+ queryParamSuffix: string;
/* tslint:disable-next-line */
unstable_ignoreMimeParameters: boolean;
@@ -177,6 +190,12 @@ export class RedocNormalizedOptions {
raw.jsonSampleExpandLevel,
);
this.enumSkipQuotes = argValueToBoolean(raw.enumSkipQuotes);
+ this.enableConsole = argValueToBoolean(raw.enableConsole);
+ this.additionalHeaders = raw.additionalHeaders || {};
+ this.providedByName = raw.providedByName || 'Documentation Powered by ReDoc';
+ this.providedByUri = raw.providedByUri || 'https://github.com/Rebilly/ReDoc';
+ this.queryParamPrefix = raw.queryParamPrefix || '{';
+ this.queryParamSuffix = raw.queryParamSuffix || '}';
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);
diff --git a/src/services/SearchStore.ts b/src/services/SearchStore.ts
index 669d8d05..ac7c57b8 100644
--- a/src/services/SearchStore.ts
+++ b/src/services/SearchStore.ts
@@ -9,7 +9,7 @@ let worker: new () => Worker;
if (IS_BROWSER) {
try {
// tslint:disable-next-line
- worker = require('workerize-loader?inline&fallback=false!./SearchWorker.worker');
+ worker = require('workerize-loader?fallback=false!./SearchWorker.worker');
} catch (e) {
worker = require('./SearchWorker.worker').default;
}
diff --git a/src/services/models/Field.ts b/src/services/models/Field.ts
index 5302a09f..d1c17697 100644
--- a/src/services/models/Field.ts
+++ b/src/services/models/Field.ts
@@ -29,9 +29,8 @@ function getDefaultStyleValue(parameterLocation: OpenAPIParameterLocation): Open
* Field or Parameter model ready to be used by components
*/
export class FieldModel {
- @observable
- expanded: boolean = false;
-
+ @observable expanded: boolean = false;
+ @observable $value: string = '';
schema: SchemaModel;
name: string;
required: boolean;
@@ -92,4 +91,9 @@ export class FieldModel {
toggle() {
this.expanded = !this.expanded;
}
+
+ @action
+ setValue(value: string) {
+ this.$value = value;
+ }
}
diff --git a/src/services/models/SecuritySchemes.ts b/src/services/models/SecuritySchemes.ts
index fc5deda8..2fb62f92 100644
--- a/src/services/models/SecuritySchemes.ts
+++ b/src/services/models/SecuritySchemes.ts
@@ -1,3 +1,4 @@
+import {observable} from 'mobx';
import { OpenAPISecurityScheme, Referenced } from '../../types';
import { SECURITY_SCHEMES_SECTION_PREFIX } from '../../utils/openapi';
import { OpenAPIParser } from '../OpenAPIParser';
@@ -22,6 +23,9 @@ export class SecuritySchemeModel {
connectUrl: string;
};
+ @observable
+ token?: string = '';
+
constructor(parser: OpenAPIParser, id: string, scheme: Referenced) {
const info = parser.deref(scheme);
this.id = id;
@@ -52,9 +56,14 @@ export class SecuritySchemeModel {
this.flows = info.flows;
}
}
+
+ setToken(token: string) {
+ this.token = token;
+ }
}
export class SecuritySchemesModel {
+ @observable
schemes: SecuritySchemeModel[];
constructor(parser: OpenAPIParser) {
diff --git a/src/theme.ts b/src/theme.ts
index 4b9f37f2..812be850 100644
--- a/src/theme.ts
+++ b/src/theme.ts
@@ -149,6 +149,10 @@ const defaultTheme: ThemeInterface = {
},
codeSample: {
backgroundColor: ({ rightPanel }) => darken(0.1, rightPanel.backgroundColor),
+ textColor: ({ rightPanel }) => rightPanel.textColor,
+ },
+ styledPre: {
+ maxHeight: '500px',
},
};
@@ -321,9 +325,13 @@ export interface ResolvedThemeInterface {
};
codeSample: {
backgroundColor: string;
+ textColor: string;
};
extensionsHook?: (name: string, props: any) => string;
+ styledPre: {
+ maxHeight: string;
+ };
}
export type primitive = string | number | boolean | undefined | null;
diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts
new file mode 100644
index 00000000..b332d125
--- /dev/null
+++ b/src/utils/fetch.ts
@@ -0,0 +1 @@
+//parseparseFetchFetch
\ No newline at end of file
diff --git a/src/utils/loadAndBundleSpec.ts b/src/utils/loadAndBundleSpec.ts
index d2431b8d..e8d3532d 100644
--- a/src/utils/loadAndBundleSpec.ts
+++ b/src/utils/loadAndBundleSpec.ts
@@ -9,11 +9,20 @@ export async function loadAndBundleSpec(specUrlOrObject: object | string): Promi
resolve: { http: { withCredentials: false } },
} as object)) as any;
+ let v2Specs = spec;
if (spec.swagger !== undefined) {
- return convertSwagger2OpenAPI(spec);
- } else {
- return spec;
+ v2Specs = await convertSwagger2OpenAPI(spec);
}
+
+ // we can derefrence the schema here for future use.
+ // import { cloneDeep } from 'lodash';
+ // const derefrencedSpec = await parser.dereference(cloneDeep(spec));
+ // const derefed = await parser.dereference(v2Specs, {
+ // resolve: { http: { withCredentials: false } },
+ // } as object);
+
+ return v2Specs;
+
}
export function convertSwagger2OpenAPI(spec: any): Promise {
diff --git a/tsconfig.json b/tsconfig.json
index 6a327741..466ea081 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -39,4 +39,4 @@
"./src/**/*.ts?",
"demo/*.tsx"
]
-}
+}
\ No newline at end of file
diff --git a/tslint.json b/tslint.json
index 9c980dcb..feec7e40 100644
--- a/tslint.json
+++ b/tslint.json
@@ -17,7 +17,7 @@
"quotemark": [true, "single", "avoid-template", "jsx-double"],
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
"arrow-parens": [true, "ban-single-arg-parens"],
- "no-submodule-imports": [true, "prismjs", "perfect-scrollbar", "react-dom", "core-js"],
+ "no-submodule-imports": [true, "prismjs", "perfect-scrollbar", "react-dom", "core-js", "brace"],
"object-literal-key-quotes": [true, "as-needed"],
"no-unused-expression": [true, "allow-tagged-template"],
"semicolon": [true, "always", "ignore-bound-class-methods"],
diff --git a/yarn.lock b/yarn.lock
index 04ee8e94..3c0db313 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -570,6 +570,14 @@
"@babel/helper-regex" "^7.4.4"
regexpu-core "^4.5.4"
+"@babel/polyfill@^7.4.4":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.3.tgz#2333fc2144a542a7c07da39502ceeeb3abe4debd"
+ integrity sha512-0QEgn2zkCzqGIkSWWAEmvxD7e00Nm9asTtQvi7HdlYvMhjy/J38V/1Y9ode0zEJeIuxAI0uftiAzqc7nVeWUGg==
+ dependencies:
+ core-js "^2.6.5"
+ regenerator-runtime "^0.13.2"
+
"@babel/preset-env@^7.0.0":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.5.5.tgz#bc470b53acaa48df4b8db24a570d6da1fef53c9a"
@@ -1052,11 +1060,21 @@
resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.16.0.tgz#4328c9f65698e59f4feade8f4e5d928c748fd643"
integrity sha512-mEyuziLrfDCQ4juQP1k706BUU/c8OGn/ZFl69AXXY6dStHClKX4P+N8+rhqpul1vRDA2VOygzMRSJJZHyDEOfw==
+"@types/promise@^7.1.30":
+ version "7.1.30"
+ resolved "https://registry.yarnpkg.com/@types/promise/-/promise-7.1.30.tgz#1b6714b321fdfc54d1527e7a17116a0e1f2ab810"
+ integrity sha1-G2cUsyH9/FTRUn56FxFqDh8quBA=
+
"@types/prop-types@*", "@types/prop-types@^15.7.1":
version "15.7.1"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.1.tgz#f1a11e7babb0c3cad68100be381d1e064c68f1f6"
integrity sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==
+"@types/qs@^6.5.1":
+ version "6.9.0"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.0.tgz#2a5fa918786d07d3725726f7f650527e1cfeaffd"
+ integrity sha512-c4zji5CjWv1tJxIZkz1oUtGcdOlsH3aza28Nqmm+uNDWBRHoMsjooBEN4czZp1V3iXPihE/VRUOBqg+4Xq0W4g==
+
"@types/react-dom@^16.8.5":
version "16.8.5"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.5.tgz#3e3f4d99199391a7fb40aa3a155c8dd99b899cbd"
@@ -1449,7 +1467,7 @@ ajv@^5.5.2:
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.3.0"
-ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1:
+ajv@^6.1.0, ajv@^6.10.2, ajv@^6.4.0, ajv@^6.5.5, ajv@^6.9.1:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
@@ -1953,6 +1971,11 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
+brace@^0.11.1:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58"
+ integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg=
+
braces@^2.3.1, braces@^2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -2879,6 +2902,11 @@ core-js@^2.5.7:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
+core-js@^2.6.5:
+ version "2.6.11"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
+ integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
+
core-js@^3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07"
@@ -3323,6 +3351,11 @@ dezalgo@^1.0.0:
asap "^2.0.0"
wrappy "1"
+diff-match-patch@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
+ integrity sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
+
diff-sequences@^24.3.0:
version "24.3.0"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
@@ -6205,6 +6238,11 @@ lodash.flattendeep@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
+
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
@@ -7886,6 +7924,11 @@ qs@6.7.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
+qs@^6.5.2:
+ version "6.9.1"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
+ integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==
+
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
@@ -7976,6 +8019,18 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-ace@^6.0.0:
+ version "6.6.0"
+ resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-6.6.0.tgz#a79457ef03c3b1f8d4fc598a003b1d6ad464f1a0"
+ integrity sha512-Jehhp8bxa8kqiXk07Jzy+uD5qZMBwo43O+raniGHjdX7Qk93xFkKaAz8LxtUVZPJGlRnV5ODMNj0qHwDSN+PBw==
+ dependencies:
+ "@babel/polyfill" "^7.4.4"
+ brace "^0.11.1"
+ diff-match-patch "^1.0.4"
+ lodash.get "^4.4.2"
+ lodash.isequal "^4.5.0"
+ prop-types "^15.7.2"
+
react-dom@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"