UNPKG

@sanity/asset-utils

Version:

<!-- This file is AUTO-GENERATED, edit _README.template.md or tweak scripts/generateDocs.ts -->

1 lines 47.8 kB
{"version":3,"file":"index.cjs","sources":["../src/constants.ts","../src/errors.ts","../src/utils.ts","../src/asserters.ts","../src/hotspotCrop.ts","../src/paths.ts","../src/parse.ts","../src/resolve.ts","../src/urls.ts"],"sourcesContent":["/**\n * @internal\n */\nexport const cdnUrl = 'https://cdn.sanity.io'\n\n/**\n * @internal\n */\nexport const cdnUrlPattern = /^https:\\/\\/cdn\\.sanity\\./\n\n/**\n * @internal\n */\nexport const customCdnUrlPattern =\n /^https:\\/\\/cdn\\.[^/]+\\/(images|files)\\/[^/]+\\/.*?[a-zA-Z0-9_]{24,40}.*$/\n\n/**\n * @internal\n */\nexport const fileAssetFilenamePattern = /^([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+\\.[a-z0-9]+$/\n\n/**\n * @internal\n */\nexport const fileAssetIdPattern = /^file-([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-[a-z0-9]+$/\n\n/**\n * @internal\n */\nexport const imageAssetFilenamePattern = /^([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})-\\d+x\\d+\\.[a-z0-9]+$/\n\n/**\n * @internal\n */\nexport const imageAssetIdPattern = /^image-([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-\\d+x\\d+-[a-z0-9]+$/\n\n/**\n * @internal\n */\nexport const assetFilenamePattern =\n /^(([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+|([a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-\\d+x\\d+\\.[a-z0-9]+)$/\n\n/**\n * @internal\n */\nexport const pathPattern = /^(images|files)\\/([a-z0-9]+)\\/([a-z0-9][-\\w]*)\\//\n\n/**\n * @internal\n */\nexport const idPattern =\n /^(?:image-(?:[a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-\\d+x\\d+-[a-z0-9]+|file-(?:[a-zA-Z0-9_]{24,40}|[a-f0-9]{40})+-[a-z0-9]+)$/\n\n/**\n * For use in cases where the project and dataset doesn't really matter\n *\n * @internal\n */\nexport const dummyProject = {projectId: 'a', dataset: 'b'}\n","/**\n * Error type thrown when the library fails to resolve a value, such as an asset ID,\n * filename or project ID/dataset information.\n *\n * The `input` property holds the value passed as the input, which failed to be\n * resolved to something meaningful.\n *\n * @public\n */\nexport class UnresolvableError extends Error {\n unresolvable = true\n\n // The input may not be a valid source, so let's not type it as one\n input?: unknown\n\n constructor(inputSource: unknown, message = 'Failed to resolve asset ID from source') {\n super(message)\n this.input = inputSource\n }\n}\n\n/**\n * Checks whether or not an error instance is of type UnresolvableError\n *\n * @param err - Error to check for unresolvable error type\n * @returns True if the passed error instance appears to be an unresolvable error\n * @public\n */\nexport function isUnresolvableError(err: unknown): err is UnresolvableError {\n const error = err as UnresolvableError\n return Boolean(error.unresolvable && 'input' in error)\n}\n","import {isUnresolvableError} from './errors'\nimport type {SafeFunction} from './types'\n\n/**\n * Returns a getter which returns `undefined` instead of throwing,\n * if encountering an `UnresolvableError`\n *\n * @param method - Function to use as resolver\n * @returns Function that returns `undefined` if passed resolver throws UnresolvableError\n * @internal\n */\nexport function getForgivingResolver<Args extends unknown[], Return>(\n method: (...args: Args) => Return,\n): SafeFunction<Args, Return> {\n return (...args: Args): Return | undefined => {\n try {\n return method(...args)\n } catch (err) {\n if (isUnresolvableError(err)) {\n return undefined\n }\n\n throw err\n }\n }\n}\n\n/**\n * Checks whether or not the passed object is an object (and not `null`)\n *\n * @param obj Item to check whether or not is an object\n * @returns Whether or not `obj` is an object\n * @internal\n */\nexport function isObject(obj: unknown): obj is object {\n return obj !== null && !Array.isArray(obj) && typeof obj === 'object'\n}\n","import {\n cdnUrlPattern,\n customCdnUrlPattern,\n fileAssetIdPattern,\n imageAssetIdPattern,\n} from './constants.js'\nimport type {\n SanityAssetIdStub,\n SanityAssetObjectStub,\n SanityAssetPathStub,\n SanityAssetUrlStub,\n SanityFileAsset,\n SanityImageAsset,\n SanityReference,\n} from './types.js'\nimport {isObject} from './utils.js'\n\n/**\n * Checks whether or not the given source is a Sanity reference\n * (an object containing _ref string key)\n *\n * @param ref - Possible reference\n * @returns Whether or not the passed object is a reference\n * @public\n */\nexport function isReference(ref: unknown): ref is SanityReference {\n return isObject(ref) && typeof (ref as SanityReference)._ref === 'string'\n}\n\n/**\n * Checks whether or not the given source is an asset ID stub\n * (an object containing an `_id` property)\n *\n * @param stub - Possible asset id stub\n * @returns Whether or not the passed object is an object id stub\n * @public\n */\nexport function isAssetIdStub(stub: unknown): stub is SanityAssetIdStub {\n return isObject(stub) && typeof (stub as SanityAssetIdStub)._id === 'string'\n}\n\n/**\n * Checks whether or not the given source is an asset path stub\n * (an object containing a `path` property)\n *\n * @param stub - Possible asset path stub\n * @returns Whether or not the passed object is an object path stub\n * @public\n */\nexport function isAssetPathStub(stub: unknown): stub is SanityAssetPathStub {\n return isObject(stub) && typeof (stub as SanityAssetPathStub).path === 'string'\n}\n\n/**\n * Checks whether or not the given source is an asset URL stub\n * (an object containing a `url` property)\n *\n * @param stub - Possible asset url stub\n * @returns Whether or not the passed object is an object url stub\n * @public\n */\nexport function isAssetUrlStub(stub: unknown): stub is SanityAssetUrlStub {\n return isObject(stub) && typeof (stub as SanityAssetUrlStub).url === 'string'\n}\n\n/**\n * Checks whether or not the given source is a (partial) sanity file asset document.\n * Only checks the `_type` property, all other properties _may_ be missing\n *\n * @param src - Source to check\n * @returns Whether or not the given source is a file asset\n * @public\n */\nexport function isSanityFileAsset(src: unknown): src is SanityFileAsset {\n return isObject(src) && (src as SanityFileAsset)._type === 'sanity.fileAsset'\n}\n\n/**\n * Checks whether or not the given source is a (partial) sanity image asset document.\n * Only checks the `_type` property, all other properties _may_ be missing\n *\n * @param src - Source to check\n * @returns Whether or not the given source is a file asset\n * @public\n */\nexport function isSanityImageAsset(src: unknown): src is SanityImageAsset {\n return isObject(src) && (src as SanityImageAsset)._type === 'sanity.imageAsset'\n}\n\n/**\n * Checks whether or not the given document ID is a valid Sanity image asset document ID\n *\n * @param documentId - Document ID to check\n * @returns Whether or not the given document ID is a Sanity image asset document ID\n * @public\n */\nexport function isImageAssetId(documentId: string): boolean {\n return imageAssetIdPattern.test(documentId)\n}\n\n/**\n * Checks whether or not the given document ID is a valid Sanity file asset document ID\n *\n * @param documentId - Document ID to check\n * @returns Whether or not the given document ID is a Sanity file asset document ID\n * @public\n */\nexport function isFileAssetId(documentId: string): boolean {\n return fileAssetIdPattern.test(documentId)\n}\n\n/**\n * Checks whether or not the given document ID is a valid Sanity asset document ID (file or image)\n *\n * @param documentId - Document ID to check\n * @returns Whether or not the given document ID is a Sanity asset document ID (file or image)\n * @public\n */\nexport function isAssetId(documentId: string): boolean {\n return isImageAssetId(documentId) || isFileAssetId(documentId)\n}\n\n/**\n * Checks whether or not the given source is an asset object stub\n *\n * @param stub - Possible asset object stub\n * @returns Whether or not the passed object is an object stub\n * @public\n */\nexport function isAssetObjectStub(stub: unknown): stub is SanityAssetObjectStub {\n const item = stub as SanityAssetObjectStub\n return isObject(item) && item.asset && typeof item.asset === 'object'\n}\n\n/**\n * Checks whether or not the given URL is a valid Sanity CDN URL or what appears to be a valid\n * custom CDN URL (has to be prefixed with `cdn.`, and follow the same path pattern as Sanity CDN )\n *\n * @param url - URL to check\n * @returns True if Sanity CDN URL/Custom CDN URL, false otherwise\n * @internal\n */\nexport function isCdnUrl(url: string): boolean {\n return cdnUrlPattern.test(url) || customCdnUrlPattern.test(url)\n}\n","import type {SanityImageCrop, SanityImageHotspot} from './types.js'\n\n/**\n * Default crop (equals to \"whole image\")\n *\n * @public\n */\nexport const DEFAULT_CROP: Readonly<SanityImageCrop> = Object.freeze({\n left: 0,\n top: 0,\n bottom: 0,\n right: 0,\n})\n\n/**\n * Default hotspot (equals to horizontal/vertical center, full size of image)\n *\n * @public\n */\nexport const DEFAULT_HOTSPOT: Readonly<SanityImageHotspot> = Object.freeze({\n x: 0.5,\n y: 0.5,\n height: 1,\n width: 1,\n})\n\n/**\n * Returns cloned version of the default crop (prevents accidental mutations)\n *\n * @returns Default image crop object\n * @public\n */\nexport const getDefaultCrop = (): SanityImageCrop => ({...DEFAULT_CROP})\n\n/**\n * Returns cloned version of the default hotspot (prevents accidental mutations)\n *\n * @returns Default image hotspot object\n * @public\n */\nexport const getDefaultHotspot = (): SanityImageHotspot => ({...DEFAULT_HOTSPOT})\n\n/**\n * Returns whether or not the passed crop has the default values for a crop region\n *\n * @param crop - The crop to return whether or not is the default crop\n * @returns True if passed crop matches default, false otherwise\n * @public\n */\nexport const isDefaultCrop = (crop: SanityImageCrop): boolean => {\n const {top, bottom, left, right} = crop\n const {\n top: defaultTop,\n bottom: defaultBottom,\n left: defaultLeft,\n right: defaultRight,\n } = DEFAULT_CROP\n\n return (\n top === defaultTop && bottom === defaultBottom && left === defaultLeft && right === defaultRight\n )\n}\n\n/**\n * Returns whether or not the passed hotspot has the default values for a hotspot region\n *\n * @param hotspot - The hotspot to return whether or not is the default hotspot\n * @returns True if passed hotspot matches default, false otherwise\n * @public\n */\nexport const isDefaultHotspot = (hotspot: SanityImageHotspot): boolean => {\n const {x, y, width, height} = hotspot\n const {x: defaultX, y: defaultY, width: defaultWidth, height: defaultHeight} = DEFAULT_HOTSPOT\n\n return x === defaultX && y === defaultY && width === defaultWidth && height === defaultHeight\n}\n","import {\n isAssetObjectStub,\n isAssetPathStub,\n isAssetUrlStub,\n isCdnUrl,\n isReference,\n} from './asserters.js'\nimport {\n cdnUrl,\n fileAssetFilenamePattern,\n imageAssetFilenamePattern,\n pathPattern,\n} from './constants.js'\nimport {UnresolvableError} from './errors.js'\nimport type {\n FileUrlBuilderOptions,\n ImageUrlBuilderOptions,\n PathBuilderOptions,\n SanityAssetSource,\n SanityFileUrlParts,\n SanityImageUrlParts,\n} from './types.js'\nimport {getForgivingResolver} from './utils.js'\n\n/**\n * Builds the base image path from the minimal set of parts required to assemble it\n *\n * @param asset - An asset-like shape defining ID, dimensions and extension\n * @param options - Project ID and dataset the image belongs to, along with other options\n * @returns The path to the image\n * @public\n */\nexport function buildImagePath(\n asset: ImageUrlBuilderOptions | SanityImageUrlParts,\n options?: PathBuilderOptions,\n): string {\n const projectId = options?.projectId || asset.projectId\n const dataset = options?.dataset || asset.dataset\n if (!projectId || !dataset) {\n throw new Error('Project details (projectId and dataset) required to resolve path for image')\n }\n\n const dimensions =\n 'metadata' in asset ? asset.metadata.dimensions : {width: asset.width, height: asset.height}\n const originalFilename = 'originalFilename' in asset ? asset.originalFilename : undefined\n const {assetId, extension, vanityFilename} = asset\n const {width, height} = dimensions\n const vanity = getVanityStub(originalFilename, vanityFilename, options)\n\n return `images/${projectId}/${dataset}/${assetId}-${width}x${height}.${extension}${vanity}`\n}\n\n/**\n * Builds the base image URL from the minimal set of parts required to assemble it\n *\n * @param asset - An asset-like shape defining ID, dimensions and extension\n * @param options - Project ID and dataset the image belongs to\n * @returns The URL to the image, as a string\n * @public\n */\nexport function buildImageUrl(\n asset: ImageUrlBuilderOptions | SanityImageUrlParts,\n options?: PathBuilderOptions,\n): string {\n const baseUrl = options?.baseUrl || cdnUrl\n return `${baseUrl}/${buildImagePath(asset, options)}`\n}\n\n/**\n * Builds the base file path from the minimal set of parts required to assemble it\n *\n * @param asset - An asset-like shape defining ID, dimensions and extension\n * @param options - Project ID and dataset the file belongs to, along with other options\n * @returns The path to the file\n * @public\n */\nexport function buildFilePath(\n asset: FileUrlBuilderOptions | SanityFileUrlParts,\n options?: PathBuilderOptions,\n): string {\n const projectId = options?.projectId || asset.projectId\n const dataset = options?.dataset || asset.dataset\n if (!projectId || !dataset) {\n throw new Error('Project details (projectId and dataset) required to resolve path for file')\n }\n\n const originalFilename = 'originalFilename' in asset ? asset.originalFilename : undefined\n const {assetId, extension, vanityFilename} = asset\n const vanity = getVanityStub(originalFilename, vanityFilename, options)\n\n return `files/${projectId}/${dataset}/${assetId}.${extension}${vanity}`\n}\n\n/**\n * Builds the base file URL from the minimal set of parts required to assemble it\n *\n * @param asset - An asset-like shape defining ID and extension\n * @param options - Project ID and dataset the file belongs to, along with other options\n * @returns The URL to the file, as a string\n * @public\n */\nexport function buildFileUrl(asset: FileUrlBuilderOptions, options?: PathBuilderOptions): string {\n const baseUrl = options?.baseUrl || cdnUrl\n return `${baseUrl}/${buildFilePath(asset, options)}`\n}\n\n/**\n * Checks whether or not the given URL contains an asset path\n *\n * @param url - URL or path name\n * @returns Whether or not it contained an asset path\n * @public\n */\nfunction hasPath(urlOrPath: string): boolean {\n return pathPattern.test(tryGetUrlPath(urlOrPath) || '')\n}\n\n/**\n * Tries to get the asset path from a given asset source\n *\n * @param src - The source image to infer an asset path from\n * @returns A path if resolvable, undefined otherwise\n * @public\n */\nexport function tryGetAssetPath(src: SanityAssetSource): string | undefined {\n if (isAssetObjectStub(src)) {\n return tryGetAssetPath(src.asset)\n }\n\n if (isReference(src)) {\n return undefined\n }\n\n if (typeof src === 'string') {\n return hasPath(src) ? getUrlPath(src) : undefined\n }\n\n if (isAssetPathStub(src)) {\n return src.path\n }\n\n if (isAssetUrlStub(src)) {\n return getUrlPath(src.url)\n }\n\n return undefined\n}\n\n/**\n * Strips the CDN URL and query params from a URL, eg:\n * `https://cdn.sanity.io/images/project/dataset/filename-200x200.jpg?foo=bar` →\n * `images/project/dataset/filename-200x200.jpg`\n *\n * @param url - URL to get path name from\n * @returns The path of a CDN URL\n * @public\n * @throws If URL is not a valid Sanity asset URL\n */\nexport function getUrlPath(url: string): string {\n if (pathPattern.test(url)) {\n // Already just a path\n return url\n }\n\n if (!isCdnUrl(url)) {\n throw new UnresolvableError(`Failed to resolve path from URL \"${url}\"`)\n }\n\n return new URL(url).pathname.replace(/^\\/+/, '')\n}\n\n/**\n * {@inheritDoc getUrlPath}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetUrlPath = getForgivingResolver(getUrlPath)\n\n/**\n * Strips the CDN URL, path and query params from a URL, eg:\n * `https://cdn.sanity.io/images/project/dataset/filename-200x200.jpg?foo=bar` →\n * `filename-200x200.jpg`\n *\n * @param url - URL to get filename from\n * @returns The filename of an URL, if URL matches the CDN URL\n * @public\n * @throws If URL is not a valid Sanity asset URL\n */\nexport function getUrlFilename(url: string): string {\n const path = tryGetUrlPath(url) || url\n const filename = path.replace(/^(images|files)\\/[a-z0-9]+\\/[a-z0-9][-\\w]\\/*/, '')\n if (!isValidFilename(filename)) {\n throw new UnresolvableError(`Failed to resolve filename from URL \"${url}\"`)\n }\n\n return filename\n}\n\n/**\n * {@inheritDoc getUrlFilename}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetUrlFilename = getForgivingResolver(getUrlFilename)\n\n/**\n * Checks whether or not a given filename matches the expected Sanity asset filename pattern\n *\n * @param filename - Filename to check for validity\n * @returns Whether or not the specified filename is valid\n * @public\n */\nexport function isValidFilename(filename: string): boolean {\n return fileAssetFilenamePattern.test(filename) || imageAssetFilenamePattern.test(filename)\n}\n\n/**\n * Get the \"path stub\" at the end of the path, if the user hasn't explicitly opted out of this behavior\n *\n * @param originalFilename - The original filename of the asset\n * @param vanityFilename - The vanity filename of the asset\n * @param options - Options to control the behavior of the path builder\n * @returns The vanity stub, if any\n * @public\n */\nexport function getVanityStub(\n originalFilename: string | undefined,\n vanityFilename: string | undefined,\n options?: PathBuilderOptions,\n): string {\n const vanity = vanityFilename || originalFilename\n return options?.useVanityName === false || !vanity ? '' : `/${vanity}`\n}\n","import {isCdnUrl} from './asserters.js'\nimport {\n fileAssetIdPattern,\n imageAssetFilenamePattern,\n imageAssetIdPattern,\n pathPattern,\n} from './constants.js'\nimport {isValidFilename, tryGetUrlFilename} from './paths.js'\nimport type {\n SanityAssetIdParts,\n SanityAssetUrlParts,\n SanityFileAssetIdParts,\n SanityFileUrlParts,\n SanityImageAssetIdParts,\n SanityImageUrlParts,\n} from './types.js'\n\n/**\n * @internal\n */\nconst exampleFileId = 'file-027401f31c3ac1e6d78c5d539ccd1beff72b9b11-pdf'\n\n/**\n * @internal\n */\nconst exampleImageId = 'image-027401f31c3ac1e6d78c5d539ccd1beff72b9b11-2000x3000-jpg'\n\n/**\n * Parses a Sanity asset document ID into individual parts (type, id, extension, width/height etc)\n *\n * @param documentId - Document ID to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If document ID is invalid\n */\nexport function parseAssetId(documentId: string): SanityAssetIdParts {\n if (imageAssetIdPattern.test(documentId)) {\n return parseImageAssetId(documentId)\n }\n\n if (fileAssetIdPattern.test(documentId)) {\n return parseFileAssetId(documentId)\n }\n\n throw new Error(`Invalid image/file asset ID: ${documentId}`)\n}\n\n/**\n * Parses a Sanity file asset document ID into individual parts (type, id, extension)\n *\n * @param documentId - File asset document ID to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If document ID invalid\n */\nexport function parseFileAssetId(documentId: string): SanityFileAssetIdParts {\n if (!fileAssetIdPattern.test(documentId)) {\n throw new Error(\n `Malformed file asset ID '${documentId}'. Expected an id like \"${exampleFileId}\"`,\n )\n }\n\n const [, assetId, extension] = documentId.split('-')\n return {type: 'file', assetId, extension}\n}\n\n/**\n * Parses a Sanity image asset document ID into individual parts (type, id, extension, width, height)\n *\n * @param documentId - Image asset document ID to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If document ID invalid\n */\nexport function parseImageAssetId(documentId: string): SanityImageAssetIdParts {\n const [, assetId, dimensionString, extension] = documentId.split('-')\n const [width, height] = (dimensionString || '').split('x').map(Number)\n\n if (!assetId || !dimensionString || !extension || !(width > 0) || !(height > 0)) {\n throw new Error(`Malformed asset ID '${documentId}'. Expected an id like \"${exampleImageId}\".`)\n }\n\n return {type: 'image', assetId, width, height, extension}\n}\n\n/**\n * Parses a Sanity asset filename into individual parts (type, id, extension, width, height)\n *\n * @param filename - Filename to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If image/filename is invalid\n */\nexport function parseAssetFilename(filename: string): SanityAssetIdParts {\n const file = tryGetUrlFilename(filename) || ''\n if (!isValidFilename(file)) {\n throw new Error(`Invalid image/file asset filename: ${filename}`)\n }\n\n try {\n const type = imageAssetFilenamePattern.test(file) ? 'image' : 'file'\n const assetId = file.replace(/\\.([a-z0-9+]+)$/i, '-$1')\n return parseAssetId(`${type}-${assetId}`)\n } catch (err) {\n throw new Error(`Invalid image/file asset filename: ${filename}`)\n }\n}\n\n/**\n * Parses a full Sanity asset URL into individual parts\n * (type, project ID, dataset, id, extension, width, height)\n *\n * @param url - Full URL to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If URL is invalid or not a Sanity asset URL\n */\nexport function parseAssetUrl(url: string): SanityAssetUrlParts {\n if (!isCdnUrl(url)) {\n throw new Error(`URL is not a valid Sanity asset URL: ${url}`)\n }\n\n const path = new URL(url).pathname.replace(/^\\/+/, '')\n const [projectPath, , projectId, dataset] = path.match(pathPattern) || []\n if (!projectPath || !projectId || !dataset) {\n throw new Error(`URL is not a valid Sanity asset URL: ${url}`)\n }\n\n const [filename, vanityFilename] = path.slice(projectPath.length).split('/')\n const parsed = parseAssetFilename(filename)\n\n return {\n ...parsed,\n projectId,\n dataset,\n vanityFilename,\n }\n}\n\n/**\n * Parses a full Sanity image asset URL into individual parts\n * (type, project ID, dataset, id, extension, width, height)\n *\n * @param url - Full URL to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If URL is invalid or not a Sanity image asset URL\n */\nexport function parseImageAssetUrl(url: string): SanityImageUrlParts {\n const parsed = parseAssetUrl(url)\n if (parsed.type !== 'image') {\n throw new Error(`URL is not a valid Sanity image asset URL: ${url}`)\n }\n\n return parsed\n}\n\n/**\n * Parses a full Sanity file asset URL into individual parts\n * (type, project ID, dataset, id, extension, width, height)\n *\n * @param url - Full URL to parse into named parts\n * @returns Object of named properties\n * @public\n * @throws If URL is invalid or not a Sanity file asset URL\n */\nexport function parseFileAssetUrl(url: string): SanityFileUrlParts {\n const parsed = parseAssetUrl(url)\n if (parsed.type !== 'file') {\n throw new Error(`URL is not a valid Sanity file asset URL: ${url}`)\n }\n\n return parsed\n}\n\n/**\n * Validates that a given URL is a Sanity asset URL, and returns the asset type if valid.\n *\n * @param url - URL to extract asset type from\n * @returns Asset type if valid URL, false otherwise\n * @public\n */\nexport function getAssetUrlType(url: string): 'image' | 'file' | false {\n try {\n return parseAssetUrl(url).type\n } catch (err) {\n return false\n }\n}\n","import {\n isAssetIdStub,\n isAssetObjectStub,\n isAssetPathStub,\n isAssetUrlStub,\n isCdnUrl,\n isReference,\n isSanityFileAsset,\n isSanityImageAsset,\n} from './asserters.js'\nimport {\n cdnUrl,\n dummyProject,\n fileAssetFilenamePattern,\n idPattern,\n imageAssetFilenamePattern,\n pathPattern,\n} from './constants.js'\nimport {UnresolvableError} from './errors.js'\nimport {getDefaultCrop, getDefaultHotspot} from './hotspotCrop.js'\nimport {parseFileAssetId, parseImageAssetId} from './parse.js'\nimport {\n buildFilePath,\n buildFileUrl,\n buildImagePath,\n buildImageUrl,\n getUrlPath,\n tryGetAssetPath,\n} from './paths.js'\nimport type {\n PathBuilderOptions,\n ResolvedSanityFile,\n ResolvedSanityImage,\n SanityAssetSource,\n SanityFileAsset,\n SanityFileObjectStub,\n SanityFileSource,\n SanityImageAsset,\n SanityImageDimensions,\n SanityImageObjectStub,\n SanityImageSource,\n SanityProjectDetails,\n} from './types.js'\nimport {getForgivingResolver} from './utils.js'\n\n/**\n * Returns the width, height and aspect ratio of a passed image asset, from any\n * inferrable structure (id, url, path, asset document, image object etc)\n *\n * @param src - Input source (image object, asset, reference, id, url, path)\n * @returns Object with width, height and aspect ratio properties\n *\n * @throws {@link UnresolvableError}\n * Throws if passed image source could not be resolved to an asset ID\n * @public\n */\nexport function getImageDimensions(src: SanityImageSource): SanityImageDimensions {\n const imageId = getAssetDocumentId(src)\n const {width, height} = parseImageAssetId(imageId)\n const aspectRatio = width / height\n return {width, height, aspectRatio}\n}\n\n/**\n * {@inheritDoc getImageDimensions}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetImageDimensions = getForgivingResolver(getImageDimensions)\n\n/**\n * Returns the file extension for a given asset\n *\n * @param src - Input source (file/image object, asset, reference, id, url, path)\n * @returns The file extension, if resolvable (no `.` included)\n *\n * @throws {@link UnresolvableError}\n * Throws if passed asset source could not be resolved to an asset ID\n * @public\n */\nexport function getExtension(src: SanityAssetSource): string {\n return isFileSource(src)\n ? getFile(src, dummyProject).asset.extension\n : getImage(src, dummyProject).asset.extension\n}\n\n/**\n * {@inheritDoc getExtension}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetExtension = getForgivingResolver(getExtension)\n\n/**\n * Tries to resolve an image object with as much information as possible,\n * from any inferrable structure (id, url, path, image object etc)\n *\n * @param src - Input source (image object, asset, reference, id, url, path)\n * @param project - Project ID and dataset the image belongs to\n * @returns Image object\n *\n * @throws {@link UnresolvableError}\n * Throws if passed image source could not be resolved to an asset ID\n * @public\n */\nexport function getImage(\n src: SanityImageSource,\n project?: SanityProjectDetails,\n): ResolvedSanityImage {\n const projectDetails = project || tryGetProject(src)\n const asset = getImageAsset(src, projectDetails)\n\n const img = src as SanityImageObjectStub\n return {\n asset,\n crop: img.crop || getDefaultCrop(),\n hotspot: img.hotspot || getDefaultHotspot(),\n }\n}\n\n/**\n * {@inheritDoc getImage}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetImage = getForgivingResolver(getImage)\n\n/**\n * Tries to resolve a (partial) image asset document with as much information as possible,\n * from any inferrable structure (id, url, path, image object etc)\n *\n * @param src - Input source (image object, asset, reference, id, url, path)\n * @param project - Project ID and dataset the image belongs to\n * @returns Image asset document\n *\n * @throws {@link UnresolvableError}\n * Throws if passed image source could not be resolved to an asset ID\n * @public\n */\nexport function getImageAsset(\n src: SanityImageSource,\n project?: SanityProjectDetails,\n): SanityImageAsset {\n const projectDetails = project || getProject(src)\n const pathOptions: PathBuilderOptions = {...projectDetails, useVanityName: false}\n\n const _id = getAssetDocumentId(src)\n const sourceObj = src as SanityImageObjectStub\n const source = (sourceObj.asset || src) as SanityImageAsset\n const metadata = source.metadata || {}\n const {assetId, width, height, extension} = parseImageAssetId(_id)\n const aspectRatio = width / height\n const baseAsset: SanityImageAsset = {\n ...(isSanityImageAsset(src) ? src : {}),\n _id,\n _type: 'sanity.imageAsset',\n assetId,\n extension,\n metadata: {\n ...metadata,\n dimensions: {width, height, aspectRatio},\n },\n\n // Placeholders, overwritten below\n url: '',\n path: '',\n }\n\n return {\n ...baseAsset,\n path: buildImagePath(baseAsset, pathOptions),\n url: buildImageUrl(baseAsset, pathOptions),\n }\n}\n\n/**\n * {@inheritDoc getImageAsset}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetImageAsset = getForgivingResolver(getImageAsset)\n\n/**\n * Tries to resolve an file object with as much information as possible,\n * from any inferrable structure (id, url, path, file object etc)\n *\n * @param src - Input source (file object, asset, reference, id, url, path)\n * @param project - Project ID and dataset the file belongs to\n * @returns File object\n *\n * @throws {@link UnresolvableError}\n * Throws if passed file source could not be resolved to an asset ID\n * @public\n */\nexport function getFile(src: SanityFileSource, project?: SanityProjectDetails): ResolvedSanityFile {\n const projectDetails = project || tryGetProject(src)\n const asset = getFileAsset(src, projectDetails)\n return {asset}\n}\n\n/**\n * {@inheritDoc getFile}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetFile = getForgivingResolver(getFile)\n\n/**\n * Tries to resolve a (partial) file asset document with as much information as possible,\n * from any inferrable structure (id, url, path, file object etc)\n *\n * @param src - Input source (file object, asset, reference, id, url, path)\n * @param options - Project ID and dataset the file belongs to, along with other options\n * @returns File asset document\n *\n * @throws {@link UnresolvableError}\n * Throws if passed file source could not be resolved to an asset ID\n * @public\n */\nexport function getFileAsset(src: SanityFileSource, options?: PathBuilderOptions): SanityFileAsset {\n const projectDetails: PathBuilderOptions = {...(options || getProject(src)), useVanityName: false}\n\n const _id = getAssetDocumentId(src)\n const sourceObj = src as SanityFileObjectStub\n const source = (sourceObj.asset || src) as SanityFileAsset\n const {assetId, extension} = parseFileAssetId(_id)\n const baseAsset: SanityFileAsset = {\n ...(isSanityFileAsset(src) ? src : {}),\n _id,\n _type: 'sanity.fileAsset',\n assetId,\n extension,\n metadata: source.metadata || {},\n\n // Placeholders, overwritten below\n url: '',\n path: '',\n }\n\n return {\n ...baseAsset,\n path: buildFilePath(baseAsset, projectDetails),\n url: buildFileUrl(baseAsset, projectDetails),\n }\n}\n\n/**\n * {@inheritDoc getFileAsset}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetFileAsset = getForgivingResolver(getFileAsset)\n\n/**\n * Tries to resolve the asset document ID from any inferrable structure\n *\n * @param src - Input source (image/file object, asset, reference, id, url, path)\n * @returns The asset document ID\n *\n * @throws {@link UnresolvableError}\n * Throws if passed asset source could not be resolved to an asset document ID\n * @public\n */\nexport function getAssetDocumentId(src: unknown): string {\n const source = isAssetObjectStub(src) ? src.asset : src\n\n let id = ''\n if (typeof source === 'string') {\n id = getIdFromString(source)\n } else if (isReference(source)) {\n id = source._ref\n } else if (isAssetIdStub(source)) {\n id = source._id\n } else if (isAssetPathStub(source)) {\n id = idFromUrl(`${cdnUrl}/${source.path}`)\n } else if (isAssetUrlStub(source)) {\n id = idFromUrl(source.url)\n }\n\n const hasId = id && idPattern.test(id)\n if (!hasId) {\n throw new UnresolvableError(src)\n }\n\n return id\n}\n\n/**\n * {@inheritDoc getAssetDocumentId}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetAssetDocumentId = getForgivingResolver(getAssetDocumentId)\n\n/**\n * Tries to cooerce a string (ID, URL or path) to an image asset ID\n *\n * @param str - Input string (ID, URL or path)\n * @returns string\n *\n *\n * @throws {@link UnresolvableError}\n * Throws if passed image source could not be resolved to an asset ID\n * @public\n */\nexport function getIdFromString(str: string): string {\n if (idPattern.test(str)) {\n // Already an ID\n return str\n }\n\n const isAbsoluteUrl = isCdnUrl(str)\n const path = isAbsoluteUrl ? new URL(str).pathname : str\n\n if (path.indexOf('/images') === 0 || path.indexOf('/files') === 0) {\n // Full URL\n return idFromUrl(str)\n }\n\n if (pathPattern.test(str)) {\n // Path\n return idFromUrl(`${cdnUrl}/${str}`)\n }\n\n if (isFileAssetFilename(str)) {\n // Just a filename (projectId/dataset irrelevant: just need asset ID)\n return idFromUrl(`${cdnUrl}/files/a/b/${str}`)\n }\n\n if (isImageAssetFilename(str)) {\n // Just a filename (projectId/dataset irrelevant: just need asset ID)\n return idFromUrl(`${cdnUrl}/images/a/b/${str}`)\n }\n\n throw new UnresolvableError(str)\n}\n\n/**\n * {@inheritDoc getIdFromString}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetIdFromString = getForgivingResolver(getIdFromString)\n\n/**\n * Converts from a full asset URL to just the asset document ID\n *\n * @param url - A full asset URL to convert\n * @returns string\n * @public\n */\nfunction idFromUrl(url: string): string {\n const path = getUrlPath(url)\n const [type, , , fileName] = path.split('/')\n const prefix = type.replace(/s$/, '')\n return `${prefix}-${fileName.replace(/\\./g, '-')}`\n}\n\n/**\n * Resolves project ID and dataset the image belongs to, based on full URL or path\n * @param src - Image URL or path\n * @returns object | undefined\n *\n * @throws {@link UnresolvableError}\n * Throws if passed image source could not be resolved to an asset ID\n * @public\n */\nexport function getProject(src: SanityImageSource): SanityProjectDetails {\n const path = tryGetAssetPath(src)\n if (!path) {\n throw new UnresolvableError(src, 'Failed to resolve project ID and dataset from source')\n }\n\n const [, , projectId, dataset] = path.match(pathPattern) || []\n if (!projectId || !dataset) {\n throw new UnresolvableError(src, 'Failed to resolve project ID and dataset from source')\n }\n\n return {projectId, dataset}\n}\n\n/**\n * {@inheritDoc getProject}\n * @returns Returns `undefined` instead of throwing if a value cannot be resolved\n * @public\n */\nexport const tryGetProject = getForgivingResolver(getProject)\n\n/**\n * Returns whether or not the passed filename is a valid image asset filename\n *\n * @param filename - Filename to validate\n * @returns Whether or not the filename is an image asset filename\n * @public\n */\nexport function isImageAssetFilename(filename: string): boolean {\n return imageAssetFilenamePattern.test(filename)\n}\n\n/**\n * Returns whether or not the passed filename is a valid file asset filename\n *\n * @param filename - Filename to validate\n * @returns Whether or not the filename is a file asset filename\n * @public\n */\nexport function isFileAssetFilename(filename: string): boolean {\n return fileAssetFilenamePattern.test(filename)\n}\n\n/**\n * Returns whether or not the passed filename is a valid file or image asset filename\n *\n * @param filename - Filename to validate\n * @returns Whether or not the filename is an asset filename\n * @public\n */\nexport function isAssetFilename(filename: string): boolean {\n return isImageAssetFilename(filename) || isFileAssetFilename(filename)\n}\n\n/**\n * Return whether or not the passed source is a file source\n *\n * @param src - Source to check\n * @returns Whether or not the given source is a file source\n * @public\n */\nexport function isFileSource(src: unknown): src is SanityFileSource {\n const assetId = tryGetAssetDocumentId(src)\n return assetId ? assetId.startsWith('file-') : false\n}\n\n/**\n * Return whether or not the passed source is an image source\n *\n * @param src - Source to check\n * @returns Whether or not the given source is an image source\n * @public\n */\nexport function isImageSource(src: unknown): src is SanityImageSource {\n const assetId = tryGetAssetDocumentId(src)\n return assetId ? assetId.startsWith('image-') : false\n}\n","import {getAssetUrlType} from './parse.js'\n\n/**\n * Checks whether or not a given URL is a valid Sanity asset URL\n *\n * @param url - URL to test\n * @returns True if url is a valid Sanity asset URL, false otherwise\n * @public\n */\nexport function isSanityAssetUrl(url: string): boolean {\n return getAssetUrlType(url) !== false\n}\n\n/**\n * Checks whether or not a given URL is a valid Sanity image asset URL\n *\n * @param url - URL to test\n * @returns True if url is a valid Sanity image asset URL, false otherwise\n * @public\n */\nexport function isSanityImageUrl(url: string): boolean {\n return getAssetUrlType(url) === 'image'\n}\n\n/**\n * Checks whether or not a given URL is a valid Sanity file asset URL\n *\n * @param url - URL to test\n * @returns True if url is a valid Sanity file asset URL, false otherwise\n * @public\n */\nexport function isSanityFileUrl(url: string): boolean {\n return getAssetUrlType(url) === 'file'\n}\n"],"names":[],"mappings":"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"}