Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support the ng-package.json in secondary entry points #1406

Merged
merged 3 commits into from
Sep 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/secondary-entrypoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ The contents of `my_package/testing/package.json` can be as simple as:
No, that is not a typo. No name is required. No version is required.
It's all handled for you by ng-packagr!
When built, the primary entry point is imported by `import {..} from '@my/library'` and the secondary entry point with `import {..} from '@my/library/testing'`.

### Alternative to `package.json`

Alternatively, you could create `ng-package.json` instead of `package.json`.
This is particularly useful in conjunction with `no-implicit-dependencies` TSLint rule, which will complain if `package.json` does not contain the dependencies used in the secondary entry point, which is misleading since all the dependencies should be mentioned in the primary `package.json`.
5 changes: 5 additions & 0 deletions integration/samples/secondary/feature-d/feature-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FEATURE_A } from '@sample/secondary/feature-a';
klemenoslaj marked this conversation as resolved.
Show resolved Hide resolved
import { FEATURE_B } from '@sample/secondary/feature-b';
import { FEATURE_C } from '@sample/secondary/feature-c';

export const FEATURE_D = `Feature D: ${FEATURE_A} ${FEATURE_B} ${FEATURE_C}`;
6 changes: 6 additions & 0 deletions integration/samples/secondary/feature-d/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../../src/ng-package.schema.json",
"lib": {
"entryFile": "feature-d.ts"
}
}
33 changes: 33 additions & 0 deletions integration/samples/secondary/specs/ep-feature-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai';

describe(`@sample/secondary/feature-d`, () => {
let PACKAGE;

before(() => {
PACKAGE = require('../dist/feature-d/package.json');
});

it(`should exist`, () => {
expect(PACKAGE).to.be.ok;
});

it(`should be named '@sample/secondary/feature-d'`, () => {
expect(PACKAGE['name']).to.equal('@sample/secondary/feature-d');
});

it(`should reference "main" bundle (UMD)`, () => {
expect(PACKAGE['main']).to.equal('../bundles/sample-secondary-feature-d.umd.js');
});

it(`should reference "module" bundle (FESM5)`, () => {
expect(PACKAGE['module']).to.equal('../fesm5/sample-secondary-feature-d.js');
});

it(`should reference "typings" files`, () => {
expect(PACKAGE['typings']).to.equal('sample-secondary-feature-d.d.ts');
});

it(`should reference "metadata" file`, () => {
expect(PACKAGE['metadata']).to.equal('sample-secondary-feature-d.metadata.json');
});
});
14 changes: 8 additions & 6 deletions src/lib/ng-v5/discover-packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,22 @@ function formatSchemaValidationErrors(errors: ajv.ErrorObject[]): string {
* Resolves a user's package by testing for 'package.json', 'ng-package.json', or 'ng-package.js'.
*
* @param folderPathOrFilePath A path pointing either to a file or a directory
* @param isSecondary A boolean determining if this is a secondary package
* @return The user's package
*/
async function resolveUserPackage(folderPathOrFilePath: string): Promise<UserPackage | undefined> {
async function resolveUserPackage(folderPathOrFilePath: string, isSecondary = false): Promise<UserPackage | undefined> {
const readConfigFile = async (filePath: string) => (pathExistsSync(filePath) ? import(filePath) : undefined);
const fullPath = path.resolve(folderPathOrFilePath);
const pathStats = await lstat(fullPath);
const basePath = pathStats.isDirectory() ? fullPath : path.dirname(fullPath);
const packageJson = await readConfigFile(path.join(basePath, 'package.json'));

if (!packageJson) {
if (!packageJson && !isSecondary) {
throw new Error(`Cannot discover package sources at ${folderPathOrFilePath} as 'package.json' was not found.`);
}

let ngPackageJson: undefined | object;
if (packageJson['ngPackage']) {
if (packageJson && packageJson['ngPackage']) {
// Read `ngPackage` from `package.json`
ngPackageJson = { ...packageJson['ngPackage'] };
} else if (pathStats.isDirectory()) {
Expand Down Expand Up @@ -74,7 +75,7 @@ async function resolveUserPackage(folderPathOrFilePath: string): Promise<UserPac

return {
basePath,
packageJson,
packageJson: packageJson || {},
ngPackageJson,
};
}
Expand Down Expand Up @@ -109,9 +110,10 @@ async function findSecondaryPackagesPaths(directoryPath: string, excludeFolder:
'**/.git/**',
`${path.resolve(directoryPath, excludeFolder)}/**`,
`${directoryPath}/package.json`,
`${directoryPath}/ng-package.json`,
];

const filePaths = await globFiles(`${directoryPath}/**/package.json`, {
const filePaths = await globFiles(`${directoryPath}/**/{package,ng-package}.json`, {
ignore,
cwd: directoryPath,
});
Expand Down Expand Up @@ -156,7 +158,7 @@ export async function discoverPackages({ project }: { project: string }): Promis
.then(folderPaths =>
Promise.all(
folderPaths.map(folderPath =>
resolveUserPackage(folderPath).catch(() => {
resolveUserPackage(folderPath, true).catch(() => {
log.warn(`Cannot read secondary entry point at ${folderPath}. Skipping.`);

return null;
Expand Down