docs-util: fixes to base OAS + circular-patch redocly plugin (#7382)

* docs-util: remove MultipleErrors schema from base OAS

* fixes to circular patch plugin

* general fixes

* change nested schemas to references
This commit is contained in:
Shahed Nasser authored and GitHub committed 2024-05-27 14:29:48 +02:00
1 parent b5b41c7a33
commit 98615c388b
15 files changed
+237 -217

No files matched your search

@@ -55,18 +55,21 @@ function CircularPatch({ schemas = {}, verbose = false }) {
return return
} }
for (const patch of patches) { for (const patch of patches) {
if (resolved.location.pointer !== patch.schemaPointer) { if (resolved.location.pointer.replaceAll("\n", "") !== patch.schemaPointer) {
continue continue
} }
const ctxSchemaPointer = const pointerMatch = ctx.location.pointer.match(refPathPrefixRegex) ||
ctx.location.pointer.match(refPathPrefixRegex)[0] resolved.location.pointer.match(refPathPrefixRegex)
if (!patch.schemaToPatchPointers.includes(ctxSchemaPointer)) { if (!pointerMatch.length) {
continue
}
if (!patch.schemaToPatchPointers.includes(pointerMatch[0])) {
continue continue
} }
applyPatch(ref) applyPatch(ref)
if (verbose) { if (verbose) {
logs.push( logs.push(
`${ctxSchemaPointer.substring(refPathPrefixLength)} patch $ref to ${ `${pointerMatch[0].substring(refPathPrefixLength)} patch $ref to ${
patch.schemaName patch.schemaName
}` }`
) )
@@ -6,138 +6,13 @@ plugins:
decorators: decorators:
medusa/circular-patch: medusa/circular-patch:
schemas: schemas:
Address:
- Customer
Cart:
- Customer
- Order
- Payment
- PaymentSession
ClaimImage:
- ClaimItem
ClaimItem:
- ClaimOrder
ClaimOrder:
- Fulfillment
- Order
- Return
Country:
- Region
Customer:
- Order
CustomerGroup:
- Customer
- PriceList
Discount:
- Discount
DiscountRule:
- DiscountCondition
DraftOrder:
- Cart
- Order
Fulfillment:
- ClaimOrder
- Order
- Swap
FulfillmentItem:
- Fulfillment
GiftCard:
- Order
GiftCardTransaction: GiftCardTransaction:
- GiftCard - GiftCard
- Order - Order
LineItem:
- Cart
- ClaimOrder
- Order
- OrderEdit
- Swap
LineItemAdjustment: LineItemAdjustment:
- LineItem - LineItem
LineItemTaxLine: LineItemTaxLine:
- LineItem - LineItem
MoneyAmount:
- PriceList
- ProductVariant
- Region
Notification:
- Notification
Order:
- Cart
- ClaimOrder
- Customer
- DraftOrder
- Fulfillment
- OrderEdit
- Payment
- Refund
- Return
- Swap
OrderEdit:
- Order
OrderItemChange:
- OrderEdit
Payment:
- Cart
- Order
- Swap
ProductCategory:
- ProductCategory
- Product
ProductCollection:
- Product
ProductOption:
- Product
ProductOptionValue:
- ProductOption
- ProductVariant
ProductVariant:
- Product
ProductVariantInventoryItem:
- ProductVariant
Refund:
- Order
- Payment
Return:
- ClaimOrder
- Order
- Swap
ReturnItem:
- Return
ReturnReason:
- ReturnReason
SalesChannelLocation:
- SalesChannel
ShippingMethod:
- Cart
- ClaimOrder
- Order
- Payment
- Return
- Swap
ShippingMethodTaxLine:
- ShippingMethod
ShippingOption:
- Region
ShippingOptionRequirement:
- ShippingOption
ShippingProfile:
- Product
- ShippingOption
Swap:
- Cart
- Fulfillment
- Order
- Payment
- Return
TaxRate:
- Region
TrackingLink:
- Fulfillment
SalesChannel:
- Order
- Cart
- PublishableApiKey
CustomerGroupResponse: CustomerGroupResponse:
- CustomerResponse - CustomerResponse
ProductCategoryResponse: ProductCategoryResponse:
+13 -4
View File
@@ -3,6 +3,7 @@ import { SchemaObject } from "../../../types/openapi"
import path from "path" import path from "path"
import { existsSync, promises as fs } from "fs" import { existsSync, promises as fs } from "fs"
import { parseDocument } from "yaml" import { parseDocument } from "yaml"
import dereference from "../../../utils/dereference"
export async function GET(request: Request) { export async function GET(request: Request) {
const { searchParams } = new URL(request.url) const { searchParams } = new URL(request.url)
@@ -37,14 +38,14 @@ export async function GET(request: Request) {
.replace("#/components/schemas/", "") .replace("#/components/schemas/", "")
.replaceAll("./components/schemas/", "") .replaceAll("./components/schemas/", "")
const schemaPath = path.join( const baseSchemasPath = path.join(
process.cwd(), process.cwd(),
"specs", "specs",
area, area,
"components", "components",
"schemas", "schemas"
name
) )
const schemaPath = path.join(baseSchemasPath, name)
if (!existsSync(schemaPath)) { if (!existsSync(schemaPath)) {
return NextResponse.json( return NextResponse.json(
@@ -61,9 +62,17 @@ export async function GET(request: Request) {
const schemaContent = await fs.readFile(schemaPath, "utf-8") const schemaContent = await fs.readFile(schemaPath, "utf-8")
const schema = parseDocument(schemaContent).toJS() as SchemaObject const schema = parseDocument(schemaContent).toJS() as SchemaObject
// resolve references in schema
const dereferencedDocument = await dereference({
basePath: baseSchemasPath,
schemas: [schema],
})
return NextResponse.json( return NextResponse.json(
{ {
schema, schema: dereferencedDocument.components?.schemas
? Object.values(dereferencedDocument.components?.schemas)[0]
: schema,
}, },
{ {
status: 200, status: 200,
@@ -114,7 +114,7 @@ const TagOperationParametersObject = ({
) )
} }
if (!schema.properties) { if (!schema.properties || !Object.values(schema.properties).length) {
return getPropertyDescriptionElm() return getPropertyDescriptionElm()
} }
@@ -15,6 +15,7 @@ import SectionContainer from "../../../Section/Container"
import useSchemaExample from "../../../../hooks/use-schema-example" import useSchemaExample from "../../../../hooks/use-schema-example"
import { InView } from "react-intersection-observer" import { InView } from "react-intersection-observer"
import checkElementInViewport from "../../../../utils/check-element-in-viewport" import checkElementInViewport from "../../../../utils/check-element-in-viewport"
import { singular } from "pluralize"
export type TagSectionSchemaProps = { export type TagSectionSchemaProps = {
schema: SchemaObject schema: SchemaObject
@@ -24,15 +25,10 @@ export type TagSectionSchemaProps = {
const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => { const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
const { addItems, setActivePath, activePath } = useSidebar() const { addItems, setActivePath, activePath } = useSidebar()
const tagSlugName = useMemo(() => getSectionId([tagName]), [tagName]) const tagSlugName = useMemo(() => getSectionId([tagName]), [tagName])
const formattedName = useMemo(() => { const formattedName = useMemo(
if (!schema["x-schemaName"]) { () => singular(tagName).replaceAll(" ", ""),
return tagName.replaceAll(" ", "") [tagName]
} )
return schema["x-schemaName"]
.replaceAll(/^(Admin|Store)/g, "")
.replaceAll(/^Create/g, "")
}, [schema, tagName])
const schemaSlug = useMemo( const schemaSlug = useMemo(
() => getSectionId([tagName, formattedName, "schema"]), () => getSectionId([tagName, formattedName, "schema"]),
[tagName, formattedName] [tagName, formattedName]
+2
View File
@@ -36,6 +36,7 @@
"next-mdx-remote": "^4.4.1", "next-mdx-remote": "^4.4.1",
"openapi-sampler": "^1.3.1", "openapi-sampler": "^1.3.1",
"openapi-types": "^12.1.3", "openapi-types": "^12.1.3",
"pluralize": "^8.0.0",
"postcss": "8.4.27", "postcss": "8.4.27",
"prism-react-renderer": "2.3.1", "prism-react-renderer": "2.3.1",
"react": "^18.2.0", "react": "^18.2.0",
@@ -54,6 +55,7 @@
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "^14.2.3", "@next/bundle-analyzer": "^14.2.3",
"@types/jsdom": "^21.1.1", "@types/jsdom": "^21.1.1",
"@types/pluralize": "^0.0.33",
"types": "*" "types": "*"
}, },
"engines": { "engines": {
+4
View File
@@ -118,3 +118,7 @@ export type ExpandedDocument = Document & {
export type TagObject = OpenAPIV3.TagObject & { export type TagObject = OpenAPIV3.TagObject & {
"x-associatedSchema"?: OpenAPIV3.ReferenceObject "x-associatedSchema"?: OpenAPIV3.ReferenceObject
} }
export type ParsedPathItemObject = OpenAPIV3.PathItemObject<Operation> & {
operationPath?: string
}
@@ -0,0 +1,59 @@
import { Document, ParsedPathItemObject, SchemaObject } from "@/types/openapi"
import OpenAPIParser from "@readme/openapi-parser"
type Options = {
basePath: string
paths?: ParsedPathItemObject[]
schemas?: SchemaObject[]
}
export default async function dereference({
basePath,
paths,
schemas,
}: Options): Promise<Document> {
// dereference the references in the paths
let document: Document = {
paths: {},
// These attributes are only for validation purposes
openapi: "3.0.0",
info: {
title: "Medusa API",
version: "1.0.0",
},
components: {
schemas: {},
},
}
if (paths) {
paths.forEach((path) => {
const documentPath = path.operationPath || ""
delete path.operationPath
document.paths[documentPath] = path
})
}
if (schemas) {
schemas.forEach((schema) => {
if (!schema["x-schemaName"]) {
return
}
document.components!.schemas![schema["x-schemaName"]] = schema
})
}
// resolve references in paths
document = (await OpenAPIParser.dereference(`${basePath}/`, document, {
parse: {
text: {
// This ensures that all files are parsed as expected
// resolving the error with incorrect new lines for
// example files having `undefined` extension.
canParse: /.*/,
},
},
})) as unknown as Document
return document
}
@@ -1,14 +1,10 @@
import path from "path" import path from "path"
import { promises as fs } from "fs" import { promises as fs } from "fs"
import type { OpenAPIV3 } from "openapi-types" import type { OpenAPIV3 } from "openapi-types"
import type { Operation, Document } from "@/types/openapi" import type { Operation, Document, ParsedPathItemObject } from "@/types/openapi"
import readSpecDocument from "./read-spec-document" import readSpecDocument from "./read-spec-document"
import getSectionId from "./get-section-id" import getSectionId from "./get-section-id"
import OpenAPIParser from "@readme/openapi-parser" import dereference from "./dereference"
type ParsedPathItemObject = OpenAPIV3.PathItemObject<Operation> & {
operationPath?: string
}
export default async function getPathsOfTag( export default async function getPathsOfTag(
tagName: string, tagName: string,
@@ -46,34 +42,8 @@ export default async function getPathsOfTag(
}) })
) )
// dereference the references in the paths return dereference({
let paths: Document = { basePath,
paths: {}, paths: documents,
// These attributes are only for validation purposes
openapi: "3.0.0",
info: {
title: "Medusa API",
version: "1.0.0",
},
}
documents.forEach((document) => {
const documentPath = document.operationPath || ""
delete document.operationPath
paths.paths[documentPath] = document
}) })
// resolve references in paths
paths = (await OpenAPIParser.dereference(`${basePath}/`, paths, {
parse: {
text: {
// This ensures that all files are parsed as expected
// resolving the error with incorrect new lines for
// example files having `undefined` extension.
canParse: /.*/,
},
},
})) as unknown as Document
return paths
} }
@@ -123,20 +123,16 @@ components:
message: Entity with id 1 was not found message: Entity with id 1 was not found
type: not_found type: not_found
400_error: 400_error:
description: Client Error or Multiple Errors description: Client Error
content: content:
application/json: application/json:
schema: schema:
oneOf: $ref: "#/components/schemas/Error"
- $ref: "#/components/schemas/Error"
- $ref: "#/components/schemas/MultipleErrors"
examples: examples:
not_allowed: not_allowed:
$ref: "#/components/examples/not_allowed_error" $ref: "#/components/examples/not_allowed_error"
invalid_data: invalid_data:
$ref: "#/components/examples/invalid_data_error" $ref: "#/components/examples/invalid_data_error"
MultipleErrors:
$ref: "#/components/examples/multiple_errors"
500_error: 500_error:
description: Server Error description: Server Error
content: content:
@@ -81,20 +81,16 @@ components:
message: Entity with id 1 was not found message: Entity with id 1 was not found
type: not_found type: not_found
400_error: 400_error:
description: Client Error or Multiple Errors description: Client Error
content: content:
application/json: application/json:
schema: schema:
oneOf: $ref: "#/components/schemas/Error"
- $ref: "#/components/schemas/Error"
- $ref: "#/components/schemas/MultipleErrors"
examples: examples:
not_allowed: not_allowed:
$ref: "#/components/examples/not_allowed_error" $ref: "#/components/examples/not_allowed_error"
invalid_data: invalid_data:
$ref: "#/components/examples/invalid_data_error" $ref: "#/components/examples/invalid_data_error"
MultipleErrors:
$ref: "#/components/examples/multiple_errors"
500_error: 500_error:
description: Server Error description: Server Error
content: content:
@@ -54,7 +54,7 @@ class OasSchemaHelper {
* @returns The schema as a reference. If the schema doesn't have the x-schemaName property set, * @returns The schema as a reference. If the schema doesn't have the x-schemaName property set,
* the schema isn't converted and `undefined` is returned. * the schema isn't converted and `undefined` is returned.
*/ */
schemaToReference( namedSchemaToReference(
schema: OpenApiSchema, schema: OpenApiSchema,
level = 0 level = 0
): OpenAPIV3.ReferenceObject | undefined { ): OpenAPIV3.ReferenceObject | undefined {
@@ -84,7 +84,7 @@ class OasSchemaHelper {
!("$ref" in propertySchema.items) !("$ref" in propertySchema.items)
) { ) {
propertySchema.items = propertySchema.items =
this.schemaToReference(propertySchema.items, level + 1) || this.namedSchemaToReference(propertySchema.items, level + 1) ||
propertySchema.items propertySchema.items
} else if ( } else if (
propertySchema.oneOf || propertySchema.oneOf ||
@@ -101,13 +101,15 @@ class OasSchemaHelper {
} }
schemaTarget![index] = schemaTarget![index] =
this.schemaToReference(item, level + 1) || item this.namedSchemaToReference(item, level + 1) || item
}) })
} }
schema.properties![property] = schema.properties![property] =
this.schemaToReference(propertySchema as OpenApiSchema, level + 1) || this.namedSchemaToReference(
propertySchema propertySchema as OpenApiSchema,
level + 1
) || propertySchema
}) })
} }
@@ -118,6 +120,67 @@ class OasSchemaHelper {
} }
} }
schemaChildrenToRefs(schema: OpenApiSchema, level = 0): OpenApiSchema {
if (level > this.MAX_LEVEL) {
return schema
}
const clonedSchema = Object.assign({}, schema)
if (clonedSchema.allOf) {
clonedSchema.allOf = clonedSchema.allOf.map((item) => {
if (this.isRefObject(item)) {
return item
}
const transformChildItems = this.schemaChildrenToRefs(item, level + 1)
return (
this.namedSchemaToReference(transformChildItems) ||
transformChildItems
)
})
} else if (clonedSchema.oneOf) {
clonedSchema.oneOf = clonedSchema.oneOf.map((item) => {
if (this.isRefObject(item)) {
return item
}
const transformChildItems = this.schemaChildrenToRefs(item, level + 1)
return (
this.namedSchemaToReference(transformChildItems) ||
transformChildItems
)
})
} else if (
clonedSchema.type === "array" &&
!this.isRefObject(clonedSchema.items)
) {
const transformedChildItems = this.schemaChildrenToRefs(
clonedSchema.items,
level
)
clonedSchema.items =
this.namedSchemaToReference(transformedChildItems) ||
transformedChildItems
} else if (clonedSchema.properties && !clonedSchema["x-schemaName"]) {
Object.entries(clonedSchema.properties).forEach(([key, property]) => {
if (this.isRefObject(property)) {
return
}
const transformedProperty = this.schemaChildrenToRefs(
property,
level + 1
)
schema.properties![key] =
this.namedSchemaToReference(transformedProperty) ||
transformedProperty
})
}
return clonedSchema
}
/** /**
* Retrieve the expected file name of the schema. * Retrieve the expected file name of the schema.
* *
@@ -264,7 +327,11 @@ class OasSchemaHelper {
*/ */
tagNameToSchemaName(tagName: string, area: OasArea): string[] { tagNameToSchemaName(tagName: string, area: OasArea): string[] {
const mainSchemaName = wordsToPascal(pluralize.singular(tagName)) const mainSchemaName = wordsToPascal(pluralize.singular(tagName))
return [mainSchemaName, `${capitalize(area)}Create${mainSchemaName}`] return [
mainSchemaName,
`${mainSchemaName}Response`,
`${capitalize(area)}Create${mainSchemaName}`,
]
} }
} }
@@ -15,6 +15,18 @@ class SchemaFactory {
BigNumber: { BigNumber: {
type: "string", type: "string",
}, },
created_at: {
type: "string",
format: "date-time",
},
updated_at: {
type: "string",
format: "date-time",
},
deleted_at: {
type: "string",
format: "date-time",
},
} }
/** /**
@@ -260,8 +260,8 @@ class OasKindGenerator extends FunctionKindGenerator {
content: { content: {
"application/json": { "application/json": {
schema: schema:
this.oasSchemaHelper.schemaToReference(requestSchema) || this.oasSchemaHelper.namedSchemaToReference(requestSchema) ||
requestSchema, this.oasSchemaHelper.schemaChildrenToRefs(requestSchema),
}, },
}, },
} }
@@ -335,8 +335,8 @@ class OasKindGenerator extends FunctionKindGenerator {
;(oas.responses[responseStatus] as OpenAPIV3.ResponseObject).content = { ;(oas.responses[responseStatus] as OpenAPIV3.ResponseObject).content = {
"application/json": { "application/json": {
schema: schema:
this.oasSchemaHelper.schemaToReference(responseSchema) || this.oasSchemaHelper.namedSchemaToReference(responseSchema) ||
responseSchema, this.oasSchemaHelper.schemaChildrenToRefs(responseSchema),
}, },
} }
} }
@@ -462,7 +462,7 @@ class OasKindGenerator extends FunctionKindGenerator {
newSchema: requestSchema, newSchema: requestSchema,
}) })
if (!updatedRequestSchema && existingRequestBodySchema) { if (!updatedRequestSchema) {
// if there's no request schema, remove it from the OAS // if there's no request schema, remove it from the OAS
delete oas.requestBody delete oas.requestBody
} else { } else {
@@ -470,10 +470,11 @@ class OasKindGenerator extends FunctionKindGenerator {
oas.requestBody = { oas.requestBody = {
content: { content: {
"application/json": { "application/json": {
schema: updatedRequestSchema schema:
? this.oasSchemaHelper.schemaToReference(updatedRequestSchema) || this.oasSchemaHelper.namedSchemaToReference(
updatedRequestSchema updatedRequestSchema
: updatedRequestSchema, ) ||
this.oasSchemaHelper.schemaChildrenToRefs(updatedRequestSchema),
}, },
}, },
} }
@@ -495,8 +496,10 @@ class OasKindGenerator extends FunctionKindGenerator {
content: { content: {
"application/json": { "application/json": {
schema: schema:
this.oasSchemaHelper.schemaToReference(newResponseSchema) || this.oasSchemaHelper.namedSchemaToReference(
newResponseSchema, newResponseSchema
) ||
this.oasSchemaHelper.schemaChildrenToRefs(newResponseSchema),
}, },
}, },
}, },
@@ -532,8 +535,10 @@ class OasKindGenerator extends FunctionKindGenerator {
content: { content: {
"application/json": { "application/json": {
schema: updatedResponseSchema schema: updatedResponseSchema
? this.oasSchemaHelper.schemaToReference(updatedResponseSchema) || ? this.oasSchemaHelper.namedSchemaToReference(
updatedResponseSchema updatedResponseSchema
) ||
this.oasSchemaHelper.schemaChildrenToRefs(updatedResponseSchema)
: updatedResponseSchema, : updatedResponseSchema,
}, },
}, },
@@ -1122,6 +1127,13 @@ class OasKindGenerator extends FunctionKindGenerator {
return return
} }
// check if parameter is already added
const isAdded = parameters.some((param) => param.name === key)
if (isAdded) {
return
}
parameters.push( parameters.push(
this.getParameterObject({ this.getParameterObject({
name: key, name: key,
@@ -1134,7 +1146,7 @@ class OasKindGenerator extends FunctionKindGenerator {
} }
) )
} }
} else { } else if (methodName !== "delete") {
requestSchema = parameterSchema requestSchema = parameterSchema
} }
} }
@@ -1273,8 +1285,8 @@ class OasKindGenerator extends FunctionKindGenerator {
descriptionOptions as SchemaDescriptionOptions descriptionOptions as SchemaDescriptionOptions
) )
: title : title
? this.getSchemaDescription({ typeStr: title, nodeType: itemType }) ? this.getSchemaDescription({ typeStr: title, nodeType: itemType })
: this.defaultSummary : this.defaultSummary
const typeAsString = const typeAsString =
zodObjectTypeName || this.checker.typeToString(itemType) zodObjectTypeName || this.checker.typeToString(itemType)
@@ -1315,8 +1327,8 @@ class OasKindGenerator extends FunctionKindGenerator {
itemType.flags === ts.TypeFlags.StringLiteral itemType.flags === ts.TypeFlags.StringLiteral
? "string" ? "string"
: itemType.flags === ts.TypeFlags.NumberLiteral : itemType.flags === ts.TypeFlags.NumberLiteral
? "number" ? "number"
: "boolean", : "boolean",
title: title || typeAsString, title: title || typeAsString,
description, description,
format: this.getSchemaTypeFormat({ format: this.getSchemaTypeFormat({
@@ -1518,13 +1530,16 @@ class OasKindGenerator extends FunctionKindGenerator {
: undefined, : undefined,
required: required:
requiredProperties.length > 0 ? requiredProperties : undefined, requiredProperties.length > 0 ? requiredProperties : undefined,
properties, }
if (Object.values(properties).length) {
objSchema.properties = properties
} }
if (objSchema["x-schemaName"]) { if (objSchema["x-schemaName"]) {
// add object to schemas to be created // add object to schemas to be created
// if necessary // if necessary
this.oasSchemaHelper.schemaToReference(objSchema) this.oasSchemaHelper.namedSchemaToReference(objSchema)
} }
return objSchema return objSchema
@@ -1826,7 +1841,7 @@ class OasKindGenerator extends FunctionKindGenerator {
if (oldSchemaObj!.type === "object") { if (oldSchemaObj!.type === "object") {
if (!oldSchemaObj?.properties && newSchemaObj?.properties) { if (!oldSchemaObj?.properties && newSchemaObj?.properties) {
oldSchemaObj!.properties = newSchemaObj.properties oldSchemaObj!.properties = newSchemaObj.properties
} else if (oldSchemaObj?.properties && !newSchemaObj?.properties) { } else if (!newSchemaObj?.properties) {
delete oldSchemaObj!.properties delete oldSchemaObj!.properties
} else { } else {
// update existing properties // update existing properties
+16
View File
@@ -5040,6 +5040,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/pluralize@npm:^0.0.33":
version: 0.0.33
resolution: "@types/pluralize@npm:0.0.33"
checksum: 24899caf85b79dd291a6b6e9b9f3b67b452b18d578d0ac0d531a705bf5ee0361d9386ea1f8532c64de9e22c6e9606c5497787bb5e31bd299c487980436c59785
languageName: node
linkType: hard
"@types/prismjs@npm:^1.26.0": "@types/prismjs@npm:^1.26.0":
version: 1.26.3 version: 1.26.3
resolution: "@types/prismjs@npm:1.26.3" resolution: "@types/prismjs@npm:1.26.3"
@@ -5657,6 +5664,7 @@ __metadata:
"@types/mapbox__rehype-prism": ^0.8.0 "@types/mapbox__rehype-prism": ^0.8.0
"@types/mdx": ^2.0.5 "@types/mdx": ^2.0.5
"@types/node": 20.4.5 "@types/node": 20.4.5
"@types/pluralize": ^0.0.33
"@types/react": ^18.2.0 "@types/react": ^18.2.0
"@types/react-dom": ^18.2.0 "@types/react-dom": ^18.2.0
"@types/react-transition-group": ^4.4.6 "@types/react-transition-group": ^4.4.6
@@ -5671,6 +5679,7 @@ __metadata:
next-mdx-remote: ^4.4.1 next-mdx-remote: ^4.4.1
openapi-sampler: ^1.3.1 openapi-sampler: ^1.3.1
openapi-types: ^12.1.3 openapi-types: ^12.1.3
pluralize: ^8.0.0
postcss: 8.4.27 postcss: 8.4.27
prism-react-renderer: 2.3.1 prism-react-renderer: 2.3.1
react: ^18.2.0 react: ^18.2.0
@@ -12494,6 +12503,13 @@ eslint-config-next@latest:
languageName: node languageName: node
linkType: hard linkType: hard
"pluralize@npm:^8.0.0":
version: 8.0.0
resolution: "pluralize@npm:8.0.0"
checksum: 2044cfc34b2e8c88b73379ea4a36fc577db04f651c2909041b054c981cd863dd5373ebd030123ab058d194ae615d3a97cfdac653991e499d10caf592e8b3dc33
languageName: node
linkType: hard
"possible-typed-array-names@npm:^1.0.0": "possible-typed-array-names@npm:^1.0.0":
version: 1.0.0 version: 1.0.0
resolution: "possible-typed-array-names@npm:1.0.0" resolution: "possible-typed-array-names@npm:1.0.0"