import { NextRouter } from 'next/router';
import React, { createContext, PropsWithChildren, useCallback, useContext } from 'react';
import navigation from '~/public/static/constants/navigation.json';
export const PageApiVersionContext = createContext({
/** The version selected in the URL, or the default version */
version: 'latest',
/** If the current URL has a version defined */
hasVersion: false,
/** Change the URL to the select version */
setVersion: newVersion => {
throw new Error('PageApiVersionContext not found');
},
} as PageApiVersionContextType);
export type PageApiVersionContextType = {
version: keyof typeof navigation.reference;
hasVersion: boolean;
setVersion: (newVersion: string) => void;
};
type Props = PropsWithChildren<{
/** The router containing the current URL info of the page, possibly containing the API version */
router: NextRouter;
}>;
export function PageApiVersionProvider(props: Props) {
const version = getVersionFromPath(props.router.pathname);
const hasVersion = version !== null;
// note: if the page doesn't exists, the error page will handle it
const setVersion = useCallback((newVersion: string) => {
props.router.push(replaceVersionInPath(props.router.pathname, newVersion));
}, []);
return (
{props.children}
);
}
export function usePageApiVersion() {
return useContext(PageApiVersionContext);
}
/**
* Determine if there is a version within the pathname of the URL.
* Versioned pages always starts with /versions/.
*/
export function isVersionedPath(path: string) {
return path.startsWith('/versions/');
}
/**
* Find the version within the pathname of the URL.
* This only accepts pathnames, without hashes or query strings.
*/
export function getVersionFromPath(path: string): PageApiVersionContextType['version'] | null {
return !isVersionedPath(path)
? null
: (path.split('/', 3).pop()! as PageApiVersionContextType['version']);
}
/**
* Replace the version in the pathname from the URL.
* If no version was found, the path is returned as is.
*/
export function replaceVersionInPath(path: string, newVersion: string) {
const version = getVersionFromPath(path);
return version ? path.replace(version, newVersion) : path;
}