Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

publint

Package Overview
Dependencies
Maintainers
1
Versions
32
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.1.13 to 0.1.14

4

index.d.ts

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

| BaseMessage<'EXPORTS_TYPES_SHOULD_BE_FIRST'>
| BaseMessage<
'EXPORTS_MODULE_SHOULD_PRECEED_IMPORT_REQUIRE',
{ conditions: string[] }
>
| BaseMessage<'EXPORTS_DEFAULT_SHOULD_BE_LAST'>

@@ -63,0 +67,0 @@ | BaseMessage<'EXPORTS_MODULE_SHOULD_BE_ESM'>

2

lib/browser.js
import { publint as _publint } from '../src/index.js'
/**
* @type {import('..').publint}
* @type {import('../index.d.ts').publint}
*/

@@ -6,0 +6,0 @@ export function publint(options) {

@@ -1,2 +0,1 @@

import fs from 'node:fs/promises'
import path from 'node:path'

@@ -8,3 +7,3 @@ import packlist from 'npm-packlist'

/**
* @type {import('..').publint}
* @type {import('../index.d.ts').publint}
*/

@@ -11,0 +10,0 @@ export async function publint(options) {

@@ -5,3 +5,3 @@ export { formatMessagePath, getPkgPathValue } from '../src/utils.js'

* no-op. leave users to implement themselves.
* @type {import('../utils').printMessage}
* @type {import('../utils.d.ts').printMessage}
*/

@@ -8,0 +8,0 @@ export function printMessage() {

{
"name": "publint",
"version": "0.1.13",
"version": "0.1.14",
"description": "Lint packaging errors",

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

@@ -9,3 +9,5 @@ import {

getPublishedField,
objectHasKeyNested
objectHasKeyNested,
isFilePathLintable,
isFileContentLintable
} from './utils.js'

@@ -17,3 +19,3 @@

* Currently only used if pkg has no `exports`
* @typedef {Required<import('..').Options> & {
* @typedef {Required<import('../index.d.ts').Options> & {
* _packedFiles?: string[]

@@ -25,6 +27,6 @@ * }} Options

* @param {Options} options
* @returns {Promise<import('..').Message[]>}
* @returns {Promise<import('../index.js').Message[]>}
*/
export async function publint({ pkgDir, vfs, level, strict, _packedFiles }) {
/** @type {import('..').Message[]} */
/** @type {import('../index.d.ts').Message[]} */
const messages = []

@@ -45,13 +47,2 @@ /**

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

@@ -265,6 +256,7 @@ * @param {string[]} [pkgPath] current path that tries to read this file.

for (const filePath of files) {
if (!isPathLintable(filePath)) continue
if (!isFilePathLintable(filePath)) continue
pq.push(async () => {
const fileContent = await readFile(filePath, [])
if (fileContent === false) return
if (!isFileContentLintable(fileContent)) return
const actualFormat = getCodeFormat(fileContent)

@@ -417,3 +409,3 @@ const expectFormat = await getFilePathFormat(filePath, vfs)

// TODO: maybe check .ts in the future
if (!isPathLintable(filePath)) continue
if (!isFilePathLintable(filePath)) continue
pq.push(async () => {

@@ -423,2 +415,3 @@ // could fail if in !isGlob

if (fileContent === false) return
if (!isFileContentLintable(fileContent)) return
// the `module` condition is only used by bundlers and must be ESM

@@ -510,2 +503,28 @@ if (currentPath.includes('module')) {

// a 'module' export should always preceed 'import' or 'require'
if ('module' in exports) {
const conditions = []
if (
'require' in exports &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('require')
) {
conditions.push('require')
}
if (
'import' in exports &&
exportsKeys.indexOf('module') > exportsKeys.indexOf('import')
) {
conditions.push('import')
}
if (conditions.length > 0) {
messages.push({
code: 'EXPORTS_MODULE_SHOULD_PRECEED_IMPORT_REQUIRE',
args: { conditions },
path: currentPath.concat('module'),
type: 'error'
})
}
}
// the default export should be the last condition

@@ -512,0 +531,0 @@ if (

@@ -5,4 +5,4 @@ import c from 'picocolors'

/**
* @param {import('..').Message} m
* @param {import('./utils').Pkg} pkg
* @param {import('../index.d.ts').Message} m
* @param {import('./utils.js').Pkg} pkg
*/

@@ -60,2 +60,12 @@ export function printMessage(m, pkg) {

return `${c.bold(fp(m.path))} should be the first in the object as required by TypeScript.`
case 'EXPORTS_MODULE_SHOULD_PRECEED_IMPORT_REQUIRE': {
let conditions = `the ${m.args.conditions
.map((cond) => `"${c.bold(cond)}"`)
.join(' and ')} condition`
if (m.args.conditions.length !== 1) {
conditions += 's'
}
// prettier-ignore
return `${c.bold(fp(m.path))} should come before ${conditions} so it can take precedence when used by a bundler.`
}
case 'EXPORTS_DEFAULT_SHOULD_BE_LAST':

@@ -72,3 +82,3 @@ // prettier-ignore

// prettier-ignore
return `${c.bold('pkg.browser')} can be refactored to use ${c.bold('pkg.exports')} and the ${c.bold('browser')} condition instead to declare browser-specific exports. (This will be a breaking change)`
return `${c.bold('pkg.browser')} can be refactored to use ${c.bold('pkg.exports')} and the ${c.bold('"browser"')} condition instead to declare browser-specific exports. (This will be a breaking change)`
case 'TYPES_NOT_EXPORTED': {

@@ -75,0 +85,0 @@ let target = fp(m.path)

@@ -18,2 +18,5 @@ /**

/([\s;]|^)(import[\w,{}\s*]*from|import\s*['"*{]|export\b\s*(?:[*{]|default|type|function|const|var|let|async function)|import\.meta\b)/m
/**
* @param {string} code
*/
export function isCodeEsm(code) {

@@ -26,2 +29,5 @@ return ESM_CONTENT_RE.test(code)

/([\s;]|^)(module.exports\b|exports\.\w|require\s*\(|global\.\w|Object\.(defineProperty|defineProperties|assign)\s*\(\s*exports\b)/m
/**
* @param {string} code
*/
export function isCodeCjs(code) {

@@ -33,2 +39,5 @@ return CJS_CONTENT_RE.test(code)

const SINGLELINE_COMMENTS_RE = /\/\/.*/g
/**
* @param {string} code
*/
export function stripComments(code) {

@@ -67,3 +76,3 @@ return code

* @param {string} globStr An absolute glob string that must contain one `*`
* @param {import('..').Vfs} vfs
* @param {import('../index.d.ts').Vfs} vfs
* @param {string[]} [packedFiles]

@@ -126,3 +135,6 @@ * @returns {Promise<string[]>} Matched file paths

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
/**
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
* @param {string} string
*/
function escapeRegExp(string) {

@@ -141,3 +153,3 @@ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')

* @param {string} filePath
* @param {import('..').Vfs} vfs
* @param {import('../index.d.ts').Vfs} vfs
* @returns {Promise<CodeFormat>}

@@ -180,5 +192,32 @@ */

/**
*
* only lint JS files. TS and others not supported.
* @param {string} filePath
* @param {import('..').Vfs} vfs
*/
export function isFilePathLintable(filePath) {
return (
filePath.endsWith('.js') ||
filePath.endsWith('.mjs') ||
filePath.endsWith('.cjs')
)
}
// support:
// // @flow
// /* @flow */
// /** @flow */
// /**
// * @flow
// */
const FLOW_COMMENT_RE = /^\s*(?:\/\/|\/\*\*?|\*)\s*@flow/m
/**
* don't lint Flow files, which is annotated by an initial `@flow` comment
* @param {string} fileContent
*/
export function isFileContentLintable(fileContent) {
return !FLOW_COMMENT_RE.test(fileContent)
}
/**
* @param {string} filePath
* @param {import('../index.d.ts').Vfs} vfs
* @returns {Promise<Pkg | undefined>}

@@ -210,4 +249,7 @@ */

for (const part of path) {
// is invalid js var name
if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(part)) {
if (/^\d+$/.test(part)) {
// plain number
formatted += `[${part}]`
} else if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(part)) {
// is invalid js var name
formatted += `["${part}"]`

@@ -214,0 +256,0 @@ } else {

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

* Creates a node-compatible Vfs object
* @returns {import('..').Vfs}
* @returns {import('../index.d.ts').Vfs}
*/

@@ -10,0 +10,0 @@ export function createNodeVfs() {

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