mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-17 16:50:22 +00:00
@uppy/compressor: migrate to TS (#4907)
* refactor compressor to ts * rename Options * export opts
This commit is contained in:
parent
2e93ba8b48
commit
6b4f5b68f7
6 changed files with 112 additions and 21 deletions
|
|
@ -3,10 +3,11 @@ import Core from '@uppy/core'
|
|||
import getFileNameAndExtension from '@uppy/utils/lib/getFileNameAndExtension'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import CompressorPlugin from './index.js'
|
||||
import CompressorPlugin from './index.ts'
|
||||
|
||||
// Compressor uses browser canvas API, so need to mock compress()
|
||||
CompressorPlugin.prototype.compress = (blob) => {
|
||||
// @ts-expect-error mocked
|
||||
CompressorPlugin.prototype.compress = async (blob: Blob) => {
|
||||
return {
|
||||
name: `${getFileNameAndExtension(blob.name).name}.webp`,
|
||||
type: 'image/webp',
|
||||
|
|
@ -16,11 +17,28 @@ CompressorPlugin.prototype.compress = (blob) => {
|
|||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const sampleImage = fs.readFileSync(path.join(__dirname, '../../../../e2e/cypress/fixtures/images/image.jpg'))
|
||||
const sampleImage = fs.readFileSync(
|
||||
path.join(__dirname, '../../../../e2e/cypress/fixtures/images/image.jpg'),
|
||||
)
|
||||
|
||||
const file1 = { source: 'jest', name: 'image-1.jpeg', type: 'image/jpeg', data: new File([sampleImage], 'image-1.jpeg', { type: 'image/jpeg' }) }
|
||||
const file2 = { source: 'jest', name: 'yolo', type: 'image/jpeg', data: new File([sampleImage], 'yolo', { type: 'image/jpeg' }) }
|
||||
const file3 = { source: 'jest', name: 'my.file.is.weird.png', type: 'image/png', data: new File([sampleImage], 'my.file.is.weird.png', { type: 'image/png' }) }
|
||||
const file1 = {
|
||||
source: 'jest',
|
||||
name: 'image-1.jpeg',
|
||||
type: 'image/jpeg',
|
||||
data: new File([sampleImage], 'image-1.jpeg', { type: 'image/jpeg' }),
|
||||
}
|
||||
const file2 = {
|
||||
source: 'jest',
|
||||
name: 'yolo',
|
||||
type: 'image/jpeg',
|
||||
data: new File([sampleImage], 'yolo', { type: 'image/jpeg' }),
|
||||
}
|
||||
const file3 = {
|
||||
source: 'jest',
|
||||
name: 'my.file.is.weird.png',
|
||||
type: 'image/png',
|
||||
data: new File([sampleImage], 'my.file.is.weird.png', { type: 'image/png' }),
|
||||
}
|
||||
|
||||
describe('CompressorPlugin', () => {
|
||||
it('should change update extension in file.name and file.meta.name', () => {
|
||||
|
|
@ -1,14 +1,34 @@
|
|||
import { BasePlugin } from '@uppy/core'
|
||||
import { BasePlugin, Uppy } from '@uppy/core'
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { RateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue'
|
||||
import getFileNameAndExtension from '@uppy/utils/lib/getFileNameAndExtension'
|
||||
import prettierBytes from '@transloadit/prettier-bytes'
|
||||
import CompressorJS from 'compressorjs'
|
||||
import locale from './locale.js'
|
||||
|
||||
export default class Compressor extends BasePlugin {
|
||||
import type { Body, Meta, UppyFile } from '@uppy/utils/lib/UppyFile'
|
||||
import type { PluginOpts } from '@uppy/core/lib/BasePlugin.ts'
|
||||
|
||||
import locale from './locale.ts'
|
||||
|
||||
declare module '@uppy/core' {
|
||||
export interface UppyEventMap<M extends Meta, B extends Body> {
|
||||
'compressor:complete': (file: UppyFile<M, B>[]) => void
|
||||
}
|
||||
}
|
||||
|
||||
export interface CompressorOpts extends PluginOpts, CompressorJS.Options {
|
||||
quality: number
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export default class Compressor<
|
||||
M extends Meta,
|
||||
B extends Body,
|
||||
> extends BasePlugin<CompressorOpts, M, B> {
|
||||
#RateLimitedQueue
|
||||
|
||||
constructor (uppy, opts) {
|
||||
constructor(uppy: Uppy<M, B>, opts: CompressorOpts) {
|
||||
super(uppy, opts)
|
||||
this.id = this.opts.id || 'Compressor'
|
||||
this.type = 'modifier'
|
||||
|
|
@ -30,7 +50,7 @@ export default class Compressor extends BasePlugin {
|
|||
this.compress = this.compress.bind(this)
|
||||
}
|
||||
|
||||
compress (blob) {
|
||||
compress(blob: Blob): Promise<Blob | File> {
|
||||
return new Promise((resolve, reject) => {
|
||||
/* eslint-disable no-new */
|
||||
new CompressorJS(blob, {
|
||||
|
|
@ -41,15 +61,17 @@ export default class Compressor extends BasePlugin {
|
|||
})
|
||||
}
|
||||
|
||||
async prepareUpload (fileIDs) {
|
||||
async prepareUpload(fileIDs: string[]): Promise<void> {
|
||||
let totalCompressedSize = 0
|
||||
const compressedFiles = []
|
||||
const compressedFiles: UppyFile<M, B>[] = []
|
||||
const compressAndApplyResult = this.#RateLimitedQueue.wrapPromiseFunction(
|
||||
async (file) => {
|
||||
async (file: UppyFile<M, B>) => {
|
||||
try {
|
||||
const compressedBlob = await this.compress(file.data)
|
||||
const compressedSavingsSize = file.data.size - compressedBlob.size
|
||||
this.uppy.log(`[Image Compressor] Image ${file.id} compressed by ${prettierBytes(compressedSavingsSize)}`)
|
||||
this.uppy.log(
|
||||
`[Image Compressor] Image ${file.id} compressed by ${prettierBytes(compressedSavingsSize)}`,
|
||||
)
|
||||
totalCompressedSize += compressedSavingsSize
|
||||
const { name, type, size } = compressedBlob
|
||||
|
||||
|
|
@ -61,7 +83,9 @@ export default class Compressor extends BasePlugin {
|
|||
|
||||
this.uppy.setFileState(file.id, {
|
||||
...(name && { name }),
|
||||
...(compressedFileName.extension && { extension: compressedFileName.extension }),
|
||||
...(compressedFileName.extension && {
|
||||
extension: compressedFileName.extension,
|
||||
}),
|
||||
...(type && { type }),
|
||||
...(size && { size }),
|
||||
data: compressedBlob,
|
||||
|
|
@ -73,7 +97,10 @@ export default class Compressor extends BasePlugin {
|
|||
})
|
||||
compressedFiles.push(file)
|
||||
} catch (err) {
|
||||
this.uppy.log(`[Image Compressor] Failed to compress ${file.id}:`, 'warning')
|
||||
this.uppy.log(
|
||||
`[Image Compressor] Failed to compress ${file.id}:`,
|
||||
'warning',
|
||||
)
|
||||
this.uppy.log(err, 'warning')
|
||||
}
|
||||
},
|
||||
|
|
@ -97,7 +124,7 @@ export default class Compressor extends BasePlugin {
|
|||
file.data = file.data.slice(0, file.data.size, file.type)
|
||||
}
|
||||
|
||||
if (!file.type.startsWith('image/')) {
|
||||
if (!file.type?.startsWith('image/')) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
|
|
@ -128,11 +155,11 @@ export default class Compressor extends BasePlugin {
|
|||
}
|
||||
}
|
||||
|
||||
install () {
|
||||
install(): void {
|
||||
this.uppy.addPreProcessor(this.prepareUpload)
|
||||
}
|
||||
|
||||
uninstall () {
|
||||
uninstall(): void {
|
||||
this.uppy.removePreProcessor(this.prepareUpload)
|
||||
}
|
||||
}
|
||||
25
packages/@uppy/compressor/tsconfig.build.json
Normal file
25
packages/@uppy/compressor/tsconfig.build.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.shared",
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": false,
|
||||
"outDir": "./lib",
|
||||
"paths": {
|
||||
"@uppy/utils/lib/*": ["../utils/src/*"],
|
||||
"@uppy/core": ["../core/src/index.js"],
|
||||
"@uppy/core/lib/*": ["../core/src/*"]
|
||||
},
|
||||
"resolveJsonModule": false,
|
||||
"rootDir": "./src",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["./src/**/*.*"],
|
||||
"exclude": ["./src/**/*.test.ts"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../utils/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../core/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
packages/@uppy/compressor/tsconfig.json
Normal file
21
packages/@uppy/compressor/tsconfig.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.shared",
|
||||
"compilerOptions": {
|
||||
"emitDeclarationOnly": false,
|
||||
"noEmit": true,
|
||||
"paths": {
|
||||
"@uppy/utils/lib/*": ["../utils/src/*"],
|
||||
"@uppy/core": ["../core/src/index.js"],
|
||||
"@uppy/core/lib/*": ["../core/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["./package.json", "./src/**/*.*"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../utils/tsconfig.build.json",
|
||||
},
|
||||
{
|
||||
"path": "../core/tsconfig.build.json",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ export interface DeterminateFileProcessing {
|
|||
}
|
||||
export interface IndeterminateFileProcessing {
|
||||
mode: 'indeterminate'
|
||||
message?: undefined
|
||||
message?: string
|
||||
value?: 0
|
||||
}
|
||||
export type FileProcessingInfo =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue