Skip to content

Commit

Permalink
fix(node): 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 5abbe89 commit f3039db
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 36 deletions.
16 changes: 14 additions & 2 deletions docs/angular/api-node/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ nx g lib mylib --directory=myapp

## Options

### buildable

Default: `false`

Type: `boolean`

Generate a buildable library.

### directory

Alias(es): d
Expand All @@ -44,6 +52,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. Must be a valid npm name.

### linter

Default: `tslint`
Expand All @@ -62,8 +76,6 @@ Library name

### publishable

Alias(es): buildable

Type: `boolean`

Create a publishable library.
Expand Down
6 changes: 6 additions & 0 deletions docs/angular/api-workspace/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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

### linter

Default: `tslint`
Expand Down
16 changes: 14 additions & 2 deletions docs/react/api-node/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ nx g lib mylib --directory=myapp

## Options

### buildable

Default: `false`

Type: `boolean`

Generate a buildable library.

### directory

Alias(es): d
Expand All @@ -44,6 +52,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. Must be a valid npm name.

### linter

Default: `tslint`
Expand All @@ -62,8 +76,6 @@ Library name

### publishable

Alias(es): buildable

Type: `boolean`

Create a publishable library.
Expand Down
6 changes: 6 additions & 0 deletions docs/react/api-workspace/schematics/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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

### linter

Default: `tslint`
Expand Down
18 changes: 12 additions & 6 deletions e2e/node/src/node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,9 @@ forEachCli((currentCLIName) => {
ensureProject();

const nodeLib = uniq('nodelib');
runCLI(`generate @nrwl/node:lib ${nodeLib} --publishable`);
runCLI(
`generate @nrwl/node:lib ${nodeLib} --publishable --importPath=@proj/${nodeLib}`
);
checkFilesExist(`libs/${nodeLib}/package.json`);
const tslibConfig = readJson(`libs/${nodeLib}/tsconfig.lib.json`);
expect(tslibConfig).toEqual({
Expand Down Expand Up @@ -303,12 +305,16 @@ forEachCli((currentCLIName) => {
const nglib = uniq('nglib');

// Generating two libraries just to have a lot of files to copy
runCLI(`generate @nrwl/node:lib ${nodelib} --publishable`);
runCLI(
`generate @nrwl/node:lib ${nodelib} --publishable --importPath=@proj/${nodelib}`
);
/**
* The angular lib contains a lot sub directories that would fail without
* `nodir: true` in the package.impl.ts
*/
runCLI(`generate @nrwl/angular:lib ${nglib} --publishable`);
runCLI(
`generate @nrwl/angular:lib ${nglib} --publishable --importPath=@proj/${nglib}`
);
const workspace = readJson(workspaceConfigName());
workspace.projects[nodelib].architect.build.options.assets.push({
input: `./dist/libs/${nglib}`,
Expand Down Expand Up @@ -428,9 +434,9 @@ forEachCli((currentCLIName) => {
ensureProject();

runCLI(`generate @nrwl/express:app ${app}`);
runCLI(`generate @nrwl/node:lib ${parentLib} --publishable=true`);
runCLI(`generate @nrwl/node:lib ${childLib} --publishable=true`);
runCLI(`generate @nrwl/node:lib ${childLib2} --publishable=true`);
runCLI(`generate @nrwl/node:lib ${parentLib} --buildable=true`);
runCLI(`generate @nrwl/node:lib ${childLib} --buildable=true`);
runCLI(`generate @nrwl/node:lib ${childLib2} --buildable=true`);

// create dependencies by importing
const createDep = (parent, children: string[]) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "@<%= prefix %>/<%= name %>",
"name": "<%= importPath %>",
"version": "0.0.1"
}
105 changes: 104 additions & 1 deletion packages/node/src/schematics/library/library.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,26 @@ describe('lib', () => {
).toBeUndefined();
});

it('should throw an exception when not passing importPath when using --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 create a local tsconfig.json', async () => {
const tree = await runSchematic(
'lib',
Expand Down Expand Up @@ -236,11 +256,39 @@ describe('lib', () => {
});
});

describe('buildable package', () => {
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'].root).toEqual('libs/my-lib');

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

describe('publishable package', () => {
it('should have a builder defined', async () => {
const tree = await runSchematic(
'lib',
{ name: 'myLib', publishable: true, importPath: '@proj/mylib' },
appTree
);
const workspaceJson = readJsonInTree(tree, '/workspace.json');

expect(workspaceJson.projects['my-lib'].root).toEqual('libs/my-lib');

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

it('should update package.json', async () => {
const publishableTree = await runSchematic(
'lib',
{ name: 'mylib', publishable: true },
{ name: 'mylib', publishable: true, importPath: '@proj/mylib' },
appTree
);

Expand All @@ -252,4 +300,59 @@ describe('lib', () => {
expect(packageJsonContent.name).toEqual('@proj/mylib');
});
});

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',
publishable: true,
importPath: '@myorg/lib',
},
tree1
);
} catch (e) {
expect(e.message).toContain(
'You already have a library using the import path'
);
}

expect.assertions(1);
});
});
});
26 changes: 19 additions & 7 deletions packages/node/src/schematics/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import {
noop,
Rule,
SchematicContext,
SchematicsException,
template,
Tree,
url,
} from '@angular-devkit/schematics';
import {
formatFiles,
getNpmScope,
names,
offsetFromRoot,
toFileName,
updateWorkspaceInTree,
getNpmScope,
} from '@nrwl/workspace';
import { Schema } from './schema';
import { libsDir } from '@nrwl/workspace/src/utils/ast-utils';
Expand All @@ -38,8 +39,17 @@ export default function (schema: NormalizedSchema): 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)`
);
}

return chain([
externalSchematic('@nrwl/workspace', 'lib', schema),
externalSchematic('@nrwl/workspace', 'lib', {
...schema,
importPath: options.importPath,
}),
createFiles(options),
addProject(options),
formatFiles(options),
Expand All @@ -62,17 +72,19 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
? options.tags.split(',').map((s) => s.trim())
: [];

const normalized: NormalizedSchema = {
const importPath =
options.importPath || `@${defaultPrefix}/${projectDirectory}`;

return {
...options,
prefix: defaultPrefix, // we could also allow customizing this
fileName,
name: projectName,
projectRoot,
projectDirectory,
parsedTags,
importPath,
};

return normalized;
}

function createFiles(options: NormalizedSchema): Rule {
Expand All @@ -88,7 +100,7 @@ function createFiles(options: NormalizedSchema): Rule {
options.unitTestRunner === 'none'
? filter((file) => !file.endsWith('spec.ts'))
: noop(),
options.publishable
options.publishable || options.buildable
? noop()
: filter((file) => !file.endsWith('package.json')),
]),
Expand All @@ -97,7 +109,7 @@ function createFiles(options: NormalizedSchema): Rule {
}

function addProject(options: NormalizedSchema): Rule {
if (!options.publishable) {
if (!options.publishable && !options.buildable) {
return noop();
}

Expand Down
2 changes: 2 additions & 0 deletions packages/node/src/schematics/library/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export interface Schema {
tags?: string;
unitTestRunner: 'jest' | 'none';
linter: Linter;
buildable?: boolean;
publishable?: boolean;
importPath?: string;
testEnvironment: 'jsdom' | 'node';
}
12 changes: 10 additions & 2 deletions packages/node/src/schematics/library/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,16 @@
},
"publishable": {
"type": "boolean",
"description": "Create a publishable 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. Must be a valid npm name."
},
"testEnvironment": {
"type": "string",
Expand Down
Loading

0 comments on commit f3039db

Please sign in to comment.