Skip to content

Commit

Permalink
feat: add new file utils
Browse files Browse the repository at this point in the history
  • Loading branch information
altaywtf committed Sep 11, 2024
1 parent d0dbc13 commit c69d22c
Show file tree
Hide file tree
Showing 12 changed files with 487 additions and 11 deletions.
113 changes: 113 additions & 0 deletions src/file/file-render-type.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { getFileRenderType, FileRenderType } from './file-render-type';

Check warning on line 1 in src/file/file-render-type.spec.ts

View workflow job for this annotation

GitHub Actions / build

'FileRenderType' is defined but never used
import type { IFile } from '@putdotio/api-client';

const baseFile: IFile = {
id: 1,
parent_id: 1,
name: 'test',
size: 100,
extension: 'txt',
file_type: 'TEXT',
content_type: 'text/plain',
crc32: '1234567890',
created_at: '2021-01-01T00:00:00Z',
};

describe('getFileRenderType', () => {
it('should return "folder" for directories', () => {
const file: IFile = {
...baseFile,
content_type: 'application/x-directory',
file_type: 'FOLDER',
};
expect(getFileRenderType(file)).toBe('folder');
});

it('should return "audio" for audio files', () => {
const file: IFile = {
...baseFile,
content_type: 'audio/mpeg',
file_type: 'AUDIO',
};
expect(getFileRenderType(file)).toBe('audio');
});

it('should return "video" for video files', () => {
const file: IFile = {
...baseFile,
content_type: 'video/mp4',
file_type: 'VIDEO',
};
expect(getFileRenderType(file)).toBe('video');
});

it('should return "text/markdown" for markdown files', () => {
const file: IFile = {
...baseFile,
content_type: 'text/markdown',
extension: 'md',
file_type: 'TEXT',
};
expect(getFileRenderType(file)).toBe('text/markdown');
});

it('should return "text" for text files', () => {
const file: IFile = {
...baseFile,
content_type: 'text/plain',
file_type: 'TEXT',
};
expect(getFileRenderType(file)).toBe('text');
});

it('should return "image" for image files', () => {
const file: IFile = {
...baseFile,
content_type: 'image/jpeg',
file_type: 'IMAGE',
};
expect(getFileRenderType(file)).toBe('image');
});

it('should return "pdf" for PDF files', () => {
const file: IFile = {
...baseFile,
content_type: 'application/pdf',
file_type: 'PDF',
};
expect(getFileRenderType(file)).toBe('pdf');
});

it('should return "archive" for archive files', () => {
const file: IFile = {
...baseFile,
content_type: 'application/zip',
file_type: 'ARCHIVE',
};
expect(getFileRenderType(file)).toBe('archive');
});

it('should return "epub" for EPUB files', () => {
const file: IFile = {
...baseFile,
content_type: 'application/epub+zip',
};
expect(getFileRenderType(file)).toBe('epub');
});

it('should return "other" for unknown file types', () => {
const file: IFile = {
...baseFile,
content_type: 'application/octet-stream',
};
expect(getFileRenderType(file)).toBe('other');
});

it('should return "other" if content_type is not a string', () => {
const file: IFile = {
...baseFile,
content_type: null as any,
};
expect(getFileRenderType(file)).toBe('other');
});
});
58 changes: 58 additions & 0 deletions src/file/file-render-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { IFile } from '@putdotio/api-client';

export type FileRenderType =
| 'archive'
| 'audio'
| 'epub'
| 'folder'
| 'image'
| 'other'
| 'pdf'
| 'text'
| 'text/markdown'
| 'video';

export const getFileRenderType = (file: IFile): FileRenderType => {
const { content_type, extension, file_type } = file;

if (typeof content_type !== 'string') {
return 'other';
}

if (content_type === 'application/x-directory') {
return 'folder';
}

if (content_type.startsWith('audio') || file_type === 'AUDIO') {
return 'audio';
}

if (content_type.startsWith('video')) {
return 'video';
}

if (content_type.startsWith('text')) {
if (content_type.endsWith('/markdown') || extension === 'md') {
return 'text/markdown';
}
return 'text';
}

if (content_type.startsWith('image')) {
return 'image';
}

if (content_type === 'application/pdf') {
return 'pdf';
}

if (['application/x-rar', 'application/zip'].includes(content_type)) {
return 'archive';
}

if (content_type === 'application/epub+zip') {
return 'epub';
}

return 'other';
};
4 changes: 2 additions & 2 deletions src/file/file.spec.ts → src/file/file-size.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toHumanFileSize } from './file';
import { toHumanFileSize } from './file-size';

describe('files', () => {
describe('file-size', () => {
describe('toHumanFileSize', () => {
it('should convert bytes to human readable format', () => {
expect(toHumanFileSize(1024)).toBe('1 KB');
Expand Down
File renamed without changes.
203 changes: 203 additions & 0 deletions src/file/file-url-provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import type { IFile } from '@putdotio/api-client';

import { FileURLProvider } from './file-url-provider';
import { getFileRenderType } from './file-render-type';

jest.mock('./file-render-type');

const apiURL = 'https://api.example.com';
const token = 'test-token';
let provider: FileURLProvider;

const baseFile: IFile = {
id: 1,
parent_id: 1,
name: 'test',
size: 100,
extension: 'txt',
file_type: 'TEXT',
content_type: 'text/plain',
crc32: '1234567890',
created_at: '2021-01-01T00:00:00Z',
};

beforeEach(() => {
provider = new FileURLProvider(apiURL, token);
});

const mockFileRenderType = (type: string) => {
(getFileRenderType as jest.Mock).mockReturnValue(type);
};

describe('FileURLProvider', () => {
describe('getDownloadURL', () => {
it('should return download URL for file ID', () => {
const fileId = 123;
const url = provider.getDownloadURL(fileId);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/123/download?oauth_token=test-token"`
);
});

it('should return null for folder type', () => {
const file: IFile = {
...baseFile,
file_type: 'FOLDER',
};
const url = provider.getDownloadURL(file);
expect(url).toBeNull();
});

it('should return download URL for file object', () => {
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
};
const url = provider.getDownloadURL(file);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/download?oauth_token=test-token"`
);
});
});

describe('getHLSStreamURL', () => {
it('should return null if file is not a video', () => {
mockFileRenderType('audio');
const file: IFile = {
...baseFile,
file_type: 'AUDIO',
};
const url = provider.getHLSStreamURL(file, {});
expect(url).toBeNull();
});

it('should return HLS stream URL with parameters', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
};
const params = {
playOriginal: true,
subtitleLanguages: ['en', 'es'],
maxSubtitleCount: 2,
};
const url = provider.getHLSStreamURL(file, params);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/hls/media.m3u8?oauth_token=test-token&original=1&subtitle_languages=en%2Ces&max_subtitle_count=2"`
);
});
});

describe('getMP4DownloadURL', () => {
it('should return null if file is not a video', () => {
mockFileRenderType('audio');
const file: IFile = {
...baseFile,
file_type: 'AUDIO',
};
const url = provider.getMP4DownloadURL(file);
expect(url).toBeNull();
});

it('should return null if MP4 is not available', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
is_mp4_available: false,
parent_id: 0,
name: 'test.mp4',
size: 1024,
content_type: 'video/mp4',
};
const url = provider.getMP4DownloadURL(file);
expect(url).toBeNull();
});

it('should return MP4 download URL if MP4 is available', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
is_mp4_available: true,
};
const url = provider.getMP4DownloadURL(file);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/mp4/download?oauth_token=test-token"`
);
});
});

describe('getMP4StreamURL', () => {
it('should return null if file is not a video', () => {
mockFileRenderType('audio');
const file: IFile = {
...baseFile,
file_type: 'AUDIO',
};
const url = provider.getMP4StreamURL(file);
expect(url).toBeNull();
});

it('should return null if MP4 is not available', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
is_mp4_available: false,
};
const url = provider.getMP4StreamURL(file);
expect(url).toBeNull();
});

it('should return MP4 stream URL if MP4 is available', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
is_mp4_available: true,
};
const url = provider.getMP4StreamURL(file);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/mp4/stream?oauth_token=test-token"`
);
});
});

describe('getStreamURL', () => {
it('should return audio stream URL for audio file', () => {
mockFileRenderType('audio');
const file: IFile = {
...baseFile,
file_type: 'AUDIO',
};
const url = provider.getStreamURL(file);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/stream.mp3?oauth_token=test-token"`
);
});

it('should return video stream URL for video file', () => {
mockFileRenderType('video');
const file: IFile = {
...baseFile,
file_type: 'VIDEO',
};
const url = provider.getStreamURL(file);
expect(url).toMatchInlineSnapshot(
`"https://api.example.com/v2/files/1/stream?oauth_token=test-token"`
);
});

it('should return null for unsupported file type', () => {
mockFileRenderType('archive');
const file: IFile = {
...baseFile,
file_type: 'ARCHIVE',
};
const url = provider.getStreamURL(file);
expect(url).toBeNull();
});
});
});
Loading

0 comments on commit c69d22c

Please sign in to comment.