chonky
Version:
A File Browser component for React
108 lines (98 loc) • 3.86 kB
text/typescript
import { Nullable } from 'tsdef';
import { FileAction } from '../types/action.types';
import { FileArray } from '../types/file.types';
import { Logger } from '../util/logger';
interface SanitizeFiles {
(mode: 'files', rawArray: FileArray | any): {
sanitizedArray: FileArray;
errorMessages: string[];
};
(mode: 'folderChain', rawArray: Nullable<FileArray> | any): {
sanitizedArray: FileArray;
errorMessages: string[];
};
(mode: 'fileActions', rawArray: FileAction[] | any): {
sanitizedArray: FileAction[];
errorMessages: string[];
};
}
export const sanitizeInputArray: SanitizeFiles = (mode: string, rawArray: any[]) => {
const sanitizedFiles = [];
const errorMessages: string[] = [];
if ((mode === 'folderChain' || mode === 'fileActions') && !rawArray) {
// Do nothing, we allow folder chain to be null.
} else if (!Array.isArray(rawArray)) {
errorMessages.push(
`Expected "${mode}" prop to be an array, got "${typeof rawArray}" instead.`
);
} else {
let nonObjectFileCount = 0;
let missingFieldFileCount = 0;
const seenIds = new Set<string>();
const duplicateIds = new Set<string>();
for (let i = 0; i < rawArray.length; ++i) {
const item = rawArray[i];
if (!item) {
if (mode === 'fileActions') nonObjectFileCount++;
else sanitizedFiles.push(null);
} else if (typeof item !== 'object') {
nonObjectFileCount++;
} else {
if (!item.id || (mode !== 'fileActions' && !item.name)) {
missingFieldFileCount++;
} else if (seenIds.has(item.id)) {
duplicateIds.add(item.id);
} else {
seenIds.add(item.id);
sanitizedFiles.push(item);
}
}
}
if (nonObjectFileCount) {
errorMessages.push(
`Detected ${nonObjectFileCount} file(s) of invalid type. Remember ` +
`that "files" array should contain either objects or nulls.`
);
}
if (missingFieldFileCount) {
errorMessages.push(
`Detected ${missingFieldFileCount} file(s) that are missing the ` +
`required fields. Remember that file object should define an ` +
`"id" and a "name".`
);
}
if (duplicateIds.size > 0) {
const repeatedIdsString = '"' + Array.from(duplicateIds).join('", "') + '"';
errorMessages.push(
`Detected ${duplicateIds.size} file IDs that are used multiple ` +
`times. Remember that each file should have a unique IDs. The ` +
`following IDs were seen multiple times: ${repeatedIdsString}`
);
}
}
if (errorMessages.length > 0) {
const errorMessageString = '\n- ' + errorMessages.join('\n- ');
let arrayString: string;
let itemString: string;
if (mode === 'folderChain') {
arrayString = 'folder chain';
itemString = 'files';
} else if (mode === 'fileActions') {
arrayString = 'file actions';
itemString = 'file actions';
} else {
// mode === 'files'
arrayString = 'files';
itemString = 'files';
}
Logger.error(
`Errors were detected when sanitizing the ${arrayString} array. ` +
`Offending ${itemString} were removed from the array. Summary of ` +
`validation errors: ${errorMessageString}`
);
}
return {
sanitizedArray: sanitizedFiles,
errorMessages,
};
};