diff --git a/packages/kbn-type-summarizer/BUILD.bazel b/packages/kbn-type-summarizer/BUILD.bazel index 13a89e0669b80f..ec0df11bc3762f 100644 --- a/packages/kbn-type-summarizer/BUILD.bazel +++ b/packages/kbn-type-summarizer/BUILD.bazel @@ -10,10 +10,7 @@ PKG_REQUIRE_NAME = "@kbn/type-summarizer" SOURCE_FILES = glob( [ "src/**/*.ts", - ], - exclude = [ - "**/*.test.*" - ], + ] ) SRCS = SOURCE_FILES @@ -49,6 +46,7 @@ TYPES_DEPS = [ "@npm//is-path-inside", "@npm//normalize-path", "@npm//source-map", + "@npm//strip-ansi", "@npm//tslib", ] diff --git a/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts b/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts index a0fdb3e4685b1f..7a0d9be4629cd7 100644 --- a/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts +++ b/packages/kbn-type-summarizer/src/lib/bazel_cli_config.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import Path from 'path'; import Fs from 'fs'; import { CliError } from './cli_error'; import { parseCliFlags } from './cli_flags'; +import * as Path from './path'; const TYPE_SUMMARIZER_PACKAGES = ['@kbn/type-summarizer', '@kbn/crypto']; @@ -25,6 +25,36 @@ interface BazelCliConfig { use: 'api-extractor' | 'type-summarizer'; } +function isKibanaRepo(dir: string) { + try { + const json = Fs.readFileSync(Path.join(dir, 'package.json'), 'utf8'); + const parsed = JSON.parse(json); + return parsed.name === 'kibana'; + } catch { + return false; + } +} + +function findRepoRoot() { + const start = Path.resolve(__dirname); + let dir = start; + while (true) { + if (isKibanaRepo(dir)) { + return dir; + } + + // this is not the kibana directory, try moving up a directory + const parent = Path.join(dir, '..'); + if (parent === dir) { + throw new Error( + `unable to find Kibana's package.json file when traversing up from [${start}]` + ); + } + + dir = parent; + } +} + export function parseBazelCliFlags(argv: string[]): BazelCliConfig { const { rawFlags, unknownFlags } = parseCliFlags(argv, { string: ['use'], @@ -39,19 +69,7 @@ export function parseBazelCliFlags(argv: string[]): BazelCliConfig { }); } - let REPO_ROOT; - try { - const name = 'utils'; - // eslint-disable-next-line @typescript-eslint/no-var-requires - const utils = require('@kbn/' + name); - REPO_ROOT = utils.REPO_ROOT as string; - } catch (error) { - if (error && error.code === 'MODULE_NOT_FOUND') { - throw new CliError('type-summarizer bazel cli only works after bootstrap'); - } - - throw error; - } + const repoRoot = findRepoRoot(); const [relativePackagePath, ...extraPositional] = rawFlags._; if (typeof relativePackagePath !== 'string') { @@ -70,26 +88,45 @@ export function parseBazelCliFlags(argv: string[]): BazelCliConfig { const packageName: string = JSON.parse( Fs.readFileSync(Path.join(packageDir, 'package.json'), 'utf8') ).name; - const repoRelativePackageDir = Path.relative(REPO_ROOT, packageDir); + const repoRelativePackageDir = Path.relative(repoRoot, packageDir); return { use, packageName, - tsconfigPath: Path.join(REPO_ROOT, repoRelativePackageDir, 'tsconfig.json'), - inputPath: Path.resolve(REPO_ROOT, 'node_modules', packageName, 'target_types/index.d.ts'), + tsconfigPath: Path.join(repoRoot, repoRelativePackageDir, 'tsconfig.json'), + inputPath: Path.join(repoRoot, 'node_modules', packageName, 'target_types/index.d.ts'), repoRelativePackageDir, - outputDir: Path.resolve(REPO_ROOT, 'data/type-summarizer-output', use), + outputDir: Path.join(repoRoot, 'data/type-summarizer-output', use), }; } -export function parseBazelCliJson(json: string): BazelCliConfig { - let config; +function parseJsonFromCli(json: string) { try { - config = JSON.parse(json); + return JSON.parse(json); } catch (error) { - throw new CliError('unable to parse first positional argument as JSON'); + // TODO: This is to handle a bug in Bazel which escapes `"` in .bat arguments incorrectly, replacing them with `\` + if ( + error.message === 'Unexpected token \\ in JSON at position 1' && + process.platform === 'win32' + ) { + const unescapedJson = json.replaceAll('\\', '"'); + try { + return JSON.parse(unescapedJson); + } catch (e) { + throw new CliError( + `unable to parse first positional argument as JSON: "${e.message}"\n unescaped value: ${unescapedJson}\n raw value: ${json}` + ); + } + } + + throw new CliError( + `unable to parse first positional argument as JSON: "${error.message}"\n value: ${json}` + ); } +} +export function parseBazelCliJson(json: string): BazelCliConfig { + const config = parseJsonFromCli(json); if (typeof config !== 'object' || config === null) { throw new CliError('config JSON must be an object'); } @@ -131,14 +168,12 @@ export function parseBazelCliJson(json: string): BazelCliConfig { throw new CliError(`buildFilePath [${buildFilePath}] must be a relative path`); } - const repoRelativePackageDir = Path.dirname(buildFilePath); - return { packageName, outputDir: Path.resolve(outputDir), tsconfigPath: Path.resolve(tsconfigPath), inputPath: Path.resolve(inputPath), - repoRelativePackageDir, + repoRelativePackageDir: Path.dirname(buildFilePath), use: TYPE_SUMMARIZER_PACKAGES.includes(packageName) ? 'type-summarizer' : 'api-extractor', }; } diff --git a/packages/kbn-type-summarizer/src/lib/is_node_module.ts b/packages/kbn-type-summarizer/src/lib/is_node_module.ts index 67efde569a1b4e..ba4d607ccb8640 100644 --- a/packages/kbn-type-summarizer/src/lib/is_node_module.ts +++ b/packages/kbn-type-summarizer/src/lib/is_node_module.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import Path from 'path'; - import isPathInside from 'is-path-inside'; +import * as Path from './path'; + export function isNodeModule(dtsDir: string, path: string) { return (isPathInside(path, dtsDir) ? Path.relative(dtsDir, path) : path) - .split(Path.sep) + .split('/') .includes('node_modules'); } diff --git a/packages/kbn-type-summarizer/src/lib/path.ts b/packages/kbn-type-summarizer/src/lib/path.ts new file mode 100644 index 00000000000000..79d56aa58fab64 --- /dev/null +++ b/packages/kbn-type-summarizer/src/lib/path.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; + +import normalizePath from 'normalize-path'; +const cwd = normalizePath(process.cwd()); + +export function cwdRelative(path: string) { + return relative(cwd, path); +} + +export function relative(from: string, to: string) { + return normalizePath(Path.relative(from, to)); +} + +export function join(...segments: string[]) { + return Path.join(...segments); +} + +export function dirname(path: string) { + return Path.dirname(path); +} + +export function resolve(path: string) { + return Path.isAbsolute(path) ? normalizePath(path) : join(cwd, path); +} + +export function isAbsolute(path: string) { + return Path.isAbsolute(path); +} diff --git a/packages/kbn-type-summarizer/src/lib/printer.ts b/packages/kbn-type-summarizer/src/lib/printer.ts index 3ce675f7279275..8ecc4356ea4a23 100644 --- a/packages/kbn-type-summarizer/src/lib/printer.ts +++ b/packages/kbn-type-summarizer/src/lib/printer.ts @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -import Path from 'path'; - import * as ts from 'typescript'; import { SourceNode, CodeWithSourceMap } from 'source-map'; +import * as Path from './path'; import { findKind } from './ts_nodes'; import { SourceMapper } from './source_mapper'; import { CollectorResult } from './export_collector'; diff --git a/packages/kbn-type-summarizer/src/lib/source_mapper.ts b/packages/kbn-type-summarizer/src/lib/source_mapper.ts index 0b0e69571469c3..1f03119e8e3fd2 100644 --- a/packages/kbn-type-summarizer/src/lib/source_mapper.ts +++ b/packages/kbn-type-summarizer/src/lib/source_mapper.ts @@ -6,16 +6,14 @@ * Side Public License, v 1. */ -import Path from 'path'; - import * as ts from 'typescript'; import { SourceNode, SourceMapConsumer, BasicSourceMapConsumer } from 'source-map'; -import normalizePath from 'normalize-path'; import { Logger } from './log'; import { tryReadFile } from './helpers/fs'; import { parseJson } from './helpers/json'; import { isNodeModule } from './is_node_module'; +import * as Path from './path'; type SourceMapConsumerEntry = [ts.SourceFile, BasicSourceMapConsumer | undefined]; @@ -38,9 +36,9 @@ export class SourceMapper { return [sourceFile, undefined]; } - const relSourceFile = Path.relative(process.cwd(), sourceFile.fileName); - const sourceMapPath = Path.resolve(Path.dirname(sourceFile.fileName), match[1]); - const relSourceMapPath = Path.relative(process.cwd(), sourceMapPath); + const relSourceFile = Path.cwdRelative(sourceFile.fileName); + const sourceMapPath = Path.join(Path.dirname(sourceFile.fileName), match[1]); + const relSourceMapPath = Path.cwdRelative(sourceMapPath); const sourceJson = await tryReadFile(sourceMapPath, 'utf8'); if (!sourceJson) { throw new Error( @@ -81,7 +79,7 @@ export class SourceMapper { * us the path to the source, relative to the `repoRelativePackageDir`. */ fixSourcePath(source: string) { - return normalizePath(Path.relative(this.sourceFixDir, Path.join('/', source))); + return Path.relative(this.sourceFixDir, Path.join('/', source)); } getSourceNode(generatedNode: ts.Node, code: string) { diff --git a/packages/kbn-type-summarizer/src/lib/tsconfig_file.ts b/packages/kbn-type-summarizer/src/lib/tsconfig_file.ts index 7d327b1f03e0a3..f3d491c93abcbe 100644 --- a/packages/kbn-type-summarizer/src/lib/tsconfig_file.ts +++ b/packages/kbn-type-summarizer/src/lib/tsconfig_file.ts @@ -7,8 +7,8 @@ */ import * as ts from 'typescript'; -import Path from 'path'; +import * as Path from './path'; import { CliError } from './cli_error'; export function readTsConfigFile(path: string) { diff --git a/packages/kbn-type-summarizer/tests/integration_helpers.ts b/packages/kbn-type-summarizer/src/tests/integration_helpers.ts similarity index 91% rename from packages/kbn-type-summarizer/tests/integration_helpers.ts rename to packages/kbn-type-summarizer/src/tests/integration_helpers.ts index 68e1f3cc3a3b0f..c64e58c4e33f93 100644 --- a/packages/kbn-type-summarizer/tests/integration_helpers.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_helpers.ts @@ -13,13 +13,14 @@ import Fsp from 'fs/promises'; import * as ts from 'typescript'; import stripAnsi from 'strip-ansi'; +import normalizePath from 'normalize-path'; -import { loadTsConfigFile } from '../src/lib/tsconfig_file'; -import { createTsProject } from '../src/lib/ts_project'; -import { TestLog } from '../src/lib/log'; -import { summarizePackage } from '../src/summarize_package'; +import { loadTsConfigFile } from '../lib/tsconfig_file'; +import { createTsProject } from '../lib/ts_project'; +import { TestLog } from '../lib/log'; +import { summarizePackage } from '../summarize_package'; -const TMP_DIR = Path.resolve(__dirname, '__tmp__'); +const TMP_DIR = Path.resolve(__dirname, '../../__tmp__'); const DIAGNOSTIC_HOST = { getCanonicalFileName: (p: string) => p, @@ -153,11 +154,11 @@ class MockCli { // summarize the .d.ts files into the output dir await summarizePackage(log, { - dtsDir: this.dtsOutputDir, - inputPaths: [this.inputPath], - outputDir: this.outputDir, + dtsDir: normalizePath(this.dtsOutputDir), + inputPaths: [normalizePath(this.inputPath)], + outputDir: normalizePath(this.outputDir), repoRelativePackageDir: 'src', - tsconfigPath: this.tsconfigPath, + tsconfigPath: normalizePath(this.tsconfigPath), strictPrinting: false, }); diff --git a/packages/kbn-type-summarizer/tests/integration_tests/class.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/class.test.ts similarity index 98% rename from packages/kbn-type-summarizer/tests/integration_tests/class.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/class.test.ts index d2b39ab69d47bf..eaf87cda8521ba 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/class.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/class.test.ts @@ -69,7 +69,7 @@ it('prints basic class correctly', async () => { } `); expect(output.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] debug Ignoring 1 global declarations for \\"Record\\" debug Ignoring 5 global declarations for \\"Promise\\" " diff --git a/packages/kbn-type-summarizer/tests/integration_tests/function.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/function.test.ts similarity index 92% rename from packages/kbn-type-summarizer/tests/integration_tests/function.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/function.test.ts index ec15d941ca1536..de0f1bb4c6d4c0 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/function.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/function.test.ts @@ -75,8 +75,8 @@ it('prints the function declaration, including comments', async () => { `); expect(result.logs).toMatchInlineSnapshot(` "debug loaded sourcemaps for [ - 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/bar.d.ts', - 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' + 'packages/kbn-type-summarizer/__tmp__/dist_dts/bar.d.ts', + 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] " `); diff --git a/packages/kbn-type-summarizer/tests/integration_tests/import_boundary.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/import_boundary.test.ts similarity index 96% rename from packages/kbn-type-summarizer/tests/integration_tests/import_boundary.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/import_boundary.test.ts index 35cf08e2973598..f1e3279bb57b0d 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/import_boundary.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/import_boundary.test.ts @@ -52,7 +52,7 @@ it('output type links to named import from node modules', async () => { } `); expect(output.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] " `); }); @@ -84,7 +84,7 @@ it('output type links to default import from node modules', async () => { } `); expect(output.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] " `); }); diff --git a/packages/kbn-type-summarizer/tests/integration_tests/interface.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/interface.test.ts similarity index 97% rename from packages/kbn-type-summarizer/tests/integration_tests/interface.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/interface.test.ts index cc821f1c9fc90f..cbccbfb1d77dc8 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/interface.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/interface.test.ts @@ -55,7 +55,7 @@ it('prints the whole interface, including comments', async () => { } `); expect(result.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] debug Ignoring 5 global declarations for \\"Promise\\" " `); diff --git a/packages/kbn-type-summarizer/tests/integration_tests/references.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/references.test.ts similarity index 90% rename from packages/kbn-type-summarizer/tests/integration_tests/references.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/references.test.ts index 796bcd5fac3d1d..0a2cc9aaf5857f 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/references.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/references.test.ts @@ -60,9 +60,9 @@ it('collects references from source files which contribute to result', async () `); expect(result.logs).toMatchInlineSnapshot(` "debug loaded sourcemaps for [ - 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/files/foo.d.ts', - 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/files/index.d.ts', - 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' + 'packages/kbn-type-summarizer/__tmp__/dist_dts/files/foo.d.ts', + 'packages/kbn-type-summarizer/__tmp__/dist_dts/files/index.d.ts', + 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] debug Ignoring 5 global declarations for \\"Promise\\" debug Ignoring 4 global declarations for \\"Symbol\\" diff --git a/packages/kbn-type-summarizer/tests/integration_tests/type_alias.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/type_alias.test.ts similarity index 96% rename from packages/kbn-type-summarizer/tests/integration_tests/type_alias.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/type_alias.test.ts index f099bad9f3de6a..cbe99c54ca0425 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/type_alias.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/type_alias.test.ts @@ -36,7 +36,7 @@ it('prints basic type alias', async () => { } `); expect(output.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] " `); }); diff --git a/packages/kbn-type-summarizer/tests/integration_tests/variables.test.ts b/packages/kbn-type-summarizer/src/tests/integration_tests/variables.test.ts similarity index 97% rename from packages/kbn-type-summarizer/tests/integration_tests/variables.test.ts rename to packages/kbn-type-summarizer/src/tests/integration_tests/variables.test.ts index c51c9b0098b6c6..a2b47d64710252 100644 --- a/packages/kbn-type-summarizer/tests/integration_tests/variables.test.ts +++ b/packages/kbn-type-summarizer/src/tests/integration_tests/variables.test.ts @@ -62,7 +62,7 @@ it('prints basic variable exports with sourcemaps', async () => { } `); expect(output.logs).toMatchInlineSnapshot(` - "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/tests/__tmp__/dist_dts/index.d.ts' ] + "debug loaded sourcemaps for [ 'packages/kbn-type-summarizer/__tmp__/dist_dts/index.d.ts' ] " `); }); diff --git a/packages/kbn-type-summarizer/tsconfig.json b/packages/kbn-type-summarizer/tsconfig.json index f3c3802071ac46..b3779bdd686ea0 100644 --- a/packages/kbn-type-summarizer/tsconfig.json +++ b/packages/kbn-type-summarizer/tsconfig.json @@ -11,7 +11,6 @@ ] }, "include": [ - "src/**/*", - "tests/**/*" + "src/**/*" ] }