nx/packages/react/src/generators/library/lib/normalize-options.ts

127 lines
3.4 KiB
TypeScript

import {
getProjects,
joinPathFragments,
logger,
normalizePath,
Tree,
} from '@nx/devkit';
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
import { assertValidStyle } from '../../../utils/assertion';
import { NormalizedSchema, Schema } from '../schema';
export async function normalizeOptions(
host: Tree,
options: Schema
): Promise<NormalizedSchema> {
const {
projectName,
names: projectNames,
projectRoot,
importPath,
} = await determineProjectNameAndRootOptions(host, {
name: options.name,
projectType: 'library',
directory: options.directory,
importPath: options.importPath,
projectNameAndRootFormat: options.projectNameAndRootFormat,
callingGenerator: '@nx/react:library',
});
const fileName = options.simpleName
? projectNames.projectSimpleName
: projectNames.projectFileName;
const parsedTags = options.tags
? options.tags.split(',').map((s) => s.trim())
: [];
let bundler = options.bundler ?? 'none';
if (bundler === 'none') {
if (options.publishable) {
logger.warn(
`Publishable libraries cannot be used with bundler: 'none'. Defaulting to 'rollup'.`
);
bundler = 'rollup';
}
if (options.buildable) {
logger.warn(
`Buildable libraries cannot be used with bundler: 'none'. Defaulting to 'rollup'.`
);
bundler = 'rollup';
}
}
const normalized = {
...options,
compiler: options.compiler ?? 'babel',
bundler,
fileName,
routePath: `/${projectNames.projectSimpleName}`,
name: projectName,
projectRoot,
parsedTags,
importPath,
} as NormalizedSchema;
// Libraries with a bundler or is publishable must also be buildable.
normalized.buildable = Boolean(
normalized.bundler !== 'none' || options.buildable || options.publishable
);
normalized.inSourceTests === normalized.minimal || normalized.inSourceTests;
if (options.appProject) {
const appProjectConfig = getProjects(host).get(options.appProject);
if (appProjectConfig.projectType !== 'application') {
throw new Error(
`appProject expected type of "application" but got "${appProjectConfig.projectType}"`
);
}
normalized.appMain =
appProjectConfig.targets.build.options.main ??
findMainEntry(host, appProjectConfig.root);
normalized.appSourceRoot = normalizePath(appProjectConfig.sourceRoot);
// TODO(jack): We should use appEntryFile instead of appProject so users can directly set it rather than us inferring it.
if (!normalized.appMain) {
throw new Error(
`Could not locate project main for ${options.appProject}`
);
}
}
assertValidStyle(normalized.style);
return normalized;
}
function findMainEntry(tree: Tree, projectRoot: string): string | undefined {
const mainFiles = [
// These are the main files we generate with.
'src/main.ts',
'src/main.tsx',
'src/main.js',
'src/main.jsx',
// Other options just in case
'src/index.ts',
'src/index.tsx',
'src/index.js',
'src/index.jsx',
'main.ts',
'main.tsx',
'main.js',
'main.jsx',
'index.ts',
'index.tsx',
'index.js',
'index.jsx',
];
const mainEntry = mainFiles.find((file) =>
tree.exists(joinPathFragments(projectRoot, file))
);
return mainEntry ? joinPathFragments(projectRoot, mainEntry) : undefined;
}