Skip to content

Commit

Permalink
Don't enforce module to precede import per se (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
nvie committed Jul 5, 2023
1 parent 00d1974 commit 9d18c31
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 47 deletions.
5 changes: 1 addition & 4 deletions pkg/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ export type Message =
}
>
| BaseMessage<'EXPORTS_TYPES_SHOULD_BE_FIRST'>
| BaseMessage<
'EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE',
{ conditions: string[] }
>
| BaseMessage<'EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE'>
| BaseMessage<'EXPORTS_DEFAULT_SHOULD_BE_LAST'>
| BaseMessage<'EXPORTS_MODULE_SHOULD_BE_ESM'>
| BaseMessage<'EXPORTS_VALUE_INVALID', { suggestValue: string }>
Expand Down
37 changes: 13 additions & 24 deletions pkg/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,30 +493,19 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
}
}

// a 'module' export should always precede 'import' or 'require'
if ('module' in exports) {
const conditions = []
if (
'require' in exports &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('require')
) {
conditions.push('require')
}
if (
'import' in exports &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('import')
) {
conditions.push('import')
}

if (conditions.length > 0) {
messages.push({
code: 'EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE',
args: { conditions },
path: currentPath.concat('module'),
type: 'error'
})
}
// if there is a 'require' and a 'module' condition at the same level,
// then 'module' should always precede 'require'
if (
'module' in exports &&
'require' in exports &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('require')
) {
messages.push({
code: 'EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE',
args: {},
path: currentPath.concat('module'),
type: 'error'
})
}

// the default export should be the last condition
Expand Down
10 changes: 2 additions & 8 deletions pkg/src/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,9 @@ export function printMessage(m, pkg) {
case 'EXPORTS_TYPES_SHOULD_BE_FIRST':
// prettier-ignore
return `${c.bold(fp(m.path))} should be the first in the object as required by TypeScript.`
case 'EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE': {
let conditions = `the ${m.args.conditions
.map((cond) => `"${c.bold(cond)}"`)
.join(' and ')} condition`
if (m.args.conditions.length !== 1) {
conditions += 's'
}
case 'EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE': {
// prettier-ignore
return `${c.bold(fp(m.path))} should come before ${conditions} so it can take precedence when used by a bundler.`
return `${c.bold(fp(m.path))} should come before the "require" condition so it can take precedence when used by a bundler.`
}
case 'EXPORTS_DEFAULT_SHOULD_BE_LAST':
// prettier-ignore
Expand Down
2 changes: 1 addition & 1 deletion pkg/tests/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ testFixture('missing-files', [

testFixture('no-exports-module', [])

testFixture('exports-module', ['EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE'])
testFixture('exports-module', ['EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE'])

testFixture('publish-config', ['USE_EXPORTS_BROWSER', 'FILE_DOES_NOT_EXIST'])

Expand Down
4 changes: 2 additions & 2 deletions site/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ If the `"exports"` field contains glob paths, but it doesn't match any files, re

The `"exports"` field should not have globs defined with trailing slashes. It is [deprecated](https://nodejs.org/docs/latest-v16.x/api/packages.html#subpath-folder-mappings) and should use [subpath patterns](https://nodejs.org/api/packages.html#subpath-patterns), e.g. a trailing `/*` instead.

## `EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE`
## `EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE`

Ensure the `"module"` condition comes before the `"import"` and `"require"` conditions. Due to the way conditions are matched top-to-bottom, the `"module"` condition (used in bundler contexts only) must come before an `"import"` or `"require"` condition, so it has the opportunity to take precedence.
Ensure the `"module"` condition comes before the `"require"` condition. Due to the way conditions are matched top-to-bottom, the `"module"` condition (used in bundler contexts only) must come before a `"require"` condition, so it has the opportunity to take precedence.

## `EXPORTS_TYPES_SHOULD_BE_FIRST`

Expand Down
10 changes: 2 additions & 8 deletions site/src/utils/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,9 @@ function messageToString(m, pkg) {
case 'EXPORTS_TYPES_SHOULD_BE_FIRST':
// prettier-ignore
return `Should be the first in the object as required by TypeScript.`
case 'EXPORTS_MODULE_SHOULD_PRECEDE_IMPORT_REQUIRE': {
let conditions = `the ${m.args.conditions
.map((cond) => `"${bold(cond)}"`)
.join(' and ')} condition`
if (m.args.conditions.length !== 1) {
conditions += 's'
}
case 'EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE': {
// prettier-ignore
return `Should come before ${conditions} so it can take precedence when used by a bundler.`
return `Should come before the "require" condition so it can take precedence when used by a bundler.`
}
case 'EXPORTS_DEFAULT_SHOULD_BE_LAST':
// prettier-ignore
Expand Down

0 comments on commit 9d18c31

Please sign in to comment.