Comparing version 0.3.1 to 0.3.2
{ | ||
"name": "publint", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"description": "Lint packaging errors", | ||
@@ -31,7 +31,7 @@ "type": "module", | ||
"type": "git", | ||
"url": "git+https://github.com/bluwy/publint.git", | ||
"url": "git+https://github.com/publint/publint.git", | ||
"directory": "packages/publint" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/bluwy/publint/issues" | ||
"url": "https://github.com/publint/publint/issues" | ||
}, | ||
@@ -46,6 +46,6 @@ "keywords": [ | ||
"sade": "^1.8.1", | ||
"@publint/pack": "^0.1.0" | ||
"@publint/pack": "^0.1.1" | ||
}, | ||
"devDependencies": { | ||
"vitest": "^3.0.0-beta.3" | ||
"vitest": "^3.0.0-beta.4" | ||
}, | ||
@@ -52,0 +52,0 @@ "scripts": { |
@@ -72,3 +72,3 @@ <br> | ||
* - `'npm'`/`'yarn'`/`'pnpm'`/`'bun'`: Uses the respective package manager to pack. | ||
* - `{ tarball }`: Packs the package from the specified tarball represented as an ArrayBuffer. | ||
* - `{ tarball }`: Packs the package from the specified tarball represented as an `ArrayBuffer` or `ReadableStream`. | ||
* - `{ files }`: Packs the package using the specified files. | ||
@@ -79,5 +79,7 @@ * - `false`: Skips packing the package. This should only be used if all the files | ||
* **Environment notes:** | ||
* - **Node.js**: Defaults to `'auto'`. All options above are supported. | ||
* - **Browser**: Only `{ tarball: ArrayBuffer }` and `{ files: PackFile[] }` are supported and either **must | ||
* be passed** to work, as the browser does not have access to the file system. | ||
* - **Node.js**: Defaults to `'auto'`. All options above are supported. When using a package manager | ||
* to pack, lifecycle scripts like `prepare`, `prepack`, and `postpack` are ignored | ||
* (except for yarn as it does not allow ignoring lifecycle scripts). | ||
* - **Browser**: Only `{ tarball }` and `{ files }` are supported and either **must be passed** to work, | ||
* as the browser does not have access to the file system. | ||
*/ | ||
@@ -88,3 +90,3 @@ pack: 'pnpm', | ||
*/ | ||
strict: true | ||
strict: true, | ||
}) | ||
@@ -102,3 +104,3 @@ | ||
const pkg = JSON.parse( | ||
await fs.readFile('./path/to/package/package.json', 'utf8') | ||
await fs.readFile('./path/to/package/package.json', 'utf8'), | ||
) | ||
@@ -130,3 +132,3 @@ | ||
const response = await fetch( | ||
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz' | ||
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz', | ||
) | ||
@@ -155,3 +157,3 @@ if (!response.body) throw new Error('Failed to fetch tarball') | ||
const response = await fetch( | ||
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz' | ||
'https://registry.npmjs.org/mylib/-/mylib-1.0.0.tgz', | ||
) | ||
@@ -158,0 +160,0 @@ if (!response.body) throw new Error('Failed to fetch tarball') |
@@ -19,3 +19,3 @@ #!/usr/bin/env node | ||
`Level of messages to log ('suggestion' | 'warning' | 'error')`, | ||
'suggestion' | ||
'suggestion', | ||
) | ||
@@ -25,3 +25,3 @@ .option( | ||
`Package manager to use for packing ('auto' | 'npm' | 'yarn' | 'pnpm' | 'bun' | false)`, | ||
'auto' | ||
'auto', | ||
) | ||
@@ -32,3 +32,3 @@ .option('--strict', `Report warnings as errors`, false) | ||
.command('run [dir]', 'Lint a directory (defaults to current directory)', { | ||
default: true | ||
default: true, | ||
}) | ||
@@ -99,3 +99,3 @@ .action(async (dir, opts) => { | ||
depDir.includes('node_modules') ? false : opts.pack, | ||
true | ||
true, | ||
) | ||
@@ -156,3 +156,3 @@ : [] | ||
suggestions.forEach((m, i) => | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)) | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)), | ||
) | ||
@@ -165,3 +165,3 @@ } | ||
warnings.forEach((m, i) => | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)) | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)), | ||
) | ||
@@ -174,3 +174,3 @@ } | ||
errors.forEach((m, i) => | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)) | ||
logs.push(c.dim(`${i + 1}. `) + formatMessage(m, rootPkg)), | ||
) | ||
@@ -177,0 +177,0 @@ process.exitCode = 1 |
@@ -12,3 +12,3 @@ import { unpack } from '@publint/pack' | ||
throw new Error( | ||
'[publint] The `pack` option must be set to an object with `tarball` or `files` to work in the browser' | ||
'[publint] The `pack` option must be set to an object with `tarball` or `files` to work in the browser', | ||
) | ||
@@ -33,4 +33,4 @@ } | ||
level: options.level ?? 'suggestion', | ||
strict: options?.strict ?? false | ||
strict: options?.strict ?? false, | ||
}) | ||
} |
@@ -36,16 +36,3 @@ import path from 'node:path' | ||
const pkgDir = options?.pkgDir ?? process.cwd() | ||
let packageManager = pack | ||
if (packageManager === 'auto') { | ||
let detected = (await detect({ cwd: pkgDir }))?.name ?? 'npm' | ||
// Deno is not supported in `@publint/pack` (doesn't have a pack command) | ||
if (detected === 'deno') { | ||
detected = 'npm' | ||
} | ||
packageManager = detected | ||
} | ||
packedFiles = (await packAsList(pkgDir, { packageManager })).map((file) => | ||
path.join(pkgDir, file) | ||
) | ||
packedFiles = await detectAndPack(pkgDir, pack) | ||
} | ||
@@ -60,4 +47,46 @@ vfs = createNodeVfs() | ||
strict: options?.strict ?? false, | ||
_packedFiles: packedFiles | ||
_packedFiles: packedFiles, | ||
}) | ||
} | ||
/** | ||
* @typedef {T extends string ? T : never} ExtractStringLiteral | ||
* @template T | ||
*/ | ||
/** | ||
* @param {string} pkgDir | ||
* @param {ExtractStringLiteral<import('./index.d.ts').Options['pack']>} pack | ||
*/ | ||
async function detectAndPack(pkgDir, pack) { | ||
let packageManager = pack | ||
if (packageManager === 'auto') { | ||
let detected = (await detect({ cwd: pkgDir }))?.name ?? 'npm' | ||
// Deno is not supported in `@publint/pack` (doesn't have a pack command) | ||
if (detected === 'deno') { | ||
detected = 'npm' | ||
} | ||
packageManager = detected | ||
} | ||
// When packing, we want to ignore scripts as `publint` itself could be used in one of them and could | ||
// cause an infinite loop. Also, running scripts might be slow and unexpected. | ||
// Yarn does not support ignoring scripts. If we know we're in a lifecycle event, try to warn about an infinite loop. | ||
// NOTE: this is not foolproof as one could invoke `yarn run <something>` within the lifecycle event, causing us | ||
// to unable to check if we're in a problematic lifecycle event. | ||
if ( | ||
packageManager === 'yarn' && | ||
['prepack', 'postpack'].includes(process.env.npm_lifecycle_event ?? '') | ||
) { | ||
throw new Error( | ||
`[publint] publint requires running \`yarn pack\` to lint the package, however, ` + | ||
`it is also being executed in the "${process.env.npm_lifecycle_event}" lifecycle event, ` + | ||
`which causes an infinite loop. Try to run publint outside of the lifecycle event instead.`, | ||
) | ||
} | ||
const list = await packAsList(pkgDir, { packageManager, ignoreScripts: true }) | ||
return list.map((file) => path.join(pkgDir, file)) | ||
} |
@@ -155,3 +155,3 @@ export type MessageType = 'suggestion' | 'warning' | 'error' | ||
* - `'npm'`/`'yarn'`/`'pnpm'`/`'bun'`: Uses the respective package manager to pack. | ||
* - `{ tarball }`: Packs the package from the specified tarball represented as an ArrayBuffer or ReadableStream. | ||
* - `{ tarball }`: Packs the package from the specified tarball represented as an`ArrayBuffer` or `ReadableStream`. | ||
* - `{ files }`: Packs the package using the specified files. | ||
@@ -162,5 +162,7 @@ * - `false`: Skips packing the package. This should only be used if all the files | ||
* **Environment notes:** | ||
* - **Node.js**: Defaults to `'auto'`. All options above are supported. | ||
* - **Browser**: Only `{ tarball: ArrayBuffer | ReadableStream }` and `{ files: PackFile[] }` are supported | ||
* and either **must be passed** to work, as the browser does not have access to the file system. | ||
* - **Node.js**: Defaults to `'auto'`. All options above are supported. When using a package manager | ||
* to pack, lifecycle scripts like `prepack` and `postpack` are ignored | ||
* (except for yarn as it does not allow ignoring lifecycle scripts). | ||
* - **Browser**: Only `{ tarball }` and `{ files }` are supported and either **must be passed** to work, | ||
* as the browser does not have access to the file system. | ||
*/ | ||
@@ -167,0 +169,0 @@ pack?: |
@@ -5,3 +5,3 @@ import picocolors from 'picocolors' | ||
getPkgPathValue, | ||
replaceLast | ||
replaceLast, | ||
} from '../shared/utils.js' | ||
@@ -8,0 +8,0 @@ |
@@ -38,4 +38,4 @@ import fs from 'node:fs' | ||
return nodePath.extname(path) | ||
} | ||
}, | ||
} | ||
} |
@@ -16,3 +16,3 @@ // extensions that publint is able to parse and lint. while there's partial support | ||
// Vercel Edge: https://runtime-keys.proposal.wintercg.org/#edge-light | ||
'edge-light' | ||
'edge-light', | ||
] | ||
@@ -32,3 +32,3 @@ | ||
'.eslintrc', | ||
'.eslintrc.js' | ||
'.eslintrc.js', | ||
] | ||
@@ -35,0 +35,0 @@ |
@@ -5,3 +5,3 @@ import { | ||
knownBrowserishConditions, | ||
licenseFiles | ||
licenseFiles, | ||
} from './constants.js' | ||
@@ -31,3 +31,3 @@ import { | ||
isShorthandGitHubOrGitLabUrl, | ||
isDeprecatedGitHubGitUrl | ||
isDeprecatedGitHubGitUrl, | ||
} from './utils.js' | ||
@@ -93,3 +93,3 @@ | ||
path: ['name'], | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -120,3 +120,3 @@ break | ||
path: ['name'], | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -138,3 +138,3 @@ } | ||
path: ['dependencies', depName], | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -153,3 +153,3 @@ } | ||
path: ['name'], | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -179,6 +179,6 @@ } | ||
actualFormat, | ||
expectFormat | ||
expectFormat, | ||
}, | ||
path: ['name'], | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -201,3 +201,3 @@ } | ||
'.js', | ||
'/index.js' | ||
'/index.js', | ||
]) | ||
@@ -223,6 +223,6 @@ if (mainContent === false) return | ||
actualExtension, | ||
expectExtension: getCodeFormatExtension(actualFormat) | ||
expectExtension: getCodeFormatExtension(actualFormat), | ||
}, | ||
path: mainPkgPath, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -235,3 +235,3 @@ } | ||
path: mainPkgPath, | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -254,3 +254,3 @@ } | ||
'.js', | ||
'/index.js' | ||
'/index.js', | ||
]) | ||
@@ -266,3 +266,3 @@ if (moduleContent === false) return | ||
path: modulePkgPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -276,3 +276,3 @@ } | ||
path: modulePkgPath, | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -305,3 +305,3 @@ } | ||
path: exportsPkgPath, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -324,7 +324,7 @@ } | ||
'unpkg', | ||
'jsdelivr' | ||
'jsdelivr', | ||
] | ||
// if has typesVersions field, it complicates `types`/`typings` field resolution a lot. | ||
// for now skip it, but further improvements are tracked at | ||
// https://github.com/bluwy/publint/issues/42 | ||
// https://github.com/publint/publint/issues/42 | ||
if (getPublishedField(rootPkg, 'typesVersions')[0]) { | ||
@@ -354,3 +354,3 @@ knownFields.splice(0, 2) | ||
// as the jsnext fields are likely for compat only. | ||
type: module ? 'suggestion' : 'warning' | ||
type: module ? 'suggestion' : 'warning', | ||
}) | ||
@@ -374,3 +374,3 @@ } | ||
path: browserPkgPath, | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -382,3 +382,3 @@ } else { | ||
path: browserPkgPath, | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -400,3 +400,3 @@ } | ||
vfs, | ||
_packedFiles | ||
_packedFiles, | ||
) | ||
@@ -409,3 +409,3 @@ const pq = createPromiseQueue() | ||
['name'], | ||
'/' + vfs.pathRelative(pkgDir, filePath) | ||
'/' + vfs.pathRelative(pkgDir, filePath), | ||
) | ||
@@ -442,3 +442,3 @@ ) | ||
actualExtension, | ||
expectExtension | ||
expectExtension, | ||
) | ||
@@ -456,6 +456,6 @@ if (await vfs.isPathExist(expectFilePath)) return | ||
expectExtension, | ||
actualFilePath: '/' + vfs.pathRelative(pkgDir, filePath) | ||
actualFilePath: '/' + vfs.pathRelative(pkgDir, filePath), | ||
}, | ||
path: ['name'], | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -520,3 +520,3 @@ } | ||
path: pkgPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -544,3 +544,3 @@ } | ||
path: ['repository'], | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -558,3 +558,3 @@ } | ||
path: ['repository', 'url'], | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -566,3 +566,3 @@ } else if (isDeprecatedGitHubGitUrl(repository.url)) { | ||
path: ['repository', 'url'], | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -574,3 +574,3 @@ } else if (isShorthandGitHubOrGitLabUrl(repository.url)) { | ||
path: ['repository', 'url'], | ||
type: 'suggestion' | ||
type: 'suggestion', | ||
}) | ||
@@ -589,3 +589,3 @@ } | ||
path: pkgPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -606,6 +606,6 @@ } | ||
actualExtension: matched, | ||
globbedFilePath | ||
globbedFilePath, | ||
}, | ||
path: currentPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -629,6 +629,6 @@ return true | ||
actualType: typeof fieldValue, | ||
expectTypes | ||
expectTypes, | ||
}, | ||
path: pkgPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -678,3 +678,3 @@ return false | ||
currentPath, | ||
isAfterNodeCondition = false | ||
isAfterNodeCondition = false, | ||
) { | ||
@@ -694,3 +694,3 @@ if (typeof exportsValue === 'string') { | ||
expectPath, | ||
expectValue: exportsValue + '*' | ||
expectValue: exportsValue + '*', | ||
}, | ||
@@ -700,3 +700,3 @@ path: currentPath, | ||
// lower severity to suggestion instead. | ||
type: expectPathAlreadyExist ? 'suggestion' : 'warning' | ||
type: expectPathAlreadyExist ? 'suggestion' : 'warning', | ||
}) | ||
@@ -712,6 +712,6 @@ // help fix glob so we can further analyze other issues | ||
args: { | ||
suggestValue: './' + exportsValue.replace(/^[\/]+/, '') | ||
suggestValue: './' + exportsValue.replace(/^[\/]+/, ''), | ||
}, | ||
path: currentPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -728,3 +728,3 @@ } | ||
path: currentPath, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -739,3 +739,3 @@ return | ||
const browserishCondition = knownBrowserishConditions.find((c) => | ||
currentPath.includes(c) | ||
currentPath.includes(c), | ||
) | ||
@@ -747,6 +747,6 @@ if (browserishCondition) { | ||
browserPath: browserPkgPath.concat(exportsValue), | ||
browserishCondition | ||
browserishCondition, | ||
}, | ||
path: currentPath, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -764,3 +764,3 @@ } | ||
currentPath, | ||
isGlob ? './' + vfs.pathRelative(pkgDir, filePath) : undefined | ||
isGlob ? './' + vfs.pathRelative(pkgDir, filePath) : undefined, | ||
) | ||
@@ -791,3 +791,3 @@ ) | ||
path: currentPath, | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -825,3 +825,3 @@ } | ||
actualExtension, | ||
expectExtension | ||
expectExtension, | ||
) | ||
@@ -842,6 +842,6 @@ if (await vfs.isPathExist(expectFilePath)) return | ||
? './' + vfs.pathRelative(pkgDir, filePath) | ||
: exportsValue | ||
: exportsValue, | ||
}, | ||
path: currentPath, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -881,3 +881,3 @@ } | ||
path: currentPath.concat('types'), | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -898,3 +898,3 @@ } | ||
path: currentPath.concat('module'), | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -912,3 +912,3 @@ } | ||
path: currentPath.concat('default'), | ||
type: 'error' | ||
type: 'error', | ||
}) | ||
@@ -925,3 +925,3 @@ } | ||
currentPath.concat(key), | ||
isKeyAfterNodeCondition | ||
isKeyAfterNodeCondition, | ||
) | ||
@@ -983,3 +983,3 @@ if (key === 'node') { | ||
['types', format, env].filter(Boolean), | ||
exportsPath | ||
exportsPath, | ||
) | ||
@@ -1010,3 +1010,3 @@ | ||
resolvedPath, | ||
vfs | ||
vfs, | ||
) | ||
@@ -1028,3 +1028,3 @@ | ||
[format, env].filter(Boolean), | ||
exportsPath | ||
exportsPath, | ||
) | ||
@@ -1034,3 +1034,3 @@ if (nonTypesResult?.value) { | ||
pkgDir, | ||
nonTypesResult.value | ||
nonTypesResult.value, | ||
) | ||
@@ -1040,3 +1040,3 @@ if (await vfs.isPathExist(nonTypesResolvedPath)) { | ||
nonTypesResolvedPath, | ||
vfs | ||
vfs, | ||
) | ||
@@ -1062,6 +1062,6 @@ } | ||
actualExtension: vfs.getExtName(result.value), | ||
expectExtension: getDtsCodeFormatExtension(dtsExpectFormat) | ||
expectExtension: getDtsCodeFormatExtension(dtsExpectFormat), | ||
}, | ||
path: result.path, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -1072,3 +1072,3 @@ } | ||
const hasAdjacentDtsFile = await vfs.isPathExist( | ||
vfs.pathJoin(pkgDir, getAdjacentDtsPath(result.value)) | ||
vfs.pathJoin(pkgDir, getAdjacentDtsPath(result.value)), | ||
) | ||
@@ -1082,3 +1082,3 @@ // if there's no adjacent dts file, it's likely they don't support moduleResolution: bundler. | ||
vfs.pathJoin(pkgDir, typesFilePath), | ||
vfs | ||
vfs, | ||
) | ||
@@ -1099,6 +1099,6 @@ const dtsExpectFormat = format === 'import' ? 'ESM' : 'CJS' | ||
? undefined | ||
: getDtsCodeFormatExtension(dtsExpectFormat) | ||
: getDtsCodeFormatExtension(dtsExpectFormat), | ||
}, | ||
path: result.path, | ||
type: 'warning' | ||
type: 'warning', | ||
}) | ||
@@ -1105,0 +1105,0 @@ } |
@@ -137,3 +137,3 @@ import { lintableFileExtensions } from './constants.js' | ||
const globStrRe = new RegExp( | ||
`^${slash(globStr).split('*').map(escapeRegExp).join('(.+)')}$` | ||
`^${slash(globStr).split('*').map(escapeRegExp).join('(.+)')}$`, | ||
) | ||
@@ -375,3 +375,3 @@ // the longest directory that doesn't contain `*` | ||
push: (/** @type {Function} */ fn) => promises.push(fn()), | ||
wait: () => Promise.all(promises) | ||
wait: () => Promise.all(promises), | ||
} | ||
@@ -439,3 +439,3 @@ } | ||
currentPath = [], | ||
_metadata = { dualPublish: false } | ||
_metadata = { dualPublish: false }, | ||
) { | ||
@@ -450,3 +450,3 @@ if (typeof exportsValue === 'string') { | ||
currentPath.concat('0'), | ||
_metadata | ||
_metadata, | ||
) | ||
@@ -471,3 +471,3 @@ } | ||
currentPath.concat(key), | ||
_metadata | ||
_metadata, | ||
) | ||
@@ -474,0 +474,0 @@ } |
@@ -19,3 +19,3 @@ /** | ||
return files.some( | ||
(file) => file.name === path || file.name.startsWith(pathDirVariant) | ||
(file) => file.name === path || file.name.startsWith(pathDirVariant), | ||
) | ||
@@ -45,4 +45,4 @@ }, | ||
} | ||
} | ||
}, | ||
} | ||
} |
@@ -20,3 +20,3 @@ import type { Message } from './index.js' | ||
pkg: Pkg, | ||
opts?: FormatMessageOptions | ||
opts?: FormatMessageOptions, | ||
): string | undefined |
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
91976
2317
165
2
Updated@publint/pack@^0.1.1