Merge pull request #28778 from backstage/sennyeya/typedoc
feat: use typedocs for new API reference docsite
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/repo-tools': minor
|
||||
---
|
||||
|
||||
Adds a new experimental hidden command `package-docs` for generating API documentation. This is currently only intended for use in the Backstage main repository.
|
||||
@@ -174,3 +174,8 @@ knip.json
|
||||
# Schemathesis temporary files
|
||||
.hypothesis/
|
||||
.cassettes/
|
||||
|
||||
# Typedocs temporary files
|
||||
type-docs
|
||||
docs.json
|
||||
tsconfig.typedoc.tmp.json
|
||||
@@ -144,6 +144,7 @@
|
||||
"shx": "^0.3.2",
|
||||
"sloc": "^0.3.1",
|
||||
"sort-package-json": "^2.8.0",
|
||||
"typedoc": "^0.27.6",
|
||||
"typescript": "~5.2.0"
|
||||
},
|
||||
"packageManager": "yarn@3.8.1",
|
||||
|
||||
@@ -89,7 +89,8 @@
|
||||
"@backstage/types": "workspace:^",
|
||||
"@types/is-glob": "^4.0.2",
|
||||
"@types/node": "^20.16.0",
|
||||
"@types/prettier": "^2.0.0"
|
||||
"@types/prettier": "^2.0.0",
|
||||
"typedoc": "^0.27.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@microsoft/api-extractor-model": "*",
|
||||
@@ -97,11 +98,15 @@
|
||||
"@microsoft/tsdoc-config": "*",
|
||||
"@useoptic/optic": "^1.0.0",
|
||||
"prettier": "^2.8.1",
|
||||
"typedoc": "^0.27.0",
|
||||
"typescript": "> 3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"prettier": {
|
||||
"optional": true
|
||||
},
|
||||
"typedoc": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +262,11 @@ export function registerCommands(program: Command) {
|
||||
lazy(() => import('./knip-reports/knip-reports'), 'buildKnipReports'),
|
||||
);
|
||||
|
||||
program
|
||||
.command('package-docs [paths...]', { hidden: true })
|
||||
.description('EXPERIMENTAL: Generate package documentation')
|
||||
.action(lazy(() => import('./package-docs/command'), 'default'));
|
||||
|
||||
registerPackageCommand(program);
|
||||
registerRepoCommand(program);
|
||||
registerLintCommand(program);
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
import { paths as cliPaths, resolvePackagePaths } from '../../lib/paths';
|
||||
import { createTemporaryTsConfig } from './utils';
|
||||
import { mkdir, readFile, writeFile } from 'fs/promises';
|
||||
import pLimit from 'p-limit';
|
||||
|
||||
const limit = pLimit(8);
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
const EXCLUDE = [
|
||||
'packages/app',
|
||||
'packages/app-next',
|
||||
'packages/app-next-example-plugin',
|
||||
'packages/cli',
|
||||
'packages/cli-common',
|
||||
'packages/cli-node',
|
||||
'packages/e2e-test',
|
||||
'packages/e2e-test-utils',
|
||||
'packages/opaque-internal',
|
||||
'packages/techdocs-cli',
|
||||
'packages/techdocs-cli-embedded-app',
|
||||
'packages/yarn-plugin',
|
||||
'packages/backend',
|
||||
];
|
||||
|
||||
const HIGHLIGHT_LANGUAGES = [
|
||||
'ts',
|
||||
'tsx',
|
||||
'yaml',
|
||||
'bash',
|
||||
'sh',
|
||||
'shell',
|
||||
'yml',
|
||||
'jsx',
|
||||
'diff',
|
||||
'js',
|
||||
'json',
|
||||
];
|
||||
|
||||
function getExports(packageJson: any) {
|
||||
if (packageJson.exports) {
|
||||
return Object.values(packageJson.exports).filter(
|
||||
(e: any) => !(e as string).endsWith('package.json'),
|
||||
);
|
||||
}
|
||||
return [packageJson.main];
|
||||
}
|
||||
|
||||
async function generateDocJson(pkg: string) {
|
||||
const temporaryTsConfigPath: string = await createTemporaryTsConfig(pkg);
|
||||
|
||||
const packageJson = JSON.parse(
|
||||
await readFile(cliPaths.resolveTargetRoot(pkg, 'package.json'), 'utf-8'),
|
||||
);
|
||||
|
||||
const exports = getExports(packageJson);
|
||||
if (
|
||||
!exports.length ||
|
||||
!exports.some(e => e.startsWith('src') || e.startsWith('./src'))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await mkdir(cliPaths.resolveTargetRoot(`dist-types`, pkg), {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
const { stdout, stderr } = await execAsync(
|
||||
[
|
||||
cliPaths.resolveTargetRoot('node_modules/.bin/typedoc'),
|
||||
'--json',
|
||||
cliPaths.resolveTargetRoot(`dist-types`, pkg, 'docs.json'),
|
||||
'--tsconfig',
|
||||
temporaryTsConfigPath,
|
||||
'--basePath',
|
||||
cliPaths.targetRoot,
|
||||
'--skipErrorChecking',
|
||||
...(getExports(packageJson).flatMap(e => [
|
||||
'--entryPoints',
|
||||
e,
|
||||
]) as string[]),
|
||||
].join(' '),
|
||||
{
|
||||
cwd: pkg,
|
||||
env: { ...process.env, NODE_OPTIONS: '--max-old-space-size=12288' },
|
||||
},
|
||||
);
|
||||
console.log(`### Processed ${pkg}`);
|
||||
console.log(stdout);
|
||||
console.error(stderr);
|
||||
} catch (e) {
|
||||
console.error('Failed to generate docs for', pkg);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
export default async function packageDocs(paths: string[] = [], opts: any) {
|
||||
console.warn('!!! This is an experimental command !!!');
|
||||
const selectedPackageDirs = await resolvePackagePaths({
|
||||
paths,
|
||||
include: opts.include,
|
||||
exclude: opts.exclude,
|
||||
});
|
||||
|
||||
console.log(`### Generating docs.`);
|
||||
await Promise.all(
|
||||
selectedPackageDirs.map(pkg =>
|
||||
limit(async () => {
|
||||
if (EXCLUDE.includes(pkg)) {
|
||||
return;
|
||||
}
|
||||
console.log(`### Processing ${pkg}`);
|
||||
await generateDocJson(pkg);
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const generatedPackageDirs = [];
|
||||
for (const pkg of selectedPackageDirs) {
|
||||
try {
|
||||
const docsJsonPath = cliPaths.resolveTargetRoot(
|
||||
`dist-types/${pkg}/docs.json`,
|
||||
);
|
||||
const docsJson = JSON.parse(await readFile(docsJsonPath, 'utf-8'));
|
||||
const index = docsJson.children?.find((child: any) =>
|
||||
child.sources.some((e: any) => e.fileName.endsWith('src/index.ts')),
|
||||
);
|
||||
|
||||
if (index) {
|
||||
index.name = 'index';
|
||||
}
|
||||
await writeFile(docsJsonPath, JSON.stringify(docsJson, null, 2));
|
||||
generatedPackageDirs.push(pkg);
|
||||
} catch (e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
console.log('No docs.json found for', pkg);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { stdout, stderr } = await execAsync(
|
||||
[
|
||||
cliPaths.resolveTargetRoot('node_modules/.bin/typedoc'),
|
||||
'--entryPointStrategy',
|
||||
'merge',
|
||||
...generatedPackageDirs.flatMap(pkg => [
|
||||
'--entryPoints',
|
||||
`dist-types/${pkg}/docs.json`,
|
||||
]),
|
||||
...HIGHLIGHT_LANGUAGES.flatMap(e => ['--highlightLanguages', e]),
|
||||
'--out',
|
||||
cliPaths.resolveTargetRoot('type-docs'),
|
||||
].join(' '),
|
||||
{
|
||||
cwd: cliPaths.targetRoot,
|
||||
},
|
||||
);
|
||||
|
||||
console.log(stdout);
|
||||
console.error(stderr);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import { paths as cliPaths } from '../../lib/paths';
|
||||
|
||||
export async function createTemporaryTsConfig(dir: string) {
|
||||
const path = cliPaths.resolveOwnRoot(dir, 'tsconfig.typedoc.tmp.json');
|
||||
|
||||
process.once('exit', () => {
|
||||
fs.removeSync(path);
|
||||
});
|
||||
|
||||
let assetTypeFile: string[] = [];
|
||||
|
||||
try {
|
||||
assetTypeFile = [
|
||||
require.resolve('@backstage/cli/asset-types/asset-types.d.ts'),
|
||||
];
|
||||
} catch {
|
||||
/** ignore */
|
||||
}
|
||||
|
||||
await fs.writeJson(path, {
|
||||
extends: '../../tsconfig.json',
|
||||
include: [...assetTypeFile, 'src'],
|
||||
exclude: [],
|
||||
});
|
||||
|
||||
return path;
|
||||
}
|
||||
@@ -8748,6 +8748,7 @@ __metadata:
|
||||
portfinder: ^1.0.32
|
||||
tar: ^6.1.12
|
||||
ts-morph: ^24.0.0
|
||||
typedoc: ^0.27.6
|
||||
yaml-diff-patch: ^2.0.0
|
||||
peerDependencies:
|
||||
"@microsoft/api-extractor-model": "*"
|
||||
@@ -8755,10 +8756,13 @@ __metadata:
|
||||
"@microsoft/tsdoc-config": "*"
|
||||
"@useoptic/optic": ^1.0.0
|
||||
prettier: ^2.8.1
|
||||
typedoc: ^0.27.0
|
||||
typescript: "> 3.0.0"
|
||||
peerDependenciesMeta:
|
||||
prettier:
|
||||
optional: true
|
||||
typedoc:
|
||||
optional: true
|
||||
bin:
|
||||
backstage-repo-tools: bin/backstage-repo-tools
|
||||
languageName: unknown
|
||||
@@ -10159,6 +10163,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gerrit0/mini-shiki@npm:^1.24.0":
|
||||
version: 1.27.2
|
||||
resolution: "@gerrit0/mini-shiki@npm:1.27.2"
|
||||
dependencies:
|
||||
"@shikijs/engine-oniguruma": ^1.27.2
|
||||
"@shikijs/types": ^1.27.2
|
||||
"@shikijs/vscode-textmate": ^10.0.1
|
||||
checksum: aa4a0def0c7c73f2ef49b53f4dab5bf95f8f3b3d2c895baf384d338856a082a6a0487bc87c28d550b7f52ed71cbe98dae7754a5397be52df49a18e75cdd7d087
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gitbeaker/core@npm:^35.8.1":
|
||||
version: 35.8.1
|
||||
resolution: "@gitbeaker/core@npm:35.8.1"
|
||||
@@ -16591,6 +16606,33 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shikijs/engine-oniguruma@npm:^1.27.2":
|
||||
version: 1.29.2
|
||||
resolution: "@shikijs/engine-oniguruma@npm:1.29.2"
|
||||
dependencies:
|
||||
"@shikijs/types": 1.29.2
|
||||
"@shikijs/vscode-textmate": ^10.0.1
|
||||
checksum: 8713ada50e8875d22d928bd605d509a2c7d5e8c2c8a67b215b169f999457123082a02000182b37b9621903577dae5ac8067c614037fbf0aeb5b6dc2c195e58a2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shikijs/types@npm:1.29.2, @shikijs/types@npm:^1.27.2":
|
||||
version: 1.29.2
|
||||
resolution: "@shikijs/types@npm:1.29.2"
|
||||
dependencies:
|
||||
"@shikijs/vscode-textmate": ^10.0.1
|
||||
"@types/hast": ^3.0.4
|
||||
checksum: 3aeb2933b5ceda8afe6e4be624847de5fab392085ddf77fb785cf33014120d1afd6825e666d58895e4c489981196abc161c8a4d2e41f7da33d8f5e83b58cc606
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@shikijs/vscode-textmate@npm:^10.0.1":
|
||||
version: 10.0.1
|
||||
resolution: "@shikijs/vscode-textmate@npm:10.0.1"
|
||||
checksum: c5a8490417b9439b055844c6c09c3435fc435b1fc3923eb28f05ee346fd68e69df2d93cdaab319a51193970558ff1bf49c5ab047c9ed4fd86c3f9d062457a565
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@short.io/opensearch-mock@npm:^0.4.0":
|
||||
version: 0.4.0
|
||||
resolution: "@short.io/opensearch-mock@npm:0.4.0"
|
||||
@@ -19806,6 +19848,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/hast@npm:^3.0.4":
|
||||
version: 3.0.4
|
||||
resolution: "@types/hast@npm:3.0.4"
|
||||
dependencies:
|
||||
"@types/unist": "*"
|
||||
checksum: 7a973e8d16fcdf3936090fa2280f408fb2b6a4f13b42edeb5fbd614efe042b82eac68e298e556d50f6b4ad585a3a93c353e9c826feccdc77af59de8dd400d044
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/highlightjs@npm:^10.1.0":
|
||||
version: 10.1.0
|
||||
resolution: "@types/highlightjs@npm:10.1.0"
|
||||
@@ -42842,6 +42893,7 @@ __metadata:
|
||||
shx: ^0.3.2
|
||||
sloc: ^0.3.1
|
||||
sort-package-json: ^2.8.0
|
||||
typedoc: ^0.27.6
|
||||
typescript: ~5.2.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
@@ -46054,6 +46106,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typedoc@npm:^0.27.6":
|
||||
version: 0.27.6
|
||||
resolution: "typedoc@npm:0.27.6"
|
||||
dependencies:
|
||||
"@gerrit0/mini-shiki": ^1.24.0
|
||||
lunr: ^2.3.9
|
||||
markdown-it: ^14.1.0
|
||||
minimatch: ^9.0.5
|
||||
yaml: ^2.6.1
|
||||
peerDependencies:
|
||||
typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x
|
||||
bin:
|
||||
typedoc: bin/typedoc
|
||||
checksum: 1a8ac5dd636406fa0bcd4a1e9801d72896256c531c09a56207f991b62b7d4ceb336050a8933a3aba0239da6df5da3436e51c86776043501b6e9483aa0b31e69f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"types-ramda@npm:^0.30.0":
|
||||
version: 0.30.0
|
||||
resolution: "types-ramda@npm:0.30.0"
|
||||
@@ -47982,7 +48051,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3, yaml@npm:^2.3.4, yaml@npm:^2.7.0":
|
||||
"yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3, yaml@npm:^2.3.4, yaml@npm:^2.6.1, yaml@npm:^2.7.0":
|
||||
version: 2.7.0
|
||||
resolution: "yaml@npm:2.7.0"
|
||||
bin:
|
||||
|
||||
Reference in New Issue
Block a user