Skip to content

Commit

Permalink
Check license field is set if license file exists
Browse files Browse the repository at this point in the history
close #111
  • Loading branch information
bluwy committed Oct 24, 2024
1 parent 4525806 commit 6f2e4f2
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 2 deletions.
1 change: 1 addition & 0 deletions pkg/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export type Message =
| BaseMessage<'USE_EXPORTS_OR_IMPORTS_BROWSER'>
| BaseMessage<'USE_FILES'>
| BaseMessage<'USE_TYPE'>
| BaseMessage<'USE_LICENSE', { licenseFilePath: string }>
| BaseMessage<
'TYPES_NOT_EXPORTED',
{
Expand Down
3 changes: 3 additions & 0 deletions pkg/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ export const commonInternalPaths = [
'.eslintrc',
'.eslintrc.js'
]

// https://github.com/npm/npm-packlist/blob/53b2a4f42b7fef0f63e8f26a3ea4692e23a58fed/lib/index.js#L284-L286
export const licenseFiles = [/^copying/i, /^licence/i, /^license/i]
27 changes: 26 additions & 1 deletion pkg/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
commonInternalPaths,
invalidJsxExtensions,
knownBrowserishConditions
knownBrowserishConditions,
licenseFiles
} from './constants.js'
import {
exportsGlob,
Expand Down Expand Up @@ -82,6 +83,30 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
})
}

// Check if has license file but no license field
if (rootPkg.license == null) {
promiseQueue.push(async () => {
const topFiles = await vfs.readDir(pkgDir)
/** @type {string | undefined} */
let matchedLicenseFilePath
for (const f of topFiles) {
if (await vfs.isPathDir(vfs.pathJoin(pkgDir, f))) continue
if (licenseFiles.some((r) => r.test(f))) {
matchedLicenseFilePath = '/' + f
break
}
}
if (matchedLicenseFilePath) {
messages.push({
code: 'USE_LICENSE',
args: { licenseFilePath: matchedLicenseFilePath },
path: ['name'],
type: 'suggestion'
})
}
})
}

// Check if "type" field is specified, help Node.js push towards an ESM default future:
// https://nodejs.org/en/blog/release/v20.10.0
if (rootPkg.type == null) {
Expand Down
5 changes: 4 additions & 1 deletion pkg/src/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ export function formatMessage(m, pkg, opts = {}) {
return `The package ${c.bold('publishes internal tests or config files')}. You can use ${c.bold('pkg.files')} to only publish certain files and save user bandwidth.`
case 'USE_TYPE':
// prettier-ignore
return `The package does not specify the ${c.bold('type')} field. NodeJS may attempt to detect the package type causing a small performance hit. Consider adding ${c.bold('"type"')}: "${c.bold('commonjs')}".`
return `The package does not specify the ${c.bold('"type"')} field. NodeJS may attempt to detect the package type causing a small performance hit. Consider adding ${c.bold('"type"')}: "${c.bold('commonjs')}".`
case 'USE_LICENSE':
// prettier-ignore
return `The package does not specify the ${c.bold('"license"')} field but a license file was detected at ${c.bold(m.args.licenseFilePath)}. Consider adding a ${c.bold('"license"')} field so it's displayed on npm.`
case 'TYPES_NOT_EXPORTED': {
const typesFilePath = exportsRel(m.args.typesFilePath)
if (m.args.actualExtension && m.args.expectExtension) {
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions pkg/tests/fixtures/missing-license/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "publint-missing-license",
"version": "0.0.1",
"private": true,
"type": "commonjs"
}
2 changes: 2 additions & 0 deletions pkg/tests/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ testFixture('missing-files', [
'USE_EXPORTS_OR_IMPORTS_BROWSER'
])

testFixture('missing-license', ['USE_LICENSE'])

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

testFixture('not-missing-files', [])
Expand Down
4 changes: 4 additions & 0 deletions site/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ Internal tests or config files are published, which are usually not needed and u

[Node.js v21.1.0](https://nodejs.org/en/blog/release/v21.1.0) adds a new `--experimental-detect-module`, which can be used to automatically run ES modules when ESM syntax can be detected. Node.js hopes to make detection enabled by default in the future. Detection increases startup time, so Node is encouraging everyone — especially package authors — to add a type field to `package.json`, even for the default `"type": "commonjs"`.

## `USE_LICENSE`

A license file is published but the `"license"` field is not set in `package.json`. Consider adding a `"license"` field so that it's correctly displayed on npm and allows other tooling to parse the package license.

## `FIELD_INVALID_VALUE_TYPE`

Some `package.json` fields has a set of allowed types, e.g. `string` or `object` only. If an invalid type is passed, this error message will be showed.
Expand Down
3 changes: 3 additions & 0 deletions site/src/utils/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ function messageToString(m, pkg) {
case 'USE_TYPE':
// prettier-ignore
return `The package does not specify the ${bold('"type"')} field. NodeJS may attempt to detect the package type causing a small performance hit. Consider adding ${bold('"type"')}: "${bold('commonjs')}".`
case 'USE_LICENSE':
// prettier-ignore
return `The package does not specify the ${bold('"license"')} field but a license file was detected at ${bold(m.args.licenseFilePath)}. Consider adding a ${bold('"license"')} field so it's displayed on npm.`
case 'TYPES_NOT_EXPORTED': {
const typesFilePath = exportsRel(m.args.typesFilePath)
if (m.args.actualExtension && m.args.expectExtension) {
Expand Down

0 comments on commit 6f2e4f2

Please sign in to comment.