|
- const MULTIPLE_VALID_MIME_TYPE_DELIMITER = ' '
- const CATCH_ALL_MIME_TYPES = ['*', '*/*']
- const MIME_TYPE_FORMAT_DELIMITER = '/'
-
- // catch-all for format, e.g. "image/*" matches all MIME types starting with "image/"
- const MIME_TYPE_FORMAT_CATCH_ALL = '*'
-
- export type IsValidMimeTypeConfig = {
- validMimeTypes: string | string[]
- }
-
- type IsValidMimeType = (config: IsValidMimeTypeConfig) => (mimeType: string) => boolean
-
- const isValidMimeType: IsValidMimeType = config => {
- let validMimeTypes: string[]
- const maybeValidMimeTypes = config.validMimeTypes as unknown
- if (typeof maybeValidMimeTypes === 'string') {
- validMimeTypes = (config.validMimeTypes as string)
- .split(MULTIPLE_VALID_MIME_TYPE_DELIMITER)
- .filter(p => p.trim().length > 0)
- } else if (
- Array.isArray(maybeValidMimeTypes)
- && (config.validMimeTypes as unknown[]).every(s => typeof s === 'string')
- ) {
- if ((config.validMimeTypes as unknown[]).length < 1) {
- throw RangeError('There must be at least 1 valid extension defined.')
- }
- validMimeTypes = config.validMimeTypes as string[]
- } else {
- throw TypeError('Valid MimeTypes should be a space-delimited string or a string array.')
- }
-
- return mimeType => {
- if (typeof mimeType as unknown !== 'string') {
- throw TypeError('Argument should be a string.')
- }
-
- // short-circuit valid MIME types that are catch-all
- if (validMimeTypes.some(a => CATCH_ALL_MIME_TYPES.includes(a))) {
- return true
- }
-
- return (
- validMimeTypes.reduce<boolean>(
- (isValid, validMimeType) => {
- const [type, format] = validMimeType.split(MIME_TYPE_FORMAT_DELIMITER)
-
- // maybe short circuit matching format catch-all valid MIME types?
- if (format === MIME_TYPE_FORMAT_CATCH_ALL) {
- return isValid || mimeType.startsWith(type + MIME_TYPE_FORMAT_DELIMITER)
- }
-
- return isValid || mimeType === validMimeType
- },
- false,
- )
- )
- }
- }
-
- export default isValidMimeType
|