Browse Source

@uppy/compressor: migrate to TS (#4907)

* refactor compressor to ts

* rename Options

* export opts
Mikael Finstad 1 year ago
parent
commit
6b4f5b68f7

+ 24 - 6
packages/@uppy/compressor/src/index.test.js → packages/@uppy/compressor/src/index.test.ts

@@ -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', () => {

+ 41 - 14
packages/@uppy/compressor/src/index.js → packages/@uppy/compressor/src/index.ts

@@ -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)
   }
 }

+ 0 - 0
packages/@uppy/compressor/src/locale.js → packages/@uppy/compressor/src/locale.ts


+ 25 - 0
packages/@uppy/compressor/tsconfig.build.json

@@ -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 - 0
packages/@uppy/compressor/tsconfig.json

@@ -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",
+    },
+  ],
+}

+ 1 - 1
packages/@uppy/utils/src/FileProgress.ts

@@ -5,7 +5,7 @@ export interface DeterminateFileProcessing {
 }
 export interface IndeterminateFileProcessing {
   mode: 'indeterminate'
-  message?: undefined
+  message?: string
   value?: 0
 }
 export type FileProcessingInfo =