197 lines
5.0 KiB
TypeScript

import {
addProjectConfiguration,
convertNxGenerator,
formatFiles,
generateFiles,
GeneratorCallback,
getWorkspaceLayout,
joinPathFragments,
names,
offsetFromRoot,
TargetConfiguration,
toJS,
Tree,
updateJson,
} from '@nrwl/devkit';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import init from '../init/init';
import { addLinting } from '../../utils/add-linting';
import { addJest } from '../../utils/add-jest';
import { NormalizedSchema, normalizeOptions } from './lib/normalize-options';
import { Schema } from './schema';
export async function reactNativeLibraryGenerator(
host: Tree,
schema: Schema
): Promise<GeneratorCallback> {
const options = normalizeOptions(host, schema);
if (options.publishable === true && !schema.importPath) {
throw new Error(
`For publishable libs you have to provide a proper "--importPath" which needs to be a valid npm package name (e.g. my-awesome-lib or @myorg/my-lib)`
);
}
addProject(host, options);
createFiles(host, options);
const initTask = await init(host, {
...options,
skipFormat: true,
e2eTestRunner: 'none',
});
const lintTask = await addLinting(
host,
options.name,
options.projectRoot,
[joinPathFragments(options.projectRoot, 'tsconfig.lib.json')],
options.linter,
options.setParserOptionsProject
);
if (!options.skipTsConfig) {
updateBaseTsConfig(host, options);
}
const jestTask = await addJest(
host,
options.unitTestRunner,
options.name,
options.projectRoot
);
if (options.publishable || options.buildable) {
updateLibPackageNpmScope(host, options);
}
if (!options.skipFormat) {
await formatFiles(host);
}
return runTasksInSerial(initTask, lintTask, jestTask);
}
function addProject(host: Tree, options: NormalizedSchema) {
const targets: { [key: string]: TargetConfiguration } = {};
if (options.publishable || options.buildable) {
const { libsDir } = getWorkspaceLayout(host);
const external = ['react/jsx-runtime'];
targets.build = {
executor: '@nrwl/web:package',
outputs: ['{options.outputPath}'],
options: {
outputPath: `dist/${libsDir}/${options.projectDirectory}`,
tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
project: `${options.projectRoot}/package.json`,
entryFile: maybeJs(options, `${options.projectRoot}/src/index.ts`),
external,
rollupConfig: `@nrwl/react/plugins/bundle-rollup`,
assets: [
{
glob: `${options.projectRoot}/README.md`,
input: '.',
output: '.',
},
],
},
};
}
addProjectConfiguration(host, options.name, {
root: options.projectRoot,
sourceRoot: joinPathFragments(options.projectRoot, 'src'),
projectType: 'library',
tags: options.parsedTags,
targets,
});
}
function updateTsConfig(tree: Tree, options: NormalizedSchema) {
updateJson(
tree,
joinPathFragments(options.projectRoot, 'tsconfig.json'),
(json) => {
if (options.strict) {
json.compilerOptions = {
...json.compilerOptions,
forceConsistentCasingInFileNames: true,
strict: true,
noImplicitReturns: true,
noFallthroughCasesInSwitch: true,
};
}
return json;
}
);
}
function updateBaseTsConfig(host: Tree, options: NormalizedSchema) {
updateJson(host, 'tsconfig.base.json', (json) => {
const c = json.compilerOptions;
c.paths = c.paths || {};
delete c.paths[options.name];
if (c.paths[options.importPath]) {
throw new Error(
`You already have a library using the import path "${options.importPath}". Make sure to specify a unique one.`
);
}
const { libsDir } = getWorkspaceLayout(host);
c.paths[options.importPath] = [
maybeJs(
options,
joinPathFragments(libsDir, `${options.projectDirectory}/src/index.ts`)
),
];
return json;
});
}
function createFiles(host: Tree, options: NormalizedSchema) {
generateFiles(
host,
joinPathFragments(__dirname, './files/lib'),
options.projectRoot,
{
...options,
...names(options.name),
tmpl: '',
offsetFromRoot: offsetFromRoot(options.projectRoot),
}
);
if (!options.publishable && !options.buildable) {
host.delete(`${options.projectRoot}/package.json`);
}
if (options.js) {
toJS(host);
}
updateTsConfig(host, options);
}
function updateLibPackageNpmScope(host: Tree, options: NormalizedSchema) {
return updateJson(host, `${options.projectRoot}/package.json`, (json) => {
json.name = options.importPath;
return json;
});
}
function maybeJs(options: NormalizedSchema, path: string): string {
return options.js && (path.endsWith('.ts') || path.endsWith('.tsx'))
? path.replace(/\.tsx?$/, '.js')
: path;
}
export default reactNativeLibraryGenerator;
export const reactNativeLibrarySchematic = convertNxGenerator(
reactNativeLibraryGenerator
);