diff --git a/docs/scripts/formattedTSDemos.js b/docs/scripts/formattedTSDemos.js index 5bfa845c3432d2..a5a2644c500491 100644 --- a/docs/scripts/formattedTSDemos.js +++ b/docs/scripts/formattedTSDemos.js @@ -136,7 +136,6 @@ async function transpileFile(tsxPath, project) { async function main(argv) { const { watch: watchMode, disableCache, pattern } = argv; - const buildProject = createTypescriptProjectBuilder(CORE_TYPESCRIPT_PROJECTS); // TODO: Remove at some point. // Though not too soon so that it isn't disruptive. @@ -157,7 +156,8 @@ async function main(argv) { ...(await getFiles(path.join(workspaceRoot, 'docs/data'))), // new structure ].filter((fileName) => filePattern.test(fileName)); - const project = buildProject('docs'); + const buildProject = createTypescriptProjectBuilder(CORE_TYPESCRIPT_PROJECTS); + const project = buildProject('docs', { files: tsxFiles }); let successful = 0; let failed = 0; diff --git a/packages/api-docs-builder/buildApi.ts b/packages/api-docs-builder/buildApi.ts index eb8da0cb0cd1f8..3d4d6b92e7697b 100644 --- a/packages/api-docs-builder/buildApi.ts +++ b/packages/api-docs-builder/buildApi.ts @@ -164,7 +164,7 @@ async function run(argv: yargs.ArgumentsCamelCase) { let allBuilds: Array> = []; await SETTINGS.reduce(async (resolvedPromise, setting) => { await resolvedPromise; - const projects = setting.typeScriptProjects.map(buildTypeScriptProject); + const projects = setting.typeScriptProjects.map((project) => buildTypeScriptProject(project)); const apiPagesManifestPath = setting.output.apiManifestPath; const manifestDir = apiPagesManifestPath.match(/(.*)\/[^/]+\./)?.[1]; diff --git a/packages/api-docs-builder/utils/createTypeScriptProject.ts b/packages/api-docs-builder/utils/createTypeScriptProject.ts index 933e93708ec856..eb8fa737397382 100644 --- a/packages/api-docs-builder/utils/createTypeScriptProject.ts +++ b/packages/api-docs-builder/utils/createTypeScriptProject.ts @@ -25,6 +25,11 @@ export interface CreateTypeScriptProjectOptions { * The path must be relative to the root path. */ entryPointPath?: string; + /** + * Files to include in the project. + * By default, it will use the files defined in the tsconfig. + */ + files?: string[]; } export const createTypeScriptProject = ( @@ -35,6 +40,7 @@ export const createTypeScriptProject = ( rootPath, tsConfigPath: inputTsConfigPath = 'tsconfig.build.json', entryPointPath: inputEntryPointPath, + files, } = options; const tsConfigPath = path.join(rootPath, inputTsConfigPath); @@ -65,7 +71,7 @@ export const createTypeScriptProject = ( } const program = ts.createProgram({ - rootNames: tsConfigFileContent.fileNames, + rootNames: files ?? tsConfigFileContent.fileNames, options: tsConfigFileContent.options, }); @@ -99,7 +105,7 @@ export const createTypescriptProjectBuilder =

( ) => { const projects = new Map(); - return (projectName: P) => { + return (projectName: P, options: { files?: string[] } = {}) => { const cachedProject = projects.get(projectName); if (cachedProject != null) { return cachedProject; @@ -111,6 +117,7 @@ export const createTypescriptProjectBuilder =

( const project = createTypeScriptProject({ name: projectName, ...projectsConfig[projectName], + ...options, }); projects.set(projectName, project); diff --git a/packages/typescript-to-proptypes/src/generatePropTypes.ts b/packages/typescript-to-proptypes/src/generatePropTypes.ts index 8b85af8c91c380..004fbb17ab1416 100644 --- a/packages/typescript-to-proptypes/src/generatePropTypes.ts +++ b/packages/typescript-to-proptypes/src/generatePropTypes.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; import { PropTypeDefinition, PropTypesComponent, PropType, LiteralType } from './models'; import { createDOMElementType, createBooleanType, uniqueUnionTypes } from './createType'; -export interface GenerateOptions { +export interface GeneratePropTypesOptions { /** * If source itself written in typescript prop-types disable prop-types validation * by injecting propTypes as @@ -99,7 +99,7 @@ function defaultSortLiteralUnions(a: LiteralType, b: LiteralType) { */ export function generatePropTypes( component: PropTypesComponent, - options: GenerateOptions = {}, + options: GeneratePropTypesOptions = {}, ): string { const { disablePropTypesTypeChecking = false, diff --git a/packages/typescript-to-proptypes/src/index.ts b/packages/typescript-to-proptypes/src/index.ts index e6cc055f53b1d6..0431fe53ca7658 100644 --- a/packages/typescript-to-proptypes/src/index.ts +++ b/packages/typescript-to-proptypes/src/index.ts @@ -1,3 +1,6 @@ export { getPropTypesFromFile } from './getPropTypesFromFile'; +export type { GetPropTypesFromFileOptions } from './getPropTypesFromFile'; export { injectPropTypesInFile } from './injectPropTypesInFile'; export type { InjectPropTypesInFileOptions } from './injectPropTypesInFile'; +export { generatePropTypes } from './generatePropTypes'; +export type { GeneratePropTypesOptions } from './generatePropTypes'; diff --git a/packages/typescript-to-proptypes/src/injectPropTypesInFile.ts b/packages/typescript-to-proptypes/src/injectPropTypesInFile.ts index 22f5cd86c78d42..2aaaa6baae0eec 100644 --- a/packages/typescript-to-proptypes/src/injectPropTypesInFile.ts +++ b/packages/typescript-to-proptypes/src/injectPropTypesInFile.ts @@ -1,12 +1,12 @@ import * as babel from '@babel/core'; import * as babelTypes from '@babel/types'; import { v4 as uuid } from 'uuid'; -import { generatePropTypes, GenerateOptions } from './generatePropTypes'; +import { generatePropTypes, GeneratePropTypesOptions } from './generatePropTypes'; import { PropTypesComponent, PropTypeDefinition, LiteralType } from './models'; export interface InjectPropTypesInFileOptions extends Pick< - GenerateOptions, + GeneratePropTypesOptions, | 'sortProptypes' | 'includeJSDoc' | 'comment' diff --git a/packages/typescript-to-proptypes/test/types.d.ts b/packages/typescript-to-proptypes/test/types.d.ts index 16200bbc2e8177..27694d0f5754bc 100644 --- a/packages/typescript-to-proptypes/test/types.d.ts +++ b/packages/typescript-to-proptypes/test/types.d.ts @@ -1,7 +1,11 @@ -import { ParserOptions, GenerateOptions, InjectOptions } from '../src'; +import { + InjectPropTypesInFileOptions, + GetPropTypesFromFileOptions, + GeneratePropTypesOptions, +} from '../src'; export type TestOptions = { - parser?: Partial; - generator?: Partial; - injector?: Partial; + parser?: GetPropTypesFromFileOptions; + generator?: GeneratePropTypesOptions; + injector?: InjectPropTypesInFileOptions; }; diff --git a/packages/typescript-to-proptypes/test/typescript-to-proptypes.test.ts b/packages/typescript-to-proptypes/test/typescript-to-proptypes.test.ts index c077086b6ab127..822d9dd5682a29 100644 --- a/packages/typescript-to-proptypes/test/typescript-to-proptypes.test.ts +++ b/packages/typescript-to-proptypes/test/typescript-to-proptypes.test.ts @@ -1,9 +1,16 @@ import path from 'path'; import fs from 'fs'; +import * as ts from 'typescript'; import { expect } from 'chai'; import glob from 'fast-glob'; import prettier from 'prettier'; -import * as ttp from '../src'; +import { + TypeScriptProject, + createTypescriptProjectBuilder, +} from '@mui-internal/api-docs-builder/utils/createTypeScriptProject'; +import { generatePropTypes } from '../src/generatePropTypes'; +import { injectPropTypesInFile } from '../src/injectPropTypesInFile'; +import { getPropTypesFromFile } from '../src/getPropTypesFromFile'; import { TestOptions } from './types'; const testCases = glob @@ -23,26 +30,38 @@ const testCases = glob }); describe('typescript-to-proptypes', () => { - let cachedProgram: ttp.ts.Program; - function getProgram() { - return cachedProgram; + let cachedProject: TypeScriptProject; + function getProject() { + return cachedProject; } before(function beforeHook() { // Creating a TS program might take a while. this.timeout(20000); + + const buildProject = createTypescriptProjectBuilder({ + test: { + rootPath: path.join(__dirname, '..'), + tsConfigPath: 'tsconfig.json', + }, + }); + + cachedProject = buildProject('test', { + files: testCases.map((testCase) => testCase.inputPath), + }); + // Create program for all files to speed up tests - cachedProgram = ttp.createTSProgram( - testCases.map((testCase) => testCase.inputPath), - ttp.loadConfig(path.resolve(__dirname, '../tsconfig.json')), - ); + // cachedProject = ttp.createTSProgram( + // testCases.map((testCase) => testCase.inputPath), + // ttp.loadConfig(path.resolve(__dirname, '../tsconfig.json')), + // ); }); testCases.forEach((testCase) => { const { name: testName, inputPath, inputJS, outputPath } = testCase; it(testName, async () => { - const program = getProgram(); + const project = getProject(); let options: TestOptions = {}; try { const optionsModule = await import(`./${testName}/options`); @@ -51,7 +70,7 @@ describe('typescript-to-proptypes', () => { // Assume "Cannot find module" which means "no options". } - const ast = ttp.parseFromProgram(inputPath, program, options.parser); + const components = getPropTypesFromFile({ filePath: inputPath, project, ...options.parser }); let inputSource = null; if (inputPath.endsWith('.d.ts')) { @@ -61,10 +80,10 @@ describe('typescript-to-proptypes', () => { // ignore } } else { - inputSource = ttp.ts.transpileModule(fs.readFileSync(inputPath, 'utf8'), { + inputSource = ts.transpileModule(fs.readFileSync(inputPath, 'utf8'), { compilerOptions: { - target: ttp.ts.ScriptTarget.ESNext, - jsx: ttp.ts.JsxEmit.Preserve, + target: ts.ScriptTarget.ESNext, + jsx: ts.JsxEmit.Preserve, }, }).outputText; } @@ -72,14 +91,18 @@ describe('typescript-to-proptypes', () => { let result = ''; // For d.ts files we just generate the AST if (!inputSource) { - result = ast.body + result = components .map((component) => { - return ttp.generate(component, options.generator); + return generatePropTypes(component, options.generator); }) .join('\n'); } else { // For .tsx? files we transpile them and inject the proptypes - const injected = ttp.inject(ast, inputSource, options.injector); + const injected = injectPropTypesInFile({ + components, + target: inputSource, + options: options.injector, + }); if (!injected) { throw new Error('Injection failed'); }