Skip to content

Commit bf8514e

Browse files
authored
Reexport management example (#41)
* . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * . * Automated pre-commit update --------- Co-authored-by: kopekC <28070492+kopekC@users.noreply.github.com>
1 parent 367a72e commit bf8514e

File tree

12 files changed

+364
-0
lines changed

12 files changed

+364
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Transform Module Re-exports Organization
2+
3+
This example demonstrates how to use Codegen to automatically analyze and reorganize TypeScript module re-exports through shared directories. The script makes this process simple by handling all the tedious manual updates automatically.
4+
5+
> [!NOTE]
6+
> This codemod helps maintain clean module boundaries and improves code organization by centralizing shared exports.
7+
8+
## How the Migration Script Works
9+
10+
The script automates the entire reorganization process in a few key steps:
11+
12+
1. **Export Analysis**
13+
```python
14+
for export_stmt in file.export_statements:
15+
for export in export_stmt.exports:
16+
if export.is_reexport() and not export.is_external_export:
17+
all_reexports.append(export)
18+
```
19+
- Automatically identifies re-exports in shared directories
20+
- Analyzes export patterns and dependencies
21+
- Uses Codegen's intelligent code analysis engine
22+
23+
2. **Shared File Management**
24+
```python
25+
resolved_public_file = export.resolved_symbol.filepath.replace("src/", "src/shared/")
26+
if not codebase.has_file(resolved_public_file):
27+
target_file = codebase.create_file(resolved_public_file, sync=True)
28+
```
29+
- Creates or updates shared export files
30+
- Maintains proper file structure
31+
- Handles path resolution automatically
32+
33+
3. **Import Updates**
34+
```python
35+
# Updates imports to use new shared paths
36+
new_path = usage.file.ts_config.translate_import_path(resolved_public_file)
37+
new_import = f'import {{ {name} }} from "{new_path}"'
38+
```
39+
- Updates all import statements to use new paths
40+
- Maintains proper TypeScript path resolution
41+
- Handles different import types (normal, type)
42+
43+
## Why This Makes Organization Easy
44+
45+
1. **Zero Manual Updates**
46+
- Codegen SDK handles all file creation and updates
47+
- No tedious export management
48+
49+
2. **Consistent Structure**
50+
- Ensures all shared exports follow the same pattern
51+
- Maintains clean module boundaries
52+
53+
3. **Safe Transformations**
54+
- Validates changes before applying them
55+
- Preserves existing functionality
56+
57+
## Common Re-export Patterns
58+
59+
### Module to Shared Exports
60+
```typescript
61+
// Before: Direct module import
62+
import { validateEmail } from '../module_a/src/functions';
63+
64+
// After: Import through shared
65+
import { validateEmail } from '../module_a/src/shared';
66+
```
67+
68+
### Export Consolidation
69+
```typescript
70+
// Before: Multiple export files
71+
export { foo } from './foo';
72+
export { bar } from './bar';
73+
74+
// After: Consolidated in shared
75+
export * from '../functions';
76+
```
77+
78+
## Key Benefits to Note
79+
80+
1. **Better Module Boundaries**
81+
- Clear public API for each module
82+
- Centralized shared functionality
83+
84+
2. **Improved Maintainability**
85+
- Easier to track dependencies
86+
- Simplified import paths
87+
88+
3. **Code Organization**
89+
- Consistent export structure
90+
- Reduced import complexity
91+
92+
93+
The script will:
94+
1. 🎯 Start the reexport organization
95+
2. 📁 Analyze shared directories
96+
3. 🔄 Process and update exports
97+
4. ✨ Create shared export files
98+
5. 🧹 Clean up redundant exports
99+
100+
## Learn More
101+
102+
- [TypeScript Modules](https://www.typescriptlang.org/docs/handbook/modules.html)
103+
- [Export/Import Documentation](https://www.typescriptlang.org/docs/handbook/modules.html#export)
104+
- [Codegen Documentation](https://docs.codegen.com)
105+
- [Tutorial on Analyzing and Organizing Re-exports](https://docs.codegen.com/tutorials/managing-typescript-exports)
106+
- [More on exports ](https://docs.codegen.com/building-with-codegen/exports)
107+
## Contributing
108+
109+
Feel free to submit issues and enhancement requests!
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export const calculateSum = (a: number, b: number): number => {
2+
return a + b;
3+
};
4+
5+
export const formatName = (firstName: string, lastName: string): string => {
6+
return `${firstName} ${lastName}`;
7+
};
8+
9+
export const generateId = (): string => {
10+
return Math.random().toString(36).substring(7);
11+
};
12+
13+
export const validateEmail = (email: string): boolean => {
14+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
15+
return emailRegex.test(email);
16+
};
17+
18+
export const capitalize = (str: string): string => {
19+
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
20+
};

examples/reexport_management/input_repo/modules/module_a/src/shared/index.ts

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { calculateSum, formatName, capitalize } from '../module_a/src/functions';
2+
export { validateEmail } from '../module_c/src/shared/symbols/exports';
3+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { calculateSum, formatName, capitalize, validateEmail } from './shared/exports';
2+
3+
export const calculateAverage = (numbers: number[]): number => {
4+
const sum = numbers.reduce((acc, curr) => calculateSum(acc, curr), 0);
5+
return sum / numbers.length;
6+
};
7+
8+
export const createUserProfile = (firstName: string, lastName: string): string => {
9+
const formattedName = formatName(firstName, lastName);
10+
return `Profile: ${formattedName}`;
11+
};
12+
13+
export const formatText = (text: string): string => {
14+
return text.split(' ').map(capitalize).join(' ');
15+
};
16+
17+
export const multiply = (a: number, b: number): number => {
18+
return a * b;
19+
};
20+
21+
export const generateGreeting = (name: string): string => {
22+
const email = validateEmail(name);
23+
return `Hello, ${capitalize(name)}!`;
24+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { calculateSum, formatName, capitalize } from "../../imports";
2+
export {validateEmail} from "../../imports"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { validateEmail, generateId } from '../module_a/src/functions';
2+
export { calculateAverage, multiply, createUserProfile } from '../module_b/src/functions';
3+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { validateEmail, generateId, calculateAverage, multiply, createUserProfile } from './shared/symbols/exports';
2+
3+
export const createUser = (email: string, firstName: string, lastName: string) => {
4+
if (!validateEmail(email)) {
5+
throw new Error('Invalid email');
6+
}
7+
8+
return {
9+
id: generateId(),
10+
profile: createUserProfile(firstName, lastName),
11+
email
12+
};
13+
};
14+
15+
export const calculateMetrics = (values: number[]): { average: number; scaled: number[] } => {
16+
const avg = calculateAverage(values);
17+
const scaled = values.map(v => multiply(v, 2));
18+
return { average: avg, scaled };
19+
};
20+
21+
export const validateAndFormatUser = (email: string, firstName: string, lastName: string) => {
22+
if (!validateEmail(email)) {
23+
return { success: false, message: 'Invalid email' };
24+
}
25+
26+
const profile = createUserProfile(firstName, lastName);
27+
return { success: true, profile };
28+
};
29+
30+
export const processNumbers = (numbers: number[]): number => {
31+
const { average } = calculateMetrics(numbers);
32+
return multiply(average, 100);
33+
};
34+
35+
export const generateReport = (userData: { email: string; name: string }): string => {
36+
const isValidEmail = validateEmail(userData.email);
37+
const id = generateId();
38+
return `Report ${id}: Email ${isValidEmail ? 'valid' : 'invalid'} - ${userData.name}`;
39+
};
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { validateEmail, generateId } from '../../../imports'
2+
export { calculateAverage, multiply, createUserProfile } from '../../../imports'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "default-exports-test",
3+
"version": "1.0.0",
4+
"description": "Test codebase for converting default exports",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [],
10+
"author": "",
11+
"license": "ISC",
12+
"devDependencies": {
13+
"typescript": "^5.0.0"
14+
}
15+
}

0 commit comments

Comments
 (0)