rushstack icon indicating copy to clipboard operation
rushstack copied to clipboard

[node-core-library] Refactor Text static class to module namespace object for tree-shaking

Open Copilot opened this issue 3 months ago • 0 comments

✅ Refactor Text static class to module namespace object pattern

This PR successfully refactors the Text static class to use the module namespace object pattern (similar to existing Disposables, Objects, and User) for better tree-shaking support by modern bundlers.

Completed Work

Text Refactoring (COMPLETE):

  • [x] Created text/ directory with 13 individual function files
  • [x] Updated Text.ts to re-export from text/index using module namespace pattern
  • [x] Ensured all types/enums (Encoding, NewlineKind, IReadLinesFromIterableOptions) remain accessible
  • [x] Updated test file to use function.name for synchronized test titles
  • [x] Factored out common newline regex helper to reduce duplication
  • [x] Used Symbol.matchAll for proper regex iteration
  • [x] Added module documentation to text/index.ts with @module JSDoc tag
  • [x] All 235 tests passing (0 failures)
  • [x] Build successful with no errors
  • [x] CodeQL security check passed (0 alerts)
  • [x] Removed unrelated FileSystem changes to keep PR focused on Text API only

API Compatibility

Backward compatibility maintained - All consumers continue to use the same API:

// Usage remains identical
import { Text } from '@rushstack/node-core-library';
Text.padEnd('hello', 10);      // Works exactly as before
Text.convertToLf(content);     // Works exactly as before  
Text.escapeRegExp('[test]');   // Works exactly as before

Tree-Shaking Benefits

With this refactoring, bundlers can now tree-shake unused Text functions:

// Before: Importing Text pulls in ALL methods (~293 lines)
import { Text } from '@rushstack/node-core-library';

// After: Bundlers can eliminate unused functions
// Only padEnd() will be included in the final bundle
Text.padEnd('hello', 10);

Recent Updates

  • Created _newlineHelpers.ts to factor out common NEWLINE_REGEX and replace logic
  • Updated convertTo, convertToCrLf, convertToLf to use shared helper
  • Changed readLinesFromIterable.ts to use NEWLINE_REGEX[Symbol.matchAll] instead of .matchAll()
  • Restored use of Text.functionName.name in tests for synchronized test titles
  • Removed fileSystem/errorChecks.ts to keep PR focused on Text API only
  • Preserved original class documentation in text/index.ts with @module tag for module-level documentation
Original prompt

This section details on the original issue you should resolve

<issue_title>[node-core-library] Replace static classes with exported module namespace objects</issue_title> <issue_description>## Summary While preserving the implementations and outward-facing API shape (All consumers of the refactored APIs should not need any code changes to compile and test successfully), replace static classes like:

./FileSystem.ts

export class FileSystem {
  public static someApi(...): TResult { ... }
}

with a reexported module namespace object that forwards individual exports for single files:

./FileSystem.ts

import * as FileSystem from './fileSystem/index';

./fileSystem/index.ts

export { someApi } from './someApi';

./fileSystem/someApi.ts

export function someApi(...): TResult { ... }

The Disposables and Objects APIs are existing examples of the new pattern. FileSystem and Text are examples of the old pattern to be replaced.

The reason for this conversion is that module namespace objects can be tree-shaken by modern bundlers, but static members on classes cannot.

Question Answer
Package name:
Package version?
Operating system?
Would you consider contributing a PR?
Node.js version (node -v)?
</issue_description>

Comments on the Issue (you are @copilot in this section)

  • Fixes microsoft/rushstack#5434

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot avatar Nov 06 '25 20:11 Copilot