nodejs / nodejs/userland-migrations

feat: handle Instantiating `node:zlib` classes without `new` depreciation

Open
#132 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

good first issue human help wanted let's do it
Dominant language
TypeScript
Stars
85
Forks
55
Avg merge
3d 11h
Merged PRs (30d)
9

Description

Description

Since instantiating node:zlib classes without new is deprecated (DEP0184) and has reached Runtime status, we should provide a codemod to replace them.

  • The codemod should add the new qualifier to all zlib class instantiations that are missing it.
  • The codemod should handle all zlib classes: Deflate, DeflateRaw, Gunzip, Gzip, Inflate, InflateRaw, Unzip, BrotliCompress, BrotliDecompress, ZstdCompress, ZstdDecompress, and Zlib.
  • The codemod should work with both CommonJS and ESM import patterns.
  • The codemod should handle destructured imports, namespace imports, and direct property access.

Additional Information

Note that instantiating classes without the new qualifier exported by the node:zlib module was deprecated in Node.js v24.0.0 and became a runtime deprecation. This pattern was deprecated because it goes against JavaScript best practices and class instantiation conventions. Using new makes the code more explicit and follows standard JavaScript patterns.

All zlib classes should be instantiated with the new keyword to create proper instances and avoid potential issues with this context and prototype chain.

Examples

Case 1: Direct class instantiation with namespace import

Before:

const zlib = require('node:zlib');

const deflate = zlib.Deflate();
const gzip = zlib.Gzip();
const gunzip = zlib.Gunzip();

After:

const zlib = require('node:zlib');

const deflate = new zlib.Deflate();
const gzip = new zlib.Gzip();
const gunzip = new zlib.Gunzip();
Case 2: ESM namespace import

Before:

import * as zlib from 'node:zlib';

const deflate = zlib.Deflate();
const inflate = zlib.Inflate();
const brotli = zlib.BrotliCompress();

After:

import * as zlib from 'node:zlib';

const deflate = new zlib.Deflate();
const inflate = new zlib.Inflate();
const brotli = new zlib.BrotliCompress();
Case 3: Destructured import

Before:

const { Deflate, Gzip, Gunzip, Inflate } = require('node:zlib');

const deflate = Deflate();
const gzip = Gzip();
const gunzip = Gunzip();
const inflate = Inflate();

After:

const { Deflate, Gzip, Gunzip, Inflate } = require('node:zlib');

const deflate = new Deflate();
const gzip = new Gzip();
const gunzip = new Gunzip();
const inflate = new Inflate();
Case 4: ESM destructured import

Before:

import { BrotliCompress, BrotliDecompress, ZstdCompress } from 'node:zlib';

const brotliComp = BrotliCompress();
const brotliDecomp = BrotliDecompress();
const zstdComp = ZstdCompress();

After:

import { BrotliCompress, BrotliDecompress, ZstdCompress } from 'node:zlib';

const brotliComp = new BrotliCompress();
const brotliDecomp = new BrotliDecompress();
const zstdComp = new ZstdCompress();
Case 5: With options parameter

Before:

const zlib = require('node:zlib');

const gzip = zlib.Gzip({ level: 9 });
const deflate = zlib.Deflate({ windowBits: 15 });

After:

const zlib = require('node:zlib');

const gzip = new zlib.Gzip({ level: 9 });
const deflate = new zlib.Deflate({ windowBits: 15 });
Case 6: In function calls and expressions

Before:

import { DeflateRaw, InflateRaw } from 'node:zlib';

function createCompressor() {
  return DeflateRaw({ level: 6 });
}

const stream = InflateRaw().pipe(process.stdout);

After:

import { DeflateRaw, InflateRaw } from 'node:zlib';

function createCompressor() {
  return new DeflateRaw({ level: 6 });
}

const stream = new InflateRaw().pipe(process.stdout);
Case 7: All zlib classes

Before:

const zlib = require('node:zlib');

const deflate = zlib.Deflate();
const deflateRaw = zlib.DeflateRaw();
const gzip = zlib.Gzip();
const gunzip = zlib.Gunzip();
const inflate = zlib.Inflate();
const inflateRaw = zlib.InflateRaw();
const unzip = zlib.Unzip();
const brotliComp = zlib.BrotliCompress();
const brotliDecomp = zlib.BrotliDecompress();

After:

const zlib = require('node:zlib');

const deflate = new zlib.Deflate();
const deflateRaw = new zlib.DeflateRaw();
const gzip = new zlib.Gzip();
const gunzip = new zlib.Gunzip();
const inflate = new zlib.Inflate();
const inflateRaw = new zlib.InflateRaw();
const unzip = new zlib.Unzip();
const brotliComp = new zlib.BrotliCompress();
const brotliDecomp = new zlib.BrotliDecompress();
Case 8: Mixed with factory functions (should not change)

Before:

const zlib = require('node:zlib');

// These should NOT be changed (factory functions)
const gzipStream = zlib.createGzip();
const deflateStream = zlib.createDeflate();

// These should be changed (class constructors)
const gzipClass = zlib.Gzip();
const deflateClass = zlib.Deflate();

After:

const zlib = require('node:zlib');

// These should NOT be changed (factory functions)
const gzipStream = zlib.createGzip();
const deflateStream = zlib.createDeflate();

// These should be changed (class constructors)
const gzipClass = new zlib.Gzip();
const deflateClass = new zlib.Deflate();
Case 9: Experimental Zstd classes

Before:

import { ZstdCompress, ZstdDecompress } from 'node:zlib';

const compressor = ZstdCompress({ level: 10 });
const decompressor = ZstdDecompress();

After:

import { ZstdCompress, ZstdDecompress } from 'node:zlib';

const compressor = new ZstdCompress({ level: 10 });
const decompressor = new ZstdDecompress();

Refs

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names no repository files or tests; start by locating the codemod entry point and existing fixtures or tests for node:zlib imports. Cover the listed CommonJS and ESM import patterns and all named classes, while leaving factory functions unchanged. Done means each missing new qualifier is added and the existing test suite passes.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.