This is an automated email from the ASF dual-hosted git repository.

dpogue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-ios.git


The following commit(s) were added to refs/heads/master by this push:
     new f7e29536 chore(deps): Modernize some dependencies (#1413)
f7e29536 is described below

commit f7e29536474378249ba6278ce88aa853fef1f923
Author: Darryl Pogue <dar...@dpogue.ca>
AuthorDate: Thu Mar 28 22:13:50 2024 -0700

    chore(deps): Modernize some dependencies (#1413)
---
 .eslintrc.yml                                 |   4 -
 .github/workflows/ci.yml                      |   8 +-
 lib/Api.js                                    |  11 +-
 lib/BridgingHeader.js                         |   2 +-
 lib/Podfile.js                                |   6 +-
 lib/PodsJson.js                               |   6 +-
 lib/build.js                                  |  13 +-
 lib/clean.js                                  |   6 +-
 lib/create.js                                 |  74 ++--
 lib/plugman/pluginHandlers.js                 |  28 +-
 lib/prepare.js                                |  26 +-
 lib/projectFile.js                            |   6 +-
 lib/run.js                                    |  12 +-
 package-lock.json                             | 547 ++++++++++++--------------
 package.json                                  |   7 +-
 tests/spec/createAndBuild.spec.js             |  19 +-
 tests/spec/unit/Api.spec.js                   |   6 +-
 tests/spec/unit/BridgingHeader.spec.js        |   6 +-
 tests/spec/unit/Plugman/common.spec.js        |  58 +--
 tests/spec/unit/Plugman/pluginHandler.spec.js | 112 +++---
 tests/spec/unit/Podfile.spec.js               |   8 +-
 tests/spec/unit/PodsJson.spec.js              |   8 +-
 tests/spec/unit/build.spec.js                 |   4 +-
 tests/spec/unit/create.spec.js                |   8 +-
 tests/spec/unit/lib/list-devices.spec.js      |   4 +-
 tests/spec/unit/pluginAdd.spec.js             |  14 +-
 tests/spec/unit/prepare.spec.js               |  26 +-
 tests/spec/unit/preparePlatform.spec.js       |  12 +-
 tests/spec/unit/projectFile.spec.js           |  22 +-
 29 files changed, 516 insertions(+), 547 deletions(-)

diff --git a/.eslintrc.yml b/.eslintrc.yml
index 71f88e79..31281afb 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -24,7 +24,3 @@ overrides:
 
   - files: [cordova-js-src/**/*.js]
     extends: '@cordova/eslint-config/browser'
-
-    # TODO add this to @cordova/eslint-config/browser
-    rules:
-      no-var: 0
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c5152657..20f69471 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,10 +29,10 @@ jobs:
         os: [macos-14]
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Use Node.js ${{ matrix.node-version }}
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: ${{ matrix.node-version }}
 
@@ -61,10 +61,10 @@ jobs:
         os: [ubuntu-latest, windows-latest]
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Use Node.js ${{ matrix.node-version }}
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: ${{ matrix.node-version }}
 
diff --git a/lib/Api.js b/lib/Api.js
index 0437a1ad..96e7c54c 100644
--- a/lib/Api.js
+++ b/lib/Api.js
@@ -21,9 +21,9 @@
 
 const VERSION = require('../package.json').version;
 
-const fs = require('fs-extra');
-const path = require('path');
-const unorm = require('unorm');
+const fs = require('node:fs');
+const path = require('node:path');
+const util = require('node:util');
 const projectFile = require('./projectFile');
 const check_reqs = require('./check_reqs');
 const {
@@ -33,7 +33,6 @@ const {
     events,
     PluginManager
 } = require('cordova-common');
-const util = require('util');
 
 function setupEvents (externalEventEmitter) {
     if (externalEventEmitter) {
@@ -111,7 +110,7 @@ class Api {
             www: path.join(this.root, 'www'),
             platformWww: path.join(this.root, 'platform_www'),
             configXml: path.join(xcodeCordovaProj, 'config.xml'),
-            defaultConfigXml: path.join(this.root, 'cordova/defaults.xml'),
+            defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'),
             pbxproj: path.join(this.root, xcodeProjDir, 'project.pbxproj'),
             xcodeProjDir: path.join(this.root, xcodeProjDir),
             xcodeCordovaProj
@@ -142,7 +141,7 @@ class Api {
         // CB-6992 it is necessary to normalize characters
         // because node and shell scripts handles unicode symbols differently
         // We need to normalize the name to NFD form since iOS uses NFD 
unicode form
-        const name = unorm.nfd(config.name());
+        const name = config.name().normalize('NFD');
         let result;
         try {
             result = require('./create')
diff --git a/lib/BridgingHeader.js b/lib/BridgingHeader.js
index 9e200b50..a15d73f3 100644
--- a/lib/BridgingHeader.js
+++ b/lib/BridgingHeader.js
@@ -18,7 +18,7 @@
 */
 'use strict';
 
-const fs = require('fs-extra');
+const fs = require('node:fs');
 const CordovaError = require('cordova-common').CordovaError;
 
 function BridgingHeader (bridgingHeaderPath) {
diff --git a/lib/Podfile.js b/lib/Podfile.js
index 3500b5f0..fd7bf8db 100644
--- a/lib/Podfile.js
+++ b/lib/Podfile.js
@@ -18,9 +18,9 @@
 */
 'use strict';
 
-const fs = require('fs-extra');
-const path = require('path');
-const util = require('util');
+const fs = require('node:fs');
+const path = require('node:path');
+const util = require('node:util');
 const execa = require('execa');
 const { CordovaError, events } = require('cordova-common');
 
diff --git a/lib/PodsJson.js b/lib/PodsJson.js
index efea7d8d..c35ff09e 100644
--- a/lib/PodsJson.js
+++ b/lib/PodsJson.js
@@ -17,9 +17,9 @@
        under the License.
 */
 
-const fs = require('fs-extra');
-const path = require('path');
-const util = require('util');
+const fs = require('node:fs');
+const path = require('node:path');
+const util = require('node:util');
 const xcode = require('xcode');
 const check_reqs = require('./check_reqs');
 const events = require('cordova-common').events;
diff --git a/lib/build.js b/lib/build.js
index 53dafa6a..cfb6a894 100644
--- a/lib/build.js
+++ b/lib/build.js
@@ -17,13 +17,14 @@
  * under the License.
  */
 
-const path = require('path');
+const fs = require('node:fs');
+const fsp = require('node:fs/promises');
+const path = require('node:path');
+const util = require('node:util');
 const which = require('which');
 const execa = require('execa');
 const { CordovaError, events } = require('cordova-common');
-const fs = require('fs-extra');
 const plist = require('plist');
-const util = require('util');
 
 const check_reqs = require('./check_reqs');
 const projectFile = require('./projectFile');
@@ -206,7 +207,7 @@ module.exports.run = function (buildOpts) {
                 writeCodeSignStyle('Automatic');
             }
 
-            return fs.writeFile(path.join(projectPath, 
'cordova/build-extras.xcconfig'), extraConfig, 'utf-8');
+            return fsp.writeFile(path.join(projectPath, 'cordova', 
'build-extras.xcconfig'), extraConfig, 'utf-8');
         }).then(() => {
             const configuration = buildOpts.release ? 'Release' : 'Debug';
 
@@ -218,7 +219,7 @@ module.exports.run = function (buildOpts) {
             const buildOutputDir = path.join(projectPath, 'build', 
`${configuration}-${(buildOpts.device ? 'iphoneos' : 'iphonesimulator')}`);
 
             // remove the build output folder before building
-            fs.removeSync(buildOutputDir);
+            fs.rmSync(buildOutputDir, { recursive: true, force: true });
 
             const xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, 
configuration, emulatorTarget, buildOpts);
             return execa('xcodebuild', xcodebuildArgs, { cwd: projectPath, 
stdio: 'inherit' });
@@ -278,7 +279,7 @@ module.exports.run = function (buildOpts) {
                 return execa('xcodebuild', xcodearchiveArgs, { cwd: 
projectPath, stdio: 'inherit' });
             }
 
-            return fs.writeFile(exportOptionsPath, exportOptionsPlist, 'utf-8')
+            return fsp.writeFile(exportOptionsPath, exportOptionsPlist, 
'utf-8')
                 .then(checkSystemRuby)
                 .then(packageArchive);
         })
diff --git a/lib/clean.js b/lib/clean.js
index 38748559..2c8c2e6b 100644
--- a/lib/clean.js
+++ b/lib/clean.js
@@ -17,8 +17,8 @@
  * under the License.
  */
 
-const path = require('path');
-const fs = require('fs-extra');
+const path = require('node:path');
+const fs = require('node:fs');
 const execa = require('execa');
 const { CordovaError } = require('cordova-common');
 
@@ -40,5 +40,5 @@ module.exports.run = function () {
 
     return xcodebuildClean('Debug')
         .then(() => xcodebuildClean('Release'))
-        .then(() => fs.removeSync(path.join(projectPath, 'build')));
+        .then(() => fs.rmSync(path.join(projectPath, 'build'), { recursive: 
true, force: true }));
 };
diff --git a/lib/create.js b/lib/create.js
index 0f638f13..5e0f630e 100755
--- a/lib/create.js
+++ b/lib/create.js
@@ -17,8 +17,8 @@
     under the License.
 */
 
-const path = require('path');
-const fs = require('fs-extra');
+const path = require('node:path');
+const fs = require('node:fs');
 const xmlescape = require('xml-escape');
 const { CordovaError, events } = require('cordova-common');
 const pkg = require('../package');
@@ -55,7 +55,7 @@ exports.createProject = async (project_path, package_name, 
project_name, opts) =
             id: package_name
         },
         options: {
-            templatePath: opts.customTemplate || path.join(ROOT, 
'templates/project'),
+            templatePath: opts.customTemplate || path.join(ROOT, 'templates', 
'project'),
             linkLib: !!opts.link
         }
     }).create();
@@ -77,18 +77,18 @@ class ProjectCreator {
     }
 
     provideProjectTemplate () {
-        fs.copySync(this.options.templatePath, this.project.path);
+        fs.cpSync(this.options.templatePath, this.project.path, { recursive: 
true });
 
         // TODO: why two .gitignores?
         const r = this.projectPath('__PROJECT_NAME__');
-        fs.moveSync(path.join(r, 'gitignore'), path.join(r, '.gitignore'));
-        fs.copySync(path.join(r, '.gitignore'), 
this.projectPath('.gitignore'));
+        fs.renameSync(path.join(r, 'gitignore'), path.join(r, '.gitignore'));
+        fs.cpSync(path.join(r, '.gitignore'), this.projectPath('.gitignore'));
     }
 
     provideCordovaJs () {
-        fs.copySync(
-            this.projectPath('www/cordova.js'),
-            this.projectPath('platform_www/cordova.js')
+        fs.cpSync(
+            this.projectPath('www', 'cordova.js'),
+            this.projectPath('platform_www', 'cordova.js')
         );
     }
 
@@ -98,9 +98,9 @@ class ProjectCreator {
     }
 
     provideBuildScripts () {
-        const srcScriptsDir = path.join(ROOT, 'templates/cordova');
+        const srcScriptsDir = path.join(ROOT, 'templates', 'cordova');
         const destScriptsDir = this.projectPath('cordova');
-        fs.copySync(srcScriptsDir, destScriptsDir);
+        fs.cpSync(srcScriptsDir, destScriptsDir, { recursive: true });
     }
 
     expandTokens () {
@@ -118,7 +118,7 @@ class ProjectCreator {
             // like it should).
             fs.symlinkSync(cordovaLibPathSrc, cordovaLibPathDest);
         } else {
-            fs.copySync(cordovaLibPathSrc, cordovaLibPathDest);
+            fs.cpSync(cordovaLibPathSrc, cordovaLibPathDest, { recursive: true 
});
         }
     }
 
@@ -137,7 +137,7 @@ class ProjectCreator {
         }
 
         // Replace magic line in project.pbxproj
-        const pbxprojPath = 
this.projectPath('__PROJECT_NAME__.xcodeproj/project.pbxproj');
+        const pbxprojPath = this.projectPath('__PROJECT_NAME__.xcodeproj', 
'project.pbxproj');
         transformFileContents(pbxprojPath, contents => {
             const regex = 
/(.+CordovaLib.xcodeproj.+PBXFileReference.+wrapper.pb-project.+)(path = 
.+?;)(.*)(sourceTree.+;)(.+)/;
             const line = contents.split(/\r?\n/)
@@ -162,47 +162,47 @@ class ProjectCreator {
     expandTokensInFileContents () {
         // Expand __PROJECT_ID__ token in file contents
         transformFileContents(
-            this.projectPath('__PROJECT_NAME__.xcodeproj/project.pbxproj'),
+            this.projectPath('__PROJECT_NAME__.xcodeproj', 'project.pbxproj'),
             contents => contents.replace(/__PROJECT_ID__/g, this.project.id)
         );
 
         // Expand __PROJECT_NAME__ token in file contents
         for (const p of [
-            'cordova/build-debug.xcconfig',
-            'cordova/build-release.xcconfig',
-            '__PROJECT_NAME__.xcworkspace/contents.xcworkspacedata',
-            
'__PROJECT_NAME__.xcworkspace/xcshareddata/xcschemes/__PROJECT_NAME__.xcscheme',
-            '__PROJECT_NAME__.xcodeproj/project.pbxproj',
-            '__PROJECT_NAME__/AppDelegate.h',
-            '__PROJECT_NAME__/AppDelegate.m',
-            '__PROJECT_NAME__/MainViewController.h',
-            '__PROJECT_NAME__/MainViewController.m',
-            '__PROJECT_NAME__/main.m',
-            '__PROJECT_NAME__/__PROJECT_NAME__-Info.plist',
-            '__PROJECT_NAME__/__PROJECT_NAME__-Prefix.pch'
+            ['cordova', 'build-debug.xcconfig'],
+            ['cordova', 'build-release.xcconfig'],
+            ['__PROJECT_NAME__.xcworkspace', 'contents.xcworkspacedata'],
+            ['__PROJECT_NAME__.xcworkspace', 'xcshareddata', 'xcschemes', 
'__PROJECT_NAME__.xcscheme'],
+            ['__PROJECT_NAME__.xcodeproj', 'project.pbxproj'],
+            ['__PROJECT_NAME__', 'AppDelegate.h'],
+            ['__PROJECT_NAME__', 'AppDelegate.m'],
+            ['__PROJECT_NAME__', 'MainViewController.h'],
+            ['__PROJECT_NAME__', 'MainViewController.m'],
+            ['__PROJECT_NAME__', 'main.m'],
+            ['__PROJECT_NAME__', '__PROJECT_NAME__-Info.plist'],
+            ['__PROJECT_NAME__', '__PROJECT_NAME__-Prefix.pch']
         ]) {
-            this.expandProjectNameInFileContents(this.projectPath(p));
+            this.expandProjectNameInFileContents(this.projectPath(...p));
         }
     }
 
     expandTokensInFileNames () {
         // Expand __PROJECT_NAME__ token in file & folder names
         for (const p of [
-            
'__PROJECT_NAME__.xcworkspace/xcshareddata/xcschemes/__PROJECT_NAME__.xcscheme',
-            '__PROJECT_NAME__.xcworkspace',
-            '__PROJECT_NAME__.xcodeproj',
-            '__PROJECT_NAME__/__PROJECT_NAME__-Info.plist',
-            '__PROJECT_NAME__/__PROJECT_NAME__-Prefix.pch',
-            '__PROJECT_NAME__'
+            ['__PROJECT_NAME__.xcworkspace', 'xcshareddata', 'xcschemes', 
'__PROJECT_NAME__.xcscheme'],
+            ['__PROJECT_NAME__.xcworkspace'],
+            ['__PROJECT_NAME__.xcodeproj'],
+            ['__PROJECT_NAME__', '__PROJECT_NAME__-Info.plist'],
+            ['__PROJECT_NAME__', '__PROJECT_NAME__-Prefix.pch'],
+            ['__PROJECT_NAME__']
         ]) {
-            this.expandProjectNameInBaseName(this.projectPath(p));
+            this.expandProjectNameInBaseName(this.projectPath(...p));
         }
     }
 
     expandProjectNameInBaseName (f) {
         const { dir, base } = path.parse(f);
         const newBase = base.replace('__PROJECT_NAME__', this.project.name);
-        return fs.moveSync(f, path.join(dir, newBase));
+        return fs.renameSync(f, path.join(dir, newBase));
     }
 
     expandProjectNameInFileContents (f) {
@@ -217,8 +217,8 @@ class ProjectCreator {
         );
     }
 
-    projectPath (projectRelativePath) {
-        return path.join(this.project.path, projectRelativePath);
+    projectPath (...projectRelativePaths) {
+        return path.join(this.project.path, ...projectRelativePaths);
     }
 }
 
diff --git a/lib/plugman/pluginHandlers.js b/lib/plugman/pluginHandlers.js
index b4e963ea..7cd55ba1 100644
--- a/lib/plugman/pluginHandlers.js
+++ b/lib/plugman/pluginHandlers.js
@@ -15,9 +15,9 @@
        under the License.
 */
 'use strict';
-const fs = require('fs-extra');
-const path = require('path');
-const util = require('util');
+const fs = require('node:fs');
+const path = require('node:path');
+const util = require('node:util');
 const events = require('cordova-common').events;
 const CordovaError = require('cordova-common').CordovaError;
 
@@ -76,7 +76,7 @@ const handlers = {
             const destFile = path.resolve(project.resources_dir, target);
 
             project.xcode.removeResourceFile(path.join('Resources', target));
-            fs.removeSync(destFile);
+            fs.rmSync(destFile, { recursive: true, force: true });
         }
     },
     framework: { // CB-5238 custom frameworks only
@@ -154,7 +154,7 @@ const handlers = {
             if (pbxFile) {
                 project.xcode.removeFromPbxEmbedFrameworksBuildPhase(pbxFile);
             }
-            fs.removeSync(targetDir);
+            fs.rmSync(targetDir, { recursive: true, force: true });
         }
     },
     'lib-file': {
@@ -206,11 +206,11 @@ const handlers = {
             scriptContent = `cordova.define("${moduleName}", function(require, 
exports, module) {\n${scriptContent}\n});\n`;
 
             const moduleDestination = path.resolve(project.www, 'plugins', 
plugin.id, obj.src);
-            fs.ensureDirSync(path.dirname(moduleDestination));
+            fs.mkdirSync(path.dirname(moduleDestination), { recursive: true });
             fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
             if (options && options.usePlatformWww) {
                 const platformWwwDestination = 
path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
-                fs.ensureDirSync(path.dirname(platformWwwDestination));
+                fs.mkdirSync(path.dirname(platformWwwDestination), { 
recursive: true });
                 fs.writeFileSync(platformWwwDestination, scriptContent, 
'utf-8');
             }
         },
@@ -292,7 +292,7 @@ function uninstallHelper (type, obj, project_dir, 
plugin_id, options, project) {
         project_ref = `Plugins/${fixPathSep(path.relative(project.plugins_dir, 
destFile))}`;
     }
 
-    fs.removeSync(targetDir);
+    fs.rmSync(targetDir, { recursive: true, force: true });
 
     if (type === 'header-file') {
         project.xcode.removeHeaderFile(project_ref);
@@ -324,12 +324,12 @@ function copyFile (plugin_dir, src, project_dir, dest, 
link) {
     // check that dest path is located in project directory
     if (dest.indexOf(project_dir) !== 0) { throw new CordovaError(`Destination 
"${dest}" for source file "${src}" is located outside the project`); }
 
-    fs.ensureDirSync(path.dirname(dest));
+    fs.mkdirSync(path.dirname(dest), { recursive: true });
 
     if (link) {
         linkFileOrDirTree(src, dest);
     } else {
-        fs.copySync(src, dest);
+        fs.cpSync(src, dest, { recursive: true });
     }
 }
 
@@ -343,11 +343,11 @@ function copyNewFile (plugin_dir, src, project_dir, dest, 
link) {
 
 function linkFileOrDirTree (src, dest) {
     if (fs.existsSync(dest)) {
-        fs.removeSync(dest);
+        fs.rmSync(dest, { recursive: true, force: true });
     }
 
     if (fs.statSync(src).isDirectory()) {
-        fs.ensureDirSync(dest);
+        fs.mkdirSync(dest, { recursive: true });
         fs.readdirSync(src).forEach(entry => {
             linkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
         });
@@ -359,12 +359,12 @@ function linkFileOrDirTree (src, dest) {
 // checks if file exists and then deletes. Error if doesn't exist
 function removeFile (project_dir, src) {
     const file = path.resolve(project_dir, src);
-    fs.removeSync(file);
+    fs.rmSync(file);
 }
 
 // deletes file/directory without checking
 function removeFileF (file) {
-    fs.removeSync(file);
+    fs.rmSync(file);
 }
 
 function removeFileAndParents (baseDir, destFile, stopper) {
diff --git a/lib/prepare.js b/lib/prepare.js
index df88fd6c..722fc641 100644
--- a/lib/prepare.js
+++ b/lib/prepare.js
@@ -17,12 +17,10 @@
     under the License.
 */
 
-const fs = require('fs-extra');
-const path = require('path');
-const unorm = require('unorm');
+const fs = require('node:fs');
+const path = require('node:path');
 const plist = require('plist');
 const et = require('elementtree');
-const URL = require('url');
 const events = require('cordova-common').events;
 const xmlHelpers = require('cordova-common').xmlHelpers;
 const ConfigParser = require('cordova-common').ConfigParser;
@@ -140,7 +138,7 @@ function updateConfigFile (sourceConfig, configMunger, 
locations) {
 
     // First cleanup current config and merge project's one into own
     // Overwrite platform config.xml with defaults.xml.
-    fs.copySync(locations.defaultConfigXml, locations.configXml);
+    fs.cpSync(locations.defaultConfigXml, locations.configXml);
 
     // Then apply config changes from global munge to all config files
     // in project (including project's config)
@@ -217,7 +215,7 @@ function updateProject (platformConfig, locations) {
     // CB-6992 it is necessary to normalize characters
     // because node and shell scripts handles unicode symbols differently
     // We need to normalize the name to NFD form since iOS uses NFD unicode 
form
-    const name = unorm.nfd(platformConfig.name());
+    const name = platformConfig.name().normalize('NFD');
     const version = platformConfig.version();
     const displayName = platformConfig.shortName && platformConfig.shortName();
 
@@ -408,12 +406,12 @@ function mapIconResources (icons, iconsDir) {
 
 function getIconsDir (projectRoot, platformProjDir) {
     let iconsDir;
-    const xcassetsExists = folderExists(path.join(projectRoot, 
platformProjDir, 'Assets.xcassets/'));
+    const xcassetsExists = folderExists(path.join(projectRoot, 
platformProjDir, 'Assets.xcassets'));
 
     if (xcassetsExists) {
-        iconsDir = path.join(platformProjDir, 
'Assets.xcassets/AppIcon.appiconset/');
+        iconsDir = path.join(platformProjDir, 'Assets.xcassets', 
'AppIcon.appiconset');
     } else {
-        iconsDir = path.join(platformProjDir, 'Resources/icons/');
+        iconsDir = path.join(platformProjDir, 'Resources', 'icons');
     }
 
     return iconsDir;
@@ -460,7 +458,7 @@ function cleanIcons (projectRoot, projectConfig, locations) 
{
  * @param  {string} platformProjDir    The platform's project directory
  */
 function getBackgroundColorDir (projectRoot, platformProjDir) {
-    if (folderExists(path.join(projectRoot, platformProjDir, 
'Assets.xcassets/'))) {
+    if (folderExists(path.join(projectRoot, platformProjDir, 
'Assets.xcassets'))) {
         return path.join(platformProjDir, 'Assets.xcassets', 
'BackgroundColor.colorset');
     } else {
         return null;
@@ -906,10 +904,10 @@ function getLaunchStoryboardContentsJSON (splashScreens, 
launchStoryboardImagesD
  */
 function getLaunchStoryboardImagesDir (projectRoot, platformProjDir) {
     let launchStoryboardImagesDir;
-    const xcassetsExists = folderExists(path.join(projectRoot, 
platformProjDir, 'Assets.xcassets/'));
+    const xcassetsExists = folderExists(path.join(projectRoot, 
platformProjDir, 'Assets.xcassets'));
 
     if (xcassetsExists) {
-        launchStoryboardImagesDir = path.join(platformProjDir, 
'Assets.xcassets/LaunchStoryboard.imageset/');
+        launchStoryboardImagesDir = path.join(platformProjDir, 
'Assets.xcassets', 'LaunchStoryboard.imageset');
     } else {
         // if we don't have a asset library for images, we can't do the 
storyboard.
         launchStoryboardImagesDir = null;
@@ -1117,13 +1115,13 @@ function parseAllowlistUrlForATS (url, options) {
 
     let href = null;
     try {
-        href = new URL.URL(url);
+        href = new URL(url);
     } catch (e) {
         const scheme = url.split(':')[0];
         // If there's a wildcard in the protocol, the URL will fail to parse
         // Replace it with "http" to allow insecure loads
         if (scheme.includes('*')) {
-            href = new URL.URL(url.replace(scheme, 'http'));
+            href = new URL(url.replace(scheme, 'http'));
         } else {
             return null;
         }
diff --git a/lib/projectFile.js b/lib/projectFile.js
index 0807d77a..1ad65f7b 100644
--- a/lib/projectFile.js
+++ b/lib/projectFile.js
@@ -17,10 +17,10 @@
        under the License.
 */
 
+const fs = require('node:fs');
+const path = require('node:path');
 const xcode = require('xcode');
 const plist = require('plist');
-const path = require('path');
-const fs = require('fs-extra');
 
 const pluginHandlers = require('./plugman/pluginHandlers');
 const CordovaError = require('cordova-common').CordovaError;
@@ -70,7 +70,7 @@ function parseProjectFile (locations) {
             fs.writeFileSync(pbxPath, xcodeproj.writeSync());
             if (Object.keys(this.frameworks).length === 0) {
                 // If there is no framework references remain in the project, 
just remove this file
-                fs.removeSync(frameworks_file);
+                fs.rmSync(frameworks_file, { force: true });
                 return;
             }
             fs.writeFileSync(frameworks_file, JSON.stringify(this.frameworks, 
null, 4));
diff --git a/lib/run.js b/lib/run.js
index f29dc2bf..494439f0 100644
--- a/lib/run.js
+++ b/lib/run.js
@@ -17,12 +17,12 @@
        under the License.
 */
 
-const path = require('path');
-const build = require('./build');
+const fs = require('node:fs');
+const path = require('node:path');
 const execa = require('execa');
 const { CordovaError, events } = require('cordova-common');
+const build = require('./build');
 const check_reqs = require('./check_reqs');
-const fs = require('fs-extra');
 
 /** @returns {Promise<void>} */
 module.exports.run = function (runOptions) {
@@ -82,11 +82,11 @@ module.exports.run = function (runOptions) {
                         const payloadFolder = path.join(buildOutputDir, 
'Payload');
 
                         // delete the existing 
platform/ios/build/device/appname.app
-                        fs.removeSync(appFile);
+                        fs.rmSync(appFile, { recursive: true, force: true });
                         // move the 
platform/ios/build/device/Payload/appname.app to parent
-                        fs.moveSync(appFileInflated, appFile);
+                        fs.renameSync(appFileInflated, appFile);
                         // delete the platform/ios/build/device/Payload folder
-                        fs.removeSync(payloadFolder);
+                        fs.rmSync(payloadFolder, { recursive: true, force: 
true });
 
                         return null;
                     })
diff --git a/package-lock.json b/package-lock.json
index 862e2115..d0782eda 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,18 +12,15 @@
         "cordova-common": "^5.0.0",
         "elementtree": "^0.1.7",
         "execa": "^5.1.1",
-        "fs-extra": "^11.1.1",
         "ios-sim": "^8.0.2",
-        "nopt": "^7.1.0",
         "plist": "^3.0.6",
         "semver": "^7.4.0",
-        "unorm": "^1.6.0",
-        "which": "^3.0.1",
+        "which": "^4.0.0",
         "xcode": "^3.0.1",
         "xml-escape": "^1.1.0"
       },
       "devDependencies": {
-        "@cordova/eslint-config": "^5.0.0",
+        "@cordova/eslint-config": "^5.1.0",
         "cordova-js": "^6.1.0",
         "jasmine": "^4.6.0",
         "nyc": "^15.1.0",
@@ -57,113 +54,42 @@
       }
     },
     "node_modules/@babel/code-frame": {
-      "version": "7.23.5",
-      "resolved": 
"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz";,
-      "integrity": 
"sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+      "version": "7.24.2",
+      "resolved": 
"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz";,
+      "integrity": 
"sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==",
       "dev": true,
       "dependencies": {
-        "@babel/highlight": "^7.23.4",
-        "chalk": "^2.4.2"
+        "@babel/highlight": "^7.24.2",
+        "picocolors": "^1.0.0"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
-    "node_modules/@babel/code-frame/node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": 
"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz";,
-      "integrity": 
"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz";,
-      "integrity": 
"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": 
"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz";,
-      "integrity": 
"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": 
"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz";,
-      "integrity": 
"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
-    },
-    "node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": 
"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz";,
-      "integrity": 
"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz";,
-      "integrity": 
"sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": 
"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz";,
-      "integrity": 
"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/@babel/compat-data": {
-      "version": "7.23.5",
-      "resolved": 
"https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz";,
-      "integrity": 
"sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz";,
+      "integrity": 
"sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.24.0",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz";,
-      "integrity": 
"sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==",
+      "version": "7.24.3",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz";,
+      "integrity": 
"sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==",
       "dev": true,
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.23.5",
-        "@babel/generator": "^7.23.6",
+        "@babel/code-frame": "^7.24.2",
+        "@babel/generator": "^7.24.1",
         "@babel/helper-compilation-targets": "^7.23.6",
         "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helpers": "^7.24.0",
-        "@babel/parser": "^7.24.0",
+        "@babel/helpers": "^7.24.1",
+        "@babel/parser": "^7.24.1",
         "@babel/template": "^7.24.0",
-        "@babel/traverse": "^7.24.0",
+        "@babel/traverse": "^7.24.1",
         "@babel/types": "^7.24.0",
         "convert-source-map": "^2.0.0",
         "debug": "^4.1.0",
@@ -195,14 +121,14 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.23.6",
-      "resolved": 
"https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz";,
-      "integrity": 
"sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz";,
+      "integrity": 
"sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.23.6",
-        "@jridgewell/gen-mapping": "^0.3.2",
-        "@jridgewell/trace-mapping": "^0.3.17",
+        "@babel/types": "^7.24.0",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
         "jsesc": "^2.5.1"
       },
       "engines": {
@@ -269,12 +195,12 @@
       }
     },
     "node_modules/@babel/helper-module-imports": {
-      "version": "7.22.15",
-      "resolved": 
"https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz";,
-      "integrity": 
"sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+      "version": "7.24.3",
+      "resolved": 
"https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz";,
+      "integrity": 
"sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.22.15"
+        "@babel/types": "^7.24.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -324,9 +250,9 @@
       }
     },
     "node_modules/@babel/helper-string-parser": {
-      "version": "7.23.4",
-      "resolved": 
"https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz";,
-      "integrity": 
"sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz";,
+      "integrity": 
"sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -351,13 +277,13 @@
       }
     },
     "node_modules/@babel/helpers": {
-      "version": "7.24.0",
-      "resolved": 
"https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz";,
-      "integrity": 
"sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz";,
+      "integrity": 
"sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==",
       "dev": true,
       "dependencies": {
         "@babel/template": "^7.24.0",
-        "@babel/traverse": "^7.24.0",
+        "@babel/traverse": "^7.24.1",
         "@babel/types": "^7.24.0"
       },
       "engines": {
@@ -365,14 +291,15 @@
       }
     },
     "node_modules/@babel/highlight": {
-      "version": "7.23.4",
-      "resolved": 
"https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz";,
-      "integrity": 
"sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+      "version": "7.24.2",
+      "resolved": 
"https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz";,
+      "integrity": 
"sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==",
       "dev": true,
       "dependencies": {
         "@babel/helper-validator-identifier": "^7.22.20",
         "chalk": "^2.4.2",
-        "js-tokens": "^4.0.0"
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.0.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -450,9 +377,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.24.0",
-      "resolved": 
"https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz";,
-      "integrity": 
"sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz";,
+      "integrity": 
"sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -476,18 +403,18 @@
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.24.0",
-      "resolved": 
"https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz";,
-      "integrity": 
"sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==",
+      "version": "7.24.1",
+      "resolved": 
"https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz";,
+      "integrity": 
"sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.23.5",
-        "@babel/generator": "^7.23.6",
+        "@babel/code-frame": "^7.24.1",
+        "@babel/generator": "^7.24.1",
         "@babel/helper-environment-visitor": "^7.22.20",
         "@babel/helper-function-name": "^7.23.0",
         "@babel/helper-hoist-variables": "^7.22.5",
         "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/parser": "^7.24.0",
+        "@babel/parser": "^7.24.1",
         "@babel/types": "^7.24.0",
         "debug": "^4.3.1",
         "globals": "^11.1.0"
@@ -520,9 +447,9 @@
       }
     },
     "node_modules/@cordova/eslint-config": {
-      "version": "5.0.0",
-      "resolved": 
"https://registry.npmjs.org/@cordova/eslint-config/-/eslint-config-5.0.0.tgz";,
-      "integrity": 
"sha512-tBSV8LbT6RjWsO2lSp45Y+zU7hfXhGMGhfYTZjDrjzli87WOgE6IAS37k6F45JNoGq1XlCJEVkCWwz4KCF8Scw==",
+      "version": "5.1.0",
+      "resolved": 
"https://registry.npmjs.org/@cordova/eslint-config/-/eslint-config-5.1.0.tgz";,
+      "integrity": 
"sha512-9Da72mSQli08ylGf6jYKWJo67LSu6HWlDPELJsW+bVVos3b0ZMxXsHUCluwrlmZ+sxCFq7VhxAFjK+2/YQFncw==",
       "dev": true,
       "dependencies": {
         "eslint": "^8.31.0",
@@ -843,12 +770,9 @@
       }
     },
     "node_modules/abbrev": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz";,
-      "integrity": 
"sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
-      "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
-      }
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz";,
+      "integrity": 
"sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
     },
     "node_modules/acorn": {
       "version": "8.11.3",
@@ -979,15 +903,16 @@
       }
     },
     "node_modules/array-includes": {
-      "version": "3.1.7",
-      "resolved": 
"https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz";,
-      "integrity": 
"sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+      "version": "3.1.8",
+      "resolved": 
"https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz";,
+      "integrity": 
"sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1",
-        "get-intrinsic": "^1.2.1",
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.2",
+        "es-object-atoms": "^1.0.0",
+        "get-intrinsic": "^1.2.4",
         "is-string": "^1.0.7"
       },
       "engines": {
@@ -1006,35 +931,17 @@
         "node": ">=8"
       }
     },
-    "node_modules/array.prototype.filter": {
-      "version": "1.0.3",
-      "resolved": 
"https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz";,
-      "integrity": 
"sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==",
-      "dev": true,
-      "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1",
-        "es-array-method-boxes-properly": "^1.0.0",
-        "is-string": "^1.0.7"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb";
-      }
-    },
     "node_modules/array.prototype.findlastindex": {
-      "version": "1.2.4",
-      "resolved": 
"https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz";,
-      "integrity": 
"sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==",
+      "version": "1.2.5",
+      "resolved": 
"https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz";,
+      "integrity": 
"sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.5",
+        "call-bind": "^1.0.7",
         "define-properties": "^1.2.1",
-        "es-abstract": "^1.22.3",
+        "es-abstract": "^1.23.2",
         "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.0.0",
         "es-shim-unscopables": "^1.0.2"
       },
       "engines": {
@@ -1308,9 +1215,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001594",
-      "resolved": 
"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz";,
-      "integrity": 
"sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==",
+      "version": "1.0.30001600",
+      "resolved": 
"https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz";,
+      "integrity": 
"sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==",
       "dev": true,
       "funding": [
         {
@@ -1470,6 +1377,11 @@
         "node": ">= 8"
       }
     },
+    "node_modules/cross-spawn/node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz";,
+      "integrity": 
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+    },
     "node_modules/cross-spawn/node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz";,
@@ -1484,6 +1396,57 @@
         "node": ">= 8"
       }
     },
+    "node_modules/data-view-buffer": {
+      "version": "1.0.1",
+      "resolved": 
"https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz";,
+      "integrity": 
"sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.6",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb";
+      }
+    },
+    "node_modules/data-view-byte-length": {
+      "version": "1.0.1",
+      "resolved": 
"https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz";,
+      "integrity": 
"sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.7",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb";
+      }
+    },
+    "node_modules/data-view-byte-offset": {
+      "version": "1.0.0",
+      "resolved": 
"https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz";,
+      "integrity": 
"sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.6",
+        "es-errors": "^1.3.0",
+        "is-data-view": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb";
+      }
+    },
     "node_modules/debug": {
       "version": "4.3.4",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz";,
@@ -1595,9 +1558,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.693",
-      "resolved": 
"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.693.tgz";,
-      "integrity": 
"sha512-/if4Ueg0GUQlhCrW2ZlXwDAm40ipuKo+OgeHInlL8sbjt+hzISxZK949fZeJaVsheamrzANXvw1zQTvbxTvSHw==",
+      "version": "1.4.719",
+      "resolved": 
"https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.719.tgz";,
+      "integrity": 
"sha512-FbWy2Q2YgdFzkFUW/W5jBjE9dj+804+98E4Pup78JBPnbdb3pv6IneY2JCPKdeKLh3AOKHQeYf+KwLr7mxGh6Q==",
       "dev": true
     },
     "node_modules/elementtree": {
@@ -1641,17 +1604,21 @@
       }
     },
     "node_modules/es-abstract": {
-      "version": "1.22.5",
-      "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz";,
-      "integrity": 
"sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==",
+      "version": "1.23.2",
+      "resolved": 
"https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz";,
+      "integrity": 
"sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==",
       "dev": true,
       "dependencies": {
         "array-buffer-byte-length": "^1.0.1",
         "arraybuffer.prototype.slice": "^1.0.3",
         "available-typed-arrays": "^1.0.7",
         "call-bind": "^1.0.7",
+        "data-view-buffer": "^1.0.1",
+        "data-view-byte-length": "^1.0.1",
+        "data-view-byte-offset": "^1.0.0",
         "es-define-property": "^1.0.0",
         "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.0.0",
         "es-set-tostringtag": "^2.0.3",
         "es-to-primitive": "^1.2.1",
         "function.prototype.name": "^1.1.6",
@@ -1662,10 +1629,11 @@
         "has-property-descriptors": "^1.0.2",
         "has-proto": "^1.0.3",
         "has-symbols": "^1.0.3",
-        "hasown": "^2.0.1",
+        "hasown": "^2.0.2",
         "internal-slot": "^1.0.7",
         "is-array-buffer": "^3.0.4",
         "is-callable": "^1.2.7",
+        "is-data-view": "^1.0.1",
         "is-negative-zero": "^2.0.3",
         "is-regex": "^1.1.4",
         "is-shared-array-buffer": "^1.0.3",
@@ -1676,17 +1644,17 @@
         "object-keys": "^1.1.1",
         "object.assign": "^4.1.5",
         "regexp.prototype.flags": "^1.5.2",
-        "safe-array-concat": "^1.1.0",
+        "safe-array-concat": "^1.1.2",
         "safe-regex-test": "^1.0.3",
-        "string.prototype.trim": "^1.2.8",
-        "string.prototype.trimend": "^1.0.7",
+        "string.prototype.trim": "^1.2.9",
+        "string.prototype.trimend": "^1.0.8",
         "string.prototype.trimstart": "^1.0.7",
         "typed-array-buffer": "^1.0.2",
         "typed-array-byte-length": "^1.0.1",
         "typed-array-byte-offset": "^1.0.2",
         "typed-array-length": "^1.0.5",
         "unbox-primitive": "^1.0.2",
-        "which-typed-array": "^1.1.14"
+        "which-typed-array": "^1.1.15"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1695,12 +1663,6 @@
         "url": "https://github.com/sponsors/ljharb";
       }
     },
-    "node_modules/es-array-method-boxes-properly": {
-      "version": "1.0.0",
-      "resolved": 
"https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz";,
-      "integrity": 
"sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
-      "dev": true
-    },
     "node_modules/es-define-property": {
       "version": "1.0.0",
       "resolved": 
"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz";,
@@ -1722,6 +1684,18 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/es-object-atoms": {
+      "version": "1.0.0",
+      "resolved": 
"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz";,
+      "integrity": 
"sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+      "dev": true,
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/es-set-tostringtag": {
       "version": "2.0.3",
       "resolved": 
"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz";,
@@ -2724,9 +2698,9 @@
       }
     },
     "node_modules/hasown": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz";,
-      "integrity": 
"sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz";,
+      "integrity": 
"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
       "dependencies": {
         "function-bind": "^1.1.2"
       },
@@ -2844,30 +2818,11 @@
         "node": ">=6"
       }
     },
-    "node_modules/ios-sim/node_modules/abbrev": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz";,
-      "integrity": 
"sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
-    },
     "node_modules/ios-sim/node_modules/bplist-parser": {
       "version": "0.0.6",
       "resolved": 
"https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.0.6.tgz";,
       "integrity": 
"sha512-fGeghPEH4Eytvf+Mi446aKcDqvkA/+eh6r7QGiZWMQG6TzqrnsToLP379XFfqRSZ41+676hhGIm++maNST1Apw=="
     },
-    "node_modules/ios-sim/node_modules/nopt": {
-      "version": "1.0.9",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.9.tgz";,
-      "integrity": 
"sha512-CmUZ3rzN0/4kRHum5pGRiGkhmBMzgtEDxrZVHqRJDSv8qK6s+wzaig/xeyB22Due5aZQeTiEZg/nrmMH2tapDQ==",
-      "dependencies": {
-        "abbrev": "1"
-      },
-      "bin": {
-        "nopt": "bin/nopt.js"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
     "node_modules/is-array-buffer": {
       "version": "3.0.4",
       "resolved": 
"https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz";,
@@ -2935,6 +2890,21 @@
         "url": "https://github.com/sponsors/ljharb";
       }
     },
+    "node_modules/is-data-view": {
+      "version": "1.0.1",
+      "resolved": 
"https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz";,
+      "integrity": 
"sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+      "dev": true,
+      "dependencies": {
+        "is-typed-array": "^1.1.13"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb";
+      }
+    },
     "node_modules/is-date-object": {
       "version": "1.0.5",
       "resolved": 
"https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz";,
@@ -3143,9 +3113,12 @@
       "dev": true
     },
     "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz";,
-      "integrity": 
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz";,
+      "integrity": 
"sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
+      "engines": {
+        "node": ">=16"
+      }
     },
     "node_modules/istanbul-lib-coverage": {
       "version": "3.2.2",
@@ -3552,17 +3525,17 @@
       "dev": true
     },
     "node_modules/nopt": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz";,
-      "integrity": 
"sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==",
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.9.tgz";,
+      "integrity": 
"sha512-CmUZ3rzN0/4kRHum5pGRiGkhmBMzgtEDxrZVHqRJDSv8qK6s+wzaig/xeyB22Due5aZQeTiEZg/nrmMH2tapDQ==",
       "dependencies": {
-        "abbrev": "^2.0.0"
+        "abbrev": "1"
       },
       "bin": {
         "nopt": "bin/nopt.js"
       },
       "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+        "node": "*"
       }
     },
     "node_modules/npm-run-path": {
@@ -3715,14 +3688,15 @@
       }
     },
     "node_modules/object.fromentries": {
-      "version": "2.0.7",
-      "resolved": 
"https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz";,
-      "integrity": 
"sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+      "version": "2.0.8",
+      "resolved": 
"https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz";,
+      "integrity": 
"sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1"
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.2",
+        "es-object-atoms": "^1.0.0"
       },
       "engines": {
         "node": ">= 0.4"
@@ -3732,27 +3706,28 @@
       }
     },
     "node_modules/object.groupby": {
-      "version": "1.0.2",
-      "resolved": 
"https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz";,
-      "integrity": 
"sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==",
+      "version": "1.0.3",
+      "resolved": 
"https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz";,
+      "integrity": 
"sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
       "dev": true,
       "dependencies": {
-        "array.prototype.filter": "^1.0.3",
-        "call-bind": "^1.0.5",
+        "call-bind": "^1.0.7",
         "define-properties": "^1.2.1",
-        "es-abstract": "^1.22.3",
-        "es-errors": "^1.0.0"
+        "es-abstract": "^1.23.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
       }
     },
     "node_modules/object.values": {
-      "version": "1.1.7",
-      "resolved": 
"https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz";,
-      "integrity": 
"sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+      "version": "1.2.0",
+      "resolved": 
"https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz";,
+      "integrity": 
"sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1"
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0"
       },
       "engines": {
         "node": ">= 0.4"
@@ -4516,13 +4491,13 @@
       }
     },
     "node_modules/safe-array-concat": {
-      "version": "1.1.0",
-      "resolved": 
"https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz";,
-      "integrity": 
"sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
+      "version": "1.1.2",
+      "resolved": 
"https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz";,
+      "integrity": 
"sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.5",
-        "get-intrinsic": "^1.2.2",
+        "call-bind": "^1.0.7",
+        "get-intrinsic": "^1.2.4",
         "has-symbols": "^1.0.3",
         "isarray": "^2.0.5"
       },
@@ -4592,17 +4567,17 @@
       "dev": true
     },
     "node_modules/set-function-length": {
-      "version": "1.2.1",
-      "resolved": 
"https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz";,
-      "integrity": 
"sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
+      "version": "1.2.2",
+      "resolved": 
"https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz";,
+      "integrity": 
"sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
       "dev": true,
       "dependencies": {
-        "define-data-property": "^1.1.2",
+        "define-data-property": "^1.1.4",
         "es-errors": "^1.3.0",
         "function-bind": "^1.1.2",
-        "get-intrinsic": "^1.2.3",
+        "get-intrinsic": "^1.2.4",
         "gopd": "^1.0.1",
-        "has-property-descriptors": "^1.0.1"
+        "has-property-descriptors": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -4763,6 +4738,12 @@
         "node": ">=8"
       }
     },
+    "node_modules/spawn-wrap/node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz";,
+      "integrity": 
"sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
     "node_modules/spawn-wrap/node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz";,
@@ -4807,14 +4788,15 @@
       }
     },
     "node_modules/string.prototype.trim": {
-      "version": "1.2.8",
-      "resolved": 
"https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz";,
-      "integrity": 
"sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+      "version": "1.2.9",
+      "resolved": 
"https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz";,
+      "integrity": 
"sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1"
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.23.0",
+        "es-object-atoms": "^1.0.0"
       },
       "engines": {
         "node": ">= 0.4"
@@ -4824,28 +4806,31 @@
       }
     },
     "node_modules/string.prototype.trimend": {
-      "version": "1.0.7",
-      "resolved": 
"https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz";,
-      "integrity": 
"sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+      "version": "1.0.8",
+      "resolved": 
"https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz";,
+      "integrity": 
"sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1"
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb";
       }
     },
     "node_modules/string.prototype.trimstart": {
-      "version": "1.0.7",
-      "resolved": 
"https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz";,
-      "integrity": 
"sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+      "version": "1.0.8",
+      "resolved": 
"https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz";,
+      "integrity": 
"sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.2.0",
-        "es-abstract": "^1.22.1"
+        "call-bind": "^1.0.7",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb";
@@ -4915,9 +4900,9 @@
       }
     },
     "node_modules/table": {
-      "version": "6.8.1",
-      "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz";,
-      "integrity": 
"sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+      "version": "6.8.2",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz";,
+      "integrity": 
"sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==",
       "dev": true,
       "dependencies": {
         "ajv": "^8.0.1",
@@ -5120,9 +5105,9 @@
       }
     },
     "node_modules/typed-array-length": {
-      "version": "1.0.5",
-      "resolved": 
"https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz";,
-      "integrity": 
"sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==",
+      "version": "1.0.6",
+      "resolved": 
"https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz";,
+      "integrity": 
"sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
       "dev": true,
       "dependencies": {
         "call-bind": "^1.0.7",
@@ -5171,14 +5156,6 @@
         "node": ">= 10.0.0"
       }
     },
-    "node_modules/unorm": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz";,
-      "integrity": 
"sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==",
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
     "node_modules/update-browserslist-db": {
       "version": "1.0.13",
       "resolved": 
"https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz";,
@@ -5234,17 +5211,17 @@
       "dev": true
     },
     "node_modules/which": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz";,
-      "integrity": 
"sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz";,
+      "integrity": 
"sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
       "dependencies": {
-        "isexe": "^2.0.0"
+        "isexe": "^3.1.1"
       },
       "bin": {
         "node-which": "bin/which.js"
       },
       "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+        "node": "^16.13.0 || >=18.0.0"
       }
     },
     "node_modules/which-boxed-primitive": {
@@ -5270,16 +5247,16 @@
       "dev": true
     },
     "node_modules/which-typed-array": {
-      "version": "1.1.14",
-      "resolved": 
"https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz";,
-      "integrity": 
"sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==",
+      "version": "1.1.15",
+      "resolved": 
"https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz";,
+      "integrity": 
"sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
       "dev": true,
       "dependencies": {
-        "available-typed-arrays": "^1.0.6",
-        "call-bind": "^1.0.5",
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.7",
         "for-each": "^0.3.3",
         "gopd": "^1.0.1",
-        "has-tostringtag": "^1.0.1"
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
diff --git a/package.json b/package.json
index 6673bccf..2beca612 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
   "author": "Apache Software Foundation",
   "license": "Apache-2.0",
   "devDependencies": {
-    "@cordova/eslint-config": "^5.0.0",
+    "@cordova/eslint-config": "^5.1.0",
     "cordova-js": "^6.1.0",
     "jasmine": "^4.6.0",
     "nyc": "^15.1.0",
@@ -43,13 +43,10 @@
   "dependencies": {
     "cordova-common": "^5.0.0",
     "execa": "^5.1.1",
-    "fs-extra": "^11.1.1",
     "ios-sim": "^8.0.2",
-    "nopt": "^7.1.0",
     "plist": "^3.0.6",
     "semver": "^7.4.0",
-    "unorm": "^1.6.0",
-    "which": "^3.0.1",
+    "which": "^4.0.0",
     "xcode": "^3.0.1",
     "xml-escape": "^1.1.0",
     "elementtree": "^0.1.7"
diff --git a/tests/spec/createAndBuild.spec.js 
b/tests/spec/createAndBuild.spec.js
index ff2f7992..1d858d24 100644
--- a/tests/spec/createAndBuild.spec.js
+++ b/tests/spec/createAndBuild.spec.js
@@ -17,9 +17,9 @@
  under the License.
  */
 
-const fs = require('fs-extra');
-const os = require('os');
-const path = require('path');
+const fs = require('node:fs');
+const os = require('node:os');
+const path = require('node:path');
 const xcode = require('xcode');
 const create = require('../../lib/create');
 
@@ -50,7 +50,7 @@ function verifyProjectFiles (tmpDir, projectName) {
  * @param {String} expectedBundleIdentifier
  */
 function verifyProjectBundleIdentifier (tmpDir, projectName, 
expectedBundleIdentifier) {
-    const pbxproj = path.join(tmpDir, 
`${projectName}.xcodeproj/project.pbxproj`);
+    const pbxproj = path.join(tmpDir, `${projectName}.xcodeproj`, 
'project.pbxproj');
     const xcodeproj = xcode.project(pbxproj);
     xcodeproj.parseSync();
     const actualBundleIdentifier = 
xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER');
@@ -65,13 +65,14 @@ function verifyProjectBundleIdentifier (tmpDir, 
projectName, expectedBundleIdent
  */
 function verifyBuild (tmpDir) {
     // Allow test project to find the `cordova-ios` module
-    fs.ensureSymlinkSync(
-        path.join(__dirname, '../..'),
-        path.join(tmpDir, 'node_modules/cordova-ios'),
+    fs.mkdirSync(path.join(tmpDir, 'node_modules'), { recursive: true });
+    fs.symlinkSync(
+        path.join(__dirname, '..', '..'),
+        path.join(tmpDir, 'node_modules', 'cordova-ios'),
         'junction'
     );
 
-    const Api = require(path.join(tmpDir, 'cordova/Api.js'));
+    const Api = require(path.join(tmpDir, 'cordova', 'Api.js'));
 
     return expectAsync(new Api('ios', tmpDir).build({ emulator: true }))
         .toBeResolved();
@@ -100,7 +101,7 @@ describe('create', () => {
     });
 
     afterEach(() => {
-        fs.removeSync(tmpDir);
+        fs.rmSync(tmpDir, { recursive: true, force: true });
     });
 
     it('Test#001 : create project with ascii name, no spaces', () => {
diff --git a/tests/spec/unit/Api.spec.js b/tests/spec/unit/Api.spec.js
index 9d383557..fe8b7a43 100644
--- a/tests/spec/unit/Api.spec.js
+++ b/tests/spec/unit/Api.spec.js
@@ -17,9 +17,9 @@
  under the License.
  */
 
-const path = require('path');
-const fs = require('fs-extra');
-const EventEmitter = require('events');
+const path = require('node:path');
+const fs = require('node:fs');
+const EventEmitter = require('node:events');
 const PluginManager = require('cordova-common').PluginManager;
 const Api = require('../../../lib/Api');
 const check_reqs = require('../../../lib/check_reqs');
diff --git a/tests/spec/unit/BridgingHeader.spec.js 
b/tests/spec/unit/BridgingHeader.spec.js
index f57af790..48d33776 100644
--- a/tests/spec/unit/BridgingHeader.spec.js
+++ b/tests/spec/unit/BridgingHeader.spec.js
@@ -17,10 +17,10 @@
  under the License.
  */
 
-const fs = require('fs-extra');
-const path = require('path');
+const fs = require('node:fs');
+const path = require('node:path');
 
-const BridgingHeader = require(path.resolve(path.join(__dirname, 
'../../../lib/BridgingHeader.js'))).BridgingHeader;
+const BridgingHeader = require(path.resolve(__dirname, '..', '..', '..', 
'lib', 'BridgingHeader.js')).BridgingHeader;
 const fixtureBridgingHeader = fs.readFileSync(path.resolve(__dirname, 
'fixtures', 'test-Bridging-Header.h'), 'utf-8');
 
 describe('unit tests for BridgingHeader module', () => {
diff --git a/tests/spec/unit/Plugman/common.spec.js 
b/tests/spec/unit/Plugman/common.spec.js
index 5b70a6e6..3621b4b7 100644
--- a/tests/spec/unit/Plugman/common.spec.js
+++ b/tests/spec/unit/Plugman/common.spec.js
@@ -16,9 +16,9 @@
  *
 */
 
-const fs = require('fs-extra');
-const path = require('path');
-const osenv = require('os');
+const fs = require('node:fs');
+const path = require('node:path');
+const osenv = require('node:os');
 const rewire = require('rewire');
 
 const common = rewire('../../../../lib/plugman/pluginHandlers');
@@ -39,22 +39,22 @@ const removeFileAndParents = 
common.__get__('removeFileAndParents');
 describe('common handler routines', () => {
     describe('copyFile', () => {
         it('Test 001 : should throw if source path not found', () => {
-            fs.removeSync(test_dir);
+            fs.rmSync(test_dir, { recursive: true, force: true });
             expect(() => { copyFile(test_dir, src, project_dir, dest); })
                 .toThrow(new Error(`"${src}" not found!`));
         });
 
         it('Test 002 : should throw if src not in plugin directory', () => {
-            fs.ensureDirSync(project_dir);
+            fs.mkdirSync(project_dir, { recursive: true });
             fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
             const outside_file = '../non_plugin_file';
             expect(() => { copyFile(test_dir, outside_file, project_dir, 
dest); })
                 .toThrow(new Error(`File "${path.resolve(test_dir, 
outside_file)}" is located outside the plugin directory "${test_dir}"`));
-            fs.removeSync(test_dir);
+            fs.rmSync(test_dir, { recursive: true, force: true });
         });
 
         it('Test 003 : should allow symlink src, if inside plugin', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             // This will fail on windows if not admin - ignore the error in 
that case.
@@ -63,11 +63,11 @@ describe('common handler routines', () => {
             }
 
             copyFile(test_dir, symlink_file, project_dir, dest);
-            fs.removeSync(project_dir);
+            fs.rmSync(project_dir, { recursive: true, force: true });
         });
 
         it('Test 004 : should throw if symlink is linked to a file outside the 
plugin', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
 
             // This will fail on windows if not admin - ignore the error in 
that case.
@@ -77,70 +77,70 @@ describe('common handler routines', () => {
 
             expect(() => { copyFile(test_dir, symlink_file, project_dir, 
dest); })
                 .toThrow(new Error(`File "${path.resolve(test_dir, 
symlink_file)}" is located outside the plugin directory "${test_dir}"`));
-            fs.removeSync(project_dir);
+            fs.rmSync(project_dir, { recursive: true, force: true });
         });
 
         it('Test 005 : should throw if dest is outside the project directory', 
() => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
             expect(() => { copyFile(test_dir, srcFile, project_dir, 
non_plugin_file); })
                 .toThrow(new Error(`Destination "${path.resolve(project_dir, 
non_plugin_file)}" for source file "${path.resolve(test_dir, srcFile)}" is 
located outside the project`));
-            fs.removeSync(project_dir);
+            fs.rmSync(project_dir, { recursive: true, force: true });
         });
 
         it('Test 006 : should call mkdir -p on target path', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
-            const s = spyOn(fs, 'ensureDirSync').and.callThrough();
+            const s = spyOn(fs, 'mkdirSync').and.callThrough();
             const resolvedDest = path.resolve(project_dir, dest);
 
             copyFile(test_dir, srcFile, project_dir, dest);
 
             expect(s).toHaveBeenCalled();
-            expect(s).toHaveBeenCalledWith(path.dirname(resolvedDest));
-            fs.removeSync(project_dir);
+            expect(s).toHaveBeenCalledWith(path.dirname(resolvedDest), { 
recursive: true });
+            fs.rmSync(project_dir, { recursive: true, force: true });
         });
 
         it('Test 007 : should call cp source/dest paths', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
-            spyOn(fs, 'copySync').and.callThrough();
+            spyOn(fs, 'cpSync').and.callThrough();
             const resolvedDest = path.resolve(project_dir, dest);
 
             copyFile(test_dir, srcFile, project_dir, dest);
 
-            expect(fs.copySync).toHaveBeenCalled();
-            expect(fs.copySync).toHaveBeenCalledWith(srcFile, resolvedDest);
+            expect(fs.cpSync).toHaveBeenCalled();
+            expect(fs.cpSync).toHaveBeenCalledWith(srcFile, resolvedDest, { 
recursive: true });
 
-            fs.removeSync(project_dir);
+            fs.rmSync(project_dir, { recursive: true, force: true });
         });
     });
 
     describe('copyNewFile', () => {
         it('Test 008 : should throw if target path exists', () => {
-            fs.ensureDirSync(dest);
+            fs.mkdirSync(dest, { recursive: true });
             expect(() => { copyNewFile(test_dir, src, project_dir, dest); })
                 .toThrow(new Error(`"${dest}" already exists!`));
-            fs.removeSync(dest);
+            fs.rmSync(dest, { recursive: true, force: true });
         });
     });
 
     describe('deleteJava', () => {
         it('Test 009 : source file should have been removed', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             expect(fs.existsSync(srcFile)).toBe(true);
             removeFileAndParents(project_dir, srcFile);
             expect(fs.existsSync(srcFile)).toBe(false);
 
-            fs.removeSync(srcDirTree);
+            fs.rmSync(srcDirTree, { recursive: true, force: true });
         });
 
         it('Test 010 : should delete empty directories after removing source 
code in path hierarchy', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             removeFileAndParents(project_dir, srcFile);
@@ -148,17 +148,17 @@ describe('common handler routines', () => {
             expect(fs.existsSync(srcDirTree)).not.toBe(true);
             expect(fs.existsSync(path.join(src, 'one'))).not.toBe(true);
 
-            fs.removeSync(srcDirTree);
+            fs.rmSync(srcDirTree, { recursive: true, force: true });
         });
 
         it('Test 011 : should delete the top-level src directory if all 
plugins added were removed', () => {
-            fs.ensureDirSync(srcDirTree);
+            fs.mkdirSync(srcDirTree, { recursive: true });
             fs.writeFileSync(srcFile, 'contents', 'utf-8');
 
             removeFileAndParents(project_dir, srcFile);
             expect(fs.existsSync(src)).toBe(false);
 
-            fs.removeSync(srcDirTree);
+            fs.rmSync(srcDirTree, { recursive: true, force: true });
         });
     });
 });
diff --git a/tests/spec/unit/Plugman/pluginHandler.spec.js 
b/tests/spec/unit/Plugman/pluginHandler.spec.js
index b911ca7d..682a5f94 100644
--- a/tests/spec/unit/Plugman/pluginHandler.spec.js
+++ b/tests/spec/unit/Plugman/pluginHandler.spec.js
@@ -17,11 +17,11 @@
     under the License.
 */
 
-const os = require('os');
-const fs = require('fs-extra');
-const path = require('path');
+const os = require('node:os');
+const fs = require('node:fs');
+const path = require('node:path');
 const rewire = require('rewire');
-const EventEmitter = require('events');
+const EventEmitter = require('node:events');
 
 const PluginInfo = require('cordova-common').PluginInfo;
 const Api = require('../../../../lib/Api');
@@ -30,7 +30,7 @@ const pluginHandlers = 
rewire('../../../../lib/plugman/pluginHandlers');
 
 const temp = path.join(os.tmpdir(), 'plugman');
 
-const FIXTURES = path.join(__dirname, '../fixtures');
+const FIXTURES = path.join(__dirname, '..', 'fixtures');
 const iosProject = path.join(FIXTURES, 'ios-config-xml');
 const faultyplugin = path.join(FIXTURES, 'org.test.plugins.faultyplugin');
 const dummyplugin = path.join(FIXTURES, 'org.test.plugins.dummyplugin');
@@ -71,17 +71,17 @@ describe('ios plugin handler', () => {
     let dummyProject;
 
     beforeEach(() => {
-        fs.copySync(iosProject, temp);
+        fs.cpSync(iosProject, temp, { recursive: true });
         projectFile.purgeProjectFileCache(temp);
 
         dummyProject = projectFile.parse({
             root: temp,
-            pbxproj: path.join(temp, 'SampleApp.xcodeproj/project.pbxproj')
+            pbxproj: path.join(temp, 'SampleApp.xcodeproj', 'project.pbxproj')
         });
     });
 
     afterEach(() => {
-        fs.removeSync(temp);
+        fs.rmSync(temp, { recursive: true, force: true });
     });
 
     describe('installation', () => {
@@ -101,7 +101,7 @@ describe('ios plugin handler', () => {
             it('Test 002 : should throw if source-file target already exists', 
() => {
                 const source = copyArray(valid_source);
                 const target = path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'DummyPluginCommand.m');
-                fs.ensureDirSync(path.dirname(target));
+                fs.mkdirSync(path.dirname(target), { recursive: true });
                 fs.writeFileSync(target, 'some bs', 'utf-8');
                 expect(() => {
                     install(source[0], dummyPluginInfo, dummyProject);
@@ -121,15 +121,15 @@ describe('ios plugin handler', () => {
             });
             it('Test 005 : should cp the file to the right target location 
when element has no target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 install(source[0], dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 
'DummyPluginCommand.m'));
+                expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 
'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'DummyPluginCommand.m'), { recursive: true });
             });
             it('Test 006 : should cp the file to the right target location 
when element has a target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
!== undefined);
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 install(source[0], dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 
'targetDir', 'TargetDirTest.m'));
+                expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 
'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'targetDir', 'TargetDirTest.m'), { recursive: true });
             });
             it('Test 007 : should call into xcodeproj\'s addFramework 
appropriately when element has framework=true set', () => {
                 const source = copyArray(valid_source).filter(s => 
s.framework);
@@ -156,7 +156,7 @@ describe('ios plugin handler', () => {
             it('Test 009 : should throw if header-file target already exists', 
() => {
                 const headers = copyArray(valid_headers);
                 const target = path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'DummyPluginCommand.h');
-                fs.ensureDirSync(path.dirname(target));
+                fs.mkdirSync(path.dirname(target), { recursive: true });
                 fs.writeFileSync(target, 'some bs', 'utf-8');
                 expect(() => {
                     install(headers[0], dummyPluginInfo, dummyProject);
@@ -176,15 +176,15 @@ describe('ios plugin handler', () => {
             });
             it('Test 012 : should cp the file to the right target location 
when element has no target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir === undefined);
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 install(headers[0], dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 
'DummyPluginCommand.h'));
+                expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 
'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'DummyPluginCommand.h'), { recursive: true });
             });
             it('Test 013 : should cp the file to the right target location 
when element has a target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir !== undefined);
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 install(headers[0], dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 
'targetDir', 'TargetDirTest.h'));
+                expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 
'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', 
dummy_id, 'targetDir', 'TargetDirTest.h'), { recursive: true });
             });
         });
 
@@ -199,12 +199,12 @@ describe('ios plugin handler', () => {
                 const resources = copyArray(invalid_resources);
                 expect(() => {
                     install(resources[0], faultyPluginInfo, dummyProject);
-                }).toThrow(new Error(`Cannot find resource file 
"${path.resolve(faultyplugin, 'src/ios/IDontExist.bundle')}" for plugin 
${faultyPluginInfo.id} in iOS platform`));
+                }).toThrow(new Error(`Cannot find resource file 
"${path.resolve(faultyplugin, 'src', 'ios', 'IDontExist.bundle')}" for plugin 
${faultyPluginInfo.id} in iOS platform`));
             });
             it('Test 015 : should throw if resource-file target already 
exists', () => {
                 const resources = copyArray(valid_resources);
                 const target = path.join(temp, 'SampleApp', 'Resources', 
'DummyPlugin.bundle');
-                fs.ensureDirSync(path.dirname(target));
+                fs.mkdirSync(path.dirname(target), { recursive: true });
                 fs.writeFileSync(target, 'some bs', 'utf-8');
                 expect(() => {
                     install(resources[0], dummyPluginInfo, dummyProject);
@@ -218,9 +218,9 @@ describe('ios plugin handler', () => {
             });
             it('Test 017 : should cp the file to the right target location', 
() => {
                 const resources = copyArray(valid_resources);
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 install(resources[0], dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources', 
'DummyPlugin.bundle'));
+                expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 
'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources', 
'DummyPlugin.bundle'), { recursive: true });
             });
 
             it('Test 018 : should link files to the right target location', () 
=> {
@@ -228,7 +228,7 @@ describe('ios plugin handler', () => {
                 const spy = spyOn(fs, 'linkSync');
                 install(resources[0], dummyPluginInfo, dummyProject, { link: 
true });
                 const src_bundle = path.join(dummyplugin, 'src', 'ios', 
'DummyPlugin.bundle');
-                const dest_bundle = path.join(temp, 
'SampleApp/Resources/DummyPlugin.bundle');
+                const dest_bundle = path.join(temp, 'SampleApp', 'Resources', 
'DummyPlugin.bundle');
                 expect(spy).toHaveBeenCalledWith(src_bundle, dest_bundle);
             });
         });
@@ -265,22 +265,22 @@ describe('ios plugin handler', () => {
                     const frameworks = copyArray(invalid_custom_frameworks);
                     expect(() => {
                         install(frameworks[0], faultyPluginInfo, dummyProject);
-                    }).toThrow(new Error(`Cannot find framework 
"${path.resolve(faultyplugin, 'src/ios/NonExistantCustomFramework.framework')}" 
for plugin ${faultyPluginInfo.id} in iOS platform`));
+                    }).toThrow(new Error(`Cannot find framework 
"${path.resolve(faultyplugin, 'src', 'ios', 
'NonExistantCustomFramework.framework')}" for plugin ${faultyPluginInfo.id} in 
iOS platform`));
                 });
                 it('Test 021 : should throw if framework target already 
exists', () => {
                     const frameworks = copyArray(valid_custom_frameworks);
-                    const target = path.join(temp, 
'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework');
-                    fs.ensureDirSync(target);
+                    const target = path.join(temp, 'SampleApp', 'Plugins', 
'org.test.plugins.dummyplugin', 'Custom.framework');
+                    fs.mkdirSync(target, { recursive: true });
                     expect(() => {
                         install(frameworks[0], dummyPluginInfo, dummyProject);
                     }).toThrow(new Error(`Framework "${target}" for plugin 
${dummyPluginInfo.id} already exists in iOS platform`));
                 });
                 it('Test 022 : should cp the file to the right target 
location', () => {
                     const frameworks = copyArray(valid_custom_frameworks);
-                    spyOn(fs, 'copySync');
+                    spyOn(fs, 'cpSync');
                     install(frameworks[0], dummyPluginInfo, dummyProject);
-                    
expect(fs.copySync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'Custom.framework'),
-                        path.join(temp, 
'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework'));
+                    
expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 
'Custom.framework'),
+                        path.join(temp, 'SampleApp', 'Plugins', 
'org.test.plugins.dummyplugin', 'Custom.framework'), { recursive: true });
                 });
 
                 it('Test 023 : should deep symlink files to the right target 
location', () => {
@@ -288,7 +288,7 @@ describe('ios plugin handler', () => {
                     const spy = spyOn(fs, 'linkSync');
                     install(frameworks[0], dummyPluginInfo, dummyProject, { 
link: true });
                     const src_binlib = path.join(dummyplugin, 'src', 'ios', 
'Custom.framework', 'somebinlib');
-                    const dest_binlib = path.join(temp, 
'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework/somebinlib');
+                    const dest_binlib = path.join(temp, 'SampleApp', 
'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework', 'somebinlib');
                     expect(spy).toHaveBeenCalledWith(src_binlib, dest_binlib);
                 });
             });
@@ -374,21 +374,21 @@ describe('ios plugin handler', () => {
             /* eslint-enable no-unused-vars */
 
             beforeEach(() => {
-                spyOn(fs, 'copySync');
+                spyOn(fs, 'cpSync');
                 wwwDest = path.resolve(dummyProject.www, asset.target);
                 platformWwwDest = path.resolve(dummyProject.platformWww, 
asset.target);
             });
 
             it('Test 026 : should put asset to both www and platform_www when 
options.usePlatformWww flag is specified', () => {
                 install(asset, dummyPluginInfo, dummyProject, { 
usePlatformWww: true });
-                
expect(fs.copySync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.www, asset.target));
-                
expect(fs.copySync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.platformWww, asset.target));
+                
expect(fs.cpSync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.www, asset.target), { recursive: true });
+                
expect(fs.cpSync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.platformWww, asset.target), { recursive: 
true });
             });
 
             it('Test 027 : should put asset to www only when 
options.usePlatformWww flag is not specified', () => {
                 install(asset, dummyPluginInfo, dummyProject);
-                
expect(fs.copySync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.www, asset.target));
-                
expect(fs.copySync).not.toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.platformWww, asset.target));
+                
expect(fs.cpSync).toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.www, asset.target), { recursive: true });
+                
expect(fs.cpSync).not.toHaveBeenCalledWith(path.resolve(dummyPluginInfo.dir, 
asset.src), path.resolve(dummyProject.platformWww, asset.target), { recursive: 
true });
             });
         });
 
@@ -400,7 +400,7 @@ describe('ios plugin handler', () => {
                 .then(() => {
                     const xcode = projectFile.parse({
                         root: temp,
-                        pbxproj: path.join(temp, 
'SampleApp.xcodeproj/project.pbxproj')
+                        pbxproj: path.join(temp, 'SampleApp.xcodeproj', 
'project.pbxproj')
                     }).xcode;
 
                     // from org.test.plugins.dummyplugin
@@ -440,15 +440,15 @@ describe('ios plugin handler', () => {
             });
             it('Test 031 : should rm the file from the right target location 
when element has no target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
-                const spy = spyOn(fs, 'removeSync');
+                const spy = spyOn(fs, 'rmSync');
                 uninstall(source[0], dummyPluginInfo, dummyProject);
-                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id));
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id), { recursive: true, force: true });
             });
             it('Test 032 : should rm the file from the right target location 
when element has a target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
!== undefined);
-                const spy = spyOn(fs, 'removeSync');
+                const spy = spyOn(fs, 'rmSync');
                 uninstall(source[0], dummyPluginInfo, dummyProject);
-                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id, 'targetDir'));
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true });
             });
             it('Test 033 : should call into xcodeproj\'s removeFramework 
appropriately when element framework=true set', () => {
                 const source = copyArray(valid_source).filter(s => 
s.framework);
@@ -475,9 +475,9 @@ describe('ios plugin handler', () => {
             });
             it('Test 036 : should rm the file from the right target location', 
() => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir !== undefined);
-                const spy = spyOn(fs, 'removeSync');
+                const spy = spyOn(fs, 'rmSync');
                 uninstall(headers[0], dummyPluginInfo, dummyProject);
-                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id, 'targetDir'));
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true });
             });
         });
 
@@ -494,9 +494,9 @@ describe('ios plugin handler', () => {
             });
             it('Test 038 : should rm the file from the right target location', 
() => {
                 const resources = copyArray(valid_resources);
-                const spy = spyOn(fs, 'removeSync');
+                const spy = spyOn(fs, 'rmSync');
                 uninstall(resources[0], dummyPluginInfo, dummyProject);
-                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Resources', 'DummyPlugin.bundle'));
+                expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 
'Resources', 'DummyPlugin.bundle'), { recursive: true, force: true });
             });
         });
 
@@ -521,9 +521,9 @@ describe('ios plugin handler', () => {
             describe('with custom="true" attribute', () => {
                 it('Test 040 : should rm the file from the right target 
location', () => {
                     const frameworks = copyArray(valid_custom_frameworks);
-                    const spy = spyOn(fs, 'removeSync');
+                    const spy = spyOn(fs, 'rmSync');
                     uninstall(frameworks[0], dummyPluginInfo, dummyProject);
-                    expect(spy).toHaveBeenCalledWith(frameworkPath);
+                    expect(spy).toHaveBeenCalledWith(frameworkPath, { 
recursive: true, force: true });
                 });
             });
 
@@ -554,7 +554,7 @@ describe('ios plugin handler', () => {
                 wwwDest = path.resolve(dummyProject.www, 'plugins', 
dummyPluginInfo.id, jsModule.src);
                 platformWwwDest = path.resolve(dummyProject.platformWww, 
'plugins', dummyPluginInfo.id, jsModule.src);
 
-                spyOn(fs, 'removeSync');
+                spyOn(fs, 'rmSync');
 
                 const existsSyncOrig = fs.existsSync;
                 spyOn(fs, 'existsSync').and.callFake(file => {
@@ -565,14 +565,14 @@ describe('ios plugin handler', () => {
 
             it('Test 042 : should put module to both www and platform_www when 
options.usePlatformWww flag is specified', () => {
                 uninstall(jsModule, dummyPluginInfo, dummyProject, { 
usePlatformWww: true });
-                expect(fs.removeSync).toHaveBeenCalledWith(wwwDest);
-                expect(fs.removeSync).toHaveBeenCalledWith(platformWwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(wwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(platformWwwDest);
             });
 
             it('Test 043 : should put module to www only when 
options.usePlatformWww flag is not specified', () => {
                 uninstall(jsModule, dummyPluginInfo, dummyProject);
-                expect(fs.removeSync).toHaveBeenCalledWith(wwwDest);
-                
expect(fs.removeSync).not.toHaveBeenCalledWith(platformWwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(wwwDest);
+                expect(fs.rmSync).not.toHaveBeenCalledWith(platformWwwDest);
             });
         });
 
@@ -586,7 +586,7 @@ describe('ios plugin handler', () => {
                 wwwDest = path.resolve(dummyProject.www, asset.target);
                 platformWwwDest = path.resolve(dummyProject.platformWww, 
asset.target);
 
-                spyOn(fs, 'removeSync');
+                spyOn(fs, 'rmSync');
 
                 const existsSyncOrig = fs.existsSync;
                 spyOn(fs, 'existsSync').and.callFake(file => {
@@ -597,14 +597,14 @@ describe('ios plugin handler', () => {
 
             it('Test 044 : should put module to both www and platform_www when 
options.usePlatformWww flag is specified', () => {
                 uninstall(asset, dummyPluginInfo, dummyProject, { 
usePlatformWww: true });
-                expect(fs.removeSync).toHaveBeenCalledWith(wwwDest);
-                expect(fs.removeSync).toHaveBeenCalledWith(platformWwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(wwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(platformWwwDest);
             });
 
             it('Test 045 : should put module to www only when 
options.usePlatformWww flag is not specified', () => {
                 uninstall(asset, dummyPluginInfo, dummyProject);
-                expect(fs.removeSync).toHaveBeenCalledWith(wwwDest);
-                
expect(fs.removeSync).not.toHaveBeenCalledWith(platformWwwDest);
+                expect(fs.rmSync).toHaveBeenCalledWith(wwwDest);
+                expect(fs.rmSync).not.toHaveBeenCalledWith(platformWwwDest);
             });
         });
     });
diff --git a/tests/spec/unit/Podfile.spec.js b/tests/spec/unit/Podfile.spec.js
index 7b43415a..27a05316 100644
--- a/tests/spec/unit/Podfile.spec.js
+++ b/tests/spec/unit/Podfile.spec.js
@@ -17,13 +17,13 @@
        under the License.
 */
 
-const path = require('path');
-const util = require('util');
-const fs = require('fs-extra');
+const path = require('node:path');
+const util = require('node:util');
+const fs = require('node:fs');
 const CordovaError = require('cordova-common').CordovaError;
 
 const PROJECT_NAME = 'testProj';
-const Podfile = require(path.resolve(path.join(__dirname, 
'../../../lib/Podfile.js'))).Podfile;
+const Podfile = require(path.resolve(__dirname, '..', '..', '..', 'lib', 
'Podfile.js')).Podfile;
 const fixturePodfile = path.resolve(__dirname, 'fixtures', PROJECT_NAME, 
'platforms', 'ios', 'Podfile');
 const fixturePodXcconfigDebug = path.resolve(__dirname, 'fixtures', 
PROJECT_NAME, 'platforms', 'ios', 'pods-debug.xcconfig');
 const fixturePodXcconfigRelease = path.resolve(__dirname, 'fixtures', 
PROJECT_NAME, 'platforms', 'ios', 'pods-release.xcconfig');
diff --git a/tests/spec/unit/PodsJson.spec.js b/tests/spec/unit/PodsJson.spec.js
index 891ffe77..424e012a 100644
--- a/tests/spec/unit/PodsJson.spec.js
+++ b/tests/spec/unit/PodsJson.spec.js
@@ -17,12 +17,12 @@
        under the License.
 */
 
-const fs = require('fs-extra');
-const path = require('path');
-const util = require('util');
+const fs = require('node:fs');
+const path = require('node:path');
+const util = require('node:util');
 const CordovaError = require('cordova-common').CordovaError;
 
-const PodsJson = require(path.resolve(path.join(__dirname, 
'../../../lib/PodsJson.js'))).PodsJson;
+const PodsJson = require(path.resolve(__dirname, '..', '..', '..', 'lib', 
'PodsJson.js')).PodsJson;
 const fixturePodsJson = path.resolve(__dirname, 'fixtures', 'testProj', 
'platforms', 'ios', 'pods.json');
 
 // tests are nested in a describe to ensure clean up happens after all unit 
tests are run
diff --git a/tests/spec/unit/build.spec.js b/tests/spec/unit/build.spec.js
index 0b1a9491..6e0b1da4 100644
--- a/tests/spec/unit/build.spec.js
+++ b/tests/spec/unit/build.spec.js
@@ -17,8 +17,8 @@
  under the License.
  */
 
-const path = require('path');
-const fs = require('fs-extra');
+const fs = require('node:fs');
+const path = require('node:path');
 const rewire = require('rewire');
 const { CordovaError, events } = require('cordova-common');
 const build = rewire('../../../lib/build');
diff --git a/tests/spec/unit/create.spec.js b/tests/spec/unit/create.spec.js
index bbbcdeeb..1b3bf170 100644
--- a/tests/spec/unit/create.spec.js
+++ b/tests/spec/unit/create.spec.js
@@ -17,9 +17,9 @@
  under the License.
  */
 
-const fs = require('fs-extra');
-const os = require('os');
-const path = require('path');
+const fs = require('node:fs');
+const os = require('node:os');
+const path = require('node:path');
 const xcode = require('xcode');
 const create = require('../../../lib/create');
 
@@ -86,7 +86,7 @@ describe('create', () => {
     });
 
     afterEach(() => {
-        fs.removeSync(tmpDir);
+        fs.rmSync(tmpDir, { recursive: true, force: true });
     });
 
     it('should create project with ascii name, no spaces', () => {
diff --git a/tests/spec/unit/lib/list-devices.spec.js 
b/tests/spec/unit/lib/list-devices.spec.js
index fb049850..516ec5b7 100644
--- a/tests/spec/unit/lib/list-devices.spec.js
+++ b/tests/spec/unit/lib/list-devices.spec.js
@@ -17,8 +17,8 @@
        under the License.
 */
 
-const fs = require('fs-extra');
-const path = require('path');
+const fs = require('node:fs');
+const path = require('node:path');
 const rewire = require('rewire');
 
 const list_devices = rewire('../../../../lib/listDevices');
diff --git a/tests/spec/unit/pluginAdd.spec.js 
b/tests/spec/unit/pluginAdd.spec.js
index 52573d0d..5eaa1a6a 100644
--- a/tests/spec/unit/pluginAdd.spec.js
+++ b/tests/spec/unit/pluginAdd.spec.js
@@ -17,9 +17,9 @@
  under the License.
  */
 
-const path = require('path');
-const fs = require('fs-extra');
-const EventEmitter = require('events').EventEmitter;
+const path = require('node:path');
+const fs = require('node:fs');
+const EventEmitter = require('node:events').EventEmitter;
 const ConfigParser = require('cordova-common').ConfigParser;
 const PluginInfo = require('cordova-common').PluginInfo;
 const Api = require('../../../lib/Api');
@@ -29,20 +29,20 @@ const DUMMY_PLUGIN = 'org.test.plugins.dummyplugin';
 
 const iosProjectFixture = path.join(FIXTURES, 'ios-config-xml');
 const iosProject = path.join(FIXTURES, 'dummyProj');
-const iosPlatform = path.join(iosProject, 'platforms/ios');
+const iosPlatform = path.join(iosProject, 'platforms', 'ios');
 const dummyPlugin = path.join(FIXTURES, DUMMY_PLUGIN);
 
 describe('plugin add', () => {
     let api;
 
     beforeEach(() => {
-        fs.ensureDirSync(iosPlatform);
-        fs.copySync(iosProjectFixture, iosPlatform);
+        fs.mkdirSync(iosPlatform, { recursive: true });
+        fs.cpSync(iosProjectFixture, iosPlatform, { recursive: true });
         api = new Api('ios', iosPlatform, new EventEmitter());
     });
 
     afterEach(() => {
-        fs.removeSync(iosPlatform);
+        fs.rmSync(iosPlatform, { recursive: true, force: true });
     });
 
     it('should handle plugin preference default values', () => {
diff --git a/tests/spec/unit/prepare.spec.js b/tests/spec/unit/prepare.spec.js
index 2ec83531..769a3afa 100644
--- a/tests/spec/unit/prepare.spec.js
+++ b/tests/spec/unit/prepare.spec.js
@@ -18,10 +18,10 @@
  */
 
 'use strict';
-const fs = require('fs-extra');
 
-const EventEmitter = require('events');
-const path = require('path');
+const fs = require('node:fs');
+const EventEmitter = require('node:events');
+const path = require('node:path');
 const plist = require('plist');
 const xcode = require('xcode');
 const XcodeProject = xcode.project;
@@ -45,13 +45,13 @@ describe('prepare', () => {
     beforeEach(() => {
         Api = rewire('../../../lib/Api');
 
-        fs.ensureDirSync(iosPlatform);
-        fs.copySync(iosProjectFixture, iosPlatform);
+        fs.mkdirSync(iosPlatform, { recursive: true });
+        fs.cpSync(iosProjectFixture, iosPlatform, { recursive: true });
         p = new Api('ios', iosPlatform, new EventEmitter());
     });
 
     afterEach(() => {
-        fs.removeSync(tmpDir);
+        fs.rmSync(tmpDir, { recursive: true, force: true });
     });
 
     describe('launch storyboard feature (CB-9762)', () => {
@@ -275,7 +275,7 @@ describe('prepare', () => {
             it('should find the Assets.xcassets file in a project with an 
asset catalog', () => {
                 const platformProjDir = path.join('platforms', 'ios', 
'SampleApp');
                 const assetCatalogPath = path.join(iosProject, 
platformProjDir, 'Assets.xcassets');
-                const expectedPath = path.join(platformProjDir, 
'Assets.xcassets', 'LaunchStoryboard.imageset/');
+                const expectedPath = path.join(platformProjDir, 
'Assets.xcassets', 'LaunchStoryboard.imageset');
 
                 expect(fs.existsSync(assetCatalogPath)).toEqual(true);
 
@@ -316,7 +316,7 @@ describe('prepare', () => {
                 };
 
                 // copy the splash screen fixtures to the iOS project
-                fs.copySync(path.join(FIXTURES, 'launch-storyboard-support', 
'res'), path.join(iosProject, 'res'));
+                fs.cpSync(path.join(FIXTURES, 'launch-storyboard-support', 
'res'), path.join(iosProject, 'res'), { recursive: true });
 
                 // copy splash screens and update Contents.json
                 updateLaunchStoryboardImages(project, p.locations);
@@ -333,7 +333,7 @@ describe('prepare', () => {
                 // update keys with path to storyboardImagesDir
                 for (const k in expectedResourceMap) {
                     if 
(Object.prototype.hasOwnProperty.call(expectedResourceMap, k)) {
-                        expectedResourceMap[storyboardImagesDir + k] = 
expectedResourceMap[k];
+                        expectedResourceMap[path.join(storyboardImagesDir, k)] 
= expectedResourceMap[k];
                         delete expectedResourceMap[k];
                     }
                 }
@@ -364,7 +364,7 @@ describe('prepare', () => {
                     projectConfig: new ConfigParser(path.join(FIXTURES, 
'launch-storyboard-support', 'configs', 'modern-only.xml'))
                 };
 
-                fs.copySync(path.join(FIXTURES, 'launch-storyboard-support', 
'res'), path.join(iosProject, 'res'));
+                fs.cpSync(path.join(FIXTURES, 'launch-storyboard-support', 
'res'), path.join(iosProject, 'res'), { recursive: true });
                 updateLaunchStoryboardImages(project, p.locations);
 
                 // now, clean the images
@@ -383,7 +383,7 @@ describe('prepare', () => {
                 // update keys with path to storyboardImagesDir
                 for (const k in expectedResourceMap) {
                     if 
(Object.prototype.hasOwnProperty.call(expectedResourceMap, k)) {
-                        expectedResourceMap[storyboardImagesDir + k] = null;
+                        expectedResourceMap[path.join(storyboardImagesDir, k)] 
= null;
                         delete expectedResourceMap[k];
                     }
                 }
@@ -1650,7 +1650,7 @@ describe('prepare', () => {
 
         it('Test#021 : should update project-level www and with platform 
agnostic www and merges', () => {
             const merges_path = path.join(project.root, 'merges', 'ios');
-            fs.ensureDirSync(merges_path);
+            fs.mkdirSync(merges_path, { recursive: true });
             updateWww(project, p.locations);
             expect(FileUpdater.mergeAndUpdateDir).toHaveBeenCalledWith(
                 ['www', path.join('platforms', 'ios', 'platform_www'), 
path.join('merges', 'ios')],
@@ -1660,7 +1660,7 @@ describe('prepare', () => {
         });
         it('Test#022 : should skip merges if merges directory does not exist', 
() => {
             const merges_path = path.join(project.root, 'merges', 'ios');
-            fs.removeSync(merges_path);
+            fs.rmSync(merges_path, { recursive: true, force: true });
             updateWww(project, p.locations);
             expect(FileUpdater.mergeAndUpdateDir).toHaveBeenCalledWith(
                 ['www', path.join('platforms', 'ios', 'platform_www')],
diff --git a/tests/spec/unit/preparePlatform.spec.js 
b/tests/spec/unit/preparePlatform.spec.js
index 4d7eaed0..5e017e66 100644
--- a/tests/spec/unit/preparePlatform.spec.js
+++ b/tests/spec/unit/preparePlatform.spec.js
@@ -17,9 +17,9 @@
  under the License.
  */
 
-const path = require('path');
-const fs = require('fs-extra');
-const EventEmitter = require('events').EventEmitter;
+const path = require('node:path');
+const fs = require('node:fs');
+const EventEmitter = require('node:events').EventEmitter;
 const ConfigParser = require('cordova-common').ConfigParser;
 const PluginInfo = require('cordova-common').PluginInfo;
 const Api = require('../../../lib/Api');
@@ -35,8 +35,8 @@ const dummyPlugin = path.join(FIXTURES, DUMMY_PLUGIN);
 describe('prepare after plugin add', () => {
     let api;
     beforeEach(() => {
-        fs.ensureDirSync(iosPlatform);
-        fs.copySync(iosProjectFixture, iosPlatform);
+        fs.mkdirSync(iosPlatform, { recursive: true });
+        fs.cpSync(iosProjectFixture, iosPlatform, { recursive: true });
         api = new Api('ios', iosPlatform, new EventEmitter());
 
         jasmine.addMatchers({
@@ -66,7 +66,7 @@ describe('prepare after plugin add', () => {
     });
 
     afterEach(() => {
-        fs.removeSync(iosPlatform);
+        fs.rmSync(iosPlatform, { recursive: true, force: true });
     });
 
     it('Test 001 : should not overwrite plugin metadata added by "addPlugin"', 
() => {
diff --git a/tests/spec/unit/projectFile.spec.js 
b/tests/spec/unit/projectFile.spec.js
index adc77563..184213a9 100644
--- a/tests/spec/unit/projectFile.spec.js
+++ b/tests/spec/unit/projectFile.spec.js
@@ -17,9 +17,9 @@
     under the License.
 */
 
-const os = require('os');
-const path = require('path');
-const fs = require('fs-extra');
+const os = require('node:os');
+const path = require('node:path');
+const fs = require('node:fs');
 const projectFile = require('../../../lib/projectFile');
 
 const iosProject = path.join(os.tmpdir(), 'plugman/projectFile');
@@ -27,38 +27,38 @@ const iosProjectFixture = path.join(__dirname, 
'fixtures/ios-config-xml');
 
 const locations = {
     root: iosProject,
-    pbxproj: path.join(iosProject, 'SampleApp.xcodeproj/project.pbxproj')
+    pbxproj: path.join(iosProject, 'SampleApp.xcodeproj', 'project.pbxproj')
 };
 
 describe('projectFile', () => {
     beforeEach(() => {
-        fs.copySync(iosProjectFixture, iosProject);
+        fs.cpSync(iosProjectFixture, iosProject, { recursive: true });
     });
 
     afterEach(() => {
-        fs.removeSync(iosProject);
+        fs.rmSync(iosProject, { recursive: true, force: true });
     });
 
     describe('parse method', () => {
         it('Test#001 : should throw if project is not an xcode project', () => 
{
-            fs.removeSync(path.join(iosProject, 'SampleApp', 
'SampleApp.xcodeproj'));
+            fs.rmSync(path.join(iosProject, 'SampleApp', 
'SampleApp.xcodeproj'), { recursive: true, force: true });
             expect(() => { projectFile.parse(); }).toThrow();
         });
         it('Test#002 : should throw if project does not contain an appropriate 
config.xml file', () => {
-            fs.removeSync(path.join(iosProject, 'SampleApp', 'config.xml'));
+            fs.rmSync(path.join(iosProject, 'SampleApp', 'config.xml'));
             expect(() => { projectFile.parse(locations); })
                 .toThrow(new Error('Could not find *-Info.plist file, or 
config.xml file.'));
         });
         it('Test#003 : should throw if project does not contain an appropriate 
-Info.plist file', () => {
-            fs.removeSync(path.join(iosProject, 'SampleApp', 
'SampleApp-Info.plist'));
+            fs.rmSync(path.join(iosProject, 'SampleApp', 
'SampleApp-Info.plist'));
             expect(() => { projectFile.parse(locations); })
                 .toThrow(new Error('Could not find *-Info.plist file, or 
config.xml file.'));
         });
         it('Test#004 : should return right directory when multiple .plist 
files are present', () => {
             // Create a folder named A with config.xml and .plist files in it
             const pathToFolderA = path.join(iosProject, 'A');
-            fs.ensureDirSync(pathToFolderA);
-            fs.copySync(path.join(iosProject, 'SampleApp'), pathToFolderA);
+            fs.mkdirSync(pathToFolderA, { recursive: true });
+            fs.cpSync(path.join(iosProject, 'SampleApp'), pathToFolderA, { 
recursive: true });
 
             const parsedProjectFile = projectFile.parse(locations);
             const pluginsDir = parsedProjectFile.plugins_dir;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org
For additional commands, e-mail: commits-h...@cordova.apache.org

Reply via email to