Skip to content

Commit

Permalink
Remove auto-camelcasing of settings
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Aug 21, 2023
1 parent 5546bb5 commit 1e3b3dc
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 60 deletions.
81 changes: 25 additions & 56 deletions lib/parse-argv.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@

import assert from 'node:assert/strict'
import {parse as commaParse} from 'comma-separated-tokens'
import camelcase from 'camelcase'
import json5 from 'json5'
import minimist from 'minimist'
import table from 'text-table'
Expand Down Expand Up @@ -110,33 +109,31 @@ while (++index < schema.length) {
// eslint-disable-next-line complexity
export function parseArgv(flags, options) {
/** @type {Record<string, Array<string> | string | boolean | undefined>} */
const miniconfig = minimist(flags, minischema)
const config = minimist(flags, minischema)
let index = -1

// Fix defaults: minimist only understand `null`, not `undefined`, so we had to use `null`.
// But we want `undefined`, so clean it here.
/** @type {string} */
let key

for (key in miniconfig) {
if (miniconfig[key] === null) {
miniconfig[key] = undefined
for (key in config) {
if (config[key] === null) {
config[key] = undefined
}
}

// Crash on passed but missing string values.
while (++index < schema.length) {
const field = schema[index]
if (field.type === 'string' && miniconfig[field.long] === '') {
if (field.type === 'string' && config[field.long] === '') {
throw new Error('Missing value: ' + inspect(field).join(' ').trimStart())
}
}

const config = toCamelCase(miniconfig)

// Make sure we parsed everything correctly.
// Minimist guarantees that `''` is an array of strings.
assert(Array.isArray(config['']))
assert(Array.isArray(config._))
// Minimist guarantees that our booleans are never strings.
// Most have defaults, so they’re not `undefined`.
assert(typeof config.color === 'boolean')
Expand All @@ -147,19 +144,23 @@ export function parseArgv(flags, options) {
assert(typeof config.inspect === 'boolean')
assert(typeof config.quiet === 'boolean')
assert(typeof config.silent === 'boolean')
assert(typeof config.silentlyIgnore === 'boolean')
assert(typeof config['silently-ignore'] === 'boolean')
assert(typeof config.tree === 'boolean')
assert(typeof config.version === 'boolean')
assert(typeof config.watch === 'boolean')
assert(config.stdout === undefined || typeof config.stdout === 'boolean')
assert(config.treeIn === undefined || typeof config.treeIn === 'boolean')
assert(config.treeOut === undefined || typeof config.treeOut === 'boolean')
assert(
config['tree-in'] === undefined || typeof config['tree-in'] === 'boolean'
)
assert(
config['tree-out'] === undefined || typeof config['tree-out'] === 'boolean'
)

// The rest are strings, never booleans, but with minimist they could be
// arrays.
// `ignore-path-resolve-from` is an enum.
const ignorePathResolveFrom = undefinedIfBoolean(
lastIfArray(config.ignorePathResolveFrom)
lastIfArray(config['ignore-path-resolve-from'])
)

if (
Expand All @@ -174,14 +175,15 @@ export function parseArgv(flags, options) {
)
}

const filePath = lastIfArray(undefinedIfBoolean(config.filePath))
const ignorePath = lastIfArray(undefinedIfBoolean(config.ignorePath))
const rcPath = lastIfArray(undefinedIfBoolean(config.rcPath))
const filePath = lastIfArray(undefinedIfBoolean(config['file-path']))
const ignorePath = lastIfArray(undefinedIfBoolean(config['ignore-path']))
const rcPath = lastIfArray(undefinedIfBoolean(config['rc-path']))
const output = lastIfArray(config.output)

const ext = parseIfString(joinIfArray(undefinedIfBoolean(config.ext))) || []
const ignorePattern =
parseIfString(joinIfArray(undefinedIfBoolean(config.ignorePattern))) || []
parseIfString(joinIfArray(undefinedIfBoolean(config['ignore-pattern']))) ||
[]

const setting = toArray(undefinedIfBoolean(config.setting)) || []
/** @type {Record<string, unknown>} */
Expand Down Expand Up @@ -229,7 +231,7 @@ export function parseArgv(flags, options) {
detectIgnore: config.ignore,
extensions: ext.length === 0 ? options.extensions : ext,
filePath,
files: config[''],
files: config._,
frail: config.frail,
ignoreName: options.ignoreName,
ignorePath,
Expand All @@ -249,10 +251,10 @@ export function parseArgv(flags, options) {
reporterOptions,
settings,
silent: config.silent,
silentlyIgnore: config.silentlyIgnore,
silentlyIgnore: config['silently-ignore'],
tree: config.tree,
treeIn: config.treeIn,
treeOut: config.treeOut
treeIn: config['tree-in'],
treeOut: config['tree-out']
}
}
}
Expand Down Expand Up @@ -286,7 +288,7 @@ function generateHelpMessage(options) {
}

/**
* Parse configuration, as JSON5, and camelcase the result.
* Parse configuration as JSON5.
*
* @param {string} value
* Settings.
Expand All @@ -302,7 +304,7 @@ function parseConfig(value, cache) {
let flag

try {
flags = toCamelCase(json5.parse('{' + value + '}'))
flags = json5.parse('{' + value + '}')
} catch (error) {
const cause = /** @type {Error} */ (error)
cause.message = cause.message.replace(/at(?= position)/, 'around')
Expand Down Expand Up @@ -415,39 +417,6 @@ function splitOptions(value) {
: [value.slice(0, index), value.slice(index + 1)]
}

/**
* Transform the keys on an object to camelcase, recursivly.
*
* @template {Record<string, unknown>} T
* Record.
* @param {T} object
* Value.
* @returns {T}
* Camelcased record.
*/
function toCamelCase(object) {
const result = /** @type {T} */ ({})
/** @type {keyof T} */
let key

for (key in object) {
if (own.call(object, key)) {
/** @type {keyof T} */
const camelcased = camelcase(key)
let value = object[key]

if (value && typeof value === 'object' && !Array.isArray(value)) {
// @ts-expect-error: objects are indexable.
value = toCamelCase(value)
}

result[camelcased] = value
}
}

return result
}

/**
* @template {unknown} T
* Value.
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
],
"dependencies": {
"@types/text-table": "^0.2.0",
"camelcase": "^8.0.0",
"chalk": "^5.0.0",
"chokidar": "^3.0.0",
"comma-separated-tokens": "^2.0.0",
Expand Down
6 changes: 3 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ test('args', async function (t) {
// Parser and Compiler both log stringified settings.
assert.deepEqual(
[result.stdout, cleanError(result.stderr)],
['{"fooBar":"baz"}\none', 'one.txt: no issues found']
['{"foo-bar":"baz"}\none', 'one.txt: no issues found']
)
})
}
Expand Down Expand Up @@ -675,7 +675,7 @@ test('args', async function (t) {
await t.test('should support `--watch`', async function () {
// On Windows, `SIGINT` crashes immediately and results in an error.
// Hence `reject: false`, `exitCode`, and extra lines when non-windows.
const delay = 500
const delay = 1000
const url = new URL('watch.txt', base)

await fs.writeFile(url, 'alpha')
Expand Down Expand Up @@ -712,7 +712,7 @@ test('args', async function (t) {
})

await t.test('should not regenerate when watching', async function () {
const delay = 500
const delay = 1000
const url = new URL('watch.txt', base)

await fs.writeFile(url, 'alpha')
Expand Down

0 comments on commit 1e3b3dc

Please sign in to comment.