Socket
Socket
Sign inDemoInstall

publint

Package Overview
Dependencies
Maintainers
1
Versions
31
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.0.1 to 0.1.0

10

lib/index.d.ts

@@ -22,2 +22,3 @@ export type MessageType = 'suggestion' | 'warning' | 'error'

// TODO: Check nodejs modules usage
export type Message =

@@ -53,4 +54,9 @@ | BaseMessage<

| BaseMessage<'EXPORTS_GLOB_NO_MATCHED_FILES'>
// TODO
// | BaseMessage<'EXPORTS_GLOB_NO_MATCHED_FILES_BUT_IMPLICIT_INDEX_DETECTED'>
| BaseMessage<
'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING',
{
expectPath: string[]
expectValue: string
}
>
| BaseMessage<'EXPORTS_TYPES_SHOULD_BE_FIRST'>

@@ -57,0 +63,0 @@ | BaseMessage<'EXPORTS_DEFAULT_SHOULD_BE_LAST'>

2

package.json
{
"name": "publint",
"version": "0.0.1",
"version": "0.1.0",
"description": "Lint packaging errors",

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

@@ -1,5 +0,23 @@

# publint
<br>
Lint before you publish! Catch packaging errors and ensure compatibility across environments.
<p align="center">
<img src="https://user-images.githubusercontent.com/34116392/172312754-0407aeaa-d7a6-4ada-8bc0-ea80bc314f5f.svg" height="80">
</p>
<h1 align="center">
publint
</h1>
<p align="center">
Lint packaging errors. Ensure compatibility across environments.
</p>
<p align="center">
<a href="https://publint.bjornlu.com">
<strong>Try it online</strong>
</a>
</p>
<br>
This package contains a CLI and API to lint packages locally. The package to be linted must exist and be built locally for the lint to succeed. To test other npm packages, try https://publint.bjornlu.com.

@@ -28,3 +46,3 @@

const messages = await publint({
/**
/**
* Path to your package that contains a package.json file.

@@ -31,0 +49,0 @@ * Defaults to `process.cwd()` in node, `/` in browser.

@@ -16,2 +16,5 @@ import {

const messages = []
/**
* A promise queue is created to run all linting tasks in parallel
*/
const promiseQueue = createPromiseQueue()

@@ -26,2 +29,13 @@

/**
* @param {string} filePath
*/
function isPathLintable(filePath) {
return (
filePath.endsWith('.js') ||
filePath.endsWith('.mjs') ||
filePath.endsWith('.cjs')
)
}
/**
* @param {string} path

@@ -74,3 +88,3 @@ * @param {string[]} pkgPath

},
path: [],
path: ['name'],
type: 'warning'

@@ -169,2 +183,39 @@ })

crawlExports(exports)
} else {
// all files can be accessed. verify them all
promiseQueue.push(async () => {
const files = await exportsGlob(vfs.pathJoin(pkgDir, './*'), vfs)
const pq = createPromiseQueue()
for (const filePath of files) {
if (!isPathLintable(filePath)) continue
pq.push(async () => {
const fileContent = await readFile(filePath, [])
if (fileContent === false) return
const actualFormat = getCodeFormat(fileContent)
let expectFormat = await getFilePathFormat(filePath, vfs)
if (
actualFormat !== expectFormat &&
actualFormat !== 'unknown' &&
actualFormat !== 'mixed'
) {
const actualExtension = vfs.getExtName(filePath)
messages.push({
code: isExplicitExtension(actualExtension)
? 'FILE_INVALID_EXPLICIT_FORMAT'
: 'FILE_INVALID_FORMAT',
args: {
actualFormat,
expectFormat,
actualExtension,
expectExtension: getCodeFormatExtension(actualFormat),
actualFilePath: '/' + vfs.pathRelative(pkgDir, filePath)
},
path: ['name'],
type: 'warning'
})
}
})
}
await pq.wait()
})
}

@@ -186,2 +237,20 @@

promiseQueue.push(async () => {
// https://nodejs.org/docs/latest-v16.x/api/packages.html#subpath-folder-mappings
if (exports.endsWith('/')) {
const expectPath = currentPath.map((part) => {
return part.endsWith('/') ? part + '*' : part
})
messages.push({
code: 'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING',
args: {
expectPath,
expectValue: exports + '*'
},
path: currentPath,
type: 'warning'
})
// Help fix glob so we can further analyze other issues
exports += '*'
}
const exportsPath = vfs.pathJoin(pkgDir, exports)

@@ -196,5 +265,3 @@ const isGlob = exports.includes('*')

code: 'EXPORTS_GLOB_NO_MATCHED_FILES',
args: {
pattern: exports
},
args: {},
path: currentPath,

@@ -208,5 +275,6 @@ type: 'warning'

// todo: group glob warnings
// TODO: group glob warnings
for (const filePath of exportsFiles) {
if (filePath.endsWith('.d.ts')) continue
// TODO: Maybe check .ts in the future
if (!isPathLintable(filePath)) continue
pq.push(async () => {

@@ -213,0 +281,0 @@ // Could fail if in !isGlob

@@ -30,3 +30,3 @@ import c from 'picocolors'

// prettier-ignore
return `${c.bold(fp(m.path))} is ${pv(m.path)} but file does not exist`
return `${c.bold(fp(m.path))} is ${pv(m.path)} but file does not exist.`
case 'HAS_ESM_MAIN_BUT_NO_EXPORTS':

@@ -39,3 +39,2 @@ // prettier-ignore

case 'MODULE_SHOULD_BE_ESM':
// TODO: Show how we know this? Likely case is `type: module`
// prettier-ignore

@@ -45,3 +44,6 @@ return `${c.bold('pkg.module')} should be ESM, but the code is written in CJS.`

// prettier-ignore
return `${c.bold(fp(m.path))} is ${c.bold(pv(m.path))} but does not match any files`
return `${c.bold(fp(m.path))} is ${c.bold(pv(m.path))} but does not match any files.`
case 'EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING':
// prettier-ignore
return `${c.bold(fp(m.path))} maps to a path that ends with ${c.bold('/')} which is deprecated. Use ${c.bold(fp(m.args.expectPath))}: "${c.bold(m.args.expectValue)}" instead.`
case 'EXPORTS_TYPES_SHOULD_BE_FIRST':

@@ -48,0 +50,0 @@ // prettier-ignore

@@ -70,5 +70,10 @@ /**

const [dir, ext] = globStr.split('*')
await scanDir(dir)
if (await vfs.isPathDir(dir)) {
await scanDir(dir)
}
return filePaths
/**
* @param {string} dirPath
*/
async function scanDir(dirPath) {

@@ -143,3 +148,3 @@ const items = await vfs.readDir(dirPath)

export function formatMessagePath(path) {
let formatted = 'pkg.'
let formatted = 'pkg'
for (const part of path) {

@@ -150,3 +155,3 @@ // is invalid js var name

} else {
formatted += part
formatted += '.' + part
}

@@ -153,0 +158,0 @@ }

@@ -18,3 +18,7 @@ import fs from 'node:fs'

async isPathDir(path) {
return (await fsp.stat(path)).isDirectory()
try {
return (await fsp.stat(path)).isDirectory()
} catch {
return false
}
},

@@ -21,0 +25,0 @@ async isPathExist(path) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc