Skip to content

Commit 15c0552

Browse files
Gerrit0efokschaner
andcommitted
feat: Support for monorepos
Based on npm / Yarn workspaces, introducing the --packages option Co-Authored-By: efokschaner <eddyaod@gmail.com>
1 parent 2c2b91b commit 15c0552

26 files changed

+795
-120
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,39 @@ will treat each file contained within it as an entry point.
3434
typedoc package1/index.ts package2/index.ts
3535
```
3636

37+
### Monorepos / Workspaces
38+
39+
If your codebase is comprised of one or more npm packages, you can pass the paths to these
40+
packages and TypeDoc will attempt to determine entry points from your `package.json`'s `main`
41+
property (or its default value `index.js`).
42+
If any of the packages given are the root of an [npm Workspace](https://docs.npmjs.com/cli/v7/using-npm/workspaces)
43+
or a [Yarn Workspace](https://classic.yarnpkg.com/en/docs/workspaces/) TypeDoc will find all
44+
the `workpsaces` defined in the `package.json`.
45+
This mode requires sourcemaps in your JS entry points, in order to find the TS entry points.
46+
Supports wildcard paths in the same fashion as those found in npm or Yarn workspaces.
47+
48+
#### Single npm module
49+
50+
```text
51+
typedoc --packages .
52+
```
53+
54+
#### Monorepo with npm/Yarn workspace at the root
55+
56+
```text
57+
typedoc --packages .
58+
```
59+
60+
#### Monorepo with manually specified sub-packages to document
61+
62+
This can be useful if you do not want all your workspaces to be processed.
63+
Accepts the same paths as would go in the `package.json`'s workspaces
64+
65+
```text
66+
# Note the single quotes prevent shell widcard expansion, allowing typedoc to do the expansion
67+
typedoc --packages a-package --packages 'some-more-packages/*' --packages 'some-other-packages/*'
68+
```
69+
3770
### Arguments
3871

3972
For a complete list of the command line arguments run `typedoc --help` or visit
@@ -47,6 +80,9 @@ For a complete list of the command line arguments run `typedoc --help` or visit
4780
- `--options`<br>
4881
Specify a json option file that should be loaded. If not specified TypeDoc
4982
will look for 'typedoc.json' in the current directory.
83+
- `--packages <path/to/package/>`<br>
84+
Specify one or more sub packages, or the root of a monorepo with workspaces.
85+
Supports wildcard paths in the same fashion as those found in npm or Yarn workspaces.
5086
- `--tsconfig <path/to/tsconfig.json>`<br>
5187
Specify a typescript config file that should be loaded. If not
5288
specified TypeDoc will look for 'tsconfig.json' in the current directory.

bin/typedoc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ async function run(app) {
5959
return ExitCodes.OptionError;
6060
}
6161

62-
if (app.options.getValue("entryPoints").length === 0) {
63-
app.logger.error("No entry points provided");
62+
if (
63+
app.options.getValue("entryPoints").length === 0 &&
64+
app.options.getValue("packages").length === 0
65+
) {
66+
app.logger.error("No entry points or packages provided");
6467
return ExitCodes.NoEntryPoints;
6568
}
6669

examples/basic/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docs

package-lock.json

Lines changed: 14 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"node": ">= 12.20.0"
2121
},
2222
"dependencies": {
23+
"glob": "^7.1.6",
2324
"handlebars": "^4.7.7",
2425
"lodash": "^4.17.21",
2526
"lunr": "^2.3.9",
@@ -33,6 +34,7 @@
3334
"typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x"
3435
},
3536
"devDependencies": {
37+
"@types/glob": "^7.1.3",
3638
"@types/lodash": "^4.14.170",
3739
"@types/lunr": "^2.3.3",
3840
"@types/marked": "^2.0.3",
@@ -57,7 +59,7 @@
5759
],
5860
"scripts": {
5961
"pretest": "node scripts/copy_test_files.js",
60-
"test": "nyc --reporter=html --reporter=text-summary mocha --timeout=10000 'dist/test/**/*.test.js'",
62+
"test": "nyc --reporter=html --reporter=text-summary mocha --timeout=10000 'dist/test/**/*.test.js' --exclude 'dist/test/packages/**'",
6163
"prerebuild_specs": "npm run pretest",
6264
"rebuild_specs": "node scripts/rebuild_specs.js",
6365
"build": "tsc --project .",

scripts/copy_test_files.js

Lines changed: 125 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,128 @@
22

33
const { remove, copy } = require("../dist/lib/utils/fs");
44
const { join } = require("path");
5+
const { spawn } = require("child_process");
6+
7+
function promiseFromChildProcess(childProcess) {
8+
return new Promise(function (resolve, reject) {
9+
childProcess.on("error", function (error) {
10+
reject(
11+
new Error(
12+
childProcess.spawnargs.join(" ") + " : " + error.message
13+
)
14+
);
15+
});
16+
childProcess.on("exit", function (code) {
17+
if (code !== 0) {
18+
reject(
19+
new Error(
20+
childProcess.spawnargs.join(" ") +
21+
" : exited with code " +
22+
code
23+
)
24+
);
25+
} else {
26+
resolve();
27+
}
28+
});
29+
});
30+
}
31+
32+
const isWindows = process.platform === "win32";
33+
const npmCommand = isWindows ? "npm.cmd" : "npm";
34+
35+
function ensureNpmVersion() {
36+
return Promise.resolve().then(() => {
37+
const npmProc = spawn(npmCommand, ["--version"], {
38+
stdio: ["ignore", "pipe", "inherit"],
39+
});
40+
let npmVersion = "";
41+
npmProc.stdout.on("data", (data) => {
42+
npmVersion += data;
43+
});
44+
return promiseFromChildProcess(npmProc).then(() => {
45+
npmVersion = npmVersion.trim();
46+
let firstDot = npmVersion.indexOf(".");
47+
const npmMajorVer = parseInt(
48+
npmVersion.slice(0, npmVersion.indexOf("."))
49+
);
50+
if (npmMajorVer < 7) {
51+
throw new Error(
52+
"npm version must be at least 7, version installed is " +
53+
npmVersion
54+
);
55+
}
56+
});
57+
});
58+
}
59+
60+
function prepareMonorepoFolder() {
61+
return Promise.resolve()
62+
.then(() => {
63+
return promiseFromChildProcess(
64+
spawn(
65+
"git",
66+
["clone", "https://github.com/efokschaner/ts-monorepo.git"],
67+
{
68+
cwd: join(__dirname, "../dist/test/packages"),
69+
stdio: "inherit",
70+
}
71+
)
72+
);
73+
})
74+
.then(() => {
75+
return promiseFromChildProcess(
76+
spawn(
77+
"git",
78+
["checkout", "73bdd4c6458ad4cc3de35498e65d55a1a44a8499"],
79+
{
80+
cwd: join(
81+
__dirname,
82+
"../dist/test/packages/ts-monorepo"
83+
),
84+
stdio: "inherit",
85+
}
86+
)
87+
);
88+
})
89+
.then(() => {
90+
return promiseFromChildProcess(
91+
spawn(npmCommand, ["install"], {
92+
cwd: join(__dirname, "../dist/test/packages/ts-monorepo"),
93+
stdio: "inherit",
94+
})
95+
);
96+
})
97+
.then(() => {
98+
return promiseFromChildProcess(
99+
spawn(npmCommand, ["run", "build"], {
100+
cwd: join(__dirname, "../dist/test/packages/ts-monorepo"),
101+
stdio: "inherit",
102+
})
103+
);
104+
});
105+
}
106+
107+
function prepareSinglePackageExample() {
108+
return Promise.resolve().then(() => {
109+
return promiseFromChildProcess(
110+
spawn(npmCommand, ["run", "build"], {
111+
cwd: join(
112+
__dirname,
113+
"../dist/test/packages/typedoc-single-package-example"
114+
),
115+
stdio: "inherit",
116+
})
117+
);
118+
});
119+
}
5120

6121
const toCopy = [
7122
"test/converter",
8123
"test/converter2",
9124
"test/renderer",
10125
"test/module",
126+
"test/packages",
11127
"test/utils/options/readers/data",
12128
];
13129

@@ -18,7 +134,12 @@ const copies = toCopy.map(async (dir) => {
18134
await copy(source, target);
19135
});
20136

21-
Promise.all(copies).catch((reason) => {
22-
console.error(reason);
23-
process.exit(1);
24-
});
137+
Promise.all(copies)
138+
.then(ensureNpmVersion)
139+
.then(() =>
140+
Promise.all([prepareMonorepoFolder(), prepareSinglePackageExample()])
141+
)
142+
.catch((reason) => {
143+
console.error(reason);
144+
process.exit(1);
145+
});

scripts/rebuild_specs.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ function rebuildConverterTests(dirs) {
6969

7070
for (const fullPath of dirs) {
7171
console.log(fullPath);
72-
const src = app.expandInputFiles([fullPath]);
73-
7472
for (const [file, before, after] of conversions) {
7573
const out = path.join(fullPath, `${file}.json`);
7674
if (fs.existsSync(out)) {
7775
TypeDoc.resetReflectionID();
7876
before();
79-
const result = app.converter.convert(src, program);
77+
const result = app.converter.convert(
78+
app.getEntrypointsForPaths([fullPath])
79+
);
8080
const serialized = app.serializer.toObject(result);
8181

8282
const data = JSON.stringify(serialized, null, " ")
@@ -105,7 +105,7 @@ async function rebuildRendererTest() {
105105
externalPattern: ["**/node_modules/**"],
106106
});
107107

108-
app.options.setValue("entryPoints", app.expandInputFiles([src]));
108+
app.options.setValue("entryPoints", [src]);
109109
const project = app.convert();
110110
await app.generateDocs(project, out);
111111
await app.generateJson(project, path.join(out, "specs.json"));

0 commit comments

Comments
 (0)