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

Add support for TS entry points in monorepo configuration #1596

Merged
merged 6 commits into from Jun 13, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Expand Up @@ -37,14 +37,16 @@ typedoc package1/index.ts package2/index.ts
### Monorepos / Workspaces

If your codebase is comprised of one or more npm packages, you can pass the paths to these
packages and TypeDoc will attempt to determine entry points from your `package.json`'s `main`
property (or its default value `index.js`).
packages and TypeDoc will attempt to determine entry points based on `package.json`'s `main`
property (with default value `index.js`) and if it wasn't found, based on `types` property.
If any of the packages given are the root of an [npm Workspace](https://docs.npmjs.com/cli/v7/using-npm/workspaces)
or a [Yarn Workspace](https://classic.yarnpkg.com/en/docs/workspaces/) TypeDoc will find all
the `workspaces` defined in the `package.json`.
This mode requires sourcemaps in your JS entry points, in order to find the TS entry points.
Supports wildcard paths in the same fashion as those found in npm or Yarn workspaces.

:warning: In opposition to project entry points, package entry points are determined relatively to options file if provided.

#### Single npm module

```text
Expand Down
40 changes: 32 additions & 8 deletions src/lib/utils/package-manifest.ts
Expand Up @@ -2,6 +2,7 @@

import glob = require("glob");
import { dirname, join, resolve } from "path";
import { existsSync } from "fs";
import { flatMap } from "./array";

import { readFile } from "./fs";
Expand Down Expand Up @@ -200,29 +201,52 @@ export function getTsEntryPointForPackage(
packageJson: Record<string, unknown>
): string | undefined | typeof ignorePackage {
let packageMain = "index.js"; // The default, per the npm docs.
let packageTypes = null;
if (
hasOwnProperty(packageJson, "main") &&
typeof packageJson.main == "string"
) {
packageMain = packageJson.main;
} else if (
hasOwnProperty(packageJson, "types") &&
typeof packageJson.types == "string"
) {
packageTypes = packageJson.types;
} else if (
hasOwnProperty(packageJson, "typings") &&
typeof packageJson.typings == "string"
) {
packageTypes = packageJson.typings;
}
let jsEntryPointPath = resolve(packageJsonPath, "..", packageMain);
// The jsEntryPointPath from the package manifest can be like a require path.
let entryPointPath = resolve(packageJsonPath, "..", packageMain);
// The entryPointPath from the package manifest can be like a require path.
// It could end with .js, or it could end without .js, or it could be a folder containing an index.js
// We can use require.resolve to let node do its magic.
// Pass an empty `paths` as node_modules locations do not need to be examined
try {
jsEntryPointPath = require.resolve(jsEntryPointPath, { paths: [] });
entryPointPath = require.resolve(entryPointPath, { paths: [] });
if (/\.tsx?$/.test(entryPointPath) && existsSync(entryPointPath)) {
return entryPointPath;
}
} catch (e) {
if (e.code !== "MODULE_NOT_FOUND") {
throw e;
} else {
logger.warn(
`Could not determine the JS entry point for "${packageJsonPath}". Package will be ignored.`
entryPointPath = resolve(
packageJsonPath,
"..",
packageTypes ?? packageMain
);
logger.verbose(e.message);
return ignorePackage;
if (/\.tsx?$/.test(entryPointPath) && existsSync(entryPointPath)) {
return entryPointPath;
} else {
logger.warn(
`Could not determine the entry point for "${packageJsonPath}". Package will be ignored.`
);
logger.verbose(e.message);
return ignorePackage;
}
}
}
return getTsSourceFromJsSource(logger, jsEntryPointPath);
return getTsSourceFromJsSource(logger, entryPointPath);
}
6 changes: 5 additions & 1 deletion src/test/packages.test.ts
Expand Up @@ -14,7 +14,11 @@ describe("Packages support", () => {
const project = app.convert();
equal(
project?.children?.map((r) => r.name),
["typedoc-multi-package-bar", "typedoc-multi-package-foo"]
[
"typedoc-multi-package-bar",
"typedoc-multi-package-baz",
"typedoc-multi-package-foo",
]
);
});

Expand Down
6 changes: 0 additions & 6 deletions src/test/packages/multi-package/packages/bar/dist/index.js

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions src/test/packages/multi-package/packages/bar/index.d.ts
@@ -0,0 +1 @@
export function bar(): void;
1 change: 0 additions & 1 deletion src/test/packages/multi-package/packages/bar/index.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/packages/multi-package/packages/bar/package.json
@@ -1,5 +1,5 @@
{
"name": "typedoc-multi-package-bar",
"version": "1.0.0",
"main": "dist/index"
"types": "index.d.ts"
}
1 change: 1 addition & 0 deletions src/test/packages/multi-package/packages/baz/index.ts
@@ -0,0 +1 @@
export function baz() {}
5 changes: 5 additions & 0 deletions src/test/packages/multi-package/packages/baz/package.json
@@ -0,0 +1,5 @@
{
"name": "typedoc-multi-package-baz",
"version": "1.0.0",
"main": "index.ts"
}
8 changes: 8 additions & 0 deletions src/test/packages/multi-package/packages/baz/tsconfig.json
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"sourceMap": false,
"inlineSourceMap": true
}
}