🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

publint

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

publint - npm Package Compare versions

Comparing version
0.3.18
to
0.3.19
+3
-3
package.json
{
"name": "publint",
"version": "0.3.18",
"version": "0.3.19",
"description": "Lint packaging errors",

@@ -48,5 +48,5 @@ "type": "module",

"@types/prompts": "^2.4.9",
"fs-fixture": "^2.11.0",
"fs-fixture": "^2.13.0",
"prompts": "^2.4.2",
"vitest": "^4.0.18"
"vitest": "^4.1.5"
},

@@ -53,0 +53,0 @@ "scripts": {

@@ -203,3 +203,5 @@ #!/usr/bin/env node

cli.parse(process.argv)
if (!process.env.PUBLINT_INTERNAL_SKIP_CLI_RUN) {
cli.parse(process.argv)
}

@@ -206,0 +208,0 @@ /**

@@ -135,2 +135,6 @@ export type MessageType = 'suggestion' | 'warning' | 'error'

| BaseMessage<'CJS_WITH_ESMODULE_DEFAULT_EXPORT', { filePath?: string }>
| BaseMessage<
'NESTED_PACKAGE_JSON_FIELD_IGNORED',
{ field: 'exports' | 'imports'; filePath: string }
>

@@ -137,0 +141,0 @@ export interface PackFile {

@@ -52,5 +52,4 @@ import {

/**
* Includes internal _include that used to filter paths that is packed.
* Includes internal _packedFiles that used to filter paths that is packed.
* Mainly for node.js local usage only. So that we lint files that are packed only.
* Currently only used if pkg has no `exports`
* @typedef {Omit<Required<import('../index.d.ts').Options>, 'pack'> & {

@@ -433,2 +432,9 @@ * vfs: Vfs,

// Check if any nested package.json files have "exports" or "imports" fields, which
// Node.js ignores outside the package root (see https://github.com/nodejs/node/issues/58827).
// Some bundlers may still read them which can lead to inconsistent resolution.
promiseQueue.push(async () => {
await crawlNestedPackageJson(pkgDir)
})
await promiseQueue.wait()

@@ -1220,2 +1226,56 @@

/**
* @param {string} dir
*/
async function crawlNestedPackageJson(dir) {
const nestedPackageJsonFields = /** @type {const} */ (['exports', 'imports'])
let items
try {
items = await vfs.readDir(dir)
} catch {
return
}
for (const item of items) {
if (item === 'node_modules') continue
const itemPath = vfs.pathJoin(dir, item)
if (await vfs.isPathDir(itemPath)) {
// If packed files are known, skip directories that don't contain
// any published files to reduce unnecessary traversal.
if (_packedFiles && !_packedFiles.some((f) => isPathNestedWithin(f, itemPath))) {
continue
}
await crawlNestedPackageJson(itemPath)
continue
}
if (item !== 'package.json' || itemPath === rootPkgPath) continue
if (_packedFiles && !_packedFiles.includes(itemPath)) continue
let nestedPkg
try {
const content = await vfs.readFile(itemPath)
nestedPkg = JSON.parse(content)
} catch {
continue
}
const filePath = './' + vfs.pathRelative(pkgDir, itemPath)
for (const field of nestedPackageJsonFields) {
if (nestedPkg[field] != null) {
messages.push({
code: 'NESTED_PACKAGE_JSON_FIELD_IGNORED',
args: { field, filePath },
path: ['name'],
type: 'warning',
})
}
}
}
}
/**
* @param {string} childPath
* @param {string} dirPath
*/
function isPathNestedWithin(childPath, dirPath) {
return childPath.startsWith(dirPath + '/') || childPath.startsWith(dirPath + '\\')
}
/**
* @param {any} binValue

@@ -1222,0 +1282,0 @@ * @param {string[]} currentPath

@@ -245,2 +245,5 @@ import picocolors from 'picocolors'

}
case 'NESTED_PACKAGE_JSON_FIELD_IGNORED': {
return `${h.bold(m.args.filePath)} has an ${h.bold(`"${m.args.field}"`)} field, but it is ignored by Node.js. The field only works in root ${h.bold('package.json')} files and not nested ones. Some bundlers may still pick them up, leading to inconsistent resolution. Consider removing it.`
}
default:

@@ -247,0 +250,0 @@ return

@@ -24,5 +24,13 @@ /**

path = path.endsWith('/') ? path : path + '/'
return files
.filter((file) => file.name.startsWith(path) && file.name !== path)
.map((file) => file.name.slice(path.length))
/** @type {string[]} */
const items = []
for (const file of files) {
if (file.name.startsWith(path) && file.name !== path) {
const item = file.name.slice(path.length).replace(/\/.*$/, '')
if (!items.includes(item)) {
items.push(item)
}
}
}
return items
},

@@ -29,0 +37,0 @@ readFile: async (path) => {