chore: add isArray helper function

This commit is contained in:
Alex Varchuk 2022-05-06 19:01:47 +03:00 committed by AlexVarchuk
parent f0cf5fe149
commit e7a6d38a56
6 changed files with 35 additions and 29 deletions

View File

@ -11,6 +11,7 @@ import { ObjectSchema } from './ObjectSchema';
import { OneOfSchema } from './OneOfSchema'; import { OneOfSchema } from './OneOfSchema';
import { l } from '../../services/Labels'; import { l } from '../../services/Labels';
import { isArray } from '../../utils/helpers';
export interface SchemaOptions { export interface SchemaOptions {
showTitle?: boolean; showTitle?: boolean;
@ -68,7 +69,7 @@ export class Schema extends React.Component<Partial<SchemaProps>> {
return <OneOfSchema schema={schema} {...rest} />; return <OneOfSchema schema={schema} {...rest} />;
} }
const types = Array.isArray(type) ? type : [type]; const types = isArray(type) ? type : [type];
if (types.includes('object')) { if (types.includes('object')) {
if (schema.fields?.length) { if (schema.fields?.length) {
return <ObjectSchema {...(this.props as any)} level={level} />; return <ObjectSchema {...(this.props as any)} level={level} />;

View File

@ -1,6 +1,6 @@
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types'; import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
import { appendToMdHeading, IS_BROWSER } from '../utils/'; import { appendToMdHeading, isArray, IS_BROWSER } from '../utils/';
import { JsonPointer } from '../utils/JsonPointer'; import { JsonPointer } from '../utils/JsonPointer';
import { import {
getDefinitionName, getDefinitionName,
@ -363,7 +363,7 @@ export class OpenAPIParser {
const allOf = schema.allOf; const allOf = schema.allOf;
for (let i = 0; i < allOf.length; i++) { for (let i = 0; i < allOf.length; i++) {
const sub = allOf[i]; const sub = allOf[i];
if (Array.isArray(sub.oneOf)) { if (isArray(sub.oneOf)) {
const beforeAllOf = allOf.slice(0, i); const beforeAllOf = allOf.slice(0, i);
const afterAllOf = allOf.slice(i + 1); const afterAllOf = allOf.slice(i + 1);
return { return {

View File

@ -1,6 +1,6 @@
import defaultTheme, { ResolvedThemeInterface, resolveTheme, ThemeInterface } from '../theme'; import defaultTheme, { ResolvedThemeInterface, resolveTheme, ThemeInterface } from '../theme';
import { querySelector } from '../utils/dom'; import { querySelector } from '../utils/dom';
import { isNumeric, mergeObjects } from '../utils/helpers'; import { isArray, isNumeric, mergeObjects } from '../utils/helpers';
import { LabelsConfigRaw, setRedocLabels } from './Labels'; import { LabelsConfigRaw, setRedocLabels } from './Labels';
import { MDXComponentMeta } from './MarkdownRenderer'; import { MDXComponentMeta } from './MarkdownRenderer';
@ -316,7 +316,7 @@ export class RedocNormalizedOptions {
this.expandDefaultServerVariables = argValueToBoolean(raw.expandDefaultServerVariables); this.expandDefaultServerVariables = argValueToBoolean(raw.expandDefaultServerVariables);
this.maxDisplayedEnumValues = argValueToNumber(raw.maxDisplayedEnumValues); this.maxDisplayedEnumValues = argValueToNumber(raw.maxDisplayedEnumValues);
const ignoreNamedSchemas = Array.isArray(raw.ignoreNamedSchemas) const ignoreNamedSchemas = isArray(raw.ignoreNamedSchemas)
? raw.ignoreNamedSchemas ? raw.ignoreNamedSchemas
: raw.ignoreNamedSchemas?.split(',').map(s => s.trim()); : raw.ignoreNamedSchemas?.split(',').map(s => s.trim());
this.ignoreNamedSchemas = new Set(ignoreNamedSchemas); this.ignoreNamedSchemas = new Set(ignoreNamedSchemas);

View File

@ -11,6 +11,7 @@ import {
detectType, detectType,
extractExtensions, extractExtensions,
humanizeConstraints, humanizeConstraints,
isArray,
isNamedDefinition, isNamedDefinition,
isPrimitiveType, isPrimitiveType,
JsonPointer, JsonPointer,
@ -103,7 +104,7 @@ export class SchemaModel {
} }
hasType(type: string) { hasType(type: string) {
return this.type === type || (Array.isArray(this.type) && this.type.includes(type)); return this.type === type || (isArray(this.type) && this.type.includes(type));
} }
init(parser: OpenAPIParser, isChild: boolean) { init(parser: OpenAPIParser, isChild: boolean) {
@ -134,17 +135,14 @@ export class SchemaModel {
this.maxItems = schema.maxItems; this.maxItems = schema.maxItems;
if (!!schema.nullable || schema['x-nullable']) { if (!!schema.nullable || schema['x-nullable']) {
if ( if (isArray(this.type) && !this.type.some(value => value === null || value === 'null')) {
Array.isArray(this.type) &&
!this.type.some(value => value === null || value === 'null')
) {
this.type = [...this.type, 'null']; this.type = [...this.type, 'null'];
} else if (!Array.isArray(this.type) && (this.type !== null || this.type !== 'null')) { } else if (!isArray(this.type) && (this.type !== null || this.type !== 'null')) {
this.type = [this.type, 'null']; this.type = [this.type, 'null'];
} }
} }
this.displayType = Array.isArray(this.type) this.displayType = isArray(this.type)
? this.type.map(item => (item === null ? 'null' : item)).join(' or ') ? this.type.map(item => (item === null ? 'null' : item)).join(' or ')
: this.type; : this.type;
@ -157,7 +155,7 @@ export class SchemaModel {
return; return;
} else if ( } else if (
isChild && isChild &&
Array.isArray(schema.oneOf) && isArray(schema.oneOf) &&
schema.oneOf.find(s => s.$ref === this.pointer) schema.oneOf.find(s => s.$ref === this.pointer)
) { ) {
// we hit allOf of the schema with the parent discriminator // we hit allOf of the schema with the parent discriminator
@ -196,7 +194,7 @@ export class SchemaModel {
if (this.items.isPrimitive) { if (this.items.isPrimitive) {
this.enum = this.items.enum; this.enum = this.items.enum;
} }
if (Array.isArray(this.type)) { if (isArray(this.type)) {
const filteredType = this.type.filter(item => item !== 'array'); const filteredType = this.type.filter(item => item !== 'array');
if (filteredType.length) this.displayType += ` or ${filteredType.join(' or ')}`; if (filteredType.length) this.displayType += ` or ${filteredType.join(' or ')}`;
} }
@ -295,7 +293,7 @@ export class SchemaModel {
for (const name in mapping) { for (const name in mapping) {
const $ref = mapping[name]; const $ref = mapping[name];
if (Array.isArray(explicitInversedMapping[$ref])) { if (isArray(explicitInversedMapping[$ref])) {
explicitInversedMapping[$ref].push(name); explicitInversedMapping[$ref].push(name);
} else { } else {
// overrides implicit mapping here // overrides implicit mapping here
@ -311,7 +309,7 @@ export class SchemaModel {
for (const $ref of Object.keys(inversedMapping)) { for (const $ref of Object.keys(inversedMapping)) {
const names = inversedMapping[$ref]; const names = inversedMapping[$ref];
if (Array.isArray(names)) { if (isArray(names)) {
for (const name of names) { for (const name of names) {
refs.push({ $ref, name }); refs.push({ $ref, name });
} }

View File

@ -112,7 +112,7 @@ const isObject = (item: any): boolean => {
}; };
const isMergebleObject = (item): boolean => { const isMergebleObject = (item): boolean => {
return isObject(item) && !Array.isArray(item); return isObject(item) && !isArray(item);
}; };
/** /**
@ -209,3 +209,7 @@ export function unescapeHTMLChars(str: string): string {
.replace(/&amp;/g, '&') .replace(/&amp;/g, '&')
.replace(/&quot;/g, '"'); .replace(/&quot;/g, '"');
} }
export function isArray(value: unknown): value is Array<any> {
return Array.isArray(value);
}

View File

@ -16,7 +16,7 @@ import {
Referenced, Referenced,
} from '../types'; } from '../types';
import { IS_BROWSER } from './dom'; import { IS_BROWSER } from './dom';
import { isNumeric, removeQueryString, resolveUrl } from './helpers'; import { isNumeric, removeQueryString, resolveUrl, isArray } from './helpers';
function isWildcardStatusCode(statusCode: string | number): statusCode is string { function isWildcardStatusCode(statusCode: string | number): statusCode is string {
return typeof statusCode === 'string' && /\dxx/i.test(statusCode); return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
@ -102,7 +102,7 @@ const schemaKeywordTypes = {
}; };
export function detectType(schema: OpenAPISchema): string { export function detectType(schema: OpenAPISchema): string {
if (schema.type !== undefined && !Array.isArray(schema.type)) { if (schema.type !== undefined && !isArray(schema.type)) {
return schema.type; return schema.type;
} }
const keywords = Object.keys(schemaKeywordTypes); const keywords = Object.keys(schemaKeywordTypes);
@ -125,16 +125,19 @@ export function isPrimitiveType(
} }
let isPrimitive = true; let isPrimitive = true;
const isArray = Array.isArray(type); const isArrayType = isArray(type);
if (type === 'object' || (isArray && type?.includes('object'))) { if (type === 'object' || (isArrayType && type?.includes('object'))) {
isPrimitive = isPrimitive =
schema.properties !== undefined schema.properties !== undefined
? Object.keys(schema.properties).length === 0 ? Object.keys(schema.properties).length === 0
: schema.additionalProperties === undefined && schema.unevaluatedProperties === undefined; : schema.additionalProperties === undefined && schema.unevaluatedProperties === undefined;
} }
if (schema.items !== undefined && (type === 'array' || (isArray && type?.includes('array')))) { if (
schema.items !== undefined &&
(type === 'array' || (isArrayType && type?.includes('array')))
) {
isPrimitive = isPrimitiveType(schema.items, schema.items.type); isPrimitive = isPrimitiveType(schema.items, schema.items.type);
} }
@ -150,7 +153,7 @@ export function isFormUrlEncoded(contentType: string): boolean {
} }
function delimitedEncodeField(fieldVal: any, fieldName: string, delimiter: string): string { function delimitedEncodeField(fieldVal: any, fieldName: string, delimiter: string): string {
if (Array.isArray(fieldVal)) { if (isArray(fieldVal)) {
return fieldVal.map(v => v.toString()).join(delimiter); return fieldVal.map(v => v.toString()).join(delimiter);
} else if (typeof fieldVal === 'object') { } else if (typeof fieldVal === 'object') {
return Object.keys(fieldVal) return Object.keys(fieldVal)
@ -162,7 +165,7 @@ function delimitedEncodeField(fieldVal: any, fieldName: string, delimiter: strin
} }
function deepObjectEncodeField(fieldVal: any, fieldName: string): string { function deepObjectEncodeField(fieldVal: any, fieldName: string): string {
if (Array.isArray(fieldVal)) { if (isArray(fieldVal)) {
console.warn('deepObject style cannot be used with array value:' + fieldVal.toString()); console.warn('deepObject style cannot be used with array value:' + fieldVal.toString());
return ''; return '';
} else if (typeof fieldVal === 'object') { } else if (typeof fieldVal === 'object') {
@ -195,7 +198,7 @@ export function urlFormEncodePayload(
payload: object, payload: object,
encoding: { [field: string]: OpenAPIEncoding } = {}, encoding: { [field: string]: OpenAPIEncoding } = {},
) { ) {
if (Array.isArray(payload)) { if (isArray(payload)) {
throw new Error('Payload must have fields: ' + payload.toString()); throw new Error('Payload must have fields: ' + payload.toString());
} else { } else {
return Object.keys(payload) return Object.keys(payload)
@ -254,7 +257,7 @@ function serializeQueryParameter(
case 'form': case 'form':
return serializeFormValue(name, explode, value); return serializeFormValue(name, explode, value);
case 'spaceDelimited': case 'spaceDelimited':
if (!Array.isArray(value)) { if (!isArray(value)) {
console.warn('The style spaceDelimited is only applicable to arrays'); console.warn('The style spaceDelimited is only applicable to arrays');
return ''; return '';
} }
@ -264,7 +267,7 @@ function serializeQueryParameter(
return `${name}=${value.join('%20')}`; return `${name}=${value.join('%20')}`;
case 'pipeDelimited': case 'pipeDelimited':
if (!Array.isArray(value)) { if (!isArray(value)) {
console.warn('The style pipeDelimited is only applicable to arrays'); console.warn('The style pipeDelimited is only applicable to arrays');
return ''; return '';
} }
@ -274,7 +277,7 @@ function serializeQueryParameter(
return `${name}=${value.join('|')}`; return `${name}=${value.join('|')}`;
case 'deepObject': case 'deepObject':
if (!explode || Array.isArray(value) || typeof value !== 'object') { if (!explode || isArray(value) || typeof value !== 'object') {
console.warn('The style deepObject is only applicable for objects with explode=true'); console.warn('The style deepObject is only applicable for objects with explode=true');
return ''; return '';
} }
@ -330,7 +333,7 @@ export function serializeParameterValueWithMime(value: any, mime: string): strin
} }
export function serializeParameterValue( export function serializeParameterValue(
parameter: OpenAPIParameter & { serializationMime?: string }, parameter: (OpenAPIParameter & { serializationMime?: string }) | FieldModel,
value: any, value: any,
): string { ): string {
const { name, style, explode = false, serializationMime } = parameter; const { name, style, explode = false, serializationMime } = parameter;