Skip to content

Commit

Permalink
auto generated mdx api doc system
Browse files Browse the repository at this point in the history
  • Loading branch information
stacey-gammon committed Jan 6, 2021
1 parent ff2d0f4 commit 5736ed5
Show file tree
Hide file tree
Showing 53 changed files with 3,085 additions and 146 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.aws-config.json
.signing-config.json
/api_docs
.ackrc
/.es
/.chromium
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"test:ftr:runner": "node scripts/functional_test_runner",
"checkLicenses": "node scripts/check_licenses --dev",
"build": "node scripts/build --all-platforms",
"build:apidocs": "node scripts/build_api_docs",
"start": "node scripts/kibana --dev",
"debug": "node --nolazy --inspect scripts/kibana --dev",
"debug-break": "node --nolazy --inspect-brk scripts/kibana --dev",
Expand Down Expand Up @@ -815,6 +816,7 @@
"tinycolor2": "1.4.1",
"topojson-client": "3.0.0",
"ts-loader": "^7.0.5",
"ts-morph": "^9.1.0",
"tsd": "^0.13.1",
"typescript": "4.1.2",
"typescript-fsa": "^3.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@

import Path from 'path';
import loadJsonFile from 'load-json-file';
import { REPO_ROOT } from '@kbn/utils';

export interface KibanaPlatformPlugin {
readonly directory: string;
readonly manifestPath: string;
readonly manifest: Manifest;
readonly relativeDirectory: string;
}

function isValidDepsDeclaration(input: unknown, type: string): string[] {
Expand All @@ -40,6 +42,7 @@ interface Manifest {
server: boolean;
kibanaVersion: string;
version: string;
serviceFolders: readonly string[];
requiredPlugins: readonly string[];
optionalPlugins: readonly string[];
requiredBundles: readonly string[];
Expand All @@ -65,6 +68,7 @@ export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformP
}

return {
relativeDirectory: Path.dirname(manifestPath).slice(REPO_ROOT.length),
directory: Path.dirname(manifestPath),
manifestPath,
manifest: {
Expand All @@ -75,6 +79,7 @@ export function parseKibanaPlatformPlugin(manifestPath: string): KibanaPlatformP
id: manifest.id,
version: manifest.version,
kibanaVersion: manifest.kibanaVersion || manifest.version,
serviceFolders: manifest.serviceFolders || [],
requiredPlugins: isValidDepsDeclaration(manifest.requiredPlugins, 'requiredPlugins'),
optionalPlugins: isValidDepsDeclaration(manifest.optionalPlugins, 'optionalPlugins'),
requiredBundles: isValidDepsDeclaration(manifest.requiredBundles, 'requiredBundles'),
Expand Down
21 changes: 21 additions & 0 deletions scripts/build_api_docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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.
*/

require('../src/setup_node_env');
require('../src/dev/build_api_docs/run');
7 changes: 7 additions & 0 deletions src/core/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"id": "core",
"summary": "The core plugin has core functionality",
"version": "kibana",
"serviceFolders": ["http", "saved_objects", "chrome", "application"]
}

67 changes: 67 additions & 0 deletions src/dev/build_api_docs/api/get_api_nodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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 Path from 'path';
import { KibanaPlatformPlugin, ToolingLog } from '@kbn/dev-utils';
import { Project, SourceFile, Node } from 'ts-morph';
import { ApiScope } from './types';
import { isNamedNode } from '../tsmorph_utils';
import { getSourceFileMatching } from './utils';

export function getApisForPluginScope(
project: Project,
plugin: KibanaPlatformPlugin,
scope: ApiScope,
log: ToolingLog
): Node[] {
const path = Path.join(`${plugin.relativeDirectory}`, scope.toString(), 'index.ts');
const file = getSourceFileMatching(project, path);

if (file) {
return getApisForFile(file, log);
} else {
return [];
}
}

function getApisForFile(source: SourceFile, log: ToolingLog): Node[] {
const nodes: Node[] = [];
const exported = source.getExportedDeclarations();

exported.forEach((val) => {
val.forEach((ed) => {
const name: string = isNamedNode(ed) ? ed.getName() : '';

// Every plugin will have an export called "plugin". Don't bother listing
// it, it's only for the plugin infrastructure.
// Config is also a common export on the server side that is just for the
// plugin infrastructure.
if (name === 'plugin' || name === 'config') {
return;
}
if (name && name !== '') {
nodes.push(ed);
} else {
log.warning(`API with missing name encountered.`);
}
});
});

log.debug(`Collected ${nodes.length} exports from file ${source.getFilePath()}`);
return nodes;
}
36 changes: 36 additions & 0 deletions src/dev/build_api_docs/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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.
*/

/**
* Developers will need to know whether these APIs are available on the client, server, or both.
*/
export enum ApiScope {
CLIENT = 'public',
SERVER = 'server',
COMMON = 'common',
}

/**
* Start and Setup interfaces are special - their functionality is not imported statically but
* accessible via the dependent plugins start and setup functions.
*/
export enum Lifecycle {
START = 'start',
SETUP = 'setup',
}
41 changes: 41 additions & 0 deletions src/dev/build_api_docs/api/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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 { ToolingLog } from '@kbn/dev-utils';
import { Project, SourceFile } from 'ts-morph';
import { ApiScope } from './types';

export function getScopeFromPath(path: string, log: ToolingLog): ApiScope {
if (path.indexOf('/public/') >= 0) {
return ApiScope.CLIENT;
} else if (path.indexOf('/server/') >= 0) {
return ApiScope.SERVER;
} else if (path.indexOf('/common/') >= 0) {
return ApiScope.COMMON;
} else {
log.warning(`Unexpected path encountered ${path}`);
return ApiScope.COMMON;
}
}

export function getSourceFileMatching(
project: Project,
relativePath: string
): SourceFile | undefined {
return project.getSourceFiles().find((file) => file.getFilePath().indexOf(relativePath) >= 0);
}
78 changes: 78 additions & 0 deletions src/dev/build_api_docs/api_doc_defs/extract_import_refs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you 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 { KibanaPlatformPlugin, ToolingLog } from '@kbn/dev-utils';
import { getPluginApiDocId } from '../mdx_utils';
import { extractImportReferences } from './extract_import_refs';
import { Reference } from '../types';
import { getKibanaPlatformPlugin } from '../tests/kibana_platform_plugin_mock';

const plugins: KibanaPlatformPlugin[] = [getKibanaPlatformPlugin('pluginA', 'plugin_a')];

const log = new ToolingLog({
level: 'debug',
writeTo: process.stdout,
});

it('when there are no imports', () => {
const results = extractImportReferences(`(param: string) => Bar`, plugins, log);
expect(results.length).toBe(1);
expect(results[0]).toBe('(param: string) => Bar');
});

it('test extractImportReference', () => {
const results = extractImportReferences(
`(param: string) => import("/plugin_a/public/bar").Bar`,
plugins,
log
);
expect(results.length).toBe(2);
expect(results[0]).toBe('(param: string) => ');
expect(results[1]).toEqual({
text: 'Bar',
docId: getPluginApiDocId('plugin_a'),
section: 'def-public.Bar',
});
});

it('test extractImportReference with two imports', () => {
const results = extractImportReferences(
`<I extends import("/plugin_a/public/foo").FooFoo, O extends import("/plugin_a/public/bar").Bar>`,
plugins,
log
);
expect(results.length).toBe(5);
expect(results[0]).toBe('<I extends ');
expect((results[1] as Reference).text).toBe('FooFoo');
expect(results[2]).toBe(', O extends ');
expect((results[3] as Reference).text).toBe('Bar');
expect(results[4]).toBe('>');
});

it('test extractImportReference with unknown imports', () => {
const results = extractImportReferences(
`<I extends import("/plugin_c/public/foo").FooFoo>`,
plugins,
log
);
expect(results.length).toBe(3);
expect(results[0]).toBe('<I extends ');
expect(results[1]).toBe('FooFoo');
expect(results[2]).toBe('>');
});
Loading

0 comments on commit 5736ed5

Please sign in to comment.