zod-opts
Version:
node.js CLI option parser / validator using Zod
222 lines (221 loc) • 7.78 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
exports.parser = parser;
const node_path_1 = __importDefault(require("node:path"));
const zod_1 = require("zod");
const command_parser_1 = require("./command_parser");
const error_1 = require("./error");
const help_1 = require("./help");
const helper = __importStar(require("./parser_helper"));
const util = __importStar(require("./util"));
class Parser {
constructor({ name, version, description, options, positionalArgs, validation, handler, } = {}) {
this._options = {};
this._positionalArgs = [];
this._name = name;
this._version = version;
this._description = description;
if (options !== undefined) {
this._options = options;
}
if (positionalArgs !== undefined) {
this._positionalArgs = positionalArgs;
}
this._validation = validation;
this._handler = handler;
}
name(name) {
this._name = name;
return this;
}
version(version) {
this._version = version;
return this;
}
description(description) {
this._description = description;
return this;
}
options(options) {
util.validateParamOptionsAndPositionalArguments(options, this._positionalArgs);
return new Parser({
...this._currentState(),
options,
});
}
args(positionalArgs) {
util.validateParamOptionsAndPositionalArguments(this._options, positionalArgs);
return new Parser({
...this._currentState(),
positionalArgs: positionalArgs,
});
}
_internalHandler(handler) {
this._handler = handler;
return this;
}
validation(validation) {
this._validation = validation;
return this;
}
showHelp() {
const help = this.getHelp();
console.log(help); // eslint-disable-line no-console
}
getHelp() {
const internalOptions = helper.generateInternalOptions(this._options);
const internalPositionalArguments = helper.generateInternalPositionalArguments(this._positionalArgs);
return (0, help_1.generateGlobalHelp)({
options: internalOptions,
positionalArgs: internalPositionalArguments,
name: this._scriptName(),
description: this._description,
version: this._version,
});
}
parse(args) {
const validArgs = args !== null && args !== void 0 ? args : process.argv.slice(2);
const { _options: options, _positionalArgs: positionalArgs, _handler: handler, } = this;
// Check support of options and positionalArgs before parsing args
const shape = helper.generateZodShape(options, positionalArgs);
const internalResult = helper.createInternalParserAndParse({
options,
positionalArgs,
args: validArgs,
name: this._scriptName(),
description: this._description,
version: this._version,
});
if (internalResult.type !== "match") {
this._handleAndExit(internalResult);
}
const zodParseResult = this._zodParse(internalResult, shape);
if (!zodParseResult.success) {
this._handleAndExit(zodParseResult.error);
}
const validationError = this._validateByCustomValidation(zodParseResult.value, internalResult.help);
if (validationError !== undefined) {
this._handleAndExit(validationError);
}
if (handler != null) {
handler({ ...internalResult, parsed: zodParseResult.value });
}
return zodParseResult.value;
}
_validateByCustomValidation(value, help) {
if (this._validation === undefined) {
return undefined;
}
const validationResult = (() => {
try {
return this._validation(value);
}
catch (e) {
if (e instanceof Error) {
return e.message;
}
throw e;
}
})();
if (validationResult !== true) {
return {
type: "error",
error: new error_1.ParseError(validationResult),
help,
exitCode: 1,
};
}
}
_zodParse(prevResult, shape) {
const result = zod_1.z.object(shape).safeParse(prevResult.parsed);
if (!result.success) {
const firstError = result.error.issues[0];
return {
success: false,
error: {
type: "error",
error: new error_1.ParseError(`${firstError.message}: ${firstError.path.join("")}`, result.error),
help: prevResult.help,
exitCode: 1,
},
};
}
return { success: true, value: result.data };
}
_handleAndExit(handlerArg) {
if (this._handler != null) {
this._handler(handlerArg);
}
util.errorExit(handlerArg, this._version);
}
subcommand(command) {
if (Object.keys(this._options).length > 0) {
throw new Error("Cannot add subcommand to parser with options().");
}
if (Object.keys(this._positionalArgs).length > 0) {
throw new Error("Cannot add subcommand to parser with args().");
}
return new command_parser_1.CommandParser({
...this._currentState(),
}).subcommand(command);
}
_currentState() {
return {
name: this._name,
version: this._version,
description: this._description,
options: this._options,
positionalArgs: this._positionalArgs,
validation: this._validation,
handler: this._handler,
};
}
_scriptName() {
if (this._name !== undefined) {
return this._name;
}
const pathName = process.argv[1];
return node_path_1.default.basename(pathName);
}
}
exports.Parser = Parser;
function parser() {
return new Parser();
}