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 XML from "xml"
import RandExp from "randexp" import RandExp from "randexp"
import isEmpty from "lodash/isEmpty" import isEmpty from "lodash/isEmpty"
import { objectify, isFunc, normalizeArray, deeplyStripKey } from "core/utils" import { objectify, isFunc, normalizeArray, deeplyStripKey } from "core/utils"
import memoizeN from "../../../../helpers/memoizeN" import memoizeN from "../../../../helpers/memoizeN"
@@ -11,8 +12,8 @@ const generateStringFromRegex = (pattern) => {
try { try {
const randexp = new RandExp(pattern) const randexp = new RandExp(pattern)
return randexp.gen() return randexp.gen()
} catch (e) { } catch {
// Invalid regex should not cause a crash (regex syntax varies across languages) // invalid regex should not cause a crash (regex syntax varies across languages)
return "string" return "string"
} }
} }
@@ -36,17 +37,16 @@ const primitives = {
const primitive = (schema) => { const primitive = (schema) => {
schema = objectify(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] return typeof fn === "function" ? fn(schema) : `Unknown Type: ${schema.type}`
if (isFunc(fn)) return fn(schema)
return "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) => const sanitizeRef = (value) =>
deeplyStripKey( deeplyStripKey(
value, value,
@@ -720,8 +720,9 @@ export const createXMLExample = (schema, config, o) => {
return XML(json, { declaration: true, indent: "\t" }) return XML(json, { declaration: true, indent: "\t" })
} }
export const sampleFromSchema = (schema, config, o) => export const sampleFromSchema = (schema, config, o) => {
sampleFromSchemaGeneric(schema, config, o, false) return sampleFromSchemaGeneric(schema, config, o, false)
}
const resolver = (arg1, arg2, arg3) => [ const resolver = (arg1, arg2, arg3) => [
arg1, 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 */ /* eslint-enable react/jsx-filename-extension */
/** Utilize JSON Schema 2020-12 samples **/ /**
const wrapSampleFn = * Runs the fn replacement implementation when spec is OpenAPI 3.1.
(fnName) => * Runs the fn original implementation otherwise.
(getSystem) => *
(...args) => { * @param fn
const { fn, specSelectors } = getSystem() * @param system
* @returns {{[p: string]: function(...[*]): *}}
*/
export const wrapOAS31Fn = (fn, system) => {
const { fn: systemFn, specSelectors } = system
if (specSelectors.isOpenAPI31()) { return Object.fromEntries(
return fn.jsonSchema202012[fnName](...args) 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) return [name, impl]
} })
)
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"
)

View File

@@ -20,11 +20,6 @@ import {
isOAS31 as isOAS31Fn, isOAS31 as isOAS31Fn,
createOnlyOAS31Selector as createOnlyOAS31SelectorFn, createOnlyOAS31Selector as createOnlyOAS31SelectorFn,
createSystemSelector as createSystemSelectorFn, createSystemSelector as createSystemSelectorFn,
wrapSampleFromSchema,
wrapSampleFromSchemaGeneric,
wrapCreateXMLExample,
wrapMemoizedSampleFromSchema,
wrapMemoizedCreateXMLExample,
} from "./fn" } from "./fn"
import { import {
license as selectLicense, 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 JSONSchema202012KeywordDescriptionWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Description"
import JSONSchema202012KeywordDefaultWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Default" 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 JSONSchema202012KeywordPropertiesWrapper from "./json-schema-2020-12-extensions/wrap-components/keywords/Properties"
import { import afterLoad from "./after-load"
makeIsExpandable,
getProperties,
} from "./json-schema-2020-12-extensions/fn"
const OAS31Plugin = ({ getSystem }) => { const OAS31Plugin = ({ fn }) => {
const system = getSystem()
const { fn } = system
const createSystemSelector = fn.createSystemSelector || createSystemSelectorFn const createSystemSelector = fn.createSystemSelector || createSystemSelectorFn
const createOnlyOAS31Selector = fn.createOnlyOAS31Selector || createOnlyOAS31SelectorFn // prettier-ignore const createOnlyOAS31Selector = fn.createOnlyOAS31Selector || createOnlyOAS31SelectorFn // prettier-ignore
const pluginFn = {
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 { return {
fn: pluginFn, afterLoad,
fn: {
isOAS31: isOAS31Fn,
createSystemSelector: createSystemSelectorFn,
createOnlyOAS31Selector: createOnlyOAS31SelectorFn,
},
components: { components: {
Webhooks, Webhooks,
JsonSchemaDialect, JsonSchemaDialect,

View File

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

View File

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