@prismicio/client
Version:
The official JavaScript + TypeScript client library for Prismic
207 lines (191 loc) • 6.91 kB
text/typescript
import type { FilledContentRelationshipField } from "../types/value/contentRelationship"
import type { PrismicDocument } from "../types/value/document"
import type { FilledLinkToWebField, LinkField } from "../types/value/link"
import { LinkType } from "../types/value/link"
import type { FilledLinkToMediaField } from "../types/value/linkToMedia"
import { documentToLinkField } from "./documentToLinkField"
/**
* Resolves a link to a Prismic document to a URL
*
* @typeParam ReturnType - Return type of your link resolver function, useful if
* you prefer to return a complex object
*
* @param linkToDocumentField - A document link field to resolve
*
* @returns Resolved URL
*
* @see Prismic link resolver documentation: {@link https://prismic.io/docs/route-resolver#link-resolver}
*/
export type LinkResolverFunction<ReturnType = string | null | undefined> = (
linkToDocumentField: FilledContentRelationshipField,
) => ReturnType
/**
* Configuration that determines the output of `asLink()`.
*/
type AsLinkConfig<LinkResolverFunctionReturnType = string | null | undefined> =
{
/**
* An optional link resolver function. Without it, you are expected to use
* the `routes` options from the API.
*/
linkResolver?: LinkResolverFunction<LinkResolverFunctionReturnType> | null
}
// TODO: Remove when we remove support for deprecated tuple-style configuration.
/**
* @deprecated Use object-style configuration instead.
*/
type AsLinkDeprecatedTupleConfig<
LinkResolverFunctionReturnType = string | null | undefined,
> = [linkResolver?: LinkResolverFunction<LinkResolverFunctionReturnType> | null]
/**
* The return type of `asLink()`.
*/
export type AsLinkReturnType<
LinkResolverFunctionReturnType = string | null | undefined,
Field extends LinkField | PrismicDocument | null | undefined =
| LinkField
| PrismicDocument
| null
| undefined,
> = Field extends
| FilledLinkToWebField
| FilledLinkToMediaField
| FilledContentRelationshipField
| PrismicDocument
? LinkResolverFunctionReturnType | string | null
: null
// TODO: Remove overload when we remove support for deprecated tuple-style configuration.
export const asLink: {
/**
* Resolves any type of link field or Prismic document to a URL.
*
* @typeParam LinkResolverFunctionReturnType - link resolver function return
* type
* @typeParam Field - Link field or Prismic document to resolve to a URL
*
* @param linkFieldOrDocument - Any kind of link field or a document to
* resolve
* @param config - Configuration that determines the output of `asLink()`
*
* @returns Resolved URL or, if the provided link field or document is empty,
* `null`
*
* @see Prismic link resolver documentation: {@link https://prismic.io/docs/route-resolver#link-resolver}
* @see Prismic API `routes` options documentation: {@link https://prismic.io/docs/route-resolver}
*/
<
LinkResolverFunctionReturnType = string | null | undefined,
Field extends LinkField | PrismicDocument | null | undefined =
| LinkField
| PrismicDocument
| null
| undefined,
>(
linkFieldOrDocument: Field,
config?: AsLinkConfig<LinkResolverFunctionReturnType>,
): AsLinkReturnType<LinkResolverFunctionReturnType, Field>
/**
* Resolves any type of link field or Prismic document to a URL.
*
* @deprecated Use object-style configuration instead.
*
* @typeParam LinkResolverFunctionReturnType - link resolver function return
* type
* @typeParam Field - Link field or Prismic document to resolve to a URL
*
* @param linkFieldOrDocument - Any kind of link field or a document to
* resolve
* @param linkResolver - An optional link resolver function. Without it, you
* are expected to use the `routes` options from the API
*
* @returns Resolved URL or, if the provided link field or document is empty,
* `null`
*
* @see Prismic link resolver documentation: {@link https://prismic.io/docs/route-resolver#link-resolver}
* @see Prismic API `routes` options documentation: {@link https://prismic.io/docs/route-resolver}
*/
<
LinkResolverFunctionReturnType = string | null | undefined,
Field extends LinkField | PrismicDocument | null | undefined =
| LinkField
| PrismicDocument
| null
| undefined,
>(
linkFieldOrDocument: Field,
...config: AsLinkDeprecatedTupleConfig<LinkResolverFunctionReturnType>
): AsLinkReturnType<LinkResolverFunctionReturnType, Field>
} = <
LinkResolverFunctionReturnType = string | null | undefined,
Field extends LinkField | PrismicDocument | null | undefined =
| LinkField
| PrismicDocument
| null
| undefined,
>(
linkFieldOrDocument: Field,
// TODO: Rename to `config` when we remove support for deprecated tuple-style configuration.
...configObjectOrTuple:
| [config?: AsLinkConfig<LinkResolverFunctionReturnType>]
| AsLinkDeprecatedTupleConfig<LinkResolverFunctionReturnType>
): AsLinkReturnType<LinkResolverFunctionReturnType, Field> => {
if (!linkFieldOrDocument) {
return null as AsLinkReturnType<LinkResolverFunctionReturnType, Field>
}
// Converts document to link field if needed
const linkField =
// prettier-ignore
(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - Bug in TypeScript 4.9: https://github.com/microsoft/TypeScript/issues/51501
// TODO: Remove the `prettier-ignore` comment when this bug is fixed.
"link_type" in linkFieldOrDocument
? linkFieldOrDocument
: documentToLinkField(linkFieldOrDocument)
) as LinkField
// TODO: Remove when we remove support for deprecated tuple-style configuration.
const [configObjectOrLinkResolver] = configObjectOrTuple
let config: AsLinkConfig<LinkResolverFunctionReturnType>
if (
typeof configObjectOrLinkResolver === "function" ||
configObjectOrLinkResolver == null
) {
config = {
linkResolver: configObjectOrLinkResolver,
}
} else {
config = { ...configObjectOrLinkResolver }
}
switch (linkField.link_type) {
case LinkType.Media:
case LinkType.Web:
return ("url" in linkField ? linkField.url : null) as AsLinkReturnType<
LinkResolverFunctionReturnType,
Field
>
case LinkType.Document: {
if ("id" in linkField && config.linkResolver) {
// When using link resolver...
const resolvedURL = config.linkResolver(linkField)
if (resolvedURL != null) {
return resolvedURL as AsLinkReturnType<
LinkResolverFunctionReturnType,
Field
>
}
}
if ("url" in linkField && linkField.url) {
// When using route resolver...
return linkField.url as AsLinkReturnType<
LinkResolverFunctionReturnType,
Field
>
}
// When empty or link resolver and route resolver are not used...
return null as AsLinkReturnType<LinkResolverFunctionReturnType, Field>
}
case LinkType.Any:
default:
return null as AsLinkReturnType<LinkResolverFunctionReturnType, Field>
}
}