Skip to content

Commit

Permalink
feat(scripts-tasks): implement type-check alias, update generate-api,…
Browse files Browse the repository at this point in the history
… refactor getTsPathAliasesConfig
  • Loading branch information
Hotell committed Apr 18, 2023
1 parent e8c9c7a commit 743028b
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 26 deletions.
6 changes: 3 additions & 3 deletions scripts/tasks/src/api-extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function apiExtractor(): TaskFunction {
};

const args: ReturnType<typeof getJustArgv> & Partial<ApiExtractorCliRunCommandArgs> = getJustArgv();
const { isUsingTsSolutionConfigs, packageJson, tsConfig } = getTsPathAliasesConfig();
const { isUsingTsSolutionConfigs, packageJson, tsConfigs } = getTsPathAliasesConfig();

if (configsToExecute.length === 0) {
return noop;
Expand Down Expand Up @@ -102,14 +102,14 @@ export function apiExtractor(): TaskFunction {
}

function onConfigLoaded(config: Parameters<NonNullable<ApiExtractorOptions['onConfigLoaded']>>[0]) {
if (!(isUsingTsSolutionConfigs && tsConfig)) {
if (!(isUsingTsSolutionConfigs && tsConfigs.lib)) {
return;
}

logger.info(`api-extractor: package is using TS path aliases. Overriding TS compiler settings.`);

const compilerConfig = getTsPathAliasesApiExtractorConfig({
tsConfig,
tsConfig: tsConfigs.lib,
packageJson,
pathAliasesTsConfigPath: isLocalBuild ? path.join(workspaceRoot, 'tsconfig.base.json') : undefined,
definitionsRootPath: 'dist/out-tsc/types',
Expand Down
11 changes: 7 additions & 4 deletions scripts/tasks/src/copy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as fs from 'fs-extra';
import * as path from 'path';
import { series, resolveCwd, copyTask, copyInstructionsTask, logger, TaskFunction } from 'just-scripts';
import { getProjectMetadata, findGitRoot } from '@fluentui/scripts-monorepo';

import { findGitRoot, getProjectMetadata } from '@fluentui/scripts-monorepo';
import * as fs from 'fs-extra';
import { TaskFunction, copyInstructionsTask, copyTask, logger, resolveCwd, series } from 'just-scripts';

import { getTsPathAliasesConfig } from './utils';

export function expandSourcePath(pattern: string): string | null {
Expand Down Expand Up @@ -38,10 +40,11 @@ export function expandSourcePath(pattern: string): string | null {
* Used solely for packages that use TS solution config files with TS path aliases
*/
export function copyCompiled() {
const { isUsingTsSolutionConfigs, packageJson, tsConfig } = getTsPathAliasesConfig();
const { isUsingTsSolutionConfigs, packageJson, tsConfigs } = getTsPathAliasesConfig();
const root = findGitRoot();

const packageDir = process.cwd();
const tsConfig = tsConfigs.lib;

if (!(isUsingTsSolutionConfigs && tsConfig)) {
logger.warn(`copy-compiled: works only with packages that use TS solution config files. Skipping...`);
Expand Down
19 changes: 13 additions & 6 deletions scripts/tasks/src/generate-api.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { exec } from 'child_process';
import { promisify } from 'util';
import { execSync } from 'child_process';

import { series } from 'just-scripts';

import { apiExtractor } from './api-extractor';

const execAsync = promisify(exec);
import { getTsPathAliasesConfigUsedOnlyForDx } from './utils';

export function generateApi() {
return series(generateTypeDeclarations, apiExtractor);
}

function generateTypeDeclarations() {
const cmd = 'tsc -p ./tsconfig.lib.json --emitDeclarationOnly';
return execAsync(cmd);
const { isUsingPathAliasesForDx, tsConfigFileForCompilation } = getTsPathAliasesConfigUsedOnlyForDx();
const cmd = [
'tsc',
`-p ./${tsConfigFileForCompilation}`,
'--emitDeclarationOnly',
isUsingPathAliasesForDx ? '--baseUrl .' : null,
]
.filter(Boolean)
.join(' ');

return execSync(cmd, { stdio: 'inherit' });
}
2 changes: 2 additions & 0 deletions scripts/tasks/src/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { hasSass, sass } from './sass';
import { buildStorybookTask, startStorybookTask } from './storybook';
import { swc } from './swc';
import { ts } from './ts';
import { typeCheck } from './type-check';
import { webpack, webpackDevServer } from './webpack';

/** Do only the bare minimum setup of options and resolve paths */
Expand Down Expand Up @@ -72,6 +73,7 @@ export function preset() {
task('storybook:build', buildStorybookTask());
task('babel:postprocess', babel);
task('generate-api', generateApi);
task('type-check', typeCheck);

task('ts:compile', () => {
const moduleFlag = args.module;
Expand Down
10 changes: 6 additions & 4 deletions scripts/tasks/src/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ function prepareTsTaskConfig(options: TscTaskOptions) {
options.baseUrl = '.';
options.rootDir = './src';
options.project = tsConfigFileForCompilation;

return options;
}

const { isUsingTsSolutionConfigs, tsConfigFile, tsConfig } = getTsPathAliasesConfig();
const { isUsingTsSolutionConfigs, tsConfigFileNames, tsConfigs } = getTsPathAliasesConfig();

if (isUsingTsSolutionConfigs && tsConfig) {
if (isUsingTsSolutionConfigs && tsConfigs.lib) {
logger.info(`📣 TSC: package is using TS path aliases. Overriding tsconfig settings.`);

const tsConfigOutDir = tsConfig.compilerOptions.outDir as string;
const tsConfigOutDir = tsConfigs.lib.compilerOptions.outDir as string;

options.outDir = `${tsConfigOutDir}/${options.outDir}`;
options.project = tsConfigFile;
options.project = tsConfigFileNames.lib;
}

return options;
Expand Down
43 changes: 43 additions & 0 deletions scripts/tasks/src/type-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as fs from 'fs';

import { logger } from 'just-scripts';
// eslint-disable-next-line import/no-extraneous-dependencies
import { exec } from 'just-scripts-utils';

import { getTsPathAliasesConfig } from './utils';

export function typeCheck() {
const { isUsingTsSolutionConfigs, tsConfigFileContents, tsConfigs, tsConfigFilePaths } = getTsPathAliasesConfig();

if (!isUsingTsSolutionConfigs) {
logger.info('project is not using TS solution config. skipping...');
return;
}

const content = tsConfigFileContents.root;
const config = tsConfigs.root;
const configPath = tsConfigFilePaths.root;

if (!(content && config)) {
return;
}

// turn off path aliases.
// @ts-expect-error - bad just-scripts ts types
config.compilerOptions.paths = {};
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');

const cmd = 'tsc';
const args = ['-b', '--pretty', configPath];
const program = `${cmd} ${args.join(' ')}`;

return exec(program)
.catch(err => {
console.error(err.stdout);
process.exit(1);
})
.finally(() => {
// restore original tsconfig.json
fs.writeFileSync(configPath, content, 'utf-8');
});
}
65 changes: 56 additions & 9 deletions scripts/tasks/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,84 @@
import { execSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';

import { stripJsonComments } from '@nrwl/devkit';
import * as jju from 'jju';
import type { TscTaskOptions } from 'just-scripts';

/**
*
* get full TS configuration for particular tsconfig.json.
* uses tsc --showConfig under the hood
*/
export function getFullTsConfig(options: { configFileName: string; cwd: string }): TsConfig | null {
const { configFileName, cwd } = options;
const configPath = path.join(cwd, configFileName);

if (!fs.existsSync(configPath)) {
console.warn(`${configPath} doesn't exist`);
return null;
}

const output = execSync(`tsc -p ${configFileName} --showConfig`, { cwd, encoding: 'utf-8' });
const json = JSON.parse(output);

return json;
}

export function getTsPathAliasesConfig() {
const cwd = process.cwd();
const tsConfigFile = 'tsconfig.lib.json';
const tsConfigPath = path.join(cwd, './tsconfig.lib.json');
const tsConfig: TsConfig | null = fs.existsSync(tsConfigPath)
? jju.parse(fs.readFileSync(tsConfigPath, 'utf-8'))
: null;
const tsConfigFileNames = {
root: 'tsconfig.json',
lib: 'tsconfig.lib.json',
};
const tsConfigFilePaths = {
root: path.join(cwd, tsConfigFileNames.root),
lib: path.join(cwd, tsConfigFileNames.lib),
};
const tsConfigFileContents = {
root: fs.existsSync(tsConfigFilePaths.root) ? fs.readFileSync(tsConfigFilePaths.root, 'utf-8') : null,
lib: fs.existsSync(tsConfigFilePaths.lib) ? fs.readFileSync(tsConfigFilePaths.lib, 'utf-8') : null,
};
const tsConfigs = {
root: tsConfigFileContents.root ? (JSON.parse(tsConfigFileContents.root) as TsConfig) : null,
lib: tsConfigFileContents.lib ? (JSON.parse(tsConfigFileContents.lib) as TsConfig) : null,
};
const packageJson: PackageJson = JSON.parse(fs.readFileSync(path.join(cwd, './package.json'), 'utf-8'));

const isUsingTsSolutionConfigs = Boolean(tsConfig);
const isUsingTsSolutionConfigs =
tsConfigs.root &&
tsConfigs.root.references &&
tsConfigs.root.references.length > 0 &&
Boolean(tsConfigFileContents.lib);

return { tsConfig, isUsingTsSolutionConfigs, tsConfigFile, tsConfigPath, packageJson };
return {
tsConfigFileNames,
tsConfigFilePaths,
tsConfigFileContents,
tsConfigs,
packageJson,
isUsingTsSolutionConfigs,
};
}

export function getTsPathAliasesConfigUsedOnlyForDx() {
const tsConfigFilesWithAliases = ['tsconfig.app.json', 'tsconfig.lib.json', 'tsconfig.json'];
const tsConfigBaseFilesForDx = ['tsconfig.base.v8.json', 'tsconfig.base.all.json'];
const cwd = process.cwd();
const tsConfigPath = path.join(cwd, `./tsconfig.json`);

if (!fs.existsSync(tsConfigPath)) {
throw new Error(`${tsConfigPath} doesn't exist`);
}

const tsConfig = JSON.parse(stripJsonComments(fs.readFileSync(tsConfigPath, 'utf-8')));
const isUsingPathAliasesForDx =
tsConfig.extends && tsConfigBaseFilesForDx.some(relativeFilePath => tsConfig.extends.endsWith(relativeFilePath));

const tsConfigFileForCompilation = tsConfigFilesWithAliases.find(fileName => fs.existsSync(path.join(cwd, fileName)));

if (!tsConfigFileForCompilation) {
throw new Error(`no tsconfig from ${tsConfigFilesWithAliases} found!`);
throw new Error(`no tsconfig from one of [${tsConfigFilesWithAliases}] found!`);
}

return { isUsingPathAliasesForDx, tsConfigFileForCompilation };
Expand Down

0 comments on commit 743028b

Please sign in to comment.