docs: general fixes and improvements (#7918)
* docs improvements and changes * updated module definition * modules + dml changes * fix build * fix vale error * fix lint errors * fixes to stripe docs * fix condition * fix condition * fix module defintion * fix checkout * disable UI action * change oas preview action * flatten provider module options * fix lint errors * add module link docs * pr comments fixes * fix vale error * change node engine version * links -> linkable * add note about database name * small fixes * link fixes * fix response code in api reference * added migrations step
This commit is contained in:
@@ -17,130 +17,128 @@ type ApiRunnerProps = {
|
||||
bodyData?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export const ApiRunner = ({
|
||||
apiMethod,
|
||||
apiUrl,
|
||||
pathData,
|
||||
bodyData,
|
||||
queryData,
|
||||
}: ApiRunnerProps) => {
|
||||
// assemble api testing options
|
||||
const [apiTestingOptions, setApiTestingOptions] = useState<ApiTestingOptions>(
|
||||
{
|
||||
method: apiMethod,
|
||||
url: apiUrl,
|
||||
pathData,
|
||||
bodyData,
|
||||
queryData,
|
||||
}
|
||||
)
|
||||
const [isRunning, setIsRunning] = useState(false)
|
||||
const [ran, setRan] = useState(false)
|
||||
const hasData = (data?: Record<string, unknown>): boolean =>
|
||||
data !== undefined && Object.keys(data).length > 0
|
||||
// TODO change to be based on whether auth/data needed
|
||||
const manualTestTrigger = useMemo(
|
||||
() =>
|
||||
hasData(apiTestingOptions.pathData) ||
|
||||
hasData(apiTestingOptions.queryData) ||
|
||||
hasData(apiTestingOptions.bodyData),
|
||||
[apiTestingOptions]
|
||||
)
|
||||
const [responseLogs, setResponseLogs] = useState<string[]>([])
|
||||
const [responseCode, setResponseCode] = useState<string | undefined>()
|
||||
const pushMessage = (...message: string[]) =>
|
||||
setResponseLogs((prev) => [...prev, ...message])
|
||||
const { runRequest } = useRequestRunner({
|
||||
pushLog: pushMessage,
|
||||
onFinish: (_message, statusCode) => {
|
||||
setIsRunning(false)
|
||||
setResponseCode(statusCode)
|
||||
},
|
||||
replaceLog: (message) => setResponseLogs([message]),
|
||||
})
|
||||
export const ApiRunner = React.forwardRef<HTMLDivElement, ApiRunnerProps>(
|
||||
function ApiRunner(
|
||||
{ apiMethod, apiUrl, pathData, bodyData, queryData }: ApiRunnerProps,
|
||||
ref
|
||||
) {
|
||||
// assemble api testing options
|
||||
const [apiTestingOptions, setApiTestingOptions] =
|
||||
useState<ApiTestingOptions>({
|
||||
method: apiMethod,
|
||||
url: apiUrl,
|
||||
pathData,
|
||||
bodyData,
|
||||
queryData,
|
||||
})
|
||||
const [isRunning, setIsRunning] = useState(false)
|
||||
const [ran, setRan] = useState(false)
|
||||
const hasData = (data?: Record<string, unknown>): boolean =>
|
||||
data !== undefined && Object.keys(data).length > 0
|
||||
// TODO change to be based on whether auth/data needed
|
||||
const manualTestTrigger = useMemo(
|
||||
() =>
|
||||
hasData(apiTestingOptions.pathData) ||
|
||||
hasData(apiTestingOptions.queryData) ||
|
||||
hasData(apiTestingOptions.bodyData),
|
||||
[apiTestingOptions]
|
||||
)
|
||||
const [responseLogs, setResponseLogs] = useState<string[]>([])
|
||||
const [responseCode, setResponseCode] = useState<string | undefined>()
|
||||
const pushMessage = (...message: string[]) =>
|
||||
setResponseLogs((prev) => [...prev, ...message])
|
||||
const { runRequest } = useRequestRunner({
|
||||
pushLog: pushMessage,
|
||||
onFinish: (_message, statusCode) => {
|
||||
setIsRunning(false)
|
||||
setResponseCode(statusCode)
|
||||
},
|
||||
replaceLog: (message) => setResponseLogs([message]),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!isRunning && !manualTestTrigger && !ran) {
|
||||
setIsRunning(true)
|
||||
}
|
||||
}, [apiTestingOptions, manualTestTrigger, isRunning, ran])
|
||||
useEffect(() => {
|
||||
if (!isRunning && !manualTestTrigger && !ran) {
|
||||
setIsRunning(true)
|
||||
}
|
||||
}, [apiTestingOptions, manualTestTrigger, isRunning, ran])
|
||||
|
||||
useEffect(() => {
|
||||
if (isRunning && !ran) {
|
||||
setRan(true)
|
||||
setResponseLogs(["Sending request..."])
|
||||
runRequest(apiTestingOptions)
|
||||
}
|
||||
}, [isRunning, ran])
|
||||
useEffect(() => {
|
||||
if (isRunning && !ran) {
|
||||
setRan(true)
|
||||
setResponseLogs(["Sending request..."])
|
||||
runRequest(apiTestingOptions)
|
||||
}
|
||||
}, [isRunning, ran])
|
||||
|
||||
return (
|
||||
<>
|
||||
{manualTestTrigger && (
|
||||
<Card className="font-base mb-docs_1" contentClassName="gap-docs_0.5">
|
||||
{apiTestingOptions.pathData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.pathData}
|
||||
title="Path Parameters"
|
||||
baseObjPath="pathData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{apiTestingOptions.bodyData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.bodyData}
|
||||
title="Request Body Parameters"
|
||||
baseObjPath="bodyData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{apiTestingOptions.queryData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.queryData}
|
||||
title="Request Query Parameters"
|
||||
baseObjPath="queryData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsRunning(true)
|
||||
setRan(false)
|
||||
}}
|
||||
>
|
||||
Send Request
|
||||
</Button>
|
||||
</Card>
|
||||
)}
|
||||
{(isRunning || ran) && (
|
||||
<CodeBlock
|
||||
source={responseLogs.join("\n")}
|
||||
lang="json"
|
||||
title="Testing Result"
|
||||
collapsed={true}
|
||||
blockStyle="subtle"
|
||||
noReport={true}
|
||||
badgeLabel={responseCode}
|
||||
badgeColor={
|
||||
!responseCode
|
||||
? undefined
|
||||
: responseCode.startsWith("2")
|
||||
? "green"
|
||||
: "red"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div ref={ref}>
|
||||
{manualTestTrigger && (
|
||||
<Card className="font-base mb-docs_1" contentClassName="gap-docs_0.5">
|
||||
{apiTestingOptions.pathData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.pathData}
|
||||
title="Path Parameters"
|
||||
baseObjPath="pathData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{apiTestingOptions.bodyData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.bodyData}
|
||||
title="Request Body Parameters"
|
||||
baseObjPath="bodyData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{apiTestingOptions.queryData && (
|
||||
<ApiRunnerParamInputs
|
||||
data={apiTestingOptions.queryData}
|
||||
title="Request Query Parameters"
|
||||
baseObjPath="queryData"
|
||||
setValue={
|
||||
setApiTestingOptions as React.Dispatch<
|
||||
React.SetStateAction<unknown>
|
||||
>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsRunning(true)
|
||||
setRan(false)
|
||||
}}
|
||||
>
|
||||
Send Request
|
||||
</Button>
|
||||
</Card>
|
||||
)}
|
||||
{(isRunning || ran) && (
|
||||
<CodeBlock
|
||||
source={responseLogs.join("\n")}
|
||||
lang="json"
|
||||
title="Testing Result"
|
||||
collapsed={true}
|
||||
blockStyle="subtle"
|
||||
noReport={true}
|
||||
badgeLabel={responseCode}
|
||||
badgeColor={
|
||||
!responseCode
|
||||
? undefined
|
||||
: responseCode.startsWith("2")
|
||||
? "green"
|
||||
: "red"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -78,6 +78,7 @@ export const CodeBlock = ({
|
||||
const [showTesting, setShowTesting] = useState(false)
|
||||
const codeContainerRef = useRef<HTMLDivElement>(null)
|
||||
const codeRef = useRef<HTMLElement>(null)
|
||||
const apiRunnerRef = useRef<HTMLDivElement>(null)
|
||||
const [scrollable, setScrollable] = useState(false)
|
||||
const hasInnerCodeBlock = useMemo(
|
||||
() => hasTabs || title.length > 0,
|
||||
@@ -399,6 +400,7 @@ export const CodeBlock = ({
|
||||
enter: "animate-fadeIn animate-fastest",
|
||||
exit: "animate-fadeOut animate-fastest",
|
||||
}}
|
||||
nodeRef={apiRunnerRef}
|
||||
>
|
||||
<ApiRunner
|
||||
apiMethod={rest.testApiMethod!}
|
||||
@@ -406,6 +408,7 @@ export const CodeBlock = ({
|
||||
pathData={rest.testPathParams}
|
||||
bodyData={rest.testBodyParams}
|
||||
queryData={rest.testQueryParams}
|
||||
ref={apiRunnerRef}
|
||||
/>
|
||||
</CSSTransition>
|
||||
)}
|
||||
|
||||
@@ -48,12 +48,23 @@ export const useRequestRunner = ({
|
||||
replaceLog ? replaceLog(stringifiedData) : pushLog(stringifiedData)
|
||||
})
|
||||
.catch((error) => {
|
||||
pushLog(
|
||||
`An error ocurred: ${JSON.stringify(error, undefined, 2)}`,
|
||||
`\nThis could be a CORS error. You can resolve it by adding\nthe docs' URLto your CORS configurations:\n`,
|
||||
`STORE_CORS=http://localhost:8000,https://docs.medusajs.com`,
|
||||
`ADMIN_CORS=http://localhost:7001,https://docs.medusajs.com`
|
||||
)
|
||||
pushLog(`\nAn error ocurred: ${JSON.stringify(error, undefined, 2)}`)
|
||||
if (responseCode === "404") {
|
||||
pushLog(
|
||||
`\nPossible Solutions:\n`,
|
||||
`- If this is a custom API route, make sure you added it at the correct path.`,
|
||||
`- If this API route accepts any parameters, such as an ID, make sure it exists\nin the Medusa application.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (!responseCode.length) {
|
||||
pushLog(
|
||||
`\nThis could be a CORS error. You can resolve it by adding\nthe docs' URLto your CORS configurations:\n`,
|
||||
`STORE_CORS=http://localhost:8000,https://docs.medusajs.com`,
|
||||
`ADMIN_CORS=http://localhost:7001,https://docs.medusajs.com`
|
||||
)
|
||||
}
|
||||
})
|
||||
.finally(() => onFinish(`Finished running request.`, responseCode))
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ export function useTabs<T extends BaseTabType>({ tabs, group }: TabProps<T>) {
|
||||
const scrollPosition = useRef<number>(0)
|
||||
|
||||
const changeSelectedTab = (tab: T) => {
|
||||
if (tab.value === selectedTab?.value) {
|
||||
return
|
||||
}
|
||||
scrollPosition.current = window.scrollY
|
||||
setSelectedTab(tab)
|
||||
localStorage.setItem(storageKey, tab.value)
|
||||
|
||||
@@ -50,18 +50,23 @@ export const PaginationProvider = ({ children }: PaginationProviderProps) => {
|
||||
|
||||
const getFirstChild = (
|
||||
item: SidebarItemType
|
||||
): SidebarItemType | undefined => {
|
||||
): SidebarItemWithParent | undefined => {
|
||||
const children = getChildrenWithPages(item)
|
||||
if (!children?.length) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return children[0].path ? children[0] : getFirstChild(children[0])
|
||||
return children[0].path
|
||||
? {
|
||||
...children[0],
|
||||
parent: item,
|
||||
}
|
||||
: getFirstChild(children[0])
|
||||
}
|
||||
|
||||
const getChildrenWithPages = (
|
||||
item: SidebarItemType
|
||||
): SidebarItemType[] | undefined => {
|
||||
): SidebarItemWithParent[] | undefined => {
|
||||
return item.children?.filter(
|
||||
(childItem) =>
|
||||
childItem.path !== undefined || getChildrenWithPages(childItem)?.length
|
||||
|
||||
Reference in New Issue
Block a user