cleanup(angular): remove v14 specific code for generators that did not change (#13950)
This commit is contained in:
parent
f3465a9c07
commit
712d65b451
@ -1,157 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`component Generator support angular 14 --flat should create the component correctly and export it in the entry point 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 --flat should create the component correctly and not export it when "export=false" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 --path should create the component correctly and export it in the entry point 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 secondary entry points should create the component correctly and export it in the entry point 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 secondary entry points should create the component correctly and export it in the entry point 2`] = `
|
||||
"export * from \\"./lib/secondary.module\\";
|
||||
export * from \\"./lib/example/example.component\\";"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and export it in the entry point when "export=true" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and export it in the entry point when "export=true" 2`] = `
|
||||
"export * from \\"./lib/lib.module\\";
|
||||
export * from \\"./lib/example/example.component\\";"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and export it in the entry point when is standalone and "export=true" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and not export it in the entry point when "export=false" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and not export it in the entry point when is standalone and "export=false" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly and not export it when "--skip-import=true" 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`component Generator support angular 14 should create the component correctly but not export it in the entry point when it does not exist 1`] = `
|
||||
"import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'example',
|
||||
templateUrl: './example.component.html',
|
||||
styleUrls: ['./example.component.css']
|
||||
})
|
||||
export class ExampleComponent {
|
||||
|
||||
}
|
||||
"
|
||||
`;
|
||||
@ -1,53 +0,0 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import {
|
||||
formatFiles,
|
||||
normalizePath,
|
||||
readProjectConfiguration,
|
||||
readWorkspaceConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
|
||||
import { pathStartsWith } from '../../utils/path';
|
||||
import { exportComponentInEntryPoint } from './lib/component';
|
||||
import { normalizeOptions } from './lib/normalize-options';
|
||||
import type { NormalizedSchema, Schema } from './schema';
|
||||
|
||||
export async function componentGenerator(tree: Tree, rawOptions: Schema) {
|
||||
const options = await normalizeOptions(tree, rawOptions);
|
||||
const { projectSourceRoot, ...schematicOptions } = options;
|
||||
|
||||
checkPathUnderProjectRoot(tree, options);
|
||||
|
||||
const angularComponentSchematic = wrapAngularDevkitSchematic(
|
||||
'@schematics/angular',
|
||||
'component'
|
||||
);
|
||||
await angularComponentSchematic(tree, schematicOptions);
|
||||
|
||||
exportComponentInEntryPoint(tree, options);
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
function checkPathUnderProjectRoot(tree: Tree, schema: NormalizedSchema): void {
|
||||
if (!schema.path) {
|
||||
return;
|
||||
}
|
||||
|
||||
const project =
|
||||
schema.project ?? readWorkspaceConfiguration(tree).defaultProject;
|
||||
const { root } = readProjectConfiguration(tree, project);
|
||||
|
||||
let pathToComponent = normalizePath(schema.path);
|
||||
pathToComponent = pathToComponent.startsWith('/')
|
||||
? pathToComponent.slice(1)
|
||||
: pathToComponent;
|
||||
|
||||
if (!pathStartsWith(pathToComponent, root)) {
|
||||
throw new Error(
|
||||
`The path provided for the component (${schema.path}) does not exist under the project root (${root}). ` +
|
||||
`Please make sure to provide a path that exists under the project root.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default componentGenerator;
|
||||
@ -1,59 +0,0 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { logger, readProjectConfiguration, stripIndents } from '@nrwl/devkit';
|
||||
import { getComponentFileInfo } from '../../../utils/file-info';
|
||||
import { locateLibraryEntryPointFromDirectory } from '../../../utils/entry-point';
|
||||
import { getRelativeImportToFile } from '../../../utils/path';
|
||||
import type { NormalizedSchema } from '../schema';
|
||||
import { shouldExportInEntryPoint } from './entry-point';
|
||||
import { findModuleFromOptions } from './module';
|
||||
|
||||
export function exportComponentInEntryPoint(
|
||||
tree: Tree,
|
||||
schema: NormalizedSchema
|
||||
): void {
|
||||
if (!schema.export || (schema.skipImport && !schema.standalone)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { root, projectType } = readProjectConfiguration(tree, schema.project);
|
||||
|
||||
if (projectType === 'application') {
|
||||
return;
|
||||
}
|
||||
|
||||
const { directory, filePath } = getComponentFileInfo(tree, schema);
|
||||
|
||||
const entryPointPath = locateLibraryEntryPointFromDirectory(
|
||||
tree,
|
||||
directory,
|
||||
root,
|
||||
schema.projectSourceRoot
|
||||
);
|
||||
if (!entryPointPath) {
|
||||
logger.warn(
|
||||
`Unable to determine whether the component should be exported in the library entry point file. ` +
|
||||
`The library's entry point file could not be found. Skipping exporting the component in the entry point file.`
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!schema.standalone) {
|
||||
const modulePath = findModuleFromOptions(tree, schema, root);
|
||||
if (!shouldExportInEntryPoint(tree, entryPointPath, modulePath)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const relativePathFromEntryPoint = getRelativeImportToFile(
|
||||
entryPointPath,
|
||||
filePath
|
||||
);
|
||||
const updateEntryPointContent = stripIndents`${tree.read(
|
||||
entryPointPath,
|
||||
'utf-8'
|
||||
)}
|
||||
export * from "${relativePathFromEntryPoint}";`;
|
||||
|
||||
tree.write(entryPointPath, updateEntryPointContent);
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||
import type { StringLiteral } from 'typescript';
|
||||
import { getRelativeImportToFile } from '../../../utils/path';
|
||||
|
||||
export function shouldExportInEntryPoint(
|
||||
tree: Tree,
|
||||
entryPoint: string,
|
||||
modulePath: string
|
||||
): boolean {
|
||||
if (!modulePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const moduleImportPath = getRelativeImportToFile(entryPoint, modulePath);
|
||||
const entryPointContent = tree.read(entryPoint, 'utf-8');
|
||||
const entryPointAst = tsquery.ast(entryPointContent);
|
||||
const moduleExport = tsquery(
|
||||
entryPointAst,
|
||||
`ExportDeclaration StringLiteral[value='${moduleImportPath}']`,
|
||||
{ visitAllChildren: true }
|
||||
)[0] as StringLiteral;
|
||||
|
||||
return Boolean(moduleExport);
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { joinPathFragments, normalizePath } from '@nrwl/devkit';
|
||||
import { basename, dirname } from 'path';
|
||||
import type { NormalizedSchema } from '../schema';
|
||||
|
||||
// Adapted from https://github.com/angular/angular-cli/blob/main/packages/schematics/angular/utility/find-module.ts#L29
|
||||
// to match the logic in the component schematic. It doesn't throw if it can't
|
||||
// find a module since the schematic would have thrown before getting here.
|
||||
const moduleExt = '.module.ts';
|
||||
const routingModuleExt = '-routing.module.ts';
|
||||
|
||||
export function findModuleFromOptions(
|
||||
tree: Tree,
|
||||
options: NormalizedSchema,
|
||||
projectRoot: string
|
||||
): string | null {
|
||||
if (!options.module) {
|
||||
const pathToCheck = joinPathFragments(options.path, options.name);
|
||||
|
||||
return normalizePath(findModule(tree, pathToCheck, projectRoot));
|
||||
} else {
|
||||
const modulePath = joinPathFragments(options.path, options.module);
|
||||
const componentPath = joinPathFragments(options.path, options.name);
|
||||
const moduleBaseName = basename(modulePath);
|
||||
|
||||
const candidateSet = new Set<string>([options.path]);
|
||||
|
||||
const projectRootParent = dirname(projectRoot);
|
||||
for (let dir = modulePath; dir !== projectRootParent; dir = dirname(dir)) {
|
||||
candidateSet.add(dir);
|
||||
}
|
||||
for (let dir = componentPath; dir !== projectRoot; dir = dirname(dir)) {
|
||||
candidateSet.add(dir);
|
||||
}
|
||||
|
||||
const candidatesDirs = [...candidateSet].sort(
|
||||
(a, b) => b.length - a.length
|
||||
);
|
||||
for (const c of candidatesDirs) {
|
||||
const candidateFiles = [
|
||||
'',
|
||||
`${moduleBaseName}.ts`,
|
||||
`${moduleBaseName}${moduleExt}`,
|
||||
].map((x) => joinPathFragments(c, x));
|
||||
|
||||
for (const sc of candidateFiles) {
|
||||
if (tree.isFile(sc)) {
|
||||
return normalizePath(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function findModule(
|
||||
tree: Tree,
|
||||
generateDir: string,
|
||||
projectRoot: string
|
||||
): string | null {
|
||||
let dir = generateDir;
|
||||
const projectRootParent = dirname(projectRoot);
|
||||
|
||||
while (dir !== projectRootParent) {
|
||||
const allMatches = tree
|
||||
.children(dir)
|
||||
.map((path) => joinPathFragments(dir, path))
|
||||
.filter((path) => tree.isFile(path) && path.endsWith(moduleExt));
|
||||
const filteredMatches = allMatches.filter(
|
||||
(path) => !path.endsWith(routingModuleExt)
|
||||
);
|
||||
|
||||
if (filteredMatches.length == 1) {
|
||||
return filteredMatches[0];
|
||||
} else if (filteredMatches.length > 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
dir = dirname(dir);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import {
|
||||
createProjectGraphAsync,
|
||||
joinPathFragments,
|
||||
readProjectConfiguration,
|
||||
readWorkspaceConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import type { NormalizedSchema, Schema } from '../schema';
|
||||
import {
|
||||
createProjectRootMappings,
|
||||
findProjectForPath,
|
||||
} from 'nx/src/project-graph/utils/find-project-for-path';
|
||||
|
||||
async function findProjectFromOptions(options: Schema) {
|
||||
const projectGraph = await createProjectGraphAsync();
|
||||
const projectRootMappings = createProjectRootMappings(projectGraph.nodes);
|
||||
|
||||
// path can be undefined when running on the root of the workspace, we default to the root
|
||||
// to handle standalone layouts
|
||||
return findProjectForPath(options.path || '', projectRootMappings);
|
||||
}
|
||||
|
||||
export async function normalizeOptions(
|
||||
tree: Tree,
|
||||
options: Schema
|
||||
): Promise<NormalizedSchema> {
|
||||
const project =
|
||||
options.project ??
|
||||
(await findProjectFromOptions(options)) ??
|
||||
readWorkspaceConfiguration(tree).defaultProject;
|
||||
|
||||
if (!project) {
|
||||
// path is hidden, so if not provided we don't suggest setting it
|
||||
if (!options.path) {
|
||||
throw new Error(
|
||||
'No "project" was specified and "defaultProject" is not set in the workspace configuration. Please provide the "project" option and try again.'
|
||||
);
|
||||
}
|
||||
|
||||
// path was provided, so it's wrong and we should mention it
|
||||
throw new Error(
|
||||
'The provided "path" is wrong and no "project" was specified and "defaultProject" is not set in the workspace configuration. ' +
|
||||
'Please provide a correct "path" or provide the "project" option instead and try again.'
|
||||
);
|
||||
}
|
||||
|
||||
const { projectType, root, sourceRoot } = readProjectConfiguration(
|
||||
tree,
|
||||
project
|
||||
);
|
||||
const projectSourceRoot = sourceRoot ?? joinPathFragments(root, 'src');
|
||||
const path =
|
||||
options.path ??
|
||||
joinPathFragments(
|
||||
projectSourceRoot,
|
||||
projectType === 'application' ? 'app' : 'lib'
|
||||
);
|
||||
|
||||
return {
|
||||
...options,
|
||||
path,
|
||||
project,
|
||||
projectSourceRoot,
|
||||
};
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
export interface Schema {
|
||||
name: string;
|
||||
path?: string;
|
||||
project?: string;
|
||||
displayBlock?: boolean;
|
||||
inlineStyle?: boolean;
|
||||
inlineTemplate?: boolean;
|
||||
standalone?: boolean;
|
||||
viewEncapsulation?: 'Emulated' | 'None' | 'ShadowDom';
|
||||
changeDetection?: 'Default' | 'OnPush';
|
||||
style?: 'css' | 'scss' | 'sass' | 'less' | 'none';
|
||||
skipTests?: boolean;
|
||||
type?: string;
|
||||
flat?: boolean;
|
||||
skipImport?: boolean;
|
||||
selector?: string;
|
||||
module?: string;
|
||||
skipSelector?: boolean;
|
||||
export?: boolean;
|
||||
}
|
||||
|
||||
export interface NormalizedSchema extends Schema {
|
||||
path: string;
|
||||
project: string;
|
||||
projectSourceRoot: string;
|
||||
}
|
||||
@ -10,20 +10,8 @@ import { pathStartsWith } from '../utils/path';
|
||||
import { exportComponentInEntryPoint } from './lib/component';
|
||||
import { normalizeOptions } from './lib/normalize-options';
|
||||
import type { NormalizedSchema, Schema } from './schema';
|
||||
import { getGeneratorDirectoryForInstalledAngularVersion } from '../../utils/get-generator-directory-for-ng-version';
|
||||
import { join } from 'path';
|
||||
|
||||
export async function componentGenerator(tree: Tree, rawOptions: Schema) {
|
||||
const generatorDirectory =
|
||||
getGeneratorDirectoryForInstalledAngularVersion(tree);
|
||||
if (generatorDirectory) {
|
||||
let previousGenerator = await import(
|
||||
join(__dirname, generatorDirectory, 'component')
|
||||
);
|
||||
await previousGenerator.default(tree, rawOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
const options = await normalizeOptions(tree, rawOptions);
|
||||
const { projectSourceRoot, ...schematicOptions } = options;
|
||||
|
||||
|
||||
@ -1,799 +0,0 @@
|
||||
import { addProjectConfiguration, updateJson, writeJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import componentGenerator from './component';
|
||||
|
||||
describe('component Generator', () => {
|
||||
describe('support angular 14', () => {
|
||||
it('should create the component correctly and export it in the entry point when "export=true"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should create the component correctly and export it in the entry point when is standalone and "export=true"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', '');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
standalone: true,
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toMatchInlineSnapshot(
|
||||
`"export * from \\"./lib/example/example.component\\";"`
|
||||
);
|
||||
});
|
||||
|
||||
it('should create the component correctly and not export it in the entry point when "export=false"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
export: false,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).not.toContain(
|
||||
`export * from "./lib/example/example.component";`
|
||||
);
|
||||
});
|
||||
|
||||
it('should create the component correctly and not export it in the entry point when is standalone and "export=false"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
standalone: true,
|
||||
export: false,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).not.toContain(
|
||||
`export * from "./lib/example/example.component";`
|
||||
);
|
||||
});
|
||||
|
||||
it('should create the component correctly and not export it when "--skip-import=true"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', 'export * from "./lib/lib.module";');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
skipImport: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).not.toContain(
|
||||
`export * from "./lib/example/example.component";`
|
||||
);
|
||||
});
|
||||
|
||||
it('should create the component correctly but not export it in the entry point when it does not exist', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexExists = tree.exists('libs/lib1/src/index.ts');
|
||||
expect(indexExists).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not export the component in the entry point when the module it belongs to is not exported', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write('libs/lib1/src/index.ts', '');
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toBe('');
|
||||
});
|
||||
|
||||
describe('--flat', () => {
|
||||
it('should create the component correctly and export it in the entry point', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
flat: true,
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toContain(
|
||||
`export * from "./lib/example.component";`
|
||||
);
|
||||
});
|
||||
|
||||
it('should create the component correctly and not export it when "export=false"', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
flat: true,
|
||||
export: false,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).not.toContain(
|
||||
`export * from "./lib/example.component";`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('--path', () => {
|
||||
it('should create the component correctly and export it in the entry point', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
path: 'libs/lib1/src/lib/mycomp',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/src/lib/mycomp/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toContain(
|
||||
`export * from "./lib/mycomp/example/example.component";`
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw if the path specified is not under the project root', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT & ASSERT
|
||||
await expect(
|
||||
componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
path: 'apps/app1/src/mycomp',
|
||||
export: false,
|
||||
})
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('--module', () => {
|
||||
it.each([
|
||||
'./lib.module.ts',
|
||||
'lib.module.ts',
|
||||
'./lib.module',
|
||||
'lib.module',
|
||||
'./lib',
|
||||
'lib',
|
||||
])(
|
||||
'should export it in the entry point when "--module" is set to "%s"',
|
||||
async (module) => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
module,
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toContain(
|
||||
`export * from "./lib/example/example.component";`
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
it('should not export it in the entry point when the module it belong to is not exported', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/not-exported.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class NotExportedModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
module: 'not-exported',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const indexSource = tree.read('libs/lib1/src/index.ts', 'utf-8');
|
||||
expect(indexSource).toMatchInlineSnapshot(
|
||||
`"export * from \\"./lib/lib.module\\";"`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('secondary entry points', () => {
|
||||
it('should create the component correctly and export it in the entry point', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// secondary entry point
|
||||
writeJson(tree, 'libs/lib1/secondary/ng-package.json', {
|
||||
lib: { entryFile: './src/index.ts' },
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/secondary/src/index.ts',
|
||||
'export * from "./lib/secondary.module";'
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/secondary/src/lib/secondary.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class SecondaryModule {}`
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
path: 'libs/lib1/secondary/src/lib',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const componentSource = tree.read(
|
||||
'libs/lib1/secondary/src/lib/example/example.component.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(componentSource).toMatchSnapshot();
|
||||
|
||||
const secondaryIndexSource = tree.read(
|
||||
'libs/lib1/secondary/src/index.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(secondaryIndexSource).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should not export the component in the entry point when the module it belongs to is not exported', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||
updateJson(tree, 'package.json', (json) => ({
|
||||
...json,
|
||||
dependencies: {
|
||||
...json.dependencies,
|
||||
'@angular/core': '14.1.0',
|
||||
},
|
||||
}));
|
||||
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
projectType: 'library',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
root: 'libs/lib1',
|
||||
});
|
||||
tree.write(
|
||||
'libs/lib1/src/lib/lib.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class LibModule {}`
|
||||
);
|
||||
tree.write(
|
||||
'libs/lib1/src/index.ts',
|
||||
'export * from "./lib/lib.module";'
|
||||
);
|
||||
|
||||
// secondary entry point
|
||||
writeJson(tree, 'libs/lib1/secondary/ng-package.json', {
|
||||
lib: { entryFile: './src/index.ts' },
|
||||
});
|
||||
tree.write('libs/lib1/secondary/src/index.ts', '');
|
||||
tree.write(
|
||||
'libs/lib1/secondary/src/lib/secondary.module.ts',
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: []
|
||||
})
|
||||
export class SecondaryModule {}`
|
||||
);
|
||||
|
||||
// ACT
|
||||
await componentGenerator(tree, {
|
||||
name: 'example',
|
||||
project: 'lib1',
|
||||
export: true,
|
||||
});
|
||||
|
||||
// ASSERT
|
||||
const indexSource = tree.read(
|
||||
'libs/lib1/secondary/src/index.ts',
|
||||
'utf-8'
|
||||
);
|
||||
expect(indexSource).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,18 +0,0 @@
|
||||
const { createGlobPatternsForDependencies } = require('@nrwl/angular/tailwind');
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
mode: 'jit',
|
||||
purge: [
|
||||
join(__dirname, '<%= relativeSourceRoot %>/**/!(*.stories|*.spec).{ts,html}'),
|
||||
...createGlobPatternsForDependencies(__dirname),
|
||||
],
|
||||
darkMode: false, // or 'media' or 'class'
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
const { createGlobPatternsForDependencies } = require('@nrwl/angular/tailwind');
|
||||
const { join } = require('path');
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
join(__dirname, '<%= relativeSourceRoot %>/**/!(*.stories|*.spec).{ts,html}'),
|
||||
...createGlobPatternsForDependencies(__dirname),
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@ -1,56 +0,0 @@
|
||||
import {
|
||||
joinPathFragments,
|
||||
ProjectConfiguration,
|
||||
stripIndents,
|
||||
Tree,
|
||||
updateProjectConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import { NormalizedGeneratorOptions } from '../schema';
|
||||
|
||||
export function addTailwindConfigPathToProject(
|
||||
tree: Tree,
|
||||
options: NormalizedGeneratorOptions,
|
||||
project: ProjectConfiguration
|
||||
): void {
|
||||
const buildTarget = project.targets?.[options.buildTarget];
|
||||
|
||||
if (!buildTarget) {
|
||||
throw new Error(
|
||||
stripIndents`The target "${options.buildTarget}" was not found for project "${options.project}".
|
||||
If you are using a different build target, please provide it using the "--buildTarget" option.
|
||||
If the project is not a buildable or publishable library, you don't need to setup TailwindCSS for it.`
|
||||
);
|
||||
}
|
||||
|
||||
const supportedLibraryExecutors = [
|
||||
'@nrwl/angular:ng-packagr-lite',
|
||||
'@nrwl/angular:package',
|
||||
];
|
||||
if (!supportedLibraryExecutors.includes(buildTarget.executor)) {
|
||||
throw new Error(
|
||||
stripIndents`The build target for project "${
|
||||
options.project
|
||||
}" is using an unsupported executor "${buildTarget.executor}".
|
||||
Supported executors are ${supportedLibraryExecutors
|
||||
.map((e) => `"${e}"`)
|
||||
.join(', ')}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
buildTarget.options?.tailwindConfig &&
|
||||
tree.exists(buildTarget.options.tailwindConfig)
|
||||
) {
|
||||
throw new Error(
|
||||
stripIndents`The "${buildTarget.options.tailwindConfig}" file is already configured for the project "${options.project}". Are you sure this is the right project to set up Tailwind?
|
||||
If you are sure, you can remove the configuration and re-run the generator.`
|
||||
);
|
||||
}
|
||||
|
||||
buildTarget.options = {
|
||||
...buildTarget.options,
|
||||
tailwindConfig: joinPathFragments(project.root, 'tailwind.config.js'),
|
||||
};
|
||||
|
||||
updateProjectConfiguration(tree, options.project, project);
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import {
|
||||
generateFiles,
|
||||
joinPathFragments,
|
||||
ProjectConfiguration,
|
||||
stripIndents,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { relative } from 'path';
|
||||
import { GeneratorOptions } from '../schema';
|
||||
|
||||
export function addTailwindConfig(
|
||||
tree: Tree,
|
||||
options: GeneratorOptions,
|
||||
project: ProjectConfiguration,
|
||||
tailwindVersion: '2' | '3'
|
||||
): void {
|
||||
if (tree.exists(joinPathFragments(project.root, 'tailwind.config.js'))) {
|
||||
throw new Error(
|
||||
stripIndents`The "tailwind.config.js" file already exists in the project "${options.project}". Are you sure this is the right project to set up Tailwind?
|
||||
If you are sure, you can remove the existing file and re-run the generator.`
|
||||
);
|
||||
}
|
||||
|
||||
const filesDir = tailwindVersion === '3' ? 'files/v3' : 'files/v2';
|
||||
|
||||
generateFiles(
|
||||
tree,
|
||||
joinPathFragments(__dirname, '..', filesDir),
|
||||
project.root,
|
||||
{
|
||||
relativeSourceRoot: relative(project.root, project.sourceRoot),
|
||||
tmpl: '',
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
GeneratorCallback,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { versions } from '../../../../utils/versions';
|
||||
|
||||
export function addTailwindRequiredPackages(tree: Tree): GeneratorCallback {
|
||||
return addDependenciesToPackageJson(
|
||||
tree,
|
||||
{},
|
||||
{
|
||||
autoprefixer: versions.angularV14.autoprefixerVersion,
|
||||
postcss: versions.angularV14.postcssVersion,
|
||||
tailwindcss: versions.angularV14.tailwindVersion,
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { checkAndCleanWithSemver } from '@nrwl/workspace/src/utilities/version-utils';
|
||||
import { lt } from 'semver';
|
||||
|
||||
export function detectTailwindInstalledVersion(
|
||||
tree: Tree
|
||||
): '2' | '3' | undefined {
|
||||
const { dependencies, devDependencies } = readJson(tree, 'package.json');
|
||||
const tailwindVersion =
|
||||
dependencies?.tailwindcss ?? devDependencies?.tailwindcss;
|
||||
|
||||
if (!tailwindVersion) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const version = checkAndCleanWithSemver('tailwindcss', tailwindVersion);
|
||||
if (lt(version, '2.0.0')) {
|
||||
throw new Error(
|
||||
`The Tailwind CSS version "${tailwindVersion}" is not supported. Please upgrade to v2.0.0 or higher.`
|
||||
);
|
||||
}
|
||||
|
||||
return lt(version, '3.0.0') ? '2' : '3';
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
export * from './add-tailwind-config-path-to-project';
|
||||
export * from './add-tailwind-config';
|
||||
export * from './add-tailwind-required-packages';
|
||||
export * from './detect-tailwind-installed-version';
|
||||
export * from './normalize-options';
|
||||
export * from './update-application-styles';
|
||||
@ -1,10 +0,0 @@
|
||||
import type { GeneratorOptions, NormalizedGeneratorOptions } from '../schema';
|
||||
|
||||
export function normalizeOptions(
|
||||
options: GeneratorOptions
|
||||
): NormalizedGeneratorOptions {
|
||||
return {
|
||||
...options,
|
||||
buildTarget: options.buildTarget || 'build',
|
||||
};
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
import {
|
||||
joinPathFragments,
|
||||
ProjectConfiguration,
|
||||
stripIndents,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { NormalizedGeneratorOptions } from '../schema';
|
||||
|
||||
export function updateApplicationStyles(
|
||||
tree: Tree,
|
||||
options: NormalizedGeneratorOptions,
|
||||
project: ProjectConfiguration
|
||||
): void {
|
||||
let stylesEntryPoint = options.stylesEntryPoint;
|
||||
|
||||
if (stylesEntryPoint && !tree.exists(stylesEntryPoint)) {
|
||||
throw new Error(
|
||||
`The provided styles entry point "${stylesEntryPoint}" could not be found.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!stylesEntryPoint) {
|
||||
stylesEntryPoint = findStylesEntryPoint(tree, options, project);
|
||||
|
||||
if (!stylesEntryPoint) {
|
||||
throw new Error(
|
||||
stripIndents`Could not find a styles entry point for project "${options.project}".
|
||||
Please specify a styles entry point using the "--stylesEntryPoint" option.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const stylesEntryPointContent = tree.read(stylesEntryPoint, 'utf-8');
|
||||
tree.write(
|
||||
stylesEntryPoint,
|
||||
stripIndents`@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
${stylesEntryPointContent}`
|
||||
);
|
||||
}
|
||||
|
||||
function findStylesEntryPoint(
|
||||
tree: Tree,
|
||||
options: NormalizedGeneratorOptions,
|
||||
project: ProjectConfiguration
|
||||
): string | undefined {
|
||||
// first check for common names
|
||||
const possibleStylesEntryPoints = [
|
||||
joinPathFragments(project.sourceRoot ?? project.root, 'styles.css'),
|
||||
joinPathFragments(project.sourceRoot ?? project.root, 'styles.scss'),
|
||||
joinPathFragments(project.sourceRoot ?? project.root, 'styles.sass'),
|
||||
joinPathFragments(project.sourceRoot ?? project.root, 'styles.less'),
|
||||
];
|
||||
|
||||
let stylesEntryPoint = possibleStylesEntryPoints.find((s) => tree.exists(s));
|
||||
if (stylesEntryPoint) {
|
||||
return stylesEntryPoint;
|
||||
}
|
||||
|
||||
// then check for the specified styles in the build configuration if it exists
|
||||
const styles: Array<string | { input: string; inject: boolean }> =
|
||||
project.targets?.[options.buildTarget].options?.styles;
|
||||
|
||||
if (!styles) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// find the first style that belongs to the project source
|
||||
const style = styles.find((s) =>
|
||||
typeof s === 'string'
|
||||
? s.startsWith(project.root) && tree.exists(s)
|
||||
: s.input.startsWith(project.root) &&
|
||||
s.inject !== false &&
|
||||
tree.exists(s.input)
|
||||
);
|
||||
|
||||
if (!style) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return typeof style === 'string' ? style : style.input;
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
export interface GeneratorOptions {
|
||||
project: string;
|
||||
buildTarget?: string;
|
||||
skipFormat?: boolean;
|
||||
stylesEntryPoint?: string;
|
||||
skipPackageJson?: boolean;
|
||||
}
|
||||
|
||||
export interface NormalizedGeneratorOptions extends GeneratorOptions {
|
||||
buildTarget: string;
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
import {
|
||||
formatFiles,
|
||||
GeneratorCallback,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
addTailwindConfig,
|
||||
addTailwindConfigPathToProject,
|
||||
addTailwindRequiredPackages,
|
||||
detectTailwindInstalledVersion,
|
||||
normalizeOptions,
|
||||
updateApplicationStyles,
|
||||
} from './lib';
|
||||
import { GeneratorOptions } from './schema';
|
||||
|
||||
export async function setupTailwindGenerator(
|
||||
tree: Tree,
|
||||
rawOptions: GeneratorOptions
|
||||
): Promise<GeneratorCallback> {
|
||||
const options = normalizeOptions(rawOptions);
|
||||
const project = readProjectConfiguration(tree, options.project);
|
||||
|
||||
const tailwindInstalledVersion = detectTailwindInstalledVersion(tree);
|
||||
|
||||
let installTask: GeneratorCallback = () => {};
|
||||
if (!options.skipPackageJson) {
|
||||
if (tailwindInstalledVersion === undefined) {
|
||||
installTask = addTailwindRequiredPackages(tree);
|
||||
}
|
||||
}
|
||||
|
||||
addTailwindConfig(tree, options, project, tailwindInstalledVersion ?? '3');
|
||||
|
||||
if (project.projectType === 'application') {
|
||||
updateApplicationStyles(tree, options, project);
|
||||
} else if (project.projectType === 'library') {
|
||||
addTailwindConfigPathToProject(tree, options, project);
|
||||
}
|
||||
|
||||
if (!options.skipFormat) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
return installTask;
|
||||
}
|
||||
|
||||
export default setupTailwindGenerator;
|
||||
@ -13,23 +13,11 @@ import {
|
||||
updateApplicationStyles,
|
||||
} from './lib';
|
||||
import { GeneratorOptions } from './schema';
|
||||
import { getGeneratorDirectoryForInstalledAngularVersion } from '../../utils/get-generator-directory-for-ng-version';
|
||||
import { join } from 'path';
|
||||
|
||||
export async function setupTailwindGenerator(
|
||||
tree: Tree,
|
||||
rawOptions: GeneratorOptions
|
||||
): Promise<GeneratorCallback> {
|
||||
const generatorDirectory =
|
||||
getGeneratorDirectoryForInstalledAngularVersion(tree);
|
||||
if (generatorDirectory) {
|
||||
let previousGenerator = await import(
|
||||
join(__dirname, generatorDirectory, 'setup-tailwind')
|
||||
);
|
||||
await previousGenerator.default(tree, rawOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
const options = normalizeOptions(rawOptions);
|
||||
const project = readProjectConfiguration(tree, options.project);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user