feat(oas31): enable overrides for samples plugin (#8731)

These overrides are specific to OpenAPI 3.1.0
and JSON Schema 2020-12.

Refs #8577
This commit is contained in:
Vladimír Gorej
2023-05-31 14:27:36 +02:00
parent 2ce9d08af7
commit df9aadf971
6 changed files with 90 additions and 73 deletions

View File

@@ -4,6 +4,7 @@
import XML from "xml"
import RandExp from "randexp"
import isEmpty from "lodash/isEmpty"
import { objectify, isFunc, normalizeArray, deeplyStripKey } from "core/utils"
import memoizeN from "../../../../helpers/memoizeN"
@@ -11,8 +12,8 @@ const generateStringFromRegex = (pattern) => {
try {
const randexp = new RandExp(pattern)
return randexp.gen()
} catch (e) {
// Invalid regex should not cause a crash (regex syntax varies across languages)
} catch {
// invalid regex should not cause a crash (regex syntax varies across languages)
return "string"
}
}
@@ -36,17 +37,16 @@ const primitives = {
const primitive = (schema) => {
schema = objectify(schema)
let { type, format } = schema
const { type, format } = schema
const fn = primitives[`${type}_${format}`] || primitives[type]
let fn = primitives[`${type}_${format}`] || primitives[type]
if (isFunc(fn)) return fn(schema)
return "Unknown Type: " + schema.type
return typeof fn === "function" ? fn(schema) : `Unknown Type: ${schema.type}`
}
// do a couple of quick sanity tests to ensure the value
// looks like a $$ref that swagger-client generates.
/**
* Do a couple of quick sanity tests to ensure the value
* looks like a $$ref that swagger-client generates.
*/
const sanitizeRef = (value) =>
deeplyStripKey(
value,
@@ -720,8 +720,9 @@ export const createXMLExample = (schema, config, o) => {
return XML(json, { declaration: true, indent: "\t" })
}
export const sampleFromSchema = (schema, config, o) =>
sampleFromSchemaGeneric(schema, config, o, false)
export const sampleFromSchema = (schema, config, o) => {
return sampleFromSchemaGeneric(schema, config, o, false)
}
const resolver = (arg1, arg2, arg3) => [
arg1,

View File

@@ -0,0 +1,38 @@
/**
* @prettier
*/
import {
makeIsExpandable,
getProperties,
} from "./json-schema-2020-12-extensions/fn"
import { wrapOAS31Fn } from "./fn"
function afterLoad({ fn, getSystem }) {
// overrides for fn.jsonSchema202012
if (fn.jsonSchema202012) {
const isExpandable = makeIsExpandable(
fn.jsonSchema202012.isExpandable,
getSystem
)
Object.assign(this.fn.jsonSchema202012, { isExpandable, getProperties })
}
// wraps schema generators from samples plugin and make them specific to OpenAPI 3.1 version
if (typeof fn.sampleFromSchema === "function" && fn.jsonSchema202012) {
const wrappedFns = wrapOAS31Fn(
{
sampleFromSchema: fn.jsonSchema202012.sampleFromSchema,
sampleFromSchemaGeneric: fn.jsonSchema202012.sampleFromSchemaGeneric,
createXMLExample: fn.jsonSchema202012.createXMLExample,
memoizedSampleFromSchema: fn.jsonSchema202012.memoizedSampleFromSchema,
memoizedCreateXMLExample: fn.jsonSchema202012.memoizedCreateXMLExample,
},
getSystem()
)
Object.assign(this.fn, wrappedFns)
}
}
export default afterLoad

View File

@@ -97,28 +97,28 @@ export const createOnlyOAS31ComponentWrapper =
}
/* eslint-enable react/jsx-filename-extension */
/** Utilize JSON Schema 2020-12 samples **/
const wrapSampleFn =
(fnName) =>
(getSystem) =>
(...args) => {
const { fn, specSelectors } = getSystem()
/**
* Runs the fn replacement implementation when spec is OpenAPI 3.1.
* Runs the fn original implementation otherwise.
*
* @param fn
* @param system
* @returns {{[p: string]: function(...[*]): *}}
*/
export const wrapOAS31Fn = (fn, system) => {
const { fn: systemFn, specSelectors } = system
if (specSelectors.isOpenAPI31()) {
return fn.jsonSchema202012[fnName](...args)
}
return Object.fromEntries(
Object.entries(fn).map(([name, newImpl]) => {
const oriImpl = systemFn[name]
const impl = (...args) =>
specSelectors.isOAS31()
? newImpl(...args)
: typeof oriImpl === "function"
? oriImpl(...args)
: undefined
return fn[fnName](...args)
}
export const wrapSampleFromSchema = wrapSampleFn("sampleFromSchema")
export const wrapSampleFromSchemaGeneric = wrapSampleFn(
"sampleFromSchemaGeneric"
)
export const wrapCreateXMLExample = wrapSampleFn("createXMLExample")
export const wrapMemoizedSampleFromSchema = wrapSampleFn(
"memoizedSampleFromSchema"
)
export const wrapMemoizedCreateXMLExample = wrapSampleFn(
"memoizedCreateXMLExample"
)
return [name, impl]
})
)
}

View File

@@ -20,11 +20,6 @@ import {
isOAS31 as isOAS31Fn,
createOnlyOAS31Selector as createOnlyOAS31SelectorFn,
createSystemSelector as createSystemSelectorFn,
wrapSampleFromSchema,
wrapSampleFromSchemaGeneric,
wrapCreateXMLExample,
wrapMemoizedSampleFromSchema,
wrapMemoizedCreateXMLExample,
} from "./fn"
import {
license as selectLicense,
@@ -64,40 +59,19 @@ import JSONSchema202012KeywordExternalDocs from "./json-schema-2020-12-extension
import JSONSchema202012KeywordDescriptionWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Description"
import JSONSchema202012KeywordDefaultWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Default"
import JSONSchema202012KeywordPropertiesWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Properties"
import {
makeIsExpandable,
getProperties,
} from "./json-schema-2020-12-extensions/fn"
import afterLoad from "./after-load"
const OAS31Plugin = ({ getSystem }) => {
const system = getSystem()
const { fn } = system
const OAS31Plugin = ({ fn }) => {
const createSystemSelector = fn.createSystemSelector || createSystemSelectorFn
const createOnlyOAS31Selector = fn.createOnlyOAS31Selector || createOnlyOAS31SelectorFn // prettier-ignore
const pluginFn = {
isOAs31: isOAS31Fn,
return {
afterLoad,
fn: {
isOAS31: isOAS31Fn,
createSystemSelector: createSystemSelectorFn,
createOnlyOAS31Selector: createOnlyOAS31SelectorFn,
}
if (typeof fn.jsonSchema202012?.isExpandable === "function") {
pluginFn.jsonSchema202012 = {
...fn.jsonSchema202012,
isExpandable: makeIsExpandable(fn.jsonSchema202012.isExpandable, system),
getProperties,
}
}
// wraps schema generators and make them specific to OpenAPI version
if (typeof system.fn.inferSchema === "function") {
pluginFn.sampleFromSchema = wrapSampleFromSchema(getSystem)
pluginFn.sampleFromSchemaGeneric = wrapSampleFromSchemaGeneric(getSystem)
pluginFn.createXMLExample = wrapCreateXMLExample(getSystem)
pluginFn.memoizedSampleFromSchema = wrapMemoizedSampleFromSchema(getSystem)
pluginFn.memoizedCreateXMLExample = wrapMemoizedCreateXMLExample(getSystem)
}
return {
fn: pluginFn,
},
components: {
Webhooks,
JsonSchemaDialect,

View File

@@ -1,7 +1,9 @@
/**
* @prettier
*/
export const makeIsExpandable = (original, { fn }) => {
export const makeIsExpandable = (original, getSystem) => {
const { fn } = getSystem()
if (typeof original !== "function") {
return null
}

View File

@@ -10,8 +10,7 @@ import {
} from "../json-schema-2020-12-extensions/fn"
const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
const system = getSystem()
const { getComponent, fn, getConfigs } = system
const { getComponent, fn, getConfigs } = getSystem()
const configs = getConfigs()
if (ModelsWrapper.ModelsWithJSONSchemaContext) {
@@ -135,7 +134,10 @@ const ModelsWrapper = createOnlyOAS31ComponentWrapper(({ getSystem }) => {
},
fn: {
upperFirst: fn.upperFirst,
isExpandable: makeIsExpandable(fn.jsonSchema202012.isExpandable, system),
isExpandable: makeIsExpandable(
fn.jsonSchema202012.isExpandable,
getSystem
),
getProperties,
},
})