Skip to content

Instantly share code, notes, and snippets.

@stenin-nikita
Last active March 13, 2025 13:35
Show Gist options
  • Select an option

  • Save stenin-nikita/46215fb6c20a4eefd1993e9b73345e78 to your computer and use it in GitHub Desktop.

Select an option

Save stenin-nikita/46215fb6c20a4eefd1993e9b73345e78 to your computer and use it in GitHub Desktop.
Generate exports field in package.json
import fastGlob from 'fast-glob';
import { promises as fsp } from 'node:fs';
import { createRequire } from 'node:module';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { parseArgs } from 'node:util';
const _require = createRequire(fileURLToPath(import.meta.url));
async function generateExports(packageName, force) {
const exports = {};
const root = path.dirname(_require.resolve(packageName));
const files = await fastGlob(path.join(root, '**/package.json'), {
ignore: [path.join(root, 'node_modules')],
absolute: true,
});
for (const file of files) {
const { default: pkg } = await import(file, { with: { type: 'json' } });
const dirPath = path.dirname(file);
const exportKey = pkg.name.replace(packageName, '.');
const pkgEntry = `./${path.relative(root, file)}`;
const importEntry = path.resolve(dirPath, pkg.module);
const requireEntry = path.resolve(dirPath, pkg.main);
const typesEntry = path.resolve(dirPath, pkg.types);
exports[exportKey] = {
import: `./${path.relative(root, importEntry)}`,
require: `./${path.relative(root, requireEntry)}`,
types: `./${path.relative(root, typesEntry)}`,
};
exports[pkgEntry] = pkgEntry;
}
const rootPkgPath = path.resolve(root, 'package.json');
const { default: rootPkg } = await import(rootPkgPath, { with: { type: 'json' } });
if (!rootPkg.exports || force) {
rootPkg.exports = exports;
await fsp.writeFile(rootPkgPath, JSON.stringify(rootPkg, null, 2), 'utf-8');
console.log(`[success] The field "exports" in "${packageName}" successfully patched!`);
} else {
console.log(`[skipped] The field "exports" in "${packageName}" already exists!`);
}
return exports;
}
async function run() {
const args = process.argv.slice(2);
const parsed = parseArgs({
args,
options: {
packages: { type: 'string', short: 'p' },
force: { type: 'boolean', short: 'f' },
},
});
const packages = parsed.values.packages?.split(',') ?? [];
for (const name of packages) {
await generateExports(name, parsed.values.force);
}
}
run();
@stenin-nikita
Copy link
Author

Usage:

node fix-exports.js -p @apollo/client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment