Update RNW CLI to preserve and re-use `init-windows` arguments (#13988)
## Description This PR updates the RNW CLI to preserve and re-use the arguments passed to `init-windows` when the project was created. ### Type of Change - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - This change requires a documentation update ### Why The RNW CLI should be smart enough to change its command's behaviors based on the template used by the project. Closes #13927 Closes #13926 Closes #13937 Closes #13174 ### What As per #13927: 1. The `init-windows` command will now stamp the `template`, `name`, and `namespace` arguments to the project's `package.json` file as follows: ```json { "react-native-windows": { "init-windows": { "name": "testcli", "namespace": "testcli", "template": "cpp-app", }, }, } ``` 2. The `config` command (and therefore all other CLI commands) will now contain the contents of this new `react-native-windows` section in a new `rnwConfig` property. Then, as per #13937: 1. The `init-windows` command will now use the previously saved arguments if they're available (and not otherwise overwritten by passed-in arguments) 2. If the template arg is missing (as it will be for all previously created projects) the `config` command will try to determine which template was used and inject it Additionally, as per #13926: 1. The `autolink-windows` command will now use the template information to use the correct files when autolinking Bonus, as per #13174: 1. The `autolink-windows` command will now include both the CPP and H file (the H file wasn't being regenerated before) ## Screenshots N/A ## Testing Verified new projects contain the new information. ## Changelog Should this change be included in the release notes: _yes_ Update RNW CLI to preserve and re-use `init-windows` arguments
This commit is contained in:
Родитель
46d8c0a5bd
Коммит
a9afb5fdda
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "Update RNW CLI to preserve and re-use `init-windows` arguments",
|
||||
"packageName": "@react-native-windows/cli",
|
||||
"email": "jthysell@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "Update RNW CLI to preserve and re-use `init-windows` arguments",
|
||||
"packageName": "react-native-windows",
|
||||
"email": "jthysell@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -119,18 +119,12 @@ export class AutoLinkWindows {
|
|||
// Generating cs/cpp files for app code consumption
|
||||
if (projectLang === 'cs') {
|
||||
this.changesNecessary =
|
||||
(await this.generateCSAutolinking(
|
||||
templateRoot,
|
||||
projectLang,
|
||||
projectDir,
|
||||
)) || this.changesNecessary;
|
||||
(await this.generateCSAutolinking(templateRoot, projectDir)) ||
|
||||
this.changesNecessary;
|
||||
} else if (projectLang === 'cpp') {
|
||||
this.changesNecessary =
|
||||
(await this.generateCppAutolinking(
|
||||
templateRoot,
|
||||
projectLang,
|
||||
projectDir,
|
||||
)) || this.changesNecessary;
|
||||
(await this.generateCppAutolinking(templateRoot, projectDir)) ||
|
||||
this.changesNecessary;
|
||||
}
|
||||
|
||||
// Generating props for app project consumption
|
||||
|
@ -284,23 +278,51 @@ export class AutoLinkWindows {
|
|||
});
|
||||
}
|
||||
|
||||
private getAutolinkTemplateFile(
|
||||
templateRoot: string,
|
||||
targetFile: string,
|
||||
): string {
|
||||
if (templateRoot.endsWith('\\template')) {
|
||||
// Old template split into different folders
|
||||
switch (path.extname(targetFile)) {
|
||||
case '.cpp':
|
||||
case '.h':
|
||||
templateRoot = path.join(templateRoot, 'cpp-app', 'src');
|
||||
break;
|
||||
case '.cs':
|
||||
templateRoot = path.join(templateRoot, 'cs-app', 'src');
|
||||
break;
|
||||
case '.props':
|
||||
case '.targets':
|
||||
default:
|
||||
templateRoot = path.join(templateRoot, 'shared-app', 'src');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// New template with projected layout
|
||||
templateRoot = path.join(templateRoot, 'windows', 'MyApp');
|
||||
}
|
||||
|
||||
return path.join(templateRoot, targetFile);
|
||||
}
|
||||
|
||||
private async generateCppAutolinking(
|
||||
templateRoot: string,
|
||||
projectLang: string,
|
||||
projectDir: string,
|
||||
) {
|
||||
const {cppPackageProviders, cppIncludes} = this.getCppReplacements();
|
||||
|
||||
const cppFileName = 'AutolinkedNativeModules.g.cpp';
|
||||
const headerFileName = 'AutolinkedNativeModules.g.h';
|
||||
|
||||
const srcCppFile = path.join(
|
||||
const srcCppFile = this.getAutolinkTemplateFile(templateRoot, cppFileName);
|
||||
const srcHeaderFile = this.getAutolinkTemplateFile(
|
||||
templateRoot,
|
||||
`${projectLang}-app`,
|
||||
'src',
|
||||
cppFileName,
|
||||
headerFileName,
|
||||
);
|
||||
|
||||
const destCppFile = path.join(projectDir, cppFileName);
|
||||
const destHeaderFile = path.join(projectDir, headerFileName);
|
||||
|
||||
verboseMessage(
|
||||
`Calculating ${chalk.bold(path.basename(destCppFile))}...`,
|
||||
|
@ -313,7 +335,22 @@ export class AutoLinkWindows {
|
|||
autolinkCppPackageProviders: cppPackageProviders,
|
||||
});
|
||||
|
||||
return await this.updateFile(destCppFile, cppContents);
|
||||
const cppChanged = await this.updateFile(destCppFile, cppContents);
|
||||
|
||||
verboseMessage(
|
||||
`Calculating ${chalk.bold(path.basename(destHeaderFile))}...`,
|
||||
this.options.logging,
|
||||
);
|
||||
|
||||
const headerContents = generatorCommon.resolveContents(srcHeaderFile, {
|
||||
useMustache: true,
|
||||
autolinkCppIncludes: cppIncludes,
|
||||
autolinkCppPackageProviders: cppPackageProviders,
|
||||
});
|
||||
|
||||
const headerChanged = await this.updateFile(destHeaderFile, headerContents);
|
||||
|
||||
return cppChanged || headerChanged;
|
||||
}
|
||||
|
||||
public getCppReplacements() {
|
||||
|
@ -340,14 +377,13 @@ export class AutoLinkWindows {
|
|||
if (cppPackageProviders === '') {
|
||||
// There are no windows dependencies, this would result in warning. C4100: 'packageProviders': unreferenced formal parameter.
|
||||
// therefore add a usage.
|
||||
cppPackageProviders = '\n UNREFERENCED_PARAMETER(packageProviders);'; // CODESYNC: vnext\local-cli\generator-windows\index.js
|
||||
cppPackageProviders = '\n UNREFERENCED_PARAMETER(packageProviders);'; // CODESYNC: @react-native-windows\cli\src\generator-windows\index.ts
|
||||
}
|
||||
return {cppPackageProviders, cppIncludes};
|
||||
}
|
||||
|
||||
private generateCSAutolinking(
|
||||
private async generateCSAutolinking(
|
||||
templateRoot: string,
|
||||
projectLang: string,
|
||||
projectDir: string,
|
||||
) {
|
||||
const {csUsingNamespaces, csReactPackageProviders} =
|
||||
|
@ -355,12 +391,7 @@ export class AutoLinkWindows {
|
|||
|
||||
const csFileName = 'AutolinkedNativeModules.g.cs';
|
||||
|
||||
const srcCsFile = path.join(
|
||||
templateRoot,
|
||||
`${projectLang}-app`,
|
||||
'src',
|
||||
csFileName,
|
||||
);
|
||||
const srcCsFile = this.getAutolinkTemplateFile(templateRoot, csFileName);
|
||||
|
||||
const destCsFile = path.join(projectDir, csFileName);
|
||||
|
||||
|
@ -375,7 +406,7 @@ export class AutoLinkWindows {
|
|||
autolinkCsReactPackageProviders: csReactPackageProviders,
|
||||
});
|
||||
|
||||
return this.updateFile(destCsFile, csContents);
|
||||
return await this.updateFile(destCsFile, csContents);
|
||||
}
|
||||
|
||||
public getCsReplacements() {
|
||||
|
@ -505,7 +536,10 @@ export class AutoLinkWindows {
|
|||
return contentsChanged;
|
||||
}
|
||||
|
||||
private generateAutolinkTargets(projectDir: string, templateRoot: string) {
|
||||
private async generateAutolinkTargets(
|
||||
projectDir: string,
|
||||
templateRoot: string,
|
||||
) {
|
||||
let projectReferencesForTargets = '';
|
||||
|
||||
const windowsDependencies = this.getWindowsDependencies();
|
||||
|
@ -534,10 +568,8 @@ export class AutoLinkWindows {
|
|||
|
||||
const targetFileName = 'AutolinkedNativeModules.g.targets';
|
||||
|
||||
const srcTargetFile = path.join(
|
||||
const srcTargetFile = this.getAutolinkTemplateFile(
|
||||
templateRoot,
|
||||
`shared-app`,
|
||||
'src',
|
||||
targetFileName,
|
||||
);
|
||||
|
||||
|
@ -553,20 +585,18 @@ export class AutoLinkWindows {
|
|||
autolinkProjectReferencesForTargets: projectReferencesForTargets,
|
||||
});
|
||||
|
||||
return this.updateFile(destTargetFile, targetContents);
|
||||
return await this.updateFile(destTargetFile, targetContents);
|
||||
}
|
||||
|
||||
private generateAutolinkProps(
|
||||
private async generateAutolinkProps(
|
||||
templateRoot: string,
|
||||
projectDir: string,
|
||||
propertiesForProps: string,
|
||||
) {
|
||||
const propsFileName = 'AutolinkedNativeModules.g.props';
|
||||
|
||||
const srcPropsFile = path.join(
|
||||
const srcPropsFile = this.getAutolinkTemplateFile(
|
||||
templateRoot,
|
||||
`shared-app`,
|
||||
'src',
|
||||
propsFileName,
|
||||
);
|
||||
|
||||
|
@ -582,7 +612,7 @@ export class AutoLinkWindows {
|
|||
autolinkPropertiesForProps: propertiesForProps,
|
||||
});
|
||||
|
||||
return this.updateFile(destPropsFile, propsContents);
|
||||
return await this.updateFile(destPropsFile, propsContents);
|
||||
}
|
||||
|
||||
private getCSModules() {
|
||||
|
@ -863,6 +893,16 @@ function resolveRnwRoot(projectConfig: WindowsProjectConfig) {
|
|||
*/
|
||||
function resolveTemplateRoot(projectConfig: WindowsProjectConfig) {
|
||||
const rnwPackage = resolveRnwRoot(projectConfig);
|
||||
const template = projectConfig.rnwConfig?.['init-windows']?.template as
|
||||
| string
|
||||
| undefined;
|
||||
|
||||
// For new templates, return the template's root path
|
||||
if (template && !template.startsWith('old/')) {
|
||||
return path.join(rnwPackage, 'templates', template);
|
||||
}
|
||||
|
||||
// For old (unknown templates) fall back to old behavior
|
||||
return path.join(rnwPackage, 'template');
|
||||
}
|
||||
|
||||
|
|
|
@ -95,38 +95,105 @@ export function findSolutionFiles(winFolder: string): string[] {
|
|||
return solutionFiles;
|
||||
}
|
||||
|
||||
export interface RawTemplateInfo {
|
||||
projectLang: 'cpp' | 'cs' | null;
|
||||
projectType: 'app' | 'lib' | null;
|
||||
projectArch: 'old' | 'new' | 'mixed' | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the RawTemplateInfo of the target project file.
|
||||
* @param filePath The absolute file path to check.
|
||||
* @return The RawTemplateInfo for the specific project.
|
||||
*/
|
||||
export function getRawTemplateInfo(filePath: string): RawTemplateInfo {
|
||||
const result: RawTemplateInfo = {
|
||||
projectLang: null,
|
||||
projectType: null,
|
||||
projectArch: null,
|
||||
};
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.projectLang = getProjectLanguage(filePath);
|
||||
|
||||
const projectContents = readProjectFile(filePath);
|
||||
|
||||
if (result.projectLang === 'cs') {
|
||||
if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CSharpApp.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'app';
|
||||
result.projectArch = 'old';
|
||||
} else if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CSharpLib.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'lib';
|
||||
result.projectArch = 'old';
|
||||
}
|
||||
} else if (result.projectLang === 'cpp') {
|
||||
if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CppApp.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'app';
|
||||
result.projectArch = 'old';
|
||||
} else if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CppLib.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'lib';
|
||||
result.projectArch = 'old';
|
||||
} else if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Composition.CppApp.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'app';
|
||||
result.projectArch = 'new';
|
||||
} else if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Composition.CppLib.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'lib';
|
||||
result.projectArch = 'new';
|
||||
} else if (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.CppLib.targets',
|
||||
)
|
||||
) {
|
||||
result.projectType = 'lib';
|
||||
result.projectArch = 'mixed';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the target file path is a RNW lib project file.
|
||||
* @param filePath The absolute file path to check.
|
||||
* @return Whether the path is to a RNW lib project file.
|
||||
*/
|
||||
export function isRnwDependencyProject(filePath: string): boolean {
|
||||
const projectContents = readProjectFile(filePath);
|
||||
|
||||
const projectLang = getProjectLanguage(filePath);
|
||||
if (projectLang === 'cs') {
|
||||
return importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CSharpLib.targets',
|
||||
);
|
||||
} else if (projectLang === 'cpp') {
|
||||
return (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CppLib.targets',
|
||||
) ||
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Composition.CppLib.targets',
|
||||
) ||
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.CppLib.targets',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
const rawTemplateInfo = getRawTemplateInfo(filePath);
|
||||
return rawTemplateInfo.projectType === 'lib';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,56 +233,14 @@ export function findDependencyProjectFiles(winFolder: string): string[] {
|
|||
return dependencyProjectFiles;
|
||||
}
|
||||
|
||||
type ReactNativeProjectType = 'unknown' | 'App-WinAppSDK';
|
||||
|
||||
function getReactNativeProjectType(
|
||||
value: string | null,
|
||||
): ReactNativeProjectType {
|
||||
switch (value) {
|
||||
case 'App-WinAppSDK':
|
||||
return value;
|
||||
|
||||
default:
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the target file path is a RNW app project file.
|
||||
* @param filePath The absolute file path to check.
|
||||
* @return Whether the path is to a RNW app project file.
|
||||
*/
|
||||
function isRnwAppProject(filePath: string): boolean {
|
||||
const projectContents = readProjectFile(filePath);
|
||||
|
||||
const rnProjectType = getReactNativeProjectType(
|
||||
tryFindPropertyValue(projectContents, 'ReactNativeProjectType'),
|
||||
);
|
||||
|
||||
if (rnProjectType !== 'unknown') {
|
||||
return true;
|
||||
}
|
||||
|
||||
const projectLang = getProjectLanguage(filePath);
|
||||
if (projectLang === 'cs') {
|
||||
return importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CSharpApp.targets',
|
||||
);
|
||||
} else if (projectLang === 'cpp') {
|
||||
return (
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Uwp.CppApp.targets',
|
||||
) ||
|
||||
importProjectExists(
|
||||
projectContents,
|
||||
'Microsoft.ReactNative.Composition.CppApp.targets',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
export function isRnwAppProject(filePath: string): boolean {
|
||||
const rawTemplateInfo = getRawTemplateInfo(filePath);
|
||||
return rawTemplateInfo.projectType === 'app';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -503,3 +528,25 @@ export function getExperimentalFeatures(
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getRnwConfig(
|
||||
root: string,
|
||||
projectFile: string,
|
||||
): Record<string, any> | undefined {
|
||||
const pkgJson = require(path.join(root, 'package.json'));
|
||||
|
||||
const config: Record<string, any> = pkgJson['react-native-windows'] ?? {};
|
||||
|
||||
// if init-windows is missing (most existing projects), try to auto-calculate it
|
||||
config['init-windows'] ??= {};
|
||||
if (!config['init-windows'].template) {
|
||||
const info = getRawTemplateInfo(projectFile);
|
||||
if (info.projectArch && info.projectLang && info.projectType) {
|
||||
config['init-windows'].template = `${
|
||||
info.projectArch === 'old' ? 'old/uwp-' : ''
|
||||
}${info.projectLang}-${info.projectType}`;
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ opt - Item is optional. If an override file exists, it MAY provide it. If no ov
|
|||
csPackageProviders: [], // (req) Array of fully qualified cs IReactPackageProviders, ie: 'NugetModule.ReactPackageProvider'
|
||||
},
|
||||
],
|
||||
rnwConfig: Record<string, any>, // (auto) Object extracted from 'react-native-windows' property in package.json
|
||||
}
|
||||
|
||||
Example react-native.config.js for a 'MyModule':
|
||||
|
@ -105,6 +106,7 @@ export interface WindowsDependencyConfig {
|
|||
solutionFile?: string | null;
|
||||
projects: ProjectDependency[];
|
||||
nugetPackages: NuGetPackageDependency[];
|
||||
rnwConfig?: Record<string, any>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,6 +324,8 @@ export function dependencyConfigWindows(
|
|||
csNamespaces,
|
||||
csPackageProviders,
|
||||
});
|
||||
|
||||
result.rnwConfig ??= configUtils.getRnwConfig(folder, projectFile);
|
||||
} else {
|
||||
const projectPath = path.relative(sourceDir, projectFile);
|
||||
result.projects.push({
|
||||
|
|
|
@ -39,7 +39,8 @@ opt - Item is optional. If an override file exists, it MAY provide it. If no ov
|
|||
projectLang: string, // (auto) Language of the project, cpp or cs, determined from projectFile
|
||||
projectGuid: string, // (auto) Project identifier, determined from projectFile
|
||||
},
|
||||
experimentalFeatures: Record<String, string> // (auto) Properties extracted from ExperimentalFeatures.props
|
||||
experimentalFeatures: Record<string, string>, // (auto) Properties extracted from ExperimentalFeatures.props
|
||||
rnwConfig: Record<string, any>, // (auto) Object extracted from 'react-native-windows' property in package.json
|
||||
}
|
||||
|
||||
Example react-native.config.js for a 'MyApp':
|
||||
|
@ -73,6 +74,7 @@ export interface WindowsProjectConfig {
|
|||
project: Project;
|
||||
useWinUI3?: boolean;
|
||||
experimentalFeatures?: Record<string, string>;
|
||||
rnwConfig?: Record<string, any>;
|
||||
}
|
||||
|
||||
type DeepPartial<T> = {[P in keyof T]?: DeepPartial<T[P]>};
|
||||
|
@ -234,6 +236,18 @@ export function projectConfigWindows(
|
|||
result.experimentalFeatures = result.experimentalFeatures ?? {};
|
||||
result.experimentalFeatures.UseExperimentalNuget = useExperimentalNuget;
|
||||
}
|
||||
|
||||
result.rnwConfig = configUtils.getRnwConfig(folder, projectFile);
|
||||
}
|
||||
|
||||
if (!result.rnwConfig) {
|
||||
// No rnwConfig, maybe it's actually a lib, try to get some info from it
|
||||
let projectFile = '';
|
||||
const foundProjects = configUtils.findDependencyProjectFiles(sourceDir);
|
||||
if (foundProjects.length > 0) {
|
||||
projectFile = path.join(sourceDir, foundProjects[0]);
|
||||
}
|
||||
result.rnwConfig = configUtils.getRnwConfig(folder, projectFile);
|
||||
}
|
||||
|
||||
return result as WindowsProjectConfig;
|
||||
|
|
|
@ -52,11 +52,13 @@ export interface InitWindowsTemplateConfig {
|
|||
|
||||
export class InitWindows {
|
||||
protected readonly rnwPath: string;
|
||||
protected readonly rnwConfig?: Record<string, any>;
|
||||
protected readonly templates: Map<string, InitWindowsTemplateConfig> =
|
||||
new Map();
|
||||
|
||||
constructor(readonly config: Config, readonly options: InitOptions) {
|
||||
this.rnwPath = pathHelpers.resolveRnwRoot(this.config.root);
|
||||
this.rnwConfig = this.config.project.windows?.rnwConfig;
|
||||
}
|
||||
|
||||
protected verboseMessage(message: any) {
|
||||
|
@ -140,6 +142,7 @@ export class InitWindows {
|
|||
console.log(`\n`);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
public async run(spinner: Ora) {
|
||||
await this.loadTemplates();
|
||||
|
||||
|
@ -150,7 +153,9 @@ export class InitWindows {
|
|||
return;
|
||||
}
|
||||
|
||||
this.options.template ??= this.getDefaultTemplateName();
|
||||
this.options.template ??=
|
||||
(this.rnwConfig?.['init-windows']?.template as string | undefined) ??
|
||||
this.getDefaultTemplateName();
|
||||
|
||||
spinner.info(`Using template '${this.options.template}'...`);
|
||||
if (!this.templates.has(this.options.template.replace(/[\\]/g, '/'))) {
|
||||
|
@ -172,9 +177,11 @@ export class InitWindows {
|
|||
);
|
||||
}
|
||||
|
||||
// If no project name is provided, calculate the name and clean if necessary
|
||||
// If no project name is provided, check previously used name or calculate a name and clean if necessary
|
||||
if (!this.options.name) {
|
||||
const projectName = this.getReactNativeProjectName(this.config.root);
|
||||
const projectName =
|
||||
(this.rnwConfig?.['init-windows']?.name as string | undefined) ??
|
||||
this.getReactNativeProjectName(this.config.root);
|
||||
this.options.name = nameHelpers.isValidProjectName(projectName)
|
||||
? projectName
|
||||
: nameHelpers.cleanName(projectName);
|
||||
|
@ -199,9 +206,11 @@ export class InitWindows {
|
|||
);
|
||||
}
|
||||
|
||||
// If no project namespace is provided, use the project name and clean if necessary
|
||||
// If no project namespace is provided, check previously used namespace or use the project name and clean if necessary
|
||||
if (!this.options.namespace) {
|
||||
const namespace = this.options.name;
|
||||
const namespace =
|
||||
(this.rnwConfig?.['init-windows']?.namespace as string | undefined) ??
|
||||
this.options.name;
|
||||
this.options.namespace = nameHelpers.isValidProjectNamespace(namespace)
|
||||
? namespace
|
||||
: nameHelpers.cleanNamespace(namespace);
|
||||
|
|
|
@ -227,7 +227,7 @@ export async function copyProjectTemplateAndReplace(
|
|||
autolinkCsReactPackageProviders: '',
|
||||
autolinkCppIncludes: '',
|
||||
autolinkCppPackageProviders:
|
||||
'\n UNREFERENCED_PARAMETER(packageProviders);', // CODESYNC: vnext\local-cli\runWindows\utils\autolink.js
|
||||
'\n UNREFERENCED_PARAMETER(packageProviders);', // CODESYNC: @react-native-windows\cli\src\commands\autolinkWindows\autolinkWindows.ts
|
||||
};
|
||||
|
||||
const commonMappings =
|
||||
|
|
|
@ -75,6 +75,13 @@ async function getFileMappings(config = {}, options = {}) {
|
|||
addReactNativePublicAdoFeed: true || isCanary, // Temporary true for all new projects until code-signing is restored, see issue #14030
|
||||
|
||||
cppNugetPackages,
|
||||
|
||||
// autolinking template variables
|
||||
autolinkPropertiesForProps: '',
|
||||
autolinkProjectReferencesForTargets: '',
|
||||
autolinkCppIncludes: '',
|
||||
autolinkCppPackageProviders:
|
||||
'\n UNREFERENCED_PARAMETER(packageProviders);', // CODESYNC: @react-native-windows\cli\src\commands\autolinkWindows\autolinkWindows.ts
|
||||
};
|
||||
|
||||
let fileMappings = [];
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- AutolinkedNativeModules.g.props contents generated by "npx @react-native-community/cli autolink-windows" -->
|
||||
<PropertyGroup>{{ &autolinkPropertiesForProps }}
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- AutolinkedNativeModules.g.targets contents generated by "npx @react-native-community/cli autolink-windows" -->
|
||||
<ItemGroup>{{ &autolinkProjectReferencesForTargets }}
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -55,6 +55,8 @@ function makeGenerateWindowsWrapper(
|
|||
options.namespace,
|
||||
generateOptions,
|
||||
);
|
||||
|
||||
await templateUtils.updateProjectPackageJson(config, options);
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -110,7 +110,12 @@ async function runNpmInstall(config = {}, options = {}) {
|
|||
}
|
||||
}
|
||||
|
||||
async function updateProjectPackageJson(config = {}, options = {}, props = {}) {
|
||||
async function updateProjectPackageJson(
|
||||
config = {},
|
||||
options = {},
|
||||
props = {},
|
||||
saveOptions = true,
|
||||
) {
|
||||
const projectRoot = config?.root ?? process.cwd();
|
||||
const projectPackage =
|
||||
await pkgUtils.WritableNpmPackage.fromPath(projectRoot);
|
||||
|
@ -121,6 +126,16 @@ async function updateProjectPackageJson(config = {}, options = {}, props = {}) {
|
|||
);
|
||||
}
|
||||
|
||||
if (saveOptions) {
|
||||
props['react-native-windows'] = {
|
||||
'init-windows': {
|
||||
name: options.name,
|
||||
namespace: options.namespace,
|
||||
template: options.template,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (options?.logging) {
|
||||
console.log(`Modifying ${path.join(projectRoot, 'package.json')}...`);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче