@react-native-windows/cli
Advanced tools
Comparing version 0.0.0-canary.99 to 0.0.0-canary.100
@@ -12,3 +12,3 @@ "use strict"; | ||
exports.getExperimentalFeatures = exports.getProjectGuid = exports.getProjectNamespace = exports.getProjectName = exports.getProjectType = exports.getOutputType = exports.getConfigurationType = exports.importProjectExists = exports.findPropertyValue = exports.tryFindPropertyValue = exports.readProjectFile = exports.getProjectLanguage = exports.findAppProjectFiles = exports.findDependencyProjectFiles = exports.isRnwDependencyProject = exports.findSolutionFiles = exports.isRnwSolution = exports.findWindowsFolder = exports.findFiles = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -15,0 +15,0 @@ const glob_1 = __importDefault(require("glob")); |
@@ -12,2 +12,3 @@ "use strict"; | ||
const path_1 = __importDefault(require("path")); | ||
const telemetry_1 = require("@react-native-windows/telemetry"); | ||
const projectConfig_1 = require("../config/projectConfig"); | ||
@@ -403,2 +404,14 @@ const autolink_1 = require("../runWindows/utils/autolink"); | ||
}); | ||
function validateOptionName(name, optionName) { | ||
// Do not add a default case here. Every item must explicitly return true | ||
switch (optionName) { | ||
case 'check': | ||
case 'logging': | ||
case 'sln': | ||
case 'proj': | ||
case 'telemetry': | ||
return true; | ||
} | ||
throw new Error(`Unable to find ${optionName} to match '${name}' in AutoLinkOptions.`); | ||
} | ||
test('autolinkOptions - validate options', () => { | ||
@@ -419,4 +432,7 @@ for (const commandOption of autolink_1.autolinkOptions) { | ||
expect(commandOption.description).toBe(commandOption.description.trim()); | ||
// Validate all command options are present in RunWindowsOptions | ||
const optionName = (0, telemetry_1.commanderNameToOptionName)(commandOption.name); | ||
expect(validateOptionName(commandOption.name, optionName)).toBe(true); | ||
} | ||
}); | ||
//# sourceMappingURL=autolink.test.js.map |
@@ -11,3 +11,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -20,3 +20,3 @@ const dependencyConfig_1 = require("../config/dependencyConfig"); | ||
try { | ||
await fs_1.default.promises.mkdir(dir, { recursive: true }); | ||
await fs_1.default.mkdir(dir, { recursive: true }); | ||
} | ||
@@ -23,0 +23,0 @@ catch (err) { } |
@@ -11,3 +11,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -121,4 +121,4 @@ const projectConfig_1 = require("../config/projectConfig"); | ||
expect(exd).toBeTruthy(); | ||
const packagesConfig = (await fs_1.default.promises.readFile(path_1.default.join(folder, 'windows/WithWinUI3/packages.config'))).toString(); | ||
const experimentalFeatures = (await fs_1.default.promises.readFile(path_1.default.join(folder, 'windows/ExperimentalFeatures.props'))).toString(); | ||
const packagesConfig = (await fs_1.default.readFile(path_1.default.join(folder, 'windows/WithWinUI3/packages.config'))).toString(); | ||
const experimentalFeatures = (await fs_1.default.readFile(path_1.default.join(folder, 'windows/ExperimentalFeatures.props'))).toString(); | ||
expect(packagesConfig.replace(/\r/g, '')).toMatchSnapshot(); | ||
@@ -125,0 +125,0 @@ expect(experimentalFeatures.replace(/\r/g, '')).toMatchSnapshot(); |
@@ -7,3 +7,3 @@ "use strict"; | ||
exports.ensureWinUI3Project = exports.tryMkdir = exports.testProjectGuid = exports.templateRoot = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -15,3 +15,3 @@ const generator_common_1 = require("../generator-common"); | ||
try { | ||
await fs_1.default.promises.mkdir(dir, { recursive: true }); | ||
await fs_1.default.mkdir(dir, { recursive: true }); | ||
} | ||
@@ -24,3 +24,3 @@ catch (err) { } | ||
if (fs_1.default.existsSync(windowsDir)) { | ||
await fs_1.default.promises.rmdir(windowsDir, { recursive: true }); | ||
await fs_1.default.rmdir(windowsDir, { recursive: true }); | ||
} | ||
@@ -27,0 +27,0 @@ await tryMkdir(windowsDir); |
@@ -8,17 +8,35 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const runWindows_1 = require("../runWindows/runWindows"); | ||
const telemetry_1 = require("@react-native-windows/telemetry"); | ||
const runWindowsOptions_1 = require("../runWindows/runWindowsOptions"); | ||
test('getAnonymizedProjectName - Project Exists', async () => { | ||
const fooName = await (0, runWindows_1.getAnonymizedProjectName)(`${__dirname}/projects/FooPackage`); | ||
const barName = await (0, runWindows_1.getAnonymizedProjectName)(`${__dirname}/projects/BarPackage`); | ||
expect(typeof fooName).toBe('string'); | ||
expect(typeof barName).toBe('string'); | ||
expect(fooName.length).toBeGreaterThan(0); | ||
expect(barName.length).toBeGreaterThan(0); | ||
expect(fooName).not.toBe(barName); | ||
}); | ||
test('getAnonymizedProjectName - Project Doesnt Exist', async () => { | ||
const emptyPackageName = await (0, runWindows_1.getAnonymizedProjectName)(`${__dirname}/projects/BlankApp`); | ||
expect(emptyPackageName).toBeNull(); | ||
}); | ||
// eslint-disable-next-line complexity | ||
function validateOptionName(name, optionName) { | ||
// Do not add a default case here. Every item must explicitly return true | ||
switch (optionName) { | ||
case 'release': | ||
case 'root': | ||
case 'arch': | ||
case 'singleproc': | ||
case 'emulator': | ||
case 'device': | ||
case 'target': | ||
case 'remoteDebugging': | ||
case 'logging': | ||
case 'packager': | ||
case 'bundle': | ||
case 'launch': | ||
case 'autolink': | ||
case 'build': | ||
case 'deploy': | ||
case 'deployFromLayout': | ||
case 'sln': | ||
case 'proj': | ||
case 'msbuildprops': | ||
case 'buildLogDirectory': | ||
case 'info': | ||
case 'directDebugging': | ||
case 'telemetry': | ||
return true; | ||
} | ||
throw new Error(`Unable to find ${optionName} to match '${name}' in RunWindowsOptions.`); | ||
} | ||
test('runWindowsOptions - validate options', () => { | ||
@@ -39,4 +57,7 @@ for (const commandOption of runWindowsOptions_1.runWindowsOptions) { | ||
expect(commandOption.description).toBe(commandOption.description.trim()); | ||
// Validate all command options are present in RunWindowsOptions | ||
const optionName = (0, telemetry_1.commanderNameToOptionName)(commandOption.name); | ||
expect(validateOptionName(commandOption.name, optionName)).toBe(true); | ||
} | ||
}); | ||
//# sourceMappingURL=runWindows.test.js.map |
@@ -12,3 +12,3 @@ "use strict"; | ||
exports.copyAndReplaceAll = exports.copyAndReplaceWithChangedCallback = exports.createDir = exports.copyAndReplace = exports.resolveContents = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const chalk_1 = __importDefault(require("chalk")); | ||
@@ -15,0 +15,0 @@ const prompts_1 = __importDefault(require("prompts")); |
@@ -17,3 +17,3 @@ "use strict"; | ||
const child_process_1 = __importDefault(require("child_process")); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const semver_1 = __importDefault(require("semver")); | ||
@@ -87,3 +87,4 @@ const lodash_1 = __importDefault(require("lodash")); | ||
if (appJsonPath) { | ||
mainComponentName = JSON.parse(fs_1.default.readFileSync(appJsonPath, 'utf8')).name; | ||
const appJson = await fs_1.default.readJsonFile(appJsonPath); | ||
mainComponentName = appJson.name; | ||
} | ||
@@ -90,0 +91,0 @@ const xamlNamespace = options.useWinUI3 |
@@ -22,5 +22,4 @@ "use strict"; | ||
exports.projectConfig = exports.dependencyConfig = exports.commands = exports.generateWindows = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
const telemetry_1 = require("@react-native-windows/telemetry"); | ||
const generator_windows_1 = require("./generator-windows"); | ||
@@ -31,15 +30,2 @@ const autolink_1 = require("./runWindows/utils/autolink"); | ||
const projectConfig_1 = require("./config/projectConfig"); | ||
function scrubOptions(opt) { | ||
return { | ||
overwrite: opt.overwrite, | ||
language: opt.language, | ||
projectType: opt.projectType, | ||
experimentalNuGetDependency: opt.experimentalNuGetDependency, | ||
nuGetTestFeed: opt.nuGetTestFeed !== undefined ? true : false, | ||
nuGetTestVersion: opt.nuGetTestVersion !== undefined ? true : false, | ||
useWinUI3: opt.useWinUI3, | ||
useHermes: opt.useHermes, | ||
verbose: opt.verbose, | ||
}; | ||
} | ||
/** | ||
@@ -54,48 +40,11 @@ * Simple utility for running the Windows generator. | ||
async function generateWindows(projectDir, name, ns, options) { | ||
let error; | ||
try { | ||
if (!fs_1.default.existsSync(projectDir)) { | ||
fs_1.default.mkdirSync(projectDir); | ||
} | ||
await (0, generator_windows_1.installScriptsAndDependencies)(options); | ||
const rnwPackage = path_1.default.dirname(require.resolve('react-native-windows/package.json', { | ||
paths: [projectDir], | ||
})); | ||
const templateRoot = path_1.default.join(rnwPackage, 'template'); | ||
await (0, generator_windows_1.copyProjectTemplateAndReplace)(templateRoot, projectDir, name, ns, options); | ||
if (!fs_1.default.existsSync(projectDir)) { | ||
fs_1.default.mkdirSync(projectDir); | ||
} | ||
catch (e) { | ||
error = e; | ||
telemetry_1.Telemetry.trackException(error); | ||
throw e; | ||
} | ||
finally { | ||
if (telemetry_1.Telemetry.client) { | ||
let rnVersion = ''; | ||
let cliVersion = ''; | ||
try { | ||
const cwd = process.cwd(); | ||
const rnwPkg = JSON.parse(fs_1.default | ||
.readFileSync(require.resolve('react-native-windows/package.json', { | ||
paths: [cwd], | ||
})) | ||
.toString()); | ||
rnVersion = rnwPkg.peerDependencies['react-native'] || ''; | ||
const rnwCliPkgJson = require('../package.json'); | ||
cliVersion = rnwCliPkgJson.version; | ||
} | ||
catch (_a) { } | ||
const optScrubbed = scrubOptions(options); | ||
telemetry_1.Telemetry.client.trackEvent({ | ||
name: 'generate-windows', | ||
properties: { | ||
error: error, | ||
...optScrubbed, | ||
'react-native': rnVersion, | ||
'cli-version': cliVersion, | ||
}, | ||
}); | ||
telemetry_1.Telemetry.client.flush(); | ||
} | ||
} | ||
await (0, generator_windows_1.installScriptsAndDependencies)(options); | ||
const rnwPackage = path_1.default.dirname(require.resolve('react-native-windows/package.json', { | ||
paths: [projectDir], | ||
})); | ||
const templateRoot = path_1.default.join(rnwPackage, 'template'); | ||
await (0, generator_windows_1.copyProjectTemplateAndReplace)(templateRoot, projectDir, name, ns, options); | ||
} | ||
@@ -102,0 +51,0 @@ exports.generateWindows = generateWindows; |
@@ -7,3 +7,2 @@ /** | ||
import { Command } from '@react-native-community/cli-types'; | ||
export declare function getAnonymizedProjectName(projectRoot: string): Promise<string | null>; | ||
/** | ||
@@ -10,0 +9,0 @@ * Starts the app on a connected Windows emulator or mobile device. |
@@ -30,5 +30,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.runWindowsCommand = exports.getAnonymizedProjectName = void 0; | ||
const crypto_1 = __importDefault(require("crypto")); | ||
const fs_1 = __importDefault(require("fs")); | ||
exports.runWindowsCommand = void 0; | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -40,2 +39,3 @@ const telemetry_1 = require("@react-native-windows/telemetry"); | ||
const commandWithProgress_1 = require("./utils/commandWithProgress"); | ||
const telemetryHelpers_1 = require("./utils/telemetryHelpers"); | ||
const info = __importStar(require("./utils/info")); | ||
@@ -45,34 +45,57 @@ const msbuildtools_1 = __importDefault(require("./utils/msbuildtools")); | ||
const autolink_1 = require("./utils/autolink"); | ||
const os_1 = require("os"); | ||
function setExitProcessWithError(error, loggingWasEnabled) { | ||
if (loggingWasEnabled !== true) { | ||
console.log(`Re-run the command with ${chalk_1.default.bold('--logging')} for more information`); | ||
if (telemetry_1.Telemetry.client) { | ||
console.log(`Your session id was ${telemetry_1.Telemetry.client.commonProperties.sessionId}`); | ||
} | ||
/** | ||
* Sanitizes the given option for telemetery. | ||
* @param key The key of the option. | ||
* @param value The unsanitized value of the option. | ||
* @returns The sanitized value of the option. | ||
*/ | ||
// eslint-disable-next-line complexity | ||
function optionSanitizer(key, value) { | ||
// Do not add a default case here. | ||
// Strings risking PII should just return true if present, false otherwise. | ||
// All others should return the value (or false if undefined). | ||
switch (key) { | ||
case 'root': | ||
case 'target': | ||
case 'sln': | ||
case 'proj': | ||
case 'buildLogDirectory': | ||
return value === undefined ? false : true; // Strip PII | ||
case 'msbuildprops': | ||
return value === undefined ? 0 : value.split(',').length; // Convert to count | ||
case 'release': | ||
case 'arch': | ||
case 'singleproc': | ||
case 'emulator': | ||
case 'device': | ||
case 'remoteDebugging': | ||
case 'logging': | ||
case 'packager': | ||
case 'bundle': | ||
case 'launch': | ||
case 'autolink': | ||
case 'build': | ||
case 'deploy': | ||
case 'deployFromLayout': | ||
case 'info': | ||
case 'directDebugging': | ||
case 'telemetry': | ||
return value === undefined ? false : value; // Return value | ||
} | ||
if (error instanceof telemetry_1.CodedError) { | ||
process.exitCode = telemetry_1.CodedErrors[error.name]; | ||
} | ||
else { | ||
process.exitCode = 1; | ||
} | ||
} | ||
function getPkgVersion(pkgName) { | ||
try { | ||
const pkgJsonPath = require.resolve(`${pkgName}/package.json`, { | ||
paths: [process.cwd(), __dirname], | ||
}); | ||
const pkgJson = JSON.parse(fs_1.default.readFileSync(pkgJsonPath).toString()); | ||
if (pkgJson.name === pkgName && pkgJson.version !== undefined) { | ||
return pkgJson.version; | ||
} | ||
} | ||
catch (_a) { } | ||
(0, commandWithProgress_1.newWarn)(`Could not determine ${pkgName} version`); | ||
return ''; | ||
/** | ||
* Get the extra props to add to the `run-windows` telemetry event. | ||
* @returns The extra props. | ||
*/ | ||
async function getExtraProps() { | ||
const extraProps = { | ||
phase: runWindowsPhase, | ||
hasRunRnwDependencies, | ||
}; | ||
return extraProps; | ||
} | ||
let runWindowsPhase = 'None'; | ||
let hasRunRnwDependencies = false; | ||
/** | ||
* Performs build deploy and launch of RNW apps. | ||
* The function run when calling `react-native run-windows`. | ||
* @param args Unprocessed args passed from react-native CLI. | ||
@@ -83,12 +106,3 @@ * @param config Config passed from react-native CLI. | ||
async function runWindows(args, config, options) { | ||
var _a, _b; | ||
if (!options.telemetry) { | ||
if (options.logging) { | ||
console.log('Disabling telemetry'); | ||
} | ||
telemetry_1.Telemetry.disable(); | ||
} | ||
else { | ||
telemetry_1.Telemetry.setup(); | ||
} | ||
await (0, telemetryHelpers_1.startTelemetrySession)('run-windows', config, options, (0, telemetryHelpers_1.getDefaultOptions)(config, runWindowsOptions_1.runWindowsOptions), optionSanitizer); | ||
// https://github.com/yarnpkg/yarn/issues/8334 - Yarn on Windows breaks apps that read from the environment variables | ||
@@ -102,4 +116,6 @@ // Yarn will run node via CreateProcess and pass npm_config_* variables in lowercase without unifying their value | ||
delete process.env.NPM_CONFIG_PREFIX; | ||
const hasRunRnwDependencies = process.env.LocalAppData && | ||
fs_1.default.existsSync(path_1.default.join(process.env.LocalAppData, 'rnw-dependencies.txt')); // CODESYNC \vnext\scripts\rnw-dependencies.ps1 | ||
if (process.env.LocalAppData) { | ||
hasRunRnwDependencies = fs_1.default.existsSync(path_1.default.join(process.env.LocalAppData, 'rnw-dependencies.txt')); // CODESYNC \vnext\scripts\rnw-dependencies.ps1 | ||
} | ||
let runWindowsError; | ||
if (options.info) { | ||
@@ -112,18 +128,20 @@ try { | ||
sdks.forEach(version => console.log(' ' + version)); | ||
return; | ||
} | ||
catch (err) { | ||
const e = err; | ||
telemetry_1.Telemetry.trackException(e); | ||
(0, commandWithProgress_1.newError)('Unable to print environment info.\n' + e.toString()); | ||
return setExitProcessWithError(e, options.logging); | ||
catch (ex) { | ||
runWindowsError = | ||
ex instanceof Error ? ex : new Error(String(ex)); | ||
telemetry_1.Telemetry.trackException(runWindowsError); | ||
(0, commandWithProgress_1.newError)('Unable to print environment info.\n' + runWindowsError.toString()); | ||
} | ||
await (0, telemetryHelpers_1.endTelemetrySession)(runWindowsError, getExtraProps); | ||
(0, commandWithProgress_1.setExitProcessWithError)(options.logging, runWindowsError); | ||
return; | ||
} | ||
let runWindowsError; | ||
try { | ||
await runWindowsInternal(args, config, options); | ||
} | ||
catch (e) { | ||
telemetry_1.Telemetry.trackException(e); | ||
runWindowsError = e; | ||
catch (ex) { | ||
runWindowsError = | ||
ex instanceof Error ? ex : new Error(String(ex)); | ||
telemetry_1.Telemetry.trackException(runWindowsError); | ||
if (!hasRunRnwDependencies) { | ||
@@ -136,64 +154,12 @@ const rnwPkgJsonPath = require.resolve('react-native-windows/package.json', { | ||
} | ||
return setExitProcessWithError(e, options.logging); | ||
} | ||
finally { | ||
(_a = telemetry_1.Telemetry.client) === null || _a === void 0 ? void 0 : _a.trackEvent({ | ||
name: 'run-windows', | ||
properties: { | ||
release: options.release, | ||
arch: options.arch, | ||
singleproc: options.singleproc, | ||
emulator: options.emulator, | ||
device: options.device, | ||
target: options.target, | ||
remoteDebugging: options.remoteDebugging, | ||
logging: options.logging, | ||
packager: options.packager, | ||
bundle: options.bundle, | ||
launch: options.launch, | ||
autolink: options.autolink, | ||
build: options.bundle, | ||
deploy: options.deploy, | ||
sln: options.sln !== undefined, | ||
proj: options.proj !== undefined, | ||
msBuildProps: options.msbuildprops !== undefined | ||
? options.msbuildprops.split(',').length | ||
: 0, | ||
info: options.info, | ||
directDebugging: options.directDebugging, | ||
'react-native-windows': getPkgVersion('react-native-windows'), | ||
'react-native': getPkgVersion('react-native'), | ||
'cli-version': getPkgVersion('@react-native-windows/cli'), | ||
msftInternal: (0, telemetry_1.isMSFTInternal)(), | ||
durationInSecs: process.uptime(), | ||
success: runWindowsError === undefined, | ||
phase: runWindowsPhase, | ||
totalMem: (0, os_1.totalmem)(), | ||
diskFree: (0, telemetry_1.getDiskFreeSpace)(__dirname), | ||
cpus: (0, os_1.cpus)().length, | ||
project: await getAnonymizedProjectName(config.root), | ||
hasRunRnwDependencies: hasRunRnwDependencies, | ||
}, | ||
}); | ||
(_b = telemetry_1.Telemetry.client) === null || _b === void 0 ? void 0 : _b.flush(); | ||
} | ||
await (0, telemetryHelpers_1.endTelemetrySession)(runWindowsError, getExtraProps); | ||
(0, commandWithProgress_1.setExitProcessWithError)(options.logging, runWindowsError); | ||
} | ||
async function getAnonymizedProjectName(projectRoot) { | ||
const projectJsonPath = path_1.default.join(projectRoot, 'package.json'); | ||
if (!fs_1.default.existsSync(projectJsonPath)) { | ||
return null; | ||
} | ||
const projectJson = JSON.parse((await fs_1.default.promises.readFile(projectJsonPath)).toString()); | ||
const projectName = projectJson.name; | ||
if (typeof projectName !== 'string') { | ||
return null; | ||
} | ||
// Ensure the project name cannot be reverse engineered to avoid leaking PII | ||
return crypto_1.default | ||
.createHash('sha256') | ||
.update(projectName) | ||
.digest('hex') | ||
.toString(); | ||
} | ||
exports.getAnonymizedProjectName = getAnonymizedProjectName; | ||
/** | ||
* Performs build deploy and launch of RNW apps. | ||
* @param args Unprocessed args passed from react-native CLI. | ||
* @param config Config passed from react-native CLI. | ||
* @param options Options passed from react-native CLI. | ||
*/ | ||
async function runWindowsInternal(args, config, options) { | ||
@@ -219,7 +185,9 @@ const verbose = options.logging === true; | ||
logging: options.logging, | ||
check: false, | ||
proj: options.proj, | ||
sln: options.sln, | ||
telemetry: options.telemetry, | ||
}; | ||
runWindowsPhase = 'AutoLink'; | ||
await autolink_1.autoLinkCommand.func(autolinkArgs, autolinkConfig, autoLinkOptions); | ||
await (0, autolink_1.autolinkWindowsInternal)(autolinkArgs, autolinkConfig, autoLinkOptions); | ||
} | ||
@@ -226,0 +194,0 @@ else { |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
import { Command, CommandOption, Dependency, ProjectConfig } from '@react-native-community/cli-types'; | ||
import { Command, CommandOption, Config, Dependency, ProjectConfig } from '@react-native-community/cli-types'; | ||
import { WindowsProjectConfig } from '../../config/projectConfig'; | ||
@@ -77,2 +77,9 @@ import { Ora } from 'ora'; | ||
} | ||
/** | ||
* Performs auto-linking for RNW native modules and apps. | ||
* @param args Unprocessed args passed from react-native CLI. | ||
* @param config Config passed from react-native CLI. | ||
* @param options Options passed from react-native CLI. | ||
*/ | ||
export declare function autolinkWindowsInternal(args: string[], config: Config, options: AutoLinkOptions): Promise<void>; | ||
export interface AutoLinkOptions { | ||
@@ -83,2 +90,3 @@ logging?: boolean; | ||
proj?: string; | ||
telemetry?: boolean; | ||
} | ||
@@ -85,0 +93,0 @@ export declare const autolinkOptions: CommandOption[]; |
@@ -30,3 +30,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.autoLinkCommand = exports.autolinkOptions = exports.AutolinkWindows = void 0; | ||
exports.autoLinkCommand = exports.autolinkOptions = exports.autolinkWindowsInternal = exports.AutolinkWindows = void 0; | ||
// Types in this file are inaccurate compared to usage in terms of falsiness. | ||
@@ -36,3 +36,3 @@ // We should try to rewrite some of this to do automated schema validation to | ||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */ | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -46,2 +46,3 @@ const chalk_1 = __importDefault(require("chalk")); | ||
const telemetry_1 = require("@react-native-windows/telemetry"); | ||
const telemetryHelpers_1 = require("./telemetryHelpers"); | ||
const xmldom_1 = require("@xmldom/xmldom"); | ||
@@ -317,3 +318,3 @@ const formatter = require('xml-formatter'); | ||
const actualContents = fs_1.default.existsSync(filePath) | ||
? (await fs_1.default.promises.readFile(filePath)).toString() | ||
? (await fs_1.default.readFile(filePath)).toString() | ||
: ''; | ||
@@ -325,3 +326,3 @@ const contentsChanged = expectedContents !== actualContents; | ||
verboseMessage(`Writing ${fileName}...`, this.options.logging); | ||
await fs_1.default.promises.writeFile(filePath, expectedContents, { | ||
await fs_1.default.writeFile(filePath, expectedContents, { | ||
encoding: 'utf8', | ||
@@ -576,2 +577,50 @@ flag: 'w', | ||
/** | ||
* Sanitizes the given option for telemetery. | ||
* @param key The key of the option. | ||
* @param value The unsanitized value of the option. | ||
* @returns The sanitized value of the option. | ||
*/ | ||
function optionSanitizer(key, value) { | ||
// Do not add a default case here. | ||
// Strings risking PII should just return true if present, false otherwise. | ||
// All others should return the value (or false if undefined). | ||
switch (key) { | ||
case 'sln': | ||
case 'proj': | ||
return value === undefined ? false : true; // Strip PII | ||
case 'logging': | ||
case 'check': | ||
case 'telemetry': | ||
return value === undefined ? false : value; // Return value | ||
} | ||
} | ||
/** | ||
* Get the extra props to add to the `autolink-windows` telemetry event. | ||
* @returns The extra props. | ||
*/ | ||
async function getExtraProps() { | ||
const extraProps = {}; | ||
return extraProps; | ||
} | ||
/** | ||
* The function run when calling `react-native autolink-windows`. | ||
* @param args Unprocessed args passed from react-native CLI. | ||
* @param config Config passed from react-native CLI. | ||
* @param options Options passed from react-native CLI. | ||
*/ | ||
async function autolinkWindows(args, config, options) { | ||
await (0, telemetryHelpers_1.startTelemetrySession)('autolink-windows', config, options, (0, telemetryHelpers_1.getDefaultOptions)(config, exports.autolinkOptions), optionSanitizer); | ||
let autolinkWindowsError; | ||
try { | ||
await autolinkWindowsInternal(args, config, options); | ||
} | ||
catch (ex) { | ||
autolinkWindowsError = | ||
ex instanceof Error ? ex : new Error(String(ex)); | ||
telemetry_1.Telemetry.trackException(autolinkWindowsError); | ||
} | ||
await (0, telemetryHelpers_1.endTelemetrySession)(autolinkWindowsError, getExtraProps); | ||
(0, commandWithProgress_1.setExitProcessWithError)(options.logging, autolinkWindowsError); | ||
} | ||
/** | ||
* Performs auto-linking for RNW native modules and apps. | ||
@@ -582,3 +631,3 @@ * @param args Unprocessed args passed from react-native CLI. | ||
*/ | ||
async function updateAutoLink(args, config, options) { | ||
async function autolinkWindowsInternal(args, config, options) { | ||
const startTime = perf_hooks_1.performance.now(); | ||
@@ -609,2 +658,3 @@ const spinner = (0, commandWithProgress_1.newSpinner)(options.check ? 'Checking auto-linked files...' : 'Auto-linking...'); | ||
} | ||
exports.autolinkWindowsInternal = autolinkWindowsInternal; | ||
exports.autolinkOptions = [ | ||
@@ -629,2 +679,6 @@ { | ||
}, | ||
{ | ||
name: '--no-telemetry', | ||
description: 'Disables sending telemetry that allows analysis of usage and failures of the react-native-windows CLI', | ||
}, | ||
]; | ||
@@ -637,5 +691,5 @@ /** | ||
description: 'performs autolinking', | ||
func: updateAutoLink, | ||
func: autolinkWindows, | ||
options: exports.autolinkOptions, | ||
}; | ||
//# sourceMappingURL=autolink.js.map |
@@ -16,1 +16,7 @@ /** | ||
export declare function newInfo(text: string): void; | ||
/** | ||
* Sets the process exit code and offers some information at the end of a CLI command. | ||
* @param loggingIsEnabled Is verbose logging enabled. | ||
* @param error The error caught during the process, if any. | ||
*/ | ||
export declare function setExitProcessWithError(loggingIsEnabled?: boolean, error?: Error): void; |
@@ -11,3 +11,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.newInfo = exports.newSuccess = exports.newWarn = exports.newError = exports.commandWithProgress = exports.runPowerShellScriptFunction = exports.powershell = exports.newSpinner = void 0; | ||
exports.setExitProcessWithError = exports.newInfo = exports.newSuccess = exports.newWarn = exports.newError = exports.commandWithProgress = exports.runPowerShellScriptFunction = exports.powershell = exports.newSpinner = void 0; | ||
const child_process_1 = require("child_process"); | ||
@@ -129,2 +129,23 @@ const ora_1 = __importDefault(require("ora")); | ||
exports.newInfo = newInfo; | ||
/** | ||
* Sets the process exit code and offers some information at the end of a CLI command. | ||
* @param loggingIsEnabled Is verbose logging enabled. | ||
* @param error The error caught during the process, if any. | ||
*/ | ||
function setExitProcessWithError(loggingIsEnabled, error) { | ||
if (error) { | ||
const errorType = error instanceof telemetry_1.CodedError ? error.type : 'Unknown'; | ||
process.exitCode = telemetry_1.CodedErrors[errorType]; | ||
if (loggingIsEnabled) { | ||
console.log(`Command failed with error ${chalk_1.default.bold(errorType)}: ${error.message}`); | ||
if (telemetry_1.Telemetry.isEnabled()) { | ||
console.log(`Your telemetry sessionId was ${chalk_1.default.bold(telemetry_1.Telemetry.getSessionId())}`); | ||
} | ||
} | ||
else { | ||
console.log(`Command failed. Re-run the command with ${chalk_1.default.bold('--logging')} for more information.`); | ||
} | ||
} | ||
} | ||
exports.setExitProcessWithError = setExitProcessWithError; | ||
//# sourceMappingURL=commandWithProgress.js.map |
@@ -32,3 +32,3 @@ "use strict"; | ||
const child_process_1 = require("child_process"); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const http_1 = __importDefault(require("http")); | ||
@@ -35,0 +35,0 @@ const path_1 = __importDefault(require("path")); |
@@ -31,3 +31,3 @@ "use strict"; | ||
const os_1 = require("os"); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -124,3 +124,3 @@ const child_process_1 = __importDefault(require("child_process")); | ||
if (!e) { | ||
const firstMessage = (await fs_1.default.promises.readFile(errorLog)) | ||
const firstMessage = (await fs_1.default.readFile(errorLog)) | ||
.toString() | ||
@@ -134,4 +134,4 @@ .split(os_1.EOL)[0]; | ||
// If we have no errors, delete the error log when we're done | ||
if ((await fs_1.default.promises.stat(errorLog)).size === 0) { | ||
await fs_1.default.promises.unlink(errorLog); | ||
if ((await fs_1.default.stat(errorLog)).size === 0) { | ||
await fs_1.default.unlink(errorLog); | ||
} | ||
@@ -138,0 +138,0 @@ } |
@@ -14,3 +14,3 @@ "use strict"; | ||
const child_process_1 = require("child_process"); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -17,0 +17,0 @@ /** |
@@ -12,3 +12,3 @@ "use strict"; | ||
exports.addProjectToSolution = exports.dotNetCoreProjectTypeGuid = void 0; | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -15,0 +15,0 @@ const chalk_1 = __importDefault(require("chalk")); |
@@ -11,3 +11,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs_1 = __importDefault(require("fs")); | ||
const fs_1 = __importDefault(require("@react-native-windows/fs")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -14,0 +14,0 @@ const child_process_1 = require("child_process"); |
{ | ||
"name": "@react-native-windows/cli", | ||
"version": "0.0.0-canary.99", | ||
"version": "0.0.0-canary.100", | ||
"license": "MIT", | ||
@@ -20,4 +20,5 @@ "main": "lib-commonjs/index.js", | ||
"dependencies": { | ||
"@react-native-windows/package-utils": "^0.0.0-canary.22", | ||
"@react-native-windows/telemetry": "^0.0.0-canary.24", | ||
"@react-native-windows/fs": "^1.0.0", | ||
"@react-native-windows/package-utils": "^0.0.0-canary.23", | ||
"@react-native-windows/telemetry": "^0.0.0-canary.25", | ||
"@xmldom/xmldom": "^0.7.5", | ||
@@ -43,3 +44,3 @@ "chalk": "^4.1.0", | ||
"@react-native-community/cli-types": "^5.0.1-alpha.0", | ||
"@rnw-scripts/eslint-config": "1.1.8", | ||
"@rnw-scripts/eslint-config": "1.1.9", | ||
"@rnw-scripts/jest-unittest-config": "1.2.4", | ||
@@ -46,0 +47,0 @@ "@rnw-scripts/just-task": "2.2.1", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
644837
82
5549
29
20