Skip to content

Conversation

@AugustinMauroy
Copy link
Member

@AugustinMauroy AugustinMauroy commented Oct 30, 2025

Related issues:

Closes #241

@AugustinMauroy
Copy link
Member Author

I need review on test cases so I can finish/clean the implementation

@AugustinMauroy AugustinMauroy requested review from a team and Copilot October 31, 2025 14:09
@AugustinMauroy AugustinMauroy added awaiting reviewer Author has responded and needs action from the reviewer dep:v24 Migration handles deprecation introduced in node v24 dep:EoL Migration handles deprecation introduced in an EoL version of node labels Oct 31, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a comprehensive codemod recipe to migrate deprecated Node.js timers APIs to modern timer functions. The codemod replaces timers.enroll(), timers.unenroll(), timers.active(), and timers._unrefActive() with standard setTimeout(), clearTimeout(), and Timer#unref() constructs, addressing Node.js deprecations DEP0095, DEP0096, DEP0126, and DEP0127.

Key changes include:

  • New utility functions for GCD calculation and indent detection in the codemod-utils package
  • Five transformation modules that handle different deprecated APIs
  • Comprehensive test suite covering various import/require patterns
  • Automated cleanup of unused imports after transformations

Reviewed Changes

Copilot reviewed 45 out of 46 changed files in this pull request and generated 107 comments.

Show a summary per file
File Description
utils/src/math.ts Implements GCD function to calculate indentation units
utils/src/math.test.ts Tests for GCD function including edge cases
utils/src/ast-grep/indent.ts Detects indentation style and retrieves line indentation
utils/src/ast-grep/indent.test.ts Tests for indentation detection utilities
utils/src/ast-grep/general.ts Helper functions for AST manipulation
utils/src/ast-grep/general.test.ts Tests for AST manipulation helpers
recipes/timers-deprecations/src/*.ts Five transformation modules for each deprecated API
recipes/timers-deprecations/tests/** Comprehensive test cases for all transformations
recipes/timers-deprecations/workflow.yaml Workflow configuration for codemod execution
recipes/timers-deprecations/package.json Package configuration and test scripts
recipes/timers-deprecations/codemod.yaml Codemod metadata and registry configuration
recipes/timers-deprecations/README.md Documentation with examples and caveats

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@AugustinMauroy AugustinMauroy linked an issue Nov 1, 2025 that may be closed by this pull request
Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this and sorry it's taken me a quite a while to get to it. It's been a helluva month :(

@JakobJingleheimer
Copy link
Member

@AugustinMauroy I tried to review the rest of this, but the browser tab crashes trying to load it (it's big, but I didn't think it was that big). Would it be possible to break this into smaller pieces?

@AugustinMauroy
Copy link
Member Author

@AugustinMauroy I tried to review the rest of this, but the browser tab crashes trying to load it (it's big, but I didn't think it was that big). Would it be possible to break this into smaller pieces?

I already do that. I just sub step for each deprecation + cleanup import

@AugustinMauroy AugustinMauroy requested a review from a team December 15, 2025 19:32
Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! Smaller PRs though please 🫠

I didn't review all the test files, but the implementation looks good! I don't understand how DEP0095 possibly works, but it has test coverage, so it obviously does 🤪

Comment on lines +60 to +73
const indent = getLineIndent(sourceCode, statement.range().start.index);
const resourceText = resourceNode.text();
const childIndent = indent + indentUnit;
const innerIndent = childIndent + indentUnit;

const replacement =
`if (${resourceText}.timeout != null) {${EOL}` +
`${childIndent}clearTimeout(${resourceText}.timeout);${EOL}` +
`${indent}}${EOL}${EOL}` +
`${indent}${resourceText}.timeout = setTimeout(() => {${EOL}` +
`${childIndent}if (typeof ${resourceText}._onTimeout === "function") {${EOL}` +
`${innerIndent}${resourceText}._onTimeout();${EOL}` +
`${childIndent}}${EOL}` +
`${indent}}, ${resourceText}._idleTimeout);`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aw, that's nice :)

if (!statement) continue;

if (handledStatements.has(statement.id())) continue;
handledStatements.add(statement.id());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I this line should go at the bottom just in case something goes wrong in the code below.

'active',
'_unrefActive',
] as const;
const DEPRECATED_SET = new Set<string>(DEPRECATED_METHODS);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: manually setting the optional generic param actually works against it; without, typescript infers Set<"enroll" | "unenroll" | "active" | "_unrefActive"> 🙂

Suggested change
const DEPRECATED_SET = new Set<string>(DEPRECATED_METHODS);
const DEPRECATED_SET = new Set(DEPRECATED_METHODS);

Comment on lines +36 to +38
if (statement.kind() === 'expression_statement') {
continue;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit for consistency

Suggested change
if (statement.kind() === 'expression_statement') {
continue;
}
if (statement.kind() === 'expression_statement') continue;

if (!statement) continue;

if (handledStatements.has(statement.id())) continue;
handledStatements.add(statement.id());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same: I'd put this at the end

if (!statement) continue;

if (handledStatements.has(statement.id())) continue;
handledStatements.add(statement.id());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same: move to the end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 vs 2 indentation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would collapse all the ifs etc into 1 line that are if x do y.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too much indentation here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too much indentation here

@JakobJingleheimer JakobJingleheimer removed the awaiting reviewer Author has responded and needs action from the reviewer label Jan 1, 2026
@AugustinMauroy AugustinMauroy added the awaiting author Reviewer has requested something from the author label Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting author Reviewer has requested something from the author dep:EoL Migration handles deprecation introduced in an EoL version of node dep:v24 Migration handles deprecation introduced in node v24

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: handle timers deprecation

4 participants