feat(json-schema): expose API that generates examples from JSON Schema (#9190)

This allows to use the samples API in a static way
without fully instantiating SwaggerUI.

Refs #9188
This commit is contained in:
Vladimír Gorej
2023-09-05 14:13:53 +02:00
committed by GitHub
parent edd1153723
commit 113996f627
83 changed files with 292 additions and 88 deletions

View File

@@ -169,6 +169,7 @@ SwaggerUI.defaultProps = {
oauth2RedirectUrl: undefined,
}
SwaggerUI.System = SwaggerUIConstructor.System
SwaggerUI.presets = SwaggerUIConstructor.presets
SwaggerUI.plugins = SwaggerUIConstructor.plugins

View File

@@ -12,13 +12,14 @@ import ErrPlugin from "./plugins/err"
import FilterPlugin from "./plugins/filter"
import IconsPlugin from "./plugins/icons"
import JSONSchema202012Plugin from "./plugins/json-schema-2020-12"
import JSONSchema202012SamplesPlugin from "./plugins/json-schema-2020-12-samples"
import LayoutPlugin from "./plugins/layout"
import LogsPlugin from "./plugins/logs"
import OpenAPI30Plugin from "./plugins/oas3"
import OpenAPI31Plugin from "./plugins/oas3"
import OnCompletePlugin from "./plugins/on-complete"
import RequestSnippetsPlugin from "./plugins/request-snippets"
import SamplesPlugin from "./plugins/samples"
import JSONSchema5SamplesPlugin from "./plugins/json-schema-5-samples"
import SpecPlugin from "./plugins/spec"
import SwaggerClientPlugin from "./plugins/swagger-client"
import UtilPlugin from "./plugins/util"
@@ -239,6 +240,8 @@ export default function SwaggerUI(opts) {
return system
}
SwaggerUI.System = System
SwaggerUI.presets = {
base: BasePreset,
apis: ApisPreset,
@@ -251,14 +254,15 @@ SwaggerUI.plugins = {
Err: ErrPlugin,
Filter: FilterPlugin,
Icons: IconsPlugin,
JSONSchema5Samples: JSONSchema5SamplesPlugin,
JSONSchema202012: JSONSchema202012Plugin,
JSONSchema202012Samples: JSONSchema202012SamplesPlugin,
Layout: LayoutPlugin,
Logs: LogsPlugin,
OpenAPI30: OpenAPI30Plugin,
OpenAPI31: OpenAPI31Plugin,
OnComplete: OnCompletePlugin,
RequestSnippets: RequestSnippetsPlugin,
Samples: SamplesPlugin,
Spec: SpecPlugin,
SwaggerClient: SwaggerClientPlugin,
Util: UtilPlugin,

View File

@@ -2,7 +2,7 @@
* @prettier
*/
import EncoderRegistry from "core/plugins/json-schema-2020-12/samples-extensions/fn/class/EncoderRegistry"
import EncoderRegistry from "../class/EncoderRegistry"
const registry = new EncoderRegistry()

View File

@@ -0,0 +1,36 @@
/**
* @prettier
*/
import some from "lodash/some"
const shouldStringifyTypesConfig = [
{
when: /json/,
shouldStringifyTypes: ["string"],
},
]
const defaultStringifyTypes = ["object"]
const makeGetJsonSampleSchema =
(getSystem) => (schema, config, contentType, exampleOverride) => {
const { fn } = getSystem()
const res = fn.jsonSchema202012.memoizedSampleFromSchema(
schema,
config,
exampleOverride
)
const resType = typeof res
const typesToStringify = shouldStringifyTypesConfig.reduce(
(types, nextConfig) =>
nextConfig.when.test(contentType)
? [...types, ...nextConfig.shouldStringifyTypes]
: types,
defaultStringifyTypes
)
return some(typesToStringify, (x) => x === resType)
? JSON.stringify(res, null, 2)
: res
}
export default makeGetJsonSampleSchema

View File

@@ -0,0 +1,39 @@
/**
* @prettier
*/
const makeGetSampleSchema =
(getSystem) =>
(schema, contentType = "", config = {}, exampleOverride = undefined) => {
const { fn } = getSystem()
if (typeof schema?.toJS === "function") {
schema = schema.toJS()
}
if (typeof exampleOverride?.toJS === "function") {
exampleOverride = exampleOverride.toJS()
}
if (/xml/.test(contentType)) {
return fn.jsonSchema202012.getXmlSampleSchema(
schema,
config,
exampleOverride
)
}
if (/(yaml|yml)/.test(contentType)) {
return fn.jsonSchema202012.getYamlSampleSchema(
schema,
config,
contentType,
exampleOverride
)
}
return fn.jsonSchema202012.getJsonSampleSchema(
schema,
config,
contentType,
exampleOverride
)
}
export default makeGetSampleSchema

View File

@@ -0,0 +1,35 @@
/**
* @prettier
*/
const makeGetXmlSampleSchema =
(getSystem) => (schema, config, exampleOverride) => {
const { fn } = getSystem()
if (schema && !schema.xml) {
schema.xml = {}
}
if (schema && !schema.xml.name) {
if (
!schema.$$ref &&
(schema.type ||
schema.items ||
schema.properties ||
schema.additionalProperties)
) {
// eslint-disable-next-line quotes
return '<?xml version="1.0" encoding="UTF-8"?>\n<!-- XML example cannot be generated; root element name is undefined -->'
}
if (schema.$$ref) {
let match = schema.$$ref.match(/\S*\/(\S+)$/)
schema.xml.name = match[1]
}
}
return fn.jsonSchema202012.memoizedCreateXMLExample(
schema,
config,
exampleOverride
)
}
export default makeGetXmlSampleSchema

View File

@@ -0,0 +1,34 @@
/**
* @prettier
*/
import YAML, { JSON_SCHEMA } from "js-yaml"
const makeGetYamlSampleSchema =
(getSystem) => (schema, config, contentType, exampleOverride) => {
const { fn } = getSystem()
const jsonExample = fn.jsonSchema202012.getJsonSampleSchema(
schema,
config,
contentType,
exampleOverride
)
let yamlString
try {
yamlString = YAML.dump(
YAML.load(jsonExample),
{
lineWidth: -1, // don't generate line folds
},
{ schema: JSON_SCHEMA }
)
if (yamlString[yamlString.length - 1] === "\n") {
yamlString = yamlString.slice(0, yamlString.length - 1)
}
} catch (e) {
console.error(e)
return "error: could not generate yaml example"
}
return yamlString.replace(/\t/g, " ")
}
export default makeGetYamlSampleSchema

View File

@@ -0,0 +1,45 @@
/**
* @prettier
*/
import {
sampleFromSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
encoderAPI,
mediaTypeAPI,
formatAPI,
} from "./fn/index"
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "./fn/get-xml-sample-schema"
import makeGetSampleSchema from "./fn/get-sample-schema"
const JSONSchema202012SamplesPlugin = ({ getSystem }) => {
const getJsonSampleSchema = makeGetJsonSampleSchema(getSystem)
const getYamlSampleSchema = makeGetYamlSampleSchema(getSystem)
const getXmlSampleSchema = makeGetXmlSampleSchema(getSystem)
const getSampleSchema = makeGetSampleSchema(getSystem)
return {
fn: {
jsonSchema202012: {
sampleFromSchema,
sampleFromSchemaGeneric,
sampleEncoderAPI: encoderAPI,
sampleFormatAPI: formatAPI,
sampleMediaTypeAPI: mediaTypeAPI,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
getJsonSampleSchema,
getYamlSampleSchema,
getXmlSampleSchema,
getSampleSchema,
},
},
}
}
export default JSONSchema202012SamplesPlugin

View File

@@ -44,16 +44,6 @@ import Accordion from "./components/Accordion/Accordion"
import ExpandDeepButton from "./components/ExpandDeepButton/ExpandDeepButton"
import ChevronRightIcon from "./components/icons/ChevronRight"
import { upperFirst, hasKeyword, isExpandable } from "./fn"
import {
sampleFromSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
encoderAPI,
mediaTypeAPI,
formatAPI,
} from "./samples-extensions/fn/index"
import { JSONSchemaDeepExpansionContext } from "./context"
import { useFn, useConfig, useComponent, useIsExpandedDeeply } from "./hooks"
import { withJSONSchemaContext } from "./hoc"
@@ -114,14 +104,6 @@ const JSONSchema202012Plugin = () => ({
useConfig,
useComponent,
useIsExpandedDeeply,
sampleFromSchema,
sampleFromSchemaGeneric,
sampleEncoderAPI: encoderAPI,
sampleFormatAPI: formatAPI,
sampleMediaTypeAPI: mediaTypeAPI,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
},
},
})

View File

@@ -0,0 +1,51 @@
/**
* @prettier
*/
import {
sampleFromSchema,
inferSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedCreateXMLExample,
memoizedSampleFromSchema,
} from "./fn/index"
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "./fn/get-xml-sample-schema"
import makeGetSampleSchema from "./fn/get-sample-schema"
const JSONSchema5SamplesPlugin = ({ getSystem }) => {
const getJsonSampleSchema = makeGetJsonSampleSchema(getSystem)
const getYamlSampleSchema = makeGetYamlSampleSchema(getSystem)
const getXmlSampleSchema = makeGetXmlSampleSchema(getSystem)
const getSampleSchema = makeGetSampleSchema(getSystem)
return {
fn: {
jsonSchema5: {
inferSchema,
sampleFromSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
getJsonSampleSchema,
getYamlSampleSchema,
getXmlSampleSchema,
getSampleSchema,
},
inferSchema,
sampleFromSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
getJsonSampleSchema,
getYamlSampleSchema,
getXmlSampleSchema,
getSampleSchema,
},
}
}
export default JSONSchema5SamplesPlugin

View File

@@ -1,32 +0,0 @@
/**
* @prettier
*/
import {
sampleFromSchema,
inferSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedCreateXMLExample,
memoizedSampleFromSchema,
} from "./fn/index"
import makeGetJsonSampleSchema from "./fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "./fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "./fn/get-xml-sample-schema"
import makeGetSampleSchema from "./fn/get-sample-schema"
const SamplesPlugin = ({ getSystem }) => ({
fn: {
inferSchema,
sampleFromSchema,
sampleFromSchemaGeneric,
createXMLExample,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
getJsonSampleSchema: makeGetJsonSampleSchema(getSystem),
getYamlSampleSchema: makeGetYamlSampleSchema(getSystem),
getXmlSampleSchema: makeGetXmlSampleSchema(getSystem),
getSampleSchema: makeGetSampleSchema(getSystem),
},
})
export default SamplesPlugin

View File

@@ -5,7 +5,14 @@ import BasePreset from "core/presets/base"
import OpenAPI30Plugin from "core/plugins/oas3"
import OpenAPI31Plugin from "core/plugins/oas31"
import JSONSchema202012Plugin from "core/plugins/json-schema-2020-12"
import JSONSchema202012SamplesPlugin from "core/plugins/json-schema-2020-12-samples"
export default function PresetApis() {
return [BasePreset, OpenAPI30Plugin, JSONSchema202012Plugin, OpenAPI31Plugin]
return [
BasePreset,
OpenAPI30Plugin,
JSONSchema202012Plugin,
JSONSchema202012SamplesPlugin,
OpenAPI31Plugin,
]
}

View File

@@ -11,7 +11,7 @@ import LayoutPlugin from "core/plugins/layout"
import LogsPlugin from "core/plugins/logs"
import OnCompletePlugin from "core/plugins/on-complete"
import RequestSnippetsPlugin from "core/plugins/request-snippets"
import SamplesPlugin from "core/plugins/samples"
import JSONSchema5SamplesPlugin from "core/plugins/json-schema-5-samples"
import SpecPlugin from "core/plugins/spec"
import SwaggerClientPlugin from "core/plugins/swagger-client"
import UtilPlugin from "core/plugins/util"
@@ -32,7 +32,7 @@ const BasePreset = () => [
ErrPlugin,
IconsPlugin,
LayoutPlugin,
SamplesPlugin,
JSONSchema5SamplesPlugin,
CoreComponentsPlugin,
FormComponentsPlugin,
SwaggerClientPlugin,

View File

@@ -9,11 +9,11 @@ import ParameterRow from "core/components/parameter-row"
import {
memoizedSampleFromSchema,
memoizedCreateXMLExample,
} from "core/plugins/samples/fn/index"
import makeGetSampleSchema from "core/plugins/samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/samples/fn/get-xml-sample-schema"
} from "core/plugins/json-schema-5-samples/fn/index"
import makeGetSampleSchema from "core/plugins/json-schema-5-samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/json-schema-5-samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-xml-sample-schema"
describe("bug #4557: default parameter values", function () {
it("should apply a Swagger 2.0 default value", function () {

View File

@@ -9,11 +9,11 @@ import ParameterRow from "core/components/parameter-row"
import {
memoizedSampleFromSchema,
memoizedCreateXMLExample,
} from "core/plugins/samples/fn/index"
import makeGetSampleSchema from "core/plugins/samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/samples/fn/get-xml-sample-schema"
} from "core/plugins/json-schema-5-samples/fn/index"
import makeGetSampleSchema from "core/plugins/json-schema-5-samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/json-schema-5-samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-xml-sample-schema"
describe("<ParameterRow/>", () => {
const createProps = ({ param, isOAS3 }) => {

View File

@@ -11,11 +11,11 @@ import {
inferSchema,
memoizedSampleFromSchema,
memoizedCreateXMLExample,
} from "core/plugins/samples/fn/index"
import makeGetSampleSchema from "core/plugins/samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/samples/fn/get-xml-sample-schema"
} from "core/plugins/json-schema-5-samples/fn/index"
import makeGetSampleSchema from "core/plugins/json-schema-5-samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/json-schema-5-samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-xml-sample-schema"
describe("<Response />", function () {
const dummyComponent = () => null

View File

@@ -8,7 +8,7 @@ import {
sampleFromSchema,
memoizedCreateXMLExample,
memoizedSampleFromSchema,
} from "core/plugins/json-schema-2020-12/samples-extensions/fn"
} from "core/plugins/json-schema-2020-12-samples/fn"
describe("sampleFromSchema", () => {
it("should return appropriate example for primitive types + format", function () {

View File

@@ -4,22 +4,24 @@
import {
memoizedSampleFromSchema,
memoizedCreateXMLExample,
} from "core/plugins/samples/fn/index"
import makeGetSampleSchema from "core/plugins/samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/samples/fn/get-xml-sample-schema"
} from "core/plugins/json-schema-2020-12-samples/fn/index"
import makeGetSampleSchema from "core/plugins/json-schema-2020-12-samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/json-schema-2020-12-samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/json-schema-2020-12-samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/json-schema-2020-12-samples/fn/get-xml-sample-schema"
describe("getSampleSchema", () => {
const oriDate = Date
const getSystem = () => ({
fn: {
jsonSchema202012: {
memoizedSampleFromSchema,
memoizedCreateXMLExample,
getJsonSampleSchema: makeGetJsonSampleSchema(getSystem),
getYamlSampleSchema: makeGetYamlSampleSchema(getSystem),
getXmlSampleSchema: makeGetXmlSampleSchema(getSystem),
},
},
})
const getSampleSchema = makeGetSampleSchema(getSystem)

View File

@@ -4,11 +4,11 @@
import {
memoizedSampleFromSchema,
memoizedCreateXMLExample,
} from "core/plugins/json-schema-2020-12/samples-extensions/fn"
import makeGetSampleSchema from "core/plugins/samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/samples/fn/get-xml-sample-schema"
} from "core/plugins/json-schema-5-samples/fn/index"
import makeGetSampleSchema from "core/plugins/json-schema-5-samples/fn/get-sample-schema"
import makeGetJsonSampleSchema from "core/plugins/json-schema-5-samples/fn/get-json-sample-schema"
import makeGetYamlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-yaml-sample-schema"
import makeGetXmlSampleSchema from "core/plugins/json-schema-5-samples/fn/get-xml-sample-schema"
describe("getSampleSchema", () => {
const oriDate = Date

View File

@@ -1,5 +1,5 @@
import { fromJS } from "immutable"
import { createXMLExample, sampleFromSchema, memoizedCreateXMLExample, memoizedSampleFromSchema } from "core/plugins/samples/fn/index"
import { createXMLExample, sampleFromSchema, memoizedCreateXMLExample, memoizedSampleFromSchema } from "core/plugins/json-schema-5-samples/fn/index"
describe("sampleFromSchema", () => {
it("handles Immutable.js objects for nested schemas", function () {