diff --git a/common/changes/@itwin/viewer-react/cospace-10-25_2025-10-06-17-45.json b/common/changes/@itwin/viewer-react/cospace-10-25_2025-10-06-17-45.json new file mode 100644 index 00000000..40f075ed --- /dev/null +++ b/common/changes/@itwin/viewer-react/cospace-10-25_2025-10-06-17-45.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/viewer-react", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/viewer-react" +} \ No newline at end of file diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json index 85faf91a..4a9c4241 100644 --- a/common/config/rush/command-line.json +++ b/common/config/rush/command-line.json @@ -1,6 +1,16 @@ { "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json", "commands": [ + { + "name": "build", + "commandKind": "bulk", + "summary": "Run build script for each package", + "description": "Iterates through each package in the monorepo and runs the 'build' script", + "enableParallelism": true, + "ignoreMissingScript": false, + "ignoreDependencyOrder": true, + "allowWarningsInSuccessfulBuild": true + }, { "name": "test", "commandKind": "bulk", diff --git a/common/config/rush/common-versions.json b/common/config/rush/common-versions.json index c58ab69d..3b600370 100644 --- a/common/config/rush/common-versions.json +++ b/common/config/rush/common-versions.json @@ -4,6 +4,7 @@ "preferredVersions": { "lint-staged": "^10.2.11", "immer": "^9.0.6", - "react-error-overlay": "6.0.9" + "react-error-overlay": "6.0.9", + "browserslist": "latest" // https://github.com/browserslist/update-db#readme } } \ No newline at end of file diff --git a/common/config/rush/pnpm-config.json b/common/config/rush/pnpm-config.json index 3c5abcd2..b985493e 100644 --- a/common/config/rush/pnpm-config.json +++ b/common/config/rush/pnpm-config.json @@ -1,4 +1,19 @@ { "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/pnpm-config.schema.json", - "useWorkspaces": true + "useWorkspaces": true, + // A list of temporary advisories excluded from the High and Critical list. + // Warning this should only be used as a temporary measure to avoid build failures + // for development dependencies only. + // All security issues should be addressed asap. + // every entry should look like: + // "CVE-202x-xxxxxx", // https://github.com/advisories/GHSA-xxxx-xxxx-xxxx pkgName>subDepA>subDepB + "unsupportedPackageJsonSettings": { + "pnpm": { + "auditConfig": { + "ignoreCves": [ + "CVE-2025-58754" // https://github.com/advisories/GHSA-4hjh-wcwx-xvwj axios + ] + } + } + } } \ No newline at end of file diff --git a/common/config/rush/repo-state.json b/common/config/rush/repo-state.json index bd264b45..27323620 100644 --- a/common/config/rush/repo-state.json +++ b/common/config/rush/repo-state.json @@ -1,4 +1,4 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "preferredVersionsHash": "29412695565de6483296c62c78a26bda534c820d" + "preferredVersionsHash": "cb75c3d4a84b5a92e59c1e793f2d2b861e0afaf3" } diff --git a/common/scripts/install-run-rush-pnpm.js b/common/scripts/install-run-rush-pnpm.js index 72a7bfdf..2356649f 100644 --- a/common/scripts/install-run-rush-pnpm.js +++ b/common/scripts/install-run-rush-pnpm.js @@ -10,6 +10,9 @@ // node common/scripts/install-run-rush-pnpm.js pnpm-command // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. /******/ (() => { // webpackBootstrap /******/ "use strict"; diff --git a/common/scripts/install-run-rush.js b/common/scripts/install-run-rush.js index fe5101a2..20f33d19 100644 --- a/common/scripts/install-run-rush.js +++ b/common/scripts/install-run-rush.js @@ -8,12 +8,15 @@ // node common/scripts/install-run-rush.js install // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ -/***/ 657147: +/***/ 179896: /*!*********************!*\ !*** external "fs" ***! \*********************/ @@ -23,7 +26,7 @@ module.exports = require("fs"); /***/ }), -/***/ 371017: +/***/ 16928: /*!***********************!*\ !*** external "path" ***! \***********************/ @@ -108,9 +111,9 @@ var __webpack_exports__ = {}; !*** ./lib-esnext/scripts/install-run-rush.js ***! \************************************************/ __webpack_require__.r(__webpack_exports__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! path */ 16928); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 179896); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. @@ -137,8 +140,8 @@ function _getRushVersion(logger) { return rushJsonMatches[1]; } catch (e) { - throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + - "The 'rushVersion' field is either not assigned in rush.json or was specified " + + throw new Error(`Unable to determine the required version of Rush from ${RUSH_JSON_FILENAME} (${rushJsonFolder}). ` + + `The 'rushVersion' field is either not assigned in ${RUSH_JSON_FILENAME} or was specified ` + 'using an unexpected syntax.'); } } @@ -197,7 +200,7 @@ function _run() { } runWithErrorAndStatusCode(logger, () => { const version = _getRushVersion(logger); - logger.info(`The rush.json configuration requests Rush version ${version}`); + logger.info(`The ${RUSH_JSON_FILENAME} configuration requests Rush version ${version}`); const lockFilePath = process.env[INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE]; if (lockFilePath) { logger.info(`Found ${INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE}="${lockFilePath}", installing with lockfile.`); diff --git a/common/scripts/install-run-rushx.js b/common/scripts/install-run-rushx.js index 0a0235f2..6581521f 100644 --- a/common/scripts/install-run-rushx.js +++ b/common/scripts/install-run-rushx.js @@ -10,6 +10,9 @@ // node common/scripts/install-run-rushx.js custom-command // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. /******/ (() => { // webpackBootstrap /******/ "use strict"; diff --git a/common/scripts/install-run.js b/common/scripts/install-run.js index bf89cd23..96cbd258 100644 --- a/common/scripts/install-run.js +++ b/common/scripts/install-run.js @@ -8,12 +8,15 @@ // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ -/***/ 679877: +/***/ 832286: /*!************************************************!*\ !*** ./lib-esnext/utilities/npmrcUtilities.js ***! \************************************************/ @@ -21,12 +24,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "isVariableSetInNpmrcFile": () => (/* binding */ isVariableSetInNpmrcFile), -/* harmony export */ "syncNpmrc": () => (/* binding */ syncNpmrc) +/* harmony export */ isVariableSetInNpmrcFile: () => (/* binding */ isVariableSetInNpmrcFile), +/* harmony export */ syncNpmrc: () => (/* binding */ syncNpmrc), +/* harmony export */ trimNpmrcFileLines: () => (/* binding */ trimNpmrcFileLines) /* harmony export */ }); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! fs */ 179896); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! path */ 16928); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. @@ -42,13 +46,38 @@ __webpack_require__.r(__webpack_exports__); */ // create a global _combinedNpmrc for cache purpose const _combinedNpmrcMap = new Map(); -function _trimNpmrcFile(sourceNpmrcPath) { +function _trimNpmrcFile(options) { + const { sourceNpmrcPath, linesToPrepend, linesToAppend, supportEnvVarFallbackSyntax } = options; const combinedNpmrcFromCache = _combinedNpmrcMap.get(sourceNpmrcPath); if (combinedNpmrcFromCache !== undefined) { return combinedNpmrcFromCache; } - let npmrcFileLines = fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(sourceNpmrcPath).toString().split('\n'); + let npmrcFileLines = []; + if (linesToPrepend) { + npmrcFileLines.push(...linesToPrepend); + } + if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) { + npmrcFileLines.push(...fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(sourceNpmrcPath).toString().split('\n')); + } + if (linesToAppend) { + npmrcFileLines.push(...linesToAppend); + } npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); + const resultLines = trimNpmrcFileLines(npmrcFileLines, process.env, supportEnvVarFallbackSyntax); + const combinedNpmrc = resultLines.join('\n'); + //save the cache + _combinedNpmrcMap.set(sourceNpmrcPath, combinedNpmrc); + return combinedNpmrc; +} +/** + * + * @param npmrcFileLines The npmrc file's lines + * @param env The environment variables object + * @param supportEnvVarFallbackSyntax Whether to support fallback values in the form of `${VAR_NAME:-fallback}` + * @returns + */ +function trimNpmrcFileLines(npmrcFileLines, env, supportEnvVarFallbackSyntax) { + var _a; const resultLines = []; // This finds environment variable tokens that look like "${VAR_NAME}" const expansionRegExp = /\$\{([^\}]+)\}/g; @@ -67,10 +96,35 @@ function _trimNpmrcFile(sourceNpmrcPath) { const environmentVariables = line.match(expansionRegExp); if (environmentVariables) { for (const token of environmentVariables) { - // Remove the leading "${" and the trailing "}" from the token - const environmentVariableName = token.substring(2, token.length - 1); - // Is the environment variable defined? - if (!process.env[environmentVariableName]) { + /** + * Remove the leading "${" and the trailing "}" from the token + * + * ${nameString} -> nameString + * ${nameString-fallbackString} -> name-fallbackString + * ${nameString:-fallbackString} -> name:-fallbackString + */ + const nameWithFallback = token.substring(2, token.length - 1); + let environmentVariableName; + let fallback; + if (supportEnvVarFallbackSyntax) { + /** + * Get the environment variable name and fallback value. + * + * name fallback + * nameString -> nameString undefined + * nameString-fallbackString -> nameString fallbackString + * nameString:-fallbackString -> nameString fallbackString + */ + const matched = nameWithFallback.match(/^([^:-]+)(?:\:?-(.+))?$/); + // matched: [originStr, variableName, fallback] + environmentVariableName = (_a = matched === null || matched === void 0 ? void 0 : matched[1]) !== null && _a !== void 0 ? _a : nameWithFallback; + fallback = matched === null || matched === void 0 ? void 0 : matched[2]; + } + else { + environmentVariableName = nameWithFallback; + } + // Is the environment variable and fallback value defined. + if (!env[environmentVariableName] && !fallback) { // No, so trim this line lineShouldBeTrimmed = true; break; @@ -87,52 +141,34 @@ function _trimNpmrcFile(sourceNpmrcPath) { resultLines.push(line); } } - const combinedNpmrc = resultLines.join('\n'); - //save the cache - _combinedNpmrcMap.set(sourceNpmrcPath, combinedNpmrc); - return combinedNpmrc; + return resultLines; } -/** - * As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims - * unusable lines from the .npmrc file. - * - * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in - * the .npmrc file to provide different authentication tokens for different registry. - * However, if the environment variable is undefined, it expands to an empty string, which - * produces a valid-looking mapping with an invalid URL that causes an error. Instead, - * we'd prefer to skip that line and continue looking in other places such as the user's - * home directory. - * - * @returns - * The text of the the .npmrc with lines containing undefined variables commented out. - */ -function _copyAndTrimNpmrcFile(logger, sourceNpmrcPath, targetNpmrcPath) { +function _copyAndTrimNpmrcFile(options) { + const { logger, sourceNpmrcPath, targetNpmrcPath } = options; logger.info(`Transforming ${sourceNpmrcPath}`); // Verbose logger.info(` --> "${targetNpmrcPath}"`); - const combinedNpmrc = _trimNpmrcFile(sourceNpmrcPath); + const combinedNpmrc = _trimNpmrcFile(options); fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(targetNpmrcPath, combinedNpmrc); return combinedNpmrc; } -/** - * syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file. - * If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder. - * - * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() - * - * @returns - * The text of the the synced .npmrc, if one exists. If one does not exist, then undefined is returned. - */ -function syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish, logger = { - // eslint-disable-next-line no-console - info: console.log, - // eslint-disable-next-line no-console - error: console.error -}) { +function syncNpmrc(options) { + const { sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish, logger = { + // eslint-disable-next-line no-console + info: console.log, + // eslint-disable-next-line no-console + error: console.error + }, createIfMissing = false } = options; const sourceNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); const targetNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(targetNpmrcFolder, '.npmrc'); try { - if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) { - return _copyAndTrimNpmrcFile(logger, sourceNpmrcPath, targetNpmrcPath); + if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath) || createIfMissing) { + // Ensure the target folder exists + if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcFolder)) { + fs__WEBPACK_IMPORTED_MODULE_0__.mkdirSync(targetNpmrcFolder, { recursive: true }); + } + return _copyAndTrimNpmrcFile(Object.assign({ sourceNpmrcPath, + targetNpmrcPath, + logger }, options)); } else if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcPath)) { // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target @@ -144,13 +180,13 @@ function syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish, logger throw new Error(`Error syncing .npmrc file: ${e}`); } } -function isVariableSetInNpmrcFile(sourceNpmrcFolder, variableKey) { +function isVariableSetInNpmrcFile(sourceNpmrcFolder, variableKey, supportEnvVarFallbackSyntax) { const sourceNpmrcPath = `${sourceNpmrcFolder}/.npmrc`; //if .npmrc file does not exist, return false directly if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) { return false; } - const trimmedNpmrcFile = _trimNpmrcFile(sourceNpmrcPath); + const trimmedNpmrcFile = _trimNpmrcFile({ sourceNpmrcPath, supportEnvVarFallbackSyntax }); const variableKeyRegExp = new RegExp(`^${variableKey}=`, 'm'); return trimmedNpmrcFile.match(variableKeyRegExp) !== null; } @@ -158,7 +194,7 @@ function isVariableSetInNpmrcFile(sourceNpmrcFolder, variableKey) { /***/ }), -/***/ 532081: +/***/ 535317: /*!********************************!*\ !*** external "child_process" ***! \********************************/ @@ -168,7 +204,7 @@ module.exports = require("child_process"); /***/ }), -/***/ 657147: +/***/ 179896: /*!*********************!*\ !*** external "fs" ***! \*********************/ @@ -178,7 +214,7 @@ module.exports = require("fs"); /***/ }), -/***/ 822037: +/***/ 370857: /*!*********************!*\ !*** external "os" ***! \*********************/ @@ -188,7 +224,7 @@ module.exports = require("os"); /***/ }), -/***/ 371017: +/***/ 16928: /*!***********************!*\ !*** external "path" ***! \***********************/ @@ -274,21 +310,21 @@ var __webpack_exports__ = {}; \*******************************************/ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "RUSH_JSON_FILENAME": () => (/* binding */ RUSH_JSON_FILENAME), -/* harmony export */ "findRushJsonFolder": () => (/* binding */ findRushJsonFolder), -/* harmony export */ "getNpmPath": () => (/* binding */ getNpmPath), -/* harmony export */ "installAndRun": () => (/* binding */ installAndRun), -/* harmony export */ "runWithErrorAndStatusCode": () => (/* binding */ runWithErrorAndStatusCode) +/* harmony export */ RUSH_JSON_FILENAME: () => (/* binding */ RUSH_JSON_FILENAME), +/* harmony export */ findRushJsonFolder: () => (/* binding */ findRushJsonFolder), +/* harmony export */ getNpmPath: () => (/* binding */ getNpmPath), +/* harmony export */ installAndRun: () => (/* binding */ installAndRun), +/* harmony export */ runWithErrorAndStatusCode: () => (/* binding */ runWithErrorAndStatusCode) /* harmony export */ }); -/* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! child_process */ 532081); +/* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! child_process */ 535317); /* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(child_process__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 179896); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! os */ 822037); +/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! os */ 370857); /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! path */ 16928); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utilities/npmrcUtilities */ 679877); +/* harmony import */ var _utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utilities/npmrcUtilities */ 832286); // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. /* eslint-disable no-console */ @@ -335,7 +371,7 @@ let _npmPath = undefined; function getNpmPath() { if (!_npmPath) { try { - if (os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32') { + if (_isWindows()) { // We're on Windows const whereOutput = child_process__WEBPACK_IMPORTED_MODULE_0__.execSync('where npm', { stdio: [] }).toString(); const lines = whereOutput.split(os__WEBPACK_IMPORTED_MODULE_2__.EOL).filter((line) => !!line); @@ -431,7 +467,12 @@ function _resolvePackageVersion(logger, rushCommonFolder, { name, version }) { try { const rushTempFolder = _getRushTempFolder(rushCommonFolder); const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush'); - (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)(sourceNpmrcFolder, rushTempFolder, undefined, logger); + (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({ + sourceNpmrcFolder, + targetNpmrcFolder: rushTempFolder, + logger, + supportEnvVarFallbackSyntax: false + }); const npmPath = getNpmPath(); // This returns something that looks like: // ``` @@ -450,10 +491,13 @@ function _resolvePackageVersion(logger, rushCommonFolder, { name, version }) { // ``` // // if only a single version matches. - const npmVersionSpawnResult = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier', '--json'], { + const spawnSyncOptions = { cwd: rushTempFolder, - stdio: [] - }); + stdio: [], + shell: _isWindows() + }; + const platformNpmPath = _getPlatformPath(npmPath); + const npmVersionSpawnResult = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformNpmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier', '--json'], spawnSyncOptions); if (npmVersionSpawnResult.status !== 0) { throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`); } @@ -498,7 +542,7 @@ function findRushJsonFolder() { } } while (basePath !== (tempPath = path__WEBPACK_IMPORTED_MODULE_3__.dirname(basePath))); // Exit the loop when we hit the disk root if (!_rushJsonFolder) { - throw new Error('Unable to find rush.json.'); + throw new Error(`Unable to find ${RUSH_JSON_FILENAME}.`); } } return _rushJsonFolder; @@ -586,10 +630,12 @@ function _installPackage(logger, packageInstallFolder, name, version, command) { try { logger.info(`Installing ${name}...`); const npmPath = getNpmPath(); - const result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(npmPath, [command], { + const platformNpmPath = _getPlatformPath(npmPath); + const result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformNpmPath, [command], { stdio: 'inherit', cwd: packageInstallFolder, - env: process.env + env: process.env, + shell: _isWindows() }); if (result.status !== 0) { throw new Error(`"npm ${command}" encountered an error`); @@ -605,9 +651,18 @@ function _installPackage(logger, packageInstallFolder, name, version, command) { */ function _getBinPath(packageInstallFolder, binName) { const binFolderPath = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); - const resolvedBinName = os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32' ? `${binName}.cmd` : binName; + const resolvedBinName = _isWindows() ? `${binName}.cmd` : binName; return path__WEBPACK_IMPORTED_MODULE_3__.resolve(binFolderPath, resolvedBinName); } +/** + * Returns a cross-platform path - windows must enclose any path containing spaces within double quotes. + */ +function _getPlatformPath(platformPath) { + return _isWindows() && platformPath.includes(' ') ? `"${platformPath}"` : platformPath; +} +function _isWindows() { + return os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32'; +} /** * Write a flag file to the package's install directory, signifying that the install was successful. */ @@ -629,7 +684,12 @@ function installAndRun(logger, packageName, packageVersion, packageBinName, pack // The package isn't already installed _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath); const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush'); - (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)(sourceNpmrcFolder, packageInstallFolder, undefined, logger); + (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({ + sourceNpmrcFolder, + targetNpmrcFolder: packageInstallFolder, + logger, + supportEnvVarFallbackSyntax: false + }); _createPackageJson(packageInstallFolder, packageName, packageVersion); const command = lockFilePath ? 'ci' : 'install'; _installPackage(logger, packageInstallFolder, packageName, packageVersion, command); @@ -645,15 +705,14 @@ function installAndRun(logger, packageName, packageVersion, packageBinName, pack const originalEnvPath = process.env.PATH || ''; let result; try { - // Node.js on Windows can not spawn a file when the path has a space on it - // unless the path gets wrapped in a cmd friendly way and shell mode is used - const shouldUseShell = binPath.includes(' ') && os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32'; - const platformBinPath = shouldUseShell ? `"${binPath}"` : binPath; + // `npm` bin stubs on Windows are `.cmd` files + // Node.js will not directly invoke a `.cmd` file unless `shell` is set to `true` + const platformBinPath = _getPlatformPath(binPath); process.env.PATH = [binFolderPath, originalEnvPath].join(path__WEBPACK_IMPORTED_MODULE_3__.delimiter); result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformBinPath, packageBinArgs, { stdio: 'inherit', windowsVerbatimArguments: false, - shell: shouldUseShell, + shell: _isWindows(), cwd: process.cwd(), env: process.env }); diff --git a/packages/modules/viewer-react/src/tests/components/iModel/IModelViewer.test.tsx b/packages/modules/viewer-react/src/tests/components/iModel/IModelViewer.test.tsx index e4dd1027..4cfa8378 100644 --- a/packages/modules/viewer-react/src/tests/components/iModel/IModelViewer.test.tsx +++ b/packages/modules/viewer-react/src/tests/components/iModel/IModelViewer.test.tsx @@ -8,7 +8,7 @@ import type { FrontstageConfig } from "@itwin/appui-react"; import { ContentGroup, IModelViewportControl } from "@itwin/appui-react"; import { FrontstageProvider } from "@itwin/appui-react"; import { UiFramework } from "@itwin/appui-react"; -import { render, waitFor } from "@testing-library/react"; +import { act, render, waitFor } from "@testing-library/react"; import React from "react"; import { describe, expect, it, vi } from "vitest"; @@ -88,7 +88,7 @@ describe("IModelViewer", () => { }, ]; - await React.act(async () => { + await act(async () => { render(); }); diff --git a/rush.json b/rush.json index 19fd9531..7074c775 100644 --- a/rush.json +++ b/rush.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json", - "rushVersion": "5.112.2", + "rushVersion": "5.147.0", "pnpmVersion": "7.32.2", "nodeSupportedVersionRange": "^20.19.0 || ^22.12.0", "projectFolderMinDepth": 2,