Implementing Subpath Exports in TypeScript
Subpath exports are a powerful feature in modern JavaScript and TypeScript that allow you to selectively export specific members from a deeply nested module structure. This improves code organization, reduces bundle size, and enhances maintainability by preventing unnecessary exports. This challenge asks you to implement a function that transforms a standard TypeScript export statement into a subpath export.
Problem Description
You are given a TypeScript export statement represented as a string. This statement can be a standard export statement or a subpath export statement. Your task is to write a function that takes this string as input and transforms it into a subpath export statement if it's a standard export. If the input is already a subpath export, the function should return the input unchanged.
The function should identify standard exports (e.g., export const myVariable = 123; or export function myFunction() { ... }) and convert them into subpath exports using a predefined subpath. The subpath will be a string representing the directory path where the module resides (e.g., "components/utils").
Key Requirements:
- Standard Export Detection: Accurately identify standard export statements.
- Subpath Transformation: Convert standard exports into subpath exports by prepending the subpath to the exported identifier.
- Subpath Export Preservation: Do not modify existing subpath exports.
- String Manipulation: The solution must manipulate the input string to achieve the transformation.
- TypeScript Syntax: The generated subpath exports must be valid TypeScript syntax.
Expected Behavior:
The function should return a string representing the transformed export statement. If the input is already a subpath export, it should return the original string.
Edge Cases to Consider:
- Multiline Exports: Handle export statements that span multiple lines.
- Comments: Ensure comments are preserved correctly.
- Existing Subpath Exports: Recognize and leave unchanged exports that already use subpath syntax (e.g.,
export * as utils from './utils';). - Different Export Types: Handle
export const,export let,export var,export function,export class,export interface,export type,export default,export * as, andexport { ... }statements. - String Literals in Exports: Handle cases where the exported identifier is a string literal.
Examples
Example 1:
Input: "export const myVariable = 123;"
Output: "export const components/utils_myVariable = 123;"
Explanation: The input is a standard export. The function prepends the subpath "components/utils_" to the identifier "myVariable".
Example 2:
Input: "export * as utils from './utils';"
Output: "export * as utils from './utils';"
Explanation: The input is already a subpath export (using `export * as`). The function returns the input unchanged.
Example 3:
Input: "export function myFunction() { console.log('hello'); }"
Output: "export function components/utils_myFunction() { console.log('hello'); }"
Explanation: The input is a standard function export. The function prepends the subpath "components/utils_" to the identifier "myFunction".
Example 4:
Input: "export class MyClass {\n constructor() { }\n}"
Output: "export class components/utils_MyClass {\n constructor() { }\n}"
Explanation: Handles multiline class exports.
Constraints
- The input string will be a valid TypeScript export statement.
- The subpath will be a string of length up to 50 characters.
- The function must handle a reasonable variety of export statement formats.
- The function should be efficient enough to process moderately sized TypeScript files (e.g., up to 1000 lines).
Notes
- Consider using regular expressions to identify and manipulate the export statements.
- Be mindful of preserving whitespace and comments within the export statements.
- The subpath should be prepended to the exported identifier, followed by an underscore (
_). This ensures that the new identifier is unique and avoids potential naming conflicts. - Focus on correctly transforming the identifier part of the export statement, leaving the rest of the statement intact.
- This is a string manipulation problem, not a TypeScript compiler problem. You don't need to parse or generate TypeScript code in a complex way. Simple string replacement is sufficient.