fix(angular): improve prefix handling across generators (#16913)
This commit is contained in:
parent
20f25bfe1c
commit
284fedab46
@ -11,7 +11,7 @@ import { E2eTestRunner, UnitTestRunner } from '../../../utils/test-runners';
|
||||
import { Linter } from '@nx/linter';
|
||||
import {
|
||||
normalizeDirectory,
|
||||
normalizePrefix,
|
||||
normalizeNewProjectPrefix,
|
||||
normalizeProjectName,
|
||||
} from '../../utils/project';
|
||||
|
||||
@ -45,7 +45,7 @@ export function normalizeOptions(
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
: [];
|
||||
|
||||
const prefix = normalizePrefix(options.prefix, npmScope);
|
||||
const prefix = normalizeNewProjectPrefix(options.prefix, npmScope, 'app');
|
||||
|
||||
options.standaloneConfig = options.standaloneConfig ?? standaloneAsDefault;
|
||||
|
||||
|
||||
@ -64,6 +64,7 @@ export async function host(tree: Tree, options: Schema) {
|
||||
skipFormat: true,
|
||||
skipE2E,
|
||||
e2eProjectName: skipE2E ? undefined : `${appName}-e2e`,
|
||||
prefix: options.prefix,
|
||||
});
|
||||
|
||||
let installTasks = [appInstallTask];
|
||||
|
||||
@ -10,7 +10,7 @@ import { Schema } from '../schema';
|
||||
import { NormalizedSchema } from './normalized-schema';
|
||||
import { Linter } from '@nx/linter';
|
||||
import { UnitTestRunner } from '../../../utils/test-runners';
|
||||
import { normalizePrefix } from '../../utils/project';
|
||||
import { normalizeNewProjectPrefix } from '../../utils/project';
|
||||
|
||||
export function normalizeOptions(host: Tree, schema: Schema): NormalizedSchema {
|
||||
// Create a schema with populated default values
|
||||
@ -55,7 +55,7 @@ export function normalizeOptions(host: Tree, schema: Schema): NormalizedSchema {
|
||||
? options.tags.split(',').map((s) => s.trim())
|
||||
: [];
|
||||
const modulePath = `${projectRoot}/src/lib/${fileName}.module.ts`;
|
||||
const prefix = normalizePrefix(options.prefix, npmScope);
|
||||
const prefix = normalizeNewProjectPrefix(options.prefix, npmScope, 'lib');
|
||||
|
||||
options.standaloneConfig = options.standaloneConfig ?? standaloneAsDefault;
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ export async function remote(tree: Tree, options: Schema) {
|
||||
skipE2E,
|
||||
e2eProjectName: skipE2E ? undefined : `${appName}-e2e`,
|
||||
standalone: options.standalone,
|
||||
prefix: options.prefix,
|
||||
});
|
||||
|
||||
let installTasks = [appInstallTask];
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import {
|
||||
generateFiles,
|
||||
joinPathFragments,
|
||||
readNxJson,
|
||||
readProjectConfiguration,
|
||||
} from '@nx/devkit';
|
||||
import { generateFiles, joinPathFragments } from '@nx/devkit';
|
||||
import { addRoute } from '../../../utils/nx-devkit/route-utils';
|
||||
import type { AngularProjectConfiguration } from '../../../utils/types';
|
||||
import type { Schema } from '../schema';
|
||||
|
||||
export function addRemoteEntry(
|
||||
@ -14,11 +8,6 @@ export function addRemoteEntry(
|
||||
{ appName, routing, prefix, standalone }: Schema,
|
||||
appRoot: string
|
||||
) {
|
||||
prefix =
|
||||
prefix ??
|
||||
(readProjectConfiguration(tree, appName) as AngularProjectConfiguration)
|
||||
?.prefix ??
|
||||
readNxJson(tree).npmScope;
|
||||
generateFiles(
|
||||
tree,
|
||||
standalone
|
||||
|
||||
@ -5,6 +5,7 @@ export * from './change-build-target';
|
||||
export * from './fix-bootstrap';
|
||||
export * from './generate-config';
|
||||
export * from './get-remotes-with-ports';
|
||||
export * from './normalize-options';
|
||||
export * from './set-tsconfig-target';
|
||||
export * from './setup-host-if-dynamic';
|
||||
export * from './setup-serve-target';
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import { getProjectPrefix } from '../../utils/project';
|
||||
import type { NormalizedOptions, Schema } from '../schema';
|
||||
|
||||
export function normalizeOptions(
|
||||
tree: Tree,
|
||||
options: Schema
|
||||
): NormalizedOptions {
|
||||
return {
|
||||
...options,
|
||||
federationType: options.federationType ?? 'static',
|
||||
prefix: options.prefix ?? getProjectPrefix(tree, options.appName),
|
||||
};
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
import { Tree } from 'nx/src/generators/tree';
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import { joinPathFragments, readProjectConfiguration } from '@nx/devkit';
|
||||
import { Schema } from '../schema';
|
||||
import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration';
|
||||
import { joinPathFragments } from 'nx/src/utils/path';
|
||||
import { readNxJson } from '@nx/devkit';
|
||||
|
||||
export function removeDeadCodeFromRemote(tree: Tree, options: Schema) {
|
||||
const projectName = options.appName;
|
||||
@ -73,13 +71,15 @@ export class AppModule {}`
|
||||
} else {
|
||||
tree.delete(pathToAppComponent);
|
||||
|
||||
const prefix = options.prefix ?? readNxJson(tree).npmScope;
|
||||
const remoteEntrySelector = `${prefix}-${projectName}-entry`;
|
||||
|
||||
const pathToIndexHtml = project.targets.build.options.index;
|
||||
const indexContents = tree.read(pathToIndexHtml, 'utf-8');
|
||||
|
||||
const rootSelectorRegex = new RegExp(`${prefix}-root`, 'ig');
|
||||
const rootSelectorRegex = new RegExp(
|
||||
`${options.prefix || 'app'}-root`,
|
||||
'ig'
|
||||
);
|
||||
const remoteEntrySelector = `${
|
||||
options.prefix || 'app'
|
||||
}-${projectName}-entry`;
|
||||
const newIndexContents = indexContents.replace(
|
||||
rootSelectorRegex,
|
||||
remoteEntrySelector
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
type FederationType = 'static' | 'dynamic';
|
||||
|
||||
export interface Schema {
|
||||
appName: string;
|
||||
mfType: 'host' | 'remote';
|
||||
port?: number;
|
||||
remotes?: string[];
|
||||
host?: string;
|
||||
federationType?: 'static' | 'dynamic';
|
||||
federationType?: FederationType;
|
||||
routing?: boolean;
|
||||
skipFormat?: boolean;
|
||||
skipPackageJson?: boolean;
|
||||
@ -13,3 +15,8 @@ export interface Schema {
|
||||
standalone?: boolean;
|
||||
skipE2E?: boolean;
|
||||
}
|
||||
|
||||
export interface NormalizedOptions extends Schema {
|
||||
federationType: FederationType;
|
||||
prefix: string | undefined;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
fixBootstrap,
|
||||
generateWebpackConfig,
|
||||
getRemotesWithPorts,
|
||||
normalizeOptions,
|
||||
removeDeadCodeFromRemote,
|
||||
setupHostIfDynamic,
|
||||
setupServeTarget,
|
||||
@ -24,17 +25,16 @@ import { getInstalledAngularVersionInfo } from '../utils/version-utils';
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
import { lt } from 'semver';
|
||||
|
||||
export async function setupMf(tree: Tree, options: Schema) {
|
||||
export async function setupMf(tree: Tree, rawOptions: Schema) {
|
||||
const installedAngularInfo = getInstalledAngularVersionInfo(tree);
|
||||
|
||||
if (lt(installedAngularInfo.version, '14.1.0') && options.standalone) {
|
||||
if (lt(installedAngularInfo.version, '14.1.0') && rawOptions.standalone) {
|
||||
throw new Error(
|
||||
`The --standalone flag is not supported in your current version of Angular (${installedAngularInfo.version}). Please update to a version of Angular that supports Standalone Components (>= 14.1.0).`
|
||||
);
|
||||
}
|
||||
const projectConfig = readProjectConfiguration(tree, options.appName);
|
||||
|
||||
options.federationType = options.federationType ?? 'static';
|
||||
const options = normalizeOptions(tree, rawOptions);
|
||||
const projectConfig = readProjectConfiguration(tree, options.appName);
|
||||
|
||||
if (options.mfType === 'host') {
|
||||
setupHostIfDynamic(tree, options);
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { names } from '@nx/devkit';
|
||||
import type { Tree } from '@nx/devkit';
|
||||
import { names, readNxJson, readProjectConfiguration } from '@nx/devkit';
|
||||
import type { AngularProjectConfiguration } from '../../utils/types';
|
||||
|
||||
export function normalizeDirectory(
|
||||
appName: string,
|
||||
@ -16,19 +18,27 @@ export function normalizeProjectName(
|
||||
return normalizeDirectory(appName, directoryName).replace(/\//g, '-');
|
||||
}
|
||||
|
||||
export function normalizePrefix(
|
||||
export function normalizeNewProjectPrefix(
|
||||
prefix: string | undefined,
|
||||
npmScope: string | undefined
|
||||
npmScope: string | undefined,
|
||||
fallbackPrefix: string
|
||||
): string {
|
||||
if (prefix) {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
// Prefix needs to be a valid html selector, if npmScope it's not valid, we don't default
|
||||
// to it and let it fall through to the Angular schematic to handle it
|
||||
// https://github.com/angular/angular-cli/blob/1c634cd327e5a850553b258aa2d5e6a6b2c75c65/packages/schematics/angular/component/index.ts#L130
|
||||
const htmlSelectorRegex =
|
||||
/^[a-zA-Z][.0-9a-zA-Z]*(:?-[a-zA-Z][.0-9a-zA-Z]*)*$/;
|
||||
|
||||
if (prefix) {
|
||||
if (!htmlSelectorRegex.test(prefix)) {
|
||||
throw new Error(
|
||||
'The provided "prefix" is invalid. The prefix must start with a letter, and must contain only alphanumeric characters or dashes. When adding a dash the segment after the dash must also start with a letter.'
|
||||
);
|
||||
}
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
if (npmScope && !htmlSelectorRegex.test(npmScope)) {
|
||||
throw new Error(`The "--prefix" option was not provided, therefore attempted to use the "npmScope" defined in "nx.json" to set the application's selector prefix, but it is invalid.
|
||||
|
||||
@ -41,5 +51,15 @@ If you encountered this error when creating a new Nx Workspace, the workspace na
|
||||
Valid selector prefixes must start with a letter, and must contain only alphanumeric characters or dashes. When adding a dash the segment after the dash must also start with a letter.`);
|
||||
}
|
||||
|
||||
return npmScope || 'app';
|
||||
return npmScope || fallbackPrefix;
|
||||
}
|
||||
|
||||
export function getProjectPrefix(
|
||||
tree: Tree,
|
||||
project: string
|
||||
): string | undefined {
|
||||
return (
|
||||
(readProjectConfiguration(tree, project) as AngularProjectConfiguration)
|
||||
.prefix ?? readNxJson(tree).npmScope
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user