args-json
Version:
Zero-dependency descriptively typed command-line argument parser
202 lines (186 loc) • 5.72 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
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;
}
exports.Args = Args;
exports.args = args;
exports.getValue = getValue;
exports.getValues = getValues;
exports.hasKey = hasKey;
exports.isExplicitlyOff = isExplicitlyOff;
exports.isKey = isKey;
exports.isOff = isOff;
exports.isOn = isOn;
exports.parseArgs = parseArgs;