Skip to content

Commit

Permalink
Lower trailing slash glob for compat as suggestion
Browse files Browse the repository at this point in the history
fix #62
  • Loading branch information
bluwy committed Aug 20, 2023
1 parent cff41dd commit 987d780
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 39 deletions.
62 changes: 35 additions & 27 deletions pkg/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
resolveExports,
isDtsFile,
getDtsFilePathFormat,
getDtsCodeFormatExtension
getDtsCodeFormatExtension,
getPkgPathValue
} from './utils.js'

/**
Expand Down Expand Up @@ -351,57 +352,64 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
}

/**
* @param {string} exports
* @param {string} exportsValue
*/
async function getExportsFiles(exports) {
const exportsPath = vfs.pathJoin(pkgDir, exports)
const isGlob = exports.includes('*')
async function getExportsFiles(exportsValue) {
const exportsPath = vfs.pathJoin(pkgDir, exportsValue)
const isGlob = exportsValue.includes('*')
return isGlob
? await exportsGlob(exportsPath, vfs, _packedFiles)
: [exportsPath]
}

/**
* @param {any} exports
* @param {any} exportsValue
* @param {string[]} currentPath
* @param {boolean} isAfterNodeCondition
*/
function crawlExports(exports, currentPath, isAfterNodeCondition = false) {
if (typeof exports === 'string') {
function crawlExports(
exportsValue,
currentPath,
isAfterNodeCondition = false
) {
if (typeof exportsValue === 'string') {
promiseQueue.push(async () => {
// warn deprecated subpath mapping
// https://nodejs.org/docs/latest-v16.x/api/packages.html#subpath-folder-mappings
if (exports.endsWith('/')) {
if (exportsValue.endsWith('/')) {
const expectPath = currentPath.map((part) => {
return part.endsWith('/') ? part + '*' : part
})
const expectPathAlreadyExist = !!getPkgPathValue(rootPkg, expectPath)
messages.push({
code: 'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING',
args: {
expectPath,
expectValue: exports + '*'
expectValue: exportsValue + '*'
},
path: currentPath,
type: 'warning'
// if a trailing glob is also specified, that means this key is for backwards compat only.
// lower severity to suggestion instead.
type: expectPathAlreadyExist ? 'suggestion' : 'warning'
})
// Help fix glob so we can further analyze other issues
exports += '*'
// help fix glob so we can further analyze other issues
exportsValue += '*'
}

// error incorrect exports value
if (!exports.startsWith('./')) {
if (!exportsValue.startsWith('./')) {
messages.push({
code: 'EXPORTS_VALUE_INVALID',
args: {
suggestValue: './' + exports.replace(/^[\/]+/, '')
suggestValue: './' + exportsValue.replace(/^[\/]+/, '')
},
path: currentPath,
type: 'error'
})
}

const isGlob = exports.includes('*')
const exportsFiles = await getExportsFiles(exports)
const isGlob = exportsValue.includes('*')
const exportsFiles = await getExportsFiles(exportsValue)

if (isGlob && !exportsFiles.length) {
messages.push({
Expand Down Expand Up @@ -477,7 +485,7 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
expectExtension: getCodeFormatExtension(actualFormat),
actualFilePath: isGlob
? './' + vfs.pathRelative(pkgDir, filePath)
: exports
: exportsValue
},
path: currentPath,
type: 'warning'
Expand All @@ -490,11 +498,11 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
})
}
// `exports` could be null to disallow exports of globs from another key
else if (exports) {
const exportsKeys = Object.keys(exports)
else if (exportsValue) {
const exportsKeys = Object.keys(exportsValue)

// the types export should be the first condition
if ('types' in exports && exportsKeys[0] !== 'types') {
if ('types' in exportsValue && exportsKeys[0] !== 'types') {
// check preceding conditions before the `types` condition, if there are nested
// conditions, check if they also have the `types` condition. If they do, there's
// a good chance those take precendence over this non-first `types` condition, which
Expand All @@ -503,8 +511,8 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
let isPrecededByNestedTypesCondition = false
for (const key of precedingKeys) {
if (
typeof exports[key] === 'object' &&
objectHasKeyNested(exports[key], 'types')
typeof exportsValue[key] === 'object' &&
objectHasKeyNested(exportsValue[key], 'types')
) {
isPrecededByNestedTypesCondition = true
break
Expand All @@ -523,8 +531,8 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
// 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 &&
'module' in exportsValue &&
'require' in exportsValue &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('require')
) {
messages.push({
Expand All @@ -537,7 +545,7 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {

// the default export should be the last condition
if (
'default' in exports &&
'default' in exportsValue &&
exportsKeys[exportsKeys.length - 1] !== 'default'
) {
messages.push({
Expand All @@ -554,7 +562,7 @@ export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
let isKeyAfterNodeCondition = isAfterNodeCondition
for (const key of exportsKeys) {
crawlExports(
exports[key],
exportsValue[key],
currentPath.concat(key),
isKeyAfterNodeCondition
)
Expand Down
3 changes: 3 additions & 0 deletions pkg/tests/fixtures/test-2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"./module": {
"module": "./lib/cjs.js"
},
"./types/": {
"default": "./types/"
},
"./types/*": {
"types": "./types/*.d.ts",
"default": "./types/*.js"
Expand Down
2 changes: 2 additions & 0 deletions pkg/tests/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ testFixture('publish-config', ['FILE_DOES_NOT_EXIST', 'USE_EXPORTS_BROWSER'])
testFixture('test-1', ['FILE_INVALID_FORMAT', 'TYPES_NOT_EXPORTED'])

testFixture('test-2', [
'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING',
'EXPORTS_MODULE_SHOULD_BE_ESM',
'EXPORTS_VALUE_INVALID',
'FILE_DOES_NOT_EXIST',
Expand Down Expand Up @@ -80,6 +81,7 @@ testFixture(
testFixture(
'test-2 (strict: true)',
[
{ code: 'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING', type: 'suggestion' },
{ code: 'EXPORTS_MODULE_SHOULD_BE_ESM', type: 'error' },
{ code: 'EXPORTS_VALUE_INVALID', type: 'error' },
{ code: 'FILE_DOES_NOT_EXIST', type: 'error' },
Expand Down
25 changes: 13 additions & 12 deletions site/src/pages/Package.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@
// prettier-ignore
`${import.meta.env.VITE_NPM_REGISTRY}/${encodeURIComponent(npmPkgName)}/latest`
)
.then(async (res) => {
const result = await res.json()
if (typeof result === 'string') {
error = result
return
}
if (result?.version) {
url.replace(`/${npmPkgName}@${result.version}`)
}
}).finally(() => {
versionFetched = true
})
.then(async (res) => {
const result = await res.json()
if (typeof result === 'string') {
error = result
return
}
if (result?.version) {
url.replace(`/${npmPkgName}@${result.version}`)
}
})
.finally(() => {
versionFetched = true
})
}
/** @type {Worker} */
Expand Down

0 comments on commit 987d780

Please sign in to comment.