diff --git a/Gruntfile.js b/Gruntfile.js index 26f6fffbe1..a08b50c319 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,7 +2,7 @@ const childProcess = require("child_process"); const EOL = require("os").EOL; const path = require("path"); const now = new Date().toISOString(); -const latestVersion = require('latest-version').default; +const manifest = require('pacote').manifest; const ENVIRONMENTS = { @@ -260,28 +260,26 @@ function registerTestingDependenciesTasks(grunt) { return done(false); } - - // Kick off all version resolutions in parallel - const versionPromises = testDependencies.map(dep => { - if (dep.version) { - dependenciesVersions[dep.name] = dep.version; - return Promise.resolve(); - } - return latestVersion(dep.name).then(v => { - dependenciesVersions[dep.name] = v; - }); - }); - - Promise.all(versionPromises) - .then(() => { - grunt.file.write(generatedVersionFilePath, JSON.stringify(dependenciesVersions, null, 2)); + (async () => { + try { + for (const dep of testDependencies) { + if (dep.version) { + dependenciesVersions[dep.name] = dep.version; + } else { + dependenciesVersions[dep.name] = await latestVersion(dep.name); + } + } + grunt.file.write( + generatedVersionFilePath, + JSON.stringify(dependenciesVersions, null, 2) + ); grunt.log.writeln("Wrote", generatedVersionFilePath); done(); - }) - .catch(err => { + } catch (err) { grunt.log.error(err); done(false); - }); + } + })(); }); grunt.registerTask("verify_unit_testing_dependencies", function () { @@ -291,3 +289,9 @@ function registerTestingDependenciesTasks(grunt) { }); } +async function latestVersion(name) { + // only fetches the package.json for the latest dist-tag + const { version } = await manifest(name.toLowerCase(), { fullMetadata: false }); + return version; +} + diff --git a/lib/bootstrap.ts b/lib/bootstrap.ts index ca8fe39888..ad181a1062 100644 --- a/lib/bootstrap.ts +++ b/lib/bootstrap.ts @@ -414,8 +414,8 @@ injector.require( injector.requirePublic("cleanupService", "./services/cleanup-service"); injector.require( - "webpackCompilerService", - "./services/webpack/webpack-compiler-service", + "bundlerCompilerService", + "./services/bundler/bundler-compiler-service", ); injector.require( diff --git a/lib/color.ts b/lib/color.ts index 9260c23f5c..936569201e 100644 --- a/lib/color.ts +++ b/lib/color.ts @@ -1,12 +1,92 @@ -// using chalk as some of our other dependencies are already using it... -// exporting from here so we can easily refactor to a different color library if needed -import * as ansi from "ansi-colors"; -import * as chalk from "chalk"; +import { styleText, stripVTControlCharacters } from "node:util"; -export type Color = typeof chalk.Color; +// Define color types based on util.inspect.colors +export type StyleFormat = + | "reset" + | "bold" + | "dim" + | "italic" + | "underline" + | "blink" + | "inverse" + | "hidden" + | "strikethrough" + | "doubleunderline" + | "black" + | "red" + | "green" + | "yellow" + | "blue" + | "magenta" + | "cyan" + | "white" + | "gray" + | "redBright" + | "greenBright" + | "yellowBright" + | "blueBright" + | "magentaBright" + | "cyanBright" + | "whiteBright" + | "bgBlack" + | "bgRed" + | "bgGreen" + | "bgYellow" + | "bgBlue" + | "bgMagenta" + | "bgCyan" + | "bgWhite" + | "bgGray" + | "bgRedBright" + | "bgGreenBright" + | "bgYellowBright" + | "bgBlueBright" + | "bgMagentaBright" + | "bgCyanBright" + | "bgWhiteBright"; -export function stripColors(formatStr: string) { - return ansi.stripColor(formatStr); -} +export type Color = StyleFormat; -export const color = chalk; +// Create a chalk-like API using the Node.js util.styleText function +export const color = { + reset: (text: string) => styleText("reset", text), + bold: (text: string) => styleText("bold", text), + dim: (text: string) => styleText("dim", text), + italic: (text: string) => styleText("italic", text), + underline: (text: string) => styleText("underline", text), + inverse: (text: string) => styleText("inverse", text), + hidden: (text: string) => styleText("hidden", text), + strikethrough: (text: string) => styleText("strikethrough", text), + + // Text colors + black: (text: string) => styleText("black", text), + red: (text: string) => styleText("red", text), + blue: (text: string) => styleText("blue", text), + magenta: (text: string) => styleText("magenta", text), + cyan: (text: string) => styleText("cyan", text), + white: (text: string) => styleText("white", text), + gray: (text: string) => styleText("gray", text), + yellow: (text: string) => styleText("yellow", text), + green: (text: string) => styleText("green", text), + grey: (text: string) => styleText("grey", text), + + // Background colors + bgBlack: (text: string) => styleText("bgBlack", text), + bgBlackBright: (text: string) => styleText("bgBlackBright", text), + bgRed: (text: string) => styleText("bgRed", text), + bgGreen: (text: string) => styleText("bgGreen", text), + bgYellow: (text: string) => styleText("bgYellow", text), + bgBlue: (text: string) => styleText("bgBlue", text), + bgMagenta: (text: string) => styleText("bgMagenta", text), + bgCyan: (text: string) => styleText("bgCyan", text), + bgWhite: (text: string) => styleText("bgWhite", text), + cyanBright: (text: string) => styleText("cyanBright", text), + whiteBright: (text: string) => styleText("whiteBright", text), + greenBright: (text: string) => styleText("greenBright", text), + yellowBright: (text: string) => styleText("yellowBright", text), + redBright: (text: string) => styleText("redBright", text), + + styleText, +}; + +export const stripColors = (text: string) => stripVTControlCharacters(text); diff --git a/lib/commands/clean.ts b/lib/commands/clean.ts index 1d8c636a55..2d0608140d 100644 --- a/lib/commands/clean.ts +++ b/lib/commands/clean.ts @@ -267,7 +267,8 @@ export class CleanCommand implements ICommand { spinner.warn( `This will run "${color.yellow( `ns clean`, - )}" in all the selected projects and ${color.red.bold( + )}" in all the selected projects and ${color.styleText( + ["red", "bold"], "delete files from your system", )}!`, ); diff --git a/lib/commands/embedding/embed.ts b/lib/commands/embedding/embed.ts index a186b8763c..f5c488cd46 100644 --- a/lib/commands/embedding/embed.ts +++ b/lib/commands/embedding/embed.ts @@ -56,8 +56,9 @@ export class EmbedCommand extends PrepareCommand implements ICommand { if (!this.$fs.exists(resolvedHostProjectPath)) { this.$logger.error( `The host project path ${color.yellow( - hostProjectPath - )} (resolved to: ${color.yellow.dim( + hostProjectPath, + )} (resolved to: ${color.styleText( + ["yellow", "dim"], resolvedHostProjectPath )}) does not exist.` ); diff --git a/lib/commands/post-install.ts b/lib/commands/post-install.ts index d02b0d769f..c0a6ac8a45 100644 --- a/lib/commands/post-install.ts +++ b/lib/commands/post-install.ts @@ -55,11 +55,14 @@ export class PostInstallCliCommand implements ICommand { public async postCommandAction(args: string[]): Promise { this.$logger.info(""); this.$logger.info( - color.green.bold("You have successfully installed the NativeScript CLI!") + color.styleText( + ["green", "bold"], + "You have successfully installed the NativeScript CLI!", + ), ); this.$logger.info(""); this.$logger.info("Your next step is to create a new project:"); - this.$logger.info(color.green.bold("ns create")); + this.$logger.info(color.styleText(["green", "bold"], "ns create")); this.$logger.info(""); this.$logger.printMarkdown( diff --git a/lib/commands/typings.ts b/lib/commands/typings.ts index 67f01cfc62..6811a247d8 100644 --- a/lib/commands/typings.ts +++ b/lib/commands/typings.ts @@ -1,4 +1,4 @@ -import { glob } from "glob"; +import { glob } from "node:fs/promises"; import { homedir } from "os"; import * as path from "path"; import { PromptObject } from "prompts"; @@ -67,18 +67,12 @@ export class TypingsCommand implements ICommand { const pattern = `${target.replaceAll(":", "/")}/**/*.{jar,aar}`; - const res = await glob(pattern, { + const items = []; + for await (const item of glob(pattern, { cwd: gradleFiles, - }); - - if (!res || res.length === 0) { - this.$logger.warn("No files found"); - return []; - } - - const items = res.map((item) => { + })) { const [group, artifact, version, sha1, file] = item.split(path.sep); - return { + items.push({ id: sha1 + version, group, artifact, @@ -86,8 +80,13 @@ export class TypingsCommand implements ICommand { sha1, file, path: path.resolve(gradleFiles, item), - }; - }); + }); + } + + if (items.length === 0) { + this.$logger.warn("No files found"); + return []; + } this.$logger.clearScreen(); @@ -108,9 +107,10 @@ export class TypingsCommand implements ICommand { .map((item) => { return { title: `${color.white(item.group)}:${color.greenBright( - item.artifact - )}:${color.yellow(item.version)} - ${color.cyanBright.bold( - item.file + item.artifact, + )}:${color.yellow(item.version)} - ${color.styleText( + ["cyanBright", "bold"], + item.file, )}`, value: item.id, }; diff --git a/lib/common/header.ts b/lib/common/header.ts index 6cc7b0eed8..6fb1f2c671 100644 --- a/lib/common/header.ts +++ b/lib/common/header.ts @@ -10,15 +10,18 @@ export function printHeader() { const header = [ color.dim("│ "), - color.cyanBright.bold("{N} NativeScript "), - color.whiteBright.bold("CLI"), + color.styleText(["cyanBright", "bold"], "{N} NativeScript "), + color.styleText(["whiteBright", "bold"], "CLI"), color.dim(` [v${version}] `), // color.dim(" │"), ].join(""); const tagLine = [ color.dim("│ "), color.dim(" → "), - color.whiteBright.bold("Empower JavaScript with native APIs "), + color.styleText( + ["whiteBright", "bold"], + "Empower JavaScript with native APIs ", + ), // color.dim(" │"), ].join(""); diff --git a/lib/common/logger/layouts/cli-layout.ts b/lib/common/logger/layouts/cli-layout.ts index 003854ed77..aadae92252 100644 --- a/lib/common/logger/layouts/cli-layout.ts +++ b/lib/common/logger/layouts/cli-layout.ts @@ -22,7 +22,7 @@ export function layout(config: any) { } if (logEvent.level.isEqualTo(LoggerLevel.ERROR)) { - return color.red.bold(msg); + return color.styleText(["red", "bold"], msg); } if (logEvent.level.isEqualTo(LoggerLevel.WARN)) { diff --git a/lib/common/logger/logger.ts b/lib/common/logger/logger.ts index d0cb1ccd88..cd6ae95ce0 100644 --- a/lib/common/logger/logger.ts +++ b/lib/common/logger/logger.ts @@ -136,8 +136,8 @@ export class Logger implements ILogger { const opts = { unescape: true, link: color.red, - strong: color.green.bold, - firstHeading: color.blue.bold, + strong: (str: string) => color.styleText(["green", "bold"], str), + firstHeading: (str: string) => color.styleText(["blue", "bold"], str), tableOptions: { chars: { mid: "", "left-mid": "", "mid-mid": "", "right-mid": "" }, style: { diff --git a/lib/common/mobile/android/android-emulator-services.ts b/lib/common/mobile/android/android-emulator-services.ts index 8fd7cbb592..6a973d2ed4 100644 --- a/lib/common/mobile/android/android-emulator-services.ts +++ b/lib/common/mobile/android/android-emulator-services.ts @@ -8,7 +8,8 @@ import { injector } from "../../yok"; import * as semver from "semver"; export class AndroidEmulatorServices - implements Mobile.IEmulatorPlatformService { + implements Mobile.IEmulatorPlatformService +{ constructor( private $androidGenymotionService: Mobile.IAndroidVirtualDeviceService, private $androidVirtualDeviceService: Mobile.IAndroidVirtualDeviceService, @@ -16,71 +17,75 @@ export class AndroidEmulatorServices private $childProcess: IChildProcess, private $emulatorHelper: Mobile.IEmulatorHelper, private $logger: ILogger, - private $utils: IUtils + private $utils: IUtils, ) {} public async getEmulatorImages(): Promise { const adbDevicesOutput = await this.$adb.getDevicesSafe(); - const avdAvailableEmulatorsOutput = await this.$androidVirtualDeviceService.getEmulatorImages( - adbDevicesOutput - ); - const genyAvailableDevicesOutput = await this.$androidGenymotionService.getEmulatorImages( - adbDevicesOutput - ); + const avdAvailableEmulatorsOutput = + await this.$androidVirtualDeviceService.getEmulatorImages( + adbDevicesOutput, + ); + const genyAvailableDevicesOutput = + await this.$androidGenymotionService.getEmulatorImages(adbDevicesOutput); const devices = _.concat( avdAvailableEmulatorsOutput.devices, - genyAvailableDevicesOutput.devices + genyAvailableDevicesOutput.devices, ).filter((item) => !!item); return { devices, errors: avdAvailableEmulatorsOutput.errors.concat( - genyAvailableDevicesOutput.errors + genyAvailableDevicesOutput.errors, ), }; } public async getRunningEmulatorIds(): Promise { const adbDevicesOutput = await this.$adb.getDevicesSafe(); - const avds = await this.$androidVirtualDeviceService.getRunningEmulatorIds( - adbDevicesOutput - ); - const genies = await this.$androidGenymotionService.getRunningEmulatorIds( - adbDevicesOutput - ); + const avds = + await this.$androidVirtualDeviceService.getRunningEmulatorIds( + adbDevicesOutput, + ); + const genies = + await this.$androidGenymotionService.getRunningEmulatorIds( + adbDevicesOutput, + ); return avds.concat(genies); } public async getRunningEmulatorName(emulatorId: string): Promise { - let result = await this.$androidVirtualDeviceService.getRunningEmulatorName( - emulatorId - ); - if (!result) { - result = await this.$androidGenymotionService.getRunningEmulatorName( - emulatorId + let result = + await this.$androidVirtualDeviceService.getRunningEmulatorName( + emulatorId, ); + if (!result) { + result = + await this.$androidGenymotionService.getRunningEmulatorName(emulatorId); } return result; } public async getRunningEmulatorImageIdentifier( - emulatorId: string + emulatorId: string, ): Promise { - let result = await this.$androidVirtualDeviceService.getRunningEmulatorImageIdentifier( - emulatorId - ); - if (!result) { - result = await this.$androidGenymotionService.getRunningEmulatorImageIdentifier( - emulatorId + let result = + await this.$androidVirtualDeviceService.getRunningEmulatorImageIdentifier( + emulatorId, ); + if (!result) { + result = + await this.$androidGenymotionService.getRunningEmulatorImageIdentifier( + emulatorId, + ); } return result; } public async startEmulator( - options: Mobile.IAndroidStartEmulatorOptions + options: Mobile.IAndroidStartEmulatorOptions, ): Promise { const output = await this.startEmulatorCore(options); let bootToCompleteOutput = null; @@ -88,13 +93,13 @@ export class AndroidEmulatorServices bootToCompleteOutput = await this.waitForEmulatorBootToComplete( output.runningEmulator, output.endTimeEpoch, - options.timeout + options.timeout, ); } return { errors: ((output && output.errors) || []).concat( - (bootToCompleteOutput && bootToCompleteOutput.errors) || [] + (bootToCompleteOutput && bootToCompleteOutput.errors) || [], ), }; } @@ -104,7 +109,7 @@ export class AndroidEmulatorServices } private async startEmulatorCore( - options: Mobile.IAndroidStartEmulatorOptions + options: Mobile.IAndroidStartEmulatorOptions, ): Promise<{ runningEmulator: Mobile.IDeviceInfo; errors: string[]; @@ -118,7 +123,7 @@ export class AndroidEmulatorServices let emulator = this.$emulatorHelper.getEmulatorByStartEmulatorOptions( options, - availableEmulators + availableEmulators, ); if ( !emulator && @@ -158,7 +163,7 @@ export class AndroidEmulatorServices const emulators = (await this.getEmulatorImages()).devices; const newEmulator = _.find( emulators, - (e) => e.imageIdentifier === emulator.imageIdentifier + (e) => e.imageIdentifier === emulator.imageIdentifier, ); if (newEmulator && this.$emulatorHelper.isEmulatorRunning(newEmulator)) { return { @@ -185,29 +190,29 @@ export class AndroidEmulatorServices let pathToEmulatorExecutable = null; let startEmulatorArgs = null; if (emulator.vendor === AndroidVirtualDevice.AVD_VENDOR_NAME) { - pathToEmulatorExecutable = this.$androidVirtualDeviceService - .pathToEmulatorExecutable; + pathToEmulatorExecutable = + this.$androidVirtualDeviceService.pathToEmulatorExecutable; startEmulatorArgs = this.$androidVirtualDeviceService.startEmulatorArgs( - emulator.imageIdentifier + emulator.imageIdentifier, ); } else if ( emulator.vendor === AndroidVirtualDevice.GENYMOTION_VENDOR_NAME ) { - pathToEmulatorExecutable = this.$androidGenymotionService - .pathToEmulatorExecutable; + pathToEmulatorExecutable = + this.$androidGenymotionService.pathToEmulatorExecutable; startEmulatorArgs = this.$androidGenymotionService.startEmulatorArgs( - emulator.imageIdentifier + emulator.imageIdentifier, ); } this.$logger.info( - `Starting Android emulator with image ${emulator.imageIdentifier}` + `Starting Android emulator with image ${emulator.imageIdentifier}`, ); const childProcess = this.$childProcess.spawn( pathToEmulatorExecutable, startEmulatorArgs, - { stdio: "ignore", detached: true } + { stdio: "ignore", detached: true }, ); childProcess.unref(); childProcess.on("error", (err: Error) => { @@ -241,7 +246,7 @@ export class AndroidEmulatorServices private async waitForEmulatorBootToComplete( emulator: Mobile.IDeviceInfo, endTimeEpoch: number, - timeout: number + timeout: number, ): Promise<{ runningEmulator: Mobile.IDeviceInfo; errors: string[] }> { this.$logger.info("Waiting for emulator device initialization...", { [LoggerConfigData.skipNewLine]: true, @@ -249,11 +254,11 @@ export class AndroidEmulatorServices const isInfiniteWait = this.$utils.getMilliSecondsTimeout( - timeout || AndroidVirtualDevice.TIMEOUT_SECONDS + timeout || AndroidVirtualDevice.TIMEOUT_SECONDS, ) === 0; while (getCurrentEpochTime() < endTimeEpoch || isInfiniteWait) { const isEmulatorBootCompleted = await this.isEmulatorBootCompleted( - emulator.identifier + emulator.identifier, ); if (isEmulatorBootCompleted) { this.$logger.info(EOL, { [LoggerConfigData.skipNewLine]: true }); @@ -276,7 +281,7 @@ export class AndroidEmulatorServices private async isEmulatorBootCompleted(emulatorId: string): Promise { const output = await this.$adb.getPropertyValue( emulatorId, - "dev.bootcomplete" + "dev.bootcomplete", ); const matches = output.match("1"); return matches && matches.length > 0; diff --git a/lib/common/mobile/device-log-provider.ts b/lib/common/mobile/device-log-provider.ts index 4a3c8e0617..d1a786db9e 100644 --- a/lib/common/mobile/device-log-provider.ts +++ b/lib/common/mobile/device-log-provider.ts @@ -4,7 +4,7 @@ import { injector } from "../yok"; import { LoggerConfigData } from "../../constants"; import { IOptions } from "../../declarations"; -import { Color, color } from "../../color"; +import { color, StyleFormat } from "../../color"; import { ITimelineProfilerService } from "../../services/timeline-profiler-service"; @@ -55,10 +55,9 @@ export class DeviceLogProvider extends DeviceLogProviderBase { time: color.greenBright, }; - private deviceColorMap = new Map(); + private deviceColorMap = new Map(); - private colorPool: Color[] = [ - "bgBlackBright", + private colorPool: StyleFormat[] = [ "bgMagentaBright", "bgBlueBright", "bgWhiteBright", @@ -73,7 +72,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase { return this.deviceColorMap.get(deviceIdentifier); } - const color = this.colorPool[this.colorPoolIndex]; + const color = this.colorPool[this.colorPoolIndex] as StyleFormat; // wrap around if we have no more colors in the pool this.colorPoolIndex = this.colorPoolIndex === this.colorPool.length - 1 @@ -150,7 +149,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase { toLog.split("\n").forEach((actualLine) => { this.printLine( - color[this.getDeviceColor(deviceIdentifier)](" "), + color.styleText(this.getDeviceColor(deviceIdentifier), " "), this.consoleLevelColor[level](actualLine) ); }); diff --git a/lib/common/mobile/emulator-helper.ts b/lib/common/mobile/emulator-helper.ts index 9e8434cba7..baf98fc7aa 100644 --- a/lib/common/mobile/emulator-helper.ts +++ b/lib/common/mobile/emulator-helper.ts @@ -28,7 +28,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { }; public getEmulatorsFromAvailableEmulatorsOutput( - availableEmulatorsOutput: Mobile.IListEmulatorsOutput + availableEmulatorsOutput: Mobile.IListEmulatorsOutput, ): Mobile.IDeviceInfo[] { return _(availableEmulatorsOutput) .valuesIn() @@ -39,7 +39,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { } public getErrorsFromAvailableEmulatorsOutput( - availableEmulatorsOutput: Mobile.IListEmulatorsOutput + availableEmulatorsOutput: Mobile.IListEmulatorsOutput, ): string[] { return _(availableEmulatorsOutput) .valuesIn() @@ -51,7 +51,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { public getEmulatorByImageIdentifier( imageIdentifier: string, - emulators: Mobile.IDeviceInfo[] + emulators: Mobile.IDeviceInfo[], ): Mobile.IDeviceInfo { const imagerIdentifierLowerCase = imageIdentifier && imageIdentifier.toLowerCase(); @@ -61,13 +61,13 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { emulator && emulator.imageIdentifier && imageIdentifier && - emulator.imageIdentifier.toLowerCase() === imagerIdentifierLowerCase + emulator.imageIdentifier.toLowerCase() === imagerIdentifierLowerCase, ); } public getEmulatorByIdOrName( emulatorIdOrName: string, - emulators: Mobile.IDeviceInfo[] + emulators: Mobile.IDeviceInfo[], ): Mobile.IDeviceInfo { const emulatorIdOrNameLowerCase = emulatorIdOrName && emulatorIdOrName.toLowerCase(); @@ -78,7 +78,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { emulatorIdOrNameLowerCase && ((emulator.identifier && emulator.identifier.toLowerCase() === emulatorIdOrNameLowerCase) || - emulator.displayName.toLowerCase() === emulatorIdOrNameLowerCase) + emulator.displayName.toLowerCase() === emulatorIdOrNameLowerCase), ); } @@ -88,7 +88,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { public getEmulatorByStartEmulatorOptions( options: Mobile.IStartEmulatorOptions, - emulators: Mobile.IDeviceInfo[] + emulators: Mobile.IDeviceInfo[], ): Mobile.IDeviceInfo { let result: Mobile.IDeviceInfo = null; @@ -99,7 +99,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { if (!result && options.imageIdentifier) { result = this.getEmulatorByImageIdentifier( options.imageIdentifier, - emulators + emulators, ); } @@ -112,7 +112,7 @@ export class EmulatorHelper implements Mobile.IEmulatorHelper { public setRunningAndroidEmulatorProperties( emulatorId: string, - emulator: Mobile.IDeviceInfo + emulator: Mobile.IDeviceInfo, ): void { emulator.identifier = emulatorId; emulator.status = RUNNING_EMULATOR_STATUS; diff --git a/lib/common/verify-node-version.ts b/lib/common/verify-node-version.ts index fb64c4a456..fa13e858ba 100644 --- a/lib/common/verify-node-version.ts +++ b/lib/common/verify-node-version.ts @@ -46,14 +46,16 @@ export function verifyNodeVersion(): void { semver.lt(nodeVer, minimumRequiredVersion) ) { console.error( - color.red.bold( - util.format( - "%sNode.js '%s' is not supported. To be able to work with %s CLI, install any Node.js version in the following range: %s.%s", - os.EOL, - nodeVer, - cliName, - supportedVersionsRange, - os.EOL, + color.bold( + color.red( + util.format( + "%sNode.js '%s' is not supported. To be able to work with %s CLI, install any Node.js version in the following range: %s.%s", + os.EOL, + nodeVer, + cliName, + supportedVersionsRange, + os.EOL, + ), ), ), ); diff --git a/lib/constants.ts b/lib/constants.ts index 0ac436ec77..c76d6f6696 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -16,6 +16,7 @@ export const SCOPED_TNS_CORE_MODULES = "@nativescript/core"; export const TNS_CORE_THEME_NAME = "nativescript-theme-core"; export const SCOPED_TNS_CORE_THEME_NAME = "@nativescript/theme"; export const WEBPACK_PLUGIN_NAME = "@nativescript/webpack"; +export const RSPACK_PLUGIN_NAME = "@nativescript/rspack"; export const TNS_CORE_MODULES_WIDGETS_NAME = "tns-core-modules-widgets"; export const UI_MOBILE_BASE_NAME = "@nativescript/ui-mobile-base"; export const TNS_ANDROID_RUNTIME_NAME = "tns-android"; @@ -36,6 +37,7 @@ export const XML_FILE_EXTENSION = ".xml"; export const PLATFORMS_DIR_NAME = "platforms"; export const HOOKS_DIR_NAME = "hooks"; export const WEBPACK_CONFIG_NAME = "webpack.config.js"; +export const RSPACK_CONFIG_NAME = "rspack.config.js"; export const TSCCONFIG_TNS_JSON_NAME = "tsconfig.tns.json"; export const KARMA_CONFIG_NAME = "karma.conf.js"; export const LIB_DIR_NAME = "lib"; @@ -222,7 +224,7 @@ export const CACACHE_DIRECTORY_NAME = "_cacache"; export const FILES_CHANGE_EVENT_NAME = "filesChangeEvent"; export const INITIAL_SYNC_EVENT_NAME = "initialSyncEvent"; export const PREPARE_READY_EVENT_NAME = "prepareReadyEvent"; -export const WEBPACK_COMPILATION_COMPLETE = "webpackCompilationComplete"; +export const BUNDLER_COMPILATION_COMPLETE = "bundlerCompilationComplete"; export class DebugCommandErrors { public static UNABLE_TO_USE_FOR_DEVICE_AND_EMULATOR = diff --git a/lib/controllers/prepare-controller.ts b/lib/controllers/prepare-controller.ts index 8ba3550b86..73fa9ab5b3 100644 --- a/lib/controllers/prepare-controller.ts +++ b/lib/controllers/prepare-controller.ts @@ -13,6 +13,7 @@ import { hook } from "../common/helpers"; import { injector } from "../common/yok"; import { AnalyticsEventLabelDelimiter, + BUNDLER_COMPILATION_COMPLETE, CONFIG_FILE_NAME_JS, CONFIG_FILE_NAME_TS, PACKAGE_JSON_FILE_NAME, @@ -20,7 +21,6 @@ import { PREPARE_READY_EVENT_NAME, SupportedPlatform, TrackActionNames, - WEBPACK_COMPILATION_COMPLETE, } from "../constants"; import { IOptions, IWatchIgnoreListService } from "../declarations"; import { @@ -67,7 +67,7 @@ export class PrepareController extends EventEmitter { private $prepareNativePlatformService: IPrepareNativePlatformService, private $projectChangesService: IProjectChangesService, private $projectDataService: IProjectDataService, - private $webpackCompilerService: IWebpackCompilerService, + private $bundlerCompilerService: IBundlerCompilerService, private $watchIgnoreListService: IWatchIgnoreListService, private $analyticsService: IAnalyticsService, private $markingModeService: IMarkingModeService, @@ -117,9 +117,9 @@ export class PrepareController extends EventEmitter { this.watchersData[projectDir][platformLowerCase] && this.watchersData[projectDir][platformLowerCase].hasWebpackCompilerProcess ) { - await this.$webpackCompilerService.stopWebpackCompiler(platformLowerCase); - this.$webpackCompilerService.removeListener( - WEBPACK_COMPILATION_COMPLETE, + await this.$bundlerCompilerService.stopBundlerCompiler(platformLowerCase); + this.$bundlerCompilerService.removeListener( + BUNDLER_COMPILATION_COMPLETE, this.webpackCompilerHandler, ); this.watchersData[projectDir][ @@ -177,7 +177,7 @@ export class PrepareController extends EventEmitter { prepareData, ); } else { - await this.$webpackCompilerService.compileWithoutWatch( + await this.$bundlerCompilerService.compileWithoutWatch( platformData, projectData, prepareData, @@ -296,15 +296,15 @@ export class PrepareController extends EventEmitter { }; this.webpackCompilerHandler = handler.bind(this); - this.$webpackCompilerService.on( - WEBPACK_COMPILATION_COMPLETE, + this.$bundlerCompilerService.on( + BUNDLER_COMPILATION_COMPLETE, this.webpackCompilerHandler, ); this.watchersData[projectData.projectDir][ platformData.platformNameLowerCase ].hasWebpackCompilerProcess = true; - await this.$webpackCompilerService.compileWithWatch( + await this.$bundlerCompilerService.compileWithWatch( platformData, projectData, prepareData, @@ -560,7 +560,7 @@ export class PrepareController extends EventEmitter { if (this.pausedFileWatch) { for (const watcher of watchers) { for (const platform in watcher) { - await this.$webpackCompilerService.stopWebpackCompiler(platform); + await this.$bundlerCompilerService.stopBundlerCompiler(platform); watcher[platform].hasWebpackCompilerProcess = false; } } @@ -569,7 +569,7 @@ export class PrepareController extends EventEmitter { for (const platform in watcher) { const args = watcher[platform].prepareArguments; watcher[platform].hasWebpackCompilerProcess = true; - await this.$webpackCompilerService.compileWithWatch( + await this.$bundlerCompilerService.compileWithWatch( args.platformData, args.projectData, args.prepareData, diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index e99e204691..c8046b2ed4 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -121,6 +121,7 @@ export interface IOSLocalSPMPackage extends IOSSPMPackageBase { } export type IOSSPMPackage = IOSRemoteSPMPackage | IOSLocalSPMPackage; +export type BundlerType = "webpack" | "rspack" | "vite"; interface INsConfigIOS extends INsConfigPlaform { discardUncaughtJsExceptions?: boolean; @@ -182,6 +183,8 @@ interface INsConfig { shared?: boolean; overridePods?: string; webpackConfigPath?: string; + bundlerConfigPath?: string; + bundler?: BundlerType; ios?: INsConfigIOS; android?: INsConfigAndroid; visionos?: INSConfigVisionOS; @@ -215,13 +218,28 @@ interface IProjectData extends ICreateProjectData { * Value is true when project has nativescript.config and it has `shared: true` in it. */ isShared: boolean; - /** + * Specifies the bundler used to build the application. + * + * - `"webpack"`: Uses Webpack for traditional bundling. + * - `"rspack"`: Uses Rspack for fast bundling. + * - `"vite"`: Uses Vite for fast bundling. + * + * @default "webpack" + */ + bundler: BundlerType; + /** + * @deprecated Use bundlerConfigPath * Defines the path to the configuration file passed to webpack process. * By default this is the webpack.config.js at the root of the application. * The value can be changed by setting `webpackConfigPath` in nativescript.config. */ webpackConfigPath: string; + /** + * Defines the path to the bundler configuration file passed to the compiler. + * The value can be changed by setting `bundlerConfigPath` in nativescript.config. + */ + bundlerConfigPath: string; projectName: string; /** diff --git a/lib/helpers/key-command-helper.ts b/lib/helpers/key-command-helper.ts index ecfaabd367..821a1ea113 100644 --- a/lib/helpers/key-command-helper.ts +++ b/lib/helpers/key-command-helper.ts @@ -1,4 +1,5 @@ -import { color, stripColors } from "../color"; +import { color } from "../color"; +import { stripVTControlCharacters } from "node:util"; import { IKeyCommandHelper, IKeyCommandPlatform, @@ -62,7 +63,7 @@ export default class KeyCommandHelper implements IKeyCommandHelper { const line = ` ${color.dim("→")} ${color.bold(keyCommand.key)} — ${ keyCommand.description }`; - const lineLength = stripColors(line).length - 1; + const lineLength = stripVTControlCharacters(line).length - 1; console.log(color.dim(` ┌${"─".repeat(lineLength)}┐`)); console.log(line + color.dim(" │")); console.log(color.dim(` └${"─".repeat(lineLength)}┘`)); diff --git a/lib/project-data.ts b/lib/project-data.ts index 3e36c374b5..277dbf32d1 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -5,6 +5,7 @@ import { parseJson } from "./common/helpers"; import { EOL } from "os"; import { cache } from "./common/decorators"; import { + BundlerType, INsConfig, IProjectConfigService, IProjectData, @@ -99,6 +100,8 @@ export class ProjectData implements IProjectData { public podfilePath: string; public isShared: boolean; public webpackConfigPath: string; + public bundlerConfigPath: string; + public bundler: BundlerType; public initialized: boolean; constructor( @@ -110,7 +113,7 @@ export class ProjectData implements IProjectData { private $logger: ILogger, private $injector: IInjector, private $androidResourcesMigrationService: IAndroidResourcesMigrationService, - private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, ) {} get projectConfig(): IProjectConfigService { @@ -142,7 +145,7 @@ export class ProjectData implements IProjectData { public initializeProjectDataFromContent( packageJsonContent: string, - projectDir?: string + projectDir?: string, ): void { projectDir = projectDir || this.$projectHelper.projectDir || ""; this.projectDir = projectDir; @@ -157,7 +160,7 @@ export class ProjectData implements IProjectData { this.$errors.fail( `The project file ${this.projectFilePath} is corrupted. ${EOL}` + `Consider restoring an earlier version from your source control or backup.${EOL}` + - `Additional technical info: ${err.toString()}` + `Additional technical info: ${err.toString()}`, ); } @@ -178,36 +181,43 @@ export class ProjectData implements IProjectData { this.appDirectoryPath = this.getAppDirectoryPath(); this.appResourcesDirectoryPath = this.getAppResourcesDirectoryPath(); this.androidManifestPath = this.getPathToAndroidManifest( - this.appResourcesDirectoryPath + this.appResourcesDirectoryPath, ); this.gradleFilesDirectoryPath = path.join( this.appResourcesDirectoryPath, - this.$devicePlatformsConstants.Android + this.$devicePlatformsConstants.Android, ); this.appGradlePath = path.join( this.gradleFilesDirectoryPath, - constants.APP_GRADLE_FILE_NAME + constants.APP_GRADLE_FILE_NAME, ); this.infoPlistPath = path.join( this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, - constants.INFO_PLIST_FILE_NAME + constants.INFO_PLIST_FILE_NAME, ); this.buildXcconfigPath = path.join( this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, - constants.BUILD_XCCONFIG_FILE_NAME + constants.BUILD_XCCONFIG_FILE_NAME, ); this.podfilePath = path.join( this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, - constants.PODFILE_NAME + constants.PODFILE_NAME, ); this.isShared = !!(this.nsConfig && this.nsConfig.shared); - this.webpackConfigPath = + + const webpackConfigPath = this.nsConfig && this.nsConfig.webpackConfigPath ? path.resolve(this.projectDir, this.nsConfig.webpackConfigPath) : path.join(this.projectDir, "webpack.config.js"); + this.webpackConfigPath = webpackConfigPath; + this.bundlerConfigPath = + this.nsConfig && this.nsConfig.bundlerConfigPath + ? path.resolve(this.projectDir, this.nsConfig.bundlerConfigPath) + : webpackConfigPath; + this.bundler = this?.nsConfig?.bundler ?? "webpack"; return; } @@ -217,7 +227,7 @@ export class ProjectData implements IProjectData { private getPathToAndroidManifest(appResourcesDir: string): string { const androidDirPath = path.join( appResourcesDir, - this.$devicePlatformsConstants.Android + this.$devicePlatformsConstants.Android, ); const androidManifestDir = this.$androidResourcesMigrationService.hasMigrated(appResourcesDir) @@ -230,13 +240,13 @@ export class ProjectData implements IProjectData { private errorInvalidProject(projectDir: string): void { const currentDir = path.resolve("."); this.$logger.trace( - `Unable to find project. projectDir: ${projectDir}, options.path: ${this.$options.path}, ${currentDir}` + `Unable to find project. projectDir: ${projectDir}, options.path: ${this.$options.path}, ${currentDir}`, ); // This is the case when no project file found this.$errors.fail( "No project found at or above '%s' and neither was a --path specified.", - projectDir || this.$options.path || currentDir + projectDir || this.$options.path || currentDir, ); } @@ -291,7 +301,7 @@ export class ProjectData implements IProjectData { private resolveToProjectDir( pathToResolve: string, - projectDir?: string + projectDir?: string, ): string { if (!projectDir) { projectDir = this.projectDir; @@ -306,7 +316,7 @@ export class ProjectData implements IProjectData { @cache() private initializeProjectIdentifiers( - config: INsConfig + config: INsConfig, ): Mobile.IProjectIdentifier { this.$logger.trace(`Initializing project identifiers. Config: `, config); @@ -341,18 +351,18 @@ export class ProjectData implements IProjectData { private getProjectType(): string { let detectedProjectType = _.find( ProjectData.PROJECT_TYPES, - (projectType) => projectType.isDefaultProjectType + (projectType) => projectType.isDefaultProjectType, ).type; const deps: string[] = _.keys(this.dependencies).concat( - _.keys(this.devDependencies) + _.keys(this.devDependencies), ); _.each(ProjectData.PROJECT_TYPES, (projectType) => { if ( _.some( projectType.requiredDependencies, - (requiredDependency) => deps.indexOf(requiredDependency) !== -1 + (requiredDependency) => deps.indexOf(requiredDependency) !== -1, ) ) { detectedProjectType = projectType.type; @@ -366,7 +376,7 @@ export class ProjectData implements IProjectData { @cache() private warnProjectId(): void { this.$logger.warn( - "[WARNING]: IProjectData.projectId is deprecated. Please use IProjectData.projectIdentifiers[platform]." + "[WARNING]: IProjectData.projectId is deprecated. Please use IProjectData.projectIdentifiers[platform].", ); } } diff --git a/lib/services/analytics-settings-service.ts b/lib/services/analytics-settings-service.ts index 9a73f67ed8..825ef0e682 100644 --- a/lib/services/analytics-settings-service.ts +++ b/lib/services/analytics-settings-service.ts @@ -38,13 +38,17 @@ class AnalyticsSettingsService implements IAnalyticsSettingsService { } public getClientName(): string { - return "" + color.cyan.bold(this.$staticConfig.CLIENT_NAME_ALIAS); + return ( + "" + + color.styleText(["cyan", "bold"], this.$staticConfig.CLIENT_NAME_ALIAS) + ); } public async getUserSessionsCount(projectName: string): Promise { - const sessionsCountForProject = await this.$userSettingsService.getSettingValue< - number - >(this.getSessionsProjectKey(projectName)); + const sessionsCountForProject = + await this.$userSettingsService.getSettingValue( + this.getSessionsProjectKey(projectName), + ); return sessionsCountForProject || 0; } @@ -97,9 +101,8 @@ class AnalyticsSettingsService implements IAnalyticsSettingsService { } private async getSettingValueOrDefault(settingName: string): Promise { - let guid = await this.$userSettingsService.getSettingValue( - settingName - ); + let guid = + await this.$userSettingsService.getSettingValue(settingName); if (!guid) { guid = createGUID(false); diff --git a/lib/services/webpack/webpack-compiler-service.ts b/lib/services/bundler/bundler-compiler-service.ts similarity index 53% rename from lib/services/webpack/webpack-compiler-service.ts rename to lib/services/bundler/bundler-compiler-service.ts index 5a571b7168..12f637b389 100644 --- a/lib/services/webpack/webpack-compiler-service.ts +++ b/lib/services/bundler/bundler-compiler-service.ts @@ -5,8 +5,8 @@ import * as _ from "lodash"; import { EventEmitter } from "events"; import { performanceLog } from "../../common/decorators"; import { - WEBPACK_COMPILATION_COMPLETE, WEBPACK_PLUGIN_NAME, + BUNDLER_COMPILATION_COMPLETE, PackageManagers, CONFIG_FILE_NAME_DISPLAY, } from "../../constants"; @@ -16,7 +16,11 @@ import { IOptions, } from "../../declarations"; import { IPlatformData } from "../../definitions/platform"; -import { IProjectData } from "../../definitions/project"; +import { + BundlerType, + IProjectConfigService, + IProjectData, +} from "../../definitions/project"; import { IDictionary, IErrors, @@ -34,23 +38,23 @@ import { } from "../../helpers/package-path-helper"; // todo: move out of here -interface IWebpackMessage { +interface IBundlerMessage { type: "compilation" | "hmr-status"; version?: number; hash?: string; data?: T; } -interface IWebpackCompilation { +interface IBundlerCompilation { emittedAssets: string[]; staleAssets: string[]; } -export class WebpackCompilerService +export class BundlerCompilerService extends EventEmitter - implements IWebpackCompilerService + implements IBundlerCompilerService { - private webpackProcesses: IDictionary = {}; + private bundlerProcesses: IDictionary = {}; private expectedHashes: IStringDictionary = {}; constructor( @@ -65,6 +69,7 @@ export class WebpackCompilerService private $cleanupService: ICleanupService, private $packageManager: IPackageManager, private $packageInstallationManager: IPackageInstallationManager, // private $sharedEventBus: ISharedEventBus + private $projectConfigService: IProjectConfigService, ) { super(); } @@ -75,20 +80,23 @@ export class WebpackCompilerService prepareData: IPrepareData, ): Promise { return new Promise(async (resolve, reject) => { - if (this.webpackProcesses[platformData.platformNameLowerCase]) { + if (this.bundlerProcesses[platformData.platformNameLowerCase]) { resolve(void 0); return; } - let isFirstWebpackWatchCompilation = true; + let isFirstBundlerWatchCompilation = true; prepareData.watch = true; try { - const childProcess = await this.startWebpackProcess( + const childProcess = await this.startBundleProcess( platformData, projectData, prepareData, ); + // Handle Vite differently from webpack + const isVite = this.getBundler() === "vite"; + childProcess.stdout.on("data", function (data) { process.stdout.write(data); }); @@ -97,8 +105,123 @@ export class WebpackCompilerService process.stderr.write(data); }); - childProcess.on("message", (message: string | IWebpackEmitMessage) => { - this.$logger.trace("Message from webpack", message); + // For both Vite and webpack, we wait for the first build to complete + // Don't resolve immediately for Vite - wait for first IPC message + + childProcess.on("message", (message: string | IBundlerEmitMessage) => { + this.$logger.trace(`Message from ${projectData.bundler}`, message); + + // Handle Vite messages + if ( + isVite && + message && + (message as IBundlerEmitMessage).emittedFiles + ) { + message = message as IBundlerEmitMessage; + console.log("Received Vite IPC message:", message); + + // Copy Vite output files directly to platform destination + const distOutput = path.join(projectData.projectDir, "dist"); + const destDir = path.join( + platformData.appDestinationDirectoryPath, + this.$options.hostProjectModuleName, + ); + + console.log(`🔥 Copying from ${distOutput} to ${destDir}`); + + // For HMR updates, only copy changed files; for full builds, copy everything + if ( + message.isHMR && + message.changedFiles && + message.changedFiles.length > 0 + ) { + console.log( + "🔥 HMR update - copying only changed files for:", + message.changedFiles, + ); + + // For HTML template changes, we need to copy the component files that were rebuilt + let filesToCopy = message.emittedFiles; + + // If we have HTML changes, identify which component files need copying + const hasHTMLChanges = message.changedFiles.some((f) => + f.endsWith(".html"), + ); + if (hasHTMLChanges) { + // Copy component-related files (the ones that would have been rebuilt due to template changes) + filesToCopy = message.emittedFiles.filter( + (f) => + f.includes(".component") || + f === "bundle.mjs" || + f === "bundle.mjs.map", + ); + console.log( + "🔥 HTML change detected - copying component files:", + filesToCopy, + ); + } + + this.copyViteBundleToNative(distOutput, destDir, filesToCopy); + } else { + console.log("🔥 Full build - copying all files"); + this.copyViteBundleToNative(distOutput, destDir); + } + + // Resolve the promise on first build completion + if (isFirstBundlerWatchCompilation) { + isFirstBundlerWatchCompilation = false; + console.log( + "Vite first build completed, resolving compileWithWatch", + ); + resolve(childProcess); + } + + // Transform Vite message to match webpack format + const files = (message as IBundlerEmitMessage).emittedFiles.map( + (file) => + path.join( + platformData.appDestinationDirectoryPath, + this.$options.hostProjectModuleName, + file, + ), + ); + + const data = { + files, + hasOnlyHotUpdateFiles: message.isHMR || false, + hmrData: { + hash: (message as IBundlerEmitMessage).hash || "", + fallbackFiles: [] as string[], + }, + platform: platformData.platformNameLowerCase, + }; + + this.$logger.info( + `Vite build completed! Files copied to native platform.`, + ); + // Send HMR notification to connected WebSocket clients first + this.notifyHMRClients({ + type: message.isHMR ? "js-update" : "build-complete", + timestamp: Date.now(), + changedFiles: message.changedFiles || [], + buildType: message.buildType || "incremental", + isHMR: message.isHMR || false, + }); + + if (message.isHMR) { + console.log( + "🔥 Skipping BUNDLER_COMPILATION_COMPLETE for HMR update - app will not restart", + ); + } else { + // Only emit BUNDLER_COMPILATION_COMPLETE for non-HMR builds + // This prevents the CLI from restarting the app during HMR updates + console.log( + "🔥 Emitting BUNDLER_COMPILATION_COMPLETE for full build", + ); + this.emit(BUNDLER_COMPILATION_COMPLETE, data); + } + return; + } // if we are on webpack5 - we handle HMR in a slightly different way if ( @@ -108,8 +231,8 @@ export class WebpackCompilerService ) { // first compilation can be ignored because it will be synced regardless // handling it here would trigger 2 syncs - if (isFirstWebpackWatchCompilation) { - isFirstWebpackWatchCompilation = false; + if (isFirstBundlerWatchCompilation) { + isFirstBundlerWatchCompilation = false; resolve(childProcess); return; } @@ -122,22 +245,27 @@ export class WebpackCompilerService // } return this.handleHMRMessage( - message as IWebpackMessage, + message as IBundlerMessage, platformData, projectData, prepareData, ); } - if (message === "Webpack compilation complete.") { - this.$logger.info("Webpack build done!"); + if ( + message === + `${capitalizeFirstLetter(projectData.bundler)} compilation complete.` + ) { + this.$logger.info( + `${capitalizeFirstLetter(projectData.bundler)} build done!`, + ); resolve(childProcess); } - message = message as IWebpackEmitMessage; + message = message as IBundlerEmitMessage; if (message.emittedFiles) { - if (isFirstWebpackWatchCompilation) { - isFirstWebpackWatchCompilation = false; + if (isFirstBundlerWatchCompilation) { + isFirstBundlerWatchCompilation = false; this.expectedHashes[platformData.platformNameLowerCase] = prepareData.hmr ? message.hash : ""; return; @@ -189,7 +317,10 @@ export class WebpackCompilerService platform: platformData.platformNameLowerCase, }; - this.$logger.trace("Generated data from webpack message:", data); + this.$logger.trace( + `Generated data from ${projectData.bundler} message:`, + data, + ); // the hash of the compilation is the same as the previous one and there are only hot updates produced if (data.hasOnlyHotUpdateFiles && previousHash === message.hash) { @@ -197,33 +328,33 @@ export class WebpackCompilerService } if (data.files.length) { - this.emit(WEBPACK_COMPILATION_COMPLETE, data); + this.emit(BUNDLER_COMPILATION_COMPLETE, data); } } }); childProcess.on("error", (err) => { this.$logger.trace( - `Unable to start webpack process in watch mode. Error is: ${err}`, + `Unable to start ${projectData.bundler} process in watch mode. Error is: ${err}`, ); - delete this.webpackProcesses[platformData.platformNameLowerCase]; + delete this.bundlerProcesses[platformData.platformNameLowerCase]; reject(err); }); childProcess.on("close", async (arg: any) => { - await this.$cleanupService.removeKillProcess( - childProcess.pid.toString(), - ); - const exitCode = typeof arg === "number" ? arg : arg && arg.code; this.$logger.trace( - `Webpack process exited with code ${exitCode} when we expected it to be long living with watch.`, + `${capitalizeFirstLetter(projectData.bundler)} process exited with code ${exitCode} when we expected it to be long living with watch.`, + ); + + await this.$cleanupService.removeKillProcess( + childProcess.pid.toString(), ); const error: any = new Error( - `Executing webpack failed with exit code ${exitCode}.`, + `Executing ${projectData.bundler} failed with exit code ${exitCode}.`, ); error.code = exitCode; - delete this.webpackProcesses[platformData.platformNameLowerCase]; + delete this.bundlerProcesses[platformData.platformNameLowerCase]; reject(error); }); } catch (err) { @@ -238,13 +369,13 @@ export class WebpackCompilerService prepareData: IPrepareData, ): Promise { return new Promise(async (resolve, reject) => { - if (this.webpackProcesses[platformData.platformNameLowerCase]) { + if (this.bundlerProcesses[platformData.platformNameLowerCase]) { resolve(); return; } try { - const childProcess = await this.startWebpackProcess( + const childProcess = await this.startBundleProcess( platformData, projectData, prepareData, @@ -252,9 +383,9 @@ export class WebpackCompilerService childProcess.on("error", (err) => { this.$logger.trace( - `Unable to start webpack process in non-watch mode. Error is: ${err}`, + `Unable to start ${projectData.bundler} process in non-watch mode. Error is: ${err}`, ); - delete this.webpackProcesses[platformData.platformNameLowerCase]; + delete this.bundlerProcesses[platformData.platformNameLowerCase]; reject(err); }); @@ -263,13 +394,13 @@ export class WebpackCompilerService childProcess.pid.toString(), ); - delete this.webpackProcesses[platformData.platformNameLowerCase]; + delete this.bundlerProcesses[platformData.platformNameLowerCase]; const exitCode = typeof arg === "number" ? arg : arg && arg.code; if (exitCode === 0) { resolve(); } else { const error: any = new Error( - `Executing webpack failed with exit code ${exitCode}.`, + `Executing ${projectData.bundler} failed with exit code ${exitCode}.`, ); error.code = exitCode; reject(error); @@ -281,14 +412,14 @@ export class WebpackCompilerService }); } - public async stopWebpackCompiler(platform: string): Promise { + public async stopBundlerCompiler(platform: string): Promise { if (platform) { - await this.stopWebpackForPlatform(platform); + await this.stopBundlerForPlatform(platform); } else { - const webpackedPlatforms = Object.keys(this.webpackProcesses); + const bundlerPlatforms = Object.keys(this.bundlerProcesses); - for (let i = 0; i < webpackedPlatforms.length; i++) { - await this.stopWebpackForPlatform(webpackedPlatforms[i]); + for (let i = 0; i < bundlerPlatforms.length; i++) { + await this.stopBundlerForPlatform(bundlerPlatforms[i]); } } } @@ -304,15 +435,23 @@ export class WebpackCompilerService } @performanceLog() - private async startWebpackProcess( + private async startBundleProcess( platformData: IPlatformData, projectData: IProjectData, prepareData: IPrepareData, ): Promise { - if (!this.$fs.exists(projectData.webpackConfigPath)) { - this.$errors.fail( - `The webpack configuration file ${projectData.webpackConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}.`, - ); + if (projectData.bundlerConfigPath) { + if (!this.$fs.exists(projectData.bundlerConfigPath)) { + this.$errors.fail( + `The bundler configuration file ${projectData.bundlerConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}.`, + ); + } + } else { + if (!this.$fs.exists(projectData.bundlerConfigPath)) { + this.$errors.fail( + `The ${projectData.bundler} configuration file ${projectData.bundlerConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}.`, + ); + } } const envData = this.buildEnvData( @@ -320,12 +459,22 @@ export class WebpackCompilerService projectData, prepareData, ); - const envParams = await this.buildEnvCommandLineParams( + const isVite = this.getBundler() === "vite"; + const cliArgs = await this.buildEnvCommandLineParams( envData, platformData, projectData, prepareData, ); + // Note: With Vite, we need `--` to prevent vite cli from erroring on unknown options. + const envParams = isVite + ? [ + `--mode=${platformData.platformNameLowerCase}`, + `--watch`, + "--", + ...cliArgs, + ] + : cliArgs; const additionalNodeArgs = semver.major(process.version) <= 8 ? ["--harmony"] : []; @@ -339,17 +488,19 @@ export class WebpackCompilerService const args = [ ...additionalNodeArgs, - this.getWebpackExecutablePath(projectData), - this.isWebpack5(projectData) ? `build` : null, - `--config=${projectData.webpackConfigPath}`, + this.getBundlerExecutablePath(projectData), + isVite ? "build" : this.isModernBundler(projectData) ? `build` : null, + `--config=${projectData.bundlerConfigPath}`, ...envParams, ].filter(Boolean); - if (prepareData.watch) { - args.push("--watch"); + if (!isVite) { + if (prepareData.watch) { + args.push("--watch"); + } } - const stdio = prepareData.watch ? ["ipc"] : "inherit"; + const stdio = prepareData.watch || isVite ? ["ipc"] : "inherit"; const options: { [key: string]: any } = { cwd: projectData.projectDir, stdio, @@ -357,6 +508,7 @@ export class WebpackCompilerService options.env = { ...process.env, NATIVESCRIPT_WEBPACK_ENV: JSON.stringify(envData), + NATIVESCRIPT_BUNDLER_ENV: JSON.stringify(envData), }; if (this.$hostInfo.isWindows) { Object.assign(options.env, { APPDATA: process.env.appData }); @@ -370,13 +522,15 @@ export class WebpackCompilerService }); } + console.log("args:", args); + const childProcess = this.$childProcess.spawn( process.execPath, args, options, ); - this.webpackProcesses[platformData.platformNameLowerCase] = childProcess; + this.bundlerProcesses[platformData.platformNameLowerCase] = childProcess; await this.$cleanupService.addKillProcess(childProcess.pid.toString()); return childProcess; @@ -467,23 +621,26 @@ export class WebpackCompilerService ); envFlagNames.splice(envFlagNames.indexOf("snapshot"), 1); } else if (this.$hostInfo.isWindows) { - const minWebpackPluginWithWinSnapshotsVersion = "1.3.0"; - const installedWebpackPluginVersion = - await this.$packageInstallationManager.getInstalledDependencyVersion( - WEBPACK_PLUGIN_NAME, - projectData.projectDir, - ); - const hasWebpackPluginWithWinSnapshotsSupport = - !!installedWebpackPluginVersion - ? semver.gte( - semver.coerce(installedWebpackPluginVersion), - minWebpackPluginWithWinSnapshotsVersion, - ) - : true; - if (!hasWebpackPluginWithWinSnapshotsSupport) { - this.$errors.fail( - `In order to generate Snapshots on Windows, please upgrade your Webpack plugin version (npm i ${WEBPACK_PLUGIN_NAME}@latest).`, - ); + if (projectData.bundler === "webpack") { + //TODO: check this use case for webpack5 WEBPACK_PLUGIN_NAME + const minWebpackPluginWithWinSnapshotsVersion = "1.3.0"; + const installedWebpackPluginVersion = + await this.$packageInstallationManager.getInstalledDependencyVersion( + WEBPACK_PLUGIN_NAME, + projectData.projectDir, + ); + const hasWebpackPluginWithWinSnapshotsSupport = + !!installedWebpackPluginVersion + ? semver.gte( + semver.coerce(installedWebpackPluginVersion), + minWebpackPluginWithWinSnapshotsVersion, + ) + : true; + if (!hasWebpackPluginWithWinSnapshotsSupport) { + this.$errors.fail( + `In order to generate Snapshots on Windows, please upgrade your Webpack plugin version (npm i ${WEBPACK_PLUGIN_NAME}@latest).`, + ); + } } } } @@ -562,30 +719,37 @@ export class WebpackCompilerService return hotHash || ""; } - private async stopWebpackForPlatform(platform: string) { - this.$logger.trace(`Stopping webpack watch for platform ${platform}.`); - const webpackProcess = this.webpackProcesses[platform]; - await this.$cleanupService.removeKillProcess(webpackProcess.pid.toString()); - if (webpackProcess) { - webpackProcess.kill("SIGINT"); - delete this.webpackProcesses[platform]; + private async stopBundlerForPlatform(platform: string) { + this.$logger.trace( + `Stopping ${this.getBundler()} watch for platform ${platform}.`, + ); + const bundlerProcess = this.bundlerProcesses[platform]; + await this.$cleanupService.removeKillProcess(bundlerProcess.pid.toString()); + if (bundlerProcess) { + bundlerProcess.kill("SIGINT"); + delete this.bundlerProcesses[platform]; } } private handleHMRMessage( - message: IWebpackMessage, + message: IBundlerMessage, platformData: IPlatformData, projectData: IProjectData, prepareData: IPrepareData, ) { - // handle new webpack hmr packets - this.$logger.trace("Received message from webpack process:", message); + // handle new bundler hmr packets + this.$logger.trace( + `Received message from ${projectData.bundler} process:`, + message, + ); if (message.type !== "compilation") { return; } - this.$logger.trace("Webpack build done!"); + this.$logger.trace( + `${capitalizeFirstLetter(projectData.bundler)} build done!`, + ); const files = message.data.emittedAssets.map((asset: string) => path.join( @@ -624,7 +788,7 @@ export class WebpackCompilerService return; } - this.emit(WEBPACK_COMPILATION_COMPLETE, { + this.emit(BUNDLER_COMPILATION_COMPLETE, { files, staleFiles, hasOnlyHotUpdateFiles: prepareData.hmr, @@ -636,9 +800,19 @@ export class WebpackCompilerService }); } - private getWebpackExecutablePath(projectData: IProjectData): string { - if (this.isWebpack5(projectData)) { - const packagePath = resolvePackagePath("@nativescript/webpack", { + private getBundlerExecutablePath(projectData: IProjectData): string { + const bundler = this.getBundler(); + + if (bundler === "vite") { + const packagePath = resolvePackagePath(`vite`, { + paths: [projectData.projectDir], + }); + + if (packagePath) { + return path.resolve(packagePath, "bin", "vite.js"); + } + } else if (this.isModernBundler(projectData)) { + const packagePath = resolvePackagePath(`@nativescript/${bundler}`, { paths: [projectData.projectDir], }); @@ -658,22 +832,131 @@ export class WebpackCompilerService return path.resolve(packagePath, "bin", "webpack.js"); } - private isWebpack5(projectData: IProjectData): boolean { - const packageJSONPath = resolvePackageJSONPath("@nativescript/webpack", { - paths: [projectData.projectDir], - }); + private isModernBundler(projectData: IProjectData): boolean { + const bundler = this.getBundler(); + switch (bundler) { + case "rspack": + return true; + default: + const packageJSONPath = resolvePackageJSONPath(WEBPACK_PLUGIN_NAME, { + paths: [projectData.projectDir], + }); - if (packageJSONPath) { - const packageData = this.$fs.readJson(packageJSONPath); - const ver = semver.coerce(packageData.version); + if (packageJSONPath) { + const packageData = this.$fs.readJson(packageJSONPath); + const ver = semver.coerce(packageData.version); - if (semver.satisfies(ver, ">= 5.0.0")) { - return true; - } + if (semver.satisfies(ver, ">= 5.0.0")) { + return true; + } + } + break; } return false; } + + public getBundler(): BundlerType { + return this.$projectConfigService.getValue(`bundler`, "webpack"); + } + + private copyViteBundleToNative( + distOutput: string, + destDir: string, + specificFiles: string[] = null, + ) { + // Clean and copy Vite output to native platform folder + console.log(`Copying Vite bundle from "${distOutput}" to "${destDir}"`); + + const fs = require("fs"); + + try { + if (specificFiles) { + // HMR mode: only copy specific files + console.log("🔥 HMR: Copying specific files:", specificFiles); + + // Ensure destination directory exists + fs.mkdirSync(destDir, { recursive: true }); + + // Copy only the specified files + for (const file of specificFiles) { + const srcPath = path.join(distOutput, file); + const destPath = path.join(destDir, file); + + if (!fs.existsSync(srcPath)) continue; + + // create parent dirs + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + + fs.copyFileSync(srcPath, destPath); + + console.log(`🔥 HMR: Copied ${file}`); + } + } else { + // Full build mode: clean and copy everything + console.log("🔥 Full build: Copying all files"); + + // Clean destination directory + if (fs.existsSync(destDir)) { + fs.rmSync(destDir, { recursive: true, force: true }); + } + fs.mkdirSync(destDir, { recursive: true }); + + // Copy all files from dist to platform destination + if (fs.existsSync(distOutput)) { + this.copyRecursiveSync(distOutput, destDir, fs); + } else { + this.$logger.warn( + `Vite output directory does not exist: ${distOutput}`, + ); + } + } + } catch (error) { + this.$logger.warn(`Failed to copy Vite bundle: ${error.message}`); + } + } + + private notifyHMRClients(message: any) { + // Send WebSocket notification to HMR clients + try { + const WebSocket = require("ws"); + + // Try to connect to HMR bridge and send notification + const ws = new WebSocket("ws://localhost:24678"); + + ws.on("open", () => { + console.log("🔥 Sending HMR notification to bridge:", message.type); + ws.send(JSON.stringify(message)); + ws.close(); + }); + + ws.on("error", () => { + // HMR bridge not available, which is fine + console.log("🔥 HMR bridge not available (this is normal without HMR)"); + }); + } catch (error) { + // WebSocket not available, which is fine + console.log("🔥 WebSocket not available for HMR notifications"); + } + } + + private copyRecursiveSync(src: string, dest: string, fs: any) { + for (const entry of fs.readdirSync(src, { withFileTypes: true })) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + fs.mkdirSync(destPath, { recursive: true }); + this.copyRecursiveSync(srcPath, destPath, fs); + } else if (entry.isFile() || entry.isSymbolicLink()) { + fs.copyFileSync(srcPath, destPath); + } + } + } +} + +function capitalizeFirstLetter(val: string) { + return String(val).charAt(0).toUpperCase() + String(val).slice(1); } -injector.register("webpackCompilerService", WebpackCompilerService); +injector.register("bundlerCompilerService", BundlerCompilerService); diff --git a/lib/services/webpack/webpack.d.ts b/lib/services/bundler/bundler.ts similarity index 89% rename from lib/services/webpack/webpack.d.ts rename to lib/services/bundler/bundler.ts index e3a8dddd8b..08e6bda859 100644 --- a/lib/services/webpack/webpack.d.ts +++ b/lib/services/bundler/bundler.ts @@ -18,21 +18,21 @@ import { import { INotConfiguredEnvOptions } from "../../common/definitions/commands"; declare global { - interface IWebpackCompilerService extends EventEmitter { + interface IBundlerCompilerService extends EventEmitter { compileWithWatch( platformData: IPlatformData, projectData: IProjectData, - prepareData: IPrepareData + prepareData: IPrepareData, ): Promise; compileWithoutWatch( platformData: IPlatformData, projectData: IProjectData, - prepareData: IPrepareData + prepareData: IPrepareData, ): Promise; - stopWebpackCompiler(platform: string): Promise; + stopBundlerCompiler(platform: string): Promise; } - interface IWebpackEnvOptions { + interface IBundlerEnvOptions { sourceMap?: boolean; uglify?: boolean; production?: boolean; @@ -42,19 +42,19 @@ declare global { checkForChanges( platformData: IPlatformData, projectData: IProjectData, - prepareData: IPrepareData + prepareData: IPrepareData, ): Promise; getPrepareInfoFilePath(platformData: IPlatformData): string; getPrepareInfo(platformData: IPlatformData): IPrepareInfo; savePrepareInfo( platformData: IPlatformData, projectData: IProjectData, - prepareData: IPrepareData + prepareData: IPrepareData, ): Promise; setNativePlatformStatus( platformData: IPlatformData, projectData: IProjectData, - addedPlatform: IAddedNativePlatform + addedPlatform: IAddedNativePlatform, ): void; currentChanges: IProjectChangesInfo; } @@ -68,10 +68,14 @@ declare global { hasNativeChanges: boolean; } - interface IWebpackEmitMessage { + interface IBundlerEmitMessage { emittedFiles: string[]; chunkFiles: string[]; hash: string; + changedFiles?: string[]; + isHMR?: boolean; + filesToCopy?: string[]; + buildType?: string; } interface IPlatformProjectService @@ -81,12 +85,12 @@ declare global { validate( projectData: IProjectData, options: IOptions, - notConfiguredEnvOptions?: INotConfiguredEnvOptions + notConfiguredEnvOptions?: INotConfiguredEnvOptions, ): Promise; createProject( frameworkDir: string, frameworkVersion: string, - projectData: IProjectData + projectData: IProjectData, ): Promise; interpolateData(projectData: IProjectData): Promise; interpolateConfigurationFile(projectData: IProjectData): void; @@ -108,13 +112,13 @@ declare global { validateOptions( projectId?: string, provision?: true | string, - teamId?: true | string + teamId?: true | string, ): Promise; buildProject( projectRoot: string, projectData: IProjectData, - buildConfig: T + buildConfig: T, ): Promise; /** @@ -125,7 +129,7 @@ declare global { */ prepareProject( projectData: IProjectData, - prepareData: T + prepareData: T, ): Promise; /** @@ -146,7 +150,7 @@ declare global { preparePluginNativeCode( pluginData: IPluginData, - options?: any + options?: any, ): Promise; /** @@ -157,17 +161,17 @@ declare global { */ removePluginNativeCode( pluginData: IPluginData, - projectData: IProjectData + projectData: IProjectData, ): Promise; beforePrepareAllPlugins( projectData: IProjectData, - dependencies?: IDependencyData[] + dependencies?: IDependencyData[], ): Promise; handleNativeDependenciesChange( projectData: IProjectData, - opts: IRelease + opts: IRelease, ): Promise; /** @@ -178,11 +182,11 @@ declare global { cleanDeviceTempFolder( deviceIdentifier: string, - projectData: IProjectData + projectData: IProjectData, ): Promise; processConfigurationFilesFromAppResources( projectData: IProjectData, - opts: { release: boolean } + opts: { release: boolean }, ): Promise; /** @@ -214,7 +218,7 @@ declare global { checkForChanges( changeset: IProjectChangesInfo, prepareData: T, - projectData: IProjectData + projectData: IProjectData, ): Promise; /** diff --git a/package-lock.json b/package-lock.json index 0a968451af..fe0a393e74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nativescript", - "version": "8.9.4", + "version": "9.0.0-alpha.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nativescript", - "version": "8.9.4", + "version": "9.0.0-alpha.5", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -15,11 +15,9 @@ "@npmcli/arborist": "^9.0.0", "@rigor789/resolve-package-path": "1.0.7", "@rigor789/trapezedev-project": "7.1.2", - "ansi-colors": "^4.1.3", "archiver": "^7.0.1", "axios": "1.11.0", "byline": "5.0.0", - "chalk": "4.1.2", "chokidar": "4.0.3", "cli-table3": "0.6.5", "color": "4.2.3", @@ -28,7 +26,6 @@ "email-validator": "2.0.4", "esprima": "4.0.1", "font-finder": "1.1.0", - "glob": "11.0.1", "ios-device-lib": "0.9.4", "ios-mobileprovision-finder": "1.2.1", "ios-sim-portable": "4.5.1", @@ -83,7 +80,6 @@ "@types/chai-as-promised": "8.0.1", "@types/color": "4.2.0", "@types/convert-source-map": "2.0.3", - "@types/glob": "^8.1.0", "@types/lodash": "4.17.15", "@types/marked-terminal": "^6.1.1", "@types/node": "^22.0.0", @@ -119,7 +115,6 @@ "grunt-ts": "6.0.0-beta.22", "husky": "9.1.7", "istanbul": "0.4.5", - "latest-version": "9.0.0", "lint-staged": "~15.4.3", "mocha": "11.1.0", "sinon": "19.0.2", @@ -857,9 +852,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -1108,41 +1103,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/map-workspaces/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/map-workspaces/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1158,31 +1118,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@npmcli/map-workspaces/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@npmcli/map-workspaces/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@npmcli/metavuln-calculator": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-9.0.1.tgz", @@ -1235,81 +1170,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/package-json/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/package-json/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@npmcli/package-json/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@npmcli/promise-spawn": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.2.tgz", @@ -1379,51 +1239,6 @@ "node": ">=14" } }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "license": "ISC" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@prettier/plugin-xml": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@prettier/plugin-xml/-/plugin-xml-2.2.0.tgz", @@ -1839,17 +1654,6 @@ "@types/node": "*" } }, - "node_modules/@types/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "^5.1.2", - "@types/node": "*" - } - }, "node_modules/@types/lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz", @@ -1871,9 +1675,9 @@ } }, "node_modules/@types/marked-terminal/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -1896,13 +1700,6 @@ "node": ">= 18" } }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -1910,9 +1707,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.17.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.0.tgz", - "integrity": "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ==", + "version": "22.18.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz", + "integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2111,6 +1908,32 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@types/shelljs/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/shelljs/node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@types/shelljs/node_modules/minimatch": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", @@ -2137,6 +1960,23 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/@types/shelljs/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@types/sinon": { "version": "17.0.4", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", @@ -2367,6 +2207,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2388,9 +2229,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "license": "MIT", "engines": { "node": ">=12" @@ -2625,81 +2466,6 @@ "node": ">= 14" } }, - "node_modules/archiver-utils/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/archiver-utils/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/archiver-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/archiver-utils/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/archiver-utils/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -2915,9 +2681,9 @@ "license": "MIT" }, "node_modules/bare-events": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.0.tgz", - "integrity": "sha512-EKZ5BTXYExaNqi3I3f9RtEsaI/xBSGjE0XZCZilPzFAV/goswFHuPd9jEZlPIZ/iNZJwDSao9qRiScySz7MbQg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.1.tgz", + "integrity": "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==", "license": "Apache-2.0", "optional": true }, @@ -3190,61 +2956,11 @@ "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/cacache/node_modules/minipass": { @@ -3256,22 +2972,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/cacache/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -3895,24 +3595,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, "node_modules/continuable-cache": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", @@ -5240,16 +4922,6 @@ "node": ">=6" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -7190,24 +6862,21 @@ "license": "ISC" }, "node_modules/glob": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", - "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": "20 || >=22" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -7224,6 +6893,21 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob/node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -8607,9 +8291,9 @@ } }, "node_modules/ios-mobileprovision-finder/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -8811,24 +8495,14 @@ } }, "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, "engines": { "node": ">= 12" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "license": "BSD-3-Clause" - }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -9339,18 +9013,18 @@ } }, "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": "20 || >=22" - }, "funding": { "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/jimp": { @@ -9417,12 +9091,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "license": "MIT" - }, "node_modules/jsmin2": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/jsmin2/-/jsmin2-1.2.1.tgz", @@ -9461,9 +9129,9 @@ "license": "ISC" }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -9535,9 +9203,9 @@ } }, "node_modules/ky": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/ky/-/ky-1.8.2.tgz", - "integrity": "sha512-XybQJ3d4Ea1kI27DoelE5ZCT3bSJlibYTtQuMsyzKox3TMyayw1asgQdl54WroAm+fIA3ZCr8zXW2RpR7qWVpA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.9.1.tgz", + "integrity": "sha512-WGzpBn57klhxsqRTEABAqF4tqTtqCuxoTIv9m6nIZtMMFTVcrHp7bRDWblzFIfqkb47+OhTztOgHn6A4xItmqg==", "dev": true, "license": "MIT", "engines": { @@ -9724,9 +9392,9 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -10058,9 +9726,9 @@ } }, "node_modules/loupe": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", - "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, @@ -10189,9 +9857,9 @@ } }, "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -10678,43 +10346,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/mocha/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mocha/node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -10728,22 +10359,6 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/mocha/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -10770,33 +10385,6 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mocha/node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -11031,9 +10619,9 @@ } }, "node_modules/node-gyp": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.3.0.tgz", - "integrity": "sha512-9J0+C+2nt3WFuui/mC46z2XCZ21/cKlFDuywULmseD/LlmnOrSeEAE4c/1jw6aybXLmpZnQY3/LmOJfgyHIcng==", + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.4.2.tgz", + "integrity": "sha512-3gD+6zsrLQH7DyYOUIutaauuXrcyxeTPyQuZQCQoNPZMHMMS5m4y0xclNpvYzoK3VNzuyxT6eF4mkIL4WSZ1eQ==", "license": "MIT", "dependencies": { "env-paths": "^2.2.0", @@ -11298,9 +10886,9 @@ } }, "node_modules/npm-install-checks": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.1.tgz", - "integrity": "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.2.tgz", + "integrity": "sha512-z9HJBCYw9Zr8BqXcllKIs5nI+QggAImbBdHphOzVYrz2CB4iQ6FzWyKmlqDZua+51nAu7FcemlbTc9VgQN5XDQ==", "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" @@ -11784,25 +11372,6 @@ "node": ">=6" } }, - "node_modules/package-json": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", - "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ky": "^1.2.0", - "registry-auth-token": "^5.0.2", - "registry-url": "^6.0.1", - "semver": "^7.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -12132,30 +11701,21 @@ } }, "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": "20 || >=22" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/path-scurry/node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -12330,9 +11890,9 @@ } }, "node_modules/plist/node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -12500,13 +12060,6 @@ "signal-exit": "^3.0.2" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true, - "license": "ISC" - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -12639,39 +12192,6 @@ "dev": true, "license": "MIT" }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/read-cmd-shim": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-5.0.0.tgz", @@ -13089,35 +12609,6 @@ "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", "license": "MIT" }, - "node_modules/registry-auth-token": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", - "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -14249,12 +13740,12 @@ } }, "node_modules/socks": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz", - "integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==", + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", + "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" }, "engines": { @@ -15048,10 +14539,13 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -15074,9 +14568,9 @@ } }, "node_modules/tmp": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", - "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "license": "MIT", "engines": { "node": ">=14.14" diff --git a/package.json b/package.json index 60976bca6d..b055efd158 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nativescript", "main": "./lib/nativescript-cli-lib.js", - "version": "8.9.4", + "version": "9.0.0-alpha.5", "author": "NativeScript ", "description": "Command-line interface for building NativeScript projects", "bin": { @@ -59,11 +59,9 @@ "@npmcli/arborist": "^9.0.0", "@rigor789/resolve-package-path": "1.0.7", "@rigor789/trapezedev-project": "7.1.2", - "ansi-colors": "^4.1.3", "archiver": "^7.0.1", "axios": "1.11.0", "byline": "5.0.0", - "chalk": "4.1.2", "chokidar": "4.0.3", "cli-table3": "0.6.5", "color": "4.2.3", @@ -72,7 +70,6 @@ "email-validator": "2.0.4", "esprima": "4.0.1", "font-finder": "1.1.0", - "glob": "11.0.1", "ios-device-lib": "0.9.4", "ios-mobileprovision-finder": "1.2.1", "ios-sim-portable": "4.5.1", @@ -121,7 +118,6 @@ "@types/chai-as-promised": "8.0.1", "@types/color": "4.2.0", "@types/convert-source-map": "2.0.3", - "@types/glob": "^8.1.0", "@types/lodash": "4.17.15", "@types/marked-terminal": "^6.1.1", "@types/node": "^22.0.0", @@ -157,7 +153,6 @@ "grunt-ts": "6.0.0-beta.22", "husky": "9.1.7", "istanbul": "0.4.5", - "latest-version": "9.0.0", "lint-staged": "~15.4.3", "mocha": "11.1.0", "sinon": "19.0.2", @@ -183,4 +178,4 @@ "lint-staged": { "*.ts": "prettier --write" } -} \ No newline at end of file +} diff --git a/packages/doctor/src/android-tools-info.ts b/packages/doctor/src/android-tools-info.ts index 7c5dfb67e4..90b7ad5989 100644 --- a/packages/doctor/src/android-tools-info.ts +++ b/packages/doctor/src/android-tools-info.ts @@ -71,11 +71,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { private childProcess: ChildProcess, private fs: FileSystem, private hostInfo: HostInfo, - private helpers: Helpers + private helpers: Helpers, ) {} public getToolsInfo( - config: Partial = {} + config: Partial = {}, ): NativeScriptDoctor.IAndroidToolsInfoData { if (!this.toolsInfo) { const infoData: NativeScriptDoctor.IAndroidToolsInfoData = @@ -84,7 +84,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { infoData.installedTargets = this.getInstalledTargets(); infoData.compileSdkVersion = this.getCompileSdk( infoData.installedTargets, - config.projectDir + config.projectDir, ); infoData.buildToolsVersion = this.getBuildToolsVersion(config.projectDir); @@ -95,14 +95,14 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { } public validateInfo( - config: Partial = {} + config: Partial = {}, ): NativeScriptDoctor.IWarning[] { const errors: NativeScriptDoctor.IWarning[] = []; const toolsInfoData = this.getToolsInfo(config); const isAndroidHomeValid = this.isAndroidHomeValid(); if (!toolsInfoData.compileSdkVersion) { const supportedTargetsForAndroidRuntime = this.getSupportedTargets( - config.projectDir + config.projectDir, ); errors.push({ warning: [ @@ -110,7 +110,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { `To be able to build for Android with your current android runtime, install one of the following supported Android SDK targets:`, ...supportedTargetsForAndroidRuntime.map((target) => ` ${target}`), `Supported targets vary based on what android runtime you have installed. Currently your app uses @nativescript/android ${this.getRuntimeVersion( - { projectDir: config.projectDir } + { projectDir: config.projectDir }, )}`, ].join("\n"), additionalInformation: `Run \`\$ ${this.getPathToSdkManagementTool()}\` to manage your Android SDK versions.`, @@ -121,7 +121,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { if (!toolsInfoData.buildToolsVersion) { const buildToolsRange = this.getBuildToolsRange(config.projectDir); const versionRangeMatches = buildToolsRange.match( - /^.*?([\d\.]+)\s+.*?([\d\.]+)$/ + /^.*?([\d\.]+)\s+.*?([\d\.]+)$/, ); let message = `You can install any version in the following range: '${buildToolsRange}'.`; @@ -155,7 +155,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { } public static unsupportedJavaMessage( - installedJavaCompilerVersion: string + installedJavaCompilerVersion: string, ): string { return `Javac version ${installedJavaCompilerVersion} is not supported. You must install a java version greater than ${ AndroidToolsInfo.MIN_JAVA_VERSION @@ -169,7 +169,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { public validateJavacVersion( installedJavaCompilerVersion: string, projectDir?: string, - runtimeVersion?: string + runtimeVersion?: string, ): NativeScriptDoctor.IWarning[] { const errors: NativeScriptDoctor.IWarning[] = []; @@ -196,17 +196,17 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { if ( semver.lt( installedJavaCompilerSemverVersion, - AndroidToolsInfo.MIN_JAVA_VERSION + AndroidToolsInfo.MIN_JAVA_VERSION, ) || (AndroidToolsInfo.MAX_JAVA_VERSION ? semver.gte( installedJavaCompilerSemverVersion, - AndroidToolsInfo.MAX_JAVA_VERSION - ) + AndroidToolsInfo.MAX_JAVA_VERSION, + ) : false) ) { warning = AndroidToolsInfo.unsupportedJavaMessage( - installedJavaCompilerVersion + installedJavaCompilerVersion, ); } else { runtimeVersion = this.getRuntimeVersion({ runtimeVersion, projectDir }); @@ -288,7 +288,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { }); } else if ( expectedDirectoriesInAndroidHome.map((dir) => - this.fs.exists(path.join(this.androidHome, dir)) + this.fs.exists(path.join(this.androidHome, dir)), ).length === 0 ) { errors.push({ @@ -316,7 +316,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { if (!_.includes(supportedTargets, newTarget)) { const supportedVersions = supportedTargets.sort(); const minSupportedVersion = this.parseAndroidSdkString( - _.first(supportedVersions) + _.first(supportedVersions), ); if (!targetSupported && targetSdk && targetSdk < minSupportedVersion) { @@ -339,7 +339,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { const newTarget = `${this.ANDROID_TARGET_PREFIX}-${targetSdk}`; const targetSupported = _.includes( this.getSupportedTargets(projectDir), - newTarget + newTarget, ); if ( @@ -369,7 +369,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { const pathToEmulatorFromAndroidStudio = path.join( this.androidHome, emulatorExecutableName, - emulatorExecutableName + emulatorExecutableName, ); const realFilePath = this.hostInfo.isWindows ? `${pathToEmulatorFromAndroidStudio}.exe` @@ -381,7 +381,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { this.pathToEmulatorExecutable = path.join( this.androidHome, "tools", - emulatorExecutableName + emulatorExecutableName, ); } } @@ -403,12 +403,12 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { this.androidHome, "tools", "bin", - sdkmanagerName + sdkmanagerName, ); const pathToAndroidExecutable = path.join( this.androidHome, "tools", - "android" + "android", ); const pathToExecutable = this.fs.exists(pathToSdkmanager) ? pathToSdkmanager @@ -416,7 +416,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { sdkManagementToolPath = pathToExecutable.replace( this.androidHome, - this.hostInfo.isWindows ? "%ANDROID_HOME%" : "$ANDROID_HOME" + this.hostInfo.isWindows ? "%ANDROID_HOME%" : "$ANDROID_HOME", ); } @@ -425,15 +425,15 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { private getCompileSdk( installedTargets: string[], - projectDir: string + projectDir: string, ): number { const latestValidAndroidTarget = this.getLatestValidAndroidTarget( installedTargets, - projectDir + projectDir, ); if (latestValidAndroidTarget) { const integerVersion = this.parseAndroidSdkString( - latestValidAndroidTarget + latestValidAndroidTarget, ); if ( @@ -483,7 +483,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { const buildToolsRange = this.getBuildToolsRange(projectDir); buildToolsVersion = this.getMatchingDir( pathToBuildTools, - buildToolsRange + buildToolsRange, ); } @@ -492,17 +492,17 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { private getLatestValidAndroidTarget( installedTargets: string[], - projectDir: string + projectDir: string, ): string { return _.findLast( this.getSupportedTargets(projectDir).sort(), - (supportedTarget) => _.includes(installedTargets, supportedTarget) + (supportedTarget) => _.includes(installedTargets, supportedTarget), ); } private parseAndroidSdkString(androidSdkString: string): number { return parseInt( - androidSdkString.replace(`${this.ANDROID_TARGET_PREFIX}-`, "") + androidSdkString.replace(`${this.ANDROID_TARGET_PREFIX}-`, ""), ); } @@ -523,7 +523,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { const supportedTargets = this.getSupportedTargets(projectDir); return this.parseAndroidSdkString( - supportedTargets.sort()[supportedTargets.length - 1] + supportedTargets.sort()[supportedTargets.length - 1], ); } @@ -581,7 +581,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { depName === Constants.ANDROID_SCOPED_RUNTIME || depName === Constants.ANDROID_OLD_RUNTIME ); - } + }, ); if (foundRuntime) { @@ -593,7 +593,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { `${foundRuntime}/package.json`, { paths: [projectDir], - } + }, ); version = require(packagePath).version; } catch (err) { @@ -636,7 +636,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { if (!semver.validRange(runtimeVersion)) { try { const npmViewOutput = this.childProcess.execSync( - `npm view ${runtimePackage.name} dist-tags --json` + `npm view ${runtimePackage.name} dist-tags --json`, ); const jsonNpmViewOutput = JSON.parse(npmViewOutput); @@ -650,7 +650,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { if (runtimeVersion && !semver.validRange(runtimeVersion)) { // If we got here, something terribly wrong happened. throw new Error( - `The determined Android runtime version ${runtimeVersion} is not valid. Unable to verify if the current system is setup for Android development.` + `The determined Android runtime version ${runtimeVersion} is not valid. Unable to verify if the current system is setup for Android development.`, ); } @@ -661,7 +661,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { private getMaxSupportedCompileVersion( config: Partial & { runtimeVersion?: string; - } + }, ): number { if ( config.runtimeVersion && @@ -670,7 +670,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo { return 28; } return this.parseAndroidSdkString( - _.last(this.getSupportedTargets(config.projectDir).sort()) + _.last(this.getSupportedTargets(config.projectDir).sort()), ); } } diff --git a/packages/doctor/test/android-tools-info.ts b/packages/doctor/test/android-tools-info.ts index 90a24bb552..89d1eb3f31 100644 --- a/packages/doctor/test/android-tools-info.ts +++ b/packages/doctor/test/android-tools-info.ts @@ -42,7 +42,7 @@ describe("androidToolsInfo", () => { devDependencies: { "@nativescript/android": runtimeVersion, }, - } + } : null; }, readDirectory: (path: string) => { @@ -114,7 +114,7 @@ describe("androidToolsInfo", () => { const assertSupportedRange = ( runtimeVersion: string, min: number, - max: number + max: number, ) => { let cnt = 0; const androidToolsInfo = getAndroidToolsInfo(runtimeVersion); @@ -211,7 +211,7 @@ describe("androidToolsInfo", () => { const androidToolsInfo = getAndroidToolsInfo(runtimeVersion); const actualWarnings = androidToolsInfo.validateJavacVersion( javacVersion, - "/Users/username/projectDir" + "/Users/username/projectDir", ); let expectedWarnings: NativeScriptDoctor.IWarning[] = []; @@ -228,7 +228,7 @@ describe("androidToolsInfo", () => { assert.deepEqual(actualWarnings, expectedWarnings); }); - } + }, ); const npmTagsTestData: ITestData[] = [ @@ -323,12 +323,12 @@ describe("androidToolsInfo", () => { childProcess, fs, hostInfo, - helpers + helpers, ); const actualWarnings = androidToolsInfo.validateJavacVersion( javacVersion, - "/Users/username/projectDir" + "/Users/username/projectDir", ); let expectedWarnings: NativeScriptDoctor.IWarning[] = []; if (warnings && warnings.length) { @@ -345,10 +345,10 @@ describe("androidToolsInfo", () => { assert.deepEqual(actualWarnings, expectedWarnings); assert.equal( execSyncCommand, - "npm view tns-android dist-tags --json" + "npm view tns-android dist-tags --json", ); }); - } + }, ); }); diff --git a/test/controllers/prepare-controller.ts b/test/controllers/prepare-controller.ts index a8bf78ad3b..e3982de1e4 100644 --- a/test/controllers/prepare-controller.ts +++ b/test/controllers/prepare-controller.ts @@ -38,7 +38,7 @@ function createTestInjector(data: { hasNativeChanges: boolean }): IInjector { }, }); - injector.register("webpackCompilerService", { + injector.register("bundlerCompilerService", { on: () => ({}), emit: () => ({}), compileWithWatch: async () => { @@ -119,7 +119,7 @@ describe("prepareController", () => { injector.resolve("prepareController"); const prepareNativePlatformService = injector.resolve( - "prepareNativePlatformService" + "prepareNativePlatformService", ); prepareNativePlatformService.prepareNativePlatform = async () => { const nativeFilesWatcher = (prepareController).watchersData[ @@ -128,7 +128,7 @@ describe("prepareController", () => { nativeFilesWatcher.emit( "all", "change", - "my/project/App_Resources/some/file" + "my/project/App_Resources/some/file", ); isNativePrepareCalled = true; return false; diff --git a/test/project-data.ts b/test/project-data.ts index 7ce33a1320..5b8c747bd1 100644 --- a/test/project-data.ts +++ b/test/project-data.ts @@ -56,14 +56,16 @@ describe("projectData", () => { configData?: { shared?: boolean; webpackConfigPath?: string; + bundlerConfigPath?: string; projectName?: string; + bundler?: string; }; }): IProjectData => { const testInjector = createTestInjector(); const fs = testInjector.resolve("fs"); testInjector.register( "projectConfigService", - stubs.ProjectConfigServiceStub.initWithConfig(opts?.configData) + stubs.ProjectConfigServiceStub.initWithConfig(opts?.configData), ); fs.exists = (filePath: string) => { @@ -98,7 +100,7 @@ describe("projectData", () => { const assertProjectType = ( dependencies: any, devDependencies: any, - expectedProjecType: string + expectedProjecType: string, ) => { const projectData = prepareTest({ packageJsonData: { @@ -125,7 +127,7 @@ describe("projectData", () => { assertProjectType( { "nativescript-vue": "*" }, { typescript: "*" }, - "Vue.js" + "Vue.js", ); }); @@ -141,7 +143,7 @@ describe("projectData", () => { assertProjectType( null, { "nativescript-dev-typescript": "*" }, - "Pure TypeScript" + "Pure TypeScript", ); }); @@ -195,13 +197,13 @@ describe("projectData", () => { const projectData = prepareTest(); assert.equal( projectData.webpackConfigPath, - path.join(projectDir, "webpack.config.js") + path.join(projectDir, "webpack.config.js"), ); }); it("returns correct path when full path is set in nsconfig.json", () => { const pathToConfig = path.resolve( - path.join("/testDir", "innerDir", "mywebpack.config.js") + path.join("/testDir", "innerDir", "mywebpack.config.js"), ); const projectData = prepareTest({ configData: { webpackConfigPath: pathToConfig }, @@ -211,7 +213,7 @@ describe("projectData", () => { it("returns correct path when relative path is set in nsconfig.json", () => { const pathToConfig = path.resolve( - path.join("projectDir", "innerDir", "mywebpack.config.js") + path.join("projectDir", "innerDir", "mywebpack.config.js"), ); const projectData = prepareTest({ configData: { @@ -221,4 +223,81 @@ describe("projectData", () => { assert.equal(projectData.webpackConfigPath, pathToConfig); }); }); + + describe("bundlerConfigPath", () => { + it("default path to webpack.config.js is set when nsconfig.json does not set value", () => { + const projectData = prepareTest(); + assert.equal( + projectData.bundlerConfigPath, + path.join(projectDir, "webpack.config.js"), + ); + }); + + it("should use webpackConfigPath property when bundlerConfigPath is not defined", () => { + const pathToConfig = path.resolve( + path.join("/testDir", "innerDir", "mywebpack.config.js"), + ); + const projectData = prepareTest({ + configData: { webpackConfigPath: pathToConfig }, + }); + assert.equal(projectData.bundlerConfigPath, pathToConfig); + }); + + it("returns correct path when full path is set in nsconfig.json", () => { + const pathToConfig = path.resolve( + path.join("/testDir", "innerDir", "mywebpack.config.js"), + ); + const projectData = prepareTest({ + configData: { bundlerConfigPath: pathToConfig }, + }); + assert.equal(projectData.bundlerConfigPath, pathToConfig); + }); + + it("returns correct path when relative path is set in nsconfig.json", () => { + const pathToConfig = path.resolve( + path.join("projectDir", "innerDir", "mywebpack.config.js"), + ); + const projectData = prepareTest({ + configData: { + bundlerConfigPath: path.join("./innerDir", "mywebpack.config.js"), + }, + }); + assert.equal(projectData.bundlerConfigPath, pathToConfig); + }); + + it("should use bundlerConfigPath instead of webpackConfigPath if both are defined.", () => { + const pathToConfig = path.resolve( + path.join("projectDir", "innerDir", "myrspack.config.js"), + ); + const projectData = prepareTest({ + configData: { + webpackConfigPath: path.join("./innerDir", "mywebpack.config.js"), + bundlerConfigPath: path.join("./innerDir", "myrspack.config.js"), + }, + }); + assert.equal(projectData.bundlerConfigPath, pathToConfig); + }); + }); + + describe("bundler", () => { + it("sets bundler to 'webpack' by default when nsconfig.json does not specify a bundler", () => { + const projectData = prepareTest(); + assert.equal(projectData.bundler, "webpack"); + }); + + it("sets bundler to 'webpack' when explicitly defined in nsconfig.json", () => { + const projectData = prepareTest({ configData: { bundler: "webpack" } }); + assert.equal(projectData.bundler, "webpack"); + }); + + it("sets bundler to 'rspack' when explicitly defined in nsconfig.json", () => { + const projectData = prepareTest({ configData: { bundler: "rspack" } }); + assert.equal(projectData.bundler, "rspack"); + }); + + it("sets bundler to 'vite' when explicitly defined in nsconfig.json", () => { + const projectData = prepareTest({ configData: { bundler: "vite" } }); + assert.equal(projectData.bundler, "vite"); + }); + }); }); diff --git a/test/services/webpack/webpack-compiler-service.ts b/test/services/bundler/bundler-compiler-service.ts similarity index 62% rename from test/services/webpack/webpack-compiler-service.ts rename to test/services/bundler/bundler-compiler-service.ts index d15cccc430..49d69a55f4 100644 --- a/test/services/webpack/webpack-compiler-service.ts +++ b/test/services/bundler/bundler-compiler-service.ts @@ -1,5 +1,5 @@ import { Yok } from "../../../lib/common/yok"; -import { WebpackCompilerService } from "../../../lib/services/webpack/webpack-compiler-service"; +import { BundlerCompilerService } from "../../../lib/services/bundler/bundler-compiler-service"; import { assert } from "chai"; import { ErrorsStub } from "../../stubs"; import { IInjector } from "../../../lib/common/definitions/yok"; @@ -23,7 +23,7 @@ function createTestInjector(): IInjector { testInjector.register("packageManager", { getPackageManagerName: async () => "npm", }); - testInjector.register("webpackCompilerService", WebpackCompilerService); + testInjector.register("bundlerCompilerService", BundlerCompilerService); testInjector.register("childProcess", {}); testInjector.register("hooksService", {}); testInjector.register("hostInfo", {}); @@ -33,6 +33,9 @@ function createTestInjector(): IInjector { testInjector.register("packageInstallationManager", {}); testInjector.register("mobileHelper", {}); testInjector.register("cleanupService", {}); + testInjector.register("projectConfigService", { + getValue: (key: string, defaultValue?: string) => defaultValue, + }); testInjector.register("fs", { exists: (filePath: string) => true, }); @@ -40,23 +43,23 @@ function createTestInjector(): IInjector { return testInjector; } -describe("WebpackCompilerService", () => { +describe("BundlerCompilerService", () => { let testInjector: IInjector = null; - let webpackCompilerService: WebpackCompilerService = null; + let bundlerCompilerService: BundlerCompilerService = null; beforeEach(() => { testInjector = createTestInjector(); - webpackCompilerService = testInjector.resolve(WebpackCompilerService); + bundlerCompilerService = testInjector.resolve(BundlerCompilerService); }); describe("getUpdatedEmittedFiles", () => { // backwards compatibility with old versions of nativescript-dev-webpack it("should return only hot updates when nextHash is not provided", async () => { - const result = webpackCompilerService.getUpdatedEmittedFiles( + const result = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, null, - iOSPlatformName + iOSPlatformName, ); const expectedEmittedFiles = [ "bundle.hash1.hot-update.js", @@ -65,19 +68,19 @@ describe("WebpackCompilerService", () => { assert.deepStrictEqual(result.emittedFiles, expectedEmittedFiles); }); - // 2 successful webpack compilations + // 2 successful bundler compilations it("should return only hot updates when nextHash is provided", async () => { - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, "hash2", - iOSPlatformName + iOSPlatformName, ); - const result = webpackCompilerService.getUpdatedEmittedFiles( + const result = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash2"), chunkFiles, "hash3", - iOSPlatformName + iOSPlatformName, ); assert.deepStrictEqual(result.emittedFiles, [ @@ -85,19 +88,19 @@ describe("WebpackCompilerService", () => { "hash2.hot-update.json", ]); }); - // 1 successful webpack compilation, n compilations with no emitted files - it("should return all files when there is a webpack compilation with no emitted files", () => { - webpackCompilerService.getUpdatedEmittedFiles( + // 1 successful bundler compilation, n compilations with no emitted files + it("should return all files when there is a bundler compilation with no emitted files", () => { + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, "hash2", - iOSPlatformName + iOSPlatformName, ); - const result = webpackCompilerService.getUpdatedEmittedFiles( + const result = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash4"), chunkFiles, "hash5", - iOSPlatformName + iOSPlatformName, ); assert.deepStrictEqual(result.emittedFiles, [ @@ -107,25 +110,25 @@ describe("WebpackCompilerService", () => { "hash4.hot-update.json", ]); }); - // 1 successful webpack compilation, n compilations with no emitted files, 1 successful webpack compilation + // 1 successful bundler compilation, n compilations with no emitted files, 1 successful bundler compilation it("should return only hot updates after fixing the compilation error", () => { - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, "hash2", - iOSPlatformName + iOSPlatformName, ); - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash5"), chunkFiles, "hash6", - iOSPlatformName + iOSPlatformName, ); - const result = webpackCompilerService.getUpdatedEmittedFiles( + const result = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash6"), chunkFiles, "hash7", - iOSPlatformName + iOSPlatformName, ); assert.deepStrictEqual(result.emittedFiles, [ @@ -133,16 +136,16 @@ describe("WebpackCompilerService", () => { "hash6.hot-update.json", ]); }); - // 1 webpack compilation with no emitted files + // 1 bundler compilation with no emitted files it("should return all files when first compilation on livesync change is not successful", () => { - (webpackCompilerService).expectedHashes = { + (bundlerCompilerService).expectedHashes = { ios: "hash1", }; - const result = webpackCompilerService.getUpdatedEmittedFiles( + const result = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, "hash2", - iOSPlatformName + iOSPlatformName, ); assert.deepStrictEqual(result.emittedFiles, [ @@ -151,48 +154,48 @@ describe("WebpackCompilerService", () => { ]); }); it("should return correct hashes when there are more than one platform", () => { - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash1"), chunkFiles, "hash2", - iOSPlatformName + iOSPlatformName, ); - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash3"), chunkFiles, "hash4", - androidPlatformName + androidPlatformName, ); - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash2"), chunkFiles, "hash5", - iOSPlatformName + iOSPlatformName, ); - webpackCompilerService.getUpdatedEmittedFiles( + bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash4"), chunkFiles, "hash6", - androidPlatformName + androidPlatformName, ); - const iOSResult = webpackCompilerService.getUpdatedEmittedFiles( + const iOSResult = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash5"), chunkFiles, "hash7", - iOSPlatformName + iOSPlatformName, ); assert.deepStrictEqual(iOSResult.emittedFiles, [ "bundle.hash5.hot-update.js", "hash5.hot-update.json", ]); - const androidResult = webpackCompilerService.getUpdatedEmittedFiles( + const androidResult = bundlerCompilerService.getUpdatedEmittedFiles( getAllEmittedFiles("hash6"), chunkFiles, "hash8", - androidPlatformName + androidPlatformName, ); assert.deepStrictEqual(androidResult.emittedFiles, [ "bundle.hash6.hot-update.js", @@ -202,33 +205,33 @@ describe("WebpackCompilerService", () => { }); describe("compileWithWatch", () => { - it("fails when the value set for webpackConfigPath is not existant file", async () => { - const webpackConfigPath = "some path.js"; + it("fails when the value set for bundlerConfigPath is not existant file", async () => { + const bundlerConfigPath = "some path.js"; testInjector.resolve("fs").exists = (filePath: string) => - filePath !== webpackConfigPath; + filePath !== bundlerConfigPath; await assert.isRejected( - webpackCompilerService.compileWithWatch( + bundlerCompilerService.compileWithWatch( { platformNameLowerCase: "android" }, - { webpackConfigPath }, - {} + { bundlerConfigPath: bundlerConfigPath }, + {}, ), - `The webpack configuration file ${webpackConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}` + `The bundler configuration file ${bundlerConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}`, ); }); }); describe("compileWithoutWatch", () => { - it("fails when the value set for webpackConfigPath is not existant file", async () => { - const webpackConfigPath = "some path.js"; + it("fails when the value set for bundlerConfigPath is not existant file", async () => { + const bundlerConfigPath = "some path.js"; testInjector.resolve("fs").exists = (filePath: string) => - filePath !== webpackConfigPath; + filePath !== bundlerConfigPath; await assert.isRejected( - webpackCompilerService.compileWithoutWatch( + bundlerCompilerService.compileWithoutWatch( { platformNameLowerCase: "android" }, - { webpackConfigPath }, - {} + { bundlerConfigPath: bundlerConfigPath }, + {}, ), - `The webpack configuration file ${webpackConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}` + `The bundler configuration file ${bundlerConfigPath} does not exist. Ensure the file exists, or update the path in ${CONFIG_FILE_NAME_DISPLAY}`, ); }); }); diff --git a/test/stubs.ts b/test/stubs.ts index fc4d687c15..7ec3580891 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -38,6 +38,7 @@ import { IProjectConfigInformation, IProjectBackupService, IBackup, + BundlerType, } from "../lib/definitions/project"; import { IPlatformData, @@ -658,6 +659,8 @@ export class ProjectDataStub implements IProjectData { projectDir: string; projectName: string; webpackConfigPath: string; + bundlerConfigPath: string; + bundler: BundlerType; get platformsDir(): string { return (