zsy-recycling-supervision-a.../plugin/zip-dist.ts

67 lines
1.8 KiB
TypeScript

import {
bold,
red
} from 'colorette'
import {
AsyncZippable,
zip
} from 'fflate'
import { filesize } from 'filesize'
import {
readdir,
readFile,
writeFile
} from 'node:fs/promises'
import { promisify } from 'node:util'
import { Plugin } from 'vite'
import { relative } from 'node:path'
async function* traversalDir(path: string): AsyncGenerator<[ string, string, Uint8Array ]> {
yield [ 'startDir', path, new Uint8Array(1) ]
let dirents = await readdir(path, {withFileTypes: true})
for (let dirent of dirents) {
let subDir = `${path}/${dirent.name}`
if (dirent.isDirectory()) {
yield* traversalDir(subDir)
} else {
yield [ 'file', subDir, await readFile(subDir) ]
}
}
yield [ 'endDir', path, new Uint8Array(1) ]
}
async function doZip(path: string) {
let data: AsyncZippable = {}
for await (const e of traversalDir(path)) {
if (e[0] === 'file') {
data[relative(path, e[1])] = e[2]
}
}
return await promisify(zip)(data)
}
export default function zipDist(name?: string, addVersion: boolean = false): Plugin {
if (!!name && !name.endsWith('.zip')) {
name = `${name}.zip`
} else if (!name) {
let {npm_package_name = 'bundle', npm_package_version} = process.env
name = !!npm_package_version && addVersion ?
`${npm_package_name}-${npm_package_version}.zip` : `${npm_package_name}.zip`
}
return {
name: 'vite-plugin-dist-zip',
writeBundle: {
sequential: true,
order: 'post',
handler(options, bundle) {
doZip(options.dir!)
.then(value => Promise.all([ writeFile(`./dist/${name}`, value), Promise.resolve(value.byteLength) ]))
.then(value => console.log(red(`\n压缩完成 ${bold(`dist/${name}`)} ${filesize(value[1])}`)))
}
}
}
}