Skip to content

Commit

Permalink
Merge pull request #34 from KID-joker/feat-ignore
Browse files Browse the repository at this point in the history
feat(#32): support ignore option
  • Loading branch information
KID-joker authored Jan 6, 2025
2 parents 52396b1 + d8a3fb3 commit 5da05be
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 30 deletions.
35 changes: 31 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,40 @@ Commands:
help [command] display help for command
```
For `OpenAI` config:
`OpenAI` config:
```bash
Options:
--openaiKey <value> recommend alternative packages via ChatGPT
--openaiModel <value> ChatGPT model (choices: "gpt-3.5-turbo", "gpt-4", "gpt-4-turbo", "gpt-4o-mini", "gpt-4o")
--openaiBaseURL <value> override the default base URL for the API
--openaiKey <value> recommend alternative packages via ChatGPT
--openaiModel <value> ChatGPT model (choices: "gpt-3.5-turbo", "gpt-4", "gpt-4-turbo", "gpt-4o-mini", "gpt-4o")
--openaiBaseURL <value> override the default base URL for the API
```
For `current`:
```bash
Options:
--registry <value> specify registry URL, default: https://registry.npmjs.org/
--ignore <value> ignore specific packages, example: request,tslint
--failfast exit the program if it has been deprecated
```
For `global`:
```bash
Options:
-m, --manager <value> check specified package manager (choices: "npm", "yarn", "pnpm")
--registry <value> specify registry URL, default: https://registry.npmjs.org/
--ignore <value> ignore specific packages, example: request,tslint
--failfast exit the program if it has been deprecated
```
For `package`:
```bash
-r, --range <value> check specified versions
--registry <value> specify registry URL, default: https://registry.npmjs.org/
--failfast exit the program if it has been deprecated
```
You can also save them to global configuration:
Expand Down
5 changes: 5 additions & 0 deletions src/check.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CommonOption, PackageInfo, PackageVersions, VersionOrRange } from './types'
import process from 'node:process'
import ansis from 'ansis'
import fetch from 'node-fetch'
import semver from 'semver'
Expand Down Expand Up @@ -39,6 +40,10 @@ export async function checkDependencies(dependencies: Record<string, VersionOrRa
}
}
log()

if (config.failfast) {
process.exit(1)
}
}
}

Expand Down
35 changes: 20 additions & 15 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Command } from 'commander'
import type { CommonOption, ConfigOption, GlobalOption, PackageOption } from './types'
import type { CommonOption, ConfigOption, CurrentOption, GlobalOption, PackageOption } from './types'
import process from 'node:process'
import { Option, program } from 'commander'
import { version } from '../package.json'
Expand All @@ -21,22 +21,33 @@ program
.version(`npm-deprecated-check ${version}`)
.usage('<command> [options]')

program
.command('node')
.description('check if used node version is deprecated (reached End Of Life)')
.action(() => {
checkNode()
})

program
.command('current')
.description('check the packages of the current project')
.addOption(new Option('--ignore <value>', 'ignore specific packages'))
.addOption(new Option('--failfast', 'exit the program if it has been deprecated'))
.addOption(registryOption)
.addOption(gptOption)
.addOption(gptModelOption)
.addOption(gptBaseURL)
.action((option: CommonOption) => {
.action((option: CurrentOption) => {
checkNode()
checkCurrent(option)
})

program
.command('global')
.description('check global packages, default: npm')
.addOption(new Option('-m, --manger <value>', 'check specified package manger').choices(['npm', 'yarn', 'pnpm']).default('npm'))
.addOption(new Option('-m, --manager <value>', 'check specified package manager').choices(['npm', 'yarn', 'pnpm']).default('npm'))
.addOption(new Option('--ignore <value>', 'ignore specific packages'))
.addOption(new Option('--failfast', 'exit the program if it has been deprecated'))
.addOption(registryOption)
.addOption(gptOption)
.addOption(gptModelOption)
Expand All @@ -46,17 +57,11 @@ program
checkGlobal(globalOption)
})

program
.command('node')
.description('check if used node version is deprecated (reached End Of Life)')
.action(() => {
checkNode()
})

program
.command('package <packageName>')
.description('check for specified package')
.option('-r, --range <value>', 'check specified versions')
.addOption(new Option('-r, --range <value>', 'check specified versions'))
.addOption(new Option('--failfast', 'exit the program if it has been deprecated'))
.addOption(registryOption)
.addOption(gptOption)
.addOption(gptModelOption)
Expand All @@ -72,10 +77,10 @@ program
program
.command('config')
.description('inspect and modify the config')
.option('-g, --get <path>', 'get value from option')
.option('-s, --set <path> <value>', 'set option value')
.option('-d, --delete <path>', 'delete option from config')
.option('-l, --list', 'list all options')
.addOption(new Option('-g, --get <path>', 'get value from option'))
.addOption(new Option('-s, --set <path> <value>', 'set option value'))
.addOption(new Option('-d, --delete <path>', 'delete option from config'))
.addOption(new Option('-l, --list', 'list all options'))
.action((option: Record<string, any>, command: Command) => {
if (Object.keys(option).length === 0) {
command.outputHelp()
Expand Down
16 changes: 11 additions & 5 deletions src/io/current.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import type { CommonOption } from '../types'
import type { CurrentOption, VersionOrRange } from '../types'
import { checkDependencies } from '../check'
import { isGitPackage, isLocalPackage, isURLPackage } from '../filter'
import { getDependenciesOfLockfile } from '../packages/lockfiles'
import { getDependenciesOfPackageJson } from '../packages/package_json'
import { error } from '../utils/console'

export default async function checkCurrent(options: CommonOption) {
export default async function checkCurrent(options: CurrentOption) {
try {
const dependenciesOfPackageJson = getDependenciesOfPackageJson()

if (!dependenciesOfPackageJson)
return

const entries = Object.entries(dependenciesOfPackageJson)
.filter(ele => !isLocalPackage(ele[1].range as string) && !isURLPackage(ele[1].range as string) && !isGitPackage(ele[1].range as string))
const ignores = options.ignore?.split(',') || []

const npmDependencies = Object.fromEntries(entries)
const npmDependencies: Record<string, VersionOrRange> = {}

for (const name in dependenciesOfPackageJson) {
const versionInfo = dependenciesOfPackageJson[name]
if (!ignores.includes(name) && !isLocalPackage(versionInfo.range as string) && !isURLPackage(versionInfo.range as string) && !isGitPackage(versionInfo.range as string)) {
npmDependencies[name] = versionInfo
}
}

const dependenciesOfLockfile = await getDependenciesOfLockfile(npmDependencies)

Expand Down
5 changes: 4 additions & 1 deletion src/io/global.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { GlobalOption } from '../types'
import { checkDependencies } from '../check'
import { isLocalPackage } from '../filter'
import { error } from '../utils/console'
import { execCommand } from '../utils/exec'

Expand Down Expand Up @@ -30,7 +31,9 @@ export default function checkGlobal(options: GlobalOption) {
dependencies = result.dependencies
}

return checkDependencies(dependencies, openaiOptions)
const ignores = options.ignore?.split(',') || []

return checkDependencies(Object.fromEntries(Object.entries(dependencies).filter(([key, { version }]) => !ignores.includes(key) && !isLocalPackage(version))), openaiOptions)
}
catch (e: any) {
error(e.message)
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ export interface OpenaiOption {

export interface CommonOption extends OpenaiOption {
registry: string
failfast: boolean
}

export interface CurrentOption extends CommonOption {
ignore: string
}

export interface GlobalOption extends CommonOption {
manager: string
ignore: string
}

export interface PackageOption extends CommonOption {
Expand Down
38 changes: 33 additions & 5 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ import assert from 'node:assert/strict'
import { exec } from 'node:child_process'
import { test } from 'node:test'

test('node tests', async (t) => {
await t.test('test node version deprecation check', (_t, done) => {
exec('node ./dist/cli.mjs node', (_error, stdout, stderr) => {
assert.ok(/node version/.test(stdout) || /node version/.test(stderr), 'Expected "node version" to be mentioned in output.')
done()
})
})
})

test('current tests', async (t) => {
await t.test('check if no deprecation warning is shown', (_t, done) => {
exec('node ./dist/cli.mjs current', (_error, _stdout, stderr) => {
Expand All @@ -18,12 +27,22 @@ test('current tests', async (t) => {
done()
})
})
})

test('node tests', async (t) => {
await t.test('test node version deprecation check', (_t, done) => {
exec('node ./dist/cli.mjs node', (_error, stdout, stderr) => {
assert.ok(/node version/.test(stdout) || /node version/.test(stderr), 'Expected "node version" to be mentioned in output.')
await t.test('check if no deprecation warning is shown if ignore deprecated package', (_t, done) => {
exec('pnpm i request --force && node ./dist/cli.mjs current --ignore request', { timeout: 160000 }, (_error, _stdout, stderr) => {
assert.ok(!/has been deprecated/.test(stderr), 'Not expected "has been deprecated" to be mentioned in deprecation warning.')
// Cleanup: Undo the installation
exec('pnpm remove request')
done()
})
})

await t.test('check if exit the program if the package is deprecated', (_t, done) => {
exec('pnpm i request tslint --force && node ./dist/cli.mjs current --failfast', { timeout: 160000 }, (_error, _stdout, stderr) => {
assert.ok(/request has been deprecated/.test(stderr), 'Expected "has been deprecated" to be mentioned in deprecation warning.')
assert.ok(!/tslint has been deprecated/.test(stderr), 'Expected process.exit(1), only "request has been deprecated".')
// Cleanup: Undo the installation
exec('pnpm remove request tslint')
done()
})
})
Expand All @@ -36,6 +55,15 @@ test('global tests', async (t) => {
done()
})
})

await t.test('check if no deprecation warning is shown if ignore deprecated package', (_t, done) => {
exec('pnpm i request --force -g && node ./dist/cli.mjs global --manager pnpm --ignore request', { timeout: 160000 }, (_error, _stdout, stderr) => {
assert.ok(!/has been deprecated/.test(stderr), 'Not expected "has been deprecated" to be mentioned in deprecation warning.')
// Cleanup: Undo the installation
exec('pnpm remove request -g')
done()
})
})
})

test('package tests', async (t) => {
Expand Down

0 comments on commit 5da05be

Please sign in to comment.