Skip to content

Commit 9d1b4a1

Browse files
committed
feat(rush-sdk): add named export support for CommonJS compatibility
This commit enhances @rushstack/rush-sdk to support named imports when the package is consumed via ESM project.
1 parent 272a7b4 commit 9d1b4a1

File tree

13 files changed

+117
-41
lines changed

13 files changed

+117
-41
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Chore: add named exports to support for `@rushstack/rush-sdk` used via ESM named import.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

common/config/rush/browser-approved-packages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@
5858
"name": "axios",
5959
"allowedCategories": [ "libraries" ]
6060
},
61+
{
62+
"name": "cjs-module-lexer",
63+
"allowedCategories": [ "libraries" ]
64+
},
6165
{
6266
"name": "dependency-path",
6367
"allowedCategories": [ "libraries" ]

common/config/subspaces/build-tests-subspace/pnpm-lock.yaml

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
22
{
3-
"pnpmShrinkwrapHash": "32f13ef1f15898a4f614bf9897cc1d74d8fdf2dd",
3+
"pnpmShrinkwrapHash": "402417ff6a3ef549c064c379cb9793ec4b4d64af",
44
"preferredVersionsHash": "550b4cee0bef4e97db6c6aad726df5149d20e7d9",
5-
"packageJsonInjectedDependenciesHash": "cb59d652ae8cf04249e1fa557d15d2958128a5e8"
5+
"packageJsonInjectedDependenciesHash": "248fe4df023dec4d802dbb3f8d3f90842fd458ed"
66
}

common/config/subspaces/default/pnpm-lock.yaml

Lines changed: 25 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
22
{
3-
"pnpmShrinkwrapHash": "02e03149d5bf0b6a4e8dd2df668ed5350b0506c5",
3+
"pnpmShrinkwrapHash": "f91ada7a0ec37139e2f0cff3fb869d1f514ee628",
44
"preferredVersionsHash": "a9b67c38568259823f9cfb8270b31bf6d8470b27"
55
}

libraries/rush-sdk/config/jest.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"extends": "local-node-rig/profiles/default/config/jest.config.json",
33

4-
"roots": ["<rootDir>/lib-shim"],
4+
"roots": ["<rootDir>/lib-commonjs"],
55

6-
"testMatch": ["<rootDir>/lib-shim/**/*.test.js"],
6+
"testMatch": ["<rootDir>/lib-commonjs/**/*.test.js"],
77

88
"collectCoverageFrom": [
99
"lib-shim/**/*.js",

libraries/rush-sdk/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"@rushstack/webpack-preserve-dynamic-require-plugin": "workspace:*",
5757
"@types/semver": "7.5.0",
5858
"@types/webpack-env": "1.18.8",
59+
"cjs-module-lexer": "2.1.0",
5960
"eslint": "~9.37.0",
6061
"local-node-rig": "workspace:*",
6162
"webpack": "~5.103.0"

libraries/rush-sdk/src/generate-stubs.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
import * as path from 'node:path';
55

6-
import { FileSystem, Import, Path } from '@rushstack/node-core-library';
6+
import { initSync, parse } from 'cjs-module-lexer';
7+
8+
import { Encoding, FileSystem, Import, Path } from '@rushstack/node-core-library';
79

810
function generateLibFilesRecursively(options: {
911
parentSourcePath: string;
@@ -14,6 +16,10 @@ function generateLibFilesRecursively(options: {
1416
for (const folderItem of FileSystem.readFolderItems(options.parentSourcePath)) {
1517
const sourcePath: string = path.join(options.parentSourcePath, folderItem.name);
1618
const targetPath: string = path.join(options.parentTargetPath, folderItem.name);
19+
const commonjsPath: string = path.join(
20+
options.parentSourcePath.replace('/rush-lib/lib', '/rush-lib/lib-commonjs'),
21+
folderItem.name
22+
);
1723

1824
if (folderItem.isDirectory()) {
1925
// create destination folder
@@ -36,11 +42,17 @@ function generateLibFilesRecursively(options: {
3642
const shimPathLiteral: string = JSON.stringify(Path.convertToSlashes(shimPath));
3743
const srcImportPathLiteral: string = JSON.stringify(srcImportPath);
3844

45+
const sourceCode: string = FileSystem.readFile(commonjsPath, { encoding: Encoding.Utf8 });
46+
const exportedNames: string[] = extractNamedExports(sourceCode);
47+
const namedExportsPlaceholder: string = exportedNames.length
48+
? `${exportedNames.map((name) => `exports.${name}`).join(' = ')} = undefined;\n\n`
49+
: '';
50+
3951
FileSystem.writeFile(
4052
targetPath,
4153
// Example:
4254
// module.exports = require("../../../lib-shim/index")._rushSdk_loadInternalModule("logic/policy/GitEmailPolicy");
43-
`module.exports = require(${shimPathLiteral})._rushSdk_loadInternalModule(${srcImportPathLiteral});`
55+
`${namedExportsPlaceholder}module.exports = require(${shimPathLiteral})._rushSdk_loadInternalModule(${srcImportPathLiteral});`
4456
);
4557
}
4658
}
@@ -58,6 +70,7 @@ export async function runAsync(): Promise<void> {
5870
const stubsTargetPath: string = path.resolve(__dirname, '../lib');
5971
// eslint-disable-next-line no-console
6072
console.log('generate-stubs: Generating stub files under: ' + stubsTargetPath);
73+
initSync();
6174
generateLibFilesRecursively({
6275
parentSourcePath: path.join(rushLibFolder, 'lib'),
6376
parentTargetPath: stubsTargetPath,
@@ -67,3 +80,8 @@ export async function runAsync(): Promise<void> {
6780
// eslint-disable-next-line no-console
6881
console.log('generate-stubs: Completed successfully.');
6982
}
83+
84+
export function extractNamedExports(source: string): string[] {
85+
const { exports, reexports } = parse(source);
86+
return [...exports, ...reexports].filter((d) => d !== '__esModule');
87+
}

libraries/rush-sdk/src/test/__snapshots__/script.test.ts.snap

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Loaded @microsoft/rush-lib from process.env._RUSH_LIB_PATH
5757
'VersionPolicyDefinitionName',
5858
'YarnOptionsConfiguration',
5959
'_FlagFile',
60+
'_OperationBuildCache',
6061
'_OperationMetadataManager',
6162
'_OperationStateFile',
6263
'_RushGlobalFolder',
@@ -76,15 +77,6 @@ exports[`@rushstack/rush-sdk Should load via global (for plugins): stdout 1`] =
7677

7778
exports[`@rushstack/rush-sdk Should load via install-run (for standalone tools): stderr 1`] = `""`;
7879

79-
exports[`@rushstack/rush-sdk Should load via install-run (for standalone tools): stdout 1`] = `
80-
"Trying to load @microsoft/rush-lib installed by install-run-rush
81-
Loaded @microsoft/rush-lib installed by install-run-rush
82-
[
83-
'_rushSdk_loadInternalModule',
84-
'foo'
85-
]"
86-
`;
87-
8880
exports[`@rushstack/rush-sdk Should load via process.env._RUSH_LIB_PATH (for child processes): stderr 1`] = `""`;
8981

9082
exports[`@rushstack/rush-sdk Should load via process.env._RUSH_LIB_PATH (for child processes): stdout 1`] = `

0 commit comments

Comments
 (0)