From e2db32f3873cfe15bdb98e5e58b938a61d21f463 Mon Sep 17 00:00:00 2001 From: sebastien Date: Thu, 8 Oct 2026 17:52:11 +0200 Subject: [PATCH] chore(monorepo): remove fs-extra from website, admin scripts and root (AI-assisted) Use node:fs/promises and @docusaurus/fs helpers instead, and remove the fs-extra dependencies from the root and website package.json. Co-Authored-By: Claude Opus 5.5 --- __tests__/validate-package-json.test.ts | 9 +++--- __tests__/validate-tsconfig.test.ts | 9 +++--- admin/scripts/generateExamples.js | 5 ++-- admin/scripts/resizeImage.js | 2 +- eslint.rules.ts | 3 +- package.json | 3 +- pnpm-lock.yaml | 30 ++++--------------- .../_dogfooding/testSwizzleThemeClassic.mjs | 4 +-- website/package.json | 2 +- website/src/data/__tests__/user.test.ts | 2 +- website/src/plugins/changelog/index.ts | 2 +- website/src/plugins/changelog/utils.ts | 6 ++-- website/testCSSOrder.mjs | 2 +- 13 files changed, 31 insertions(+), 48 deletions(-) diff --git a/__tests__/validate-package-json.test.ts b/__tests__/validate-package-json.test.ts index c5ce7c164eee..b4a5d93bd308 100644 --- a/__tests__/validate-package-json.test.ts +++ b/__tests__/validate-package-json.test.ts @@ -6,8 +6,8 @@ */ import {describe, expect, it} from 'vitest'; -import fs from 'fs-extra'; import {glob} from '@docusaurus/glob'; +import {readJSON} from '@docusaurus/fs'; type PackageJsonFile = { file: string; @@ -30,9 +30,10 @@ async function getPackagesJsonFiles(): Promise { const files = await glob('packages/*/package.json'); return Promise.all( files.map((file) => - fs - .readJSON(file) - .then((content: PackageJsonFile['content']) => ({file, content})), + readJSON(file).then((content) => ({ + file, + content: content as PackageJsonFile['content'], + })), ), ); } diff --git a/__tests__/validate-tsconfig.test.ts b/__tests__/validate-tsconfig.test.ts index 4751b2938315..97da094bff9f 100644 --- a/__tests__/validate-tsconfig.test.ts +++ b/__tests__/validate-tsconfig.test.ts @@ -6,9 +6,9 @@ */ import {describe, it} from 'vitest'; -import fs from 'fs-extra'; import {glob} from '@docusaurus/glob'; import {Joi} from '@docusaurus/utils-validation'; +import {readJSON} from '@docusaurus/fs'; type TsconfigFile = { file: string; @@ -24,9 +24,10 @@ async function getTsconfigFiles(): Promise { const files = await glob('packages/*/tsconfig.*'); return Promise.all( files.map((file) => - fs - .readJSON(file) - .then((content: TsconfigFile['content']) => ({file, content})), + readJSON(file).then((content) => ({ + file, + content: content as TsconfigFile['content'], + })), ), ); } diff --git a/admin/scripts/generateExamples.js b/admin/scripts/generateExamples.js index b1b34e938f98..20ecede76f94 100644 --- a/admin/scripts/generateExamples.js +++ b/admin/scripts/generateExamples.js @@ -7,8 +7,9 @@ // @ts-check -import fs from 'fs-extra'; +import fs from 'node:fs/promises'; import {execa} from 'execa'; +import {readJSON} from '@docusaurus/fs'; /** * Generate one example per init template @@ -49,7 +50,7 @@ async function generateTemplateExample(template) { const templatePackageJson = await /** @type {Promise} */ ( - fs.readJSON(`examples/${template}/package.json`) + readJSON(`examples/${template}/package.json`) ); // Attach the dev script which would be used in code sandbox by default diff --git a/admin/scripts/resizeImage.js b/admin/scripts/resizeImage.js index bc90b30bf9d1..dccaf47b7327 100644 --- a/admin/scripts/resizeImage.js +++ b/admin/scripts/resizeImage.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import fs from 'fs-extra'; +import fs from 'node:fs/promises'; import path from 'node:path'; import {fileURLToPath} from 'node:url'; import {program} from 'commander'; diff --git a/eslint.rules.ts b/eslint.rules.ts index cecc032305b6..b5aea5e4ed01 100644 --- a/eslint.rules.ts +++ b/eslint.rules.ts @@ -159,7 +159,7 @@ export default defineConfig( // @ 'ExportDefaultDeclaration > Identifier, ExportNamedDeclaration[source=null] > ExportSpecifier', // message: 'Export in one statement' // }, - ...['node:path', 'fs-extra', 'webpack', 'lodash'].map((m) => ({ + ...['node:path', 'webpack', 'lodash'].map((m) => ({ selector: `ImportDeclaration[importKind=value]:has(Literal[value="${m}"]) > ImportSpecifier[importKind=value]`, message: 'Default-import this, both for readability and interoperability with ESM', @@ -237,7 +237,6 @@ export default defineConfig( {pattern: 'react', group: 'builtin', position: 'before'}, {pattern: 'react-dom', group: 'builtin', position: 'before'}, {pattern: 'react-dom/**', group: 'builtin', position: 'before'}, - {pattern: 'fs-extra', group: 'builtin'}, {pattern: 'lodash', group: 'external', position: 'before'}, {pattern: 'clsx', group: 'external', position: 'before'}, // 'Bit weird to not use the `import/internal-regex` option, but this diff --git a/package.json b/package.json index 944d0e75d28a..2df802ae9869 100644 --- a/package.json +++ b/package.json @@ -82,11 +82,11 @@ "@docusaurus/plugin-content-blog": "workspace:*", "@docusaurus/plugin-content-docs": "workspace:*", "@docusaurus/plugin-content-pages": "workspace:*", + "@docusaurus/fs": "workspace:*", "@eslint/js": "^10.0.1", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^7.0.1", "@testing-library/react": "^16.3.3", - "@types/fs-extra": "^11.0.4", "@types/lodash": "^4.17.25", "@types/node": "^26.6.1", "@types/prompts": "^2.4.9", @@ -108,7 +108,6 @@ "eslint-plugin-react-you-might-not-need-an-effect": "^1.0.2", "eslint-plugin-regexp": "^3.3.0", "execa": "^10.0.1", - "fs-extra": "^11.4.0", "globals": "^17.12.0", "husky": "^9.1.7", "image-size": "^2.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63b68772a9e6..7a92f85a2afd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,9 @@ importers: '@docusaurus/eslint-plugin': specifier: workspace:* version: link:packages/eslint-plugin + '@docusaurus/fs': + specifier: workspace:* + version: link:packages/docusaurus-fs '@docusaurus/plugin-content-blog': specifier: workspace:* version: link:packages/docusaurus-plugin-content-blog @@ -144,9 +147,6 @@ importers: '@testing-library/react': specifier: ^16.3.3 version: 16.3.3(@testing-library/dom@10.4.1)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) - '@types/fs-extra': - specifier: ^11.0.4 - version: 11.0.4 '@types/lodash': specifier: ^4.17.25 version: 4.17.25 @@ -213,9 +213,6 @@ importers: execa: specifier: ^10.0.1 version: 10.0.1 - fs-extra: - specifier: ^11.4.0 - version: 11.4.0 globals: specifier: ^17.12.0 version: 17.12.0 @@ -2183,6 +2180,9 @@ importers: '@docusaurus/core': specifier: workspace:* version: link:../packages/docusaurus + '@docusaurus/fs': + specifier: workspace:* + version: link:../packages/docusaurus-fs '@docusaurus/glob': specifier: workspace:* version: link:../packages/docusaurus-glob @@ -2249,9 +2249,6 @@ importers: color: specifier: ^4.2.3 version: 4.2.3 - fs-extra: - specifier: ^11.4.0 - version: 11.4.0 netlify-plugin-cache: specifier: ^1.0.3 version: 1.0.3 @@ -6282,9 +6279,6 @@ packages: '@types/file-loader@5.0.4': resolution: {integrity: sha512-aB4X92oi5D2nIGI8/kolnJ47btRM2MQjQS4eJgA/VnCD12x0+kP5v7b5beVQWKHLOcquwUXvv6aMt8PmMy9uug==} - '@types/fs-extra@11.0.4': - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} @@ -6315,9 +6309,6 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/jsonfile@6.1.4': - resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - '@types/katex@0.16.8': resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==} @@ -17537,11 +17528,6 @@ snapshots: dependencies: '@types/webpack': 4.41.40 - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 26.6.1 - '@types/geojson@7946.0.16': {} '@types/hast@3.0.5': @@ -17568,10 +17554,6 @@ snapshots: '@types/json5@0.0.29': {} - '@types/jsonfile@6.1.4': - dependencies: - '@types/node': 26.6.1 - '@types/katex@0.16.8': {} '@types/lodash@4.17.25': {} diff --git a/website/_dogfooding/testSwizzleThemeClassic.mjs b/website/_dogfooding/testSwizzleThemeClassic.mjs index 607237cb9819..491c5bfecff2 100644 --- a/website/_dogfooding/testSwizzleThemeClassic.mjs +++ b/website/_dogfooding/testSwizzleThemeClassic.mjs @@ -6,7 +6,7 @@ */ import path from 'node:path'; -import fs from 'fs-extra'; +import fs from 'node:fs/promises'; import {fileURLToPath} from 'node:url'; import {logger} from '@docusaurus/logger'; @@ -51,7 +51,7 @@ console.log('Args', { }); console.log('\n'); -await fs.remove(toPath); +await fs.rm(toPath, {recursive: true, force: true}); function filterComponentNames(componentNames) { // TODO temp workaround: non-comps should be forbidden to wrap diff --git a/website/package.json b/website/package.json index 955a570c5947..a624075014e0 100644 --- a/website/package.json +++ b/website/package.json @@ -40,6 +40,7 @@ "@crowdin/crowdin-api-client": "^1.57.0", "@docsearch/react": "^4.7.0", "@docusaurus/core": "workspace:*", + "@docusaurus/fs": "workspace:*", "@docusaurus/glob": "workspace:*", "@docusaurus/logger": "workspace:*", "@docusaurus/plugin-client-redirects": "workspace:*", @@ -62,7 +63,6 @@ "@docusaurus/utils-validation": "workspace:*", "clsx": "^2.1.1", "color": "^4.2.3", - "fs-extra": "^11.4.0", "netlify-plugin-cache": "^1.0.3", "prism-react-renderer": "^2.4.1", "raw-loader": "^4.0.2", diff --git a/website/src/data/__tests__/user.test.ts b/website/src/data/__tests__/user.test.ts index f674aab2df7f..e89af285c8be 100644 --- a/website/src/data/__tests__/user.test.ts +++ b/website/src/data/__tests__/user.test.ts @@ -6,7 +6,7 @@ */ import {describe, expect, it} from 'vitest'; -import fs from 'fs-extra'; +import fs from 'node:fs'; import path from 'node:path'; import _ from 'lodash'; import {imageSizeFromFile} from 'image-size/fromFile'; diff --git a/website/src/plugins/changelog/index.ts b/website/src/plugins/changelog/index.ts index 1b0111bfa53b..fb32e7bf10df 100644 --- a/website/src/plugins/changelog/index.ts +++ b/website/src/plugins/changelog/index.ts @@ -6,7 +6,7 @@ */ import path from 'node:path'; -import fs from 'fs-extra'; +import fs from 'node:fs/promises'; import pluginContentBlog from '@docusaurus/plugin-content-blog'; import {aliasedSitePath, docuHash, normalizeUrl} from '@docusaurus/utils'; import {safeGlob} from '@docusaurus/glob'; diff --git a/website/src/plugins/changelog/utils.ts b/website/src/plugins/changelog/utils.ts index fee7a02dc09b..9b2b5fc8a294 100644 --- a/website/src/plugins/changelog/utils.ts +++ b/website/src/plugins/changelog/utils.ts @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import fs from 'fs-extra'; import path from 'node:path'; +import {outputFile} from '@docusaurus/fs'; /** * Multiple versions may be published on the same day, causing the order to be @@ -118,14 +118,14 @@ export async function createBlogFiles( ): Promise { await Promise.all( changelogEntries.map((changelogEntry) => - fs.outputFile( + outputFile( path.join(generateDir, `${changelogEntry.title}.md`), changelogEntry.content, ), ), ); - await fs.outputFile( + await outputFile( path.join(generateDir, 'authors.json'), JSON.stringify(createAuthorsMap(changelogEntries), null, 2), ); diff --git a/website/testCSSOrder.mjs b/website/testCSSOrder.mjs index 7c10ad67b57b..4407846f0028 100644 --- a/website/testCSSOrder.mjs +++ b/website/testCSSOrder.mjs @@ -7,7 +7,7 @@ import path from 'node:path'; import {fileURLToPath} from 'node:url'; -import fs from 'fs-extra'; +import fs from 'node:fs/promises'; /* This verifies CSS ordering on the Docusaurus site itself,