Skip to content

Commit

Permalink
fix(react): require importPath for publishable libs & adjust buildable
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #2794
  • Loading branch information
juristr committed Jul 21, 2020
1 parent 77378a0 commit 5abbe89
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 22 deletions.
12 changes: 9 additions & 3 deletions docs/angular/api-react/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ Type: `string`

The application project to add the library route to.

### buildable

Default: `false`

Type: `boolean`

Generate a buildable library.

### component

Default: `true`
Expand Down Expand Up @@ -108,11 +116,9 @@ Use pascal case component file name (e.g. App.tsx).

### publishable

Alias(es): buildable

Type: `boolean`

Create a buildable library.
Create a publishable library.

### routing

Expand Down
18 changes: 15 additions & 3 deletions docs/react/api-react/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ Type: `string`

The application project to add the library route to.

### buildable

Default: `false`

Type: `boolean`

Generate a buildable library.

### component

Default: `true`
Expand All @@ -66,6 +74,12 @@ Type: `string`

A directory where the lib is placed.

### importPath

Type: `string`

The library name used to import it, like @myorg/my-awesome-lib

### js

Default: `false`
Expand Down Expand Up @@ -102,11 +116,9 @@ Use pascal case component file name (e.g. App.tsx).

### publishable

Alias(es): buildable

Type: `boolean`

Create a buildable library.
Create a publishable library.

### routing

Expand Down
6 changes: 3 additions & 3 deletions e2e/react/src/react-package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ forEachCli('nx', (cli) => {
runCLI(`generate @nrwl/react:app ${app}`);

runCLI(
`generate @nrwl/react:library ${parentLib} --buildable --no-interactive`
`generate @nrwl/react:library ${parentLib} --publishable --importPath=@proj/${parentLib} --no-interactive`
);
runCLI(
`generate @nrwl/react:library ${childLib} --buildable --no-interactive`
`generate @nrwl/react:library ${childLib} --publishable --importPath=@proj/${childLib} --no-interactive`
);
runCLI(
`generate @nrwl/react:library ${childLib2} --buildable --no-interactive`
`generate @nrwl/react:library ${childLib2} --publishable --importPath=@proj/${childLib2} --no-interactive`
);

// create dependencies by importing
Expand Down
4 changes: 2 additions & 2 deletions e2e/react/src/react.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ forEachCli('nx', () => {
const libName = uniq('lib');

runCLI(
`generate @nrwl/react:lib ${libName} --publishable --no-interactive`
`generate @nrwl/react:lib ${libName} --publishable --importPath=@proj/${libName} --no-interactive`
);

const libTestResults = await runCLIAsync(
Expand Down Expand Up @@ -113,7 +113,7 @@ forEachCli('nx', () => {
const libName = uniq('lib');

runCLI(
`generate @nrwl/react:lib ${libName} --publishable --no-interactive`
`generate @nrwl/react:lib ${libName} --publishable --importPath=@proj/${libName} --no-interactive`
);

const mainPath = `libs/${libName}/src/lib/${libName}.tsx`;
Expand Down
95 changes: 95 additions & 0 deletions packages/react/src/schematics/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,31 @@ describe('lib', () => {
});
});

describe('--buildable', () => {
it('should have a builder defined', async () => {
const tree = await runSchematic(
'lib',
{
name: 'myLib',
buildable: true,
},
appTree
);

const workspaceJson = readJsonInTree(tree, '/workspace.json');

expect(workspaceJson.projects['my-lib'].architect.build).toBeDefined();
});
});

describe('--publishable', () => {
it('should add build architect', async () => {
const tree = await runSchematic(
'lib',
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
},
appTree
);
Expand All @@ -384,12 +402,29 @@ describe('lib', () => {
});
});

it('should fail if no importPath is provided with publishable', async () => {
expect.assertions(1);

try {
const tree = await runSchematic(
'lib',
{ name: 'myLib', directory: 'myDir', publishable: true },
appTree
);
} catch (e) {
expect(e.message).toContain(
'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)'
);
}
});

it('should support styled-components', async () => {
const tree = await runSchematic(
'lib',
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
style: 'styled-components',
},
appTree
Expand All @@ -410,6 +445,7 @@ describe('lib', () => {
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
style: '@emotion/styled',
},
appTree
Expand All @@ -430,6 +466,7 @@ describe('lib', () => {
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
style: 'styled-jsx',
},
appTree
Expand All @@ -450,6 +487,7 @@ describe('lib', () => {
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
style: 'none',
},
appTree
Expand All @@ -470,6 +508,7 @@ describe('lib', () => {
{
name: 'myLib',
publishable: true,
importPath: '@proj/my-lib',
},
appTree
);
Expand All @@ -494,4 +533,60 @@ describe('lib', () => {
expect(tree.exists('/libs/my-lib/src/index.js')).toBe(true);
});
});

describe('--importPath', () => {
it('should update the package.json & tsconfig with the given import path', async () => {
const tree = await runSchematic(
'lib',
{
name: 'myLib',
publishable: true,
directory: 'myDir',
importPath: '@myorg/lib',
},
appTree
);
const packageJson = readJsonInTree(
tree,
'libs/my-dir/my-lib/package.json'
);
const tsconfigJson = readJsonInTree(tree, '/tsconfig.base.json');

expect(packageJson.name).toBe('@myorg/lib');
expect(
tsconfigJson.compilerOptions.paths[packageJson.name]
).toBeDefined();
});

it('should fail if the same importPath has already been used', async () => {
const tree1 = await runSchematic(
'lib',
{
name: 'myLib1',
publishable: true,
importPath: '@myorg/lib',
},
appTree
);

try {
await runSchematic(
'lib',
{
name: 'myLib2',
framework: 'angular',
publishable: true,
importPath: '@myorg/lib',
},
tree1
);
} catch (e) {
expect(e.message).toContain(
'You already have a library using the import path'
);
}

expect.assertions(1);
});
});
});
35 changes: 26 additions & 9 deletions packages/react/src/schematics/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
noop,
Rule,
SchematicContext,
SchematicsException,
template,
Tree,
url,
Expand Down Expand Up @@ -66,6 +67,12 @@ export default function (schema: Schema): Rule {
return (host: Tree, context: SchematicContext) => {
const options = normalizeOptions(host, schema);

if (options.publishable === true && !schema.importPath) {
throw new SchematicsException(
`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)`
);
}

if (!options.component) {
options.style = 'none';
}
Expand Down Expand Up @@ -125,7 +132,7 @@ function addProject(options: NormalizedSchema): Rule {
options.linter
);

if (options.publishable) {
if (options.publishable || options.buildable) {
const external = ['react', 'react-dom'];
// Also exclude CSS-in-JS packages from build
if (
Expand Down Expand Up @@ -179,12 +186,20 @@ function updateTsConfig(options: NormalizedSchema): Rule {
const c = json.compilerOptions;
c.paths = c.paths || {};
delete c.paths[options.name];
c.paths[`@${nxJson.npmScope}/${options.projectDirectory}`] = [

if (c.paths[options.importPath]) {
throw new SchematicsException(
`You already have a library using the import path "${options.importPath}". Make sure to specify a unique one.`
);
}

c.paths[options.importPath] = [
maybeJs(
options,
`${libsDir(host)}/${options.projectDirectory}/src/index.ts`
),
];

return json;
})(host, context);
},
Expand All @@ -201,7 +216,7 @@ function createFiles(options: NormalizedSchema): Rule {
offsetFromRoot: offsetFromRoot(options.projectRoot),
}),
move(options.projectRoot),
options.publishable
options.publishable || options.buildable
? noop()
: filter((file) => !file.endsWith('package.json')),
options.js ? toJS() : noop(),
Expand Down Expand Up @@ -324,6 +339,9 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
? options.tags.split(',').map((s) => s.trim())
: [];

const importPath =
options.importPath || `@${getNpmScope(host)}/${projectDirectory}`;

const normalized: NormalizedSchema = {
...options,
fileName,
Expand All @@ -332,6 +350,7 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
projectRoot,
projectDirectory,
parsedTags,
importPath,
};

if (options.appProject) {
Expand Down Expand Up @@ -359,12 +378,10 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
}

function updateLibPackageNpmScope(options: NormalizedSchema): Rule {
return (host: Tree) => {
return updateJsonInTree(`${options.projectRoot}/package.json`, (json) => {
json.name = `@${getNpmScope(host)}/${options.name}`;
return json;
});
};
return updateJsonInTree(`${options.projectRoot}/package.json`, (json) => {
json.name = options.importPath;
return json;
});
}

function maybeJs(options: NormalizedSchema, path: string): string {
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/schematics/library/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ export interface Schema {
linter: Linter;
component?: boolean;
publishable?: boolean;
buildable?: boolean;
importPath?: string;
js?: boolean;
}
12 changes: 10 additions & 2 deletions packages/react/src/schematics/library/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,16 @@
},
"publishable": {
"type": "boolean",
"description": "Create a buildable library.",
"alias": "buildable"
"description": "Create a publishable library."
},
"buildable": {
"type": "boolean",
"default": false,
"description": "Generate a buildable library."
},
"importPath": {
"type": "string",
"description": "The library name used to import it, like @myorg/my-awesome-lib"
},
"component": {
"type": "boolean",
Expand Down

0 comments on commit 5abbe89

Please sign in to comment.