Created
October 30, 2022 13:22
-
-
Save barelyhuman/e829bee7e83be919927ac5c04d819623 to your computer and use it in GitHub Desktop.
Pure ESM version of sizesnap cli
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import glob from 'tiny-glob' | |
import _xs from 'xstream' | |
import zlib from 'zlib' | |
import {promises as fs} from 'node:fs' | |
import _concat from 'xstream/extra/concat.js' | |
const xs = _xs.default | |
const concat = _concat.default | |
// contained exec of the streams | |
;(async function main() { | |
const snapper = createSnapper() | |
let files = [] | |
let arg | |
let i = 2 | |
while ((arg = process.argv[i])) { | |
try { | |
const res = await glob(arg) | |
files = files.concat(res) | |
} catch (err) {} | |
i += 1 | |
} | |
const sizeCollection$ = [] | |
files.forEach(file => sizeCollection$.push(size(file, snapper))) | |
concat(...sizeCollection$).addListener({ | |
error: err => console.error(err), | |
complete: async () => { | |
snapper.write() | |
console.log('.sizesnap.json created!') | |
}, | |
}) | |
})() | |
// Generate a steam that generates the object with file's data | |
function size(file, snapper) { | |
return xs | |
.fromPromise(fs.readFile(file)) | |
.map(buffer => ({ | |
original: bytes.pretty(buffer.length), | |
gz: bytes.pretty(zlib.gzipSync(buffer, {level: 9}).length), | |
brotli: bytes.pretty(zlib.brotliCompressSync(buffer).length), | |
})) | |
.map(obj => { | |
snapper.add(file, obj) | |
return obj | |
}) | |
} | |
function createSnapper() { | |
let snapObject = {} | |
return { | |
write: () => { | |
fs.writeFile('.sizesnap.json', JSON.stringify(snapObject, null, 2)) | |
}, | |
add: (file, snap) => (snapObject[file] = snap), | |
} | |
} | |
const sizeDefinitions = { | |
get b() { | |
return 1 | |
}, | |
get kb() { | |
return 1000 * this.b | |
}, | |
get mb() { | |
return 1000 * this.kb | |
}, | |
get gb() { | |
return 1000 * this.mb | |
}, | |
get tb() { | |
return 1000 * this.gb | |
}, | |
} | |
const byteRgx = /^([0-9]*[.]?[0-9]*)(b|kb|mb|gb|tb)$/i | |
const bytes = { | |
pretty(num) { | |
const entries = Object.entries(sizeDefinitions).sort((x, y) => y[1] - x[1]) | |
for (const [k, s] of entries) { | |
if (num > s) return num / s + k.toUpperCase() | |
} | |
}, | |
parse(toParse) { | |
if (!isNaN(toParse)) return Number(toParse) | |
if (!byteRgx.test(toParse)) | |
throw new Error('Invalid `toParse` value provided to `parse`') | |
const [_, size, suffix] = byteRgx.exec(toParse) | |
return Number(size) * sizeDefinitions[suffix.toLowerCase()] | |
}, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment