Skip to content

Commit

Permalink
fix: support the ng-package.json in secondary entry points (#1406)
Browse files Browse the repository at this point in the history
* fix: support the ng-package.json in secondary entry points

Currently secondary entry points are breaking "no-implicit-dependencies" TSLint rule, because the
rule is checking for package.json files, which in secondary entry points are anyway just containing
"ngPackage" configuration. Adding the support for ng-package.json removes the need for package.json,
thus TSLint will look correctly in parent package.json file and act accordingly.

fix 1391

* test: add a missing test for the feature-d integration

* docs: document the alternative secondary entry point setup
  • Loading branch information
klemenoslaj authored and alan-agius4 committed Sep 25, 2019
1 parent 88f8cb4 commit 8b97bfa
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 6 deletions.
5 changes: 5 additions & 0 deletions docs/secondary-entrypoints.md
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
@@ -0,0 +1,5 @@
import { FEATURE_A } from '@sample/secondary/feature-a';
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
@@ -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
@@ -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
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

0 comments on commit 8b97bfa

Please sign in to comment.