feat: extend TD pipeline to analyze @patternfly/react-styles utility class modules #5

Open
opened 2026-04-07 10:04:50 -04:00 by shawn_hurley · 0 comments
Owner

Problem
@patternfly/react-styles exports CSS utility class mappings via deep import paths (e.g., @patternfly/react-styles/css/utilities/Alignment/alignment). These are JS objects that map property names to CSS class names:
// v5
declare const _default: {
textAlignRight: string;
textAlignLeft: string;
textAlignCenter: string;
};
In PFv6, several property names changed (e.g., textAlignRight → textAlignEnd for CSS logical properties). The semver-analyzer does not detect these changes because @patternfly/react-styles is not in the analyzed package set.
Consumer code using these utilities breaks silently at runtime — alignment.textAlignRight returns undefined instead of a CSS class name.
Why TD Pipeline
This is a TypeScript API surface change — exported object shapes in .d.ts files changed between versions. The TD pipeline (structural API diff) is the architecturally correct place to detect renamed/removed/added properties on these exported objects.
Challenges
Three compounding issues make this harder than adding a normal package to the analysis:

  1. Package not in analysis scope — react-styles is not in the --packages list. Need to add it, but the main entry point (src/index.ts) only exports css() — the utility modules aren't reachable from it.
  2. Deep import paths — Utilities are at paths like css/utilities/Alignment/alignment, not re-exported from index.ts. The filter_to_reachable() step in crates/ts/src/extract/mod.rs:424 traces the re-export graph from entry points and would filter these out.
  3. Generated build artifacts — The .d.ts files are generated by packages/react-styles/scripts/writeClassMaps.mjs during yarn build:generate, not by tsc --declaration. The analyzer would need to either:
    • Run the build step at each git ref before extraction
    • Point at pre-built artifacts
    • Parse the generation script to understand the output shape
      Proposed Approach
      Option A: Add deep-import discovery for react-styles
      Extend the entry-point reachability filter to also discover css/**/*.d.ts modules within react-styles. This would work if the .d.ts files exist in the repo at the analyzed refs (they may be committed or gitignored).
      Steps:
  4. Add @patternfly/react-styles to the analyzed packages
  5. In crates/ts/src/extract/mod.rs, add a fallback discovery path for packages where the entry point doesn't re-export deep modules: glob css/**/*.d.ts and include them as additional entry points
  6. The diff engine would then naturally detect property renames/removals on the default-exported objects
  7. Rule generation would need to handle the deep import path in the from: condition (e.g., from: '@patternfly/react-styles/css/utilities/Alignment/alignment')
    Option B: Dedicated react-styles extractor
    Build a lighter-weight extractor specifically for react-styles CSS module .d.ts files:
  8. Glob packages/react-styles/css/**/*.d.ts at both refs
  9. Parse the default export object shapes (property names)
  10. Diff the property sets per module
  11. Feed results into the existing rule generation pipeline
    This is simpler but less general.
    Impact
  • textAlignRight → textAlignEnd (and likely other utility class renames) would be detected
  • Rules would match import alignment from '@patternfly/react-styles/css/utilities/Alignment/alignment' and flag alignment.textAlignRight usage
  • The BEM analysis in the SD pipeline already parses these imports (source_profile/bem.rs), so the rule matcher infrastructure partially exists
    Context
    Discovered during tackle2-ui migration analysis. The issue was initially classified as "analysis-scope gap" in the diagnostic session. The SD pipeline already recognizes react-styles imports for BEM block extraction but doesn't diff the utility class shapes.
    Related: hack/integration/patternfly-token-mappings.yaml handles a similar case for @patternfly/react-tokens via a curated mapping file. A similar approach could be used as an interim solution before the full TD pipeline extension.
Problem @patternfly/react-styles exports CSS utility class mappings via deep import paths (e.g., @patternfly/react-styles/css/utilities/Alignment/alignment). These are JS objects that map property names to CSS class names: // v5 declare const _default: { textAlignRight: string; textAlignLeft: string; textAlignCenter: string; }; In PFv6, several property names changed (e.g., textAlignRight → textAlignEnd for CSS logical properties). The semver-analyzer does not detect these changes because @patternfly/react-styles is not in the analyzed package set. Consumer code using these utilities breaks silently at runtime — alignment.textAlignRight returns undefined instead of a CSS class name. Why TD Pipeline This is a TypeScript API surface change — exported object shapes in .d.ts files changed between versions. The TD pipeline (structural API diff) is the architecturally correct place to detect renamed/removed/added properties on these exported objects. Challenges Three compounding issues make this harder than adding a normal package to the analysis: 1. Package not in analysis scope — react-styles is not in the --packages list. Need to add it, but the main entry point (src/index.ts) only exports css() — the utility modules aren't reachable from it. 2. Deep import paths — Utilities are at paths like css/utilities/Alignment/alignment, not re-exported from index.ts. The filter_to_reachable() step in crates/ts/src/extract/mod.rs:424 traces the re-export graph from entry points and would filter these out. 3. Generated build artifacts — The .d.ts files are generated by packages/react-styles/scripts/writeClassMaps.mjs during yarn build:generate, not by tsc --declaration. The analyzer would need to either: - Run the build step at each git ref before extraction - Point at pre-built artifacts - Parse the generation script to understand the output shape Proposed Approach Option A: Add deep-import discovery for react-styles Extend the entry-point reachability filter to also discover css/**/*.d.ts modules within react-styles. This would work if the .d.ts files exist in the repo at the analyzed refs (they may be committed or gitignored). Steps: 1. Add @patternfly/react-styles to the analyzed packages 2. In crates/ts/src/extract/mod.rs, add a fallback discovery path for packages where the entry point doesn't re-export deep modules: glob css/**/*.d.ts and include them as additional entry points 3. The diff engine would then naturally detect property renames/removals on the default-exported objects 4. Rule generation would need to handle the deep import path in the from: condition (e.g., from: '@patternfly/react-styles/css/utilities/Alignment/alignment') Option B: Dedicated react-styles extractor Build a lighter-weight extractor specifically for react-styles CSS module .d.ts files: 1. Glob packages/react-styles/css/**/*.d.ts at both refs 2. Parse the default export object shapes (property names) 3. Diff the property sets per module 4. Feed results into the existing rule generation pipeline This is simpler but less general. Impact - textAlignRight → textAlignEnd (and likely other utility class renames) would be detected - Rules would match import alignment from '@patternfly/react-styles/css/utilities/Alignment/alignment' and flag alignment.textAlignRight usage - The BEM analysis in the SD pipeline already parses these imports (source_profile/bem.rs), so the rule matcher infrastructure partially exists Context Discovered during tackle2-ui migration analysis. The issue was initially classified as "analysis-scope gap" in the diagnostic session. The SD pipeline already recognizes react-styles imports for BEM block extraction but doesn't diff the utility class shapes. Related: hack/integration/patternfly-token-mappings.yaml handles a similar case for @patternfly/react-tokens via a curated mapping file. A similar approach could be used as an interim solution before the full TD pipeline extension.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
shawn_hurley/semver-analyzer#5
No description provided.