expo-image-manipulator
Version:
Provides functions that let you manipulation images on the local file system, eg: resize, crop.
135 lines (124 loc) • 4.61 kB
text/typescript
import {
Action,
ActionCrop,
ActionExtent,
ActionFlip,
ActionResize,
ActionRotate,
FlipType,
SaveFormat,
SaveOptions,
} from './ImageManipulator.types';
export function validateArguments(uri: string, actions: Action[], saveOptions: SaveOptions) {
validateUri(uri);
validateActions(actions);
validateSaveOptions(saveOptions);
}
export function validateUri(uri: string): void {
if (!(typeof uri === 'string')) {
throw new TypeError('The "uri" argument must be a string');
}
}
export function validateActions(actions: Action[]): void {
if (!Array.isArray(actions)) {
throw new TypeError('The "actions" argument must be an array');
}
for (const action of actions) {
if (typeof action !== 'object' || action === null) {
throw new TypeError('Action must be an object');
}
const supportedActionTypes = ['crop', 'extent', 'flip', 'rotate', 'resize'];
const actionKeys = Object.keys(action);
if (actionKeys.length !== 1) {
throw new TypeError(
`Single action must contain exactly one transformation: ${supportedActionTypes.join(', ')}`
);
}
const actionType = actionKeys[0];
if (!supportedActionTypes.includes(actionType)) {
throw new TypeError(`Unsupported action type: ${actionType}`);
}
if (actionType === 'crop') {
validateCropAction(action as ActionCrop);
} else if (actionType === 'extent') {
validateExtentAction(action as ActionExtent);
} else if (actionType === 'flip') {
validateFlipAction(action as ActionFlip);
} else if (actionType === 'rotate') {
validateRotateAction(action as ActionRotate);
} else if (actionType === 'resize') {
validateResizeAction(action as ActionResize);
}
}
}
function validateCropAction(action: ActionCrop): void {
const isValid =
typeof action.crop === 'object' &&
action.crop !== null &&
typeof action.crop.originX === 'number' &&
typeof action.crop.originY === 'number' &&
typeof action.crop.width === 'number' &&
typeof action.crop.height === 'number';
if (!isValid) {
throw new TypeError(
'Crop action must be an object of shape { originX: number; originY: number; width: number; height: number }'
);
}
}
function validateExtentAction(action: ActionExtent): void {
const isValid =
typeof action.extent === 'object' &&
action.extent !== null &&
(action.extent.backgroundColor == null || typeof action.extent.backgroundColor === 'string') &&
(action.extent.originX == null || typeof action.extent.originX === 'number') &&
(action.extent.originY == null || typeof action.extent.originY === 'number') &&
typeof action.extent.width === 'number' &&
typeof action.extent.height === 'number';
if (!isValid) {
throw new TypeError(
'Extent action must be an object of shape { backgroundColor?: string; originX?: number; originY?: number; width: number; height: number }'
);
}
}
function validateFlipAction(action: ActionFlip): void {
if (
typeof action.flip !== 'string' ||
![FlipType.Horizontal, FlipType.Vertical].includes(action.flip)
) {
throw new TypeError(`Unsupported flip type: ${action.flip}`);
}
}
function validateRotateAction(action: ActionRotate): void {
if (typeof action.rotate !== 'number') {
throw new TypeError('Rotation must be a number');
}
}
function validateResizeAction(action: ActionResize): void {
const isValid =
typeof action.resize === 'object' &&
action.resize !== null &&
(typeof action.resize.width === 'number' || typeof action.resize.width === 'undefined') &&
(typeof action.resize.height === 'number' || typeof action.resize.height === 'undefined');
if (!isValid) {
throw new TypeError(
'Resize action must be an object of shape { width?: number; height?: number }'
);
}
}
export function validateSaveOptions({ base64, compress, format }: SaveOptions): void {
if (base64 !== undefined && typeof base64 !== 'boolean') {
throw new TypeError('The "base64" argument must be a boolean');
}
if (compress !== undefined) {
if (typeof compress !== 'number') {
throw new TypeError('The "compress" argument must be a number');
}
if (compress < 0 || compress > 1) {
throw new TypeError('The "compress" argument must be a number between 0 and 1');
}
}
const allowedFormats = [SaveFormat.JPEG, SaveFormat.PNG, SaveFormat.WEBP];
if (format !== undefined && !allowedFormats.includes(format)) {
throw new TypeError(`The "format" argument must be one of: ${allowedFormats.join(', ')}`);
}
}