Skip to content

Commit

Permalink
chore:pretty type (nonzzz#40)
Browse files Browse the repository at this point in the history
* chore:pretty type

* chore:pretty type

* feat: algorithm using promise

* fix: compress fn

* fix: fix opt type

* chore: make test happy

---------

Co-authored-by: kanno <[email protected]>
  • Loading branch information
mengdaoshizhongxinyang and nonzzz authored Sep 28, 2023
1 parent 6bab2ad commit 7db5d17
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 46 deletions.
12 changes: 6 additions & 6 deletions __tests__/compress.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { Buffer } from 'buffer'
import test from 'ava'
import { ensureAlgorithm, transfer } from '../src/compress'
import { compress, ensureAlgorithm } from '../src/compress'
import type { Algorithm } from '../src/interface'

const mockTransfer = async (userAlgorithm: Algorithm, buf: Buffer) => {
const mockCompress = async (userAlgorithm: Algorithm, buf: Buffer) => {
const { algorithm } = ensureAlgorithm(userAlgorithm)
return transfer(buf, algorithm, {})
return compress(buf, algorithm, {})
}

test('transer', async (t) => {
const fake = Buffer.alloc(4, 'test')
await mockTransfer('gzip', fake)
await mockCompress('gzip', fake)
t.pass()
})

test('transfer with error', async (t) => {
test('compress with error', async (t) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const msg = await t.throwsAsync(mockTransfer('gzip', 123 as any))
const msg = await t.throwsAsync(mockCompress('gzip', 123 as any))
t.is(
msg.message,
'The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received type number (123)'
Expand Down
4 changes: 2 additions & 2 deletions __tests__/options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import path from 'path'
import fsp from 'fs/promises'
import test from 'ava'
import { build } from 'vite'
import type { ViteCompressionPluginConfigAlgorithm } from '../src/interface'
import type { Pretty, ViteCompressionPluginConfigAlgorithm } from '../src/interface'
import { compression } from '../src'
import { readAll } from '../src/utils'
import type { Algorithm } from '../src'
Expand All @@ -11,7 +11,7 @@ const getId = () => Math.random().toString(32).slice(2, 10)
const sleep = (delay: number) => new Promise((resolve) => setTimeout(resolve, delay))

async function mockBuild<T extends Algorithm = never>(
conf: ViteCompressionPluginConfigAlgorithm<T>,
conf: Pretty<ViteCompressionPluginConfigAlgorithm<T>>,
dir: string,
single = false
) {
Expand Down
5 changes: 3 additions & 2 deletions __tests__/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path'
import zlib, { BrotliOptions } from 'zlib'
import fs from 'fs'
import fsp from 'fs/promises'
import util from 'util'
import type { ZlibOptions } from 'zlib'
import test from 'ava'
import { build } from 'vite'
Expand Down Expand Up @@ -96,8 +97,8 @@ test('algorithm', async (t) => {

test('custom alorithm', async (t) => {
const id = await mockBuild<ZlibOptions>({
algorithm(buf, opt, invoke) {
return zlib.gzip(buf, opt, invoke)
algorithm(buf, opt) {
return util.promisify(zlib.gzip)(buf, opt)
},
compressionOptions: {
level: 9
Expand Down
32 changes: 13 additions & 19 deletions src/compress.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import zlib from 'zlib'
import util from 'util'
import type { BrotliOptions, ZlibOptions } from 'zlib'
import type { Algorithm, AlgorithmFunction, CompressionOptions } from './interface'
import type { Algorithm, AlgorithmFunction, UserCompressionOptions } from './interface'

export function ensureAlgorithm(userAlgorithm: Algorithm) {
const algorithm = userAlgorithm in zlib ? userAlgorithm : 'gzip'
return {
algorithm: zlib[algorithm]
algorithm: util.promisify(zlib[algorithm])
}
}

export function transfer<T>(
export async function compress<T extends UserCompressionOptions | undefined>(
buf: Buffer,
compress: AlgorithmFunction<T>,
options: CompressionOptions<T>
): Promise<Buffer> {
return new Promise((resolve, reject) => {
compress(buf, options, (err, bf) => {
if (err) {
reject(err)
return
}

if (!Buffer.isBuffer(bf)) {
resolve(Buffer.from(bf))
} else {
resolve(bf)
}
})
})
options: T
) {
try {
const res = await compress(buf, options)
if (Buffer.isBuffer(res)) return res
return Buffer.from(res as any)
} catch (error) {
return Promise.reject(error)
}
}

export const defaultCompressionOptions: {
Expand Down
23 changes: 12 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import path from 'path'
import { createFilter } from '@rollup/pluginutils'
import type { Plugin, ResolvedConfig } from 'vite'
import { len, readAll, replaceFileName, slash } from './utils'
import { defaultCompressionOptions, ensureAlgorithm, transfer } from './compress'
import { compress, defaultCompressionOptions, ensureAlgorithm } from './compress'
import { createConcurrentQueue } from './task'
import type {
Algorithm,
AlgorithmFunction,
CompressMetaInfo,
CompressionOptions,
Pretty,
UserCompressionOptions,
ViteCompressionPluginConfig,
ViteCompressionPluginConfigAlgorithm,
ViteCompressionPluginConfigFunction
ViteCompressionPluginConfigFunction,
ViteWithoutCompressionPluginConfigFunction
} from './interface'

const VITE_COPY_PUBLIC_DIR = 'copyPublicDir'
Expand Down Expand Up @@ -64,9 +65,10 @@ function makeOutputs(outputs: Set<OutputOption>, file: string) {
}

function compression(): Plugin
function compression<A extends Algorithm>(opts: ViteCompressionPluginConfigAlgorithm<A>): Plugin
function compression<T = UserCompressionOptions>(opts: ViteCompressionPluginConfigFunction<T>): Plugin
function compression<T, A extends Algorithm>(opts: ViteCompressionPluginConfig<T, A> = {}): Plugin {
function compression<A extends Algorithm>(opts: Pretty<ViteCompressionPluginConfigAlgorithm<A>>): Plugin
function compression<T extends UserCompressionOptions = NonNullable<unknown>>(opts: Pretty<ViteCompressionPluginConfigFunction<T>>): Plugin
function compression(opts: ViteWithoutCompressionPluginConfigFunction): Plugin
function compression<T extends UserCompressionOptions, A extends Algorithm>(opts: ViteCompressionPluginConfig<T, A> = {}): Plugin {
const {
include,
exclude,
Expand All @@ -87,12 +89,11 @@ function compression<T, A extends Algorithm>(opts: ViteCompressionPluginConfig<T
const zlib: {
algorithm: AlgorithmFunction<T>
filename: string | ((id: string)=> string)
options: CompressionOptions<T>
options: UserCompressionOptions
} = Object.create(null)

zlib.algorithm = typeof userAlgorithm === 'string' ? ensureAlgorithm(userAlgorithm).algorithm : userAlgorithm
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

zlib.options =
typeof userAlgorithm === 'function'
? compressionOptions
Expand Down Expand Up @@ -185,7 +186,7 @@ function compression<T, A extends Algorithm>(opts: ViteCompressionPluginConfig<T
return
}
const source = Buffer.from(bundle.type === 'asset' ? bundle.source : bundle.code)
const compressed = await transfer(source, zlib.algorithm, zlib.options)
const compressed = await compress(source, zlib.algorithm, zlib.options)
if (skipIfLargerOrEqual && len(compressed) >= len(source)) return
// #issue 30
if (deleteOriginalAssets) Reflect.deleteProperty(bundles, file)
Expand All @@ -201,7 +202,7 @@ function compression<T, A extends Algorithm>(opts: ViteCompressionPluginConfig<T
for (const [pos, dest] of meta.dest.entries()) {
const f = meta.file[pos]
const buf = await fsp.readFile(f)
const compressed = await transfer(buf, zlib.algorithm, zlib.options)
const compressed = await compress(buf, zlib.algorithm, zlib.options)
if (skipIfLargerOrEqual && len(compressed) >= len(buf)) continue
const fileName = replaceFileName(file, zlib.filename)
// issue #30
Expand Down
26 changes: 20 additions & 6 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export type InferDefault<T> = T extends infer K ? K : UserCompressionOptions

export type CompressionOptions<T> = InferDefault<T>

export type Pretty<T> = {
[key in keyof T]:
T[key] extends (...args: any[])=> any
? (...args: Parameters<T[key]>)=> ReturnType<T[key]>
: T[key] & NonNullable<unknown>
} & NonNullable<unknown>

interface BaseCompressionPluginOptions {
include?: FilterPattern
exclude?: FilterPattern
Expand All @@ -26,21 +33,26 @@ interface AlgorithmToZlib {
deflateRaw: ZlibOptions
}

export type AlgorithmFunction<T> =
(buf: Buffer, options: CompressionOptions<T>, callback: (err: Error | null, result: Buffer)=> void)=> void
export type AlgorithmFunction<T extends UserCompressionOptions> =
(buf: Buffer, options: T)=> Promise<Buffer>


type InternalCompressionPluginOptionsFunction<T> = {
type InternalCompressionPluginOptionsFunction<T> = {
algorithm?: AlgorithmFunction<T>
compressionOptions?: CompressionOptions<T>
compressionOptions: T
}
type InternalWithoutCompressionPluginOptionsFunction = {
algorithm?: AlgorithmFunction<undefined>
}
type InternalCompressionPluginOptionsAlgorithm<A extends Algorithm> = {
algorithm?: A
compressionOptions?: AlgorithmToZlib[A]
compressionOptions?: Pretty<AlgorithmToZlib[A]>
}

export type ViteCompressionPluginConfigFunction<T> = BaseCompressionPluginOptions &
export type ViteCompressionPluginConfigFunction<T extends UserCompressionOptions> = BaseCompressionPluginOptions &
InternalCompressionPluginOptionsFunction<T>
export type ViteWithoutCompressionPluginConfigFunction = Pretty<BaseCompressionPluginOptions &
InternalWithoutCompressionPluginOptionsFunction>
export type ViteCompressionPluginConfigAlgorithm<A extends Algorithm> = BaseCompressionPluginOptions &
InternalCompressionPluginOptionsAlgorithm<A>
export type ViteCompressionPluginConfig<T, A extends Algorithm> =
Expand All @@ -62,3 +74,5 @@ interface DyanmiCompressMetaInfo extends BaseCompressMetaInfo {
}

export type CompressMetaInfo = NormalCompressMetaInfo | DyanmiCompressMetaInfo


0 comments on commit 7db5d17

Please sign in to comment.