Skip to content

Commit

Permalink
feat: Support for monorepos
Browse files Browse the repository at this point in the history
Based on npm / Yarn workspaces, introducing the --packages option

Co-Authored-By: efokschaner <eddyaod@gmail.com>
  • Loading branch information
Gerrit0 and efokschaner committed Jun 5, 2021
1 parent 2c2b91b commit 15c0552
Show file tree
Hide file tree
Showing 26 changed files with 795 additions and 120 deletions.
36 changes: 36 additions & 0 deletions README.md
Expand Up @@ -34,6 +34,39 @@ will treat each file contained within it as an entry point.
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`).
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 `workpsaces` 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.

#### Single npm module

```text
typedoc --packages .
```

#### Monorepo with npm/Yarn workspace at the root

```text
typedoc --packages .
```

#### Monorepo with manually specified sub-packages to document

This can be useful if you do not want all your workspaces to be processed.
Accepts the same paths as would go in the `package.json`'s workspaces

```text
# Note the single quotes prevent shell widcard expansion, allowing typedoc to do the expansion
typedoc --packages a-package --packages 'some-more-packages/*' --packages 'some-other-packages/*'
```

### Arguments

For a complete list of the command line arguments run `typedoc --help` or visit
Expand All @@ -47,6 +80,9 @@ For a complete list of the command line arguments run `typedoc --help` or visit
- `--options`<br>
Specify a json option file that should be loaded. If not specified TypeDoc
will look for 'typedoc.json' in the current directory.
- `--packages <path/to/package/>`<br>
Specify one or more sub packages, or the root of a monorepo with workspaces.
Supports wildcard paths in the same fashion as those found in npm or Yarn workspaces.
- `--tsconfig <path/to/tsconfig.json>`<br>
Specify a typescript config file that should be loaded. If not
specified TypeDoc will look for 'tsconfig.json' in the current directory.
Expand Down
7 changes: 5 additions & 2 deletions bin/typedoc
Expand Up @@ -59,8 +59,11 @@ async function run(app) {
return ExitCodes.OptionError;
}

if (app.options.getValue("entryPoints").length === 0) {
app.logger.error("No entry points provided");
if (
app.options.getValue("entryPoints").length === 0 &&
app.options.getValue("packages").length === 0
) {
app.logger.error("No entry points or packages provided");
return ExitCodes.NoEntryPoints;
}

Expand Down
1 change: 1 addition & 0 deletions examples/basic/.gitignore
@@ -0,0 +1 @@
docs
25 changes: 14 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Expand Up @@ -20,6 +20,7 @@
"node": ">= 12.20.0"
},
"dependencies": {
"glob": "^7.1.6",
"handlebars": "^4.7.7",
"lodash": "^4.17.21",
"lunr": "^2.3.9",
Expand All @@ -33,6 +34,7 @@
"typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x"
},
"devDependencies": {
"@types/glob": "^7.1.3",
"@types/lodash": "^4.14.170",
"@types/lunr": "^2.3.3",
"@types/marked": "^2.0.3",
Expand All @@ -57,7 +59,7 @@
],
"scripts": {
"pretest": "node scripts/copy_test_files.js",
"test": "nyc --reporter=html --reporter=text-summary mocha --timeout=10000 'dist/test/**/*.test.js'",
"test": "nyc --reporter=html --reporter=text-summary mocha --timeout=10000 'dist/test/**/*.test.js' --exclude 'dist/test/packages/**'",
"prerebuild_specs": "npm run pretest",
"rebuild_specs": "node scripts/rebuild_specs.js",
"build": "tsc --project .",
Expand Down
129 changes: 125 additions & 4 deletions scripts/copy_test_files.js
Expand Up @@ -2,12 +2,128 @@

const { remove, copy } = require("../dist/lib/utils/fs");
const { join } = require("path");
const { spawn } = require("child_process");

function promiseFromChildProcess(childProcess) {
return new Promise(function (resolve, reject) {
childProcess.on("error", function (error) {
reject(
new Error(
childProcess.spawnargs.join(" ") + " : " + error.message
)
);
});
childProcess.on("exit", function (code) {
if (code !== 0) {
reject(
new Error(
childProcess.spawnargs.join(" ") +
" : exited with code " +
code
)
);
} else {
resolve();
}
});
});
}

const isWindows = process.platform === "win32";
const npmCommand = isWindows ? "npm.cmd" : "npm";

function ensureNpmVersion() {
return Promise.resolve().then(() => {
const npmProc = spawn(npmCommand, ["--version"], {
stdio: ["ignore", "pipe", "inherit"],
});
let npmVersion = "";
npmProc.stdout.on("data", (data) => {
npmVersion += data;
});
return promiseFromChildProcess(npmProc).then(() => {
npmVersion = npmVersion.trim();
let firstDot = npmVersion.indexOf(".");
const npmMajorVer = parseInt(
npmVersion.slice(0, npmVersion.indexOf("."))
);
if (npmMajorVer < 7) {
throw new Error(
"npm version must be at least 7, version installed is " +
npmVersion
);
}
});
});
}

function prepareMonorepoFolder() {
return Promise.resolve()
.then(() => {
return promiseFromChildProcess(
spawn(
"git",
["clone", "https://github.com/efokschaner/ts-monorepo.git"],
{
cwd: join(__dirname, "../dist/test/packages"),
stdio: "inherit",
}
)
);
})
.then(() => {
return promiseFromChildProcess(
spawn(
"git",
["checkout", "73bdd4c6458ad4cc3de35498e65d55a1a44a8499"],
{
cwd: join(
__dirname,
"../dist/test/packages/ts-monorepo"
),
stdio: "inherit",
}
)
);
})
.then(() => {
return promiseFromChildProcess(
spawn(npmCommand, ["install"], {
cwd: join(__dirname, "../dist/test/packages/ts-monorepo"),
stdio: "inherit",
})
);
})
.then(() => {
return promiseFromChildProcess(
spawn(npmCommand, ["run", "build"], {
cwd: join(__dirname, "../dist/test/packages/ts-monorepo"),
stdio: "inherit",
})
);
});
}

function prepareSinglePackageExample() {
return Promise.resolve().then(() => {
return promiseFromChildProcess(
spawn(npmCommand, ["run", "build"], {
cwd: join(
__dirname,
"../dist/test/packages/typedoc-single-package-example"
),
stdio: "inherit",
})
);
});
}

const toCopy = [
"test/converter",
"test/converter2",
"test/renderer",
"test/module",
"test/packages",
"test/utils/options/readers/data",
];

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

Promise.all(copies).catch((reason) => {
console.error(reason);
process.exit(1);
});
Promise.all(copies)
.then(ensureNpmVersion)
.then(() =>
Promise.all([prepareMonorepoFolder(), prepareSinglePackageExample()])
)
.catch((reason) => {
console.error(reason);
process.exit(1);
});
8 changes: 4 additions & 4 deletions scripts/rebuild_specs.js
Expand Up @@ -69,14 +69,14 @@ function rebuildConverterTests(dirs) {

for (const fullPath of dirs) {
console.log(fullPath);
const src = app.expandInputFiles([fullPath]);

for (const [file, before, after] of conversions) {
const out = path.join(fullPath, `${file}.json`);
if (fs.existsSync(out)) {
TypeDoc.resetReflectionID();
before();
const result = app.converter.convert(src, program);
const result = app.converter.convert(
app.getEntrypointsForPaths([fullPath])
);
const serialized = app.serializer.toObject(result);

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

app.options.setValue("entryPoints", app.expandInputFiles([src]));
app.options.setValue("entryPoints", [src]);
const project = app.convert();
await app.generateDocs(project, out);
await app.generateJson(project, path.join(out, "specs.json"));
Expand Down

0 comments on commit 15c0552

Please sign in to comment.