type FileMetadata = { // original name name: string; extension: string; // mime type type: string; size: number; encoding: 'text' | 'base64' | 'binary'; }; export type FileMetadataPrivate = FileMetadata & Readonly<{ $superblocksId: string; }>; type FileConstructorArgs = FileMetadata & { // We should consider supporting Blobs & Buffers for streaming file // contents contents: string; }; // TODO [ro] the encoding seems wrong. // The following is an example of readable file from temp location // This is the file objects returned by FilePicker.files // { // "name": "small.png", // "extension": "png", // "type": "image/png", // "size": 5704, // "encoding": "text", // "$superblocksId": "uppy-small_png-1e-image_png-5704-1674601389293" // } export function isReadableFile(f: unknown): f is FileMetadataPrivate { if (!f || typeof f !== 'object' || Array.isArray(f)) { return false; } const entries = Object.entries(f as Record); if (entries.length === 0) { return false; } return Object.entries(f as Record).every(([key, value]) => { switch (key) { case 'name': case 'extension': case 'type': case 'encoding': case '$superblocksId': return typeof value === 'string'; case 'size': return typeof value === 'number'; case 'previewUrl': case 'path': return typeof value === 'string' || typeof value === 'undefined'; default: return false; } }); } // This is used to determine if the object is a valid custom file object // it has to have name, contents, and type export function isReadableFileConstructor(f: unknown): f is FileConstructorArgs { if (!f || typeof f !== 'object') { return false; } return Object.entries(f as Record).every(([key, value]) => { switch (key) { case 'name': case 'contents': // @ts-ignore contents might be string or Buffer.toJSON() // Buffer.toJSON() is determined by 'type' === 'Buffer' // This supports passing Buffer to contents // { // name: 'filename', // contents: {{Step2.output}}, // type: 'filetype // } return typeof value === 'string' || value['type'] === 'Buffer'; case 'type': return typeof value === 'string'; default: return false; } }); }