mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[ts/build_ts_refs] add support for --clean flag (#91060)
Co-authored-by: spalger <spalger@users.noreply.github.com>
This commit is contained in:
parent
d9abaa180b
commit
c0a974aa0e
9 changed files with 166 additions and 51 deletions
|
@ -7,4 +7,4 @@
|
|||
*/
|
||||
|
||||
require('../src/setup_node_env');
|
||||
require('../src/dev/typescript/build_refs').runBuildRefs();
|
||||
require('../src/dev/typescript').runBuildRefsCli();
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* 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 execa from 'execa';
|
||||
import { run, ToolingLog } from '@kbn/dev-utils';
|
||||
|
||||
export async function buildAllRefs(log: ToolingLog) {
|
||||
await buildRefs(log, 'tsconfig.refs.json');
|
||||
}
|
||||
|
||||
async function buildRefs(log: ToolingLog, projectPath: string) {
|
||||
try {
|
||||
log.debug(`Building TypeScript projects refs for ${projectPath}...`);
|
||||
await execa(require.resolve('typescript/bin/tsc'), ['-b', projectPath, '--pretty']);
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export async function runBuildRefs() {
|
||||
run(
|
||||
async ({ log }) => {
|
||||
await buildAllRefs(log);
|
||||
},
|
||||
{
|
||||
description: 'Build TypeScript projects',
|
||||
}
|
||||
);
|
||||
}
|
24
src/dev/typescript/build_ts_refs.ts
Normal file
24
src/dev/typescript/build_ts_refs.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 execa from 'execa';
|
||||
import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils';
|
||||
|
||||
export const REF_CONFIG_PATHS = [Path.resolve(REPO_ROOT, 'tsconfig.refs.json')];
|
||||
|
||||
export async function buildAllTsRefs(log: ToolingLog) {
|
||||
for (const path of REF_CONFIG_PATHS) {
|
||||
const relative = Path.relative(REPO_ROOT, path);
|
||||
log.debug(`Building TypeScript projects refs for ${relative}...`);
|
||||
await execa(require.resolve('typescript/bin/tsc'), ['-b', relative, '--pretty'], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
}
|
||||
}
|
37
src/dev/typescript/build_ts_refs_cli.ts
Normal file
37
src/dev/typescript/build_ts_refs_cli.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 { run } from '@kbn/dev-utils';
|
||||
import del from 'del';
|
||||
|
||||
import { buildAllTsRefs, REF_CONFIG_PATHS } from './build_ts_refs';
|
||||
import { getOutputsDeep } from './ts_configfile';
|
||||
import { concurrentMap } from './concurrent_map';
|
||||
|
||||
export async function runBuildRefsCli() {
|
||||
run(
|
||||
async ({ log, flags }) => {
|
||||
if (flags.clean) {
|
||||
const outDirs = getOutputsDeep(REF_CONFIG_PATHS);
|
||||
log.info('deleting', outDirs.length, 'ts output directories');
|
||||
await concurrentMap(100, outDirs, (outDir) => del(outDir));
|
||||
}
|
||||
|
||||
await buildAllTsRefs(log);
|
||||
},
|
||||
{
|
||||
description: 'Build TypeScript projects',
|
||||
flags: {
|
||||
boolean: ['clean'],
|
||||
},
|
||||
log: {
|
||||
defaultLevel: 'debug',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
28
src/dev/typescript/concurrent_map.ts
Normal file
28
src/dev/typescript/concurrent_map.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 * as Rx from 'rxjs';
|
||||
import { mergeMap, toArray, map } from 'rxjs/operators';
|
||||
import { lastValueFrom } from '@kbn/std';
|
||||
|
||||
export async function concurrentMap<T, T2>(
|
||||
concurrency: number,
|
||||
arr: T[],
|
||||
fn: (item: T, i: number) => Promise<T2>
|
||||
): Promise<T2[]> {
|
||||
return await lastValueFrom(
|
||||
Rx.from(arr).pipe(
|
||||
// execute items in parallel based on concurrency
|
||||
mergeMap(async (item, index) => ({ index, result: await fn(item, index) }), concurrency),
|
||||
// collect the results into an array
|
||||
toArray(),
|
||||
// sort items back into order and return array of just results
|
||||
map((list) => list.sort((a, b) => a.index - b.index).map(({ result }) => result))
|
||||
)
|
||||
);
|
||||
}
|
|
@ -11,3 +11,4 @@ export { filterProjectsByFlag } from './projects';
|
|||
export { getTsProjectForAbsolutePath } from './get_ts_project_for_absolute_path';
|
||||
export { execInProjects } from './exec_in_projects';
|
||||
export { runTypeCheckCli } from './run_type_check_cli';
|
||||
export * from './build_ts_refs_cli';
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { readFileSync } from 'fs';
|
||||
import { basename, dirname, relative, resolve } from 'path';
|
||||
|
||||
import { IMinimatch, Minimatch } from 'minimatch';
|
||||
import { parseConfigFileTextToJson } from 'typescript';
|
||||
|
||||
import { REPO_ROOT } from '@kbn/utils';
|
||||
|
||||
import { parseTsConfig } from './ts_configfile';
|
||||
|
||||
function makeMatchers(directory: string, patterns: string[]) {
|
||||
return patterns.map(
|
||||
(pattern) =>
|
||||
|
@ -23,16 +22,6 @@ function makeMatchers(directory: string, patterns: string[]) {
|
|||
);
|
||||
}
|
||||
|
||||
function parseTsConfig(path: string) {
|
||||
const { error, config } = parseConfigFileTextToJson(path, readFileSync(path, 'utf8'));
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function testMatchers(matchers: IMinimatch[], path: string) {
|
||||
return matchers.some((matcher) => matcher.match(path));
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import getopts from 'getopts';
|
|||
|
||||
import { execInProjects } from './exec_in_projects';
|
||||
import { filterProjectsByFlag } from './projects';
|
||||
import { buildAllRefs } from './build_refs';
|
||||
import { buildAllTsRefs } from './build_ts_refs';
|
||||
|
||||
export async function runTypeCheckCli() {
|
||||
const extraFlags: string[] = [];
|
||||
|
@ -69,7 +69,7 @@ export async function runTypeCheckCli() {
|
|||
process.exit();
|
||||
}
|
||||
|
||||
await buildAllRefs(log);
|
||||
await buildAllTsRefs(log);
|
||||
|
||||
const tscArgs = [
|
||||
// composite project cannot be used with --noEmit
|
||||
|
|
71
src/dev/typescript/ts_configfile.ts
Normal file
71
src/dev/typescript/ts_configfile.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 Fs from 'fs';
|
||||
import Path from 'path';
|
||||
|
||||
import { parseConfigFileTextToJson } from 'typescript';
|
||||
|
||||
// yes, this is just `any`, but I'm hoping that TypeScript will give us some help here eventually
|
||||
type TsConfigFile = ReturnType<typeof parseConfigFileTextToJson>['config'];
|
||||
|
||||
export function parseTsConfig(tsConfigPath: string): TsConfigFile {
|
||||
const { error, config } = parseConfigFileTextToJson(
|
||||
tsConfigPath,
|
||||
Fs.readFileSync(tsConfigPath, 'utf8')
|
||||
);
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
export function getOutputsDeep(tsConfigPaths: string[]) {
|
||||
const tsConfigs = new Map<string, TsConfigFile>();
|
||||
|
||||
const read = (path: string) => {
|
||||
const cached = tsConfigs.get(path);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
const config = parseTsConfig(path);
|
||||
tsConfigs.set(path, config);
|
||||
return config;
|
||||
};
|
||||
|
||||
const outputDirs: string[] = [];
|
||||
const seen = new Set<TsConfigFile>();
|
||||
|
||||
const traverse = (path: string) => {
|
||||
const config = read(path);
|
||||
if (seen.has(config)) {
|
||||
return;
|
||||
}
|
||||
seen.add(config);
|
||||
|
||||
const dirname = Path.dirname(path);
|
||||
const relativeOutDir: string | undefined = config.compilerOptions?.outDir;
|
||||
if (relativeOutDir) {
|
||||
outputDirs.push(Path.resolve(dirname, relativeOutDir));
|
||||
}
|
||||
|
||||
const refs: undefined | Array<{ path: string }> = config.references;
|
||||
for (const ref of refs ?? []) {
|
||||
traverse(Path.resolve(dirname, ref.path));
|
||||
}
|
||||
};
|
||||
|
||||
for (const path of tsConfigPaths) {
|
||||
traverse(path);
|
||||
}
|
||||
|
||||
return outputDirs;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue