Skip to content

Commit

Permalink
fix(esw): module field should always be treated as ESM format
Browse files Browse the repository at this point in the history
  • Loading branch information
lbwa committed Aug 24, 2021
1 parent 6a9d79a commit 33b9cbf
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 25 deletions.
46 changes: 21 additions & 25 deletions packages/esw/src/build.ts
Expand Up @@ -4,7 +4,6 @@ import { build, BuildOptions, Format } from 'esbuild'
import {
iif,
map,
zip,
of,
tap,
throwError,
Expand All @@ -13,8 +12,9 @@ import {
toArray,
firstValueFrom,
combineLatest,
from,
pipe
pipe,
asapScheduler,
scheduled
} from 'rxjs'
import { PackageJson } from 'type-fest'
import isNil from 'lodash/isNil'
Expand All @@ -23,11 +23,6 @@ import externalEsBuildPlugin from './plugins/external'
import { isProduction } from './shared/utils'

const ENTRY_POINTS_EXTS = ['.js', '.jsx', '.ts', '.tsx'] as const
const enum InferenceAbility {
ON = 1,
OFF
}

const FORMAT_TO_PKG_FIELD = new Map<Format, 'main' | 'module'>([
['cjs', 'main'],
['esm', 'module']
Expand All @@ -38,15 +33,6 @@ const PKG_FIELD_TO_FORMAT = new Map<'main' | 'module', Format>([
['module', 'esm']
] as const)

const FIELD_INFERENCE_LOCK = new Map([
['main', InferenceAbility.ON],
/**
* @description `module` field always specify the **ES module** entry point.
* @see https://nodejs.org/api/packages.html#packages_dual_commonjs_es_module_packages
*/
['module', InferenceAbility.OFF]
] as const)

function checkBuildOptions<Options extends BuildOptions>() {
return pipe(
// check options logics
Expand Down Expand Up @@ -84,7 +70,7 @@ export default function runBuild(
)
)

const alternativeFormats$ = from(['cjs', 'esm'] as const)
const alternativeFormats$ = scheduled(['cjs', 'esm'] as const, asapScheduler)
const moduleIdFields$ = alternativeFormats$.pipe(
map(format => FORMAT_TO_PKG_FIELD.get(format)),
filter(Boolean)
Expand All @@ -95,12 +81,20 @@ export default function runBuild(
filter(Boolean)
)

const inferenceMeta$ = zip([
const inferenceMeta$ = combineLatest([
pkgJson$,
inferredOutPaths$,
moduleIdFields$,
alternativeFormats$
]).pipe(
map(([outPath, field, alternativeFmt]) => ({
filter(([pkgJson, outPath, field, format]) => {
const isEsModuleEntry = field === 'module'
const isAvailableEsModuleEntry = isEsModuleEntry && format === 'esm'
const isMatchedField = pkgJson[field] === outPath

return isMatchedField && (!isEsModuleEntry || isAvailableEsModuleEntry)
}),
map(([, outPath, field, alternativeFmt]) => ({
outPath,
field,
alternativeFmt
Expand All @@ -122,12 +116,14 @@ export default function runBuild(
]).pipe(
map(([options, meta]) => {
const { field, outPath, alternativeFmt } = meta
const fieldLock = FIELD_INFERENCE_LOCK.get(field)
// user's format has higher priority than inference
const fmt =
fieldLock === InferenceAbility.ON && isNil(options.format)
? alternativeFmt
: options.format
field === 'module'
? /**
* @description `module` field always specify the **ES module** entry point.
* @see https://nodejs.org/api/packages.html#packages_dual_commonjs_es_module_packages
*/
alternativeFmt
: options.format ?? alternativeFmt
const outExt = options.outExtension ?? {
'.js': path.basename(outPath).replace(/[^.]+\.(.+)/i, '.$1')
}
Expand Down
18 changes: 18 additions & 0 deletions packages/esw/test/__snapshots__/build.spec.ts.snap
@@ -1,5 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`node api - build should override the cjs inference from main field: node-api---build-should-override-the-cjs-inference-from-main-field 1`] = `
Array [
Object {
"errors": Array [],
"warnings": Array [],
},
]
`;

exports[`node api - build should work with main field and cjs syntax: node-api---build-should-work-with-main-field-and-cjs-syntax 1`] = `
Array [
Object {
Expand Down Expand Up @@ -39,3 +48,12 @@ Array [
},
]
`;

exports[`node api - build shouldn't override the esm inference from module field: node-api---build-shouldn't-override-the-esm-inference-from-module-field 1`] = `
Array [
Object {
"errors": Array [],
"warnings": Array [],
},
]
`;
22 changes: 22 additions & 0 deletions packages/esw/test/build.spec.ts
Expand Up @@ -135,6 +135,28 @@ describe('node api - build', () => {
expect(output).toContain(`from "./src/fib"`)
})

it("shouldn't override the esm inference from module field", async () => {
const output = await runFixtureCase(
'only-module-field',
'dist',
{ format: 'cjs' },
'index.ts',
'index.esm.js'
)
expect(output).toContain(`from "./src/fib"`)
})

it('should override the cjs inference from main field', async () => {
const output = await runFixtureCase(
'only-module-field',
'dist',
{ format: 'esm' },
'index.ts',
'index.esm.js'
)
expect(output).toContain(`from "./src/fib"`)
})

it("shouldn't work without package.json file", async () => {
let err: Error | null = null
await build({
Expand Down

0 comments on commit 33b9cbf

Please sign in to comment.