import type { ColorField } from "../types/value/color" import type { ContentRelationshipField, EmptyContentRelationshipField, } from "../types/value/contentRelationship" import type { DateField } from "../types/value/date" import type { AnyOEmbed, EmbedField } from "../types/value/embed" import type { GeoPointField } from "../types/value/geoPoint" import type { GroupField, NestedGroupField } from "../types/value/group" import type { ImageField, ImageFieldImage } from "../types/value/image" import type { IntegrationField, IntegrationFieldData } from "../types/value/integration" import type { KeyTextField } from "../types/value/keyText" import type { LinkField } from "../types/value/link" import type { LinkToMediaField } from "../types/value/linkToMedia" import type { NumberField } from "../types/value/number" import type { RichTextField } from "../types/value/richText" import type { SelectField } from "../types/value/select" import type { SharedSlice } from "../types/value/sharedSlice" import type { Slice } from "../types/value/slice" import type { SliceZone } from "../types/value/sliceZone" import type { TableField } from "../types/value/table" import type { TimestampField } from "../types/value/timestamp" import type { TitleField } from "../types/value/title" import type { AnyRegularField, Repeatable } from "../types/value/types" /** * Determines if a value is not nullish (i.e. not `null` or `undefined`). This is used to check if * nullable field values are filled. * * @param input - The value to check. * @returns `true` if `input` is not nullish, `false` otherwise. */ const isNonNullish = (input: T): input is NonNullable => { return input != null } /** * Determines if an array is not empty. This is used to check if array-based fields are filled. * * @param input - The array to check. * @returns `true` if `input` has at least one element, `false` otherwise. */ const isNonEmptyArray = (input: T[]): input is [T, ...T[]] => { return !!input.length } /** * Determines if a rich text field is filled. * * @param field - Rich text field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const richText = ( field: RichTextField | null | undefined, ): field is RichTextField<"filled"> => { if (!isNonNullish(field)) { return false } else if (field.length === 1 && "text" in field[0]) { return !!field[0].text } else { return !!field.length } } /** * Determines if a title field is filled. * * @param field - Title field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const title = richText as ( field: TitleField | null | undefined, ) => field is TitleField<"filled"> /** * Determines if an image thumbnail is filled. * * @param thumbnail - Image thumbnail to check. * @returns `true` if the thumbnail is filled, `false` otherwise. */ export const imageThumbnail = ( thumbnail: ImageFieldImage | null | undefined, ): thumbnail is ImageFieldImage<"filled"> => { return isNonNullish(thumbnail) && !!thumbnail.url } /** * Determines if an image field is filled. * * @param field - Image field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const image = imageThumbnail as ( field: ImageField | null | undefined, ) => field is ImageField /** * Determines if a link field is filled. * * @param field - Link field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const link = < TypeEnum = string, LangEnum = string, DataInterface extends Record | unknown = unknown, >( field: LinkField | null | undefined, ): field is LinkField => { return isNonNullish(field) && ("id" in field || "url" in field) } /** * Determines if a link to media field is filled. * * @param field - Link to media field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const linkToMedia = link as ( field: LinkToMediaField | null | undefined, ) => field is LinkToMediaField<"filled"> /** * Determines if a content relationship field is filled. * * @param field - Content relationship field to check. * @returns `true` if the field is filled, `false` otherwise. */ export const contentRelationship = link as ( field: Field | null | undefined, ) => field is Exclude /** * Determines if a date field is filled. * * @param field - Date field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const date = isNonNullish as ( field: DateField | null | undefined, ) => field is DateField<"filled"> /** * Determines if a timestamp field is filled. * * @param field - Timestamp field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const timestamp = isNonNullish as ( field: TimestampField | null | undefined, ) => field is TimestampField<"filled"> /** * Determines if a color field is filled. * * @param field - Color field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const color = isNonNullish as ( field: ColorField | null | undefined, ) => field is ColorField<"filled"> /** * Determines if a number field is filled. * * @param field - Number field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const number = isNonNullish as ( field: NumberField | null | undefined, ) => field is NumberField<"filled"> /** * Determines if a key text field is filled. * * @param field - Key text field to check. * @returns `true` if the field is filled, `false` otherwise. */ export const keyText = ( field: KeyTextField | null | undefined, ): field is KeyTextField<"filled"> => { return !!field } /** * Determines if a select field is filled. * * @param field - Select field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const select = isNonNullish as ( field: SelectField | null | undefined, ) => field is SelectField /** * Determines if an embed field is filled. * * @param field - Embed field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const embed = >( field: Field | null | undefined, ): field is Extract> => { return isNonNullish(field) && !!field.embed_url } /** * Determines if a geopoint field is filled. * * @param field - Geopoint field to check. * @returns `true` if the field is filled, `false` otherwise. */ export const geoPoint = ( field: GeoPointField | null | undefined, ): field is GeoPointField<"filled"> => { return isNonNullish(field) && "longitude" in field } /** * Determines if a table field is filled. * * @param field - Table field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const table = isNonNullish as ( field: TableField | null | undefined, ) => field is TableField<"filled"> /** * Determines if an integration field is filled. * * @param field - Integration field to check. * @returns `true` if `field` is filled, `false` otherwise. */ export const integration = isNonNullish as ( field: IntegrationField | null | undefined, ) => field is IntegrationField /** @deprecated Renamed to `integration`. */ // TODO: Remove when we remove support for deprecated `integrationField` export. export const integrationField = integration /** @deprecated Renamed to `integrationField`. */ // TODO: Remove when we remove support for deprecated `integrationFields` export. export const integrationFields = integration /** * Determines if a repeatable field has at least one item. * * @param repeatable - Repeatable to check. * @returns `true` if `repeatable` contains at least one item, `false` * otherwise. */ export const repeatable = ( repeatable: Repeatable | null | undefined, ): repeatable is Repeatable => { return isNonNullish(repeatable) && isNonEmptyArray(repeatable) } /** * Determines if a group has at least one item. * * @param group - Group to check. * @returns `true` if the group contains at least one item, `false` otherwise. */ export const group = >( group: GroupField | null | undefined, ): group is GroupField => { return isNonNullish(group) && isNonEmptyArray(group) } /** * Determines if a slice zone has at least one slice. * * @param slices - Slice zone to check. * @returns `true` if the slice zone contains at least one slice, `false` * otherwise. */ export const sliceZone = ( slices: SliceZone | null | undefined, ): slices is SliceZone => { return isNonNullish(slices) && isNonEmptyArray(slices) }