From da7cf08783227596b89d5c5cd5c7c57964c1c2b8 Mon Sep 17 00:00:00 2001 From: avivkeller Date: Sun, 9 Aug 2026 16:13:19 -0400 Subject: [PATCH 1/2] feat(README): prep for learn --- .github/workflows/codemod_publish.yml | 19 +- .github/workflows/refresh-learn.yml | 71 ++++ CONTRIBUTING.md | 2 +- README.md | 2 + docs/writing-a-readme.md | 349 ++++++++++++++++++ recipes/axios-to-whatwg-fetch/README.md | 245 ++++++------ recipes/axios-to-whatwg-fetch/codemod.yaml | 2 +- recipes/axios-to-whatwg-fetch/package.json | 2 +- recipes/buffer-atob-btoa/README.md | 82 +++- recipes/buffer-atob-btoa/codemod.yaml | 2 +- recipes/buffer-atob-btoa/package.json | 2 +- recipes/chalk-to-util-styletext/README.md | 95 +++-- recipes/chalk-to-util-styletext/codemod.yaml | 2 +- recipes/chalk-to-util-styletext/package.json | 2 +- recipes/correct-ts-specifiers/.codemodrc.json | 2 +- recipes/correct-ts-specifiers/README.md | 142 ++++--- recipes/correct-ts-specifiers/package.json | 2 +- recipes/create-require-from-path/README.md | 63 +++- recipes/create-require-from-path/codemod.yaml | 2 +- recipes/create-require-from-path/package.json | 2 +- .../README.md | 76 +++- .../codemod.yaml | 2 +- .../package.json | 2 +- .../crypto-createcipheriv-migration/README.md | 88 +++-- .../codemod.yaml | 2 +- .../package.json | 2 +- recipes/crypto-fips-to-getFips/README.md | 88 +++-- recipes/crypto-fips-to-getFips/codemod.yaml | 2 +- recipes/crypto-fips-to-getFips/package.json | 2 +- recipes/crypto-rsa-pss-update/README.md | 100 +++-- recipes/crypto-rsa-pss-update/codemod.yaml | 2 +- recipes/crypto-rsa-pss-update/package.json | 2 +- recipes/dirent-path-to-parent-path/README.md | 86 ++++- .../dirent-path-to-parent-path/codemod.yaml | 2 +- .../dirent-path-to-parent-path/package.json | 2 +- recipes/dns-lookup-options-coercion/README.md | 64 +++- .../dns-lookup-options-coercion/codemod.yaml | 2 +- .../dns-lookup-options-coercion/package.json | 2 +- recipes/err-invalid-callback/README.md | 92 ++++- recipes/err-invalid-callback/codemod.yaml | 2 +- recipes/err-invalid-callback/package.json | 2 +- recipes/fs-access-mode-constants/README.md | 62 +++- recipes/fs-access-mode-constants/codemod.yaml | 2 +- recipes/fs-access-mode-constants/package.json | 2 +- recipes/fs-truncate-fd-deprecation/README.md | 68 +++- .../fs-truncate-fd-deprecation/codemod.yaml | 2 +- .../fs-truncate-fd-deprecation/package.json | 2 +- recipes/http-classes-with-new/README.md | 75 +++- recipes/http-classes-with-new/codemod.yaml | 2 +- recipes/http-classes-with-new/package.json | 2 +- .../http-outgoingmessage-headers/README.md | 130 +++++++ .../http-outgoingmessage-headers/codemod.yaml | 2 +- .../http-outgoingmessage-headers/package.json | 2 +- .../http-outgoingmessage-headers/readme.md | 40 -- recipes/http2-priority-signaling/README.md | 80 +++- recipes/http2-priority-signaling/codemod.yaml | 2 +- recipes/http2-priority-signaling/package.json | 2 +- .../import-assertions-to-attributes/README.md | 64 +++- .../codemod.yaml | 2 +- .../package.json | 2 +- recipes/mocha-to-node-test-runner/README.md | 117 +++--- .../mocha-to-node-test-runner/codemod.yaml | 2 +- .../mocha-to-node-test-runner/package.json | 2 +- recipes/mock-module-exports/README.md | 94 ++++- recipes/mock-module-exports/codemod.yaml | 2 +- recipes/mock-module-exports/package.json | 2 +- recipes/node-url-to-whatwg-url/README.md | 104 +++--- recipes/node-url-to-whatwg-url/codemod.yaml | 2 +- recipes/node-url-to-whatwg-url/package.json | 2 +- .../process-assert-to-node-assert/README.md | 79 +++- .../codemod.yaml | 2 +- .../package.json | 2 +- recipes/process-main-module/README.md | 64 +++- recipes/process-main-module/codemod.yaml | 2 +- recipes/process-main-module/package.json | 2 +- recipes/repl-builtin-modules/README.md | 62 +++- recipes/repl-builtin-modules/codemod.yaml | 2 +- recipes/repl-builtin-modules/package.json | 2 +- recipes/repl-classes-with-new/README.md | 83 +++-- recipes/repl-classes-with-new/codemod.yaml | 2 +- recipes/repl-classes-with-new/package.json | 2 +- recipes/rmdir/README.md | 87 ++++- recipes/rmdir/codemod.yaml | 2 +- recipes/rmdir/package.json | 2 +- .../README.md | 59 ++- .../codemod.yaml | 2 +- .../package.json | 2 +- recipes/timers-deprecations/README.md | 120 ++++-- recipes/timers-deprecations/codemod.yaml | 2 +- recipes/timers-deprecations/package.json | 2 +- .../README.md | 103 ++---- .../codemod.yaml | 2 +- .../package.json | 2 +- recipes/tmpdir-to-tmpdir/README.md | 62 +++- recipes/tmpdir-to-tmpdir/codemod.yaml | 2 +- recipes/tmpdir-to-tmpdir/package.json | 2 +- recipes/types-is-native-error/README.md | 78 +++- recipes/types-is-native-error/codemod.yaml | 2 +- recipes/types-is-native-error/package.json | 2 +- .../util-extend-to-object-assign/README.md | 54 ++- .../util-extend-to-object-assign/codemod.yaml | 2 +- .../util-extend-to-object-assign/package.json | 2 +- recipes/util-is/README.md | 117 ++++-- recipes/util-is/codemod.yaml | 2 +- recipes/util-is/package.json | 2 +- recipes/util-log-to-console-log/README.md | 58 ++- recipes/util-log-to-console-log/codemod.yaml | 2 +- recipes/util-log-to-console-log/package.json | 2 +- recipes/util-print-to-console-log/README.md | 81 +++- .../util-print-to-console-log/codemod.yaml | 2 +- .../util-print-to-console-log/package.json | 2 +- recipes/v22-to-v24/README.md | 70 +++- recipes/v22-to-v24/codemod.yaml | 2 +- recipes/v22-to-v24/package.json | 2 +- .../zlib-bytesread-to-byteswritten/README.md | 154 ++------ .../codemod.yaml | 2 +- .../package.json | 2 +- scripts/sync-learn.mjs | 135 +++++++ utils/README.md | 2 + 119 files changed, 2994 insertions(+), 1120 deletions(-) create mode 100644 .github/workflows/refresh-learn.yml create mode 100644 docs/writing-a-readme.md create mode 100644 recipes/http-outgoingmessage-headers/README.md delete mode 100644 recipes/http-outgoingmessage-headers/readme.md create mode 100644 scripts/sync-learn.mjs diff --git a/.github/workflows/codemod_publish.yml b/.github/workflows/codemod_publish.yml index c043b5d4..6db2085f 100644 --- a/.github/workflows/codemod_publish.yml +++ b/.github/workflows/codemod_publish.yml @@ -11,15 +11,21 @@ on: workflow_dispatch: inputs: tag: - description: "Tag to publish (format: v1.0.0@codemod-name)" - required: true + description: "Tag to publish (format: v1.0.0@codemod-name); ignored if sync_only" + required: false type: string + # For documentation-only changes, which warrant no version bump. + sync_only: + description: "Sync READMEs to nodejs/learn without publishing a codemod" + default: false + type: boolean permissions: read-all jobs: validate-and-publish: name: Validate and Publish Codemod + if: ${{ !inputs.sync_only }} runs-on: ubuntu-latest permissions: @@ -139,3 +145,12 @@ jobs: ✅ Codemod has been successfully published to the registry! EOF + + refresh-learn: + name: Sync nodejs/learn + needs: validate-and-publish + # Runs on its own when sync_only skipped the publish job above. + if: ${{ !cancelled() && (inputs.sync_only || needs.validate-and-publish.result == 'success') }} + uses: ./.github/workflows/refresh-learn.yml + secrets: + LEARN_REPO_TOKEN: ${{ secrets.LEARN_REPO_TOKEN }} diff --git a/.github/workflows/refresh-learn.yml b/.github/workflows/refresh-learn.yml new file mode 100644 index 00000000..d5f6ef84 --- /dev/null +++ b/.github/workflows/refresh-learn.yml @@ -0,0 +1,71 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + +name: Refresh nodejs/learn + +on: + workflow_call: + secrets: + LEARN_REPO_TOKEN: + required: true + description: > + Fine-grained PAT scoped to nodejs/learn with + Contents: write and Pull requests: write permissions. + +permissions: + contents: read + +concurrency: + group: refresh-learn + cancel-in-progress: false + +jobs: + sync: + name: Sync READMEs to nodejs/learn + runs-on: ubuntu-slim + + permissions: + contents: read + + steps: + - name: Harden Runner + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 + with: + egress-policy: audit + + - name: Checkout nodejs/learn + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: nodejs/learn + path: learn + token: ${{ secrets.LEARN_REPO_TOKEN }} + persist-credentials: false + + - name: Checkout userland-migrations + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: source + persist-credentials: false + + - name: Sync READMEs and update site.json + working-directory: learn + run: node ../source/scripts/sync-learn.mjs + + - name: Open or update pull request on nodejs/learn + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 + with: + path: learn + token: ${{ secrets.LEARN_REPO_TOKEN }} + add-paths: | + pages/userland-migrations + site.json + branch: automated/sync-userland-migrations + title: "chore: sync userland-migrations codemods" + commit-message: "chore: sync userland-migrations codemods" + body: | + Automated sync of codemod documentation from + [nodejs/userland-migrations](https://github.com/nodejs/userland-migrations). + + Updates `pages/userland-migrations/` and `site.json` with the + latest README from every published recipe. + + *This PR was automatically generated.* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a83b9f0..33ace462 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,7 @@ Each codemod resides in its own directory under `recipes/` and should include: | File | Purpose | |------|---------| -| `README.md` | Description, purpose, and usage instructions | +| `README.md` | Description, purpose, and usage instructions — must follow the [README writing guide](./docs/writing-a-readme.md), as it is published as an article on [nodejs.org/learn](https://nodejs.org/learn) | | `package.json` | Package manifest | | `src/workflow.ts` | Main entry point using the `jssg` codemod API | | `codemod.yml` | Codemod manifest file | diff --git a/README.md b/README.md index baec47ec..922f6bc8 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,5 @@ You can find official Node.js codemods in the [Codemod Registry](https://codemod ## Acknowledgments We would like to extend our gratitude to the team at Codemod for providing their excellent tools and for their direct assistance with the Node.js project. Their support has been invaluable in making these migrations possible. + + diff --git a/docs/writing-a-readme.md b/docs/writing-a-readme.md new file mode 100644 index 00000000..00a01884 --- /dev/null +++ b/docs/writing-a-readme.md @@ -0,0 +1,349 @@ +# Writing a README for a Recipe + +Every recipe directory must have a `README.md` that explains what the migration does, how to run it, and what the transformation looks like. This document describes the required structure, section-by-section writing guidance, and the conventions used across the repository. + +Recipe READMEs are also published as articles on [nodejs.org/learn](https://nodejs.org/learn), so each one must be a self-contained page that reads well outside the repository. See [Publishing to nodejs.org/learn](#publishing-to-nodejsorglearn) for the constraints that come with that. + +## The mandatory template + +````markdown +--- +authors: github-username +--- + +# TITLE HERE + +One-paragraph description of what the codemod does and why. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/ +``` + +## Examples + +### Example 1 + + + +```diff +-before ++after +``` + +## Notes + + + +### Limitations + + +```` + +The `Notes` and `Limitations` sections are optional. Omit them when they would be empty. The rest of the template is mandatory. + +--- + +## Frontmatter + +Every README must open with a YAML frontmatter block: + +```yaml +--- +authors: github-username +--- +``` + +**`authors` must be a GitHub username, not a display name.** The field maps to a GitHub account so that attribution is linkable and unambiguous. + +- Correct: `authors: AugustinMauroy` +- Incorrect: `authors: Augustin Mauroy` + +When a recipe has multiple authors, list them on the same line, separated by commas: + +```yaml +--- +authors: github-username-one, github-username-two +--- +``` + +Do not use a YAML sequence (`- github-username`): nodejs.org/learn parses `authors` as a single comma-separated string, and a list breaks the page's author attribution. + +--- + +## Title + +The title (`# ...`) follows the frontmatter block immediately. + +### Naming conventions + +Three patterns are used in the repository, depending on the nature of the migration: + +**1. `` DEPXXXX: `old-api` to `new-api` `` - for single-deprecation replacements** + +Use this form when the recipe addresses one deprecation notice and the old and new names are short enough to fit on one line. + +```markdown +# DEP0147: `fs.rmdir()` to `fs.rm()` + +# DEP0178: `dirent.path` to `dirent.parentPath` + +# DEP0093: `crypto.fips` to `crypto.getFips()` / `crypto.setFips()` +``` + +**2. `DEPXXXX: Description` - for deprecations where the replacement is not a simple rename** + +Use this form when the new API is not a direct drop-in or when listing all affected symbols inline would make the title too long. + +```markdown +# DEP0185: Instantiating `node:repl` Classes Without `new` + +# DEP0191: `repl.builtinModules` / `repl._builtinLibs` to `module.builtinModules` +``` + +When multiple deprecation numbers apply, separate them with `/`: + +```markdown +# DEP0095/DEP0096/DEP0126/DEP0127: Deprecated `node:timers` APIs +``` + +**3. Plain descriptive title - for non-deprecation migrations** + +When the recipe does not correspond to a numbered deprecation, use a plain descriptive title. + +```markdown +# Correct TypeScript Specifiers + +# Import Assertions to Attributes + +# Chalk to `util.styleText()` +``` + +### General title rules + +- Use backticks around API names and code tokens in the title. +- Join the old and new API with the word `to`. +- Keep the title to one line. + +--- + +## Description paragraph + +Immediately after the title, write a single paragraph (no heading) that describes: + +1. What the deprecated API is and the deprecation number, if applicable. +2. What it is replaced with. +3. Any notable variant handling (e.g., destructured imports, ESM, synchronous counterparts). + +Link to the upstream deprecation notice when one exists: + +```markdown +See [DEP0147](https://nodejs.org/api/deprecations.html#DEP0147). +``` + +If the recipe covers multiple deprecations, link each one or group them in a sentence. + +**Examples of well-written description paragraphs:** + +The `rmdir` recipe describes its scope precisely: + +> Converts `fs.rmdir(path, { recursive: true })` calls to `fs.rm(path, { recursive: true, force: true })`. Also handles the synchronous variant (`fs.rmdirSync` → `fs.rmSync`), the promises variant (`fs.promises.rmdir` → `fs.promises.rm`), destructured imports, and aliased imports. The `force: true` option is always added alongside `recursive: true`. + +The `repl-classes-with-new` recipe names the affected classes and the import styles it handles: + +> Adds the missing `new` keyword to calls to `repl.REPLServer()` and `repl.Recoverable()` that are invoked as plain functions. Works with CommonJS `require`, ESM named imports, ESM namespace imports, and dynamic imports. + +--- + +## Usage section + +The `Usage` section gives the single command a reader needs to run the codemod. Use this exact structure: + +````markdown +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/ +``` +```` + +The codemod name is the `name` field declared in the recipe's `codemod.yaml` — not the directory name. The two usually match, but the registry name is what `npx codemod` resolves, and it is case-sensitive (for example, the recipe in `recipes/tmpdir-to-tmpdir/` is published as `@nodejs/tmpDir-to-tmpdir`). Always copy the name from `codemod.yaml`. For example, the recipe in `recipes/rmdir/` declares `name: "@nodejs/rmdir"` and is run with: + +```sh +npx codemod @nodejs/rmdir +``` + +If the codemod requires special flags or environment variables, document them here. See `recipes/correct-ts-specifiers/README.md` for an example of a recipe that requires `NODE_OPTIONS` to be set, along with guidance for running inside monorepos. + +--- + +## Examples section + +The `Examples` section is the most important part of the README. It shows exactly what the transformation does by deriving examples directly from the recipe's test fixtures. + +### How to derive examples from test fixtures + +Each recipe organises its tests as one directory per case, named for what the case covers, with an `input` and an `expected` file inside: `tests//input.ts` and `tests//expected.ts` (the extension matches the fixture's language). Read those files and construct `diff` blocks by diffing them line by line. Lines that are removed carry a `-` prefix; lines that are added carry a `+` prefix; lines that are unchanged and provide useful context carry a leading space. + +For example, `tests/file-1/input.js` for the `rmdir` recipe contains: + +```js +const fs = require("node:fs"); + +const pathName = "path/to/directory"; + +fs.rmdir(pathName, { recursive: true }, () => {}); +fs.rmdirSync(pathName, { recursive: true }); +fs.promises.rmdir(pathName, { recursive: true }); +fs.rmdir(pathName, { recursive: false }); // should not be transformed +fs.rmdir(pathName); // should not be transformed +``` + +The corresponding `tests/file-1/expected.js` contains: + +```js +const fs = require("node:fs"); + +const pathName = "path/to/directory"; + +fs.rm(pathName, { recursive: true, force: true }, () => {}); +fs.rmSync(pathName, { recursive: true, force: true }); +fs.promises.rm(pathName, { recursive: true, force: true }); +fs.rmdir(pathName, { recursive: false }); // should not be transformed +fs.rmdir(pathName); // should not be transformed +``` + +This pair becomes the `diff` block shown in Example 1 of the `rmdir` README. + +### Formatting diff blocks + +Always use a fenced code block with the `diff` language tag: + +````markdown +```diff +-fs.rmdir(pathName, { recursive: true }, () => { }); ++fs.rm(pathName, { recursive: true, force: true }, () => { }); +``` +```` + +Unchanged lines that provide essential context (such as the `require` statement or surrounding code) can be included without a prefix character. Omit lines that are not relevant to the transformation being illustrated. Do not pad with large blocks of unchanged code. + +### Subsections for multiple transforms + +When a recipe handles multiple distinct transformations, give each one its own `###` subsection with a short label that says what case it covers. Name subsections by the import style or the specific API variant, not by a generic "Case 1/2/3" numbering where a descriptive label is possible. + +**Good subsection names:** + +- `### Namespace require - all three API shapes are migrated` +- `### Destructured require` +- `### Aliased ESM import` +- `### Reading crypto.fips becomes crypto.getFips()` + +**Example of subsection structure:** + +````markdown +## Examples + +### Example 1 + +Namespace `require` - all three API shapes are migrated, untouched calls are left alone: + +```diff + const fs = require("node:fs"); +-fs.rmdir(pathName, { recursive: true }, () => { }); ++fs.rm(pathName, { recursive: true, force: true }, () => { }); +``` + +### Example 2 + +Destructured `require` - `rm` is added to the destructured bindings and calls are updated: + +```diff +-const { rmdir, rmdirSync } = require("node:fs"); ++const { rm, rmdir, rmSync } = require("node:fs"); +``` +```` + +When a recipe makes a single, uniform transformation across all import styles, a single `diff` block without subsections is fine. See `recipes/util-extend-to-object-assign/README.md` for an example. + +When the set of changes is better expressed as a table than as code (for example, a codemod that replaces many individual method names), a Markdown table is acceptable. See `recipes/util-is/README.md` for an example. + +### How many examples to include + +Include one example per meaningfully distinct case the codemod handles. At minimum, show one example. Show more when: + +- The recipe handles both CJS and ESM import styles differently. +- The recipe handles destructured bindings separately from namespace imports. +- The recipe has edge cases that are explicitly not transformed. + +Do not duplicate examples that differ only in whitespace or variable names. + +--- + +## Notes section + +The `Notes` section (heading `## Notes`) is for information that does not fit the description paragraph but is important for a reader running the codemod. Examples: + +- The codemod reads `package.json` to determine module type and adjusts the output accordingly. +- Internal bookkeeping fields used by the deprecated API have no public equivalent and must be reviewed manually. +- The migration is one-and-done - the output should be committed and not re-run. + +**Omit `## Notes` entirely when there is nothing to say.** Do not include an empty section or a placeholder like "N/A". + +A `### Limitations` subsection may be nested under `## Notes` when the limitations are closely related to a noted behavior: + +```markdown +## Notes + +### Limitations + +Only calls that include `{ recursive: true }` in the options argument are transformed. +Calls to `fs.rmdir` without that option are left untouched, as they do not trigger the deprecation. +``` + +--- + +## Limitations section + +The `Limitations` section (heading `## Limitations`, or `### Limitations` nested under `## Notes`) documents what the codemod explicitly does not handle. Examples: + +- The codemod cannot determine algorithm-specific key or IV sizes; the reader must review and adjust the generated scaffolding. +- `url.resolve` has no direct equivalent in the WHATWG URL API; the reader must implement custom logic. +- Cases where the input is too dynamic to analyze statically are skipped and logged. + +**Omit `## Limitations` entirely when there is nothing to say.** + +A `## Caveats` heading is also acceptable and used in some recipes as an equivalent to `## Limitations`. Use either consistently; do not use both in the same file. + +--- + +## Publishing to nodejs.org/learn + +Recipe READMEs are copied verbatim into [nodejs/learn](https://github.com/nodejs/learn) (built with [doc-kit](https://github.com/nodejs/doc-kit)) on every publish, where each one renders as an article. That imposes a few hard rules: + +- Exactly one `#` (H1) heading per file — it becomes the page title and the sidebar label. +- `authors` in the frontmatter must be a single-line, comma-separated string of GitHub usernames (see [Frontmatter](#frontmatter)); the site uses it to render linked avatars. +- Every code fence must declare a language (`js`, `sh`, `diff`, `yaml`, ...). +- GitHub-style alerts (`> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!CAUTION]`) are supported and render as call-out boxes. +- Use `-` for bullet lists, and do not prefix shell commands with `$`. +- The page must make sense on its own: spell out repository-relative context (a learn reader cannot see the recipe's source tree). + +--- + +## Checklist for a complete README + +Before opening a pull request, verify that the README: + +- [ ] Opens with a `---`-delimited frontmatter block containing `authors: ` (comma-separated on one line when there are several). +- [ ] Has a title that follows the naming convention for its type (DEP number + `to`, DEP number + description, or plain descriptive) with API names in backticks. +- [ ] Has a description paragraph that names the deprecated API, its replacement, and any notable variant handling. +- [ ] Has a `## Usage` section whose `npx codemod` command matches the `name` field in the recipe's `codemod.yaml`. +- [ ] Has a `## Examples` section with at least one `diff` block derived from the test fixtures. +- [ ] Uses `###` subsections in `## Examples` when there are multiple distinct transforms. +- [ ] Includes `## Notes` and/or `## Limitations` only when there is substantive content to put in them. +- [ ] Does not have any empty sections. diff --git a/recipes/axios-to-whatwg-fetch/README.md b/recipes/axios-to-whatwg-fetch/README.md index 56abdac3..1198dbee 100644 --- a/recipes/axios-to-whatwg-fetch/README.md +++ b/recipes/axios-to-whatwg-fetch/README.md @@ -1,142 +1,161 @@ -# Axios to WHATWG Fetch Codemod +--- +authors: brunocroh, AugustinMauroy +--- -## Description +# Axios to WHATWG Fetch -This codemod transforms code using Axios to leverage the WHATWG Fetch API, which is now natively available in Node.js. By replacing Axios with Fetch, you can reduce dependencies, mitigate risks, and improve performance. +Migrates code from the [Axios](https://axios-http.com) HTTP client to the [WHATWG Fetch](https://fetch.spec.whatwg.org) API that is natively available in Node.js as the global [`fetch`](https://nodejs.org/docs/latest/api/globals.html#fetch), reducing dependencies and improving performance. It rewrites every Axios request helper — `axios.request()`, `axios.get()`, `axios.delete()`, `axios.head()`, `axios.options()`, `axios.post()`, `axios.put()`, `axios.patch()`, `axios.postForm()`, `axios.putForm()`, and `axios.patchForm()` — and recognizes default ESM imports, aliased imports, CommonJS `require()` calls, and dynamic `import()`. Once all call sites are converted, it also removes the `axios` and `@types/axios` entries from `package.json`. -## Supported Transformations +## Usage -The codemod supports the following Axios methods and converts them to their Fetch equivalents: +Run this codemod with: -- `axios.request(config)` -- `axios.get(url[, config])` -- `axios.delete(url[, config])` -- `axios.head(url[, config])` -- `axios.options(url[, config])` -- `axios.post(url[, data[, config]])` -- `axios.put(url[, data[, config]])` -- `axios.patch(url[, data[, config]])` -- `axios.postForm(url[, data[, config]])` -- `axios.putForm(url[, data[, config]])` -- `axios.patchForm(url[, data[, config]])` -- `axios.request(config)` +```sh +npx codemod @nodejs/axios-to-whatwg-fetch +``` -### Examples +## Examples -#### GET Request +### GET request -```diff - const base = 'https://dummyjson.com/todos'; +A plain `axios.get()` becomes a `fetch()` call with a shim that keeps the `response.data` property working. -- const all = await axios.get(base); -+ const all = await fetch(base).then(async (res) => Object.assign(res, { data: await res.json() })).catch(() => null); - console.log('\nGET /todos ->', all.status); - console.log(`Preview: ${all.data.todos.length} todos`); +```diff +-import axios from "axios"; + const base = "https://dummyjson.com/todos"; + +-const all = await axios.get(base); ++const all = await fetch(base) ++ .then(async (res) => Object.assign(res, { data: await res.json() })) ++ .catch(() => null); + console.log("\nGET /todos ->", all.status); + console.log(`Preview: ${all.data.todos.length} todos`); ``` -#### POST Request +### POST request with a JSON body + +The `data` argument of `axios.post()` is serialized with `JSON.stringify()` and passed as the `body` option. ```diff - const base = 'https://dummyjson.com/todos'; - -- const created = await axios.post( -- `${base}/add`, { -- todo: 'Use DummyJSON in the project', -- completed: false, -- userId: 5, -- }, { -- headers: { 'Content-Type': 'application/json' } -- } -- ); -+ const created = await fetch(`${base}/add`, { -+ method: 'POST', -+ headers: { 'Content-Type': 'application/json' }, -+ body: JSON.stringify({ -+ todo: 'Use DummyJSON in the project', -+ completed: false, -+ userId: 5, -+ }), -+ }).then(async (res) => Object.assign(res, { data: await res.json() })); - console.log('\nPOST /todos/add ->', created.status); - console.log('Preview:', created.data?.id ? `created id ${created.data.id}` : JSON.stringify(created.data).slice(0,200)); +-import axios from 'axios'; + const base = 'https://dummyjson.com/todos/add'; + +-const todoCreated = await axios.post(base, { +- todo: 'Use DummyJSON in the project', +- completed: false, +- userId: 5, +-}); ++const todoCreated = await fetch(base, { ++ method: "POST", ++ body: JSON.stringify({ ++ todo: 'Use DummyJSON in the project', ++ completed: false, ++ userId: 5, ++ }) ++}) ++ .then(async (resp) => Object.assign(resp, { data: await resp.json() })) ++ .catch(() => null); + console.log('\nPOST /todos ->', todoCreated); ``` - #### POST Form Request - - ```diff - const formEndpoint = '/submit'; - - - const created = await axios.postForm(formEndpoint, { - - title: 'Form Demo', - - completed: false, - - }); - + const created = await fetch(formEndpoint, { - + method: 'POST', - + body: new URLSearchParams({ - + title: 'Form Demo', - + completed: false, - + }), - + }).then(async (res) => Object.assign(res, { data: await res.json() })); - console.log('Preview:', created.data); - ``` +### Form submission -#### PUT Request +`axios.postForm()` (and the `putForm`/`patchForm` variants) send the payload as `URLSearchParams`. ```diff - const base = 'https://dummyjson.com/todos'; - -- const updatedPut = await axios.put( -- `${base}/1`, -- { completed: false }, -- { headers: { 'Content-Type': 'application/json' } } -- ); -+ const updatedPut = await fetch(`${base}/1`, { -+ method: 'PUT', -+ headers: { 'Content-Type': 'application/json' }, -+ body: JSON.stringify({ completed: false }), -+ }).then(async (res) => Object.assign(res, { data: await res.json() })); - console.log('\nPUT /todos/1 ->', updatedPut.status); - console.log('Preview:', updatedPut.data?.completed !== undefined ? `completed=${updatedPut.data.completed}` : JSON.stringify(updatedPut.data).slice(0,200)); +-import axios from 'axios'; + const base = 'https://dummyjson.com/forms'; + +-const created = await axios.postForm(`${base}/submit`, { +- title: 'Form Demo', +- completed: false, +-}); ++const created = await fetch(`${base}/submit`, { ++ method: "POST", ++ body: new URLSearchParams({ ++ title: 'Form Demo', ++ completed: false, ++ }) ++}) ++ .then(async (resp) => Object.assign(resp, { data: await resp.json() })) ++ .catch(() => null); + console.log(created); ``` -#### DELETE Request +### `axios.request()` with a config object -```diff - const base = 'https://dummyjson.com/todos'; +The `url`, `method`, and `data` properties of the config object are mapped onto the `fetch()` call. -- const deleted = await axios.delete(`${base}/1`); -+ const deleted = await fetch(`${base}/1`, { method: 'DELETE' }) -+ .then(async (res) => Object.assign(res, { data: await res.json() })); - console.log('\nDELETE /todos/1 ->', deleted.status); - console.log('Preview:', deleted.data ? JSON.stringify(deleted.data).slice(0,200) : typeof deleted.data); +```diff +-import axios from 'axios'; +- + const base = 'https://dummyjson.com/todos/1'; + +-const customRequest = await axios.request({ +- url: base, +- method: 'PATCH', +- data: { +- todo: 'Updated todo', +- completed: true, +- }, +-}); ++const customRequest = await fetch(base, { ++ method: "PATCH", ++ body: JSON.stringify({ ++ todo: 'Updated todo', ++ completed: true, ++ }) ++}) ++ .then(async (resp) => Object.assign(resp, { data: await resp.json() })) ++ .catch(() => null); + console.log('\nREQUEST /todos/1 ->', customRequest); ``` -#### `request` axios Method +### CommonJS `require()` -```diff - const base = 'https://dummyjson.com/todos'; - -- const customRequest = await axios.request({ -- url: `${base}/1`, -- method: 'PATCH', -- headers: { 'Content-Type': 'application/json' }, -- data: { completed: true }, -- }); -+ const customRequest = await fetch(`${base}/1`, { -+ method: 'PATCH', -+ headers: { 'Content-Type': 'application/json' }, -+ body: JSON.stringify({ completed: true }), -+ }).then(async (res) => Object.assign(res, { data: await res.json() })); - console.log('\nPATCH /todos/1 ->', customRequest.status); - console.log('Preview:', customRequest.data?.completed !== undefined ? `completed=${customRequest.data.completed}` : JSON.stringify(customRequest.data).slice(0,200)); -``` +CommonJS modules are handled the same way, and the now-unused `require('axios')` binding is removed. -## Unsupported APIs +```diff +-const axios = require('axios'); -The codemod does not yet cover Axios features outside of direct request helpers, such as interceptors, cancel tokens, or instance configuration from `axios.create()`. + function fetchAllTodos() { +- return axios.get('https://dummyjson.com/todos'); ++ return fetch('https://dummyjson.com/todos') ++ .then(async (res) => Object.assign(res, { data: await res.json() })) ++ .catch(() => null); + } -## References + module.exports = { fetchAllTodos }; +``` -- [Fetch Spec](https://fetch.spec.whatwg.org) -- [Axios Documentation](https://axios-http.com) -- [Node.js Documentation](https://nodejs.org/docs/latest/api/globals.html#fetch) +## Notes + +- A `fetch` response exposes its payload through `res.json()` rather than a `data` property, so each converted call is followed by `.then(async (res) => Object.assign(res, { data: await res.json() }))` to keep existing `response.data` accesses working. +- Converted calls end with `.catch(() => null)`, so a failed request resolves to `null` instead of rejecting. Also note that unlike Axios, `fetch` does not reject on HTTP error statuses (4xx/5xx), so error-handling code built around Axios rejections should be reviewed manually. +- Safety first: if any Axios call in a file uses an unsupported configuration option, the entire file is left untouched and a warning with the source location is printed, preserving the original behavior. +- After the transformation, the codemod detects your package manager and removes the `axios` and `@types/axios` dependencies from `package.json`. + +### Limitations + +The codemod skips files whose Axios calls use any of the following configuration options, because they have no direct `fetch` equivalent: + +- `beforeRedirect` +- `cancelToken` +- `decompress` +- `httpAgent` +- `httpsAgent` +- `maxBodyLength` +- `maxContentLength` +- `maxRedirects` +- `paramsSerializer` +- `signal` +- `socketPath` +- `timeout` +- `transformRequest` +- `transformResponse` +- `validateStatus` +- `withCredentials` + +It also does not cover Axios features outside of the direct request helpers, such as interceptors, cancel tokens, or instance configuration created with `axios.create()`. + + diff --git a/recipes/axios-to-whatwg-fetch/codemod.yaml b/recipes/axios-to-whatwg-fetch/codemod.yaml index 72704d0f..88e393fe 100644 --- a/recipes/axios-to-whatwg-fetch/codemod.yaml +++ b/recipes/axios-to-whatwg-fetch/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/axios-to-whatwg-fetch" -version: 1.0.0 +version: 1.0.1 description: Replace `axios` with `fetch` author: Bruno Rodrigues license: MIT diff --git a/recipes/axios-to-whatwg-fetch/package.json b/recipes/axios-to-whatwg-fetch/package.json index afdc92d4..47585e7a 100644 --- a/recipes/axios-to-whatwg-fetch/package.json +++ b/recipes/axios-to-whatwg-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/axios-to-whatwg-fetch", - "version": "1.0.0", + "version": "1.0.1", "description": "Replace `axios` with `fetch`", "type": "module", "scripts": { diff --git a/recipes/buffer-atob-btoa/README.md b/recipes/buffer-atob-btoa/README.md index 2f47fc23..e2ee35b6 100644 --- a/recipes/buffer-atob-btoa/README.md +++ b/recipes/buffer-atob-btoa/README.md @@ -1,30 +1,74 @@ -# Migrate legacy `buffer.atob()` and `buffer.btoa()` APIs +--- +authors: nekojanai +--- -Migrates usage of the legacy APIs `buffer.atob()` and `buffer.btoa()` to the current recommended approaches. +# `buffer.atob()` / `buffer.btoa()` to `Buffer` methods -## Example +Migrates legacy `buffer.atob()` and `buffer.btoa()` calls to their modern `Buffer` equivalents. The `buffer` module import is removed when no other `buffer` APIs remain in use. -### Migrating buffer.atob(data) +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/buffer-atob-btoa +``` + +## Examples + +### Example 1 + +`buffer.atob()` `Buffer.from(x, 'base64').toString('binary')` + +```diff +-const buffer = require('node:buffer'); + const data = 'SGVsbG8gV29ybGQh'; // "Hello World!" in base64 +-const decodedData = buffer.atob(data); ++const decodedData = Buffer.from(data, 'base64').toString('binary'); + console.log(decodedData); // Outputs: Hello World! +``` + +### Example 2 + +`buffer.btoa()` `Buffer.from(x, 'binary').toString('base64')` + +```diff +-const buffer = require('node:buffer'); + const data = 'Hello World!'; +-const encodedData = buffer.btoa(data); ++const encodedData = Buffer.from(data, 'binary').toString('base64'); + console.log(encodedData); // Outputs: SGVsbG8gV29ybGQh +``` + +### Example 3 + +Named import — only `atob` is removed from the import; other named exports from `buffer` are preserved. ```diff -- const buffer = require('node:buffer'); -+ const data = 'SGVsbG8gV29ybGQh'; // "Hello World!" in base64 -- const data = 'SGVsbG8gV29ybGQh'; // "Hello World!" in base64 -- const decodedData = buffer.atob(data); -+ const decodedData = Buffer.from(data, 'base64').toString('binary'); - console.log(decodedData); // Outputs: Hello World! +-import { atob, isUtf8 } from "node:buffer"; ++import { isUtf8 } from "node:buffer"; + const data = 'Hello World!'; + isUtf8(data); +-atob(data); ++Buffer.from(data, 'base64').toString('binary'); ``` -### Migrating buffer.btoa(data) +### Example 4 + +When other `buffer` APIs are still referenced, the import statement is kept. ```diff -- const buffer = require('node:buffer'); -+ const data = 'Hello World!'; -- const data = 'Hello World!'; -- const encodedData = buffer.btoa(data); -+ const encodedData = Buffer.from(data, 'binary').toString('base64'); - console.log(encodedData); // Outputs: SGVsbG8gV29ybGQh + import buffer from "node:buffer"; + buffer.constants.MAX_LENGTH; + const data = 'Hello World!'; +-buffer.btoa(data); ++Buffer.from(data, 'binary').toString('base64'); ``` -## REFS -* [Node.js Documentation: Buffer](https://nodejs.org/api/buffer.html) +## Notes + +### Limitations + +The `buffer` import is only removed when no other `buffer` APIs are referenced in the file. If any other property of the `buffer` namespace is still accessed, the import statement is preserved. + + diff --git a/recipes/buffer-atob-btoa/codemod.yaml b/recipes/buffer-atob-btoa/codemod.yaml index 2e5f1b4b..eaacbe1b 100644 --- a/recipes/buffer-atob-btoa/codemod.yaml +++ b/recipes/buffer-atob-btoa/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/buffer-atob-btoa" -version: "1.0.2" +version: "1.0.3" description: Migrates usage of the legacy APIs `buffer.atob()` and `buffer.btoa()` to the current recommended approaches author: nekojanai (Jana) license: MIT diff --git a/recipes/buffer-atob-btoa/package.json b/recipes/buffer-atob-btoa/package.json index d9183778..2cd14828 100644 --- a/recipes/buffer-atob-btoa/package.json +++ b/recipes/buffer-atob-btoa/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/buffer-atob-btoa", - "version": "1.0.1", + "version": "1.0.3", "description": "Migrates usage of the legacy APIs `buffer.atob()` and `buffer.btoa()` to the current recommended approaches", "type": "module", "scripts": { diff --git a/recipes/chalk-to-util-styletext/README.md b/recipes/chalk-to-util-styletext/README.md index e0fc812d..deca5740 100644 --- a/recipes/chalk-to-util-styletext/README.md +++ b/recipes/chalk-to-util-styletext/README.md @@ -1,56 +1,75 @@ -# Chalk to util.styleText +--- +authors: richiemccoll +--- -This recipe migrates from the external `chalk` package to Node.js built-in `util.styleText` API. It transforms chalk method calls to use the native Node.js styling functionality. +# Chalk to `util.styleText()` -## Examples +Migrates usage of the `chalk` npm package to the Node.js built-in `util.styleText()` API. Replaces the `chalk` import with `{ styleText }` from `node:util` and rewrites all chalk method calls accordingly. Chained chalk styles are converted to an array of style strings. -```diff -- import chalk from 'chalk'; -+ import { styleText } from 'node:util'; -- console.log(chalk.red('Error message')); -+ console.log(styleText('red', 'Error message')); -- console.log(chalk.green('Success message')); -+ console.log(styleText('green', 'Success message')); -- console.log(chalk.blue('Info message')); -+ console.log(styleText('blue', 'Info message')); +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/chalk-to-util-styletext ``` +## Examples + +### Example 1 + +Basic color methods (ESM default import) + ```diff -- import chalk from 'chalk'; -+ import { styleText } from 'node:util'; -- console.log(chalk.red.bold('Important error')); -+ console.log(styleText(['red', 'bold'], 'Important error')); -- console.log(chalk.green.underline('Success with emphasis')); -+ console.log(styleText(['green', 'underline'], 'Success with emphasis')); +-import chalk from "chalk"; ++import { styleText } from "node:util"; + +-console.log(chalk.red("Error message")); +-console.log(chalk.green("Success message")); +-console.log(chalk.blue("Info message")); ++console.log(styleText("red", "Error message")); ++console.log(styleText("green", "Success message")); ++console.log(styleText("blue", "Info message")); ``` +### Example 2 + +Chained styles + ```diff -- const chalk = require('chalk'); -+ const { styleText } = require('node:util'); -- const red = chalk.red; -+ const red = (text) => styleText('red', text); -- const boldBlue = chalk.blue.bold; -+ const boldBlue = (text) => styleText(['blue', 'bold'], text); -- console.log(red('Error')); -+ console.log(red('Error')); -- console.log(boldBlue('Info')); -+ console.log(boldBlue('Info')); +-import chalk from "chalk"; ++import { styleText } from "node:util"; + +-console.log(chalk.red.bold("Error: Operation failed")); +-console.log(chalk.green.underline("Success: All tests passed")); +-console.log(chalk.yellow.bgBlack("Warning: Deprecated API usage")); ++console.log(styleText(["red", "bold"], "Error: Operation failed")); ++console.log(styleText(["green", "underline"], "Success: All tests passed")); ++console.log(styleText(["yellow", "bgBlack"], "Warning: Deprecated API usage")); ``` -## Usage +### Example 3 -Run this codemod with: +CommonJS `require` -```sh -npx codemod nodejs/chalk-to-util-styletext +```diff +-const chalk = require("chalk"); ++const { styleText } = require("node:util"); + +-const error = chalk.red("Error"); +-const warning = chalk.yellow("Warning"); +-const info = chalk.blue("Info"); ++const error = styleText("red", "Error"); ++const warning = styleText("yellow", "Warning"); ++const info = styleText("blue", "Info"); + + console.log(error, warning, info); ``` -## Compatibility +## Notes -- **Removes chalk dependency** from package.json automatically -- **Supports most chalk methods**: colors, background colors, and text modifiers -- **Unsupported methods**: `hex()`, `rgb()`, `ansi256()`, `bgAnsi256()`, `visible()` (warnings will be shown) +### Limitations -## Limitations +Chalk methods that have no direct `util.styleText` equivalent — including `hex()`, `rgb()`, `ansi256()`, `bgAnsi256()`, `visible()`, and `new chalk.Chalk()` — are skipped. A warning is printed for each unsupported call, and those call sites are left unchanged for manual review. -- **Complex conditional expressions** in some contexts may need manual review + diff --git a/recipes/chalk-to-util-styletext/codemod.yaml b/recipes/chalk-to-util-styletext/codemod.yaml index a59f9334..37c2b662 100644 --- a/recipes/chalk-to-util-styletext/codemod.yaml +++ b/recipes/chalk-to-util-styletext/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/chalk-to-util-styletext" -version: 1.0.2 +version: 1.0.3 capabilities: - fs - child_process diff --git a/recipes/chalk-to-util-styletext/package.json b/recipes/chalk-to-util-styletext/package.json index 40f157b4..f5c95e48 100644 --- a/recipes/chalk-to-util-styletext/package.json +++ b/recipes/chalk-to-util-styletext/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/chalk-to-util-styletext", - "version": "1.0.2", + "version": "1.0.3", "description": "Migrate from the chalk package to Node.js's built-in util.styleText API", "type": "module", "scripts": { diff --git a/recipes/correct-ts-specifiers/.codemodrc.json b/recipes/correct-ts-specifiers/.codemodrc.json index 227dd458..d656addb 100644 --- a/recipes/correct-ts-specifiers/.codemodrc.json +++ b/recipes/correct-ts-specifiers/.codemodrc.json @@ -2,7 +2,7 @@ "$schema": "https://codemod-utils.s3.us-west-1.amazonaws.com/configuration_schema.json", "name": "@nodejs/correct-ts-specifiers", "description": "Replace erroneous 'js' or omitted file extensions of import specifiers in TypeScript files.", - "version": "1.0.0", + "version": "1.0.1", "engine": "workflow", "private": false, "entry": "./src/workflow.ts", diff --git a/recipes/correct-ts-specifiers/README.md b/recipes/correct-ts-specifiers/README.md index d7796c31..d4f7c725 100644 --- a/recipes/correct-ts-specifiers/README.md +++ b/recipes/correct-ts-specifiers/README.md @@ -1,113 +1,101 @@ -# Correct TypeScript Specifiers +--- +authors: JakobJingleheimer +--- -This package transforms import specifiers from the old `tsc` (TypeScript's compiler) requirement of using `.js` file extensions in source-code to import files that are actually typescript; the corrected specifiers enable source-code to be runnable by standards-compliant software like Node.js. +# Correct TypeScript Specifiers -This is a one-and-done process, and the updated source-code should be committed to your version control (eg git); thereafter, source-code import statements should be authored compliant with the ECMAScript (JavaScript) standard. +Transforms import specifiers from the old `tsc` (TypeScript's compiler) requirement of using `.js` file extensions in source-code to import files that are actually TypeScript; the corrected specifiers enable source-code to be runnable by standards-compliant software like Node.js. This is a one-and-done process, and the updated source-code should be committed to your version control (eg git); thereafter, source-code import statements should be authored compliant with the ECMAScript (JavaScript) standard. -## Supported cases +Supported cases: -* no file extension → `.cts`, `.mts`, `.js`, `.ts`, `.d.cts`, `.d.mts`, or `.d.ts` -* `.cjs` → `.cts`, `.mjs` → `.mts`, `.js` → `.ts` -* `.js` → `.d.cts`, `.d.mts`, or `.d.ts` -* [Package.json subpath imports](https://nodejs.org/api/packages.html#subpath-imports) -* [tsconfig paths](https://www.typescriptlang.org/tsconfig/#paths) (via [`@nodejs-loaders/alias`](https://github.com/JakobJingleheimer/nodejs-loaders/blob/main/packages/alias?tab=readme-ov-file)) - * In order to subsequently run code via node, you will need to add this (or another) loader to your own project. Or, switch to [subimports](https://nodejs.org/api/packages.html#subpath-imports). -* Commonjs-like directory specifiers +- no file extension → `.cts`, `.mts`, `.js`, `.ts`, `.d.cts`, `.d.mts`, or `.d.ts` +- `.cjs` → `.cts`, `.mjs` → `.mts`, `.js` → `.ts` +- `.js` → `.d.cts`, `.d.mts`, or `.d.ts` +- [Package.json subpath imports](https://nodejs.org/api/packages.html#subpath-imports) +- [tsconfig paths](https://www.typescriptlang.org/tsconfig/#paths) (via [`@nodejs-loaders/alias`](https://github.com/JakobJingleheimer/nodejs-loaders/blob/main/packages/alias?tab=readme-ov-file)) + - In order to subsequently run code via node, you will need to add this (or another) loader to your own project. Or, switch to [subimports](https://nodejs.org/api/packages.html#subpath-imports). +- Commonjs-like directory specifiers -Before: +## Usage -```ts -import { URL } from 'node:url'; +> [!CAUTION] +> This will change your source-code. Commit any unsaved changes before running this package. -import { bar } from '@dep/bar'; -import { foo } from 'foo'; +> [!IMPORTANT] +> [`--experimental-import-meta-resolve`](https://nodejs.org/api/cli.html#--experimental-import-meta-resolve) MUST be enabled; the feature is not really experimental—it's nonstandard because it's not relevant for browsers. -import { Bird } from './Bird'; // a directory -import { Cat } from './Cat.ts'; -import { Dog } from '…/Dog/index.mjs'; // tsconfig paths -import { baseUrl } from '#config.js'; // package.json imports +Run this codemod with: -export { Zed } from './zed'; +```sh +NODE_OPTIONS="--experimental-import-meta-resolve" \ + npx codemod @nodejs/correct-ts-specifiers +``` -export const makeLink = (path: URL) => (new URL(path, baseUrl)).href; +### Monorepos -const nil = await import('./nil.js'); +For best results, run this _within_ each workspace of the monorepo. -const bird = new Bird('Tweety'); -const cat = new Cat('Milo'); -const dog = new Dog('Otis'); +```text +project-root/ + ├ workspaces/ + ├ foo/ ←--------- RUN HERE + ├ … + ├ package.json + └ tsconfig.json + └ bar/ ←--------- RUN HERE + ├ … + ├ package.json + └ tsconfig.json + └ utils/ ←--------- RUN HERE + ├ qux.js + └ zed.js ``` -After: +## Examples -```ts -import { URL } from 'node:url'; +```diff + import { URL } from 'node:url'; -import { bar } from '@dep/bar'; -import { foo } from 'foo'; + import { bar } from '@dep/bar'; + import { foo } from 'foo'; -import { Bird } from './Bird/index.ts'; -import { Cat } from './Cat.ts'; -import { Dog } from '…/Dog/index.mts'; // tsconfig paths -import { baseUrl } from '#config.js'; // package.json imports +-import { Bird } from './Bird'; ++import { Bird } from './Bird/index.ts'; + import { Cat } from './Cat.ts'; +-import { Dog } from '…/Dog/index.mjs'; ++import { Dog } from '…/Dog/index.mts'; + import { baseUrl } from '#config.js'; +-import { qux } from './qux.js'; ++import { qux } from './qux.js/index.ts'; -export type { Zed } from './zed.d.ts'; +-export { Zed } from './zed'; ++export type { Zed } from './zed.d.ts'; -export const makeLink = (path: URL) => (new URL(path, baseUrl)).href; - -const nil = await import('./nil.ts'); - -const bird = new Bird('Tweety'); -const cat = new Cat('Milo'); -const dog = new Dog('Otis'); +-const nil = await import('./nil.js'); ++const nil = await import('./nil.ts'); ``` > [!TIP] > Those using `tsc` to compile will need to enable [`rewriteRelativeImportExtensions`](https://www.typescriptlang.org/tsconfig/#rewriteRelativeImportExtensions); using `tsc` for only type-checking (ex via a lint/test step like `npm run test:types`) needs [`allowImportingTsExtensions`](https://www.typescriptlang.org/tsconfig/#allowImportingTsExtensions) (and some additional compile options—see the cited documentation); +## Notes + This package does not just blindly find & replace file extensions within specifiers: It confirms that the replacement specifier actually exists; in ambiguous cases (such as two files with the same basename in the same location but different relevant file extensions like `/tmp/foo.js` and `/tmp/foo.ts`), it logs an error, skips that specifier, and continues processing. > [!CAUTION] -> This package does not confirm that imported modules contain the desired export(s). This _shouldn't_ actually ever result in a problem because ambiguous cases are skipped (so if there is a problem, it existed before the migration started). Merely running your source-code after the mirgration completes will confirm all is well (if there are problems, node will error, citing the problems). +> This package does not confirm that imported modules contain the desired export(s). This _shouldn't_ actually ever result in a problem because ambiguous cases are skipped (so if there is a problem, it existed before the migration started). Merely running your source-code after the migration completes will confirm all is well (if there are problems, node will error, citing the problems). > [!TIP] > Node.js requires the `type` keyword be present on type imports. For own code, this package usually handles that. However, in some cases and for node modules, it does not. Robust tooling already exists that will automatically fix this, such as > -> * [`use-import-type` via biome](https://biomejs.dev/linter/rules/use-import-type/) -> * [`typescript/no-import-type-side-effects` via oxlint](https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-import-type-side-effects) -> * [`consistent-type-imports` via typescript-lint](https://typescript-eslint.io/rules/consistent-type-imports) +> - [`use-import-type` via biome](https://biomejs.dev/linter/rules/use-import-type/) +> - [`typescript/no-import-type-side-effects` via oxlint](https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-import-type-side-effects) +> - [`consistent-type-imports` via typescript-lint](https://typescript-eslint.io/rules/consistent-type-imports) > > If your source code needs that, first run this codemod and then one of those fixers. -## Running +### Limitations -> [!CAUTION] -> This will change your source-code. Commit any unsaved changes before running this package. - -> [!IMPORTANT] -> [`--experimental-import-meta-resolve`](https://nodejs.org/api/cli.html#--experimental-import-meta-resolve) MUST be enabled; the feature is not really experimental—it's nonstandard because it's not relevant for browsers. - -```console -$ NODE_OPTIONS="--experimental-import-meta-resolve" \ - npx codemod@latest @nodejs/correct-ts-specifiers -``` +When both a `.js` file and a corresponding `.ts` file exist at the same path, the codemod cannot determine which one the specifier refers to. In that case it logs an error, leaves the specifier unchanged, and continues processing the rest of the file. -### Monorepos - -For best results, run this _within_ each workspace of the monorepo. - -```text -project-root/ - ├ workspaces/ - ├ foo/ ←--------- RUN HERE - ├ … - ├ package.json - └ tsconfig.json - └ bar/ ←--------- RUN HERE - ├ … - ├ package.json - └ tsconfig.json - └ utils/ ←--------- RUN HERE - ├ qux.js - └ zed.js -``` + diff --git a/recipes/correct-ts-specifiers/package.json b/recipes/correct-ts-specifiers/package.json index e1c81b0e..69bcd682 100644 --- a/recipes/correct-ts-specifiers/package.json +++ b/recipes/correct-ts-specifiers/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/correct-ts-specifiers", - "version": "1.0.0", + "version": "1.0.1", "description": "Replace erroneous 'js' or omitted file extensions of import specifiers in TypeScript files.", "type": "module", "main": "./src/workflow.ts", diff --git a/recipes/create-require-from-path/README.md b/recipes/create-require-from-path/README.md index 0a084754..9548af44 100644 --- a/recipes/create-require-from-path/README.md +++ b/recipes/create-require-from-path/README.md @@ -1,19 +1,56 @@ -# `createRequireFromPath` DEP0130 +--- +authors: AugustinMauroy +--- -This recipe transforms the usage of `createRequireFromPath` to use the `createRequire` function from the `node:module` module. +# DEP0130: `module.createRequireFromPath()` to `module.createRequire()` -See [DEP0130](https://nodejs.org/api/deprecations.html#DEP0130). +Replaces the deprecated `createRequireFromPath` function with `createRequire` from `node:module`. Updates both the import/require declaration and all call sites, including aliased imports. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/create-require-from-path +``` + +## Examples + +### Example 1 + +CommonJS require + +```diff +-const { createRequireFromPath } = require('module'); ++const { createRequire } = require('module'); + +-const require = createRequireFromPath('/path/to/module') ++const require = createRequire('/path/to/module') + const myModule = require('./myModule.cjs'); +``` + +### Example 2 + +ESM named import + +```diff +-import { createRequireFromPath } from 'module'; ++import { createRequire } from 'module'; + +-const require = createRequireFromPath(import.meta.url); ++const require = createRequire(import.meta.url); + const data = require('./data.json'); +``` + +### Example 3 + +Aliased import — the alias is preserved; only the imported name changes. ```diff -- const { createRequireFromPath } = require('node:module'); -+ const { createRequire } = require('node:module'); - - // Using createRequireFromPath -- const requireFromPath = createRequireFromPath('/path/to/module'); -+ // Using createRequire with a specific path -+ const require = createRequire('/path/to/module'); -- const myModule = requireFromPath('./myModule.cjs'); -+ const myModule = require('./myModule.cjs'); +-import { other as bar, createRequireFromPath as foo } from "../index.mjs"; ++import { other as bar, createRequire as foo } from "../index.mjs"; + + const r3 = foo("/path/to/module"); ``` + + diff --git a/recipes/create-require-from-path/codemod.yaml b/recipes/create-require-from-path/codemod.yaml index 5443a7ce..e0d49cba 100644 --- a/recipes/create-require-from-path/codemod.yaml +++ b/recipes/create-require-from-path/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/create-require-from-path" -version: "1.1.2" +version: "1.1.3" description: Handle DEP0130 via transforming `createRequireFromPath` to `createRequire`. author: Augustin Mauroy license: MIT diff --git a/recipes/create-require-from-path/package.json b/recipes/create-require-from-path/package.json index 3e8aed99..a7a95a8e 100644 --- a/recipes/create-require-from-path/package.json +++ b/recipes/create-require-from-path/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/create-require-from-path", - "version": "1.1.2", + "version": "1.1.3", "description": "Handle DEP0130 via transforming `createRequireFromPath` to `createRequire`.", "type": "module", "scripts": { diff --git a/recipes/createCredentials-to-createSecureContext/README.md b/recipes/createCredentials-to-createSecureContext/README.md index 33d1690b..e40f1b1a 100644 --- a/recipes/createCredentials-to-createSecureContext/README.md +++ b/recipes/createCredentials-to-createSecureContext/README.md @@ -1,24 +1,66 @@ -# `crypto.createCredentials` DEP0010 +--- +authors: 0hmx +--- -This recipe transforms `crypto.createCredentials` usage to use modern `node:tls` methods. +# DEP0010: `crypto.createCredentials()` to `tls.createSecureContext()` -See [DEP0010](https://nodejs.org/api/deprecations.html#DEP0010). +Replaces the deprecated `crypto.createCredentials()` with `tls.createSecureContext()` from `node:tls`. Updates the import or require statement accordingly, handling namespace imports, named imports, and dynamic imports. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/createCredentials-to-createSecureContext +``` ## Examples +### Example 1 + +Named ESM import + +```diff +-import { createCredentials } from 'node:crypto'; ++import { createSecureContext } from 'node:tls'; + +-const credentials = createCredentials({ ++const credentials = createSecureContext({ + key: privateKey, + cert: certificate, + ca: [caCertificate] + }); +``` + +### Example 2 + +Named CommonJS require + +```diff +-const { createCredentials } = require('node:crypto'); ++const { createSecureContext } = require('node:tls'); + +-const credentials = createCredentials({ ++const credentials = createSecureContext({ + key: privateKey, + cert: certificate, + ca: [caCertificate] + }); +``` + +### Example 3 + +Namespace ESM import + ```diff - // Using the deprecated createCredentials from node:crypto -- const { createCredentials } = require('node:crypto'); -+ // Updated to use createSecureContext from node:tls -+ const { createSecureContext } = require('node:tls'); - // OR -- import { createCredentials } from 'node:crypto'; -+ import { createSecureContext } from 'node:tls'; - -- const credentials = createCredentials({ -+ const credentials = createSecureContext({ - key: privateKey, - cert: certificate, - ca: [caCertificate] - }); +-import * as crypto from 'node:crypto'; ++import * as tls from 'node:tls'; + +-const credentials = crypto.createCredentials({ ++const credentials = tls.createSecureContext({ + key: fs.readFileSync('server-key.pem'), + cert: fs.readFileSync('server-cert.pem') + }); ``` + + diff --git a/recipes/createCredentials-to-createSecureContext/codemod.yaml b/recipes/createCredentials-to-createSecureContext/codemod.yaml index 9363d49d..a97eff5c 100644 --- a/recipes/createCredentials-to-createSecureContext/codemod.yaml +++ b/recipes/createCredentials-to-createSecureContext/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/createCredentials-to-createSecureContext" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0010 via transforming `crypto.createCredentials` to `tls.createSecureContext` author: 0hmx license: MIT diff --git a/recipes/createCredentials-to-createSecureContext/package.json b/recipes/createCredentials-to-createSecureContext/package.json index 0dec9319..1ec6e41f 100644 --- a/recipes/createCredentials-to-createSecureContext/package.json +++ b/recipes/createCredentials-to-createSecureContext/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/createcredentials-to-createsecurecontext", - "version": "1.0.1", + "version": "1.0.3", "description": "Handle DEP0010 via transforming `crypto.createCredentials` to `tls.createSecureContext` with the appropriate options.", "type": "module", "scripts": { diff --git a/recipes/crypto-createcipheriv-migration/README.md b/recipes/crypto-createcipheriv-migration/README.md index 658ba5f2..48221164 100644 --- a/recipes/crypto-createcipheriv-migration/README.md +++ b/recipes/crypto-createcipheriv-migration/README.md @@ -1,36 +1,80 @@ -# crypto-createcipheriv-migration +--- +authors: AugustinMauroy +--- -> Migrates deprecated `crypto.createCipher()` / `crypto.createDecipher()` usage to the supported `crypto.createCipheriv()` / `crypto.createDecipheriv()` APIs with explicit key derivation and IV handling. +# DEP0106: `crypto.createCipher()` to `crypto.createCipheriv()` -## Why? +Replaces the removed `crypto.createCipher()` and `crypto.createDecipher()` with `crypto.createCipheriv()` and `crypto.createDecipheriv()`. Because the new APIs require an explicit key and IV, the codemod wraps each call site in an IIFE that derives a key via `scryptSync` and generates a random IV via `randomBytes`. For decryption calls, placeholder comments are inserted to remind you to supply the salt and IV that were stored during encryption. -Node.js removed `crypto.createCipher()` and `crypto.createDecipher()` in v22.0.0 ([DEP0106](https://nodejs.org/api/deprecations.html#DEP0106)). The legacy helpers derived keys with MD5 and no salt, and silently reused static IVs. This codemod replaces those calls with the modern, explicit APIs and scaffolds secure key derivation and IV management. +## Usage -## What it does +Run this codemod with: -- Detects CommonJS and ESM imports of `crypto` (including destructured bindings). -- Replaces invocations of `createCipher()` / `createDecipher()` with `createCipheriv()` / `createDecipheriv()`. -- Inserts scaffolding that derives keys with `crypto.scryptSync()` and generates random salts and IVs. -- Reminds developers to persist salt + IV for decryption and to adjust key/IV lengths per algorithm. -- Updates destructured imports to include the new helpers (`createCipheriv`, `createDecipheriv`, `randomBytes`, `scryptSync`). +```sh +npx codemod @nodejs/crypto-createcipheriv-migration +``` + +## Examples + +### Example 1 -## Example +Namespace CommonJS require — `createCipher` ```diff + const crypto = require("node:crypto"); + + const algorithm = "aes-256-cbc"; + const password = "s3cret"; -const cipher = crypto.createCipher(algorithm, password); +const cipher = (() => { -+ const __dep0106Salt = crypto.randomBytes(16); -+ const __dep0106Key = crypto.scryptSync(password, __dep0106Salt, 32); -+ const __dep0106Iv = crypto.randomBytes(16); -+ // DEP0106: Persist __dep0106Salt and __dep0106Iv alongside the ciphertext so it can be decrypted later. -+ return crypto.createCipheriv(algorithm, __dep0106Key, __dep0106Iv); ++ const __dep0106Salt = crypto.randomBytes(16); ++ const __dep0106Key = crypto.scryptSync(password, __dep0106Salt, 32); ++ const __dep0106Iv = crypto.randomBytes(16); ++ // DEP0106: Persist __dep0106Salt and __dep0106Iv with the ciphertext so it can be decrypted later. ++ // DEP0106: Adjust the derived key length (32 bytes) and IV length to match the chosen algorithm. ++ return crypto.createCipheriv(algorithm, __dep0106Key, __dep0106Iv); ++})(); +``` + +### Example 2 + +Destructured CommonJS require — `createCipher`; `randomBytes` and `scryptSync` are added to the destructured binding. + +```diff +-const { createCipher } = require("node:crypto"); ++const { createCipheriv: createCipher, randomBytes, scryptSync } = require("node:crypto"); + +-const cipher = createCipher("aes-128-cbc", "password123"); ++const cipher = (() => { ++ const __dep0106Salt = randomBytes(16); ++ const __dep0106Key = scryptSync("password123", __dep0106Salt, 32); ++ const __dep0106Iv = randomBytes(16); ++ // DEP0106: Persist __dep0106Salt and __dep0106Iv with the ciphertext so it can be decrypted later. ++ // DEP0106: Adjust the derived key length (32 bytes) and IV length to match the chosen algorithm. ++ return createCipher("aes-128-cbc", __dep0106Key, __dep0106Iv); ++})(); +``` + +### Example 3 + +Namespace CommonJS require — `createDecipher`; placeholder TODOs are inserted for the salt and IV that must be retrieved from storage. + +```diff + const crypto = require("crypto"); + +-const decipher = crypto.createDecipher("aes-256-cbc", "pw"); ++const decipher = (() => { ++ // DEP0106: Replace the placeholders below with the salt and IV that were stored with the ciphertext. ++ const __dep0106Salt = /* TODO: stored salt Buffer */ Buffer.alloc(16); ++ const __dep0106Iv = /* TODO: stored IV Buffer */ Buffer.alloc(16); ++ const __dep0106Key = crypto.scryptSync("pw", __dep0106Salt, 32); ++ // DEP0106: Ensure __dep0106Salt and __dep0106Iv match the values used during encryption. ++ return crypto.createDecipheriv("aes-256-cbc", __dep0106Key, __dep0106Iv); +})(); ``` -## Caveats +## Notes + +The generated IIFE scaffolding uses `scryptSync` for key derivation and `randomBytes` for IV/salt generation. The salt produced during encryption **must** be stored alongside the ciphertext and supplied again at decryption time — the `// DEP0106: Persist ...` comment highlights this. The default derived-key length is 32 bytes and the IV length is 16 bytes; review these values and adjust them to match the requirements of your chosen algorithm. -- The codemod cannot guarantee algorithm-specific key/IV sizes. Review the generated `scryptSync` length and IV length defaults and adjust as needed. -- Decryption snippets include placeholders (`Buffer.alloc(16)`) that must be replaced with the salt and IV stored during encryption. -- If your project already wraps key derivation logic, you may prefer to adapt the generated scaffolding to call existing helpers. -- The generated code is not backward-compatible and will be unable to decrypt data that was encrypted using `createCipher()`. -- The use of scrypt is one possible choice for deriving a key from a password, but you may wish to use Argon2id or PBKDF2 instead. + diff --git a/recipes/crypto-createcipheriv-migration/codemod.yaml b/recipes/crypto-createcipheriv-migration/codemod.yaml index e68361e4..e3bde435 100644 --- a/recipes/crypto-createcipheriv-migration/codemod.yaml +++ b/recipes/crypto-createcipheriv-migration/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-createcipheriv-migration" -version: 1.0.0 +version: 1.0.1 description: Replace removed `crypto.createCipher()`/`createDecipher()` with `crypto.createCipheriv()`/`createDecipheriv()` and secure key derivation (DEP0106) author: Augustin Mauroy license: MIT diff --git a/recipes/crypto-createcipheriv-migration/package.json b/recipes/crypto-createcipheriv-migration/package.json index 13dba10c..95fd3128 100644 --- a/recipes/crypto-createcipheriv-migration/package.json +++ b/recipes/crypto-createcipheriv-migration/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-createcipheriv-migration", - "version": "1.0.0", + "version": "1.0.1", "description": "Migrate deprecated crypto.createCipher()/createDecipher() (DEP0106) to crypto.createCipheriv()/createDecipheriv() with secure key derivation.", "type": "module", "scripts": { diff --git a/recipes/crypto-fips-to-getFips/README.md b/recipes/crypto-fips-to-getFips/README.md index cba47eec..81ae927d 100644 --- a/recipes/crypto-fips-to-getFips/README.md +++ b/recipes/crypto-fips-to-getFips/README.md @@ -1,31 +1,71 @@ -# `crypto.fips` DEP0093 +--- +authors: max-programming +--- -This recipe transforms the usage from the deprecated `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`. +# DEP0093: `crypto.fips` to `crypto.getFips()` / `crypto.setFips()` -See [DEP0093](https://nodejs.org/api/deprecations.html#DEP0093). +Replaces the deprecated `crypto.fips` property with the `crypto.getFips()` and `crypto.setFips()` functions. Reading `crypto.fips` becomes a call to `crypto.getFips()`, and assigning to `crypto.fips` becomes a call to `crypto.setFips(value)`. Both namespace imports (`const crypto = require('crypto')`) and destructured imports (`const { fips } = require('crypto')`) are handled, including ESM `import` syntax. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/crypto-fips-to-getFips +``` ## Examples +### Example 1 + +Reading `crypto.fips` becomes `crypto.getFips()`. + +```diff + const crypto = require("node:crypto"); + +-if (crypto.fips) { ++if (crypto.getFips()) { + console.log("FIPS mode is enabled"); + } +``` + +### Example 2 + +Assigning to `crypto.fips` becomes `crypto.setFips(value)`. + +```diff + const crypto = require("node:crypto"); + +-crypto.fips = true; ++crypto.setFips(true); +``` + +### Example 3 + +Both read and write usages are handled in the same file. + ```diff - import crypto from "node:crypto"; -- import { fips } from "node:crypto"; -+ import { getFips, setFips } from "node:crypto"; - - // Using crypto.fips -- crypto.fips; -+ crypto.getFips(); -- fips; -+ getFips(); - - // Using crypto.fips = true -- crypto.fips = true; -+ crypto.setFips(true); -- fips = true; -+ setFips(true); - - // Using crypto.fips = false -- crypto.fips = false; -+ crypto.setFips(false); -- fips = false; -+ setFips(false); + const crypto = require("node:crypto"); + + if (process.env.ENABLE_FIPS === "true") { +- crypto.fips = true; ++ crypto.setFips(true); + } +-console.log("FIPS enabled:", crypto.fips); ++console.log("FIPS enabled:", crypto.getFips()); ``` + +### Example 4 + +Works with ESM default imports. + +```diff + import crypto from "node:crypto"; + +-const fipsStatus = crypto.fips; +-crypto.fips = !fipsStatus; ++const fipsStatus = crypto.getFips(); ++crypto.setFips(!fipsStatus); +``` + + diff --git a/recipes/crypto-fips-to-getFips/codemod.yaml b/recipes/crypto-fips-to-getFips/codemod.yaml index 8aa21026..64628fdf 100644 --- a/recipes/crypto-fips-to-getFips/codemod.yaml +++ b/recipes/crypto-fips-to-getFips/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-fips-to-getFips" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()` author: Usman S. license: MIT diff --git a/recipes/crypto-fips-to-getFips/package.json b/recipes/crypto-fips-to-getFips/package.json index 3a337202..6610a793 100644 --- a/recipes/crypto-fips-to-getFips/package.json +++ b/recipes/crypto-fips-to-getFips/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-fips-to-getFips", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`", "type": "module", "scripts": { diff --git a/recipes/crypto-rsa-pss-update/README.md b/recipes/crypto-rsa-pss-update/README.md index aea713f2..becd8602 100644 --- a/recipes/crypto-rsa-pss-update/README.md +++ b/recipes/crypto-rsa-pss-update/README.md @@ -1,49 +1,73 @@ -# crypto-rsa-pss-update +--- +authors: nievasdev +--- -Codemod to handle Node.js crypto deprecation [DEP0154](https://nodejs.org/docs/latest/api/deprecations.html#DEP0154) by transforming deprecated RSA-PSS key generation options. +# DEP0154: RSA-PSS `hash` / `mgf1Hash` to `hashAlgorithm` / `mgf1HashAlgorithm` -## What it does +Renames the deprecated `hash` and `mgf1Hash` options in RSA-PSS key generation calls to `hashAlgorithm` and `mgf1HashAlgorithm` respectively. Applies to both `crypto.generateKeyPair()` and `crypto.generateKeyPairSync()`, as well as promisified wrappers created with `util.promisify()`. -This codemod transforms deprecated RSA-PSS crypto options in `crypto.generateKeyPair()` and `crypto.generateKeyPairSync()` calls: +## Usage -- `hash` → `hashAlgorithm` -- `mgf1Hash` → `mgf1HashAlgorithm` +Run this codemod with: -The transformation only applies to calls with `'rsa-pss'` as the key type. +```sh +npx codemod @nodejs/crypto-rsa-pss-update +``` + +## Examples -## Supports +### Example 1 -- Both `crypto.generateKeyPair()` and `crypto.generateKeyPairSync()` -- Destructured imports: `const { generateKeyPair } = require('crypto')` -- Variable references: `const options = { hash: 'sha256' }` -- Function calls: `getKeyOptions()` returning crypto options -- This property patterns: `this.options = { hash: 'sha256' }` -- Only transforms `'rsa-pss'` key type calls -- Preserves all other options and call structure +Transforms `hash` and `mgf1Hash` in inline options objects. -## Examples +```diff + const crypto = require('crypto'); + + crypto.generateKeyPair('rsa-pss', { + modulusLength: 2048, +- hash: 'sha256', ++ hashAlgorithm: 'sha256', + saltLength: 32 + }, (err, publicKey, privateKey) => { + console.log('Generated keys'); + }); + + crypto.generateKeyPairSync('rsa-pss', { + modulusLength: 2048, +- hash: 'sha256', +- mgf1Hash: 'sha1' ++ hashAlgorithm: 'sha256', ++ mgf1HashAlgorithm: 'sha1' + }); +``` + +### Example 2 + +Works with ESM namespace imports. ```diff -const crypto = require("node:crypto"); - -crypto.generateKeyPair( - "rsa-pss", - { - modulusLength: 2048, -- hash: "sha256", -- mgf1Hash: "sha1", -+ hashAlgorithm: "sha256", -+ mgf1HashAlgorithm: "sha1", - saltLength: 32, - }, - (err, publicKey, privateKey) => { - // callback - }, -); - -crypto.generateKeyPairSync("rsa-pss", { - modulusLength: 2048, -- hash: "sha256", -+ hashAlgorithm: "sha256", -}); + import * as crypto from 'node:crypto'; + + crypto.generateKeyPair('rsa-pss', { + modulusLength: 2048, +- hash: 'sha256', ++ hashAlgorithm: 'sha256', + saltLength: 32 + }, (err, publicKey, privateKey) => { + console.log('Generated keys'); + }); + + crypto.generateKeyPairSync('rsa-pss', { + modulusLength: 2048, +- mgf1Hash: 'sha256' ++ mgf1HashAlgorithm: 'sha256' + }); ``` + +## Notes + +### Limitations + +Only transforms calls where the key type argument is the literal string `'rsa-pss'`. Calls using other key types such as `'rsa'` or `'ed25519'` are left untouched, even if they happen to contain a `hash` property. + + diff --git a/recipes/crypto-rsa-pss-update/codemod.yaml b/recipes/crypto-rsa-pss-update/codemod.yaml index 2ed16465..5b9acf88 100644 --- a/recipes/crypto-rsa-pss-update/codemod.yaml +++ b/recipes/crypto-rsa-pss-update/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-rsa-pss-update" -version: 1.0.2 +version: 1.0.3 description: >- Handle DEP0154 via transforming deprecated RSA-PSS crypto options `hash` to `hashAlgorithm` and `mgf1Hash` to `mgf1HashAlgorithm` diff --git a/recipes/crypto-rsa-pss-update/package.json b/recipes/crypto-rsa-pss-update/package.json index 650941ab..a03f1016 100644 --- a/recipes/crypto-rsa-pss-update/package.json +++ b/recipes/crypto-rsa-pss-update/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-rsa-pss-update", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0154 via transforming deprecated RSA-PSS crypto options `hash` to `hashAlgorithm` and `mgf1Hash` to `mgf1HashAlgorithm`.", "type": "module", "scripts": { diff --git a/recipes/dirent-path-to-parent-path/README.md b/recipes/dirent-path-to-parent-path/README.md index ec3c9db1..9a03655b 100644 --- a/recipes/dirent-path-to-parent-path/README.md +++ b/recipes/dirent-path-to-parent-path/README.md @@ -1,30 +1,80 @@ -# `dirent.path` DEP0178 +--- +authors: brunocroh +--- -This codemod transforms the usage of `dirent.path` to use `dirent.parentPath`. +# DEP0178: `dirent.path` to `dirent.parentPath` -See [DEP0178](https://nodejs.org/api/deprecations.html#DEP0178). +Replaces `dirent.path` with `dirent.parentPath` for `fs.Dirent` objects obtained from `fs.readdir()`, `fs.readdirSync()`, and `fs.opendir()` calls (including their `fs/promises` equivalents). Handles `for...of` loops, array methods like `forEach`, and destructured parameters. -## Example +## Usage -### readdir +Run this codemod with: + +```sh +npx codemod @nodejs/dirent-path-to-parent-path +``` + +## Examples + +### Example 1 + +`dirent.path` inside a `for...of` loop over `readdir` results. ```diff - const { readdir } = require('node:fs/promises'); - const entries = await readdir('/some/path', { withFileTypes: true }); - for (const dirent of entries) { -- console.log(dirent.path); -+ console.log(dirent.parentPath); - } + const { readdir } = require('node:fs/promises'); + + const entries = await readdir('/some/path', { withFileTypes: true }); + for (const dirent of entries) { +- console.log(dirent.path); ++ console.log(dirent.parentPath); + } ``` +### Example 2 -### opendir +`dirent.path` inside a `forEach` callback with an arrow function. ```diff - import { opendir } from 'node:fs/promises'; - const dir = await opendir('./'); - for await (const dirent of dir) { -- console.log(`Found ${dirent.name} in ${dirent.path}`); -+ console.log(`Found ${dirent.name} in ${dirent.parentPath}`); - } + import { readdir } from 'node:fs/promises'; + + const entries = await readdir('./directory', { withFileTypes: true }); + entries.forEach((dirent) => { +- const fullPath = `${dirent.path}/${dirent.name}`; ++ const fullPath = `${dirent.parentPath}/${dirent.name}`; + console.log(fullPath); + }); ``` + +### Example 3 + +Destructured `path` parameter in a callback passed to `fs.readdir`. + +```diff + const fs = require('node:fs'); + + fs.readdir('/path', { withFileTypes: true }, (err, dirents) => { + if (err) throw err; + +- dirents.forEach(({ name, path, isDirectory }) => { +- console.log(`${name} in ${path}`); ++ dirents.forEach(({ name, parentPath, isDirectory }) => { ++ console.log(`${name} in ${parentPath}`); + }); + }); +``` + +### Example 4 + +`dirent.path` inside a `for await...of` loop over `opendir` results. + +```diff + import { opendir } from 'node:fs/promises'; + + const dir = await opendir('./'); + for await (const dirent of dir) { +- console.log(`Found ${dirent.name} in ${dirent.path}`); ++ console.log(`Found ${dirent.name} in ${dirent.parentPath}`); + } +``` + + diff --git a/recipes/dirent-path-to-parent-path/codemod.yaml b/recipes/dirent-path-to-parent-path/codemod.yaml index ba8440b3..c305873a 100644 --- a/recipes/dirent-path-to-parent-path/codemod.yaml +++ b/recipes/dirent-path-to-parent-path/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/dirent-path-to-parent-path" -version: 1.0.1 +version: 1.0.2 description: Handle DEP0178 via transforming `dirent.path` to `dirent.parentPath`. author: Bruno Rodrigues license: MIT diff --git a/recipes/dirent-path-to-parent-path/package.json b/recipes/dirent-path-to-parent-path/package.json index 9a166cb4..7411eea3 100644 --- a/recipes/dirent-path-to-parent-path/package.json +++ b/recipes/dirent-path-to-parent-path/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/dirent-path-to-parent-path", - "version": "1.0.1", + "version": "1.0.2", "description": "Handle DEP0178 via transforming `dirent.path` to `dirent.parentPath`", "type": "module", "scripts": { diff --git a/recipes/dns-lookup-options-coercion/README.md b/recipes/dns-lookup-options-coercion/README.md index 415cb7f3..23c84cdf 100644 --- a/recipes/dns-lookup-options-coercion/README.md +++ b/recipes/dns-lookup-options-coercion/README.md @@ -1,25 +1,67 @@ -# dns.lookup options type coercion DEP0153 +--- +authors: Herrtian +--- -Handle DEP0153 by converting literal `dns.lookup()` and `dnsPromises.lookup()` option values to their proper types. +# DEP0153: `dns.lookup` Options Type Coercion -See [DEP0153](https://nodejs.org/api/deprecations.html#dep0153-dnslookup-and-dnspromiseslookup-options-type-coercion). +Node.js used to coerce the values of the `family`, `hints`, `all`, and `verbatim` options passed to `dns.lookup()` and `dnsPromises.lookup()` — for example, treating `family: "4"` as `family: 4`. This implicit coercion is deprecated, and newer versions of Node.js throw an `ERR_INVALID_ARG_TYPE` error instead. This codemod converts literal option values to their proper types, resolving `lookup` bindings from both `node:dns` and `node:dns/promises` across CommonJS and ESM, including namespace, destructured, and aliased imports. See [DEP0153](https://nodejs.org/api/deprecations.html#DEP0153). -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/dns-lookup-options-coercion +``` + +## Examples + +### `dns.lookup` with literal options + +Numeric options given as strings become numbers, and `0`/`1` flags become booleans. ```diff - const dns = require("node:dns"); + const dns = require("node:dns"); -- dns.lookup("example.com", { family: "4", all: 1 }, callback); -+ dns.lookup("example.com", { family: 4, all: true }, callback); +-dns.lookup("example.com", { family: "4", hints: "0", all: 1, verbatim: 0 }, callback); ++dns.lookup("example.com", { family: 4, hints: 0, all: true, verbatim: false }, callback); ``` +### Destructured `lookup` import + +String booleans such as `"false"` are converted too, whatever form the binding takes. + ```diff - import { lookup } from "node:dns/promises"; + const { lookup } = require("node:dns"); -- await lookup("example.com", { family: "6", verbatim: 0 }); -+ await lookup("example.com", { family: 6, verbatim: false }); +-lookup("example.com", { family: "4", all: "false" }, callback); ++lookup("example.com", { family: 4, all: false }, callback); +``` + +### `node:dns/promises` + +The promises API is handled the same way. + +```diff + import { lookup } from "node:dns/promises"; + +-await lookup("example.com", { family: "6", all: "true" }); ++await lookup("example.com", { family: 6, all: true }); +``` + +### Aliased `promises` namespace + +Aliased bindings of the `promises` export are resolved as well. + +```diff + import { promises as dnsPromises } from "node:dns"; + +-await dnsPromises.lookup("example.com", { family: "4", verbatim: "false" }); ++await dnsPromises.lookup("example.com", { family: 4, verbatim: false }); ``` ## Limitations -This recipe only changes literal option values. Dynamic values such as `{ family: familyOption }` need manual review. +This recipe only changes literal option values written inline in the `lookup()` call. Dynamic values such as `{ family: familyOption }`, constants like `dns.ADDRCONFIG`, and options objects stored in a variable are intentionally left unchanged and need manual review. + + diff --git a/recipes/dns-lookup-options-coercion/codemod.yaml b/recipes/dns-lookup-options-coercion/codemod.yaml index a6f1ec3f..7cf36afb 100644 --- a/recipes/dns-lookup-options-coercion/codemod.yaml +++ b/recipes/dns-lookup-options-coercion/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/dns-lookup-options-coercion" -version: "1.0.0" +version: "1.0.1" description: Handle DEP0153 by converting literal dns.lookup option values to their proper types. author: Herrtian license: MIT diff --git a/recipes/dns-lookup-options-coercion/package.json b/recipes/dns-lookup-options-coercion/package.json index 556624e2..4e97c56c 100644 --- a/recipes/dns-lookup-options-coercion/package.json +++ b/recipes/dns-lookup-options-coercion/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/dns-lookup-options-coercion", - "version": "1.0.0", + "version": "1.0.1", "description": "Handle DEP0153 by converting literal dns.lookup option values to their proper types", "type": "module", "scripts": { diff --git a/recipes/err-invalid-callback/README.md b/recipes/err-invalid-callback/README.md index cd6adb98..a5e00d18 100644 --- a/recipes/err-invalid-callback/README.md +++ b/recipes/err-invalid-callback/README.md @@ -1,27 +1,85 @@ -# DEP0159: `ERR_INVALID_CALLBACK` replaced by `ERR_INVALID_ARG_TYPE` +--- +authors: syhstanley +--- -This recipe replaces references to the deprecated `ERR_INVALID_CALLBACK` error code with `ERR_INVALID_ARG_TYPE`. +# DEP0159: `ERR_INVALID_CALLBACK` to `ERR_INVALID_ARG_TYPE` -See [DEP0159](https://nodejs.org/api/deprecations.html#DEP0159). +Node.js APIs used to throw errors with the `ERR_INVALID_CALLBACK` code when they received an invalid callback. That code was removed in favor of `ERR_INVALID_ARG_TYPE`, which those APIs now throw instead. This codemod rewrites string references to the removed code in error-code contexts — equality comparisons, object properties such as `assert.throws()` expectations, `switch` cases, and string-matching calls like `.includes()` — while leaving unrelated strings, such as log messages, untouched. It also collapses checks that already tested for both codes into a single condition. See [DEP0159](https://nodejs.org/api/deprecations.html#DEP0159). -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/err-invalid-callback +``` + +## Examples + +### Error-code comparisons + +Equality checks against the old code are rewritten; both single- and double-quoted strings are supported. ```diff - try { - fs.readFile("file.txt", "invalid-callback"); - } catch (err) { -- if (err.code === "ERR_INVALID_CALLBACK") { -+ if (err.code === "ERR_INVALID_ARG_TYPE") { - console.error("Invalid callback provided"); - } - } + try { + fs.readFile("file.txt", "invalid-callback"); + } catch (err) { +- if (err.code === "ERR_INVALID_CALLBACK") { ++ if (err.code === "ERR_INVALID_ARG_TYPE") { + console.error("Invalid callback provided"); + } + } ``` -Also handles deduplication when both codes were already checked: +### Expected-error objects + +Object properties, such as `assert.throws()` expectations, are updated. ```diff - const isCallbackError = -- err.code === "ERR_INVALID_CALLBACK" || -- err.code === "ERR_INVALID_ARG_TYPE"; -+ err.code === "ERR_INVALID_ARG_TYPE"; + assert.throws( + () => fs.readFile("file.txt", 123), +- { code: "ERR_INVALID_CALLBACK" } ++ { code: "ERR_INVALID_ARG_TYPE" } + ); ``` + +### `switch` cases + +`case` labels matching the old code are rewritten; other cases are left alone. + +```diff + switch (error.code) { +- case "ERR_INVALID_CALLBACK": ++ case "ERR_INVALID_ARG_TYPE": + console.log("Invalid callback"); + break; + } +``` + +### String-matching calls + +Arguments to string-matching methods such as `.includes()` are updated. + +```diff +-if (err.toString().includes("ERR_INVALID_CALLBACK")) { ++if (err.toString().includes("ERR_INVALID_ARG_TYPE")) { + // Handle callback error + } +``` + +### Deduplication of dual checks + +Code that already checked for both codes is collapsed into a single condition after the replacement. + +```diff + const isCallbackError = +- err.code === "ERR_INVALID_CALLBACK" || + err.code === "ERR_INVALID_ARG_TYPE"; +``` + +## Notes + +- Replacement is context-aware: only string literals in recognized error-code positions are rewritten. Strings in unrelated contexts, such as `console.warn("ERR_INVALID_CALLBACK")` or thrown message text, are intentionally left unchanged. +- The recognized string-matching methods are `includes`, `indexOf`, `match`, `test`, `startsWith`, and `endsWith`. + + diff --git a/recipes/err-invalid-callback/codemod.yaml b/recipes/err-invalid-callback/codemod.yaml index a17aaba1..d8b6b28a 100644 --- a/recipes/err-invalid-callback/codemod.yaml +++ b/recipes/err-invalid-callback/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/err-invalid-callback" -version: "1.0.0" +version: "1.0.1" description: Handle DEP0159 by replacing ERR_INVALID_CALLBACK with ERR_INVALID_ARG_TYPE. author: Stanley Shen license: MIT diff --git a/recipes/err-invalid-callback/package.json b/recipes/err-invalid-callback/package.json index 4d8784e5..bab03a86 100644 --- a/recipes/err-invalid-callback/package.json +++ b/recipes/err-invalid-callback/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/err-invalid-callback", - "version": "1.0.0", + "version": "1.0.1", "description": "Handle DEP0159 by replacing ERR_INVALID_CALLBACK with ERR_INVALID_ARG_TYPE.", "type": "module", "scripts": { diff --git a/recipes/fs-access-mode-constants/README.md b/recipes/fs-access-mode-constants/README.md index c6547b4e..8ee554ab 100644 --- a/recipes/fs-access-mode-constants/README.md +++ b/recipes/fs-access-mode-constants/README.md @@ -1,16 +1,60 @@ -# `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` DEP0176 +--- +authors: nekojanai +--- -Handle DEP0176 via transforming imports of `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` from the root `fs` module to `fs.constants`. +# DEP0176: `fs.F_OK` / `fs.R_OK` / `fs.W_OK` / `fs.X_OK` to `fs.constants.*` -See [DEP0176](https://nodejs.org/api/deprecations.html#dep0176-fsf_ok-fsr_ok-fsw_ok-fsx_ok) +Moves the deprecated `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, and `fs.X_OK` access mode constants to their canonical location under `fs.constants`. Handles both `require` and `import` syntax, updating destructured bindings to import `constants` instead and rewriting all usages at their call sites. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/fs-access-mode-constants +``` + +## Examples + +### Example 1 + +Namespace `require` — constant references on the `fs` object are prefixed with `.constants`. ```diff - const fs = require('node:fs'); + const fs = require('node:fs'); -- fs.access('/path/to/file', fs.F_OK, callback); -+ fs.access('/path/to/file', fs.constants.F_OK, callback); -- fs.access('/path/to/file', fs.R_OK | fs.W_OK, callback); -+ fs.access('/path/to/file', fs.constants.R_OK | fs.constants.W_OK, callback); +-fs.access('/path/to/file', fs.F_OK, callback); +-fs.access('/path/to/file', fs.R_OK | fs.W_OK, callback); ++fs.access('/path/to/file', fs.constants.F_OK, callback); ++fs.access('/path/to/file', fs.constants.R_OK | fs.constants.W_OK, callback); ``` + +### Example 2 + +Destructured `require` — individual constant bindings are replaced with `constants`, and usages are prefixed accordingly. + +```diff +-const { access, F_OK, R_OK, W_OK } = require('node:fs'); ++const { access, constants } = require('node:fs'); + +-access('/path/to/file', F_OK, callback); +-access('/path/to/file', R_OK | W_OK, callback); ++access('/path/to/file', constants.F_OK, callback); ++access('/path/to/file', constants.R_OK | constants.W_OK, callback); +``` + +### Example 3 + +Named `import` — constant specifiers are replaced with `constants`, and usages are updated. + +```diff +-import { access, F_OK, R_OK, W_OK, X_OK } from 'node:fs'; ++import { access, constants } from 'node:fs'; + +-access('/path/to/file', F_OK, callback); +-access('/path/to/file', R_OK | W_OK | X_OK, callback); ++access('/path/to/file', constants.F_OK, callback); ++access('/path/to/file', constants.R_OK | constants.W_OK | constants.X_OK, callback); +``` + + diff --git a/recipes/fs-access-mode-constants/codemod.yaml b/recipes/fs-access-mode-constants/codemod.yaml index a70b916c..a3103d09 100644 --- a/recipes/fs-access-mode-constants/codemod.yaml +++ b/recipes/fs-access-mode-constants/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/fs-access-mode-constants" -version: "1.0.3" +version: "1.0.4" description: Handle DEP0176 via transforming imports of `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` from the root `fs` module to `fs.constants`. author: nekojanai (Jana) license: MIT diff --git a/recipes/fs-access-mode-constants/package.json b/recipes/fs-access-mode-constants/package.json index c61e8238..041de798 100644 --- a/recipes/fs-access-mode-constants/package.json +++ b/recipes/fs-access-mode-constants/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/fs-access-mode-constants", - "version": "1.0.3", + "version": "1.0.4", "description": "Handle DEP0176 via transforming imports of `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` from the root `fs` module to `fs.constants`.", "type": "module", "scripts": { diff --git a/recipes/fs-truncate-fd-deprecation/README.md b/recipes/fs-truncate-fd-deprecation/README.md index a79701b0..1f84af6f 100644 --- a/recipes/fs-truncate-fd-deprecation/README.md +++ b/recipes/fs-truncate-fd-deprecation/README.md @@ -1,21 +1,59 @@ -# DEP0081: `fs.truncate()` using a file descriptor +--- +authors: AugustinMauroy +--- -This recipe transforms the usage of `fs.truncate()` to `fs.ftruncateSync()` when a file descriptor is used. +# DEP0081: `fs.truncate()` to `fs.ftruncate()` -See [DEP0081](https://nodejs.org/api/deprecations.html#DEP0081). +Replaces `fs.truncate()` and `fs.truncateSync()` with `fs.ftruncate()` and `fs.ftruncateSync()` when the first argument is a file descriptor. Import and `require` destructuring statements are updated accordingly. Calls that pass a file path string as the first argument are left untouched. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/fs-truncate-fd-deprecation +``` + +## Examples + +### Example 1 + +Destructured `require` with a file descriptor provided via an `open` callback. ```diff -- const { truncate, open, close } = require('node:fs'); -+ const { ftruncate, open, close } = require('node:fs'); - - open('file.txt', 'w', (err, fd) => { - if (err) throw err; -- truncate(fd, 10, (err) => { -+ ftruncate(fd, 10, (err) => { - if (err) throw err; - close(fd, () => {}); - }); - }); +-const { truncate, open, close } = require('node:fs'); ++const { ftruncate, open, close } = require('node:fs'); + + open('file.txt', 'w', (err, fd) => { + if (err) throw err; +- truncate(fd, 10, (err) => { ++ ftruncate(fd, 10, (err) => { + if (err) throw err; + close(fd, () => { }); + }); + }); ``` + +### Example 2 + +Namespace `require` with a file descriptor from `fs.openSync`. + +```diff + const fs = require('node:fs'); + + const fd = fs.openSync('file.txt', 'w'); + try { +- fs.truncateSync(fd, 10); ++ fs.ftruncateSync(fd, 10); + } finally { + fs.closeSync(fd); + } +``` + +## Notes + +### Limitations + +The codemod uses a conservative heuristic to determine whether the first argument is a file descriptor. It only transforms calls where the first argument is a numeric literal, a variable assigned from `fs.openSync` / `openSync`, or an `fd` parameter inside a callback passed to `fs.open` / `open`. Calls where the first argument is a file path string or any other expression that cannot be statically identified as a file descriptor are not transformed. + + diff --git a/recipes/fs-truncate-fd-deprecation/codemod.yaml b/recipes/fs-truncate-fd-deprecation/codemod.yaml index a734ac7d..08867af0 100644 --- a/recipes/fs-truncate-fd-deprecation/codemod.yaml +++ b/recipes/fs-truncate-fd-deprecation/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/fs-truncate-fd-deprecation" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0081 via transforming `truncate` to `ftruncateSync` when using a file descriptor. author: Augustin Mauroy license: MIT diff --git a/recipes/fs-truncate-fd-deprecation/package.json b/recipes/fs-truncate-fd-deprecation/package.json index 7e1b4bc6..e4e53b8d 100644 --- a/recipes/fs-truncate-fd-deprecation/package.json +++ b/recipes/fs-truncate-fd-deprecation/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/fs-truncate-fd-deprecation", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0081 via transforming `truncate` to `ftruncateSync` when using a file descriptor.", "type": "module", "scripts": { diff --git a/recipes/http-classes-with-new/README.md b/recipes/http-classes-with-new/README.md index 09cff3ec..80ffd22e 100644 --- a/recipes/http-classes-with-new/README.md +++ b/recipes/http-classes-with-new/README.md @@ -1,22 +1,67 @@ -# `http.request` DEP0195 +--- +authors: max-programming +--- +# DEP0195: Instantiating `node:http` Classes Without `new` -This recipe provides a guide for migrating from the deprecated `http.request` and its synchronous and promise-based counterparts to the new `http.request` method in Node.js. +Adds the `new` keyword to calls that instantiate `http.Agent`, `http.ClientRequest`, `http.IncomingMessage`, `http.OutgoingMessage`, `http.Server`, and `http.ServerResponse` without it. Works with both `require` and `import` syntax, including named and namespace imports. -See [DEP0195](https://nodejs.org/api/deprecations.html#DEP0195). +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/http-classes-with-new +``` ## Examples +### Example 1 + +`require` — all six classes gain the `new` keyword. + ```diff - // import { IncomingMessage, ClientRequest } from "node:http"; - // const http = require("node:http"); - -- const message = http.OutgoingMessage(); -+ const message = new http.OutgoingMessage(); -- const response = http.ServerResponse(socket); -+ const response = new http.ServerResponse(socket); - -- const incoming = IncomingMessage(socket); -+ const incoming = new IncomingMessage(socket); -- const request = ClientRequest(options); -+ const request = new ClientRequest(options); + const http = require("node:http"); + +-const agent = http.Agent(); +-const request = http.ClientRequest(options); +-const incoming = http.IncomingMessage(socket); +-const message = http.OutgoingMessage(); +-const server = http.Server(); +-const response = http.ServerResponse(socket); ++const agent = new http.Agent(); ++const request = new http.ClientRequest(options); ++const incoming = new http.IncomingMessage(socket); ++const message = new http.OutgoingMessage(); ++const server = new http.Server(); ++const response = new http.ServerResponse(socket); ``` + +### Example 2 + +Named `import` — destructured class names are handled the same way. + +```diff + import { + Agent, + ClientRequest, + IncomingMessage, + OutgoingMessage, + Server, + ServerResponse, + } from "node:http"; + +-const agent = Agent(); +-const request = ClientRequest(options); +-const incoming = IncomingMessage(socket); +-const message = OutgoingMessage(); +-const server = Server(); +-const response = ServerResponse(socket); ++const agent = new Agent(); ++const request = new ClientRequest(options); ++const incoming = new IncomingMessage(socket); ++const message = new OutgoingMessage(); ++const server = new Server(); ++const response = new ServerResponse(socket); +``` + + diff --git a/recipes/http-classes-with-new/codemod.yaml b/recipes/http-classes-with-new/codemod.yaml index 9655a45b..ac224e33 100644 --- a/recipes/http-classes-with-new/codemod.yaml +++ b/recipes/http-classes-with-new/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http-classes-with-new" -version: "1.0.2" +version: "1.0.3" description: "Handle DEDEP0195: Instantiating node:http classes without new" author: Usman S. license: MIT diff --git a/recipes/http-classes-with-new/package.json b/recipes/http-classes-with-new/package.json index 26ab2a53..4de546cd 100644 --- a/recipes/http-classes-with-new/package.json +++ b/recipes/http-classes-with-new/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http-classes-with-new", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0195: Instantiating node:http classes without new.", "type": "module", "scripts": { diff --git a/recipes/http-outgoingmessage-headers/README.md b/recipes/http-outgoingmessage-headers/README.md new file mode 100644 index 00000000..605a2866 --- /dev/null +++ b/recipes/http-outgoingmessage-headers/README.md @@ -0,0 +1,130 @@ +--- +authors: elvessilvavieira +--- +# DEP0066: `OutgoingMessage._headers` / `_headerNames` to `getHeaders()` / `getRawHeaderNames()` + +Replaces deprecated `response._headers` with `response.getHeaders()` and `response._headerNames` with `response.getRawHeaderNames()` on HTTP server response objects. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/http-outgoingmessage-headers +``` + +## Examples + +### Example 1 + +Reading headers and header names: + +```diff + const http = require('http'); + + function handler(req, res) { + res.setHeader('content-type', 'application/json'); + res.setHeader('x-custom-header', '42'); + + console.log({ +- headers: res._headers, +- headerNames: res._headerNames, +- customHeader: res._headers['x-custom-header'], +- count: Object.keys(res._headers).length, ++ headers: res.getHeaders(), ++ headerNames: res.getRawHeaderNames(), ++ customHeader: res.getHeaders()['x-custom-header'], ++ count: Object.keys(res.getHeaders()).length, + }); + + res.end('Hello World'); + } + + const server = http.createServer(handler); +``` + +### Example 2 + +Checking header existence: + +```diff + const http = require('http'); + + const server = http.createServer((req, res) => { +- if ('x-custom-header' in res._headers) { ++ if ('x-custom-header' in res.getHeaders()) { + console.log('exists'); + } + +- if (Object.prototype.hasOwnProperty.call(res._headers, 'x-custom-header')) { ++ if (Object.prototype.hasOwnProperty.call(res.getHeaders(), 'x-custom-header')) { + console.log('exists'); + } + +- if (res._headers['x-custom-header'] !== undefined) { ++ if (res.getHeaders()['x-custom-header'] !== undefined) { + console.log('exists'); + } + }); +``` + +### Example 3 + +Iterating over headers and header names: + +```diff + const http = require('http'); + + const server = http.createServer((req, res) => { +- for (const name in res._headers) { +- console.log(res._headers[name]); ++ for (const name in res.getHeaders()) { ++ console.log(res.getHeaders()[name]); + } + +- Array.from(res._headerNames).forEach((name) => { ++ Array.from(res.getRawHeaderNames()).forEach((name) => { + console.log(name); + }); + +- for (const name in res._headerNames) { +- console.log(res._headerNames[name]); ++ for (const name in res.getRawHeaderNames()) { ++ console.log(res.getRawHeaderNames()[name]); + } + }); +``` + +### Example 4 + +The codemod also handles `res` objects accessed via `server.on()` listeners, including when the event name or listener function is stored in a variable: + +```diff + const server = http.createServer((req, res) => { +- console.log({ createServer: res._headers }); ++ console.log({ createServer: res.getHeaders() }); + }); + + server.on('request', (req, res) => { +- console.log({ serverOnRequest: res._headers }); ++ console.log({ serverOnRequest: res.getHeaders() }); + }); + + const event = 'request'; + const listener = (req, res) => { +- console.log({ serverOnRequest: res._headers }); ++ console.log({ serverOnRequest: res.getHeaders() }); + }; + + server.on(event, listener); +``` + +## Notes + +The codemod traces the response object through `http.createServer()` request handlers and `server.on()` listeners for the `request`, `checkContinue`, and `checkExpectation` events. It resolves variable references, so handler functions and event names stored in variables are handled correctly. + +### Limitations + +Only accesses to `_headers` and `_headerNames` on the known response parameter are transformed. Arbitrary objects that happen to have a `_headers` or `_headerNames` property are left untouched. + + diff --git a/recipes/http-outgoingmessage-headers/codemod.yaml b/recipes/http-outgoingmessage-headers/codemod.yaml index 02aac3d6..03f98713 100644 --- a/recipes/http-outgoingmessage-headers/codemod.yaml +++ b/recipes/http-outgoingmessage-headers/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http-outgoingmessage-headers" -version: 1.0.1 +version: 1.0.2 description: > Handle DEP0066: migrate deprecated use of `OutgoingMessage.prototype` `_headers` & `_headerNames` to public HTTP header APIs diff --git a/recipes/http-outgoingmessage-headers/package.json b/recipes/http-outgoingmessage-headers/package.json index 1d25026a..7ffc38af 100644 --- a/recipes/http-outgoingmessage-headers/package.json +++ b/recipes/http-outgoingmessage-headers/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http-outgoingmessage-headers", - "version": "1.0.0", + "version": "1.0.2", "description": "Handle DEP0066: migrate deprecated use of `OutgoingMessage.prototype` `_headers` & `_headerNames` to public HTTP header APIs", "type": "module", "scripts": { diff --git a/recipes/http-outgoingmessage-headers/readme.md b/recipes/http-outgoingmessage-headers/readme.md deleted file mode 100644 index adae2845..00000000 --- a/recipes/http-outgoingmessage-headers/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -# `OutgoingMessage` private header fields - -This migration addresses [`DEP0066`](https://nodejs.org/api/deprecations.html#dep0066-outgoingmessageprototype_headers-outgoingmessageprototype_headernames), transforming use of deprecated private fields `_headers` and `_headerNames` on `OutgoingMessage.prototype` to their public equivalents. - -## Examples - -### Reading headers - -```diff - const http = require('node:http'); - - function handler(req, res) { - res.setHeader('content-type', 'application/json'); - res.setHeader('x-custom-header', '42'); - - console.log({ -- headers: res._headers, -+ headers: res.getHeaders(), -- headerNames: res._headerNames, -+ headerNames: res.getRawHeaderNames(), -- customHeader: res._headers['x-custom-header'], -+ customHeader: res.getHeaders()['x-custom-header'], -- count: Object.keys(res._headers).length, -+ count: Object.keys(res.getHeaders()).length, - }); - - res.end('Hello World'); - } - - const server = http.createServer(handler); - - server.listen(3000, () => { - console.log('Server running on port 3000'); - }); -``` - -### Refs - -- [http.getHeaderNames](https://nodejs.org/api/http.html#requestgetheadername) -- [http.getHeaders](https://nodejs.org/api/http.html#requestgetheaders) diff --git a/recipes/http2-priority-signaling/README.md b/recipes/http2-priority-signaling/README.md index 88a75526..7b1a8b4c 100644 --- a/recipes/http2-priority-signaling/README.md +++ b/recipes/http2-priority-signaling/README.md @@ -1,34 +1,76 @@ -# HTTP/2 Priority Signaling Removal - DEP0194 +--- +authors: AugustinMauroy +--- -This recipe removes HTTP/2 priority-related options and methods since priority signaling has been deprecated. +# DEP0194: HTTP/2 Priority Signaling -See [DEP0194](https://nodejs.org/api/deprecations.html#DEP0194). +HTTP/2 priority signaling is deprecated in Node.js and has no replacement, so priority-related options and calls should simply be removed. This codemod removes the `priority` property from the options passed to `http2.connect()`, `session.request()`, and `session.settings()`, and removes entire `stream.priority()` call statements. It resolves `http2` and `node:http2` bindings across CommonJS `require()` and ESM `import` — default, namespace, named, and aliased `connect` imports — as well as dynamic `import()`. See [DEP0194](https://nodejs.org/api/deprecations.html#DEP0194). +## Usage -## What this codemod does +Run this codemod with: -- Removes the `priority` property from `http2.connect()` call options -- Removes the `priority` property from `session.request()` call options -- Removes entire `stream.priority()` method call statements -- Removes the `priority` property from `client.settings()` call options -- Handles both CommonJS (`require()`) and ESM (`import`) imports +```sh +npx codemod @nodejs/http2-priority-signaling +``` ## Examples +### `priority` option in `http2.connect()` + +When `priority` is the only option, the whole options argument is removed. + +```diff + const http2 = require("node:http2"); +-const session = http2.connect("https://example.com", { +- priority: { +- weight: 16, +- parent: 0, +- exclusive: false +- } +-}); ++const session = http2.connect("https://example.com"); +``` + +### `priority` option in `session.request()` + +Only the `priority` property is removed; other options are preserved. + +```diff + const stream = session.request({ +- ":path": "/api/data", +- priority: { weight: 32 } ++ ":path": "/api/data" + }); +``` + +### `stream.priority()` calls + +The entire method-call statement is removed. + ```diff -import http2 from "node:http2"; + const stream = session.request({ ":path": "/" }); +-stream.priority({ +- exclusive: true, +- parent: 0, +- weight: 128 +-}); +``` -const session = http2.connect("https://example.com", { -- priority: { weight: 16, parent: 0, exclusive: false } -}); +### `priority` option in `session.settings()` -const stream = session.request({ - ":path": "/api/data", -- priority: { weight: 32 } -}); -- stream.priority({ exclusive: true, parent: 0, weight: 128 }); +The `priority` setting is dropped while the rest of the settings object is kept. -const client = http2.connect("https://example.com"); +```diff + import http2 from "node:http2"; + const client = http2.connect("https://example.com"); -client.settings({ enablePush: false, priority: true }); +client.settings({ enablePush: false }); ``` + +## Notes + +- Removal is scoped to sessions and streams the codemod can trace back to an `http2.connect()` binding, including chained `connect().request()` and `connect().settings()` calls, so unrelated objects that happen to contain a `priority` key are left untouched. +- `stream.priority()` statements are only removed for streams created from `session.request()` or a `connect().request()` chain. + + diff --git a/recipes/http2-priority-signaling/codemod.yaml b/recipes/http2-priority-signaling/codemod.yaml index 385a0e57..e26945c7 100644 --- a/recipes/http2-priority-signaling/codemod.yaml +++ b/recipes/http2-priority-signaling/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http2-priority-signaling" -version: 1.0.0 +version: 1.0.1 description: Handle DEP0194 via removing HTTP/2 priority-related options and methods. author: Augustin Mauroy license: MIT diff --git a/recipes/http2-priority-signaling/package.json b/recipes/http2-priority-signaling/package.json index d1efc258..4a14e1c3 100644 --- a/recipes/http2-priority-signaling/package.json +++ b/recipes/http2-priority-signaling/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http2-priority-signaling", - "version": "1.0.0", + "version": "1.0.1", "description": "Handle DEP0194 via removing HTTP/2 priority-related options and methods", "type": "module", "scripts": { diff --git a/recipes/import-assertions-to-attributes/README.md b/recipes/import-assertions-to-attributes/README.md index 894b6896..93084909 100644 --- a/recipes/import-assertions-to-attributes/README.md +++ b/recipes/import-assertions-to-attributes/README.md @@ -1,15 +1,65 @@ +--- +authors: AugustinMauroy +--- + # Import Assertions to Attributes -This recipe converts import assertions (`assert` syntax) to the standardized import attributes (`with` syntax). It modifies code like: +Converts the deprecated import assertion syntax (`assert { type: 'json' }`) to the standardized import attribute syntax (`with { type: 'json' }`) for both static and dynamic imports. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/import-assertions-to-attributes +``` + +## Examples + +### Example 1 + +Static and dynamic imports: ```diff -- import data from './data.json' assert { type: 'json' }; -+ import data from './data.json' with { type: 'json' }; +-import data from './data.json' assert { type: 'json' }; ++import data from './data.json' with { type: 'json' }; + + const data2 = await import('./data2.json', { +- assert: { type: 'json' }, ++ with: { type: 'json' }, + }); + + await import('./data3.json', { +- assert: { type: 'json' }, ++ with: { type: 'json' }, + }); + + function getData4() { + return import('./data4.json', { +- assert: { type: 'json' }, ++ with: { type: 'json' }, + }); + } ``` -## When is it useful? +### Example 2 + +Edge cases including compact syntax and semicolons in paths: -The import assertions syntax is being deprecated in favor of the standardized import attributes syntax. This codemod helps transition existing codebases to the new syntax, ensuring compatibility with future versions of Node.js. +```diff +-import data from './data.json' assert { type: 'json' }; ++import data from './data.json' with { type: 'json' }; +-import systemOfADown from './system;of;a;down.json' assert { type: 'json' }; ++import systemOfADown from './system;of;a;down.json' with { type: 'json' }; +-import { default as config } from './config.json'assert{type: 'json'}; ++import { default as config } from './config.json'with{type: 'json'}; +-import { thing } from "./data.json"assert{type: 'json'}; ++import { thing } from "./data.json"with{type: 'json'}; + + const data2 = await import('./data2.json', { +- assert: { type: 'json' }, ++ with: { type: 'json' }, + }); +``` -Node.js drop support of import assertions in favor of import attributes in version [`22.0.0`](https://nodejs.org/fr/blog/release/v22.0.0#other-notable-changes) -But the support for import attributes was added in Node.js version [`18.20.0`](https://nodejs.org/fr/blog/release/v18.20.0#added-support-for-import-attributes) + diff --git a/recipes/import-assertions-to-attributes/codemod.yaml b/recipes/import-assertions-to-attributes/codemod.yaml index 4bfb792a..d190466e 100644 --- a/recipes/import-assertions-to-attributes/codemod.yaml +++ b/recipes/import-assertions-to-attributes/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/import-assertions-to-attributes" -version: 1.0.0 +version: 1.0.1 description: Replace `assert` import attribute to the `with` ECMAScript import attribute. author: Augustin Mauroy license: MIT diff --git a/recipes/import-assertions-to-attributes/package.json b/recipes/import-assertions-to-attributes/package.json index cd38557a..ae8c72b9 100644 --- a/recipes/import-assertions-to-attributes/package.json +++ b/recipes/import-assertions-to-attributes/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/import-assertions-to-attributes", - "version": "1.0.0", + "version": "1.0.1", "description": "Replace `assert` import attribute to the `with` ECMAScript import attribute.", "type": "module", "scripts": { diff --git a/recipes/mocha-to-node-test-runner/README.md b/recipes/mocha-to-node-test-runner/README.md index e378b78e..5c2b38c8 100644 --- a/recipes/mocha-to-node-test-runner/README.md +++ b/recipes/mocha-to-node-test-runner/README.md @@ -1,20 +1,24 @@ +--- +authors: Xstoudi +--- + # Mocha to Node.js Test Runner -This migrates Mocha 8.x tests to Node.js (22.x, 24.x) test runner +Migrates [Mocha](https://mochajs.org/) 8.x test suites to the built-in [Node.js test runner](https://nodejs.org/api/test.html) (`node:test`, available in Node.js 22.x and 24.x). It adds the required `node:test` imports for the globals a file uses (`describe`, `it`, `before`, `after`, `beforeEach`, `afterEach`), converts `done` callbacks to the `(t, done)` signature, rewrites `this.skip()` to `t.skip()` and `this.timeout(N)` to `{ timeout: N }` options, and preserves the original function style (it never converts between `function()` and arrow functions). Both CommonJS and ESM files are supported, and the `mocha` and `@types/mocha` dependencies are removed from `package.json` afterwards. + +## Usage -## Features +Run this codemod with: -- Automatically adds `node:test` imports/requires -- Converts global `describe`, `it`, and hooks to imported versions -- Transforms `done` callbacks to `(t, done)` signature -- Converts `this.skip()` to `t.skip()` -- Converts `this.timeout(N)` to `{ timeout: N }` options -- Preserves function styles (doesn't convert between `function()` and arrow functions) -- Supports both CommonJS and ESM +```sh +npx codemod @nodejs/mocha-to-node-test-runner +``` ## Examples -### Example 1: Basic +### Adding `node:test` imports (CommonJS) + +Global `describe`/`it` usage keeps working once the matching `require('node:test')` is inserted; modifiers like `describe.skip` are already compatible. ```diff const assert = require('assert'); @@ -30,26 +34,28 @@ This migrates Mocha 8.x tests to Node.js (22.x, 24.x) test runner }); ``` -### Example 2: Async +### Adding `node:test` imports (ESM) + +In ESM files an `import` statement is inserted instead. ```diff - const assert = require('assert'); -+const { describe, it } = require('node:test'); - describe('Async Test', function() { --it('should complete after a delay', async function(done) { -+it('should complete after a delay', async function(t, done) { - const result = await new Promise(resolve => setTimeout(() => resolve(42), 100)); - assert.strictEqual(result, 42); - }); - }); + import assert from 'assert'; ++import { describe, it } from 'node:test'; + + describe('Array', function() { + describe.skip('#indexOf()', function() { + it('should return -1 when the value is not present', function() { ``` -### Example 3: Hooks +### Hooks + +Only the hooks actually used in the file are added to the import list. ```diff const assert = require('assert'); const fs = require('fs'); +const { describe, before, after, it } = require('node:test'); + describe('File System', () => { before(function() { fs.writeFileSync('test.txt', 'Hello, World!'); @@ -58,20 +64,17 @@ This migrates Mocha 8.x tests to Node.js (22.x, 24.x) test runner after(() => { fs.unlinkSync('test.txt'); }); +``` - it('should read the file', () => { - const content = fs.readFileSync('test.txt', 'utf8'); - assert.strictEqual(content, 'Hello, World!'); - }); - }); - ``` +### `done` callbacks -### Example 4: Done +Mocha passes `done` as the first callback argument; `node:test` passes the test context first, so `(done)` becomes `(t, done)`. ```diff -const assert = require('assert'); + const assert = require('assert'); +const { describe, it } = require('node:test'); -describe('Callback Test', function() { + + describe('Callback Test', function() { - it('should call done when complete', function(done) { + it('should call done when complete', function(t, done) { setTimeout(() => { @@ -79,14 +82,17 @@ describe('Callback Test', function() { done(); }, 100); }); -}) + }); ``` -### Example 5: Skipped +### Skipping with `this.skip()` + +`this.skip()` becomes `t.skip()`, with the test context parameter `t` added to the callback signature as needed. ```diff const assert = require('assert'); +const { describe, it } = require('node:test'); + describe('Skipped Test', () => { it.skip('should not run this test', () => { assert.strictEqual(1 + 1, 3); @@ -104,62 +110,41 @@ describe('Callback Test', function() { + t.skip(); assert.strictEqual(1 + 1, 3); }); - -- it('should also be skipped 3', x => { -- this.skip(); -+ it('should also be skipped 3', (t, x) => { -+ t.skip(); - assert.strictEqual(1 + 1, 3); - }); - }) + }); ``` -### Example 6: Dynamic +### Timeouts + +`this.timeout(N)` calls on suites and tests move into the `{ timeout: N }` options argument. ```diff const assert = require('assert'); +const { describe, it } = require('node:test'); - describe('Dynamic Tests', () => { - const tests = [1, 2, 3]; - tests.forEach((test) => { - it(`should handle test ${test}`, () => { - assert.strictEqual(test % 2, 0); - }); - }); - }); -``` - -### Example 7: Timeouts - -```diff -const assert = require('assert'); -describe('Timeout Test', function() { - this.timeout(500); -+const { describe, it } = require('node:test'); +describe('Timeout Test', { timeout: 500 }, function() { -+ -+ -+ it('should complete within 100ms', { timeout: 100 }, (t, done) => { - it('should complete within 100ms', (done) => { - this.timeout(100); ++ it('should complete within 100ms', { timeout: 100 }, (t, done) => { setTimeout(done, 500); // This will fail }); - it('should complete within 200ms', function(done) { - this.timeout(200); + it('should complete within 200ms', { timeout: 200 }, function(t, done) { -+ setTimeout(done, 100); // This will pass }); -}); + }); ``` -## Caveats +## Notes + +- After the transformation, the codemod detects your package manager and removes the `mocha` and `@types/mocha` dependencies from `package.json`. + +### Limitations -* `node:test` doesn't support the `retry` option that Mocha has, so any tests using that will need to be handled separately. +- `node:test` does not support Mocha's `retry` option, so tests relying on it need to be handled separately. -## References -- [Node Test Runner](https://nodejs.org/api/test.html) -- [Mocha](https://mochajs.org/) + diff --git a/recipes/mocha-to-node-test-runner/codemod.yaml b/recipes/mocha-to-node-test-runner/codemod.yaml index 0a3cadb6..21cc4c5d 100644 --- a/recipes/mocha-to-node-test-runner/codemod.yaml +++ b/recipes/mocha-to-node-test-runner/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/mocha-to-node-test-runner" -version: 1.0.0 +version: 1.0.1 capabilities: - fs - child_process diff --git a/recipes/mocha-to-node-test-runner/package.json b/recipes/mocha-to-node-test-runner/package.json index 6708d51d..7fd011a5 100644 --- a/recipes/mocha-to-node-test-runner/package.json +++ b/recipes/mocha-to-node-test-runner/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/mocha-to-node-test-runner", - "version": "1.0.0", + "version": "1.0.1", "description": "Migrate Mocha 8.x tests to Node.js (22.x, 24.x) test runner", "type": "module", "scripts": { diff --git a/recipes/mock-module-exports/README.md b/recipes/mock-module-exports/README.md index 633e9e5f..ca3643bb 100644 --- a/recipes/mock-module-exports/README.md +++ b/recipes/mock-module-exports/README.md @@ -1,19 +1,85 @@ -# Mock Module Exports +--- +authors: brunocroh +--- -This migration trasforming use of deprecated `options.defaultExport` and `options.namedExports` on -`node:test.mock` +# `mock.module()` `defaultExport` / `namedExports` to `exports` -## Example +Updates `mock.module()` calls to use the new `exports` object API, merging the deprecated `defaultExport` and `namedExports` options into a single `exports` object where the default export is keyed as `default`. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/mock-module-exports +``` + +## Examples + +### Example 1 + +Both `defaultExport` and `namedExports` present with inline object: ```diff -mock.module('…', { -- defaultExport: …, -- namedExports: { -- foo: … -- }, -+ exports: { -+ default: …, -+ foo: …, -+ }, -}); + mock.module('example', { +- defaultExport: 'bar', +- namedExports: { +- foo: 'foo', +- baz: 'baz', +- }, ++ exports: { ++ default: 'bar', ++ foo: 'foo', ++ baz: 'baz', ++ }, + }); ``` + +### Example 2 + +`namedExports` given as a variable reference — the spread is wrapped with a `|| {}` fallback: + +```diff + mock.module('example2', { +- defaultExport: 'bar', +- namedExports: namedExports, ++ exports: { ++ default: 'bar', ++ ...(namedExports || {}), ++ }, + }); +``` + +### Example 3 + +Only `defaultExport`, no named exports: + +```diff + mock.module('example', { +- defaultExport: 'bar', ++ exports: { ++ default: 'bar', ++ }, + }); +``` + +### Example 4 + +Only `namedExports`, no default export: + +```diff + mock.module('example', { +- namedExports: { +- foo: 'foo', +- }, ++ exports: { ++ foo: 'foo', ++ }, + }); +``` + +## Notes + +When `namedExports` is a variable (identifier) rather than an inline object, the codemod emits a spread with a `|| {}` fallback (`...(obj || {})`) to preserve safe behaviour when the variable may be `undefined` or `null`. + + diff --git a/recipes/mock-module-exports/codemod.yaml b/recipes/mock-module-exports/codemod.yaml index 56c69ca0..cf2be84a 100644 --- a/recipes/mock-module-exports/codemod.yaml +++ b/recipes/mock-module-exports/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/mock-module-exports" -version: 1.0.1 +version: 1.0.2 description: "Handle mock.module exports deprecation" author: Bruno Rodrigues license: MIT diff --git a/recipes/mock-module-exports/package.json b/recipes/mock-module-exports/package.json index b9dabdac..7520375c 100644 --- a/recipes/mock-module-exports/package.json +++ b/recipes/mock-module-exports/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/mock-module-exports", - "version": "1.0.0", + "version": "1.0.2", "description": "Handle mock.module exports deprecation", "type": "module", "scripts": { diff --git a/recipes/node-url-to-whatwg-url/README.md b/recipes/node-url-to-whatwg-url/README.md index 89ab533a..6fc77239 100644 --- a/recipes/node-url-to-whatwg-url/README.md +++ b/recipes/node-url-to-whatwg-url/README.md @@ -1,73 +1,71 @@ -# Node.js URL to WHATWG URL +--- +authors: AugustinMauroy +--- -This recipe converts Node.js `url` module usage to the WHATWG URL API. It modifies code that uses the legacy `url` module to use the modern `URL` class instead. +# DEP0116: `url.parse()` / `url.format()` to `new URL()` -See [DEP0116](https://nodejs.org/api/deprecations.html#DEP0116). +Migrates the deprecated `url.parse()` and `url.format()` functions to the WHATWG `URL` API. Also rewrites property accesses on the parsed URL object that differ between the legacy and WHATWG APIs. -## Example +## Usage -### `url.parse` to `new URL()` +Run this codemod with: + +```sh +npx codemod @nodejs/node-url-to-whatwg-url +``` + +## Examples + +### Example 1 + +`url.parse()` to `new URL()`, with property access rewrites: ```diff -- const url = require('node:url'); + const url = require('node:url'); -- const myURL = url.parse('https://example.com/path?query=string#hash'); -+ const myURL = new URL('https://example.com/path?query=string#hash'); +-const myURL = url.parse('https://example.com/path?query=string#hash'); ++const myURL = new URL('https://example.com/path?query=string#hash'); -- const { auth } = myURL; -+ const auth = `${myURL.username}:${myURL.password}`; -- const urlAuth = myURL.auth; -+ const urlAuth = `${myURL.username}:${myURL.password}`; +-const { auth } = myURL; +-const urlAuth = myURL.auth; ++const auth = `${myURL.username}:${myURL.password}`; ++const urlAuth = `${myURL.username}:${myURL.password}`; -- const { path } = myURL; -+ const path = `${myURL.pathname}${myURL.search}`; -- const urlPath = myURL.path; -+ const urlPath = `${myURL.pathname}${myURL.search}`; +-const { path } = myURL; +-const urlPath = myURL.path; ++const path = `${myURL.pathname}${myURL.search}`; ++const urlPath = `${myURL.pathname}${myURL.search}`; -- const { hostname } = myURL; -+ const hostname = myURL.hostname.replace(/^\[|\]$/, ''); -- const urlHostname = myURL.hostname; -+ const urlHostname = myURL.hostname.replace(/^\[|\]$/, ''); +-const { hostname } = myURL; +-const urlHostname = myURL.hostname; ++const hostname = myURL.hostname.replace(/^\[|\]$/, ''); ++const urlHostname = myURL.hostname.replace(/^\[|\]$/, ''); ``` -### `url.format` to `myUrl.toString() +### Example 2 + +`url.format()` with a static object to `new URL(...).toString()`: ```diff -- const url = require('node:url'); - -- url.format({ -+ const myUrl = new URL('https://example.com/some/path?page=1&format=json').toString(); -- protocol: 'https', -- hostname: 'example.com', -- pathname: '/some/path', -- query: { -- page: 1, -- format: 'json', -- }, -- }); + const url = require('node:url'); + +-const str = url.format({ +- protocol: 'https', +- hostname: 'example.com', +- pathname: '/some/path', +- search: '?page=1' +-}); ++const str = new URL('https://example.com/some/path?page=1').toString(); ``` -> **Note:** The migration of `url.format` can also be done as `` `${new URL('https://example.com/some/path?page=1&format=json')}` `` which is little bit more efficient. But it may be less readable for some users. - -## Caveats +## Notes -The [`url.resolve`](https://nodejs.org/api/url.html#urlresolvefrom-to) method is not directly translatable to the WHATWG URL API. You may need to implement custom logic to handle URL resolution in your application. +- `.auth` on the legacy URL object becomes a template literal combining `.username` and `.password`: `` `${url.username}:${url.password}` `` +- `.path` becomes a template literal combining `.pathname` and `.search`: `` `${url.pathname}${url.search}` `` +- `.hostname` for IPv6 addresses has surrounding brackets stripped via `.replace(/^\[|\]$/, '')` -```js -function resolve(from, to) { - const resolvedUrl = new URL(to, new URL(from, 'resolve://')); - if (resolvedUrl.protocol === 'resolve:') { - // `from` is a relative URL. - const { pathname, search, hash } = resolvedUrl; - return pathname + search + hash; - } - return resolvedUrl.toString(); -} - -resolve('/one/two/three', 'four'); // '/one/two/four' -resolve('http://example.com/', '/one'); // 'http://example.com/one' -resolve('http://example.com/one', '/two'); // 'http://example.com/two' -``` +### Limitations -If you are using `url.parse().auth`, `url.parse().username`, or `url.parse().password`. Will transform to `new URL().auth` which is not valid WHATWG url property. So you have to manually construct the `auth`, `path`, and `hostname` properties as shown in the examples above. +`url.format()` reconstruction from an object argument relies on static analysis of the object's properties. Complex cases — such as objects with many computed or dynamic properties — may not be fully transformed and could require manual review. + diff --git a/recipes/node-url-to-whatwg-url/codemod.yaml b/recipes/node-url-to-whatwg-url/codemod.yaml index cd698c81..7f58eda6 100644 --- a/recipes/node-url-to-whatwg-url/codemod.yaml +++ b/recipes/node-url-to-whatwg-url/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/node-url-to-whatwg-url" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0116 via transforming `url.parse` to `new URL()` author: Augustin Mauroy license: MIT diff --git a/recipes/node-url-to-whatwg-url/package.json b/recipes/node-url-to-whatwg-url/package.json index 0f37e827..f8481b25 100644 --- a/recipes/node-url-to-whatwg-url/package.json +++ b/recipes/node-url-to-whatwg-url/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/node-url-to-whatwg-url", - "version": "1.0.1", + "version": "1.0.3", "description": "Handle DEP0116 via transforming `url.parse` to `new URL()`", "type": "module", "scripts": { diff --git a/recipes/process-assert-to-node-assert/README.md b/recipes/process-assert-to-node-assert/README.md index 956087fb..94025415 100644 --- a/recipes/process-assert-to-node-assert/README.md +++ b/recipes/process-assert-to-node-assert/README.md @@ -1,17 +1,78 @@ -# `process.assert` to `node:assert` DEP0100 +--- +authors: matheusmorett2 +--- -This recipe transforms the usage of `process.assert` to use `node:assert` module. +# DEP0100: `process.assert()` to `node:assert` -See [DEP0100](https://nodejs.org/api/deprecations.html#DEP0100). +Replaces deprecated `process.assert()` and `process.assert.*()` calls with equivalent calls from the `node:assert` module, adding the appropriate `import` or `require` declaration automatically. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/process-assert-to-node-assert +``` + +## Examples + +### Example 1 + +Global `process.assert` in a script (ESM `import` added): + +```diff ++import assert from "node:assert"; +-process.assert(condition, "Basic assertion"); +-process.assert.strictEqual(a, b, "Values should be equal"); ++assert(condition, "Basic assertion"); ++assert.strictEqual(a, b, "Values should be equal"); +``` + +### Example 2 + +CommonJS file (`require` added): ```diff -+ import assert from "node:assert"; -- process.assert(condition, "Assertion failed"); -+ assert(condition, "Assertion failed"); ++const assert = require("node:assert"); +-process.assert(condition, "Basic assertion"); +-process.assert.strictEqual(a, b, "Values should be equal"); ++assert(condition, "Basic assertion"); ++assert.strictEqual(a, b, "Values should be equal"); ``` -## Additional Notes +### Example 3 + +ESM file that explicitly imports `process`: + +```diff + import process from "node:process"; ++import assert from "node:assert"; +-process.assert(value, "Process assertion"); +-process.assert.strictEqual(obj1, obj2); ++assert(value, "Process assertion"); ++assert.strictEqual(obj1, obj2); +``` + +### Example 4 + +Multiple `assert` methods in a single file: + +```diff ++import assert from "node:assert"; +-process.assert(condition); +-process.assert.ok(value); +-process.assert.strictEqual(a, b); +-process.assert.notStrictEqual(a, c); +-process.assert.throws(() => { throw new Error(); }); ++assert(condition); ++assert.ok(value); ++assert.strictEqual(a, b); ++assert.notStrictEqual(a, c); ++assert.throws(() => { throw new Error(); }); +``` + +## Notes + +The codemod reads `package.json` to determine whether the project uses ES modules or CommonJS, and inserts `import assert from "node:assert"` or `const assert = require("node:assert")` accordingly. If an `assert` import or require already exists, the existing binding is reused and no duplicate declaration is added. -This codemod use [`fs` capability](https://docs.codemod.com/jssg/security) to read the `package.json` file and determine if the project is using ES modules or CommonJS. Based on this information, it adds the appropriate import statement for the `assert` module. + diff --git a/recipes/process-assert-to-node-assert/codemod.yaml b/recipes/process-assert-to-node-assert/codemod.yaml index 505f8cc1..2635a100 100644 --- a/recipes/process-assert-to-node-assert/codemod.yaml +++ b/recipes/process-assert-to-node-assert/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/process-assert-to-node-assert" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0100 via transforming `process.assert` to `node:assert`. author: matheusmorett2 license: MIT diff --git a/recipes/process-assert-to-node-assert/package.json b/recipes/process-assert-to-node-assert/package.json index 7def4101..f4f6fd5d 100644 --- a/recipes/process-assert-to-node-assert/package.json +++ b/recipes/process-assert-to-node-assert/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/process-assert-to-node-assert", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0100 via transforming `process.assert` to `node:assert`.", "type": "module", "scripts": { diff --git a/recipes/process-main-module/README.md b/recipes/process-main-module/README.md index 5f346d41..397801c2 100644 --- a/recipes/process-main-module/README.md +++ b/recipes/process-main-module/README.md @@ -1,16 +1,60 @@ -# `process.mainModule` DEP0138 +--- +authors: brunocroh +--- -This recipe transforms the usage of `process.mainModule` to use `require.main` in CommonJS modules. +# DEP0138: `process.mainModule` to `require.main` -See [DEP0138](https://nodejs.org/api/deprecations.html#DEP0138). +Replaces deprecated `process.mainModule` with `require.main` in CommonJS modules. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/process-main-module +``` + +## Examples + +### Example 1 + +Direct property access: + +```diff +-if (process.mainModule === module) { ++if (require.main === module) { + // cli thing + } else { + // module thing + } +``` + +### Example 2 + +`mainModule` destructured from `process` — the destructuring is removed and all usages are replaced with `require.main`: ```diff -- if (process.mainModule === "mod.js") { -+ if (require.main === "mod.js") { - // cli thing - } else { - // module thing - } +-const { mainModule } = process; +- +-if (mainModule === module) { +- console.log(mainModule.filename); ++if (require.main === module) { ++ console.log(require.main.filename); + } ``` + +### Example 3 + +`mainModule` destructured from a `require("node:process")` call alongside other bindings — only `mainModule` is removed from the destructure; the remaining bindings are preserved: + +```diff +-const { mainModule, env, cwd } = require("node:process"); ++const { env, cwd } = require("node:process"); + +-if (mainModule === module) { ++if (require.main === module) { + console.log(env, cwd); + } +``` + + diff --git a/recipes/process-main-module/codemod.yaml b/recipes/process-main-module/codemod.yaml index a837a898..c172e6e2 100644 --- a/recipes/process-main-module/codemod.yaml +++ b/recipes/process-main-module/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/process-main-module" -version: "1.0.3" +version: "1.0.4" description: Handle DEP0138 via transforming `process.mainModule` to `require.main`. author: Bruno Rodrigues license: MIT diff --git a/recipes/process-main-module/package.json b/recipes/process-main-module/package.json index 07febdb2..2ae50bed 100644 --- a/recipes/process-main-module/package.json +++ b/recipes/process-main-module/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/process-main-module", - "version": "1.0.2", + "version": "1.0.4", "description": "Handle DEP0138 via transforming `process.mainModule` to `require.main`.", "type": "module", "scripts": { diff --git a/recipes/repl-builtin-modules/README.md b/recipes/repl-builtin-modules/README.md index 5b7ddbc4..40e445dd 100644 --- a/recipes/repl-builtin-modules/README.md +++ b/recipes/repl-builtin-modules/README.md @@ -1,17 +1,61 @@ -# `repl.builtinModules` DEP0191 +--- +authors: AugustinMauroy +--- -This recipe provides a guide for migrating from the deprecated `repl.builtinModules` & `repl._builtinLibs` to the new `module.builtinModules` property in Node.js. +# DEP0191: `repl.builtinModules` / `repl._builtinLibs` to `module.builtinModules` -See [DEP0191](https://nodejs.org/api/deprecations.html#DEP0191) and [DEP0142](https://nodejs.org/api/deprecations.html#DEP0142) +Replaces deprecated access to `repl.builtinModules` and `repl._builtinLibs` with `module.builtinModules` from `node:module`. Handles namespace requires, destructured requires (including aliased), ESM named imports, and dynamic imports. Both property names are normalized to `builtinModules` in all cases. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/repl-builtin-modules +``` ## Examples +### Example 1 + +Namespace `require` — the variable is renamed to `module` and all accesses (including `_builtinLibs`) are updated: + +```diff +-const repl = require('node:repl'); ++const module = require('node:module'); + +-console.log(repl.builtinModules); +-console.log(repl._builtinLibs); ++console.log(module.builtinModules); ++console.log(module.builtinModules); +``` + +### Example 2 + +Destructured `require` with an aliased builtin property — only the module specifier changes: + +```diff +-const { builtinModules: nodeBuiltinModules } = require('node:repl'); ++const { builtinModules: nodeBuiltinModules } = require('node:module'); + +console.log(nodeBuiltinModules); +``` + +### Example 3 + +Mixed named ESM import — the builtin specifier is split into a new import from `node:module`, and `_builtinLibs` references are renamed to `builtinModules`: + ```diff -- import repl from 'node:repl'; -+ import module from 'node:module'; +-import { builtinModules, _builtinLibs, foo } from 'node:repl'; ++import { foo } from 'node:repl'; ++import { builtinModules } from 'node:module'; -- console.log(repl.builtinModules); -+ console.log(module.builtinModules); -- console.log(repl._builtinLibs); -+ console.log(module.builtinModules); +-console.log(builtinModules); +-console.log(_builtinLibs); ++console.log(builtinModules); ++console.log(builtinModules); + +foo(); // does something else ``` + + diff --git a/recipes/repl-builtin-modules/codemod.yaml b/recipes/repl-builtin-modules/codemod.yaml index 3a2e8659..4845d6a4 100644 --- a/recipes/repl-builtin-modules/codemod.yaml +++ b/recipes/repl-builtin-modules/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/repl-builtin-modules" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0191 via transforming `repl.builtinModules` usage to `module.builtinModules`. author: Augustin Mauroy license: MIT diff --git a/recipes/repl-builtin-modules/package.json b/recipes/repl-builtin-modules/package.json index fcdf4dbf..4fd1984e 100644 --- a/recipes/repl-builtin-modules/package.json +++ b/recipes/repl-builtin-modules/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/repl-builtin-modules", - "version": "1.0.1", + "version": "1.0.3", "description": "Handle DEP0191 via transforming `repl.builtinModules` usage to `module.builtinModules`.", "type": "module", "scripts": { diff --git a/recipes/repl-classes-with-new/README.md b/recipes/repl-classes-with-new/README.md index 05aa9af4..1f4bd37d 100644 --- a/recipes/repl-classes-with-new/README.md +++ b/recipes/repl-classes-with-new/README.md @@ -1,27 +1,68 @@ -# `repl` classes DEP0185 +--- +authors: AugustinMauroy +--- +# DEP0185: Instantiating `node:repl` Classes Without `new` -This recipe provides a guide for migrating from the deprecated instantiation of `node:repl` classes without `new` to proper class instantiation in Node.js. +Adds the missing `new` keyword to calls to `repl.REPLServer()` and `repl.Recoverable()` that are invoked as plain functions. Works with CommonJS `require`, ESM named imports, ESM namespace imports, and dynamic imports. -See [DEP0185](https://nodejs.org/api/deprecations.html#DEP0185). +## Usage -## Example +Run this codemod with: + +```sh +npx codemod @nodejs/repl-classes-with-new +``` + +## Examples + +### Example 1 + +CommonJS namespace import — every class call without `new` is fixed: + +```diff +const repl = require("node:repl"); + +-const server = repl.REPLServer(); ++const server = new repl.REPLServer(); + +-const server2 = repl.REPLServer({ ++const server2 = new repl.REPLServer({ + prompt: "custom> ", + input: process.stdin, + output: process.stdout +}); + +-const error = repl.Recoverable(new SyntaxError()); ++const error = new repl.Recoverable(new SyntaxError()); + +function createREPL(options) { +- return repl.REPLServer(options); ++ return new repl.REPLServer(options); +} +``` + +### Example 2 + +ESM named import — destructured class identifiers are handled the same way: ```diff - const repl = require("node:repl"); - const { REPLServer, Recoverable } = require("node:repl"); - import { REPLServer } from "node:repl"; - const { REPLServer: REPL } = await import("node:repl"); - - // Missing 'new' keyword -- const server1 = repl.REPLServer(); -+ // With 'new' keyword -+ const server1 = new repl.REPLServer(); -- const server2 = REPLServer({ prompt: ">>> " }); -+ const server2 = new REPLServer({ prompt: ">>> " }); -- const server3 = repl.Recoverable(); -+ const server3 = new repl.Recoverable(); -- const error = Recoverable(new SyntaxError()); -+ const error = new Recoverable(new SyntaxError()); -- const server4 = REPL({ prompt: ">>> " }); -+ const server4 = new REPL({ prompt: ">>> " }); +import { REPLServer } from "node:repl"; + +-const server = REPLServer(); ++const server = new REPLServer(); + +-const server2 = REPLServer({ ++const server2 = new REPLServer({ + prompt: ">>> ", + useColors: true +}); + +function createCustomREPL() { +- return REPLServer({ ++ return new REPLServer({ + prompt: "custom> " + }); +} ``` + + diff --git a/recipes/repl-classes-with-new/codemod.yaml b/recipes/repl-classes-with-new/codemod.yaml index a8e0aaf9..5915098c 100644 --- a/recipes/repl-classes-with-new/codemod.yaml +++ b/recipes/repl-classes-with-new/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/repl-classes-with-new" -version: "1.0.2" +version: "1.0.3" description: "Handle DEP0185: Instantiating node:repl classes without new" author: GitHub Copilot license: MIT diff --git a/recipes/repl-classes-with-new/package.json b/recipes/repl-classes-with-new/package.json index 1706fd43..83b7a1a6 100644 --- a/recipes/repl-classes-with-new/package.json +++ b/recipes/repl-classes-with-new/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/repl-classes-with-new", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0185: Instantiating node:repl classes without new.", "type": "module", "scripts": { diff --git a/recipes/rmdir/README.md b/recipes/rmdir/README.md index d611c526..4f55db9a 100644 --- a/recipes/rmdir/README.md +++ b/recipes/rmdir/README.md @@ -1,24 +1,77 @@ -# `fs.rmdir` DEP0147 +--- +authors: AugustinMauroy +--- -This recipe provides a guide for migrating from the deprecated `fs.rmdir` and its synchronous and promise-based counterparts to the new `fs.rm` method in Node.js. +# DEP0147: `fs.rmdir()` to `fs.rm()` -See [DEP0147](https://nodejs.org/api/deprecations.html#DEP0147). +Converts `fs.rmdir(path, { recursive: true })` calls to `fs.rm(path, { recursive: true, force: true })`. Also handles the synchronous variant (`fs.rmdirSync` → `fs.rmSync`), the promises variant (`fs.promises.rmdir` → `fs.promises.rm`), destructured imports, and aliased imports. The `force: true` option is always added alongside `recursive: true`. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/rmdir +``` ## Examples +### Example 1 + +Namespace `require` — all three API shapes are migrated, untouched calls are left alone: + +```diff +const fs = require("node:fs"); + +const pathName = "path/to/directory"; + +-fs.rmdir(pathName, { recursive: true }, () => { }); ++fs.rm(pathName, { recursive: true, force: true }, () => { }); +-fs.rmdirSync(pathName, { recursive: true }); ++fs.rmSync(pathName, { recursive: true, force: true }); +-fs.promises.rmdir(pathName, { recursive: true }); ++fs.promises.rm(pathName, { recursive: true, force: true }); +fs.rmdir(pathName, { recursive: false }); // should not be transformed +fs.rmdir(pathName); // should not be transformed +``` + +### Example 2 + +Destructured `require` — `rm` is added to the destructured bindings and calls are updated: + ```diff - // Using fs.rmdir with the recursive option -- fs.rmdir(path, { recursive: true }, callback); -+ // Using fs.rm with recursive and force options -+ fs.rm(path, { recursive: true, force: true }, callback); - - // Using fs.rmdirSync with the recursive option -- fs.rmdirSync(path, { recursive: true }); -+ // Using fs.rmSync with recursive and force options -+ fs.rmSync(path, { recursive: true, force: true }); - - // Using fs.promises.rmdir with the recursive option -- fs.promises.rmdir(path, { recursive: true }); -+ // Using fs.promises.rm with recursive and force options -+ fs.promises.rm(path, { recursive: true, force: true }); +-const { rmdir, rmdirSync, promises } = require("node:fs"); ++const { rm, rmdir, rmSync, promises } = require("node:fs"); + +const pathName = "path/to/directory"; + +-rmdir(pathName, { recursive: true }, () => { }); ++rm(pathName, { recursive: true, force: true }, () => { }); +-rmdirSync(pathName, { recursive: true }); ++rmSync(pathName, { recursive: true, force: true }); +-promises.rmdir(pathName, { recursive: true }); ++promises.rm(pathName, { recursive: true, force: true }); +rmdir(pathName, { recursive: false }); // should not be transformed +rmdir(pathName); // should not be transformed ``` + +### Example 3 + +Aliased ESM import — the imported name is changed from `rmdir` to `rm`: + +```diff +-import { rmdir as foo } from "node:fs"; ++import { rm as foo } from "node:fs"; + +const pathName = "path/to/directory"; + +foo(pathName, { recursive: true }, () => {}); +``` + +## Notes + +### Limitations + +Only calls that include `{ recursive: true }` in the options argument are transformed. Calls to `fs.rmdir` without that option are left untouched, as they do not trigger the deprecation. + + diff --git a/recipes/rmdir/codemod.yaml b/recipes/rmdir/codemod.yaml index 2223fa29..153d103a 100644 --- a/recipes/rmdir/codemod.yaml +++ b/recipes/rmdir/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/rmdir" -version: "1.1.2" +version: "1.1.3" description: Handle DEP0147 via transforming `fs.rmdir` to `fs.rm` author: Augustin Mauroy license: MIT diff --git a/recipes/rmdir/package.json b/recipes/rmdir/package.json index 4c2e2d8c..b9d9dda6 100644 --- a/recipes/rmdir/package.json +++ b/recipes/rmdir/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/rmdir", - "version": "1.1.2", + "version": "1.1.3", "description": "Handle DEP0147 via transforming `fs.rmdir` to `fs.rm` with the appropriate options.", "type": "module", "scripts": { diff --git a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/README.md b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/README.md index a7f0d036..a60e4e86 100644 --- a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/README.md +++ b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/README.md @@ -1,20 +1,55 @@ -# SlowBuffer to Buffer.allocUnsafeSlow Codemod +--- +authors: lluisemper +--- -This codemod migrates deprecated `SlowBuffer` usage to `Buffer.allocUnsafeSlow()` to handle Node.js [DEP0030](https://nodejs.org/api/deprecations.html#DEP0030). +# DEP0030: `SlowBuffer` to `Buffer.allocUnsafeSlow()` -## What it does +Replaces deprecated `SlowBuffer` constructor and function calls with `Buffer.allocUnsafeSlow()` and updates the corresponding `require`/`import` statement so that `Buffer` is imported instead of `SlowBuffer`. -This codemod transforms: +## Usage -1. `SlowBuffer` constructor calls to `Buffer.allocUnsafeSlow()` -2. Direct `SlowBuffer` calls to `Buffer.allocUnsafeSlow()` -3. Import/require statements be synced with new function +Run this codemod with: -## Example +```sh +npx codemod @nodejs/slow-buffer-to-buffer-alloc-unsafe-slow +``` + +## Examples + +### Example 1 + +`require` with member access — both the binding and the property are renamed, and usages are replaced: + +```diff +-const SlowBuffer = require('buffer').SlowBuffer; ++const Buffer = require('buffer').Buffer; + +-const buf1 = new SlowBuffer(1024); ++const buf1 = Buffer.allocUnsafeSlow(1024); +-const buf2 = SlowBuffer(512); ++const buf2 = Buffer.allocUnsafeSlow(512); +``` + +### Example 2 + +Destructured `require` — `SlowBuffer` is replaced by `Buffer` in the destructuring: + +```diff +-const { SlowBuffer } = require('buffer'); ++const { Buffer } = require('buffer'); +-const buf3 = new SlowBuffer(256); ++const buf3 = Buffer.allocUnsafeSlow(256); +``` + +### Example 3 + +ESM named import — the import specifier is updated and the call site is rewritten: ```diff -- import { SlowBuffer } from "buffer"; -+ import { Buffer } from "buffer"; -- const buf = new SlowBuffer(1024); -+ const buf = Buffer.allocUnsafeSlow(1024); +-import { SlowBuffer } from 'buffer'; ++import { Buffer } from 'buffer'; +-const buf = new SlowBuffer(1024); ++const buf = Buffer.allocUnsafeSlow(1024); ``` + + diff --git a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml index ab0ba27f..5a5833e1 100644 --- a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml +++ b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/slow-buffer-to-buffer-alloc-unsafe-slow" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0030 via transforming SlowBuffer usage to Buffer.allocUnsafeSlow(). author: lluisemper(Lluis Semper Lloret) license: MIT diff --git a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json index 2db884e8..bf87f6a3 100644 --- a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json +++ b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/slow-buffer-to-buffer-alloc-unsafe-slow", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0030 via transforming SlowBuffer usage to Buffer.allocUnsafeSlow().", "type": "module", "scripts": { diff --git a/recipes/timers-deprecations/README.md b/recipes/timers-deprecations/README.md index 6c10ce04..f43b1b9f 100644 --- a/recipes/timers-deprecations/README.md +++ b/recipes/timers-deprecations/README.md @@ -1,39 +1,115 @@ -# Node.js Timers Deprecations +--- +authors: AugustinMauroy +--- +# DEP0095/DEP0096/DEP0126/DEP0127: Deprecated `node:timers` APIs -This recipe migrates deprecated internals from `node:timers` to the supported public timers API. It replaces usages of `timers.enroll()`, `timers.unenroll()`, `timers.active()`, and `timers._unrefActive()` with standard constructs built on top of `setTimeout()`, `clearTimeout()`, and `Timer#unref()`. +Migrates the four deprecated `node:timers` internal APIs — `timers.enroll()`, `timers.unenroll()`, `timers.active()`, and `timers._unrefActive()` — to their modern equivalents built on `setTimeout` and `clearTimeout`. -See the upstream notices: [DEP0095](https://nodejs.org/api/deprecations.html#DEP0095), [DEP0096](https://nodejs.org/api/deprecations.html#DEP0096), [DEP0126](https://nodejs.org/api/deprecations.html#DEP0126), and [DEP0127](https://nodejs.org/api/deprecations.html#DEP0127). +## Usage -## Example +Run this codemod with: -### Replace `timers.enroll()` +```sh +npx codemod @nodejs/timers-deprecations +``` + +## Examples + +### Example 1 + +`timers.enroll(resource, delay)` — replaced with an inline `setTimeout` that calls `resource._onTimeout` and stores the handle on `resource.timeout`: + +```diff +const timers = require("node:timers"); + +const resource = { + _onTimeout() { + console.log("done"); + }, +}; + +-timers.enroll(resource, 1000); ++resource._idleTimeout = 1000; ++resource.timeout = setTimeout(() => { ++ if (typeof resource._onTimeout === "function") { ++ resource._onTimeout(); ++ } ++}, 1000); +``` + +### Example 2 + +`timers.unenroll(resource)` — replaced with a `clearTimeout` followed by deleting the handle: ```diff -- const timers = require('node:timers'); -- const resource = { _idleTimeout: 1500 }; -- timers.enroll(resource, 1500); -+ const resource = { timeout: setTimeout(() => { -+ // timeout handler -+ }, 1500) }; +const timers = require("node:timers"); + +const resource = { + timeout: setTimeout(() => { }, 1000), +}; + +-timers.unenroll(resource); ++clearTimeout(resource.timeout); ++delete resource.timeout; ``` -### Replace `timers.unenroll()` +### Example 3 + +`timers.active(resource)` — replaced with a conditional `clearTimeout` and a fresh `setTimeout` that re-uses `resource._idleTimeout` and `resource._onTimeout`: ```diff -- timers.unenroll(resource); -+ clearTimeout(resource.timeout); +const timers = require("node:timers"); + +const resource = { + _idleTimeout: 500, + timeout: setTimeout(() => { }, 500), + _onTimeout() { + console.log("again"); + }, +}; + +-timers.active(resource); ++if (resource.timeout != null) { ++ clearTimeout(resource.timeout); ++} ++ ++resource.timeout = setTimeout(() => { ++ if (typeof resource._onTimeout === "function") { ++ resource._onTimeout(); ++ } ++}, resource._idleTimeout); ``` -### Replace `timers.active()` and `timers._unrefActive()` +### Example 4 + +`timers._unrefActive(resource)` — same expansion as `timers.active()` plus a call to `.unref()` on the new handle: ```diff -- const timers = require('node:timers'); -- timers.active(resource); -- timers._unrefActive(resource); -+ const handle = setTimeout(onTimeout, delay); -+ handle.unref(); +const timers = require("node:timers"); + +const resource = { + _idleTimeout: 60, + timeout: setTimeout(() => { }, 60), + _onTimeout() { + console.log("cleanup"); + }, +}; + +-timers._unrefActive(resource); ++if (resource.timeout != null) { ++ clearTimeout(resource.timeout); ++} ++ ++resource.timeout = setTimeout(() => { ++ if (typeof resource._onTimeout === "function") { ++ resource._onTimeout(); ++ } ++}, resource._idleTimeout); ++resource.timeout.unref?.(); ``` -## Caveats +## Notes + +`timers.active(resource)` and `timers._unrefActive(resource)` expand into a multi-statement block that reads `resource._idleTimeout` for the delay and `resource._onTimeout` for the callback. These are internal bookkeeping fields that the deprecated API relied on. If the resource object in your code uses different field names, review the output and adjust accordingly. -The legacy APIs exposed internal timer bookkeeping fields such as `_idleStart` or `_idleTimeout`. Those internals have no public equivalent. The codemod focuses on migrating the control flow to modern timers and leaves application specific bookkeeping to the developer. Carefully review the transformed code to ensure that any custom metadata is still updated as expected. + diff --git a/recipes/timers-deprecations/codemod.yaml b/recipes/timers-deprecations/codemod.yaml index 8b7ee68b..b6f2c9dc 100644 --- a/recipes/timers-deprecations/codemod.yaml +++ b/recipes/timers-deprecations/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/timers-deprecations" -version: 1.0.0 +version: 1.0.1 description: Migrate deprecated node:timers APIs to public timer functions. author: Augustin Mauroy license: MIT diff --git a/recipes/timers-deprecations/package.json b/recipes/timers-deprecations/package.json index 339bb67e..6eca4388 100644 --- a/recipes/timers-deprecations/package.json +++ b/recipes/timers-deprecations/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/timers-deprecations", - "version": "1.0.0", + "version": "1.0.1", "description": "Migrate deprecated node:timers APIs to public timer functions.", "type": "module", "scripts": { diff --git a/recipes/tls-create-secure-pair-to-tls-socket/README.md b/recipes/tls-create-secure-pair-to-tls-socket/README.md index 9f7f10ce..bc33b546 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/README.md +++ b/recipes/tls-create-secure-pair-to-tls-socket/README.md @@ -1,108 +1,55 @@ -# `tls.createSecurePair` deprecation DEP0064 +--- +authors: technologic-technologic +--- -This recipe transforms the usage from the deprecated `createSecurePair()` to `TLSSocket()`. +# DEP0064: `tls.createSecurePair()` to `new tls.TLSSocket()` -See [DEP0064](https://nodejs.org/api/deprecations.html#dep0064-tlscreatesecurepair). +Replaces deprecated `tls.createSecurePair(...)` calls with `new tls.TLSSocket(underlyingSocket, options)`. The four positional arguments (`secureContext`, `isServer`, `requestCert`, `rejectUnauthorized`) are converted into named properties of an options object. The result variable is renamed from `pair` to `socket`, and the import/require declaration is updated from `createSecurePair` to `TLSSocket`. -## Examples +## Usage -### 1) Basic `createSecurePair` usage -```diff --const { createSecurePair } = require('node:tls'); -+const { TLSSocket } = require('node:tls'); +Run this codemod with: --const pair = createSecurePair(credentials); -+const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); +```sh +npx codemod @nodejs/tls-create-secure-pair-to-tls-socket ``` ---- +## Examples -### 2) Namespace import (CJS) -```diff --const tls = require('node:tls'); -+const tls = require('node:tls'); +### Example 1 +Namespace `require` — the call is replaced with `new tls.TLSSocket(...)` and the result variable renamed: + +```diff +const tls = require('node:tls'); -const pair = tls.createSecurePair(credentials); +const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); ``` ---- +### Example 2 + +Destructured `require` with all four positional arguments — each argument becomes a named option: -### 3) With server context ```diff -const { createSecurePair } = require('node:tls'); +const { TLSSocket } = require('node:tls'); - -const pair = createSecurePair(credentials, true, true, false); -+const socket = new TLSSocket(underlyingSocket, { -+ secureContext: credentials, -+ isServer: true, -+ requestCert: true, -+ rejectUnauthorized: false -+}); ++const socket = new TLSSocket(underlyingSocket, { secureContext: credentials, isServer: true, requestCert: true, rejectUnauthorized: false }); ``` ---- +### Example 3 + +ESM named import: -### 4) ESM named import ```diff -import { createSecurePair } from 'node:tls'; +import { TLSSocket } from 'node:tls'; - -const pair = createSecurePair(credentials); +const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); ``` ---- +## Notes -### 5) ESM namespace import -```diff --import * as tls from 'node:tls'; -+import * as tls from 'node:tls'; - --const pair = tls.createSecurePair(credentials); -+const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); -``` - ---- +The first argument to `createSecurePair` (the secure context) maps to `secureContext` in the `TLSSocket` options object. The underlying stream that `TLSSocket` requires as its first positional argument is inserted as `underlyingSocket` — review each call site to supply the correct stream reference for your application. -### 6) Mixed usage with other TLS functions -```diff --const { createSecurePair, createServer } = require('node:tls'); -+const { TLSSocket, createServer } = require('node:tls'); - --const pair = createSecurePair(credentials); --const server = createServer(options); -+const socket = new TLSSocket(underlyingSocket, { secureContext: credentials }); -+const server = createServer(options); -``` - ---- - -### 7) ESM default import -```diff -import tls from 'node:tls'; - --const pair = tls.createSecurePair(credentials); -+const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); -``` - ---- - -### 8) ESM dynamic import (assignment) -```diff -const tls = await import('node:tls'); - --const pair = tls.createSecurePair(credentials); -+const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); -``` - ---- - -### 9) ESM dynamic import (thenable) -```diff -import('node:tls').then(tls => { -- const pair = tls.createSecurePair(credentials); -+ const socket = new tls.TLSSocket(underlyingSocket, { secureContext: credentials }); -}); -``` + diff --git a/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml index 06eaa249..f1386cfa 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml +++ b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/tls-create-secure-pair-to-tls-socket" -version: 1.0.1 +version: 1.0.2 description: Handle DEP0064 by transforming `createSecurePair` to `TLSSocket` author: Leonardo Trevizo license: MIT diff --git a/recipes/tls-create-secure-pair-to-tls-socket/package.json b/recipes/tls-create-secure-pair-to-tls-socket/package.json index 2243abf4..b404ecb8 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/package.json +++ b/recipes/tls-create-secure-pair-to-tls-socket/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/tls-create-secure-pair-to-tls-socket", - "version": "1.0.1", + "version": "1.0.2", "description": "Handle DEP0064 replacing `tls.createSecurePair()` with `tls.TLSSocket()`", "type": "module", "scripts": { diff --git a/recipes/tmpdir-to-tmpdir/README.md b/recipes/tmpdir-to-tmpdir/README.md index fda48f9b..0d95a875 100644 --- a/recipes/tmpdir-to-tmpdir/README.md +++ b/recipes/tmpdir-to-tmpdir/README.md @@ -1,14 +1,60 @@ -# `tmpDir` DEP0022 +--- +authors: nekojanai +--- -This recipe transforms `tmpDir` function calls to `tmpdir`. +# DEP0022: `os.tmpDir()` to `os.tmpdir()` -See [DEP0022](https://nodejs.org/docs/latest/api/deprecations.html#dep0022-ostmpdir). +Renames the deprecated `os.tmpDir()` function to `os.tmpdir()`. This is a case-sensitive rename that applies to both the imported binding name and all call sites. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/tmpDir-to-tmpdir +``` ## Examples +### Example 1 + +Updating a `require` import and its call sites: + +```diff +-const { tmpDir } = require('os'); ++const { tmpdir } = require('os'); + +-var t0 = tmpDir(); +-let t1 = tmpDir(); +-const t2 = tmpDir(); ++var t0 = tmpdir(); ++let t1 = tmpdir(); ++const t2 = tmpdir(); +``` + +### Example 2 + +Updating a `require` import using the `node:` protocol: + +```diff +-const { tmpDir } = require('node:os'); ++const { tmpdir } = require('node:os'); + +-var t0 = tmpDir(); +-let t1 = tmpDir(); +-const t2 = tmpDir(); ++var t0 = tmpdir(); ++let t1 = tmpdir(); ++const t2 = tmpdir(); +``` + +### Example 3 + +Updating an aliased destructuring import: + ```diff -- import { tmpDir } from 'node:os'; -+ import { tmpdir } from 'node:os'; -- const foo = tmpDir() -+ const foo = tmpdir() -```` +-const { tmpDir: tmpdir } = require('node:os'); ++const { tmpdir: tmpdir } = require('node:os'); +``` + + diff --git a/recipes/tmpdir-to-tmpdir/codemod.yaml b/recipes/tmpdir-to-tmpdir/codemod.yaml index dae8ab98..d1caee7e 100644 --- a/recipes/tmpdir-to-tmpdir/codemod.yaml +++ b/recipes/tmpdir-to-tmpdir/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/tmpDir-to-tmpdir" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0022 via transforming `tmpDir` to `tmpdir`. author: nekojanai (Jana) license: MIT diff --git a/recipes/tmpdir-to-tmpdir/package.json b/recipes/tmpdir-to-tmpdir/package.json index 8f837ff6..20520118 100644 --- a/recipes/tmpdir-to-tmpdir/package.json +++ b/recipes/tmpdir-to-tmpdir/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/tmpdir-to-tmpdir", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0022 via transforming `tmpDir` to `tmpdir`.", "type": "module", "scripts": { diff --git a/recipes/types-is-native-error/README.md b/recipes/types-is-native-error/README.md index 9122a5e5..4857d5a7 100644 --- a/recipes/types-is-native-error/README.md +++ b/recipes/types-is-native-error/README.md @@ -1,16 +1,76 @@ -# `types.isNativeError` DEP0197 +--- +authors: brunocroh +--- -This recipe transforms the usage of `types.isNativeError` to use the `Error.isError`. +# DEP0197: `util.types.isNativeError()` to `Error.isError()` -See [DEP0197](https://nodejs.org/api/deprecations.html#DEP0197). +Replaces all usages of the deprecated `util.types.isNativeError()` with `Error.isError()`. The codemod handles `util.types.isNativeError(x)`, `types.isNativeError(x)`, and destructured `isNativeError(x)` call patterns. The `util` import is removed when it becomes unused after the transformation. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/types-is-native-error +``` + +## Examples + +### Example 1 + +Named ESM import — the entire import statement is removed: + +```diff +-import { types } from "node:util"; +- +-if (types.isNativeError(err)) { ++if (Error.isError(err)) { + // handle the error + } +``` + +### Example 2 + +Multiple require patterns in the same file — all three call forms are rewritten and all three imports are removed: ```diff -- import { types } from "node:util"; +-const util = require("node:util"); +-const { types } = require("util"); +-const { +- types: { isNativeError }, +-} = require("util"); + const err = new Error(); -- if (types.isNativeError(err)) { -+ if (Error.isError(err)) { - // handle the error - } +-if (util.types.isNativeError(err)) { ++if (Error.isError(err)) { + // handle the error + } + +-if (types.isNativeError(err)) { ++if (Error.isError(err)) { + // handle the error + } + +-if (isNativeError(err)) { ++if (Error.isError(err)) { + // handle the error + } +``` + +### Example 3 + +When `types` is still used for other methods, only `isNativeError` calls are replaced and the import is kept: + +```diff + const { types } = require("util"); + +-if (types.isNativeError(err)) { ++if (Error.isError(err)) { + // handle the error + } + + if (types.isMap([])) { + } ``` + + diff --git a/recipes/types-is-native-error/codemod.yaml b/recipes/types-is-native-error/codemod.yaml index 53b17b83..f655a3fc 100644 --- a/recipes/types-is-native-error/codemod.yaml +++ b/recipes/types-is-native-error/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/types-is-native-error" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0197 via transforming `types.isNativeError` to `Error.isError` author: Bruno Rodrigues license: MIT diff --git a/recipes/types-is-native-error/package.json b/recipes/types-is-native-error/package.json index 9bc4c8b6..2c23d961 100644 --- a/recipes/types-is-native-error/package.json +++ b/recipes/types-is-native-error/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/types-is-native-error", - "version": "1.0.1", + "version": "1.0.3", "description": "Handle DEP0197 via transforming `types.isNativeError` to `Error.isError`", "type": "module", "scripts": { diff --git a/recipes/util-extend-to-object-assign/README.md b/recipes/util-extend-to-object-assign/README.md index 1460912c..57368048 100644 --- a/recipes/util-extend-to-object-assign/README.md +++ b/recipes/util-extend-to-object-assign/README.md @@ -1,15 +1,51 @@ -# `util._extend` DEP0060 +--- +authors: AugustinMauroy +--- -This recipe transforms the usage of deprecated `util._extend()` to use `Object.assign()`. +# DEP0060: `util._extend()` to `Object.assign()` -See [DEP0060](https://nodejs.org/api/deprecations.html#DEP0060). +Replaces the deprecated `util._extend(target, source)` with `Object.assign(target, source)`. The codemod handles namespace imports (`util._extend`), destructured named imports (`const { _extend } = require('util')`), and aliased imports. The `util` import is removed when it becomes unused after the transformation. -## Example +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/util-extend-to-object-assign +``` + +## Examples + +### Example 1 + +Namespace `require` — the import is removed because `util` is no longer used: ```diff -- const util = require("node:util"); - const target = { a: 1 }; - const source = { b: 2 }; -- const result = util._extend(target, source); -+ const result = Object.assign(target, source); +-const util = require('util'); + const a = { x: 1 }; + const b = { y: 2 }; +-util._extend(a, b); ++Object.assign(a, b); ``` + +### Example 2 + +Default ESM import — the import is removed: + +```diff +-import util from 'node:util'; +-util._extend({}, {}); ++Object.assign({}, {}); +``` + +### Example 3 + +Destructured named import — the import is removed: + +```diff +-const { _extend } = require('util'); +-_extend({}, {}); ++Object.assign({}, {}); +``` + + diff --git a/recipes/util-extend-to-object-assign/codemod.yaml b/recipes/util-extend-to-object-assign/codemod.yaml index c394dafc..713510fb 100644 --- a/recipes/util-extend-to-object-assign/codemod.yaml +++ b/recipes/util-extend-to-object-assign/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-extend-to-object-assign" -version: 1.0.1 +version: 1.0.2 description: "Handle DEP0060 by replacing `util._extend()` with `Object.assign()`." author: GitHub Copilot license: MIT diff --git a/recipes/util-extend-to-object-assign/package.json b/recipes/util-extend-to-object-assign/package.json index 52b906ca..d9ac3380 100644 --- a/recipes/util-extend-to-object-assign/package.json +++ b/recipes/util-extend-to-object-assign/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-extend-to-object-assign", - "version": "1.0.1", + "version": "1.0.2", "description": "Handle DEP0060 by replacing `util._extend()` with `Object.assign()`.", "type": "module", "scripts": { diff --git a/recipes/util-is/README.md b/recipes/util-is/README.md index c3e69383..fe321691 100644 --- a/recipes/util-is/README.md +++ b/recipes/util-is/README.md @@ -1,39 +1,84 @@ -# `util.is*()` - -This codemod replaces the following deprecated `util.is*()` methods with their modern equivalents: - -- [DEP0044: `util.isArray()`](https://nodejs.org/docs/latest/api/deprecations.html#DEP0044) -- [DEP0045: `util.isBoolean()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0045-utilisboolean) -- [DEP0046: `util.isBuffer()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0046-utilisbuffer) -- [DEP0047: `util.isDate()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0047-utilisdate) -- [DEP0048: `util.isError()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0048-utiliserror) -- [DEP0049: `util.isFunction()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0049-utilisfunction) -- [DEP0050: `util.isNull()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0050-utilisnull) -- [DEP0051: `util.isNullOrUndefined()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0051-utilisnullorundefined) -- [DEP0052: `util.isNumber()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0052-utilisnumber) -- [DEP0053: `util.isObject()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0053-utilisobject) -- [DEP0054: `util.isPrimitive()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0054-utilisprimitive) -- [DEP0055: `util.isRegExp()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0055-utilisregexp) -- [DEP0056: `util.isString()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0056-utilisstring) -- [DEP0057: `util.isSymbol()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0057-utilissymbol) -- [DEP0058: `util.isUndefined()`](https://nodejs.org/docs/latest/api/deprecations.html#dep0058-utilisundefined) +--- +authors: AugustinMauroy +--- +# DEP0044-DEP0058: `util.is*()` Methods + +Replaces all deprecated `util.is*()` type-checking methods with their modern equivalents. The codemod handles namespace imports (`util.isArray`), destructured named imports, and removes the `util` import when it becomes unused after the transformation. + +The full set of replacements is: + +| Deprecated | Replacement | +|---|---| +| `util.isArray(x)` | `Array.isArray(x)` | +| `util.isBoolean(x)` | `typeof x === 'boolean'` | +| `util.isBuffer(x)` | `Buffer.isBuffer(x)` | +| `util.isDate(x)` | `x instanceof Date` | +| `util.isError(x)` | `Error.isError(x)` | +| `util.isFunction(x)` | `typeof x === 'function'` | +| `util.isNull(x)` | `x === null` | +| `util.isNullOrUndefined(x)` | `x === null \|\| x === undefined` | +| `util.isNumber(x)` | `typeof x === 'number'` | +| `util.isObject(x)` | `x && typeof x === 'object'` | +| `util.isPrimitive(x)` | `Object(x) !== x` | +| `util.isRegExp(x)` | `x instanceof RegExp` | +| `util.isString(x)` | `typeof x === 'string'` | +| `util.isSymbol(x)` | `typeof x === 'symbol'` | +| `util.isUndefined(x)` | `typeof x === 'undefined'` | + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/util-is +``` ## Examples -| **Before** | **After** | -|-----------------------------------|---------------------------------------------| -| `util.isArray(value)` | `Array.isArray(value)` | -| `util.isBoolean(value)` | `typeof value === 'boolean'` | -| `util.isBuffer(value)` | `Buffer.isBuffer(value)` | -| `util.isDate(value)` | `value instanceof Date` | -| `util.isError(value)` | `Error.isError(value)` | -| `util.isFunction(value)` | `typeof value === 'function'` | -| `util.isNull(value)` | `value === null` | -| `util.isNullOrUndefined(value)` | `value === null \|\| value === undefined` | -| `util.isNumber(value)` | `typeof value === 'number'` | -| `util.isObject(value)` | `value && typeof value === 'object'` | -| `util.isPrimitive(value)` | `Object(value) !== value` | -| `util.isRegExp(value)` | `value instanceof RegExp` | -| `util.isString(value)` | `typeof value === 'string'` | -| `util.isSymbol(value)` | `typeof value === 'symbol'` | -| `util.isUndefined(value)` | `typeof value === 'undefined'` | +### Example 1 + +Namespace `require` with multiple `util.is*()` calls — the import is removed: + +```diff +-const util = require('node:util'); +- +-if (util.isArray(someValue)) { ++if (Array.isArray(someValue)) { + console.log('someValue is an array'); + } +-if (util.isBoolean(someValue)) { ++if (typeof someValue === 'boolean') { + console.log('someValue is a boolean'); + } +-if (util.isDate(someValue)) { ++if (someValue instanceof Date) { + console.log('someValue is a date'); + } +-if (util.isNullOrUndefined(someValue)) { ++if (someValue === null || someValue === undefined) { + console.log('someValue is null or undefined'); + } +-if (util.isPrimitive(someValue)) { ++if (Object(someValue) !== someValue) { + console.log('someValue is a primitive'); + } +``` + +### Example 2 + +Destructured named import — the import is removed: + +```diff +-const { isArray, isBoolean } = require('node:util'); +- +-if (isArray(someValue)) { ++if (Array.isArray(someValue)) { + console.log('someValue is an array'); + } +-if (isBoolean(someValue)) { ++if (typeof someValue === 'boolean') { + console.log('someValue is a boolean'); + } +``` + + diff --git a/recipes/util-is/codemod.yaml b/recipes/util-is/codemod.yaml index 0e8c2e90..2eeacf63 100644 --- a/recipes/util-is/codemod.yaml +++ b/recipes/util-is/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-is" -version: 1.0.2 +version: 1.0.3 description: "Replaces deprecated `util.is*()` methods with their modern equivalents." author: Augustin Mauroy license: MIT diff --git a/recipes/util-is/package.json b/recipes/util-is/package.json index 66eb371e..46a299e8 100644 --- a/recipes/util-is/package.json +++ b/recipes/util-is/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-is", - "version": "1.0.2", + "version": "1.0.3", "description": "Replaces deprecated `util.is*()` methods with their modern equivalents.", "type": "module", "scripts": { diff --git a/recipes/util-log-to-console-log/README.md b/recipes/util-log-to-console-log/README.md index e29add15..f9decc2e 100644 --- a/recipes/util-log-to-console-log/README.md +++ b/recipes/util-log-to-console-log/README.md @@ -1,30 +1,54 @@ -# `util.log` DEP0059 +--- +authors: brunocroh +--- -This recipe transforms the usage of `util.log()` to use `console.log()`. +# DEP0059: `util.log()` to `console.log()` -See [DEP0059](https://nodejs.org/api/deprecations.html#DEP0059). +Replaces the deprecated `util.log(message)` with `console.log(new Date().toLocaleString(), message)`, preserving the timestamp prefix that `util.log` appended automatically. The `util` import is removed when it becomes unused after the transformation. -## Example +## Usage -```diff -- const util = require("node:util"); +Run this codemod with: -- util.log("Hello world"); -+ console.log(new Date().toLocaleString(), "Hello world"); +```sh +npx codemod @nodejs/util-log-to-console-log ``` -**Before:** +## Examples + +### Example 1 -```js -const { log } = require("node:util"); +Namespace `require` — the import is removed: -log("Application started"); -log("Processing request"); +```diff +-const util = require("node:util"); +- +-util.log("Hello world"); ++console.log(new Date().toLocaleString(), "Hello world"); ``` -After: +### Example 2 -```js -console.log(new Date().toLocaleString(), "Application started"); -console.log(new Date().toLocaleString(), "Processing request"); +Destructured named import — the import is removed: + +```diff +-const { log } = require("node:util"); +- +-log("Application started"); +-log("Processing request"); ++console.log(new Date().toLocaleString(), "Application started"); ++console.log(new Date().toLocaleString(), "Processing request"); ``` + +### Example 3 + +Named ESM import — the import is removed: + +```diff +-import { log } from "node:util"; +- +-log("Server listening on port 3000"); ++console.log(new Date().toLocaleString(), "Server listening on port 3000"); +``` + + diff --git a/recipes/util-log-to-console-log/codemod.yaml b/recipes/util-log-to-console-log/codemod.yaml index 5ef3f55b..e19cfa16 100644 --- a/recipes/util-log-to-console-log/codemod.yaml +++ b/recipes/util-log-to-console-log/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-log-to-console-log" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0059 via transforming `log.util()` to `console.log()`. author: Bruno Rodrigues license: MIT diff --git a/recipes/util-log-to-console-log/package.json b/recipes/util-log-to-console-log/package.json index ca05beaa..ced0b78b 100644 --- a/recipes/util-log-to-console-log/package.json +++ b/recipes/util-log-to-console-log/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-log-to-console-log", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0059 via transforming `log.util()` to `console.log()`", "type": "module", "scripts": { diff --git a/recipes/util-print-to-console-log/README.md b/recipes/util-print-to-console-log/README.md index 5ac7e139..adfa9919 100644 --- a/recipes/util-print-to-console-log/README.md +++ b/recipes/util-print-to-console-log/README.md @@ -1,23 +1,70 @@ -# `util.print, util.puts, util.debug, util.error` DEP0026,DEP0027,DEP0028,DEP0029 +--- +authors: brunocroh +--- -This recipe transforms the usage of log functions from util, `print`, `puts`, `debug`, `error` to use `console.log()` or `console.error()`. +# DEP0026/DEP0027/DEP0028/DEP0029: `util` Print Functions to `console` -See [DEP0026](https://nodejs.org/api/deprecations.html#DEP0026). -See [DEP0027](https://nodejs.org/api/deprecations.html#DEP0027). -See [DEP0028](https://nodejs.org/api/deprecations.html#DEP0028). -See [DEP0029](https://nodejs.org/api/deprecations.html#DEP0029). +Replaces four deprecated `util` output functions with their `console` equivalents: -## Example +- `util.print(...)` (DEP0026) `console.log(...)` +- `util.puts(...)` (DEP0027) `console.log(...)` +- `util.debug(...)` (DEP0028) `console.error(...)` +- `util.error(...)` (DEP0029) `console.error(...)` + +The `util` import is removed when it becomes unused after the transformation. + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/util-print-to-console-log +``` + +## Examples + +### Example 1 + +`util.print` `console.log`: + +```diff +-const util = require("node:util"); +- +-util.print("Hello world"); ++console.log("Hello world"); +``` + +### Example 2 + +`util.puts` `console.log`: + +```diff +-const util = require("node:util"); +- +-util.puts("Hello world"); ++console.log("Hello world"); +``` + +### Example 3 + +`util.debug` `console.error`: ```diff -- const util = require("node:util"); - -- util.print("Hello world"); -+ console.log("Hello world"); -- util.puts("Hello world"); -+ console.log("Hello world"); -- util.debug("Hello world"); -+ console.error("Hello world"); -- util.error("Hello world"); -+ console.error("Hello world"); +-const util = require("node:util"); +- +-util.debug("Hello world"); ++console.error("Hello world"); ``` + +### Example 4 + +`util.error` `console.error`: + +```diff +-const util = require("node:util"); +- +-util.error("Hello world"); ++console.error("Hello world"); +``` + + diff --git a/recipes/util-print-to-console-log/codemod.yaml b/recipes/util-print-to-console-log/codemod.yaml index 45739cc4..d5b4d995 100644 --- a/recipes/util-print-to-console-log/codemod.yaml +++ b/recipes/util-print-to-console-log/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-print-to-console-log" -version: "1.0.2" +version: "1.0.3" description: Handle DEP0026, DEP0027, DEP0028, DEP0029 via transforming `util.print|puts|debug|error()` to `console.log|error()` author: Bruno Rodrigues license: MIT diff --git a/recipes/util-print-to-console-log/package.json b/recipes/util-print-to-console-log/package.json index 66f24c5e..be55ae81 100644 --- a/recipes/util-print-to-console-log/package.json +++ b/recipes/util-print-to-console-log/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-print-to-console-log", - "version": "1.0.2", + "version": "1.0.3", "description": "Handle DEP0026, DEP0027, DEP0028, DEP0029 via transforming `util.print|puts|debug|error()` to `console.log|error()`", "type": "module", "scripts": { diff --git a/recipes/v22-to-v24/README.md b/recipes/v22-to-v24/README.md index d1c66d3c..aeae7c2a 100644 --- a/recipes/v22-to-v24/README.md +++ b/recipes/v22-to-v24/README.md @@ -1,12 +1,70 @@ -# Node.js v22 → v24 Migration +--- +authors: AugustinMauroy +--- -This codemod only wraps all migrations needed to upgrade a Node.js codebase from **v22 to v24**. +# Node.js v22 to v24 Migration + +Meta-recipe that composes the individual migration codemods from this repository needed to upgrade a codebase from Node.js v22 to v24, replacing deprecated APIs with their modern equivalents in a single run. See the [official v22 to v24 migration guide](https://nodejs.org/en/blog/migrations/v22-to-v24) for the full list of changes in Node.js v24. > [!WARNING] -> This codemod is on `v0.0.X` because there are missing parts so be careful before pushing changes to production. If you find any missing migration, please open an issue or a PR. +> This codemod is on `v0.0.X` because there are missing parts, so be careful before pushing changes to production. If you find any missing migration, please open an issue or a PR. The known missing pieces are tracked in [nodejs/userland-migrations#239](https://github.com/nodejs/userland-migrations/issues/239). + +## Usage + +Run this codemod with: + +```sh +npx codemod @nodejs/v22-to-v24 +``` + +## Included codemods + +Running this recipe applies the following codemods from the Codemod Registry, in order: + +| Codemod | What it migrates | +| ------- | ---------------- | +| [`@nodejs/dirent-path-to-parent-path`](/learn/userland-migrations/dirent-path-to-parent-path) | DEP0178: `dirent.path` to `dirent.parentPath` | +| [`@nodejs/fs-access-mode-constants`](/learn/userland-migrations/fs-access-mode-constants) | DEP0176: `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` to `fs.constants` | +| [`@nodejs/fs-truncate-fd-deprecation`](/learn/userland-migrations/fs-truncate-fd-deprecation) | DEP0081: `fs.truncate()` with a file descriptor to the `ftruncate` family | +| [`@nodejs/http-outgoingmessage-headers`](/learn/userland-migrations/http-outgoingmessage-headers) | DEP0066: `OutgoingMessage.prototype._headers` and `_headerNames` to public header APIs | +| [`@nodejs/http2-priority-signaling`](/learn/userland-migrations/http2-priority-signaling) | DEP0194: removes HTTP/2 priority-related options and methods | +| [`@nodejs/timers-deprecations`](/learn/userland-migrations/timers-deprecations) | DEP0095/DEP0096/DEP0126/DEP0127: deprecated `node:timers` APIs to public timer functions | +| [`@nodejs/tls-create-secure-pair-to-tls-socket`](/learn/userland-migrations/tls-create-secure-pair-to-tls-socket) | DEP0064: `tls.createSecurePair()` to `tls.TLSSocket` | +| [`@nodejs/util-is`](/learn/userland-migrations/util-is) | Deprecated `util.is*()` type checks to their modern equivalents | +| [`@nodejs/util-log-to-console-log`](/learn/userland-migrations/util-log-to-console-log) | DEP0059: `util.log()` to `console.log()` | + +## Examples + +### Deprecated `util.is*()` type checks + +Applied by `@nodejs/util-is`; the unused `node:util` binding is removed once no other usage remains. + +```diff +-const util = require('node:util'); + +-if (util.isArray(someValue)) { ++if (Array.isArray(someValue)) { + console.log('someValue is an array'); + } +-if (util.isDate(someValue)) { ++if (someValue instanceof Date) { + console.log('someValue is a date'); + } +-if (util.isString(someValue)) { ++if (typeof someValue === 'string') { + console.log('someValue is a string'); + } +``` + +### `util.log()` to `console.log()` + +Applied by `@nodejs/util-log-to-console-log`, preserving the timestamp behavior of `util.log()`. -## More information +```diff +-const util = require("node:util"); -You can find more information about the changes in Node.js v24 in the [official migration guide](https://nodejs.org/en/blog/migrations/v22-to-v24). +-util.log("Hello world"); ++console.log(new Date().toLocaleString(), "Hello world"); +``` -To know missing part read this [issue](https://github.com/nodejs/userland-migrations/issues/239) + diff --git a/recipes/v22-to-v24/codemod.yaml b/recipes/v22-to-v24/codemod.yaml index 276bc4d0..c6399561 100644 --- a/recipes/v22-to-v24/codemod.yaml +++ b/recipes/v22-to-v24/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/v22-to-v24" -version: "0.0.1" +version: "0.0.2" description: Handle breaking changes in Node.js v24 by replacing deprecated APIs and updating code to be compatible with the new version. author: Augustin Mauroy license: MIT diff --git a/recipes/v22-to-v24/package.json b/recipes/v22-to-v24/package.json index 1e719f1f..9bd75f8a 100644 --- a/recipes/v22-to-v24/package.json +++ b/recipes/v22-to-v24/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/v22-to-v24", - "version": "1.0.1", + "version": "1.0.2", "description": "Handle breaking changes in Node.js v24 by replacing deprecated APIs and updating code to be compatible with the new version.", "type": "module", "scripts": { diff --git a/recipes/zlib-bytesread-to-byteswritten/README.md b/recipes/zlib-bytesread-to-byteswritten/README.md index 6cc4bb65..b6dadb97 100644 --- a/recipes/zlib-bytesread-to-byteswritten/README.md +++ b/recipes/zlib-bytesread-to-byteswritten/README.md @@ -1,139 +1,57 @@ -# `zlib.bytesRead` → `zlib.bytesWritten` DEP0108 - -This codemod replaces zlib.bytesRead with zlib.bytesWritten for consistent stream property naming. It's useful to migrate code that uses the deprecated property which has been removed. - -It replaces zlib.bytesRead with zlib.bytesWritten in all zlib transform streams and it handles both CommonJS and ESM imports. - -See [DEP0108](https://nodejs.org/api/deprecations.html#DEP0108). - +--- +authors: Eliekhoury17 --- -## Example - -**Case 1** - -Before: - -```js -const zlib = require("node:zlib"); -const gzip = zlib.createGzip(); -gzip.on("end", () => { - console.log("Bytes processed:", gzip.bytesRead); -}); -``` - -After: - -```js -const zlib = require("node:zlib"); -const gzip = zlib.createGzip(); -gzip.on("end", () => { - console.log("Bytes processed:", gzip.bytesWritten); -}); -``` - -**Case 2** - -Before: - -```js -const zlib = require("node:zlib"); -const deflate = zlib.createDeflate(); -deflate.on("finish", () => { - const stats = { - input: deflate.bytesRead, - output: deflate.bytesWritten - }; -}); -``` +# DEP0108: `zlib.bytesRead` to `zlib.bytesWritten` -After: - -```js -const zlib = require("node:zlib"); -const deflate = zlib.createDeflate(); -deflate.on("finish", () => { - const stats = { - input: deflate.bytesWritten, - output: deflate.bytesWritten - }; -}); -``` +Replaces the deprecated `.bytesRead` property with `.bytesWritten` on zlib stream objects. The codemod tracks variables assigned from any of the zlib factory functions (`createGzip`, `createGunzip`, `createDeflate`, `createInflate`, `createBrotliCompress`, `createBrotliDecompress`, `createUnzip`) and also handles function parameters used as stream arguments. Both CommonJS `require` and ESM `import` are supported. -**Case 3** +## Usage -Before: +Run this codemod with: -```js -const zlib = require("node:zlib"); -function trackProgress(stream) { - setInterval(() => { - console.log(`Progress: ${stream.bytesRead} bytes`); - }, 1000); -} +```sh +npx codemod @nodejs/zlib-bytesread-to-byteswritten ``` -After: +## Examples -```js -const zlib = require("node:zlib"); -function trackProgress(stream) { - setInterval(() => { - console.log(`Progress: ${stream.bytesWritten} bytes`); - }, 1000); -} -``` - -**Case 4** +### Example 1 -Before: +Variable assigned from a zlib factory via a namespace require: -```js -import { createGzip } from "node:zlib"; -const gzip = createGzip(); -const bytesProcessed = gzip.bytesRead; +```diff + const zlib = require("node:zlib"); + const gzip = zlib.createGzip(); + gzip.on("end", () => { +- console.log("Bytes processed:", gzip.bytesRead); ++ console.log("Bytes processed:", gzip.bytesWritten); + }); ``` -After: +### Example 2 -```js -import { createGzip } from "node:zlib"; -const gzip = createGzip(); -const bytesProcessed = gzip.bytesWritten; -``` +Named ESM import: -**Case 5** - -Before: - -```js -const zlib = require("node:zlib"); -const gzip = zlib.createGzip(); -const processed = gzip.bytesRead; -``` - -After: - -```js -const zlib = require("node:zlib"); -const gzip = zlib.createGzip(); -const processed = gzip.bytesWritten; +```diff + import { createGzip } from "node:zlib"; + const gzip = createGzip(); +-const bytesProcessed = gzip.bytesRead; ++const bytesProcessed = gzip.bytesWritten; ``` -**Case 6** +### Example 3 -Before: +Function parameter used as a stream — the codemod replaces `.bytesRead` on any parameter inside a function that receives a zlib stream: -```js -const { createGzip } = require("node:zlib"); -const gzip = createGzip(); -const bytes = gzip.bytesRead; +```diff + const zlib = require("node:zlib"); + function trackProgress(stream) { + setInterval(() => { +- console.log(`Progress: ${stream.bytesRead} bytes`); ++ console.log(`Progress: ${stream.bytesWritten} bytes`); + }, 1000); + } ``` -After: - -```js -const { createGzip } = require("node:zlib"); -const gzip = createGzip(); -const bytes = gzip.bytesWritten; -``` \ No newline at end of file + diff --git a/recipes/zlib-bytesread-to-byteswritten/codemod.yaml b/recipes/zlib-bytesread-to-byteswritten/codemod.yaml index 1293498e..87f8b033 100644 --- a/recipes/zlib-bytesread-to-byteswritten/codemod.yaml +++ b/recipes/zlib-bytesread-to-byteswritten/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/zlib-bytesread-to-byteswritten" -version: 1.0.1 +version: 1.0.2 description: Handle DEP0108 by replacing deprecated `zlib.bytesRead` with `zlib.bytesWritten` in Node.js transform streams author: Elie Khoury license: MIT diff --git a/recipes/zlib-bytesread-to-byteswritten/package.json b/recipes/zlib-bytesread-to-byteswritten/package.json index 7ea39d77..18c0f6fc 100644 --- a/recipes/zlib-bytesread-to-byteswritten/package.json +++ b/recipes/zlib-bytesread-to-byteswritten/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/zlib-bytesread-to-byteswritten", - "version": "1.0.1", + "version": "1.0.2", "description": "Replace deprecated `zlib.bytesRead` with `zlib.bytesWritten` in Node.js transform streams", "type": "module", "scripts": { diff --git a/scripts/sync-learn.mjs b/scripts/sync-learn.mjs new file mode 100644 index 00000000..1705317b --- /dev/null +++ b/scripts/sync-learn.mjs @@ -0,0 +1,135 @@ +/** + * Syncs recipe READMEs from this repo into nodejs/learn. + * + * Expected workspace layout (set up by refresh-learn.yml): + * $GITHUB_WORKSPACE/learn/ ← nodejs/learn checkout (cwd when running) + * pages/userland-migrations/ ← written by this script + * site.json ← updated by this script + * $GITHUB_WORKSPACE/source/ ← this repo (userland-migrations) + * scripts/sync-learn.mjs ← this file + * recipes/{name}/README.md ← read by this script + * + * Only recipes whose README ends with `` are + * published; recipes without the marker are treated as opt-out. + * + * Run from the nodejs/learn checkout root: + * node ../source/scripts/sync-learn.mjs + */ + +import { readdir, readFile, writeFile, mkdir } from "node:fs/promises"; +import { existsSync } from "node:fs"; +import { join, resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const workspaceRoot = process.cwd(); + +const RECIPES_DIR = resolve(__dirname, "../recipes"); +const OUTPUT_DIR = resolve(workspaceRoot, "pages", "userland-migrations"); +const SITE_JSON = resolve(workspaceRoot, "site.json"); +const SIDEBAR_GROUP_NAME = "Userland Migrations"; + +/** + * Extracts the first H1 heading from a Markdown file, + * skipping the YAML frontmatter block if present. + * Inline code markers are stripped, since sidebar labels + * in site.json are rendered as plain text. + */ +function extractTitle(content, fallback) { + const lines = content.split("\n"); + let inFrontmatter = false; + let frontmatterDone = false; + + for (const line of lines) { + if (!frontmatterDone) { + if (line.trim() === "---") { + if (!inFrontmatter) { + inFrontmatter = true; + continue; + } + frontmatterDone = true; + continue; + } + if (inFrontmatter) continue; + } + + const match = line.match(/^#\s+(.+)$/); + if (match) return match[1].trim().replaceAll("`", ""); + } + + return fallback; +} + +/** + * Reads the `` marker that every README + * carries. A missing or malformed marker means "do not publish", so a new + * recipe has to opt in explicitly. + */ +function shouldSync(content) { + const match = content.match(//); + return match?.[1] === "true"; +} + +// 1. Collect recipes +const entries = await readdir(RECIPES_DIR, { withFileTypes: true }); +const recipes = entries + .filter((e) => e.isDirectory()) + .map((e) => e.name) + .sort(); + +// 2. Create output directory +await mkdir(OUTPUT_DIR, { recursive: true }); + +// 3. Copy READMEs and collect sidebar items +const sidebarItems = []; + +for (const name of recipes) { + const readmePath = join(RECIPES_DIR, name, "README.md"); + if (!existsSync(readmePath)) { + console.warn(`Skipping ${name}: no README.md found`); + continue; + } + + const content = await readFile(readmePath, "utf8"); + + if (!shouldSync(content)) { + console.log(` – ${name} (sync_to_learn is not true)`); + continue; + } + + const title = extractTitle(content, name); + + await writeFile(join(OUTPUT_DIR, `${name}.md`), content, "utf8"); + + sidebarItems.push({ + link: `/learn/userland-migrations/${name}`, + label: title, + }); + + console.log(` ✓ ${name} → "${title}"`); +} + +console.log(`\nCopied ${sidebarItems.length} pages to pages/userland-migrations/`); + +// 4. Update site.json sidebar +const siteJson = JSON.parse(await readFile(SITE_JSON, "utf8")); + +const existingGroupIndex = siteJson.sidebar.findIndex( + (group) => group.groupName === SIDEBAR_GROUP_NAME, +); + +const newGroup = { + groupName: SIDEBAR_GROUP_NAME, + items: sidebarItems, +}; + +if (existingGroupIndex !== -1) { + siteJson.sidebar[existingGroupIndex] = newGroup; + console.log(`Updated existing "${SIDEBAR_GROUP_NAME}" group in site.json`); +} else { + siteJson.sidebar.push(newGroup); + console.log(`Added new "${SIDEBAR_GROUP_NAME}" group to site.json`); +} + +await writeFile(SITE_JSON, `${JSON.stringify(siteJson, null, 2)}\n`, "utf8"); +console.log("site.json updated."); diff --git a/utils/README.md b/utils/README.md index e39dc2af..27d8605e 100644 --- a/utils/README.md +++ b/utils/README.md @@ -282,3 +282,5 @@ import { removeNodeJsArgs } from '@nodejs/codemod-utils/ast-grep/package-json'; const edits = removeNodeJsArgs(packageJsonAst, ['--inspect']); ``` + + From 74a58677f49ad4bc05e0a99efadf6a4faadcfedc Mon Sep 17 00:00:00 2001 From: avivkeller Date: Sun, 9 Aug 2026 16:53:34 -0400 Subject: [PATCH 2/2] feat(README): learn syncing Signed-off-by: Aviv Keller --- recipes/axios-to-whatwg-fetch/codemod.yaml | 2 +- recipes/axios-to-whatwg-fetch/package.json | 2 +- recipes/buffer-atob-btoa/codemod.yaml | 2 +- recipes/buffer-atob-btoa/package.json | 2 +- recipes/chalk-to-util-styletext/codemod.yaml | 2 +- recipes/chalk-to-util-styletext/package.json | 2 +- recipes/correct-ts-specifiers/.codemodrc.json | 2 +- recipes/correct-ts-specifiers/package.json | 2 +- recipes/create-require-from-path/codemod.yaml | 2 +- recipes/create-require-from-path/package.json | 2 +- recipes/createCredentials-to-createSecureContext/codemod.yaml | 2 +- recipes/createCredentials-to-createSecureContext/package.json | 2 +- recipes/crypto-createcipheriv-migration/codemod.yaml | 2 +- recipes/crypto-createcipheriv-migration/package.json | 2 +- recipes/crypto-fips-to-getFips/codemod.yaml | 2 +- recipes/crypto-fips-to-getFips/package.json | 2 +- recipes/crypto-rsa-pss-update/codemod.yaml | 2 +- recipes/crypto-rsa-pss-update/package.json | 2 +- recipes/dirent-path-to-parent-path/codemod.yaml | 2 +- recipes/dirent-path-to-parent-path/package.json | 2 +- recipes/dns-lookup-options-coercion/codemod.yaml | 2 +- recipes/dns-lookup-options-coercion/package.json | 2 +- recipes/err-invalid-callback/codemod.yaml | 2 +- recipes/err-invalid-callback/package.json | 2 +- recipes/fs-access-mode-constants/codemod.yaml | 2 +- recipes/fs-access-mode-constants/package.json | 2 +- recipes/fs-truncate-fd-deprecation/codemod.yaml | 2 +- recipes/fs-truncate-fd-deprecation/package.json | 2 +- recipes/http-classes-with-new/codemod.yaml | 2 +- recipes/http-classes-with-new/package.json | 2 +- recipes/http-outgoingmessage-headers/codemod.yaml | 2 +- recipes/http-outgoingmessage-headers/package.json | 2 +- recipes/http2-priority-signaling/codemod.yaml | 2 +- recipes/http2-priority-signaling/package.json | 2 +- recipes/import-assertions-to-attributes/codemod.yaml | 2 +- recipes/import-assertions-to-attributes/package.json | 2 +- recipes/mocha-to-node-test-runner/codemod.yaml | 2 +- recipes/mocha-to-node-test-runner/package.json | 2 +- recipes/mock-module-exports/codemod.yaml | 2 +- recipes/mock-module-exports/package.json | 2 +- recipes/node-url-to-whatwg-url/codemod.yaml | 2 +- recipes/node-url-to-whatwg-url/package.json | 2 +- recipes/process-assert-to-node-assert/codemod.yaml | 2 +- recipes/process-assert-to-node-assert/package.json | 2 +- recipes/process-main-module/codemod.yaml | 2 +- recipes/process-main-module/package.json | 2 +- recipes/repl-builtin-modules/codemod.yaml | 2 +- recipes/repl-builtin-modules/package.json | 2 +- recipes/repl-classes-with-new/codemod.yaml | 2 +- recipes/repl-classes-with-new/package.json | 2 +- recipes/rmdir/codemod.yaml | 2 +- recipes/rmdir/package.json | 2 +- recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml | 2 +- recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json | 2 +- recipes/timers-deprecations/codemod.yaml | 2 +- recipes/timers-deprecations/package.json | 2 +- recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml | 2 +- recipes/tls-create-secure-pair-to-tls-socket/package.json | 2 +- recipes/tmpdir-to-tmpdir/codemod.yaml | 2 +- recipes/tmpdir-to-tmpdir/package.json | 2 +- recipes/types-is-native-error/codemod.yaml | 2 +- recipes/types-is-native-error/package.json | 2 +- recipes/util-extend-to-object-assign/codemod.yaml | 2 +- recipes/util-extend-to-object-assign/package.json | 2 +- recipes/util-is/codemod.yaml | 2 +- recipes/util-is/package.json | 2 +- recipes/util-log-to-console-log/codemod.yaml | 2 +- recipes/util-log-to-console-log/package.json | 2 +- recipes/util-print-to-console-log/codemod.yaml | 2 +- recipes/util-print-to-console-log/package.json | 2 +- recipes/v22-to-v24/codemod.yaml | 2 +- recipes/v22-to-v24/package.json | 2 +- recipes/zlib-bytesread-to-byteswritten/codemod.yaml | 2 +- recipes/zlib-bytesread-to-byteswritten/package.json | 2 +- 74 files changed, 74 insertions(+), 74 deletions(-) diff --git a/recipes/axios-to-whatwg-fetch/codemod.yaml b/recipes/axios-to-whatwg-fetch/codemod.yaml index 88e393fe..72704d0f 100644 --- a/recipes/axios-to-whatwg-fetch/codemod.yaml +++ b/recipes/axios-to-whatwg-fetch/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/axios-to-whatwg-fetch" -version: 1.0.1 +version: 1.0.0 description: Replace `axios` with `fetch` author: Bruno Rodrigues license: MIT diff --git a/recipes/axios-to-whatwg-fetch/package.json b/recipes/axios-to-whatwg-fetch/package.json index 47585e7a..afdc92d4 100644 --- a/recipes/axios-to-whatwg-fetch/package.json +++ b/recipes/axios-to-whatwg-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/axios-to-whatwg-fetch", - "version": "1.0.1", + "version": "1.0.0", "description": "Replace `axios` with `fetch`", "type": "module", "scripts": { diff --git a/recipes/buffer-atob-btoa/codemod.yaml b/recipes/buffer-atob-btoa/codemod.yaml index eaacbe1b..2e5f1b4b 100644 --- a/recipes/buffer-atob-btoa/codemod.yaml +++ b/recipes/buffer-atob-btoa/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/buffer-atob-btoa" -version: "1.0.3" +version: "1.0.2" description: Migrates usage of the legacy APIs `buffer.atob()` and `buffer.btoa()` to the current recommended approaches author: nekojanai (Jana) license: MIT diff --git a/recipes/buffer-atob-btoa/package.json b/recipes/buffer-atob-btoa/package.json index 2cd14828..d9183778 100644 --- a/recipes/buffer-atob-btoa/package.json +++ b/recipes/buffer-atob-btoa/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/buffer-atob-btoa", - "version": "1.0.3", + "version": "1.0.1", "description": "Migrates usage of the legacy APIs `buffer.atob()` and `buffer.btoa()` to the current recommended approaches", "type": "module", "scripts": { diff --git a/recipes/chalk-to-util-styletext/codemod.yaml b/recipes/chalk-to-util-styletext/codemod.yaml index 37c2b662..a59f9334 100644 --- a/recipes/chalk-to-util-styletext/codemod.yaml +++ b/recipes/chalk-to-util-styletext/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/chalk-to-util-styletext" -version: 1.0.3 +version: 1.0.2 capabilities: - fs - child_process diff --git a/recipes/chalk-to-util-styletext/package.json b/recipes/chalk-to-util-styletext/package.json index f5c95e48..40f157b4 100644 --- a/recipes/chalk-to-util-styletext/package.json +++ b/recipes/chalk-to-util-styletext/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/chalk-to-util-styletext", - "version": "1.0.3", + "version": "1.0.2", "description": "Migrate from the chalk package to Node.js's built-in util.styleText API", "type": "module", "scripts": { diff --git a/recipes/correct-ts-specifiers/.codemodrc.json b/recipes/correct-ts-specifiers/.codemodrc.json index d656addb..227dd458 100644 --- a/recipes/correct-ts-specifiers/.codemodrc.json +++ b/recipes/correct-ts-specifiers/.codemodrc.json @@ -2,7 +2,7 @@ "$schema": "https://codemod-utils.s3.us-west-1.amazonaws.com/configuration_schema.json", "name": "@nodejs/correct-ts-specifiers", "description": "Replace erroneous 'js' or omitted file extensions of import specifiers in TypeScript files.", - "version": "1.0.1", + "version": "1.0.0", "engine": "workflow", "private": false, "entry": "./src/workflow.ts", diff --git a/recipes/correct-ts-specifiers/package.json b/recipes/correct-ts-specifiers/package.json index 69bcd682..e1c81b0e 100644 --- a/recipes/correct-ts-specifiers/package.json +++ b/recipes/correct-ts-specifiers/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/correct-ts-specifiers", - "version": "1.0.1", + "version": "1.0.0", "description": "Replace erroneous 'js' or omitted file extensions of import specifiers in TypeScript files.", "type": "module", "main": "./src/workflow.ts", diff --git a/recipes/create-require-from-path/codemod.yaml b/recipes/create-require-from-path/codemod.yaml index e0d49cba..5443a7ce 100644 --- a/recipes/create-require-from-path/codemod.yaml +++ b/recipes/create-require-from-path/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/create-require-from-path" -version: "1.1.3" +version: "1.1.2" description: Handle DEP0130 via transforming `createRequireFromPath` to `createRequire`. author: Augustin Mauroy license: MIT diff --git a/recipes/create-require-from-path/package.json b/recipes/create-require-from-path/package.json index a7a95a8e..3e8aed99 100644 --- a/recipes/create-require-from-path/package.json +++ b/recipes/create-require-from-path/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/create-require-from-path", - "version": "1.1.3", + "version": "1.1.2", "description": "Handle DEP0130 via transforming `createRequireFromPath` to `createRequire`.", "type": "module", "scripts": { diff --git a/recipes/createCredentials-to-createSecureContext/codemod.yaml b/recipes/createCredentials-to-createSecureContext/codemod.yaml index a97eff5c..9363d49d 100644 --- a/recipes/createCredentials-to-createSecureContext/codemod.yaml +++ b/recipes/createCredentials-to-createSecureContext/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/createCredentials-to-createSecureContext" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0010 via transforming `crypto.createCredentials` to `tls.createSecureContext` author: 0hmx license: MIT diff --git a/recipes/createCredentials-to-createSecureContext/package.json b/recipes/createCredentials-to-createSecureContext/package.json index 1ec6e41f..0dec9319 100644 --- a/recipes/createCredentials-to-createSecureContext/package.json +++ b/recipes/createCredentials-to-createSecureContext/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/createcredentials-to-createsecurecontext", - "version": "1.0.3", + "version": "1.0.1", "description": "Handle DEP0010 via transforming `crypto.createCredentials` to `tls.createSecureContext` with the appropriate options.", "type": "module", "scripts": { diff --git a/recipes/crypto-createcipheriv-migration/codemod.yaml b/recipes/crypto-createcipheriv-migration/codemod.yaml index e3bde435..e68361e4 100644 --- a/recipes/crypto-createcipheriv-migration/codemod.yaml +++ b/recipes/crypto-createcipheriv-migration/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-createcipheriv-migration" -version: 1.0.1 +version: 1.0.0 description: Replace removed `crypto.createCipher()`/`createDecipher()` with `crypto.createCipheriv()`/`createDecipheriv()` and secure key derivation (DEP0106) author: Augustin Mauroy license: MIT diff --git a/recipes/crypto-createcipheriv-migration/package.json b/recipes/crypto-createcipheriv-migration/package.json index 95fd3128..13dba10c 100644 --- a/recipes/crypto-createcipheriv-migration/package.json +++ b/recipes/crypto-createcipheriv-migration/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-createcipheriv-migration", - "version": "1.0.1", + "version": "1.0.0", "description": "Migrate deprecated crypto.createCipher()/createDecipher() (DEP0106) to crypto.createCipheriv()/createDecipheriv() with secure key derivation.", "type": "module", "scripts": { diff --git a/recipes/crypto-fips-to-getFips/codemod.yaml b/recipes/crypto-fips-to-getFips/codemod.yaml index 64628fdf..8aa21026 100644 --- a/recipes/crypto-fips-to-getFips/codemod.yaml +++ b/recipes/crypto-fips-to-getFips/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-fips-to-getFips" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()` author: Usman S. license: MIT diff --git a/recipes/crypto-fips-to-getFips/package.json b/recipes/crypto-fips-to-getFips/package.json index 6610a793..3a337202 100644 --- a/recipes/crypto-fips-to-getFips/package.json +++ b/recipes/crypto-fips-to-getFips/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-fips-to-getFips", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0093 via transforming `crypto.fips` to `crypto.getFips()` and `crypto.setFips()`", "type": "module", "scripts": { diff --git a/recipes/crypto-rsa-pss-update/codemod.yaml b/recipes/crypto-rsa-pss-update/codemod.yaml index 5b9acf88..2ed16465 100644 --- a/recipes/crypto-rsa-pss-update/codemod.yaml +++ b/recipes/crypto-rsa-pss-update/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/crypto-rsa-pss-update" -version: 1.0.3 +version: 1.0.2 description: >- Handle DEP0154 via transforming deprecated RSA-PSS crypto options `hash` to `hashAlgorithm` and `mgf1Hash` to `mgf1HashAlgorithm` diff --git a/recipes/crypto-rsa-pss-update/package.json b/recipes/crypto-rsa-pss-update/package.json index a03f1016..650941ab 100644 --- a/recipes/crypto-rsa-pss-update/package.json +++ b/recipes/crypto-rsa-pss-update/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/crypto-rsa-pss-update", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0154 via transforming deprecated RSA-PSS crypto options `hash` to `hashAlgorithm` and `mgf1Hash` to `mgf1HashAlgorithm`.", "type": "module", "scripts": { diff --git a/recipes/dirent-path-to-parent-path/codemod.yaml b/recipes/dirent-path-to-parent-path/codemod.yaml index c305873a..ba8440b3 100644 --- a/recipes/dirent-path-to-parent-path/codemod.yaml +++ b/recipes/dirent-path-to-parent-path/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/dirent-path-to-parent-path" -version: 1.0.2 +version: 1.0.1 description: Handle DEP0178 via transforming `dirent.path` to `dirent.parentPath`. author: Bruno Rodrigues license: MIT diff --git a/recipes/dirent-path-to-parent-path/package.json b/recipes/dirent-path-to-parent-path/package.json index 7411eea3..9a166cb4 100644 --- a/recipes/dirent-path-to-parent-path/package.json +++ b/recipes/dirent-path-to-parent-path/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/dirent-path-to-parent-path", - "version": "1.0.2", + "version": "1.0.1", "description": "Handle DEP0178 via transforming `dirent.path` to `dirent.parentPath`", "type": "module", "scripts": { diff --git a/recipes/dns-lookup-options-coercion/codemod.yaml b/recipes/dns-lookup-options-coercion/codemod.yaml index 7cf36afb..a6f1ec3f 100644 --- a/recipes/dns-lookup-options-coercion/codemod.yaml +++ b/recipes/dns-lookup-options-coercion/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/dns-lookup-options-coercion" -version: "1.0.1" +version: "1.0.0" description: Handle DEP0153 by converting literal dns.lookup option values to their proper types. author: Herrtian license: MIT diff --git a/recipes/dns-lookup-options-coercion/package.json b/recipes/dns-lookup-options-coercion/package.json index 4e97c56c..556624e2 100644 --- a/recipes/dns-lookup-options-coercion/package.json +++ b/recipes/dns-lookup-options-coercion/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/dns-lookup-options-coercion", - "version": "1.0.1", + "version": "1.0.0", "description": "Handle DEP0153 by converting literal dns.lookup option values to their proper types", "type": "module", "scripts": { diff --git a/recipes/err-invalid-callback/codemod.yaml b/recipes/err-invalid-callback/codemod.yaml index d8b6b28a..a17aaba1 100644 --- a/recipes/err-invalid-callback/codemod.yaml +++ b/recipes/err-invalid-callback/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/err-invalid-callback" -version: "1.0.1" +version: "1.0.0" description: Handle DEP0159 by replacing ERR_INVALID_CALLBACK with ERR_INVALID_ARG_TYPE. author: Stanley Shen license: MIT diff --git a/recipes/err-invalid-callback/package.json b/recipes/err-invalid-callback/package.json index bab03a86..4d8784e5 100644 --- a/recipes/err-invalid-callback/package.json +++ b/recipes/err-invalid-callback/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/err-invalid-callback", - "version": "1.0.1", + "version": "1.0.0", "description": "Handle DEP0159 by replacing ERR_INVALID_CALLBACK with ERR_INVALID_ARG_TYPE.", "type": "module", "scripts": { diff --git a/recipes/fs-access-mode-constants/codemod.yaml b/recipes/fs-access-mode-constants/codemod.yaml index a3103d09..a70b916c 100644 --- a/recipes/fs-access-mode-constants/codemod.yaml +++ b/recipes/fs-access-mode-constants/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/fs-access-mode-constants" -version: "1.0.4" +version: "1.0.3" description: Handle DEP0176 via transforming imports of `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` from the root `fs` module to `fs.constants`. author: nekojanai (Jana) license: MIT diff --git a/recipes/fs-access-mode-constants/package.json b/recipes/fs-access-mode-constants/package.json index 041de798..c61e8238 100644 --- a/recipes/fs-access-mode-constants/package.json +++ b/recipes/fs-access-mode-constants/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/fs-access-mode-constants", - "version": "1.0.4", + "version": "1.0.3", "description": "Handle DEP0176 via transforming imports of `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, `fs.X_OK` from the root `fs` module to `fs.constants`.", "type": "module", "scripts": { diff --git a/recipes/fs-truncate-fd-deprecation/codemod.yaml b/recipes/fs-truncate-fd-deprecation/codemod.yaml index 08867af0..a734ac7d 100644 --- a/recipes/fs-truncate-fd-deprecation/codemod.yaml +++ b/recipes/fs-truncate-fd-deprecation/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/fs-truncate-fd-deprecation" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0081 via transforming `truncate` to `ftruncateSync` when using a file descriptor. author: Augustin Mauroy license: MIT diff --git a/recipes/fs-truncate-fd-deprecation/package.json b/recipes/fs-truncate-fd-deprecation/package.json index e4e53b8d..7e1b4bc6 100644 --- a/recipes/fs-truncate-fd-deprecation/package.json +++ b/recipes/fs-truncate-fd-deprecation/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/fs-truncate-fd-deprecation", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0081 via transforming `truncate` to `ftruncateSync` when using a file descriptor.", "type": "module", "scripts": { diff --git a/recipes/http-classes-with-new/codemod.yaml b/recipes/http-classes-with-new/codemod.yaml index ac224e33..9655a45b 100644 --- a/recipes/http-classes-with-new/codemod.yaml +++ b/recipes/http-classes-with-new/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http-classes-with-new" -version: "1.0.3" +version: "1.0.2" description: "Handle DEDEP0195: Instantiating node:http classes without new" author: Usman S. license: MIT diff --git a/recipes/http-classes-with-new/package.json b/recipes/http-classes-with-new/package.json index 4de546cd..26ab2a53 100644 --- a/recipes/http-classes-with-new/package.json +++ b/recipes/http-classes-with-new/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http-classes-with-new", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0195: Instantiating node:http classes without new.", "type": "module", "scripts": { diff --git a/recipes/http-outgoingmessage-headers/codemod.yaml b/recipes/http-outgoingmessage-headers/codemod.yaml index 03f98713..02aac3d6 100644 --- a/recipes/http-outgoingmessage-headers/codemod.yaml +++ b/recipes/http-outgoingmessage-headers/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http-outgoingmessage-headers" -version: 1.0.2 +version: 1.0.1 description: > Handle DEP0066: migrate deprecated use of `OutgoingMessage.prototype` `_headers` & `_headerNames` to public HTTP header APIs diff --git a/recipes/http-outgoingmessage-headers/package.json b/recipes/http-outgoingmessage-headers/package.json index 7ffc38af..1d25026a 100644 --- a/recipes/http-outgoingmessage-headers/package.json +++ b/recipes/http-outgoingmessage-headers/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http-outgoingmessage-headers", - "version": "1.0.2", + "version": "1.0.0", "description": "Handle DEP0066: migrate deprecated use of `OutgoingMessage.prototype` `_headers` & `_headerNames` to public HTTP header APIs", "type": "module", "scripts": { diff --git a/recipes/http2-priority-signaling/codemod.yaml b/recipes/http2-priority-signaling/codemod.yaml index e26945c7..385a0e57 100644 --- a/recipes/http2-priority-signaling/codemod.yaml +++ b/recipes/http2-priority-signaling/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/http2-priority-signaling" -version: 1.0.1 +version: 1.0.0 description: Handle DEP0194 via removing HTTP/2 priority-related options and methods. author: Augustin Mauroy license: MIT diff --git a/recipes/http2-priority-signaling/package.json b/recipes/http2-priority-signaling/package.json index 4a14e1c3..d1efc258 100644 --- a/recipes/http2-priority-signaling/package.json +++ b/recipes/http2-priority-signaling/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/http2-priority-signaling", - "version": "1.0.1", + "version": "1.0.0", "description": "Handle DEP0194 via removing HTTP/2 priority-related options and methods", "type": "module", "scripts": { diff --git a/recipes/import-assertions-to-attributes/codemod.yaml b/recipes/import-assertions-to-attributes/codemod.yaml index d190466e..4bfb792a 100644 --- a/recipes/import-assertions-to-attributes/codemod.yaml +++ b/recipes/import-assertions-to-attributes/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/import-assertions-to-attributes" -version: 1.0.1 +version: 1.0.0 description: Replace `assert` import attribute to the `with` ECMAScript import attribute. author: Augustin Mauroy license: MIT diff --git a/recipes/import-assertions-to-attributes/package.json b/recipes/import-assertions-to-attributes/package.json index ae8c72b9..cd38557a 100644 --- a/recipes/import-assertions-to-attributes/package.json +++ b/recipes/import-assertions-to-attributes/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/import-assertions-to-attributes", - "version": "1.0.1", + "version": "1.0.0", "description": "Replace `assert` import attribute to the `with` ECMAScript import attribute.", "type": "module", "scripts": { diff --git a/recipes/mocha-to-node-test-runner/codemod.yaml b/recipes/mocha-to-node-test-runner/codemod.yaml index 21cc4c5d..0a3cadb6 100644 --- a/recipes/mocha-to-node-test-runner/codemod.yaml +++ b/recipes/mocha-to-node-test-runner/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/mocha-to-node-test-runner" -version: 1.0.1 +version: 1.0.0 capabilities: - fs - child_process diff --git a/recipes/mocha-to-node-test-runner/package.json b/recipes/mocha-to-node-test-runner/package.json index 7fd011a5..6708d51d 100644 --- a/recipes/mocha-to-node-test-runner/package.json +++ b/recipes/mocha-to-node-test-runner/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/mocha-to-node-test-runner", - "version": "1.0.1", + "version": "1.0.0", "description": "Migrate Mocha 8.x tests to Node.js (22.x, 24.x) test runner", "type": "module", "scripts": { diff --git a/recipes/mock-module-exports/codemod.yaml b/recipes/mock-module-exports/codemod.yaml index cf2be84a..56c69ca0 100644 --- a/recipes/mock-module-exports/codemod.yaml +++ b/recipes/mock-module-exports/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/mock-module-exports" -version: 1.0.2 +version: 1.0.1 description: "Handle mock.module exports deprecation" author: Bruno Rodrigues license: MIT diff --git a/recipes/mock-module-exports/package.json b/recipes/mock-module-exports/package.json index 7520375c..b9dabdac 100644 --- a/recipes/mock-module-exports/package.json +++ b/recipes/mock-module-exports/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/mock-module-exports", - "version": "1.0.2", + "version": "1.0.0", "description": "Handle mock.module exports deprecation", "type": "module", "scripts": { diff --git a/recipes/node-url-to-whatwg-url/codemod.yaml b/recipes/node-url-to-whatwg-url/codemod.yaml index 7f58eda6..cd698c81 100644 --- a/recipes/node-url-to-whatwg-url/codemod.yaml +++ b/recipes/node-url-to-whatwg-url/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/node-url-to-whatwg-url" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0116 via transforming `url.parse` to `new URL()` author: Augustin Mauroy license: MIT diff --git a/recipes/node-url-to-whatwg-url/package.json b/recipes/node-url-to-whatwg-url/package.json index f8481b25..0f37e827 100644 --- a/recipes/node-url-to-whatwg-url/package.json +++ b/recipes/node-url-to-whatwg-url/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/node-url-to-whatwg-url", - "version": "1.0.3", + "version": "1.0.1", "description": "Handle DEP0116 via transforming `url.parse` to `new URL()`", "type": "module", "scripts": { diff --git a/recipes/process-assert-to-node-assert/codemod.yaml b/recipes/process-assert-to-node-assert/codemod.yaml index 2635a100..505f8cc1 100644 --- a/recipes/process-assert-to-node-assert/codemod.yaml +++ b/recipes/process-assert-to-node-assert/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/process-assert-to-node-assert" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0100 via transforming `process.assert` to `node:assert`. author: matheusmorett2 license: MIT diff --git a/recipes/process-assert-to-node-assert/package.json b/recipes/process-assert-to-node-assert/package.json index f4f6fd5d..7def4101 100644 --- a/recipes/process-assert-to-node-assert/package.json +++ b/recipes/process-assert-to-node-assert/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/process-assert-to-node-assert", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0100 via transforming `process.assert` to `node:assert`.", "type": "module", "scripts": { diff --git a/recipes/process-main-module/codemod.yaml b/recipes/process-main-module/codemod.yaml index c172e6e2..a837a898 100644 --- a/recipes/process-main-module/codemod.yaml +++ b/recipes/process-main-module/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/process-main-module" -version: "1.0.4" +version: "1.0.3" description: Handle DEP0138 via transforming `process.mainModule` to `require.main`. author: Bruno Rodrigues license: MIT diff --git a/recipes/process-main-module/package.json b/recipes/process-main-module/package.json index 2ae50bed..07febdb2 100644 --- a/recipes/process-main-module/package.json +++ b/recipes/process-main-module/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/process-main-module", - "version": "1.0.4", + "version": "1.0.2", "description": "Handle DEP0138 via transforming `process.mainModule` to `require.main`.", "type": "module", "scripts": { diff --git a/recipes/repl-builtin-modules/codemod.yaml b/recipes/repl-builtin-modules/codemod.yaml index 4845d6a4..3a2e8659 100644 --- a/recipes/repl-builtin-modules/codemod.yaml +++ b/recipes/repl-builtin-modules/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/repl-builtin-modules" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0191 via transforming `repl.builtinModules` usage to `module.builtinModules`. author: Augustin Mauroy license: MIT diff --git a/recipes/repl-builtin-modules/package.json b/recipes/repl-builtin-modules/package.json index 4fd1984e..fcdf4dbf 100644 --- a/recipes/repl-builtin-modules/package.json +++ b/recipes/repl-builtin-modules/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/repl-builtin-modules", - "version": "1.0.3", + "version": "1.0.1", "description": "Handle DEP0191 via transforming `repl.builtinModules` usage to `module.builtinModules`.", "type": "module", "scripts": { diff --git a/recipes/repl-classes-with-new/codemod.yaml b/recipes/repl-classes-with-new/codemod.yaml index 5915098c..a8e0aaf9 100644 --- a/recipes/repl-classes-with-new/codemod.yaml +++ b/recipes/repl-classes-with-new/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/repl-classes-with-new" -version: "1.0.3" +version: "1.0.2" description: "Handle DEP0185: Instantiating node:repl classes without new" author: GitHub Copilot license: MIT diff --git a/recipes/repl-classes-with-new/package.json b/recipes/repl-classes-with-new/package.json index 83b7a1a6..1706fd43 100644 --- a/recipes/repl-classes-with-new/package.json +++ b/recipes/repl-classes-with-new/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/repl-classes-with-new", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0185: Instantiating node:repl classes without new.", "type": "module", "scripts": { diff --git a/recipes/rmdir/codemod.yaml b/recipes/rmdir/codemod.yaml index 153d103a..2223fa29 100644 --- a/recipes/rmdir/codemod.yaml +++ b/recipes/rmdir/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/rmdir" -version: "1.1.3" +version: "1.1.2" description: Handle DEP0147 via transforming `fs.rmdir` to `fs.rm` author: Augustin Mauroy license: MIT diff --git a/recipes/rmdir/package.json b/recipes/rmdir/package.json index b9d9dda6..4c2e2d8c 100644 --- a/recipes/rmdir/package.json +++ b/recipes/rmdir/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/rmdir", - "version": "1.1.3", + "version": "1.1.2", "description": "Handle DEP0147 via transforming `fs.rmdir` to `fs.rm` with the appropriate options.", "type": "module", "scripts": { diff --git a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml index 5a5833e1..ab0ba27f 100644 --- a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml +++ b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/slow-buffer-to-buffer-alloc-unsafe-slow" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0030 via transforming SlowBuffer usage to Buffer.allocUnsafeSlow(). author: lluisemper(Lluis Semper Lloret) license: MIT diff --git a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json index bf87f6a3..2db884e8 100644 --- a/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json +++ b/recipes/slow-buffer-to-buffer-alloc-unsafe-slow/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/slow-buffer-to-buffer-alloc-unsafe-slow", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0030 via transforming SlowBuffer usage to Buffer.allocUnsafeSlow().", "type": "module", "scripts": { diff --git a/recipes/timers-deprecations/codemod.yaml b/recipes/timers-deprecations/codemod.yaml index b6f2c9dc..8b7ee68b 100644 --- a/recipes/timers-deprecations/codemod.yaml +++ b/recipes/timers-deprecations/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/timers-deprecations" -version: 1.0.1 +version: 1.0.0 description: Migrate deprecated node:timers APIs to public timer functions. author: Augustin Mauroy license: MIT diff --git a/recipes/timers-deprecations/package.json b/recipes/timers-deprecations/package.json index 6eca4388..339bb67e 100644 --- a/recipes/timers-deprecations/package.json +++ b/recipes/timers-deprecations/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/timers-deprecations", - "version": "1.0.1", + "version": "1.0.0", "description": "Migrate deprecated node:timers APIs to public timer functions.", "type": "module", "scripts": { diff --git a/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml index f1386cfa..06eaa249 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml +++ b/recipes/tls-create-secure-pair-to-tls-socket/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/tls-create-secure-pair-to-tls-socket" -version: 1.0.2 +version: 1.0.1 description: Handle DEP0064 by transforming `createSecurePair` to `TLSSocket` author: Leonardo Trevizo license: MIT diff --git a/recipes/tls-create-secure-pair-to-tls-socket/package.json b/recipes/tls-create-secure-pair-to-tls-socket/package.json index b404ecb8..2243abf4 100644 --- a/recipes/tls-create-secure-pair-to-tls-socket/package.json +++ b/recipes/tls-create-secure-pair-to-tls-socket/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/tls-create-secure-pair-to-tls-socket", - "version": "1.0.2", + "version": "1.0.1", "description": "Handle DEP0064 replacing `tls.createSecurePair()` with `tls.TLSSocket()`", "type": "module", "scripts": { diff --git a/recipes/tmpdir-to-tmpdir/codemod.yaml b/recipes/tmpdir-to-tmpdir/codemod.yaml index d1caee7e..dae8ab98 100644 --- a/recipes/tmpdir-to-tmpdir/codemod.yaml +++ b/recipes/tmpdir-to-tmpdir/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/tmpDir-to-tmpdir" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0022 via transforming `tmpDir` to `tmpdir`. author: nekojanai (Jana) license: MIT diff --git a/recipes/tmpdir-to-tmpdir/package.json b/recipes/tmpdir-to-tmpdir/package.json index 20520118..8f837ff6 100644 --- a/recipes/tmpdir-to-tmpdir/package.json +++ b/recipes/tmpdir-to-tmpdir/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/tmpdir-to-tmpdir", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0022 via transforming `tmpDir` to `tmpdir`.", "type": "module", "scripts": { diff --git a/recipes/types-is-native-error/codemod.yaml b/recipes/types-is-native-error/codemod.yaml index f655a3fc..53b17b83 100644 --- a/recipes/types-is-native-error/codemod.yaml +++ b/recipes/types-is-native-error/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/types-is-native-error" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0197 via transforming `types.isNativeError` to `Error.isError` author: Bruno Rodrigues license: MIT diff --git a/recipes/types-is-native-error/package.json b/recipes/types-is-native-error/package.json index 2c23d961..9bc4c8b6 100644 --- a/recipes/types-is-native-error/package.json +++ b/recipes/types-is-native-error/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/types-is-native-error", - "version": "1.0.3", + "version": "1.0.1", "description": "Handle DEP0197 via transforming `types.isNativeError` to `Error.isError`", "type": "module", "scripts": { diff --git a/recipes/util-extend-to-object-assign/codemod.yaml b/recipes/util-extend-to-object-assign/codemod.yaml index 713510fb..c394dafc 100644 --- a/recipes/util-extend-to-object-assign/codemod.yaml +++ b/recipes/util-extend-to-object-assign/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-extend-to-object-assign" -version: 1.0.2 +version: 1.0.1 description: "Handle DEP0060 by replacing `util._extend()` with `Object.assign()`." author: GitHub Copilot license: MIT diff --git a/recipes/util-extend-to-object-assign/package.json b/recipes/util-extend-to-object-assign/package.json index d9ac3380..52b906ca 100644 --- a/recipes/util-extend-to-object-assign/package.json +++ b/recipes/util-extend-to-object-assign/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-extend-to-object-assign", - "version": "1.0.2", + "version": "1.0.1", "description": "Handle DEP0060 by replacing `util._extend()` with `Object.assign()`.", "type": "module", "scripts": { diff --git a/recipes/util-is/codemod.yaml b/recipes/util-is/codemod.yaml index 2eeacf63..0e8c2e90 100644 --- a/recipes/util-is/codemod.yaml +++ b/recipes/util-is/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-is" -version: 1.0.3 +version: 1.0.2 description: "Replaces deprecated `util.is*()` methods with their modern equivalents." author: Augustin Mauroy license: MIT diff --git a/recipes/util-is/package.json b/recipes/util-is/package.json index 46a299e8..66eb371e 100644 --- a/recipes/util-is/package.json +++ b/recipes/util-is/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-is", - "version": "1.0.3", + "version": "1.0.2", "description": "Replaces deprecated `util.is*()` methods with their modern equivalents.", "type": "module", "scripts": { diff --git a/recipes/util-log-to-console-log/codemod.yaml b/recipes/util-log-to-console-log/codemod.yaml index e19cfa16..5ef3f55b 100644 --- a/recipes/util-log-to-console-log/codemod.yaml +++ b/recipes/util-log-to-console-log/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-log-to-console-log" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0059 via transforming `log.util()` to `console.log()`. author: Bruno Rodrigues license: MIT diff --git a/recipes/util-log-to-console-log/package.json b/recipes/util-log-to-console-log/package.json index ced0b78b..ca05beaa 100644 --- a/recipes/util-log-to-console-log/package.json +++ b/recipes/util-log-to-console-log/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-log-to-console-log", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0059 via transforming `log.util()` to `console.log()`", "type": "module", "scripts": { diff --git a/recipes/util-print-to-console-log/codemod.yaml b/recipes/util-print-to-console-log/codemod.yaml index d5b4d995..45739cc4 100644 --- a/recipes/util-print-to-console-log/codemod.yaml +++ b/recipes/util-print-to-console-log/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/util-print-to-console-log" -version: "1.0.3" +version: "1.0.2" description: Handle DEP0026, DEP0027, DEP0028, DEP0029 via transforming `util.print|puts|debug|error()` to `console.log|error()` author: Bruno Rodrigues license: MIT diff --git a/recipes/util-print-to-console-log/package.json b/recipes/util-print-to-console-log/package.json index be55ae81..66f24c5e 100644 --- a/recipes/util-print-to-console-log/package.json +++ b/recipes/util-print-to-console-log/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/util-print-to-console-log", - "version": "1.0.3", + "version": "1.0.2", "description": "Handle DEP0026, DEP0027, DEP0028, DEP0029 via transforming `util.print|puts|debug|error()` to `console.log|error()`", "type": "module", "scripts": { diff --git a/recipes/v22-to-v24/codemod.yaml b/recipes/v22-to-v24/codemod.yaml index c6399561..276bc4d0 100644 --- a/recipes/v22-to-v24/codemod.yaml +++ b/recipes/v22-to-v24/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/v22-to-v24" -version: "0.0.2" +version: "0.0.1" description: Handle breaking changes in Node.js v24 by replacing deprecated APIs and updating code to be compatible with the new version. author: Augustin Mauroy license: MIT diff --git a/recipes/v22-to-v24/package.json b/recipes/v22-to-v24/package.json index 9bd75f8a..1e719f1f 100644 --- a/recipes/v22-to-v24/package.json +++ b/recipes/v22-to-v24/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/v22-to-v24", - "version": "1.0.2", + "version": "1.0.1", "description": "Handle breaking changes in Node.js v24 by replacing deprecated APIs and updating code to be compatible with the new version.", "type": "module", "scripts": { diff --git a/recipes/zlib-bytesread-to-byteswritten/codemod.yaml b/recipes/zlib-bytesread-to-byteswritten/codemod.yaml index 87f8b033..1293498e 100644 --- a/recipes/zlib-bytesread-to-byteswritten/codemod.yaml +++ b/recipes/zlib-bytesread-to-byteswritten/codemod.yaml @@ -1,6 +1,6 @@ schema_version: "1.0" name: "@nodejs/zlib-bytesread-to-byteswritten" -version: 1.0.2 +version: 1.0.1 description: Handle DEP0108 by replacing deprecated `zlib.bytesRead` with `zlib.bytesWritten` in Node.js transform streams author: Elie Khoury license: MIT diff --git a/recipes/zlib-bytesread-to-byteswritten/package.json b/recipes/zlib-bytesread-to-byteswritten/package.json index 18c0f6fc..7ea39d77 100644 --- a/recipes/zlib-bytesread-to-byteswritten/package.json +++ b/recipes/zlib-bytesread-to-byteswritten/package.json @@ -1,6 +1,6 @@ { "name": "@nodejs/zlib-bytesread-to-byteswritten", - "version": "1.0.2", + "version": "1.0.1", "description": "Replace deprecated `zlib.bytesRead` with `zlib.bytesWritten` in Node.js transform streams", "type": "module", "scripts": {