diff --git a/.changeset/quiet-eels-fix.md b/.changeset/quiet-eels-fix.md new file mode 100644 index 000000000..660a692ba --- /dev/null +++ b/.changeset/quiet-eels-fix.md @@ -0,0 +1,10 @@ +--- +'@guardian/browserslist-config': patch +'@guardian/eslint-config': patch +'@guardian/eslint-config-typescript': patch +'@guardian/libs': patch +'@guardian/prettier': patch +'@guardian/tsconfig': patch +--- + +CommonJS exports in NPM packages target `ES2018` diff --git a/tools/nx-plugins/npm-package/build/get-compiler-options.ts b/tools/nx-plugins/npm-package/build/get-compiler-options.ts new file mode 100644 index 000000000..9b35712d9 --- /dev/null +++ b/tools/nx-plugins/npm-package/build/get-compiler-options.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/unbound-method -- this is what the TS methods do */ +import path from 'node:path'; +import type { ExecutorContext } from '@nrwl/devkit'; +import { + findConfigFile, + parseJsonConfigFileContent, + readConfigFile, + sys, +} from 'typescript'; +import type { BuildExecutorOptions } from './schema'; + +export const getCompilerOptions = ( + options: BuildExecutorOptions, + context: ExecutorContext, +) => { + const tsconfigPath = findConfigFile( + context.root, + sys.fileExists, + options.tsConfig, + ); + + if (tsconfigPath) { + // Read tsconfig.json file + const tsconfigFile = readConfigFile(tsconfigPath, sys.readFile); + + // Resolve extends + const parsedTsconfig = parseJsonConfigFileContent( + tsconfigFile.config, + sys, + path.dirname(tsconfigPath), + ); + + return parsedTsconfig.options; + } + + return {}; +}; diff --git a/tools/nx-plugins/npm-package/build/index.ts b/tools/nx-plugins/npm-package/build/index.ts index 0bbcf9fb1..cc007c76e 100644 --- a/tools/nx-plugins/npm-package/build/index.ts +++ b/tools/nx-plugins/npm-package/build/index.ts @@ -10,6 +10,8 @@ import type Cpy from 'cpy'; import type { OutputChunk } from 'rollup'; import { rollup } from 'rollup'; import ts from 'rollup-plugin-ts'; +import { ScriptTarget } from 'typescript'; +import { getCompilerOptions } from './get-compiler-options'; import { getDeclaredDeps } from './get-declared-deps'; import type { BuildExecutorOptions } from './schema'; import { setPackageDefaults } from './set-package-defaults'; @@ -34,24 +36,34 @@ export type Entries = { const getRollupConfig = ( options: BuildExecutorOptions, + context: ExecutorContext, format: typeof formats[number], -) => ({ - output: { - dir: `${options.outputPath}/${format}`, - format, - sourcemap: true, - preserveModules: true, - }, - plugins: [ - nodeResolve({ - extensions: ['.ts', '.tsx', '.mjs', '.jsx', '.js', '.json'], - }), - ts({ tsconfig: options.tsConfig }), - json(), - commonjs(), - ], -}); +) => { + const compilerOptions = getCompilerOptions(options, context); + + if (format === 'cjs') { + compilerOptions.target = ScriptTarget.ES2018; + } + return { + output: { + dir: `${options.outputPath}/${format}`, + format, + sourcemap: true, + preserveModules: true, + }, + plugins: [ + nodeResolve({ + extensions: ['.ts', '.tsx', '.mjs', '.jsx', '.js', '.json'], + }), + ts({ + tsconfig: compilerOptions, + }), + json(), + commonjs(), + ], + }; +}; export default async function buildExecutor( options: BuildExecutorOptions, context: ExecutorContext, @@ -93,7 +105,7 @@ export default async function buildExecutor( // create build for each module type const outputs = await Promise.all( formats.map(async (format) => { - const { plugins, output } = getRollupConfig(options, format); + const { plugins, output } = getRollupConfig(options, context, format); const bundle = await rollup({ input: options.entry, plugins,