From 6b32b3f05bc4ce8b6b9c7092447eb2bcbd5dda64 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 23 Nov 2021 14:46:49 +0700 Subject: [PATCH] Require Node.js 12.20 and move to ESM --- .github/workflows/main.yml | 4 +- index.d.ts | 169 +++++++++++++++++++------------------ index.js | 55 ++++++------ index.test-d.ts | 21 ++--- package.json | 12 +-- readme.md | 22 ++--- test.js | 34 +++++--- 7 files changed, 170 insertions(+), 147 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1870cf..3b8aa86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,12 +10,12 @@ jobs: fail-fast: false matrix: node-version: + - 16 - 14 - 12 - - 10 steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/index.d.ts b/index.d.ts index 921184f..95adb68 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,96 +1,103 @@ -/// -import * as stream from 'stream'; -import {ZlibOptions} from 'zlib'; - -declare namespace gzipSize { - type Options = ZlibOptions; - - interface GzipSizeStream extends stream.PassThrough { - /** - Contains the gzip size of the stream after it is finished. Since this happens asynchronously, it is recommended you use the `gzip-size` event instead. - */ - gzipSize?: number; - - addListener(event: 'gzip-size', listener: (size: number) => void): this; - addListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this; - on(event: 'gzip-size', listener: (size: number) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: 'gzip-size', listener: (size: number) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: 'gzip-size', listener: (size: number) => void): this; - removeListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this; - off(event: 'gzip-size', listener: (size: number) => void): this; - off(event: string | symbol, listener: (...args: any[]) => void): this; - emit(event: 'gzip-size', size: number): boolean; - emit(event: string | symbol, ...args: any[]): boolean; - prependListener(event: 'gzip-size', listener: (size: number) => void): this; - prependListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this; - prependOnceListener( - event: 'gzip-size', - listener: (size: number) => void - ): this; - prependOnceListener( - event: string | symbol, - listener: (...args: any[]) => void - ): this; - } -} +import {Buffer} from 'node:buffer'; +import {PassThrough as PassThroughStream} from 'node:stream'; +import {ZlibOptions} from 'node:zlib'; -declare const gzipSize: { - /** - Get the gzipped size of a string or buffer. +export type Options = ZlibOptions; - @returns The gzipped size of `input`. +export interface GzipSizeStream extends PassThroughStream { + /** + Contains the gzip size of the stream after it is finished. Since this happens asynchronously, it is recommended you use the `gzip-size` event instead. */ - (input: string | Buffer, options?: gzipSize.Options): Promise; + gzipSize?: number; + + addListener(event: 'gzip-size', listener: (size: number) => void): this; + addListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; + on(event: 'gzip-size', listener: (size: number) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: 'gzip-size', listener: (size: number) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: 'gzip-size', listener: (size: number) => void): this; + removeListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; + off(event: 'gzip-size', listener: (size: number) => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; + emit(event: 'gzip-size', size: number): boolean; + emit(event: string | symbol, ...args: any[]): boolean; + prependListener(event: 'gzip-size', listener: (size: number) => void): this; + prependListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; + prependOnceListener( + event: 'gzip-size', + listener: (size: number) => void + ): this; + prependOnceListener( + event: string | symbol, + listener: (...args: any[]) => void + ): this; +} - /** - Synchronously get the gzipped size of a string or buffer. +/** +Get the gzipped size of a string or buffer. - @returns The gzipped size of `input`. +@returns The gzipped size of `input`. - @example - ``` - import gzipSize = require('gzip-size'); +@example +``` +import {gzipSize} from 'gzip-size'; - const text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.'; +const text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.'; - console.log(text.length); - //=> 191 +console.log(text.length); +//=> 191 - console.log(gzipSize.sync(text)); - //=> 78 - ``` - */ - sync(input: string | Buffer, options?: gzipSize.Options): number; +console.log(await gzipSize(text)); +//=> 78 +``` +*/ +export function gzipSize(input: string | Buffer, options?: Options): Promise; - /** - @returns A stream that emits a `gzip-size` event and has a `gzipSize` property. - */ - stream(options?: gzipSize.Options): gzipSize.GzipSizeStream; +/** +Synchronously get the gzipped size of a string or buffer. - /** - Get the gzipped size of a file. +@returns The gzipped size of `input`. - @returns The size of the file. - */ - file(path: string, options?: gzipSize.Options): Promise; +@example +``` +import {gzipSizeSync} from 'gzip-size'; - /** - Synchronously get the gzipped size of a file. +const text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.'; - @returns The size of the file. - */ - fileSync(path: string, options?: gzipSize.Options): number; -}; +console.log(text.length); +//=> 191 + +console.log(gzipSizeSync(text)); +//=> 78 +``` +*/ +export function gzipSizeSync(input: string | Buffer, options?: Options): number; + +/** +Get the gzipped size of a file. + +@returns The size of the file. +*/ +export function gzipSizeFromFile(filePath: string, options?: Options): Promise; + +/** +Synchronously get the gzipped size of a file. + +@returns The size of the file. +*/ +export function gzipSizeFromFileSync(filePath: string, options?: Options): number; -export = gzipSize; +/** +@returns A stream that emits a `gzip-size` event and has a `gzipSize` property. +*/ +export function gzipSizeStream(options?: Options): GzipSizeStream; diff --git a/index.js b/index.js index 797dc8c..cbea6fe 100644 --- a/index.js +++ b/index.js @@ -1,25 +1,45 @@ -'use strict'; -const fs = require('fs'); -const stream = require('stream'); -const zlib = require('zlib'); -const {promisify} = require('util'); -const duplexer = require('duplexer'); +import fs from 'node:fs'; +import stream from 'node:stream'; +import zlib from 'node:zlib'; +import {promisify} from 'node:util'; +import duplexer from 'duplexer'; const getOptions = options => ({level: 9, ...options}); const gzip = promisify(zlib.gzip); -module.exports = async (input, options) => { +export async function gzipSize(input, options) { if (!input) { return 0; } const data = await gzip(input, getOptions(options)); return data.length; -}; +} -module.exports.sync = (input, options) => zlib.gzipSync(input, getOptions(options)).length; +export function gzipSizeSync(input, options) { + return zlib.gzipSync(input, getOptions(options)).length; +} + +export function gzipSizeFromFile(path, options) { + // TODO: Use `stream.pipeline` here. + + return new Promise((resolve, reject) => { + const stream = fs.createReadStream(path); + stream.on('error', reject); + + const gzipStream = stream.pipe(gzipSizeStream(options)); + gzipStream.on('error', reject); + gzipStream.on('gzip-size', resolve); + }); +} + +export function gzipSizeFromFileSync(path, options) { + return gzipSizeSync(fs.readFileSync(path), options); +} + +export function gzipSizeStream(options) { + // TODO: Use `stream.pipeline` here. -module.exports.stream = options => { const input = new stream.PassThrough(); const output = new stream.PassThrough(); const wrapper = duplexer(input, output); @@ -42,17 +62,4 @@ module.exports.stream = options => { input.pipe(output, {end: false}); return wrapper; -}; - -module.exports.file = (path, options) => { - return new Promise((resolve, reject) => { - const stream = fs.createReadStream(path); - stream.on('error', reject); - - const gzipStream = stream.pipe(module.exports.stream(options)); - gzipStream.on('error', reject); - gzipStream.on('gzip-size', resolve); - }); -}; - -module.exports.fileSync = (path, options) => module.exports.sync(fs.readFileSync(path), options); +} diff --git a/index.test-d.ts b/index.test-d.ts index d39e066..3b9a75b 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -1,18 +1,19 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return */ +import fs from 'node:fs'; import {expectType} from 'tsd'; -import * as fs from 'fs'; -import gzipSize = require('.'); +import {gzipSize, gzipSizeSync, gzipSizeFromFile, gzipSizeFromFileSync, gzipSizeStream} from './index.js'; expectType>(gzipSize('foo')); expectType>(gzipSize('foo', {chunkSize: 1})); -expectType(gzipSize.sync('foo')); -expectType(gzipSize.sync('foo', {chunkSize: 1})); +expectType(gzipSizeSync('foo')); +expectType(gzipSizeSync('foo', {chunkSize: 1})); const gstream = fs .createReadStream('index.d.ts') - .pipe(gzipSize.stream()) - .pipe(gzipSize.stream({chunkSize: 1})) + .pipe(gzipSizeStream()) + .pipe(gzipSizeStream({chunkSize: 1})) .on('gzip-size', size => expectType(size)); expectType(gstream.gzipSize); -expectType>(gzipSize.file('index.d.ts')); -expectType>(gzipSize.file('index.d.ts', {chunkSize: 1})); -expectType(gzipSize.fileSync('index.d.ts')); -expectType(gzipSize.fileSync('index.d.ts', {chunkSize: 1})); +expectType>(gzipSizeFromFile('index.d.ts')); +expectType>(gzipSizeFromFile('index.d.ts', {chunkSize: 1})); +expectType(gzipSizeFromFileSync('index.d.ts')); +expectType(gzipSizeFromFileSync('index.d.ts', {chunkSize: 1})); diff --git a/package.json b/package.json index 0f17a33..fb88bbd 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "email": "sindresorhus@gmail.com", "url": "https://sindresorhus.com" }, + "type": "module", + "exports": "./index.js", "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "scripts": { "test": "xo && ava && tsd" @@ -34,9 +36,9 @@ "duplexer": "^0.1.2" }, "devDependencies": { - "ava": "^2.4.0", - "p-event": "^4.2.0", - "tsd": "^0.13.1", - "xo": "^0.34.2" + "ava": "^3.15.0", + "p-event": "^5.0.1", + "tsd": "^0.19.0", + "xo": "^0.46.4" } } diff --git a/readme.md b/readme.md index e26d4c5..0a02249 100644 --- a/readme.md +++ b/readme.md @@ -4,21 +4,21 @@ ## Install -``` -$ npm install gzip-size +```sh +npm install gzip-size ``` ## Usage ```js -const gzipSize = require('gzip-size'); +import {gzipSize, gzipSizeSync} from 'gzip-size'; const text = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.'; console.log(text.length); //=> 191 -console.log(gzipSize.sync(text)); +console.log(gzipSizeSync(text)); //=> 78 ``` @@ -28,7 +28,7 @@ console.log(gzipSize.sync(text)); Returns a `Promise` with the size. -### gzipSize.sync(input, options?) +### gzipSizeSync(input, options?) Returns the size. @@ -42,11 +42,7 @@ Type: `object` Any [`zlib` option](https://nodejs.org/api/zlib.html#zlib_class_options). -### gzipSize.stream(options?) - -Returns a [`stream.PassThrough`](https://nodejs.org/api/stream.html#stream_class_stream_passthrough). The stream emits a `gzip-size` event and has a `gzipSize` property. - -### gzipSize.file(path, options?) +### gzipSizeFromFile(path, options?) Returns a `Promise` with the size of the file. @@ -54,10 +50,14 @@ Returns a `Promise` with the size of the file. Type: `string` -### gzipSize.fileSync(path, options?) +### gzipSizeFromFileSync(path, options?) Returns the size of the file. +### gzipSizeStream(options?) + +Returns a [`stream.PassThrough`](https://nodejs.org/api/stream.html#stream_class_stream_passthrough). The stream emits a `gzip-size` event and has a `gzipSize` property. + ## Related - [gzip-size-cli](https://github.com/sindresorhus/gzip-size-cli) - CLI for this module diff --git a/test.js b/test.js index 3e0ec15..8b0a823 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,13 @@ -import fs from 'fs'; +import fs from 'node:fs'; import test from 'ava'; -import pEvent from 'p-event'; -import gzipSize from '.'; +import {pEvent} from 'p-event'; +import { + gzipSize, + gzipSizeSync, + gzipSizeFromFile, + gzipSizeFromFileSync, + gzipSizeStream, +} from './index.js'; const fixture = fs.readFileSync('test.js', 'utf8'); @@ -14,34 +20,34 @@ test('gzip compression level', async t => { }); test('sync - get the gzipped size', t => { - t.true(gzipSize.sync(fixture) < fixture.length); + t.true(gzipSizeSync(fixture) < fixture.length); }); test('sync - match async version', async t => { - t.is(gzipSize.sync(fixture), await gzipSize(fixture)); + t.is(gzipSizeSync(fixture), await gzipSize(fixture)); }); test('sync - gzip compression level', t => { - t.true(gzipSize.sync(fixture, {level: 6}) < gzipSize.sync(fixture, {level: 1})); + t.true(gzipSizeSync(fixture, {level: 6}) < gzipSizeSync(fixture, {level: 1})); }); test('stream', async t => { - const stream = fs.createReadStream('test.js').pipe(gzipSize.stream()); + const stream = fs.createReadStream('test.js').pipe(gzipSizeStream()); await pEvent(stream, 'end'); - t.is(stream.gzipSize, gzipSize.sync(fixture)); + t.is(stream.gzipSize, gzipSizeSync(fixture)); }); test('gzip-size event', async t => { - const stream = fs.createReadStream('test.js').pipe(gzipSize.stream()); + const stream = fs.createReadStream('test.js').pipe(gzipSizeStream()); const size = await pEvent(stream, 'gzip-size'); - t.is(size, gzipSize.sync(fixture)); + t.is(size, gzipSizeSync(fixture)); }); test('passthrough', async t => { let out = ''; const stream = fs.createReadStream('test.js') - .pipe(gzipSize.stream()) + .pipe(gzipSizeStream()) .on('data', buffer => { out += buffer; }); @@ -51,13 +57,13 @@ test('passthrough', async t => { }); test('file - get the gzipped size', async t => { - t.true(await gzipSize.file('test.js') < fixture.length); + t.true(await gzipSizeFromFile('test.js') < fixture.length); }); test('fileSync - get the gzipped size', t => { - t.is(gzipSize.fileSync('test.js'), gzipSize.sync(fixture)); + t.is(gzipSizeFromFileSync('test.js'), gzipSizeSync(fixture)); }); test('file - match async version', async t => { - t.is(await gzipSize.file('test.js'), await gzipSize(fixture)); + t.is(await gzipSizeFromFile('test.js'), await gzipSize(fixture)); });