From d244e258d74b518a6868a3fb527b80c2715caad9 Mon Sep 17 00:00:00 2001 From: Peter Pal Hudak Date: Tue, 4 Aug 2026 16:53:02 +0200 Subject: [PATCH] chore: replace TypeScript compiler API with jscodeshift in generateVersionedExports - Rewrite parseVersionedComponents() to use jscodeshift AST parsing - Removes hard dependency on ts.ScriptTarget, ts.isExportDeclaration, etc. - Generates byte-identical output; preparation for TypeScript 7 upgrade - TS 7.0+ changes compiler API surface incompatibly; jscodeshift is stable across versions INSTUI-5144 --- .../scripts/generateVersionedExports.ts | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/packages/ui-codemods/scripts/generateVersionedExports.ts b/packages/ui-codemods/scripts/generateVersionedExports.ts index 47f5170431..ba5a05ab84 100644 --- a/packages/ui-codemods/scripts/generateVersionedExports.ts +++ b/packages/ui-codemods/scripts/generateVersionedExports.ts @@ -30,7 +30,7 @@ import { resolve } from 'node:path' import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs' -import ts from 'typescript' +import jscodeshift from 'jscodeshift' // '@instructure/ui-button/v8_0' → matches; '@instructure/ui-button' or 'react' → no match const VERSIONED_INSTUI = /^@instructure\/[^/]+\/v\d+_\d+$/ @@ -62,33 +62,34 @@ function findLatestVersionFile(dir: string): string { return resolve(dir, latest) } -function isVersionedInstUIExport(node: ts.ExportDeclaration): boolean { - const { moduleSpecifier } = node - return ( - moduleSpecifier !== undefined && - ts.isStringLiteral(moduleSpecifier) && - VERSIONED_INSTUI.test(moduleSpecifier.text) - ) -} - -function getExportedNames(node: ts.ExportDeclaration): string[] { - const { exportClause } = node - if (!exportClause || !ts.isNamedExports(exportClause)) return [] - return exportClause.elements.map((el) => el.name.text) -} - function parseVersionedComponents(filePath: string): string[] { const source = readFileSync(filePath, 'utf-8') - const sourceFile = ts.createSourceFile( - filePath, - source, - ts.ScriptTarget.Latest - ) - - return sourceFile.statements - .filter(ts.isExportDeclaration) - .filter(isVersionedInstUIExport) - .flatMap(getExportedNames) + const j = jscodeshift.withParser('ts') + const root = j(source) + const components: string[] = [] + + root.find(j.ExportNamedDeclaration).forEach((path: any) => { + const node = path.value + const source = node.source + + // Check if this is a versioned @instructure/ui import + if ( + source && + source.type === 'StringLiteral' && + VERSIONED_INSTUI.test(source.value) + ) { + // Extract exported names + if (node.specifiers && node.specifiers.length > 0) { + node.specifiers.forEach((spec: any) => { + if (spec.local && spec.local.name) { + components.push(spec.local.name) + } + }) + } + } + }) + + return components } function generateFileContent(components: string[]): string {