Skip to content

Commit

Permalink
feat(tasks): implement new type-check that use nx generation approach…
Browse files Browse the repository at this point in the history
… + programatic TS apis
  • Loading branch information
Hotell committed Feb 14, 2024
1 parent b74f56c commit c59ff3c
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
2 changes: 2 additions & 0 deletions scripts/tasks/src/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ts } from './ts';
import { typeCheck } from './type-check';
import { verifyPackaging } from './verify-packaging';
import { webpack, webpackDevServer } from './webpack';
import { typeCheckV2 } from './type-check-v2';

/** Do only the bare minimum setup of options and resolve paths */
function basicPreset() {
Expand Down Expand Up @@ -75,6 +76,7 @@ export function preset() {
task('babel:postprocess', babel);
task('generate-api', generateApi);
task('type-check', typeCheck);
task('type-check-v2', typeCheckV2);
task('verify-packaging', () => verifyPackaging(args));

task('ts:compile', () => {
Expand Down
111 changes: 111 additions & 0 deletions scripts/tasks/src/type-check-v2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import * as fs from 'fs';
import * as path from 'node:path';

import { workspaceRoot, writeJsonFile } from '@nx/devkit';
import { readTsConfig } from '@nx/js/src/utils/typescript/ts-config';
import { logger } from 'just-scripts';
import * as ts from 'typescript';

import { getTsPathAliasesConfig } from './utils';

// eslint-disable-next-line @typescript-eslint/no-shadow
function createTmpTsConfig(tsconfigPath: string, workspaceRoot: string, projectRoot: string) {
const tmpTsConfigPath = path.join(workspaceRoot, 'tmp', projectRoot, 'tsconfig.generated.json');
const parsedTSConfig = readTsConfigWithRemappedPaths(path.join(workspaceRoot, tsconfigPath), tmpTsConfigPath);

process.on('exit', () => cleanupTmpTsConfigFile(tmpTsConfigPath));

writeJsonFile(tmpTsConfigPath, parsedTSConfig);

return { tmpTsConfigPath };
}

function readTsConfigWithRemappedPaths(tsConfigPath: string, generatedTsConfigPath: string) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const generatedTsConfig: Record<string, any> = { compilerOptions: {} };
const originalConfig = readTsConfig(tsConfigPath);

generatedTsConfig.extends = path.relative(path.dirname(generatedTsConfigPath), tsConfigPath);
generatedTsConfig.compilerOptions.paths = updatePaths(originalConfig.options.paths ?? {});
generatedTsConfig.include = originalConfig.raw.include;
generatedTsConfig.files = originalConfig.raw.files;
generatedTsConfig.references = originalConfig.raw.references.map((ref: { path: string }) => {
const oldPath = ref.path;
const newPath = path.relative(path.dirname(generatedTsConfigPath), oldPath);
return { path: newPath };
});

// if (process.env.NX_VERBOSE_LOGGING_PATH_MAPPINGS === 'true') {
// output.log({
// title: 'TypeScript path mappings have been rewritten.',
// });
// console.log(JSON.stringify(generatedTsConfig.compilerOptions.paths, null, 2));
// }
return generatedTsConfig;
}

function updatePaths(paths: Record<string, string[]>) {
// turn off path aliases for now
return {};
}

function cleanupTmpTsConfigFile(tmpTsConfigPath: string) {
try {
if (tmpTsConfigPath) {
fs.unlinkSync(tmpTsConfigPath);
}
// eslint-disable-next-line no-empty
} catch (err) {}
}

export function typeCheckV2() {
const { isUsingTsSolutionConfigs, tsConfigFilePaths, projectRoot } = getTsPathAliasesConfig();

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

const tmpTsConfig = createTmpTsConfig(
path.relative(workspaceRoot, tsConfigFilePaths.root),
workspaceRoot,
path.relative(workspaceRoot, projectRoot),
);

tscBuild(tmpTsConfig.tmpTsConfigPath);
}

const formatHost: ts.FormatDiagnosticsHost = {
// eslint-disable-next-line @typescript-eslint/no-shadow
getCanonicalFileName: path => path,
getCurrentDirectory: ts.sys.getCurrentDirectory,
getNewLine: () => ts.sys.newLine,
};

function tscBuild(tsConfigPath: string) {
// const tsSolutionConfigPath = ts.findConfigFile(rootPath, ts.sys.fileExists, 'tsconfig.json');

if (!tsConfigPath) {
throw new Error("Could not find a valid 'tsconfig.json'.");
}

// const createProgram = ts.createSemanticDiagnosticsBuilderProgram;

// const host = ts.createSolutionBuilderHost(undefined, createProgram);
const host = ts.createSolutionBuilderHost(ts.sys, /*createProgram*/ undefined, diagnostic => {
const formattedDiagnostic = ts.formatDiagnosticsWithColorAndContext([diagnostic], formatHost);

console.info(formattedDiagnostic);
});

const solutionBuilder = ts.createSolutionBuilder(host, [tsConfigPath], {});

const buildResult = solutionBuilder.build();

if (buildResult > 0) {
console.error('Build failed');
process.exit(1);
}

console.log('Build succeeded');
}

0 comments on commit c59ff3c

Please sign in to comment.