Skip to content

Commit

Permalink
fix(frontend): fix react component for apps
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz authored and vsavkin committed May 27, 2019
1 parent c3fc1fd commit 2958f50
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 75 deletions.
3 changes: 2 additions & 1 deletion packages/react/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"component": {
"factory": "./src/schematics/component/component",
"schema": "./src/schematics/component/schema.json",
"description": "Create a component"
"description": "Create a component",
"aliases": "c"
}
}
}
58 changes: 30 additions & 28 deletions packages/react/src/schematics/component/component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Tree } from '@angular-devkit/schematics';
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
import { runSchematic } from '../../utils/testing';
import { names } from '@nrwl/workspace/src/utils/name-utils';
import { runSchematic, createApp, createLib } from '../../utils/testing';
import { readJsonInTree } from '@nrwl/workspace/src/utils/ast-utils';

describe('component', () => {
let appTree: Tree;
let projectName: string;

beforeEach(() => {
beforeEach(async () => {
projectName = 'my-lib';
appTree = Tree.empty();
appTree = createEmptyWorkspace(appTree);
appTree = createLib(appTree, projectName);
appTree = await createApp(appTree, 'my-app');
appTree = await createLib(appTree, projectName);
});

it('should generate files', async () => {
Expand All @@ -29,6 +29,20 @@ describe('component', () => {
expect(tree.exists('libs/my-lib/src/lib/hello/hello.css')).toBeTruthy();
});

it('should generate files for an app', async () => {
const tree = await runSchematic(
'component',
{ name: 'hello', project: 'my-app' },
appTree
);

expect(tree.exists('apps/my-app/src/app/hello/hello.tsx')).toBeTruthy();
expect(
tree.exists('apps/my-app/src/app/hello/hello.spec.tsx')
).toBeTruthy();
expect(tree.exists('apps/my-app/src/app/hello/hello.css')).toBeTruthy();
});

describe('--export', () => {
it('should add to index.ts barrel', async () => {
const tree = await runSchematic(
Expand All @@ -41,6 +55,18 @@ describe('component', () => {

expect(indexContent).toMatch(/lib\/hello\/hello/);
});

it('should not export from an app', async () => {
const tree = await runSchematic(
'component',
{ name: 'hello', project: 'my-app', export: true },
appTree
);

const indexContent = tree.read('libs/my-lib/src/index.ts').toString();

expect(indexContent).not.toMatch(/lib\/hello\/hello/);
});
});

describe('--pascalCaseFiles', () => {
Expand Down Expand Up @@ -123,27 +149,3 @@ describe('component', () => {
});
});
});

export function createLib(tree: Tree, libName: string): Tree {
const { fileName } = names(libName);

tree.create(`/libs/${fileName}/src/index.ts`, `\n`);

tree.overwrite(
'/angular.json',
`
{
"projects": {
"${libName}": {
"root": "libs/${fileName}",
"sourceRoot": "libs/${fileName}/src",
"projectType": "library",
"schematics": {}
}
}
}
`
);

return tree;
}
116 changes: 70 additions & 46 deletions packages/react/src/schematics/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import {
move,
noop,
Rule,
SchematicContext,
template,
Tree,
url
} from '@angular-devkit/schematics';
import { Schema } from './schema';
import { names } from '@nrwl/workspace';
import { getWorkspace, names, formatFiles } from '@nrwl/workspace';
import {
addDepsToPackageJson,
addGlobal,
getProjectConfig,
insert
} from '@nrwl/workspace/src/utils/ast-utils';
import { CSS_IN_JS_DEPENDENCIES } from '../../utils/styled';
import { formatFiles } from '@nrwl/workspace';

interface NormalizedSchema extends Schema {
projectSourceRoot: Path;
Expand All @@ -31,8 +31,8 @@ interface NormalizedSchema extends Schema {
}

export default function(schema: Schema): Rule {
return (host: Tree) => {
const options = normalizeOptions(host, schema);
return (host: Tree, context: SchematicContext) => {
const options = normalizeOptions(host, schema, context);
return chain([
createComponentFiles(options),
addStyledModuleDependencies(options),
Expand All @@ -43,19 +43,29 @@ export default function(schema: Schema): Rule {
}

function createComponentFiles(options: NormalizedSchema): Rule {
return mergeWith(
apply(url(`./files`), [
template({
...options,
tmpl: ''
}),
options.skipTests ? filter(file => !/.*spec.tsx/.test(file)) : noop(),
options.styledModule
? filter(file => !file.endsWith(`.${options.style}`))
: noop(),
move(join(options.projectSourceRoot, 'lib'))
])
);
return async (host: Tree, context: SchematicContext) => {
const workspace = await getWorkspace(host);
const directory = join(
options.projectSourceRoot,
workspace.projects.get(options.project).extensions.projectType ===
'application'
? 'app'
: 'lib'
);
return mergeWith(
apply(url(`./files`), [
template({
...options,
tmpl: ''
}),
options.skipTests ? filter(file => !/.*spec.tsx/.test(file)) : noop(),
options.styledModule
? filter(file => !file.endsWith(`.${options.style}`))
: noop(),
move(directory)
])
);
};
}

function addStyledModuleDependencies(options: NormalizedSchema): Rule {
Expand All @@ -70,48 +80,62 @@ function addStyledModuleDependencies(options: NormalizedSchema): Rule {
}

function addExportsToBarrel(options: NormalizedSchema): Rule {
return options.export
? (host: Tree) => {
const indexFilePath = join(options.projectSourceRoot, 'index.ts');
const buffer = host.read(indexFilePath);

if (!!buffer) {
const indexSource = buffer!.toString('utf-8');
const indexSourceFile = ts.createSourceFile(
indexFilePath,
indexSource,
ts.ScriptTarget.Latest,
true
);
return async (host: Tree) => {
const workspace = await getWorkspace(host);
const isApp =
workspace.projects.get(options.project).extensions.type === 'application';
return options.export && !isApp
? (host: Tree) => {
const indexFilePath = join(options.projectSourceRoot, 'index.ts');
const buffer = host.read(indexFilePath);
if (!!buffer) {
const indexSource = buffer!.toString('utf-8');
const indexSourceFile = ts.createSourceFile(
indexFilePath,
indexSource,
ts.ScriptTarget.Latest,
true
);

insert(
host,
indexFilePath,
addGlobal(
indexSourceFile,
insert(
host,
indexFilePath,
`export { default as ${options.className}, ${
options.className
}Props } from './lib/${options.name}/${options.fileName}';`
)
);
}
addGlobal(
indexSourceFile,
indexFilePath,
`export { default as ${options.className}, ${
options.className
}Props } from './lib/${options.name}/${options.fileName}';`
)
);
}

return host;
}
: noop();
return host;
}
: noop();
};
}

function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
function normalizeOptions(
host: Tree,
options: Schema,
context: SchematicContext
): NormalizedSchema {
const { className, fileName } = names(options.name);

const componentFileName = options.pascalCaseFiles ? className : fileName;

const { sourceRoot: projectSourceRoot } = getProjectConfig(
const { sourceRoot: projectSourceRoot, projectType } = getProjectConfig(
host,
options.project
);

if (options.export && projectType === 'application') {
context.logger.warn(
`The "--export" option should not be used with applications and will do nothing.`
);
}

const styledModule = /^(css|scss|less|styl)$/.test(options.style)
? null
: options.style;
Expand Down
38 changes: 38 additions & 0 deletions packages/react/src/utils/testing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { join } from 'path';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { Rule, Tree } from '@angular-devkit/schematics';
import { names } from '@nrwl/workspace/src/utils/name-utils';
import { updateWorkspace } from '@nrwl/workspace/src/utils/workspace';

const testRunner = new SchematicTestRunner(
'@nrwl/react',
Expand All @@ -14,3 +16,39 @@ export function runSchematic(schematicName: string, options: any, tree: Tree) {
export function callRule(rule: Rule, tree: Tree) {
return testRunner.callRule(rule, tree).toPromise();
}

export function createApp(tree: Tree, appName: string): Promise<Tree> {
const { fileName } = names(appName);

return callRule(
updateWorkspace(workspace => {
workspace.projects.add({
name: fileName,
root: `apps/${fileName}`,
projectType: 'application',
sourceRoot: `apps/${fileName}/src`,
targets: {}
});
}),
tree
);
}

export function createLib(tree: Tree, libName: string): Promise<Tree> {
const { fileName } = names(libName);

tree.create(`/libs/${fileName}/src/index.ts`, `\n`);

return callRule(
updateWorkspace(workspace => {
workspace.projects.add({
name: fileName,
root: `libs/${fileName}`,
projectType: 'library',
sourceRoot: `libs/${fileName}/src`,
targets: {}
});
}),
tree
);
}

0 comments on commit 2958f50

Please sign in to comment.