UNPKG

args-json

Version:

Zero-dependency descriptively typed command-line argument parser

191 lines (176 loc) 5.48 kB
function getDefaultInput() { return typeof process === "undefined" ? [] : process.argv; } const offValues = new Set([ "0", "false", "null", "undefined", "off" ]); function isOff(x) { return offValues.has(String(x)); } function isExplicitlyOff(x) { return isOff(x) && String(x) !== "undefined"; } function isKey(x) { return x.startsWith("-") && x.length === 2 && x !== "--" || x.startsWith("--") && x.length > 2; } const onValues = new Set([ "1", "true", "on" ]); function isOn(x) { return onValues.has(String(x)); } function normalizeInput(input) { let source = input ?? getDefaultInput(); let result = []; for (let s of source) { if (s.startsWith("-") && s.includes("=")) { let key = s.slice(0, s.indexOf("=")); if (isKey(key)) { result.push(key, s.slice(key.length + 1)); continue; } } result.push(s); } return result; } var Args = class { _input; constructor(input) { this._input = normalizeInput(input); } hasKey(x) { return isKey(x) && this._input.includes(x); } isOn(key) { let args = this._input; let k = args.indexOf(key); return k !== -1 && (k === args.length - 1 || isKey(args[k + 1]) || isOn(args[k + 1])); } isOff(key) { let args = this._input; let k = args.indexOf(key); return k === -1 || isOff(args[k + 1]); } isExplicitlyOff(key) { let args = this._input; let k = args.indexOf(key); return k !== -1 && isExplicitlyOff(args[k + 1]); } getValue(key, fallback) { let args = this._input; let keys = Array.isArray(key) ? key : [key]; for (let k of keys) { let i = args.indexOf(k); if (i !== -1 && args[i + 1] && !isKey(args[i + 1])) return args[i + 1]; } return fallback; } getValues(key, fallback) { let args = this._input; let keys = Array.isArray(key) ? key : [key]; let values = []; for (let k of keys) { let i = args.indexOf(k); while (i !== -1 && args[i + 1] && !isKey(args[i + 1])) values.push(args[++i]); } return values.length === 0 ? fallback : values; } }; const args = new Args(); function getValue(key, fallback) { if (fallback === void 0) return args.getValue(key); return args.getValue(key, fallback); } function getValues(key, fallback) { if (fallback === void 0) return args.getValues(key); return args.getValues(key, fallback); } function hasKey(x) { return args.hasKey(x); } function split(x) { let words = [], word = ""; let hasOpenSingleQuote = false; let hasOpenDoubleQuote = false; for (let i = 0; i < x.length; i++) { let c = x[i]; if (/^\s/.test(c) && !hasOpenSingleQuote && !hasOpenDoubleQuote) { if (word) words.push(word); word = ""; continue; } if (c === "'" && x[i - 1] !== "\\") hasOpenSingleQuote = !hasOpenSingleQuote; if (c === "\"" && x[i - 1] !== "\\") hasOpenDoubleQuote = !hasOpenDoubleQuote; word += c; } if (word) words.push(word); return words; } function toCamelCase(x) { let s = x.replace(/^[-_.\s~+]|[-_.\s~+]$/g, ""); if (!/[-_.\s~+]/.test(s)) return s.slice(0, 1).toLowerCase() + s.slice(1); return s.toLowerCase().replace(/[-_.\s~+](\S)/g, (_, match) => match.toUpperCase()); } function toKey(x) { if (x === void 0 || !isKey(x)) return; if (x.startsWith("-") && x.length === 2) return toCamelCase(x.slice(1)); if (x.startsWith("--") && x.length > 2) return toCamelCase(x.slice(2)); } function parseArgs(input, map) { let normalizedInput; let normalizedMap; if (input === void 0) normalizedInput = getDefaultInput(); else if (typeof input === "string") normalizedInput = split(input); else if (Array.isArray(input)) normalizedInput = input.map((x) => String(x)); else if (input !== null && typeof input === "object") { normalizedInput = getDefaultInput(); normalizedMap = input; } else normalizedInput = []; normalizedInput = normalizedInput.flatMap((item) => { let normalizedItem = item.trim(); let k = normalizedItem.indexOf("="); if (k === -1) return normalizedItem; let key = normalizedItem.slice(0, k); let value = normalizedItem.slice(k + 1); if (!isKey(key)) return normalizedItem; return [key, value]; }); if (map) normalizedMap = map; let key = ""; let parsedArgs = {}; for (let rawValue of normalizedInput) { rawValue = rawValue.trim(); if (rawValue.startsWith("\"") && rawValue.endsWith("\"")) rawValue = rawValue.slice(1, -1); else if (rawValue.startsWith("'") && rawValue.endsWith("'")) rawValue = rawValue.slice(1, -1); let parsedKey = toKey(rawValue); if (parsedKey !== void 0) { let nextKey = normalizedMap?.[parsedKey] ?? parsedKey; if (key && nextKey !== key && parsedArgs[key] === void 0) parsedArgs[key] = true; key = nextKey; continue; } let parsedValue; if (rawValue) try { parsedValue = JSON.parse(rawValue); } catch { parsedValue = rawValue; } else parsedValue = true; let prevValue = parsedArgs[key]; let value; if (prevValue === void 0) value = key === "" ? [parsedValue] : parsedValue; else if (Array.isArray(prevValue)) value = [...prevValue, parsedValue]; else value = [prevValue, parsedValue]; parsedArgs[key] = value; } if (key && parsedArgs[key] === void 0) parsedArgs[key] = true; return parsedArgs; } export { Args, args, getValue, getValues, hasKey, isExplicitlyOff, isKey, isOff, isOn, parseArgs };