diff --git a/doc/api/errors.md b/doc/api/errors.md
index c6c8140e259102..2a11a1c5441a74 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -2464,6 +2464,17 @@ added:
When `strict` set to `true`, thrown by [`util.parseArgs()`][] if an argument
is not configured in `options`.
+
+
+### `ERR_PARSE_ARGS_REQUIRED_OPTION`
+
+
+
+When `required` set to `true`, thrown by [`util.parseArgs()`][] if an option
+is not provided in `args`.
+
### `ERR_PERFORMANCE_INVALID_TIMESTAMP`
diff --git a/doc/api/util.md b/doc/api/util.md
index 48b32712cf83c1..5b9f94c34e4d00 100644
--- a/doc/api/util.md
+++ b/doc/api/util.md
@@ -1031,6 +1031,9 @@ added:
- v18.3.0
- v16.17.0
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/44565
+ description: support `required` field in option
- version:
- v18.7.0
- v16.17.0
@@ -1053,6 +1056,7 @@ changes:
times. If `true`, all values will be collected in an array. If
`false`, values for the option are last-wins. **Default:** `false`.
* `short` {string} A single character alias for the option.
+ * `required` {boolean} Whether this option is required. **Default:** `false`.
* `strict` {boolean} Should an error be thrown when unknown arguments
are encountered, or when arguments are passed that do not match the
`type` configured in `options`.
@@ -1085,7 +1089,8 @@ const options = {
short: 'f'
},
bar: {
- type: 'string'
+ type: 'string',
+ required: true
}
};
const {
@@ -1105,7 +1110,8 @@ const options = {
short: 'f'
},
bar: {
- type: 'string'
+ type: 'string',
+ required: true
}
};
const {
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index de861b813a4fe9..f6a035f61dc9f4 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1519,6 +1519,7 @@ E('ERR_PARSE_ARGS_UNKNOWN_OPTION', (option, allowPositionals) => {
`'--', as in '-- ${JSONStringify(option)}` : '';
return `Unknown option '${option}'${suggestDashDash}`;
}, TypeError);
+E('ERR_PARSE_ARGS_REQUIRED_OPTION', 'Required option \'%s\'.', TypeError);
E('ERR_PERFORMANCE_INVALID_TIMESTAMP',
'%d is not a valid timestamp', TypeError);
E('ERR_PERFORMANCE_MEASURE_INVALID_OPTIONS', '%s', TypeError);
diff --git a/lib/internal/util/parse_args/parse_args.js b/lib/internal/util/parse_args/parse_args.js
index 05f4c6cffbdbd7..452ad5faa4295d 100644
--- a/lib/internal/util/parse_args/parse_args.js
+++ b/lib/internal/util/parse_args/parse_args.js
@@ -44,6 +44,7 @@ const {
ERR_PARSE_ARGS_INVALID_OPTION_VALUE,
ERR_PARSE_ARGS_UNKNOWN_OPTION,
ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL,
+ ERR_PARSE_ARGS_REQUIRED_OPTION
},
} = require('internal/errors');
@@ -336,6 +337,18 @@ const parseArgs = (config = kEmptyObject) => {
}
});
+ // Phase 3: check if some options is required
+ ArrayPrototypeForEach(
+ ObjectEntries(options),
+ ({ 0: longOption, 1: optionConfig }) => {
+ if (optionConfig.required) {
+ if (result.values[longOption] == null) {
+ throw new ERR_PARSE_ARGS_REQUIRED_OPTION(longOption);
+ }
+ }
+ }
+ );
+
return result;
};
diff --git a/test/parallel/test-parse-args.mjs b/test/parallel/test-parse-args.mjs
index 98cf9403743a41..1758409f1dcf92 100644
--- a/test/parallel/test-parse-args.mjs
+++ b/test/parallel/test-parse-args.mjs
@@ -823,3 +823,78 @@ test('tokens: strict:false with -- --', () => {
const { tokens } = parseArgs({ strict: false, args, tokens: true });
assert.deepStrictEqual(tokens, expectedTokens);
});
+
+test('strict: required option', () => {
+ const args = ['--foo']
+ parseArgs({
+ args,
+ options: {
+ foo: {
+ type: 'boolean',
+ required: true
+ }
+ }
+ })
+})
+
+test('required option', () => {
+ const args = ['--foo', '--goo']
+ parseArgs({
+ strict: false,
+ args,
+ options: {
+ foo: {
+ type: 'boolean',
+ required: true
+ }
+ }
+ })
+})
+
+test('strict: false required option fail', () => {
+ const args = []
+ assert.throws(() => {
+ parseArgs({
+ strict: false,
+ args,
+ options: {
+ foo: {
+ type: 'boolean',
+ required: true
+ }
+ }
+ }, {
+ code: 'ERR_PARSE_ARGS_REQUIRED_OPTION'
+ })
+ })
+})
+
+test('strict: no input but has required option', () => {
+ const args = []
+ assert.throws(() => {
+ parseArgs({
+ args,
+ options: {
+ foo: {
+ type: 'boolean',
+ required: true
+ }
+ }
+ }, {
+ code: 'ERR_PARSE_ARGS_REQUIRED_OPTION'
+ })
+ })
+})
+
+test('strict: no input and no required option', () => {
+ const args = []
+ parseArgs({
+ args,
+ options: {
+ foo: {
+ type: 'boolean',
+ required: false
+ }
+ }
+ })
+})