From 803e7744639fb29ec3f5177629f75a8e2b571c70 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 10 Aug 2021 19:29:37 +0200 Subject: [PATCH] fix(scripts): resolve api-extractor execution issue within packages with new DX --- .../config/api-extractor.local.json | 26 ++++++- scripts/tasks/api-extractor.ts | 75 ++++++++++++++++++- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/packages/react-components/config/api-extractor.local.json b/packages/react-components/config/api-extractor.local.json index c2ea401c1c3685..3281a6d9203b4d 100644 --- a/packages/react-components/config/api-extractor.local.json +++ b/packages/react-components/config/api-extractor.local.json @@ -1,5 +1,29 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", "extends": "./api-extractor.json", - "mainEntryPointFilePath": "/dist//src/index.d.ts" + "mainEntryPointFilePath": "/dist//src/index.d.ts", + "compiler": { + /* This is a quickfix to make build:local work - @see https://github.com/microsoft/fluentui/issues/19360 */ + "overrideTsconfig": { + "extends": "../../tsconfig.base.json", + "include": ["src"], + "compilerOptions": { + "target": "ES5", + "module": "CommonJS", + "lib": ["ES2016", "dom"], + "outDir": "dist", + "jsx": "react", + "declaration": true, + "experimentalDecorators": true, + "importHelpers": true, + "noUnusedLocals": true, + "preserveConstEnums": true, + "types": ["jest", "custom-global", "inline-style-expand-shorthand", "storybook__addons"], + "baseUrl": ".", + "paths": { + "@fluentui/*": ["dist/*/src/index.d.ts"] + } + } + } + } } diff --git a/scripts/tasks/api-extractor.ts b/scripts/tasks/api-extractor.ts index cd535ecbbdf395..2d30e3575aaee6 100644 --- a/scripts/tasks/api-extractor.ts +++ b/scripts/tasks/api-extractor.ts @@ -1,6 +1,8 @@ +import fs from 'fs'; import * as glob from 'glob'; import * as path from 'path'; -import { apiExtractorVerifyTask, task, series } from 'just-scripts'; +import jju from 'jju'; +import { apiExtractorVerifyTask, task, series, resolveCwd, logger, TscTaskOptions } from 'just-scripts'; const apiExtractorConfigs = glob .sync(path.join(process.cwd(), 'config/api-extractor*.json')) @@ -14,10 +16,79 @@ export function apiExtractor() { return apiExtractorConfigs.length ? series( ...apiExtractorConfigs.map(([configPath, configName]) => { + // note we have `"strictNullChecks": false,` turned off - so from TS point of view this always returns API 🚨 + const overrideApi = overrideExtractorConfigForPackagesWithTsPathAliases({ + apiExtractorConfigPath: configPath, + tsConfigPath: resolveCwd('./tsconfig.json'), + }); + const taskName = `api-extractor:${configName}`; - task(taskName, apiExtractorVerifyTask({ configJsonFilePath: configPath, localBuild })); + + task( + taskName, + series( + () => { + overrideApi && overrideApi.overrideConfig(); + }, + apiExtractorVerifyTask({ configJsonFilePath: configPath, localBuild }), + () => { + overrideApi && overrideApi.resetConfig(); + }, + ), + ); + return taskName; }), ) : 'no-op'; } + +interface TsConfig { + extends?: string; + + /** + * typescript doesn't provide a correct type for the compiler options file + * -> (typescript.CompilerOptions has enum values instead of raw options in some cases) + */ + compilerOptions: TscTaskOptions; + include?: string[]; + exclude?: string[]; +} + +function overrideExtractorConfigForPackagesWithTsPathAliases(options: { + tsConfigPath: string; + apiExtractorConfigPath: string; +}) { + const tsConfig: TsConfig = jju.parse(fs.readFileSync(options.tsConfigPath, 'utf-8')); + const overriddenTsConfig = { ...tsConfig }; + const shouldOverrideConfig = Boolean(overriddenTsConfig.extends); + + if (!shouldOverrideConfig) { + return null; + } + + logger.info(`📣 API-EXTRACTOR: package is using TS path aliases. Overriding ts compiler settings for api-extractor.`); + + const originalContent = fs.readFileSync(options.apiExtractorConfigPath, 'utf-8'); + const apiExtractorConfigOriginal = jju.parse(originalContent, { mode: 'json' }); + + overriddenTsConfig.compilerOptions.baseUrl = '.'; + apiExtractorConfigOriginal.compiler = { + overrideTsconfig: overriddenTsConfig, + }; + + console.log({ apiExtractorConfigOriginal }); + + const api = { + overrideConfig: () => { + const newContent = jju.update(originalContent, apiExtractorConfigOriginal, { mode: 'json', indent: 2 }); + + fs.writeFileSync(options.apiExtractorConfigPath, newContent, 'utf-8'); + }, + resetConfig: () => { + fs.writeFileSync(options.apiExtractorConfigPath, originalContent, 'utf-8'); + }, + }; + + return api; +}