@@ -6,108 +6,89 @@ import * as path from 'node:path';
66import type { IRunScriptOptions } from '@rushstack/heft' ;
77import { Async , FileSystem , type FolderItem , Import , JsonFile , Path } from '@rushstack/node-core-library' ;
88
9- interface IGenerateOptions {
9+ interface IGenerateJsStubsOptions {
1010 parentSourcePath : string ;
11- parentCjsTargetPath : string ;
12- parentDtsTargetPath : string ;
11+ parentTargetPath : string ;
1312 parentSrcImportPathWithSlash : string ;
1413 libShimIndexPath : string ;
1514}
1615
17- interface IFileTask {
18- type : 'dts' | 'js' ;
19- sourcePath : string ;
16+ interface IJsStubTask {
17+ jsSourcePath : string ;
2018 targetPath : string ;
21- srcImportPath ? : string ;
22- shimPathLiteral ? : string ;
19+ srcImportPath : string ;
20+ shimPathLiteral : string ;
2321}
2422
25- async function * collectFileTasksAsync ( options : IGenerateOptions ) : AsyncGenerator < IFileTask > {
26- const {
27- parentSourcePath,
28- parentCjsTargetPath,
29- parentDtsTargetPath,
30- parentSrcImportPathWithSlash,
31- libShimIndexPath
32- } = options ;
33- const folderItems : FolderItem [ ] = await FileSystem . readFolderItemsAsync ( options . parentSourcePath ) ;
23+ /**
24+ * Walks rush-lib/lib-commonjs to collect JS stub tasks. These stubs redirect
25+ * require() calls through the rush-sdk shim so that the actual rush-lib module
26+ * is loaded at runtime.
27+ */
28+ async function * collectJsStubTasksAsync ( options : IGenerateJsStubsOptions ) : AsyncGenerator < IJsStubTask > {
29+ const { parentSourcePath, parentTargetPath, parentSrcImportPathWithSlash, libShimIndexPath } = options ;
30+ const folderItems : FolderItem [ ] = await FileSystem . readFolderItemsAsync ( parentSourcePath ) ;
3431
3532 for ( const folderItem of folderItems ) {
3633 const itemName : string = folderItem . name ;
3734 const sourcePath : string = `${ parentSourcePath } /${ itemName } ` ;
38- const cjsTargetPath : string = `${ parentCjsTargetPath } /${ itemName } ` ;
39- const dtsTargetPath : string = `${ parentDtsTargetPath } /${ itemName } ` ;
35+ const targetPath : string = `${ parentTargetPath } /${ itemName } ` ;
4036
4137 if ( folderItem . isDirectory ( ) ) {
4238 // Ensure destination folder exists
43- await FileSystem . ensureFolderAsync ( cjsTargetPath ) ;
39+ await FileSystem . ensureFolderAsync ( targetPath ) ;
4440 // Recursively yield tasks from subdirectory
45- yield * collectFileTasksAsync ( {
41+ yield * collectJsStubTasksAsync ( {
4642 parentSourcePath : sourcePath ,
47- parentCjsTargetPath : cjsTargetPath ,
48- parentDtsTargetPath : dtsTargetPath ,
43+ parentTargetPath : targetPath ,
4944 parentSrcImportPathWithSlash : parentSrcImportPathWithSlash + itemName + '/' ,
5045 libShimIndexPath
5146 } ) ;
52- } else if ( folderItem . name . endsWith ( '.d.ts' ) ) {
53- yield {
54- type : 'dts' ,
55- sourcePath,
56- targetPath : dtsTargetPath
57- } ;
5847 } else if ( folderItem . name . endsWith ( '.js' ) ) {
5948 const srcImportPath : string = parentSrcImportPathWithSlash + path . parse ( folderItem . name ) . name ;
60- const shimPath : string = path . relative ( parentCjsTargetPath , libShimIndexPath ) ;
49+ const shimPath : string = path . relative ( parentTargetPath , libShimIndexPath ) ;
6150 const shimPathLiteral : string = JSON . stringify ( Path . convertToSlashes ( shimPath ) ) ;
6251
6352 yield {
64- type : 'js' ,
65- sourcePath,
66- targetPath : cjsTargetPath ,
53+ jsSourcePath : sourcePath ,
54+ targetPath,
6755 srcImportPath,
6856 shimPathLiteral
6957 } ;
7058 }
7159 }
7260}
7361
74- async function processFileTaskAsync ( task : IFileTask ) : Promise < void > {
75- const { type, sourcePath, targetPath, srcImportPath, shimPathLiteral } = task ;
76- if ( type === 'dts' ) {
77- await FileSystem . copyFileAsync ( {
78- sourcePath,
79- destinationPath : targetPath
80- } ) ;
81- } else {
82- const srcImportPathLiteral : string = JSON . stringify ( srcImportPath ) ;
83-
84- let namedExportsAssignment : string = '' ;
85- try {
86- // Read the sidecar .exports.json file generated by DeepImportsPlugin to get module exports
87- const exportsJsonPath : string = sourcePath . slice ( 0 , - '.js' . length ) + '.exports.json' ;
88- const { moduleExports } : { moduleExports : string [ ] } = await JsonFile . loadAsync ( exportsJsonPath ) ;
89- if ( moduleExports . length > 0 ) {
90- // Assign named exports after module.exports to ensure they're properly exposed for ESM imports
91- namedExportsAssignment =
92- '\n' + moduleExports . map ( ( exportName ) => `exports.${ exportName } = _m.${ exportName } ;` ) . join ( '\n' ) ;
93- }
94- } catch ( e ) {
95- if ( ! FileSystem . isNotExistError ( e ) ) {
96- throw e ;
97- }
62+ async function processJsStubTaskAsync ( task : IJsStubTask ) : Promise < void > {
63+ const { jsSourcePath, targetPath, srcImportPath, shimPathLiteral } = task ;
64+ const srcImportPathLiteral : string = JSON . stringify ( srcImportPath ) ;
65+
66+ let namedExportsAssignment : string = '' ;
67+ try {
68+ // Read the sidecar .exports.json file generated by DeepImportsPlugin to get module exports
69+ const exportsJsonPath : string = jsSourcePath . slice ( 0 , - '.js' . length ) + '.exports.json' ;
70+ const { moduleExports } : { moduleExports : string [ ] } = await JsonFile . loadAsync ( exportsJsonPath ) ;
71+ if ( moduleExports . length > 0 ) {
72+ // Assign named exports after module.exports to ensure they're properly exposed for ESM imports
73+ namedExportsAssignment =
74+ '\n' + moduleExports . map ( ( exportName ) => `exports.${ exportName } = _m.${ exportName } ;` ) . join ( '\n' ) ;
75+ }
76+ } catch ( e ) {
77+ if ( ! FileSystem . isNotExistError ( e ) ) {
78+ throw e ;
9879 }
99-
100- await FileSystem . writeFileAsync (
101- targetPath ,
102- // Example:
103- // ```
104- // const _m = require("../../../lib-shim/index")._rushSdk_loadInternalModule("logic/policy/GitEmailPolicy");
105- // module.exports = _m;
106- // exports.GitEmailPolicy = _m.GitEmailPolicy;
107- // ```
108- `const _m = require(${ shimPathLiteral } )._rushSdk_loadInternalModule(${ srcImportPathLiteral } );\nmodule.exports = _m;${ namedExportsAssignment } \n`
109- ) ;
11080 }
81+
82+ await FileSystem . writeFileAsync (
83+ targetPath ,
84+ // Example:
85+ // ```
86+ // const _m = require("../../../lib-shim/index")._rushSdk_loadInternalModule("logic/policy/GitEmailPolicy");
87+ // module.exports = _m;
88+ // exports.GitEmailPolicy = _m.GitEmailPolicy;
89+ // ```
90+ `const _m = require(${ shimPathLiteral } )._rushSdk_loadInternalModule(${ srcImportPathLiteral } );\nmodule.exports = _m;${ namedExportsAssignment } \n`
91+ ) ;
11192}
11293
11394// Entry point invoked by "runScript" action from config/heft.json
@@ -126,23 +107,20 @@ export async function runAsync(options: IRunScriptOptions): Promise<void> {
126107 } ) ;
127108
128109 const cjsStubsTargetPath : string = `${ buildFolderPath } /lib-commonjs` ;
129- const dtsStubsTargetPath : string = `${ buildFolderPath } /lib-dts` ;
130- terminal . writeLine (
131- `generate-stubs: Generating stub files under ${ cjsStubsTargetPath } and ${ dtsStubsTargetPath } `
132- ) ;
110+ terminal . writeLine ( `generate-stubs: Generating stub files under ${ cjsStubsTargetPath } ` ) ;
133111
134112 // Ensure the target folder exists
135113 await FileSystem . ensureFolderAsync ( cjsStubsTargetPath ) ;
136114
137- // Collect and process file tasks in parallel with controlled concurrency
138- const tasks : AsyncGenerator < IFileTask > = collectFileTasksAsync ( {
115+ // Generate JS stubs from rush-lib/lib-commonjs (these redirect require() through the shim)
116+ // Note: .d.ts files are copied separately by the copy-rush-lib-types heft task from rush-lib/lib-dts
117+ const jsTasks : AsyncGenerator < IJsStubTask > = collectJsStubTasksAsync ( {
139118 parentSourcePath : `${ rushLibFolder } /lib-commonjs` ,
140- parentCjsTargetPath : cjsStubsTargetPath ,
141- parentDtsTargetPath : dtsStubsTargetPath ,
119+ parentTargetPath : cjsStubsTargetPath ,
142120 parentSrcImportPathWithSlash : '' ,
143121 libShimIndexPath : `${ buildFolderPath } /lib-shim/index.js`
144122 } ) ;
145- await Async . forEachAsync ( tasks , processFileTaskAsync , { concurrency : 50 } ) ;
123+ await Async . forEachAsync ( jsTasks , processJsStubTaskAsync , { concurrency : 50 } ) ;
146124
147125 terminal . writeLine ( 'generate-stubs: Completed successfully.' ) ;
148126}
0 commit comments