From 2e485af9cbc9d8f66122999c71de8f10bfe006d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Fri, 1 Dec 2023 23:41:55 +0900 Subject: [PATCH] Add a warning for jsnext field (#85) --- pkg/index.d.ts | 1 + pkg/src/index.js | 34 ++++++++++++++----- pkg/src/message.js | 3 ++ pkg/tests/fixtures/deprecated-fields/index.js | 0 .../fixtures/deprecated-fields/package.json | 8 +++++ pkg/tests/playground.js | 5 +++ site/rules.md | 4 +++ site/src/utils/message.js | 3 ++ 8 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 pkg/tests/fixtures/deprecated-fields/index.js create mode 100644 pkg/tests/fixtures/deprecated-fields/package.json diff --git a/pkg/index.d.ts b/pkg/index.d.ts index 1bc835d..d870fc7 100644 --- a/pkg/index.d.ts +++ b/pkg/index.d.ts @@ -106,6 +106,7 @@ export type Message = browserishCondition: string } > + | BaseMessage<'DEPRECATED_FIELD_JSNEXT'> export interface Options { /** diff --git a/pkg/src/index.js b/pkg/src/index.js index 599d19d..ec3f950 100755 --- a/pkg/src/index.js +++ b/pkg/src/index.js @@ -196,12 +196,18 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) { // check file existence for other known package fields const knownFields = [ - 'types', - 'typings', - 'jsnext:main', - 'jsnext', - 'unpkg', - 'jsdelivr' + { name: 'types' }, + { name: 'typings' }, + { + name: 'jsnext:main', + deprecatedCode: /** @type {const} */ ('DEPRECATED_FIELD_JSNEXT') + }, + { + name: 'jsnext', + deprecatedCode: /** @type {const} */ ('DEPRECATED_FIELD_JSNEXT') + }, + { name: 'unpkg' }, + { name: 'jsdelivr' } ] // if has typesVersions field, it complicates `types`/`typings` field resolution a lot. // for now skip it, but further improvements are tracked at @@ -209,15 +215,25 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) { if (getPublishedField(rootPkg, 'typesVersions')[0]) { knownFields.splice(0, 2) } - for (const field of knownFields) { - const [fieldValue, fieldPkgPath] = getPublishedField(rootPkg, field) + for (const { name: fieldName, deprecatedCode } of knownFields) { + const [fieldValue, fieldPkgPath] = getPublishedField(rootPkg, fieldName) if ( fieldValue != null && ensureTypeOfField(fieldValue, ['string'], fieldPkgPath) ) { promiseQueue.push(async () => { const fieldPath = vfs.pathJoin(pkgDir, fieldValue) - await readFile(fieldPath, fieldPkgPath, ['.js', '/index.js']) + const hasContent = + (await readFile(fieldPath, fieldPkgPath, ['.js', '/index.js'])) !== + false + if (hasContent && deprecatedCode) { + messages.push({ + code: deprecatedCode, + args: {}, + path: fieldPkgPath, + type: 'warning' + }) + } }) } } diff --git a/pkg/src/message.js b/pkg/src/message.js index ff20051..fc20de0 100644 --- a/pkg/src/message.js +++ b/pkg/src/message.js @@ -147,6 +147,9 @@ export function formatMessage(m, pkg) { case 'EXPORTS_VALUE_CONFLICTS_WITH_BROWSER': // prettier-ignore return `${c.bold(fp(m.path))} is ${c.bold(pv(m.path))} which also matches ${c.bold(fp(m.args.browserPath))}: "${c.bold(pv(m.args.browserPath))}", which overrides the path when building the library with the "${c.bold(m.args.browserishCondition)}" condition. This is usually unintentional and may cause build issues. Consider using a different file name for ${c.bold(pv(m.path))}.` + case 'DEPRECATED_FIELD_JSNEXT': + // prettier-ignore + return `${c.bold(fp(m.path))} is deprecated. ${c.bold('pkg.module')} should be used instead.` default: return } diff --git a/pkg/tests/fixtures/deprecated-fields/index.js b/pkg/tests/fixtures/deprecated-fields/index.js new file mode 100644 index 0000000..e69de29 diff --git a/pkg/tests/fixtures/deprecated-fields/package.json b/pkg/tests/fixtures/deprecated-fields/package.json new file mode 100644 index 0000000..9efbd58 --- /dev/null +++ b/pkg/tests/fixtures/deprecated-fields/package.json @@ -0,0 +1,8 @@ +{ + "name": "publint-glob-deprecated", + "version": "0.0.1", + "private": true, + "main": "./index.js", + "jsnext": "./index.js", + "jsnext:main": "./index.js" +} diff --git a/pkg/tests/playground.js b/pkg/tests/playground.js index 3a280a7..da1c9ce 100644 --- a/pkg/tests/playground.js +++ b/pkg/tests/playground.js @@ -134,6 +134,11 @@ testFixture('types-versions', []) testFixture('umd', ['FILE_INVALID_FORMAT', 'FILE_INVALID_FORMAT']) +testFixture('deprecated-fields', [ + 'DEPRECATED_FIELD_JSNEXT', + 'DEPRECATED_FIELD_JSNEXT' +]) + /** * @typedef {{ * level?: import('../index.d.ts').Options['level'] diff --git a/site/rules.md b/site/rules.md index 69d24ee..e5d00eb 100644 --- a/site/rules.md +++ b/site/rules.md @@ -226,3 +226,7 @@ When matching the `"worker"` condition, it will resolve to `"./lib.server.js"` w This is usually not intended and causes the wrong file to be loaded. If it is intended, the `"worker"` condition should point to `"./lib.browser.js"` directly instead. To fix this, you can rename `"./lib.server.js"` to `"./lib.worker.js"` for example so it has its own specific file. Or check out the [USE_EXPORTS_OR_IMPORTS_BROWSER](#use_exports_or_imports_browser) rule to refactor away the `"browser"` field. + +## `DEPRECATED_FIELD_JSNEXT` + +The `"jsnext:main"` and `"jsnext"` fields are deprecated. The `"module"` field should be used instead. See [this issue](https://github.com/jsforum/jsforum/issues/5) for more information. diff --git a/site/src/utils/message.js b/site/src/utils/message.js index 9fdb1ad..7a28397 100644 --- a/site/src/utils/message.js +++ b/site/src/utils/message.js @@ -141,6 +141,9 @@ function messageToString(m, pkg) { case 'EXPORTS_VALUE_CONFLICTS_WITH_BROWSER': // prettier-ignore return `${bold(pv(m.path))} matches ${bold(fp(m.args.browserPath))}: "${bold(pv(m.args.browserPath))}", which overrides the path when building the library with the "${bold(m.args.browserishCondition)}" condition. This is usually unintentional and may cause build issues. Consider using a different file name for ${bold(pv(m.path))}.` + case 'DEPRECATED_FIELD_JSNEXT': + // prettier-ignore + return `${bold(fp(m.path))} is deprecated. ${bold('pkg.module')} should be used instead.` default: return }