Repository: lerna-lite/lerna-lite
Pull request #998 (2025-03-22 17:01:27)

chore(deps)!: remove `node-fetch`, fixes punycode warning
<!--- Provide a general summary of your changes in the Title above -->

## Description

Remove node-fetch and use native fetch

## Motivation and Context

remove dependencies that are no longer necessary since Fetch is now native in Node 20, this also fixes a `punnycode` deprecation warning issue,

PR based on Lerna's PR 4113

## How Has This Been Tested?

update tests

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [ ] Chore (change that has absolutely no effect on users)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] My code follows the code style of this project.
- [x] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [ ] I have added tests to cover my changes.
- [x] All new and existing tests passed.


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/lerna-lite/lerna-lite/pull/998?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lerna-lite) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 97.92%. Comparing base [(`6eb5a80`)](https://app.codecov.io/gh/lerna-lite/lerna-lite/commit/6eb5a80d9dd42898b8028712cd15abc7959ade3b?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lerna-lite) to head [(`42c62f3`)](https://app.codecov.io/gh/lerna-lite/lerna-lite/commit/42c62f34d069ab88ce610b55e28704c7e9f76b49?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lerna-lite).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #998      +/-   ##
==========================================
- Coverage   97.92%   97.92%   -0.00%     
==========================================
  Files         148      148              
  Lines        9016     9015       -1     
  Branches     2288     2288              
==========================================
- Hits         8828     8827       -1     
  Misses        187      187              
  Partials        1        1              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/lerna-lite/lerna-lite/pull/998?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lerna-lite).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=lerna-lite).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>

Patch:
diff --git a/packages/version/package.json b/packages/version/package.json
index c5bbcfe9..3bcee6c2 100644
--- a/packages/version/package.json
+++ b/packages/version/package.json
@@ -55,7 +55,6 @@
     "make-dir": "^5.0.0",
     "minimatch": "catalog:",
     "new-github-release-url": "^2.0.0",
-    "node-fetch": "^3.3.2",
     "npm-package-arg": "catalog:",
     "p-limit": "^6.2.0",
     "p-map": "catalog:",
diff --git a/packages/version/src/git-clients/GitLabClient.ts b/packages/version/src/git-clients/GitLabClient.ts
index 05837d6a..cf4b6f28 100644
--- a/packages/version/src/git-clients/GitLabClient.ts
+++ b/packages/version/src/git-clients/GitLabClient.ts
@@ -1,5 +1,4 @@
 import { log } from '@lerna-lite/npmlog';
-import fetch from 'node-fetch';
 import { join } from 'node:path';
 
 import type { GitClient, GitClientReleaseOption } from '../interfaces.js';
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3957d51c..71216a48 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -770,9 +770,6 @@ importers:
       new-github-release-url:
         specifier: ^2.0.0
         version: 2.0.0
-      node-fetch:
-        specifier: ^3.3.2
-        version: 3.3.2
       npm-package-arg:
         specifier: 'catalog:'
         version: 11.0.3
@@ -1988,10 +1985,6 @@ packages:
     engines: {node: '>=4'}
     hasBin: true
 
-  data-uri-to-buffer@4.0.1:
-    resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
-    engines: {node: '>= 12'}
-
   debug@4.4.0:
     resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
     engines: {node: '>=6.0'}
@@ -2209,10 +2202,6 @@ packages:
       picomatch:
         optional: true
 
-  fetch-blob@3.2.0:
-    resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
-    engines: {node: ^12.20 || >= 14.13}
-
   file-entry-cache@8.0.0:
     resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
     engines: {node: '>=16.0.0'}
@@ -2252,10 +2241,6 @@ packages:
     resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
     engines: {node: '>=14'}
 
-  formdata-polyfill@4.0.10:
-    resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
-    engines: {node: '>=12.20.0'}
-
   fs-extra@11.3.0:
     resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
     engines: {node: '>=14.14'}
@@ -2746,14 +2731,6 @@ packages:
     resolution: {integrity: sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
-  node-domexception@1.0.0:
-    resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
-    engines: {node: '>=10.5.0'}
-
-  node-fetch@3.3.2:
-    resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
-    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
-
   node-gyp@10.3.1:
     resolution: {integrity: sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==}
     engines: {node: ^16.14.0 || >=18.0.0}
@@ -3494,10 +3471,6 @@ packages:
   wcwidth@1.0.1:
     resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
 
-  web-streams-polyfill@3.3.3:
-    resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
-    engines: {node: '>= 8'}
-
   which@2.0.2:
     resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
     engines: {node: '>= 8'}
@@ -4705,8 +4678,6 @@ snapshots:
 
   cssesc@3.0.0: {}
 
-  data-uri-to-buffer@4.0.1: {}
-
   debug@4.4.0:
     dependencies:
       ms: 2.1.3
@@ -4942,11 +4913,6 @@ snapshots:
     optionalDependencies:
       picomatch: 4.0.2
 
-  fetch-blob@3.2.0:
-    dependencies:
-      node-domexception: 1.0.0
-      web-streams-polyfill: 3.3.3
-
   file-entry-cache@8.0.0:
     dependencies:
       flat-cache: 4.0.1
@@ -4987,10 +4953,6 @@ snapshots:
       cross-spawn: 7.0.6
       signal-exit: 4.1.0
 
-  formdata-polyfill@4.0.10:
-    dependencies:
-      fetch-blob: 3.2.0
-
   fs-extra@11.3.0:
     dependencies:
       graceful-fs: 4.2.11
@@ -5459,14 +5421,6 @@ snapshots:
     dependencies:
       type-fest: 2.19.0
 
-  node-domexception@1.0.0: {}
-
-  node-fetch@3.3.2:
-    dependencies:
-      data-uri-to-buffer: 4.0.1
-      fetch-blob: 3.2.0
-      formdata-polyfill: 4.0.10
-
   node-gyp@10.3.1:
     dependencies:
       env-paths: 2.2.1
@@ -6205,8 +6159,6 @@ snapshots:
     dependencies:
       defaults: 1.0.4
 
-  web-streams-polyfill@3.3.3: {}
-
   which@2.0.2:
     dependencies:
       isexe: 2.0.0


Test patch:
diff --git a/packages/version/src/git-clients/__tests__/GitLabClient.spec.ts b/packages/version/src/git-clients/__tests__/GitLabClient.spec.ts
index 3dd498bf..9d793025 100644
--- a/packages/version/src/git-clients/__tests__/GitLabClient.spec.ts
+++ b/packages/version/src/git-clients/__tests__/GitLabClient.spec.ts
@@ -1,12 +1,26 @@
-import { describe, expect, it, Mock, vi } from 'vitest';
-
-vi.mock('node-fetch');
-
-import fetch from 'node-fetch';
+import { afterEach, beforeEach, describe, expect, it, Mock, vi } from 'vitest';
 
 import { GitLabClient } from '../GitLabClient.js';
 
 describe('GitLabClient', () => {
+  let originalFetch: any;
+  let fetchMock: Mock;
+
+  beforeEach(() => {
+    originalFetch = global.fetch;
+    global.fetch = vi.fn(() =>
+      Promise.resolve({
+        json: () => Promise.resolve({ test: 100 }),
+      })
+    ) as Mock;
+    fetchMock = global.fetch as any;
+  });
+
+  afterEach(() => {
+    global.fetch = originalFetch;
+    fetchMock = undefined as any;
+  });
+
   describe('constructor', () => {
     it('sets `baseUrl` and `token`', () => {
       const client = new GitLabClient('TOKEN', 'http://some/host');
@@ -28,7 +42,7 @@ describe('GitLabClient', () => {
   describe('createRelease', () => {
     it('requests releases api with release', () => {
       const client = new GitLabClient('TOKEN', 'http://some/host');
-      (fetch as Mock).mockResolvedValue({ ok: true });
+      fetchMock.mockResolvedValue({ ok: true });
       const release = {
         owner: 'the-owner',
         repo: 'the-repo',
@@ -39,7 +53,7 @@ describe('GitLabClient', () => {
 
       client.createRelease(release);
 
-      expect(fetch).toHaveBeenCalledWith('http://some/host/projects/the-owner%2Fthe-repo/releases', {
+      expect(fetchMock).toHaveBeenCalledWith('http://some/host/projects/the-owner%2Fthe-repo/releases', {
         method: 'post',
         body: JSON.stringify({
           name: 'the-name',