From f21a110bfd5747e8016770b5f32b2ff4543b2466 Mon Sep 17 00:00:00 2001 From: Martin Hochel Date: Tue, 8 Nov 2022 16:59:47 +0100 Subject: [PATCH] feat(scripts): remove @internal stripping and enable no deps build needed for api generation --- .../api-extractor.common.v-next.json | 3 -- scripts/tasks/api-extractor.ts | 1 + scripts/tasks/utils.spec.ts | 52 +++++++++++++++++++ scripts/tasks/utils.ts | 23 +++++++- .../migrate-converged-pkg/index.spec.ts | 8 +-- .../generators/migrate-converged-pkg/index.ts | 27 +++++----- 6 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 scripts/tasks/utils.spec.ts diff --git a/scripts/api-extractor/api-extractor.common.v-next.json b/scripts/api-extractor/api-extractor.common.v-next.json index 20f98320b8ef71..a144ad306ed500 100644 --- a/scripts/api-extractor/api-extractor.common.v-next.json +++ b/scripts/api-extractor/api-extractor.common.v-next.json @@ -9,10 +9,7 @@ }, "dtsRollup": { "enabled": true, - // TODO: replace following line with these 2 commented ones after all v9 is migrated to new build and .d.ts API stripping "untrimmedFilePath": "/dist/index.d.ts", - // "untrimmedFilePath": "/dist/untrimmed.d.ts", - // "publicTrimmedFilePath": "/dist/index.d.ts", "omitTrimmingComments": false }, "compiler": { diff --git a/scripts/tasks/api-extractor.ts b/scripts/tasks/api-extractor.ts index 00bb6182ad4881..68ae9021cfde9f 100644 --- a/scripts/tasks/api-extractor.ts +++ b/scripts/tasks/api-extractor.ts @@ -147,6 +147,7 @@ export function apiExtractor() { tsConfig, tsConfigPath, packageJson, + definitionsRootPath: 'dist/out-tsc/types', }); config.compiler = compilerConfig; diff --git a/scripts/tasks/utils.spec.ts b/scripts/tasks/utils.spec.ts new file mode 100644 index 00000000000000..60bf26d83cd168 --- /dev/null +++ b/scripts/tasks/utils.spec.ts @@ -0,0 +1,52 @@ +import { getTsPathAliasesApiExtractorConfig } from './utils'; + +type DeepPartial = Partial<{ [P in keyof T]: DeepPartial }>; +describe(`utils`, () => { + describe(`#getTsPathAliasesApiExtractorConfig`, () => { + type Options = Parameters[0]; + function setup(options: DeepPartial = {}) { + const defaults = { + tsConfig: { + compilerOptions: { + ...options.tsConfig?.compilerOptions, + }, + }, + tsConfigPath: 'tsconfig.lib.json', + packageJson: { + name: '@proj/one', + version: '0.0.1', + main: 'lib/index.js', + dependencies: { ...options.packageJson?.dependencies }, + peerDependencies: { ...options.packageJson?.peerDependencies }, + }, + definitionsRootPath: options.definitionsRootPath ?? 'dist/types', + }; + + return getTsPathAliasesApiExtractorConfig(defaults as Options); + } + + it(`should set compilerOptions`, () => { + const actual = setup(); + + expect(actual.overrideTsconfig.compilerOptions).toEqual( + expect.objectContaining({ isolatedModules: false, skipLibCheck: false }), + ); + }); + + it(`should override path aliases to emitted declaration files instead of source files`, () => { + const actual = setup({ definitionsRootPath: 'dist/for/types' }); + + const newPaths = (actual.overrideTsconfig.compilerOptions.paths as unknown) as Record; + + const newPath = Object.values(newPaths)[0][0]; + expect(newPath).toMatch(new RegExp('^dist/for/types.+src/index.d.ts$', 'i')); + }); + + it(`should set allowSyntheticDefaultImports if package has invalid deps/peerDeps`, () => { + const actual = setup({ packageJson: { dependencies: { '@storybook/api': '6.5.0' } } }); + expect(actual.overrideTsconfig.compilerOptions).toEqual( + expect.objectContaining({ allowSyntheticDefaultImports: true }), + ); + }); + }); +}); diff --git a/scripts/tasks/utils.ts b/scripts/tasks/utils.ts index 66214acb223424..fcf640a97aed2a 100644 --- a/scripts/tasks/utils.ts +++ b/scripts/tasks/utils.ts @@ -39,18 +39,36 @@ function enableAllowSyntheticDefaultImports(options: { pkgJson: PackageJson }) { return shouldEnable ? { allowSyntheticDefaultImports: true } : null; } +const rootTsConfig = JSON.parse( + fs.readFileSync(path.resolve(__dirname, '../../tsconfig.base.json'), 'utf-8'), +) as TsConfig; + +function createNormalizedTsPaths(options: { definitionsRootPath: string; rootTsConfig: TsConfig }) { + const paths = (options.rootTsConfig.compilerOptions.paths as unknown) as Record; + + const normalizedPaths = Object.entries(paths).reduce((acc, [pkgName, pathAliases]) => { + acc[pkgName] = [path.join(options.definitionsRootPath, pathAliases[0].replace('index.ts', 'index.d.ts'))]; + return acc; + }, {} as typeof paths); + + return normalizedPaths; +} + export function getTsPathAliasesApiExtractorConfig(options: { tsConfig: TsConfig; tsConfigPath: string; packageJson: PackageJson; + definitionsRootPath: string; }) { + const normalizedPaths = createNormalizedTsPaths({ definitionsRootPath: options.definitionsRootPath, rootTsConfig }); + /** * Customized TSConfig that uses `tsconfig.lib.json` as base with some required overrides: * * NOTES: * - `extends` is properly resolved via api-extractor which uses TS api * - `skipLibCheck` needs to be explicitly set to `false` so errors propagate to api-extractor - * - `paths` is set to `undefined` so api-extractor won't use source files rather rollup-ed declaration files only + * - `paths` is overriden to path mapping that points to generated declaration files. This also enables creation of dts rollup without a need of generating rollups for all dependencies 🫡 * */ const apiExtractorTsConfig: TsConfig = { @@ -71,7 +89,8 @@ export function getTsPathAliasesApiExtractorConfig(options: { /** * just-scripts provides invalid types for tsconfig, thus `paths` cannot be set to dictionary,nor null or `{}` */ - paths: undefined, + // @ts-expect-error - just-scripts provides invalid types + paths: normalizedPaths, }, }; diff --git a/tools/generators/migrate-converged-pkg/index.spec.ts b/tools/generators/migrate-converged-pkg/index.spec.ts index 0e0cd016a6fcba..c38709d931160a 100644 --- a/tools/generators/migrate-converged-pkg/index.spec.ts +++ b/tools/generators/migrate-converged-pkg/index.spec.ts @@ -853,11 +853,6 @@ describe('migrate-converged-pkg generator', () => { expect(readJson(tree, apiExtractorConfigPath)).toMatchInlineSnapshot(` Object { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "dtsRollup": Object { - "enabled": true, - "publicTrimmedFilePath": "/dist/index.d.ts", - "untrimmedFilePath": "", - }, "extends": "@fluentui/scripts/api-extractor/api-extractor.common.v-next.json", } `); @@ -1493,8 +1488,7 @@ describe('migrate-converged-pkg generator', () => { }, "dtsRollup": Object { "enabled": true, - "publicTrimmedFilePath": "/dist/unstable.d.ts", - "untrimmedFilePath": "/dist/unstable-untrimmed.d.ts", + "untrimmedFilePath": "/dist/unstable.d.ts", }, "extends": "@fluentui/scripts/api-extractor/api-extractor.common.v-next.json", "mainEntryPointFilePath": "/../../../dist/out-tsc/types/packages/react-components//src/unstable/index.d.ts", diff --git a/tools/generators/migrate-converged-pkg/index.ts b/tools/generators/migrate-converged-pkg/index.ts index 21d1cd3bf3800d..7f8f7983c49531 100644 --- a/tools/generators/migrate-converged-pkg/index.ts +++ b/tools/generators/migrate-converged-pkg/index.ts @@ -130,7 +130,7 @@ function runMigrationOnProject(tree: Tree, schema: AssertedSchema, _userLog: Use // update package npm scripts updatePackageJson(tree, optionsWithTsConfigs); - updateApiExtractorForLocalBuilds(tree, optionsWithTsConfigs); + updateApiExtractor(tree, optionsWithTsConfigs); // setup storybook setupStorybook(tree, options); @@ -155,12 +155,6 @@ const templates = { main: { $schema: 'https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json', extends: '@fluentui/scripts/api-extractor/api-extractor.common.v-next.json', - // TODO: remove after all v9 is migrated to new build and .d.ts API stripping - dtsRollup: { - enabled: true, - untrimmedFilePath: '', - publicTrimmedFilePath: '/dist/index.d.ts', - }, }, unstable: { $schema: 'https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json', @@ -174,8 +168,7 @@ const templates = { }, dtsRollup: { enabled: true, - untrimmedFilePath: '/dist/unstable-untrimmed.d.ts', - publicTrimmedFilePath: '/dist/unstable.d.ts', + untrimmedFilePath: '/dist/unstable.d.ts', }, }, }; @@ -576,11 +569,11 @@ function setupUnstableApi(tree: Tree, options: NormalizedSchemaWithTsConfigs) { } updateUnstablePackageJson(); - updateUnstableApiExtractorForLocalBuilds(); + updateUnstableApiExtractor(); return tree; - function updateUnstableApiExtractorForLocalBuilds() { + function updateUnstableApiExtractor() { const apiExtractor = templates.apiExtractor(); writeJson(tree, joinPathFragments(options.paths.configRoot, 'api-extractor.unstable.json'), apiExtractor.unstable); @@ -646,7 +639,6 @@ function updatePackageJson(tree: Tree, options: NormalizedSchemaWithTsConfigs) { function setupScripts(json: PackageJson) { const scripts = { - 'generate-api': 'tsc -p ./tsconfig.lib.json --emitDeclarationOnly && just-scripts api-extractor', test: 'jest --passWithNoTests', 'type-check': 'tsc -b tsconfig.json', }; @@ -686,12 +678,21 @@ function updatePackageJson(tree: Tree, options: NormalizedSchemaWithTsConfigs) { } } -function updateApiExtractorForLocalBuilds(tree: Tree, options: NormalizedSchemaWithTsConfigs) { +function updateApiExtractor(tree: Tree, options: NormalizedSchemaWithTsConfigs) { const apiExtractor = templates.apiExtractor(); + const scripts = { + 'generate-api': 'tsc -p ./tsconfig.lib.json --emitDeclarationOnly && just-scripts api-extractor', + }; tree.delete(joinPathFragments(options.paths.configRoot, 'api-extractor.local.json')); writeJson(tree, joinPathFragments(options.paths.configRoot, 'api-extractor.json'), apiExtractor.main); + updateJson(tree, options.paths.packageJson, (json: PackageJson) => { + Object.assign(json.scripts, scripts); + + return json; + }); + return tree; }