130 lines
3.1 KiB
TypeScript
130 lines
3.1 KiB
TypeScript
"use client"
|
|
|
|
import { OpenAPI } from "types"
|
|
import { ReactNode, createContext, useContext, useEffect, useMemo } from "react"
|
|
import getTagChildSidebarItems from "../utils/get-tag-child-sidebar-items"
|
|
import { useRouter } from "next/navigation"
|
|
import { UpdateActionType, useSidebar } from "docs-ui"
|
|
import { getSectionId } from "docs-utils"
|
|
|
|
type BaseSpecsContextType = {
|
|
baseSpecs: OpenAPI.ExpandedDocument | undefined
|
|
getSecuritySchema: (
|
|
securityName: string
|
|
) => OpenAPI.SecuritySchemeObject | null
|
|
}
|
|
|
|
const BaseSpecsContext = createContext<BaseSpecsContextType | null>(null)
|
|
|
|
type BaseSpecsProviderProps = {
|
|
baseSpecs: OpenAPI.ExpandedDocument | undefined
|
|
children?: ReactNode
|
|
}
|
|
|
|
const BaseSpecsProvider = ({ children, baseSpecs }: BaseSpecsProviderProps) => {
|
|
const router = useRouter()
|
|
const { activePath, setActivePath, resetItems, shownSidebar, updateItems } =
|
|
useSidebar()
|
|
|
|
const getSecuritySchema = (
|
|
securityName: string
|
|
): OpenAPI.SecuritySchemeObject | null => {
|
|
if (
|
|
baseSpecs?.components?.securitySchemes &&
|
|
Object.prototype.hasOwnProperty.call(
|
|
baseSpecs?.components?.securitySchemes,
|
|
securityName
|
|
)
|
|
) {
|
|
const schema = baseSpecs?.components?.securitySchemes[securityName]
|
|
if (!("$ref" in schema)) {
|
|
return schema
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
const itemsToUpdate = useMemo(() => {
|
|
if (!baseSpecs) {
|
|
return []
|
|
}
|
|
|
|
const itemsToUpdate: UpdateActionType["items"] = []
|
|
|
|
baseSpecs.tags?.forEach((tag) => {
|
|
const tagPathName = getSectionId([tag.name.toLowerCase()])
|
|
const childItems =
|
|
baseSpecs.expandedTags &&
|
|
Object.hasOwn(baseSpecs.expandedTags, tagPathName)
|
|
? getTagChildSidebarItems(baseSpecs.expandedTags[tagPathName])
|
|
: []
|
|
itemsToUpdate.push({
|
|
existingItem: {
|
|
type: "category",
|
|
title: tag.name,
|
|
},
|
|
newItem: {
|
|
children: childItems,
|
|
loaded: childItems.length > 0,
|
|
onOpen: () => {
|
|
if (location.hash !== tagPathName) {
|
|
router.push(`#${tagPathName}`, {
|
|
scroll: false,
|
|
})
|
|
}
|
|
if (activePath !== tagPathName) {
|
|
setActivePath(tagPathName)
|
|
}
|
|
},
|
|
},
|
|
options: {
|
|
setChildrenBehavior: "merge",
|
|
},
|
|
})
|
|
})
|
|
|
|
return itemsToUpdate
|
|
}, [baseSpecs])
|
|
|
|
useEffect(() => {
|
|
if (!itemsToUpdate.length || !shownSidebar) {
|
|
return
|
|
}
|
|
|
|
updateItems({
|
|
sidebar_id: shownSidebar.sidebar_id,
|
|
items: itemsToUpdate,
|
|
})
|
|
}, [itemsToUpdate, shownSidebar?.sidebar_id])
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
resetItems()
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<BaseSpecsContext.Provider
|
|
value={{
|
|
baseSpecs,
|
|
getSecuritySchema,
|
|
}}
|
|
>
|
|
{children}
|
|
</BaseSpecsContext.Provider>
|
|
)
|
|
}
|
|
|
|
export default BaseSpecsProvider
|
|
|
|
export const useBaseSpecs = (): BaseSpecsContextType => {
|
|
const context = useContext(BaseSpecsContext)
|
|
|
|
if (!context) {
|
|
throw new Error("useBaseSpecs must be used inside a BaseSpecsProvider")
|
|
}
|
|
|
|
return context
|
|
}
|