@aminya/minijson
Version:
Minify JSON files blazing fast, removing comments/whitespace.
94 lines (84 loc) • 2.95 kB
text/typescript
import { execFile } from "child_process"
import { chmodSync } from "fs"
import { readFile, writeFile } from "fs/promises"
import { join } from "path"
/**
* Minify all the given JSON files in place. It minifies the files in parallel.
*
* @param files An array of paths to the files
* @param hasComment A boolean to support comments in json. Default `true`.
* @returns {Promise<void>} Returns a void promise that resolves when all the files are minified
* @throws {Promise<string | Error>} The promise is rejected with the reason for failure
*/
export async function minifyFiles(files: readonly string[], hasComment = true): Promise<void> {
try {
const filesNum = files.length
if (filesNum === 0) {
return Promise.resolve()
}
await spawnMinijson([...files, hasComment ? "--comment=true" : "--comment=false"])
} catch (e) {
console.error(e, "Falling back to jsonminify")
await minifyFilesFallback(files)
}
}
/**
* Spawn minijson with the given arguments
*
* @param args An array of arguments
* @returns {Promise<string>} Returns a promise that resolves to stdout output string when the operation finishes
* @throws {Promise<string | Error>} The promise is rejected with the reason for failure
*/
export function spawnMinijson(args: string[]): Promise<string> {
return new Promise<string>((resolve, reject) => {
try {
execFile(minijsonBin, args, (err, stdout, stderr) => {
console.error(stderr)
console.log(stdout)
if (err) {
reject(err)
}
if (stderr !== "") {
reject(stderr)
}
resolve(stdout)
})
} catch (execErr) {
reject(execErr)
}
})
}
async function minifyFilesFallback(files: readonly string[]) {
const jsonminify = require("jsonminify")
await Promise.all(
files.map(async (file) => {
const jsonString = await readFile(file, "utf8")
const minifiedJsonString = jsonminify(jsonString) as string
await writeFile(file, minifiedJsonString)
}),
)
return
}
/**
* Minify the given JSON string
*
* @param jsonString The json string you want to minify
* @param hasComment A boolean to support comments in json. Default `true`.
* @returns {Promise<string>} The minified json string
* @throws {Promise<string | Error>} The promise is rejected with the reason for failure
*/
export async function minifyString(jsonString: string, hasComment = true): Promise<string> {
const args = ["--str", jsonString]
if (hasComment) {
args.push("--comment")
}
// trim is needed due to using stdout for interop
return (await spawnMinijson(args)).trim()
}
const exeExtention = process.platform === "win32" ? ".exe" : ""
const binName = `minijson${exeExtention}`
const minijsonBin = join(__dirname, `${process.platform}-${process.arch}`, binName)
// chmod as executable on non-windows
if (process.platform !== "win32") {
chmodSync(minijsonBin, 0o755)
}