Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: respect config file when no explicit cli flags #88

Merged
merged 4 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 15 additions & 26 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,30 @@ import c from 'picocolors'
import { version } from '../package.json'
import { check } from './commands/check'
import { usage } from './commands/usage'
import { resolveConfig } from './config'
import { LOG_LEVELS, MODE_CHOICES } from './constants'
import type { CommonOptions } from './types'
import { LOGLEVELS, resolveConfig } from './config'
import type { SortOption } from './utils/sort'
import { SORT_CHOICES } from './utils/sort'
import { checkGlobal } from './commands/check/checkGlobal'

function commonOptions(args: Argv<object>): Argv<CommonOptions> {
return args
.option('cwd', {
alias: 'C',
default: '',
type: 'string',
describe: 'specify the current working directory',
})
.option('loglevel', {
default: 'info',
type: 'string',
describe: 'log level',
choices: LOGLEVELS,
choices: LOG_LEVELS,
})
.option('failOnOutdated', {
type: 'boolean',
describe: 'exit with code 1 if outdated dependencies are found',
})
.option('silent', {
alias: 's',
default: false,
type: 'boolean',
describe: 'complete silent',
})
Expand All @@ -45,12 +43,6 @@ function commonOptions(args: Argv<object>): Argv<CommonOptions> {
type: 'boolean',
describe: 'force fetching from server, bypass cache',
})
.option('sort', {
type: 'string',
default: 'diff-asc' as SortOption,
choices: ['time-asc', 'time-desc', 'diff-asc', 'diff-desc', 'name-asc', 'name-desc', 'time', 'diff', 'name'],
describe: 'sort by most outdated absolute or relative to dependency',
})
.option('ignore-paths', {
type: 'string',
describe: 'ignore paths for search package.json',
Expand All @@ -77,11 +69,6 @@ function commonOptions(args: Argv<object>): Argv<CommonOptions> {
describe: 'update only for dependencies',
conflicts: ['dev'],
})
.option('include-locked', {
alias: 'l',
type: 'boolean',
describe: 'include locked dependencies & devDependencies',
})
}

// eslint-disable-next-line no-unused-expressions
Expand All @@ -96,7 +83,6 @@ yargs(hideBin(process.argv))
.option('detail', {
alias: 'a',
type: 'boolean',
default: false,
describe: 'show more info',
})
.help()
Expand All @@ -110,47 +96,50 @@ yargs(hideBin(process.argv))
(args) => {
return commonOptions(args)
.positional('mode', {
default: 'default',
type: 'string',
describe: 'the mode how version range resolves, can be "default", "major", "minor", "latest" or "newest"',
choices: ['default', 'major', 'minor', 'patch', 'latest', 'newest'],
choices: MODE_CHOICES,
})
.option('write', {
alias: 'w',
default: false,
type: 'boolean',
describe: 'write to package.json',
})
.option('global', {
alias: 'g',
default: false,
type: 'boolean',
describe: 'update global packages',
})
.option('interactive', {
alias: 'I',
default: false, // TODO: enable by default: !process.env.CI && process.stdout.isTTY,
type: 'boolean',
describe: 'interactive mode',
})
.option('install', {
alias: 'i',
default: false,
type: 'boolean',
describe: 'install directly after bumping',
})
.option('update', {
alias: 'u',
default: false,
type: 'boolean',
describe: 'update directly after bumping',
})
.option('all', {
alias: 'a',
default: false,
type: 'boolean',
describe: 'show all packages up to date info',
})
.option('sort', {
type: 'string',
choices: SORT_CHOICES,
describe: 'sort by most outdated absolute or relative to dependency',
})
.option('includeLocked', {
alias: 'l',
type: 'boolean',
describe: 'include locked dependencies & devDependencies',
})
.help()
},
async (args) => {
Expand Down
12 changes: 7 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import _debug from 'debug'
import { createConfigLoader } from 'unconfig'
import type { CommonOptions } from './types'
import { toArray } from './utils/toArray'
import { DEFAULT_CHECK_OPTIONS, DEFAULT_USAGE_OPTIONS } from './constants'

const debug = _debug('taze:config')

export const LOGLEVELS = ['debug', 'info', 'warn', 'error', 'silent']

function normalizeConfig<T extends CommonOptions>(options: T) {
options.ignorePaths = toArray(options.ignorePaths)
options.exclude = toArray(options.exclude)
Expand All @@ -20,7 +19,10 @@ function normalizeConfig<T extends CommonOptions>(options: T) {
return options
}

export async function resolveConfig<T extends CommonOptions>(options: T): Promise<T> {
export async function resolveConfig<T extends CommonOptions>(
options: T & { _?: (string | number)[] },
): Promise<T> {
const defaults = options?._?.[0] === 'usage' ? DEFAULT_USAGE_OPTIONS : DEFAULT_CHECK_OPTIONS
options = normalizeConfig(options)

const loader = createConfigLoader<CommonOptions>({
Expand All @@ -44,10 +46,10 @@ export async function resolveConfig<T extends CommonOptions>(options: T): Promis
const config = await loader.load()

if (!config.sources.length)
return options
return deepmerge(defaults, options as T) as T

debug(`config file found ${config.sources[0]}`)
const configOptions = normalizeConfig(config.config)

return deepmerge(configOptions, options) as T
return deepmerge(deepmerge(defaults, configOptions), options as T) as T
}
39 changes: 39 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { CheckOptions, CommonOptions, UsageOptions } from './types'

export const LOG_LEVELS = ['debug', 'info', 'warn', 'error', 'silent'] as const

export const MODE_CHOICES = ['default', 'major', 'minor', 'patch', 'latest', 'newest'] as const

export const DEFAULT_COMMON_OPTIONS: CommonOptions = {
cwd: '',
loglevel: 'info',
failOnOutdated: false,
silent: false,
recursive: false,
force: false,
ignorePaths: '',
include: '',
exclude: '',
dev: false,
prod: false,
}

export const DEFAULT_USAGE_OPTIONS: UsageOptions = {
...DEFAULT_COMMON_OPTIONS,
detail: false,
recursive: true,
}

export const DEFAULT_CHECK_OPTIONS: CheckOptions = {
...DEFAULT_COMMON_OPTIONS,
mode: 'default',
write: false,
global: false,
// TODO: enable by default: !process.env.CI && process.stdout.isTTY,
interactive: false,
install: false,
update: false,
all: false,
sort: 'diff-asc',
includeLocked: false,
}
2 changes: 1 addition & 1 deletion src/io/packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export async function writePackage(pkg: PackageMeta, options: CommonOptions) {
}

export async function loadPackage(relative: string, options: CommonOptions, shouldUpdate: (name: string) => boolean): Promise<PackageMeta> {
const filepath = path.resolve(options.cwd, relative)
const filepath = path.resolve(options.cwd ?? '', relative)
const raw = await readJSON(filepath)
let deps: RawDep[] = []

Expand Down
9 changes: 5 additions & 4 deletions src/log.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import process from 'node:process'
import c from 'picocolors'
import { MultiBar, Presets } from 'cli-progress'
import { LOGLEVELS } from './config'
import { LOG_LEVELS } from './constants'
import { visualLength, visualPadEnd, visualPadStart } from './render'
import type { LogLevel } from './types'

interface Options {
columns: number
pending: number
align: string
loglevel: string
loglevel: LogLevel
}

export function shouldLog(level: string, messageLevel: string) {
return LOGLEVELS.indexOf(level) <= LOGLEVELS.indexOf(messageLevel)
export function shouldLog(level: LogLevel, messageLevel: LogLevel) {
return LOG_LEVELS.indexOf(level) <= LOG_LEVELS.indexOf(messageLevel)
}

export class TableLogger {
Expand Down
16 changes: 9 additions & 7 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,30 +41,32 @@ export interface ResolvedDepChange extends RawDep {
aliasName?: string
}

export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'

export interface CommonOptions {
cwd: string
cwd?: string
recursive?: boolean
ignorePaths?: string | string[]
include?: string | string[]
exclude?: string | string[]
prod?: boolean
dev?: boolean
loglevel?: string
loglevel?: LogLevel
failOnOutdated?: boolean
silent?: boolean
force?: boolean
packageMode?: { [name: string]: PackageMode }
}

export interface UsageOptions extends CommonOptions {
detail: boolean
recursive: true
detail?: boolean
recursive?: true
}

export interface CheckOptions extends CommonOptions {
mode: string
write: boolean
all: boolean
mode?: RangeMode
write?: boolean
all?: boolean
sort?: SortOption
interactive?: boolean
install?: boolean
Expand Down
8 changes: 8 additions & 0 deletions src/utils/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ export type SortKey = 'time' | 'diff' | 'name'
export type SortOrder = 'asc' | 'desc'

export type SortOption = `${SortKey}-${SortOrder}`
export const SORT_CHOICES = [
'time-asc',
'time-desc',
'diff-asc',
'diff-desc',
'name-asc',
'name-desc',
] as const

export function parseSortOption(option: SortOption) {
return option.split('-') as [SortKey, SortOrder]
Expand Down