@sanity/asset-utils
Version:
<!-- This file is AUTO-GENERATED, edit _README.template.md or tweak scripts/generateDocs.ts -->
190 lines (168 loc) • 5.63 kB
text/typescript
import {isCdnUrl} from './asserters.js'
import {
fileAssetIdPattern,
imageAssetFilenamePattern,
imageAssetIdPattern,
pathPattern,
} from './constants.js'
import {isValidFilename, tryGetUrlFilename} from './paths.js'
import type {
SanityAssetIdParts,
SanityAssetUrlParts,
SanityFileAssetIdParts,
SanityFileUrlParts,
SanityImageAssetIdParts,
SanityImageUrlParts,
} from './types.js'
/**
* @internal
*/
const exampleFileId = 'file-027401f31c3ac1e6d78c5d539ccd1beff72b9b11-pdf'
/**
* @internal
*/
const exampleImageId = 'image-027401f31c3ac1e6d78c5d539ccd1beff72b9b11-2000x3000-jpg'
/**
* Parses a Sanity asset document ID into individual parts (type, id, extension, width/height etc)
*
* @param documentId - Document ID to parse into named parts
* @returns Object of named properties
* @public
* @throws If document ID is invalid
*/
export function parseAssetId(documentId: string): SanityAssetIdParts {
if (imageAssetIdPattern.test(documentId)) {
return parseImageAssetId(documentId)
}
if (fileAssetIdPattern.test(documentId)) {
return parseFileAssetId(documentId)
}
throw new Error(`Invalid image/file asset ID: ${documentId}`)
}
/**
* Parses a Sanity file asset document ID into individual parts (type, id, extension)
*
* @param documentId - File asset document ID to parse into named parts
* @returns Object of named properties
* @public
* @throws If document ID invalid
*/
export function parseFileAssetId(documentId: string): SanityFileAssetIdParts {
if (!fileAssetIdPattern.test(documentId)) {
throw new Error(
`Malformed file asset ID '${documentId}'. Expected an id like "${exampleFileId}"`,
)
}
const [, assetId, extension] = documentId.split('-')
return {type: 'file', assetId, extension}
}
/**
* Parses a Sanity image asset document ID into individual parts (type, id, extension, width, height)
*
* @param documentId - Image asset document ID to parse into named parts
* @returns Object of named properties
* @public
* @throws If document ID invalid
*/
export function parseImageAssetId(documentId: string): SanityImageAssetIdParts {
const [, assetId, dimensionString, extension] = documentId.split('-')
const [width, height] = (dimensionString || '').split('x').map(Number)
if (!assetId || !dimensionString || !extension || !(width > 0) || !(height > 0)) {
throw new Error(`Malformed asset ID '${documentId}'. Expected an id like "${exampleImageId}".`)
}
return {type: 'image', assetId, width, height, extension}
}
/**
* Parses a Sanity asset filename into individual parts (type, id, extension, width, height)
*
* @param filename - Filename to parse into named parts
* @returns Object of named properties
* @public
* @throws If image/filename is invalid
*/
export function parseAssetFilename(filename: string): SanityAssetIdParts {
const file = tryGetUrlFilename(filename) || ''
if (!isValidFilename(file)) {
throw new Error(`Invalid image/file asset filename: ${filename}`)
}
try {
const type = imageAssetFilenamePattern.test(file) ? 'image' : 'file'
const assetId = file.replace(/\.([a-z0-9+]+)$/i, '-$1')
return parseAssetId(`${type}-${assetId}`)
} catch (err) {
throw new Error(`Invalid image/file asset filename: ${filename}`)
}
}
/**
* Parses a full Sanity asset URL into individual parts
* (type, project ID, dataset, id, extension, width, height)
*
* @param url - Full URL to parse into named parts
* @returns Object of named properties
* @public
* @throws If URL is invalid or not a Sanity asset URL
*/
export function parseAssetUrl(url: string): SanityAssetUrlParts {
if (!isCdnUrl(url)) {
throw new Error(`URL is not a valid Sanity asset URL: ${url}`)
}
const path = new URL(url).pathname.replace(/^\/+/, '')
const [projectPath, , projectId, dataset] = path.match(pathPattern) || []
if (!projectPath || !projectId || !dataset) {
throw new Error(`URL is not a valid Sanity asset URL: ${url}`)
}
const [filename, vanityFilename] = path.slice(projectPath.length).split('/')
const parsed = parseAssetFilename(filename)
return {
...parsed,
projectId,
dataset,
vanityFilename,
}
}
/**
* Parses a full Sanity image asset URL into individual parts
* (type, project ID, dataset, id, extension, width, height)
*
* @param url - Full URL to parse into named parts
* @returns Object of named properties
* @public
* @throws If URL is invalid or not a Sanity image asset URL
*/
export function parseImageAssetUrl(url: string): SanityImageUrlParts {
const parsed = parseAssetUrl(url)
if (parsed.type !== 'image') {
throw new Error(`URL is not a valid Sanity image asset URL: ${url}`)
}
return parsed
}
/**
* Parses a full Sanity file asset URL into individual parts
* (type, project ID, dataset, id, extension, width, height)
*
* @param url - Full URL to parse into named parts
* @returns Object of named properties
* @public
* @throws If URL is invalid or not a Sanity file asset URL
*/
export function parseFileAssetUrl(url: string): SanityFileUrlParts {
const parsed = parseAssetUrl(url)
if (parsed.type !== 'file') {
throw new Error(`URL is not a valid Sanity file asset URL: ${url}`)
}
return parsed
}
/**
* Validates that a given URL is a Sanity asset URL, and returns the asset type if valid.
*
* @param url - URL to extract asset type from
* @returns Asset type if valid URL, false otherwise
* @public
*/
export function getAssetUrlType(url: string): 'image' | 'file' | false {
try {
return parseAssetUrl(url).type
} catch (err) {
return false
}
}