@jakubmazanec/args 1.0.0-de51f16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +84 -0
  3. package/dist/ParsingError.d.ts +4 -0
  4. package/dist/ParsingError.js +11 -0
  5. package/dist/ParsingError.js.map +1 -0
  6. package/dist/ValidationError.d.ts +4 -0
  7. package/dist/ValidationError.js +16 -0
  8. package/dist/ValidationError.js.map +1 -0
  9. package/dist/internals/Checker.d.ts +13 -0
  10. package/dist/internals/Checker.js +118 -0
  11. package/dist/internals/Checker.js.map +1 -0
  12. package/dist/internals/CommandScope.d.ts +14 -0
  13. package/dist/internals/CommandScope.js +48 -0
  14. package/dist/internals/CommandScope.js.map +1 -0
  15. package/dist/internals/OptionScope.d.ts +14 -0
  16. package/dist/internals/OptionScope.js +87 -0
  17. package/dist/internals/OptionScope.js.map +1 -0
  18. package/dist/internals/castValue.d.ts +7 -0
  19. package/dist/internals/castValue.js +25 -0
  20. package/dist/internals/castValue.js.map +1 -0
  21. package/dist/internals/commandToArguments.d.ts +7 -0
  22. package/dist/internals/commandToArguments.js +21 -0
  23. package/dist/internals/commandToArguments.js.map +1 -0
  24. package/dist/internals/createOptionShortNameMap.d.ts +2 -0
  25. package/dist/internals/createOptionShortNameMap.js +11 -0
  26. package/dist/internals/createOptionShortNameMap.js.map +1 -0
  27. package/dist/internals/expandArguments.d.ts +8 -0
  28. package/dist/internals/expandArguments.js +21 -0
  29. package/dist/internals/expandArguments.js.map +1 -0
  30. package/dist/internals/isCommand.d.ts +8 -0
  31. package/dist/internals/isCommand.js +11 -0
  32. package/dist/internals/isCommand.js.map +1 -0
  33. package/dist/internals/isFalseString.d.ts +6 -0
  34. package/dist/internals/isFalseString.js +10 -0
  35. package/dist/internals/isFalseString.js.map +1 -0
  36. package/dist/internals/isLongOption.d.ts +7 -0
  37. package/dist/internals/isLongOption.js +11 -0
  38. package/dist/internals/isLongOption.js.map +1 -0
  39. package/dist/internals/isOptionLike.d.ts +7 -0
  40. package/dist/internals/isOptionLike.js +11 -0
  41. package/dist/internals/isOptionLike.js.map +1 -0
  42. package/dist/internals/isShortOption.d.ts +7 -0
  43. package/dist/internals/isShortOption.js +11 -0
  44. package/dist/internals/isShortOption.js.map +1 -0
  45. package/dist/internals/isShortOptionsGroup.d.ts +8 -0
  46. package/dist/internals/isShortOptionsGroup.js +11 -0
  47. package/dist/internals/isShortOptionsGroup.js.map +1 -0
  48. package/dist/internals/isTrueString.d.ts +6 -0
  49. package/dist/internals/isTrueString.js +10 -0
  50. package/dist/internals/isTrueString.js.map +1 -0
  51. package/dist/internals.d.ts +14 -0
  52. package/dist/internals.js +16 -0
  53. package/dist/internals.js.map +1 -0
  54. package/dist/main.d.ts +4 -0
  55. package/dist/main.js +6 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/parseArguments.d.ts +10 -0
  58. package/dist/parseArguments.js +244 -0
  59. package/dist/parseArguments.js.map +1 -0
  60. package/dist/types/Arguments.d.ts +22 -0
  61. package/dist/types/Arguments.js +3 -0
  62. package/dist/types/Arguments.js.map +1 -0
  63. package/dist/types/ArgumentsCommand.d.ts +3 -0
  64. package/dist/types/ArgumentsCommand.js +3 -0
  65. package/dist/types/ArgumentsCommand.js.map +1 -0
  66. package/dist/types/ArgumentsOptions.d.ts +14 -0
  67. package/dist/types/ArgumentsOptions.js +3 -0
  68. package/dist/types/ArgumentsOptions.js.map +1 -0
  69. package/dist/types/ArgumentsParameters.d.ts +91 -0
  70. package/dist/types/ArgumentsParameters.js +3 -0
  71. package/dist/types/ArgumentsParameters.js.map +1 -0
  72. package/dist/types/ArgumentsUnknownOptions.d.ts +3 -0
  73. package/dist/types/ArgumentsUnknownOptions.js +3 -0
  74. package/dist/types/ArgumentsUnknownOptions.js.map +1 -0
  75. package/dist/types/Argv.d.ts +2 -0
  76. package/dist/types/Argv.js +3 -0
  77. package/dist/types/Argv.js.map +1 -0
  78. package/dist/types/CommandConfig.d.ts +2 -0
  79. package/dist/types/CommandConfig.js +3 -0
  80. package/dist/types/CommandConfig.js.map +1 -0
  81. package/dist/types/CommandsConfig.d.ts +3 -0
  82. package/dist/types/CommandsConfig.js +3 -0
  83. package/dist/types/CommandsConfig.js.map +1 -0
  84. package/dist/types/LongOptionName.d.ts +2 -0
  85. package/dist/types/LongOptionName.js +3 -0
  86. package/dist/types/LongOptionName.js.map +1 -0
  87. package/dist/types/NormalizedCommandConfig.d.ts +5 -0
  88. package/dist/types/NormalizedCommandConfig.js +3 -0
  89. package/dist/types/NormalizedCommandConfig.js.map +1 -0
  90. package/dist/types/NormalizedCommandsConfig.d.ts +3 -0
  91. package/dist/types/NormalizedCommandsConfig.js +3 -0
  92. package/dist/types/NormalizedCommandsConfig.js.map +1 -0
  93. package/dist/types/OptionConfig.d.ts +220 -0
  94. package/dist/types/OptionConfig.js +3 -0
  95. package/dist/types/OptionConfig.js.map +1 -0
  96. package/dist/types/OptionsConfig.d.ts +3 -0
  97. package/dist/types/OptionsConfig.js +3 -0
  98. package/dist/types/OptionsConfig.js.map +1 -0
  99. package/dist/types/ParameterConfig.d.ts +74 -0
  100. package/dist/types/ParameterConfig.js +3 -0
  101. package/dist/types/ParameterConfig.js.map +1 -0
  102. package/dist/types/ParametersConfig.d.ts +10 -0
  103. package/dist/types/ParametersConfig.js +3 -0
  104. package/dist/types/ParametersConfig.js.map +1 -0
  105. package/dist/types/ParserConfig.d.ts +16 -0
  106. package/dist/types/ParserConfig.js +3 -0
  107. package/dist/types/ParserConfig.js.map +1 -0
  108. package/dist/types/ShortOptionName.d.ts +2 -0
  109. package/dist/types/ShortOptionName.js +3 -0
  110. package/dist/types/ShortOptionName.js.map +1 -0
  111. package/dist/types.d.ts +17 -0
  112. package/dist/types.js +19 -0
  113. package/dist/types.js.map +1 -0
  114. package/package.json +42 -0
  115. package/src/ParsingError.ts +11 -0
  116. package/src/ValidationError.ts +22 -0
  117. package/src/internals/Checker.ts +145 -0
  118. package/src/internals/CommandScope.ts +61 -0
  119. package/src/internals/OptionScope.ts +101 -0
  120. package/src/internals/castValue.ts +36 -0
  121. package/src/internals/commandToArguments.ts +22 -0
  122. package/src/internals/createOptionShortNameMap.ts +13 -0
  123. package/src/internals/expandArguments.ts +22 -0
  124. package/src/internals/isCommand.ts +11 -0
  125. package/src/internals/isFalseString.ts +10 -0
  126. package/src/internals/isLongOption.ts +11 -0
  127. package/src/internals/isOptionLike.ts +11 -0
  128. package/src/internals/isShortOption.ts +11 -0
  129. package/src/internals/isShortOptionsGroup.ts +11 -0
  130. package/src/internals/isTrueString.ts +10 -0
  131. package/src/internals.ts +14 -0
  132. package/src/main.ts +4 -0
  133. package/src/parseArguments.ts +358 -0
  134. package/src/types/Arguments.ts +28 -0
  135. package/src/types/ArgumentsCommand.ts +8 -0
  136. package/src/types/ArgumentsOptions.ts +89 -0
  137. package/src/types/ArgumentsParameters.ts +158 -0
  138. package/src/types/ArgumentsUnknownOptions.ts +6 -0
  139. package/src/types/Argv.ts +2 -0
  140. package/src/types/CommandConfig.ts +2 -0
  141. package/src/types/CommandsConfig.ts +4 -0
  142. package/src/types/LongOptionName.ts +2 -0
  143. package/src/types/NormalizedCommandConfig.ts +5 -0
  144. package/src/types/NormalizedCommandsConfig.ts +4 -0
  145. package/src/types/OptionConfig.ts +279 -0
  146. package/src/types/OptionsConfig.ts +4 -0
  147. package/src/types/ParameterConfig.ts +100 -0
  148. package/src/types/ParametersConfig.ts +17 -0
  149. package/src/types/ParserConfig.ts +21 -0
  150. package/src/types/ShortOptionName.ts +54 -0
  151. package/src/types.ts +17 -0
package/LICENSE.md ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Jakub Mazanec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
17
+ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ <div align="center">
2
+
3
+ # @jakubmazanec/args
4
+
5
+ TypeScript-first library for parsing command line arguments.
6
+
7
+ </div>
8
+
9
+ ## Installation
10
+
11
+ ```sh
12
+ npm install @jakubmazanec/args
13
+ ```
14
+
15
+ ⚠️ This is an [ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) package!
16
+ It cannot be required from a CommonJS module.
17
+
18
+ #### Prerequisites
19
+
20
+ - Node.js 16 or later
21
+ - TypeScript 5 or later
22
+
23
+ ## Usage
24
+
25
+ Main purpose of this library is to parse command line arguments. Such command line can look like
26
+ this:
27
+
28
+ ```
29
+ ┌─ 1 ─┐ ┌─ 2 ──┐ ┌─── 3 ───┐ ┌─── 4 ───┐ ┌─ 5 ─┐ ┌ 6 ┐ ┌─── 7 ───┐ ┌─────── 8 ──────┐
30
+ binname do stuff --key value --key=value -key -K -aBDc foo bar baz -- --key value bar -B
31
+ └───────────────────────────────────────── 9 ──────────────────────────────────────────┘
32
+ ```
33
+
34
+ 1. Binary name. This is never passed to the parser.
35
+ 2. Command name.
36
+ 3. Option with a value. Option name can be in camel case or kebab case.
37
+ 4. Another way to specify an option with a value.
38
+ 5. Boolean options don't have to specify value to be true. Options can also be defined using a short
39
+ option form.
40
+ 6. Short options group; usually used for boolean options.
41
+ 7. Parameters.
42
+ 8. Rest arguments appear after the `--`; they are not parsed, but still included in the result.
43
+ 9. The whole command line.
44
+
45
+ The parser is strict and returns fully typed result. You can use it by calling `parseArguments`
46
+ function with the list of arguments and parser configuration:
47
+
48
+ ```TypeScript
49
+ import {parseArguments} from '@jakubmazanec/args';
50
+
51
+ let {command, parameters, options} = parseArguments(process.argv.slice(2), {
52
+ commands: ['run', 'build'],
53
+ parameters: [{
54
+ description: 'File name',
55
+ type: 'string',
56
+ required: true,
57
+ }],
58
+ options: {
59
+ help: {
60
+ type: 'boolean'
61
+ }
62
+ }
63
+ });
64
+
65
+ console.log(command); // type of `command` is `'run' | 'build' | undefined`
66
+ console.log(parameters); // type of `parameters` is `[string | undefined]`
67
+ console.log(options); // type of `options` is `{help: boolean | undefined}`
68
+ ```
69
+
70
+ See [`ParserConfig`](./docs/README.md#parserconfig) for more information about how to configure the
71
+ parser.
72
+
73
+ ## Documentation
74
+
75
+ See [API reference](./docs) for auto-generated documentation.
76
+
77
+ ## Contributing
78
+
79
+ If you want to contribute, see [CONTRIBUTING](./CONTRIBUTING.md) for details.
80
+
81
+ ## License
82
+
83
+ This package is licensed under the GNU Lesser General Public License v3. See [LICENSE](./LICENSE.md)
84
+ for details.
@@ -0,0 +1,4 @@
1
+ /**
2
+ * A subclass of `Error` that indicates a parsing failure.
3
+ */
4
+ export declare const ParsingError: new (code: "INVALID_PARAMETER" | "UNKNOWN_PARAMETER" | "INVALID_OPTION" | "UNKNOWN_OPTION", options?: import("@jakubmazanec/error").CustomErrorOptions | undefined) => import("@jakubmazanec/error").CustomError<"INVALID_PARAMETER" | "UNKNOWN_PARAMETER" | "INVALID_OPTION" | "UNKNOWN_OPTION" | "UNKNOWN_ERROR">;
@@ -0,0 +1,11 @@
1
+ import { createCustomError } from '@jakubmazanec/error';
2
+ /**
3
+ * A subclass of `Error` that indicates a parsing failure.
4
+ */ export const ParsingError = createCustomError('ParsingError', {
5
+ INVALID_PARAMETER: 'Invalid value "{0}" found. Allowed values for parameter "{1}" are: {2}.',
6
+ UNKNOWN_PARAMETER: 'Unknown parameter "{0}" found. Unknown parameters are not allowed.',
7
+ INVALID_OPTION: 'Invalid value "{0}" found. Allowed values for option "{1}" are: {2}.',
8
+ UNKNOWN_OPTION: 'Unknown option "{0}" found. Unknown options are not allowed.'
9
+ });
10
+
11
+ //# sourceMappingURL=ParsingError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ParsingError.ts"],"sourcesContent":["import {createCustomError} from '@jakubmazanec/error';\n\n/**\n * A subclass of `Error` that indicates a parsing failure.\n */\nexport const ParsingError = createCustomError('ParsingError', {\n INVALID_PARAMETER: 'Invalid value \"{0}\" found. Allowed values for parameter \"{1}\" are: {2}.',\n UNKNOWN_PARAMETER: 'Unknown parameter \"{0}\" found. Unknown parameters are not allowed.',\n INVALID_OPTION: 'Invalid value \"{0}\" found. Allowed values for option \"{1}\" are: {2}.',\n UNKNOWN_OPTION: 'Unknown option \"{0}\" found. Unknown options are not allowed.',\n});\n"],"names":["createCustomError","ParsingError","INVALID_PARAMETER","UNKNOWN_PARAMETER","INVALID_OPTION","UNKNOWN_OPTION"],"mappings":"AAAA,SAAQA,iBAAiB,QAAO,sBAAsB;AAEtD;;CAEC,GACD,OAAO,MAAMC,eAAeD,kBAAkB,gBAAgB;IAC5DE,mBAAmB;IACnBC,mBAAmB;IACnBC,gBAAgB;IAChBC,gBAAgB;AAClB,GAAG"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * A subclass of `Error` that indicates a validation issue.
3
+ */
4
+ export declare const ValidationError: new (code: "INVALID_COMMAND" | "MISSING_PARAMETER" | "INVALID_PARAMETER_DEFAULT_AND_CHOICES" | "INVALID_PARAMETER_ORDER" | "MISSING_OPTION" | "INVALID_OPTION_DEFAULT_AND_CHOICES" | "INVALID_OPTION_NAME" | "REPEATED_OPTION_NAME" | "INVALID_OPTION_ARITY", options?: import("@jakubmazanec/error").CustomErrorOptions | undefined) => import("@jakubmazanec/error").CustomError<"INVALID_COMMAND" | "MISSING_PARAMETER" | "INVALID_PARAMETER_DEFAULT_AND_CHOICES" | "INVALID_PARAMETER_ORDER" | "MISSING_OPTION" | "INVALID_OPTION_DEFAULT_AND_CHOICES" | "INVALID_OPTION_NAME" | "REPEATED_OPTION_NAME" | "INVALID_OPTION_ARITY" | "UNKNOWN_ERROR">;
@@ -0,0 +1,16 @@
1
+ import { createCustomError } from '@jakubmazanec/error';
2
+ /**
3
+ * A subclass of `Error` that indicates a validation issue.
4
+ */ export const ValidationError = createCustomError('ValidationError', {
5
+ INVALID_COMMAND: 'Command "{0}" has invalid format. Only words consisting of letters, numbers or dashes separated by single space are allowed.',
6
+ MISSING_PARAMETER: 'Parameter "{0}" is required but its value is undefined.',
7
+ INVALID_PARAMETER_DEFAULT_AND_CHOICES: 'Parameter "{0}" has invalid default value "{1}". Default value must be one of the `choices` elements.',
8
+ INVALID_PARAMETER_ORDER: 'Optional parameter "{0}" found before required parameter "{1}". Required parameter must be first.',
9
+ MISSING_OPTION: 'Option "{0}" is required but its value is undefined.',
10
+ INVALID_OPTION_DEFAULT_AND_CHOICES: 'Option "{0}" has invalid default value "{1}". Default value must be one of the `choices` elements.',
11
+ INVALID_OPTION_NAME: 'Option "{0}" has invalid name. Only names consisting of letters, numbers or dashes are allowed.',
12
+ REPEATED_OPTION_NAME: 'Option "{0}" has invalid short name "{1}". Short option names must be unique.',
13
+ INVALID_OPTION_ARITY: 'Option "{0}" has invalid number of values. Found "{1}", require "{2}".'
14
+ });
15
+
16
+ //# sourceMappingURL=ValidationError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ValidationError.ts"],"sourcesContent":["import {createCustomError} from '@jakubmazanec/error';\n\n/**\n * A subclass of `Error` that indicates a validation issue.\n */\nexport const ValidationError = createCustomError('ValidationError', {\n INVALID_COMMAND:\n 'Command \"{0}\" has invalid format. Only words consisting of letters, numbers or dashes separated by single space are allowed.',\n MISSING_PARAMETER: 'Parameter \"{0}\" is required but its value is undefined.',\n INVALID_PARAMETER_DEFAULT_AND_CHOICES:\n 'Parameter \"{0}\" has invalid default value \"{1}\". Default value must be one of the `choices` elements.',\n INVALID_PARAMETER_ORDER:\n 'Optional parameter \"{0}\" found before required parameter \"{1}\". Required parameter must be first.',\n MISSING_OPTION: 'Option \"{0}\" is required but its value is undefined.',\n INVALID_OPTION_DEFAULT_AND_CHOICES:\n 'Option \"{0}\" has invalid default value \"{1}\". Default value must be one of the `choices` elements.',\n INVALID_OPTION_NAME:\n 'Option \"{0}\" has invalid name. Only names consisting of letters, numbers or dashes are allowed.',\n REPEATED_OPTION_NAME:\n 'Option \"{0}\" has invalid short name \"{1}\". Short option names must be unique.',\n INVALID_OPTION_ARITY: 'Option \"{0}\" has invalid number of values. Found \"{1}\", require \"{2}\".',\n});\n"],"names":["createCustomError","ValidationError","INVALID_COMMAND","MISSING_PARAMETER","INVALID_PARAMETER_DEFAULT_AND_CHOICES","INVALID_PARAMETER_ORDER","MISSING_OPTION","INVALID_OPTION_DEFAULT_AND_CHOICES","INVALID_OPTION_NAME","REPEATED_OPTION_NAME","INVALID_OPTION_ARITY"],"mappings":"AAAA,SAAQA,iBAAiB,QAAO,sBAAsB;AAEtD;;CAEC,GACD,OAAO,MAAMC,kBAAkBD,kBAAkB,mBAAmB;IAClEE,iBACE;IACFC,mBAAmB;IACnBC,uCACE;IACFC,yBACE;IACFC,gBAAgB;IAChBC,oCACE;IACFC,qBACE;IACFC,sBACE;IACFC,sBAAsB;AACxB,GAAG"}
@@ -0,0 +1,13 @@
1
+ import { type CommandsConfig, type OptionsConfig, type ParametersConfig } from '../types.js';
2
+ /**
3
+ * `Checker` is used for handling various check before, during, and after parsing of the arguments.
4
+ */
5
+ export declare class Checker {
6
+ errors: Error[];
7
+ checkCommandsConfig(commandsConfig: CommandsConfig): void;
8
+ checkParametersConfig(parametersConfig: ParametersConfig | []): void;
9
+ checkOptionsConfig(optionsConfig: OptionsConfig): void;
10
+ checkParsedParameters(parametersConfig: ParametersConfig | [], parsedParameters: unknown[]): void;
11
+ checkParsedOptions(optionsConfig: OptionsConfig, parsedOptions: Record<string, unknown>): void;
12
+ addError(error: Error): void;
13
+ }
@@ -0,0 +1,118 @@
1
+ import { ValidationError } from '../ValidationError.js';
2
+ import { isCommand } from './isCommand.js';
3
+ import { isLongOption } from './isLongOption.js';
4
+ /**
5
+ * `Checker` is used for handling various check before, during, and after parsing of the arguments.
6
+ */ export class Checker {
7
+ errors = [];
8
+ checkCommandsConfig(commandsConfig) {
9
+ for (let commandConfig of commandsConfig){
10
+ if (!isCommand(commandConfig)) {
11
+ this.addError(new ValidationError('INVALID_COMMAND', {
12
+ messageParameters: [
13
+ commandConfig
14
+ ]
15
+ }));
16
+ }
17
+ }
18
+ }
19
+ checkParametersConfig(parametersConfig) {
20
+ for (let [i, parameterConfig] of parametersConfig.entries()){
21
+ var _parametersConfig_;
22
+ // types of choices must be correct
23
+ if (parameterConfig.type !== 'boolean' && parameterConfig.choices && // default values and chocies do not contradict each other
24
+ typeof parameterConfig.defaultValue !== 'undefined' && !parameterConfig.choices.includes(parameterConfig.defaultValue)) {
25
+ this.addError(new ValidationError('INVALID_PARAMETER_DEFAULT_AND_CHOICES', {
26
+ messageParameters: [
27
+ parameterConfig.label ?? i,
28
+ parameterConfig.defaultValue
29
+ ]
30
+ }));
31
+ }
32
+ // if parameter is required, all parameters before must be required too
33
+ if (i >= 1 && parameterConfig.required === true && ((_parametersConfig_ = parametersConfig[i - 1]) === null || _parametersConfig_ === void 0 ? void 0 : _parametersConfig_.required) !== true) {
34
+ var _parametersConfig_1;
35
+ this.addError(new ValidationError('INVALID_PARAMETER_ORDER', {
36
+ messageParameters: [
37
+ ((_parametersConfig_1 = parametersConfig[i - 1]) === null || _parametersConfig_1 === void 0 ? void 0 : _parametersConfig_1.label) ?? i - 1,
38
+ parameterConfig.label ?? i
39
+ ]
40
+ }));
41
+ }
42
+ }
43
+ }
44
+ checkOptionsConfig(optionsConfig) {
45
+ let usedShortOptionNames = new Set([]);
46
+ for (let [optionName, optionConfig] of Object.entries(optionsConfig)){
47
+ // option names must be in correct format
48
+ if (!isLongOption(`--${optionName}`)) {
49
+ this.addError(new ValidationError('INVALID_OPTION_NAME', {
50
+ messageParameters: [
51
+ optionName
52
+ ]
53
+ }));
54
+ }
55
+ // option short names must be unique
56
+ if (optionConfig.shortName && usedShortOptionNames.has(optionConfig.shortName)) {
57
+ this.addError(new ValidationError('REPEATED_OPTION_NAME', {
58
+ messageParameters: [
59
+ optionName,
60
+ optionConfig.shortName
61
+ ]
62
+ }));
63
+ } else if (optionConfig.shortName) {
64
+ usedShortOptionNames.add(optionConfig.shortName);
65
+ }
66
+ // default values and chocies do not contradict each other
67
+ if ((optionConfig.type === 'string' || optionConfig.type === 'number' && !optionConfig.count) && optionConfig.choices && typeof optionConfig.defaultValue !== 'undefined' && !optionConfig.choices.includes(optionConfig.defaultValue)) {
68
+ this.addError(new ValidationError('INVALID_OPTION_DEFAULT_AND_CHOICES', {
69
+ messageParameters: [
70
+ optionName,
71
+ optionConfig.defaultValue
72
+ ]
73
+ }));
74
+ }
75
+ }
76
+ }
77
+ checkParsedParameters(parametersConfig, parsedParameters) {
78
+ for (let [i, parameterConfig] of parametersConfig.entries()){
79
+ let parsedParameter = parsedParameters[i];
80
+ // required parameters must have value
81
+ if (parameterConfig.required === true && typeof parsedParameter === 'undefined') {
82
+ this.addError(new ValidationError('MISSING_PARAMETER', {
83
+ messageParameters: [
84
+ parameterConfig.label ?? i
85
+ ]
86
+ }));
87
+ }
88
+ }
89
+ }
90
+ checkParsedOptions(optionsConfig, parsedOptions) {
91
+ for (let [optionName, optionConfig] of Object.entries(optionsConfig)){
92
+ let parsedOption = parsedOptions[optionName];
93
+ // check required
94
+ if (optionConfig.required && typeof parsedOption === 'undefined') {
95
+ this.addError(new ValidationError('MISSING_OPTION', {
96
+ messageParameters: [
97
+ optionName
98
+ ]
99
+ }));
100
+ }
101
+ // check arity
102
+ if (typeof parsedOption !== 'undefined' && (optionConfig.type === 'string' && optionConfig.multiple || optionConfig.type === 'number' && optionConfig.multiple) && typeof optionConfig.arity === 'number' && Array.isArray(parsedOption) && parsedOption.length > 0 && parsedOption.length !== optionConfig.arity) {
103
+ this.addError(new ValidationError('INVALID_OPTION_ARITY', {
104
+ messageParameters: [
105
+ optionName,
106
+ parsedOption.length,
107
+ optionConfig.arity
108
+ ]
109
+ }));
110
+ }
111
+ }
112
+ }
113
+ addError(error) {
114
+ this.errors.push(error);
115
+ }
116
+ }
117
+
118
+ //# sourceMappingURL=Checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/Checker.ts"],"sourcesContent":["import {type CommandsConfig, type OptionsConfig, type ParametersConfig} from '../types.js';\nimport {ValidationError} from '../ValidationError.js';\nimport {isCommand} from './isCommand.js';\nimport {isLongOption} from './isLongOption.js';\n\n/**\n * `Checker` is used for handling various check before, during, and after parsing of the arguments.\n */\nexport class Checker {\n errors: Error[] = [];\n\n checkCommandsConfig(commandsConfig: CommandsConfig) {\n for (let commandConfig of commandsConfig) {\n if (!isCommand(commandConfig)) {\n this.addError(new ValidationError('INVALID_COMMAND', {messageParameters: [commandConfig]}));\n }\n }\n }\n\n checkParametersConfig(parametersConfig: ParametersConfig | []) {\n for (let [i, parameterConfig] of parametersConfig.entries()) {\n // types of choices must be correct\n if (\n parameterConfig.type !== 'boolean' &&\n parameterConfig.choices && // default values and chocies do not contradict each other\n typeof parameterConfig.defaultValue !== 'undefined' &&\n !parameterConfig.choices.includes(parameterConfig.defaultValue as never)\n ) {\n this.addError(\n new ValidationError('INVALID_PARAMETER_DEFAULT_AND_CHOICES', {\n messageParameters: [parameterConfig.label ?? i, parameterConfig.defaultValue],\n }),\n );\n }\n\n // if parameter is required, all parameters before must be required too\n if (\n i >= 1 &&\n parameterConfig.required === true &&\n parametersConfig[i - 1]?.required !== true\n ) {\n this.addError(\n new ValidationError('INVALID_PARAMETER_ORDER', {\n messageParameters: [\n parametersConfig[i - 1]?.label ?? i - 1,\n parameterConfig.label ?? i,\n ],\n }),\n );\n }\n }\n }\n\n checkOptionsConfig(optionsConfig: OptionsConfig) {\n let usedShortOptionNames: Set<string> = new Set([]);\n\n for (let [optionName, optionConfig] of Object.entries(optionsConfig)) {\n // option names must be in correct format\n if (!isLongOption(`--${optionName}`)) {\n this.addError(\n new ValidationError('INVALID_OPTION_NAME', {\n messageParameters: [optionName],\n }),\n );\n }\n\n // option short names must be unique\n if (optionConfig.shortName && usedShortOptionNames.has(optionConfig.shortName)) {\n this.addError(\n new ValidationError('REPEATED_OPTION_NAME', {\n messageParameters: [optionName, optionConfig.shortName],\n }),\n );\n } else if (optionConfig.shortName) {\n usedShortOptionNames.add(optionConfig.shortName);\n }\n\n // default values and chocies do not contradict each other\n if (\n (optionConfig.type === 'string' ||\n (optionConfig.type === 'number' && !optionConfig.count)) &&\n optionConfig.choices &&\n typeof optionConfig.defaultValue !== 'undefined' &&\n !optionConfig.choices.includes(optionConfig.defaultValue as never)\n ) {\n this.addError(\n new ValidationError('INVALID_OPTION_DEFAULT_AND_CHOICES', {\n messageParameters: [optionName, optionConfig.defaultValue],\n }),\n );\n }\n }\n }\n\n checkParsedParameters(parametersConfig: ParametersConfig | [], parsedParameters: unknown[]) {\n for (let [i, parameterConfig] of parametersConfig.entries()) {\n let parsedParameter = parsedParameters[i];\n\n // required parameters must have value\n if (parameterConfig.required === true && typeof parsedParameter === 'undefined') {\n this.addError(\n new ValidationError('MISSING_PARAMETER', {\n messageParameters: [parameterConfig.label ?? i],\n }),\n );\n }\n }\n }\n\n checkParsedOptions(optionsConfig: OptionsConfig, parsedOptions: Record<string, unknown>) {\n for (let [optionName, optionConfig] of Object.entries(optionsConfig)) {\n let parsedOption = parsedOptions[optionName];\n\n // check required\n if (optionConfig.required && typeof parsedOption === 'undefined') {\n this.addError(\n new ValidationError('MISSING_OPTION', {\n messageParameters: [optionName],\n }),\n );\n }\n\n // check arity\n if (\n typeof parsedOption !== 'undefined' &&\n ((optionConfig.type === 'string' && optionConfig.multiple) ||\n (optionConfig.type === 'number' && optionConfig.multiple)) &&\n typeof optionConfig.arity === 'number' &&\n Array.isArray(parsedOption) &&\n (parsedOption as unknown[]).length > 0 &&\n (parsedOption as unknown[]).length !== optionConfig.arity\n ) {\n this.addError(\n new ValidationError('INVALID_OPTION_ARITY', {\n messageParameters: [optionName, (parsedOption as unknown[]).length, optionConfig.arity],\n }),\n );\n }\n }\n }\n\n addError(error: Error) {\n this.errors.push(error);\n }\n}\n"],"names":["ValidationError","isCommand","isLongOption","Checker","errors","checkCommandsConfig","commandsConfig","commandConfig","addError","messageParameters","checkParametersConfig","parametersConfig","i","parameterConfig","entries","type","choices","defaultValue","includes","label","required","checkOptionsConfig","optionsConfig","usedShortOptionNames","Set","optionName","optionConfig","Object","shortName","has","add","count","checkParsedParameters","parsedParameters","parsedParameter","checkParsedOptions","parsedOptions","parsedOption","multiple","arity","Array","isArray","length","error","push"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type NormalizedCommandConfig, type NormalizedCommandsConfig } from '../types.js';
2
+ /**
3
+ * `CommandScope` handles storing information about parsing of a command.
4
+ */
5
+ export declare class CommandScope {
6
+ private readonly args;
7
+ readonly config: NormalizedCommandConfig;
8
+ constructor(arg: string, normalizedCommandsConfig: NormalizedCommandsConfig);
9
+ captureArg(arg: string): this;
10
+ isComplete(): boolean;
11
+ isDone(): boolean;
12
+ getValue(): string;
13
+ getArgs(): string[];
14
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `CommandScope` handles storing information about parsing of a command.
3
+ */ export class CommandScope {
4
+ args;
5
+ config;
6
+ constructor(arg, normalizedCommandsConfig){
7
+ let normalizedArgument = arg.toLowerCase();
8
+ let commandConfig = normalizedCommandsConfig.find((commandConfig)=>commandConfig.args[0] === normalizedArgument);
9
+ this.config = commandConfig ?? [];
10
+ this.args = [
11
+ normalizedArgument
12
+ ];
13
+ }
14
+ captureArg(arg) {
15
+ this.args.push(arg.toLowerCase());
16
+ return this;
17
+ }
18
+ isComplete() {
19
+ let isComplete = true;
20
+ for (let [i, arg] of this.config.args.entries()){
21
+ if (this.args[i] !== arg) {
22
+ isComplete = false;
23
+ break;
24
+ }
25
+ }
26
+ return isComplete;
27
+ }
28
+ isDone() {
29
+ let isDone = false;
30
+ for (let [i, arg] of this.config.args.entries()){
31
+ if (this.args[i] !== arg) {
32
+ isDone = true;
33
+ break;
34
+ }
35
+ }
36
+ return isDone;
37
+ }
38
+ getValue() {
39
+ return this.config.command;
40
+ }
41
+ getArgs() {
42
+ return [
43
+ ...this.args
44
+ ];
45
+ }
46
+ }
47
+
48
+ //# sourceMappingURL=CommandScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/CommandScope.ts"],"sourcesContent":["import {type NormalizedCommandConfig, type NormalizedCommandsConfig} from '../types.js';\n\n/**\n * `CommandScope` handles storing information about parsing of a command.\n */\nexport class CommandScope {\n private readonly args: string[];\n readonly config: NormalizedCommandConfig;\n\n constructor(arg: string, normalizedCommandsConfig: NormalizedCommandsConfig) {\n let normalizedArgument = arg.toLowerCase();\n let commandConfig = normalizedCommandsConfig.find(\n (commandConfig) => commandConfig.args[0] === normalizedArgument,\n );\n\n this.config = commandConfig ?? ([] as unknown as NormalizedCommandConfig);\n this.args = [normalizedArgument];\n }\n\n captureArg(arg: string) {\n this.args.push(arg.toLowerCase());\n\n return this;\n }\n\n isComplete() {\n let isComplete = true;\n\n for (let [i, arg] of this.config.args.entries()) {\n if (this.args[i] !== arg) {\n isComplete = false;\n\n break;\n }\n }\n\n return isComplete;\n }\n\n isDone() {\n let isDone = false;\n\n for (let [i, arg] of this.config.args.entries()) {\n if (this.args[i] !== arg) {\n isDone = true;\n\n break;\n }\n }\n\n return isDone;\n }\n\n getValue() {\n return this.config.command;\n }\n\n getArgs() {\n return [...this.args];\n }\n}\n"],"names":["CommandScope","args","config","constructor","arg","normalizedCommandsConfig","normalizedArgument","toLowerCase","commandConfig","find","captureArg","push","isComplete","i","entries","isDone","getValue","command","getArgs"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA;IACMC,KAAe;IACvBC,OAAgC;IAEzCC,YAAYC,GAAW,EAAEC,wBAAkD,CAAE;QAC3E,IAAIC,qBAAqBF,IAAIG,WAAW;QACxC,IAAIC,gBAAgBH,yBAAyBI,IAAI,CAC/C,CAACD,gBAAkBA,cAAcP,IAAI,CAAC,EAAE,KAAKK;QAG/C,IAAI,CAACJ,MAAM,GAAGM,iBAAkB,EAAE;QAClC,IAAI,CAACP,IAAI,GAAG;YAACK;SAAmB;IAClC;IAEAI,WAAWN,GAAW,EAAE;QACtB,IAAI,CAACH,IAAI,CAACU,IAAI,CAACP,IAAIG,WAAW;QAE9B,OAAO,IAAI;IACb;IAEAK,aAAa;QACX,IAAIA,aAAa,IAAI;QAErB,KAAK,IAAI,CAACC,GAAGT,IAAI,IAAI,IAAI,CAACF,MAAM,CAACD,IAAI,CAACa,OAAO,GAAI;YAC/C,IAAI,IAAI,CAACb,IAAI,CAACY,EAAE,KAAKT,KAAK;gBACxBQ,aAAa,KAAK;gBAElB,KAAM;YACR,CAAC;QACH;QAEA,OAAOA;IACT;IAEAG,SAAS;QACP,IAAIA,SAAS,KAAK;QAElB,KAAK,IAAI,CAACF,GAAGT,IAAI,IAAI,IAAI,CAACF,MAAM,CAACD,IAAI,CAACa,OAAO,GAAI;YAC/C,IAAI,IAAI,CAACb,IAAI,CAACY,EAAE,KAAKT,KAAK;gBACxBW,SAAS,IAAI;gBAEb,KAAM;YACR,CAAC;QACH;QAEA,OAAOA;IACT;IAEAC,WAAW;QACT,OAAO,IAAI,CAACd,MAAM,CAACe,OAAO;IAC5B;IAEAC,UAAU;QACR,OAAO;eAAI,IAAI,CAACjB,IAAI;SAAC;IACvB;AACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type OptionConfig, type OptionsConfig } from '../types.js';
2
+ /**
3
+ * `CommandScope` handles storing information about parsing of an option..
4
+ */
5
+ export declare class OptionScope {
6
+ name: string;
7
+ values: unknown[];
8
+ previousParsedValue?: unknown[] | unknown;
9
+ readonly config: OptionConfig;
10
+ constructor(optionName: string, optionsConfig: OptionsConfig, allowUnknownOptions?: boolean);
11
+ captureArg(arg: string): void;
12
+ isComplete(): boolean;
13
+ getValue(): unknown;
14
+ }
@@ -0,0 +1,87 @@
1
+ import camelCase from 'lodash.camelcase';
2
+ import { ParsingError } from '../ParsingError.js';
3
+ import { castValue } from './castValue.js';
4
+ /**
5
+ * `CommandScope` handles storing information about parsing of an option..
6
+ */ export class OptionScope {
7
+ name;
8
+ values = [];
9
+ previousParsedValue;
10
+ config;
11
+ constructor(optionName, optionsConfig, allowUnknownOptions = false){
12
+ this.name = optionName;
13
+ // Convert option to camel case
14
+ if (this.name.includes('-')) {
15
+ this.name = camelCase(this.name);
16
+ }
17
+ let optionConfig = optionsConfig[this.name];
18
+ if (!optionConfig) {
19
+ if (!allowUnknownOptions) {
20
+ throw new ParsingError('UNKNOWN_OPTION', {
21
+ messageParameters: [
22
+ this.name
23
+ ]
24
+ });
25
+ }
26
+ optionConfig = {
27
+ type: 'string'
28
+ };
29
+ }
30
+ this.config = optionConfig;
31
+ }
32
+ captureArg(arg) {
33
+ let value = castValue(arg, this.config.type);
34
+ if ((this.config.type === 'number' && !this.config.count || this.config.type === 'string') && typeof this.config.choices !== 'undefined' && !this.config.choices.includes(value)) {
35
+ throw new ParsingError('INVALID_OPTION', {
36
+ messageParameters: [
37
+ value,
38
+ this.name,
39
+ this.config.choices.map((choice)=>`"${choice}"`).join(', ')
40
+ ]
41
+ });
42
+ }
43
+ if (this.config.multiple) {
44
+ this.values.push(value);
45
+ } else {
46
+ this.values = [
47
+ value
48
+ ];
49
+ }
50
+ }
51
+ isComplete() {
52
+ if (!this.config.multiple && this.values.length === 1) {
53
+ return true;
54
+ }
55
+ if (this.config.multiple && typeof this.config.arity === 'number' && this.values.length + (this.previousParsedValue ?? []).length === this.config.arity) {
56
+ return true;
57
+ }
58
+ return false;
59
+ }
60
+ getValue() {
61
+ let { config , previousParsedValue } = this;
62
+ let { values } = this;
63
+ if (config.type === 'boolean' && !config.multiple && !values.length) {
64
+ values = [
65
+ true
66
+ ];
67
+ } else if (config.type === 'number' && config.count && !values.length) {
68
+ values = [
69
+ 1
70
+ ];
71
+ }
72
+ if (config.multiple && previousParsedValue) {
73
+ values = [
74
+ ...previousParsedValue,
75
+ ...values
76
+ ];
77
+ }
78
+ if (config.type === 'number' && config.count && previousParsedValue) {
79
+ values = [
80
+ values[0] + previousParsedValue
81
+ ];
82
+ }
83
+ return config.multiple ? values : values[0];
84
+ }
85
+ }
86
+
87
+ //# sourceMappingURL=OptionScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/OptionScope.ts"],"sourcesContent":["import camelCase from 'lodash.camelcase';\n\nimport {ParsingError} from '../ParsingError.js';\nimport {type OptionConfig, type OptionsConfig} from '../types.js';\nimport {castValue} from './castValue.js';\n\n/**\n * `CommandScope` handles storing information about parsing of an option..\n */\nexport class OptionScope {\n name: string;\n\n values: unknown[] = [];\n previousParsedValue?: unknown[] | unknown;\n readonly config: OptionConfig;\n\n constructor(optionName: string, optionsConfig: OptionsConfig, allowUnknownOptions = false) {\n this.name = optionName;\n\n // Convert option to camel case\n if (this.name.includes('-')) {\n this.name = camelCase(this.name);\n }\n\n let optionConfig = optionsConfig[this.name];\n\n if (!optionConfig) {\n if (!allowUnknownOptions) {\n throw new ParsingError('UNKNOWN_OPTION', {messageParameters: [this.name]});\n }\n\n optionConfig = {\n type: 'string',\n };\n }\n\n this.config = optionConfig;\n }\n\n captureArg(arg: string) {\n let value = castValue(arg, this.config.type);\n\n if (\n ((this.config.type === 'number' && !this.config.count) || this.config.type === 'string') &&\n typeof this.config.choices !== 'undefined' &&\n !this.config.choices.includes(value as never)\n ) {\n throw new ParsingError('INVALID_OPTION', {\n messageParameters: [\n value,\n this.name,\n this.config.choices.map((choice) => `\"${choice}\"`).join(', '),\n ],\n });\n }\n\n if (this.config.multiple) {\n this.values.push(value);\n } else {\n this.values = [value];\n }\n }\n\n isComplete() {\n if (!this.config.multiple && this.values.length === 1) {\n return true;\n }\n\n if (\n this.config.multiple &&\n typeof this.config.arity === 'number' &&\n this.values.length + ((this.previousParsedValue as unknown[] | undefined) ?? []).length ===\n this.config.arity\n ) {\n return true;\n }\n\n return false;\n }\n\n getValue() {\n let {config, previousParsedValue} = this;\n let {values} = this;\n\n if (config.type === 'boolean' && !config.multiple && !values.length) {\n values = [true];\n } else if (config.type === 'number' && config.count && !values.length) {\n values = [1];\n }\n\n if (config.multiple && previousParsedValue) {\n values = [...(previousParsedValue as unknown[]), ...values];\n }\n\n if (config.type === 'number' && config.count && previousParsedValue) {\n values = [(values[0] as number) + (previousParsedValue as number)];\n }\n\n return config.multiple ? values : values[0];\n }\n}\n"],"names":["camelCase","ParsingError","castValue","OptionScope","name","values","previousParsedValue","config","constructor","optionName","optionsConfig","allowUnknownOptions","includes","optionConfig","messageParameters","type","captureArg","arg","value","count","choices","map","choice","join","multiple","push","isComplete","length","arity","getValue"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A function that casts string value to a specified type.
3
+ *
4
+ * @param value The value to be converted.
5
+ * @param type The type to convert the value into.
6
+ * */
7
+ export declare function castValue<T extends 'boolean' | 'number' | 'string'>(value: string, type?: T): T extends 'boolean' ? boolean : T extends 'number' ? number : string;
@@ -0,0 +1,25 @@
1
+ import { isFalseString } from './isFalseString.js';
2
+ /**
3
+ * A function that casts string value to a specified type.
4
+ *
5
+ * @param value The value to be converted.
6
+ * @param type The type to convert the value into.
7
+ * */ export function castValue(value, type) {
8
+ switch(type){
9
+ case 'boolean':
10
+ {
11
+ let booleanString = String(value).toLowerCase();
12
+ return !(isFalseString(booleanString) || booleanString === '');
13
+ }
14
+ case 'number':
15
+ {
16
+ return Number.parseFloat(value);
17
+ }
18
+ default:
19
+ {
20
+ return String(value);
21
+ }
22
+ }
23
+ }
24
+
25
+ //# sourceMappingURL=castValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/castValue.ts"],"sourcesContent":["import {isFalseString} from './isFalseString.js';\n\n/**\n * A function that casts string value to a specified type.\n *\n * @param value The value to be converted.\n * @param type The type to convert the value into.\n * */\nexport function castValue<T extends 'boolean' | 'number' | 'string'>(\n value: string,\n type?: T,\n): T extends 'boolean' ? boolean : T extends 'number' ? number : string {\n switch (type) {\n case 'boolean': {\n let booleanString = String(value).toLowerCase();\n\n return !(isFalseString(booleanString) || booleanString === '') as T extends 'boolean'\n ? boolean\n : T extends 'number'\n ? number\n : string;\n }\n\n case 'number': {\n return Number.parseFloat(value) as T extends 'boolean'\n ? boolean\n : T extends 'number'\n ? number\n : string;\n }\n\n default: {\n return String(value) as T extends 'boolean' ? boolean : T extends 'number' ? number : string;\n }\n }\n}\n"],"names":["isFalseString","castValue","value","type","booleanString","String","toLowerCase","Number","parseFloat"],"mappings":"AAAA,SAAQA,aAAa,QAAO,qBAAqB;AAEjD;;;;;GAKG,GACH,OAAO,SAASC,UACdC,KAAa,EACbC,IAAQ,EAC8D;IACtE,OAAQA;QACN,KAAK;YAAW;gBACd,IAAIC,gBAAgBC,OAAOH,OAAOI,WAAW;gBAE7C,OAAO,CAAEN,CAAAA,cAAcI,kBAAkBA,kBAAkB,EAAC;YAK9D;QAEA,KAAK;YAAU;gBACb,OAAOG,OAAOC,UAAU,CAACN;YAK3B;QAEA;YAAS;gBACP,OAAOG,OAAOH;YAChB;IACF;AACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A function that converts a string representing a command into the arguments, i.e. array of strings.
3
+ *
4
+ * @param value The value to convert.
5
+ * @return Arguments.
6
+ */
7
+ export declare function commandToArguments(value: string): string[];
@@ -0,0 +1,21 @@
1
+ /**
2
+ * A function that converts a string representing a command into the arguments, i.e. array of strings.
3
+ *
4
+ * @param value The value to convert.
5
+ * @return Arguments.
6
+ */ export function commandToArguments(value) {
7
+ let rawArgs = value.split(' ');
8
+ let args = [];
9
+ for (let [, rawValue] of rawArgs.entries()){
10
+ if (typeof rawValue !== 'undefined') {
11
+ if (rawValue === '' && args.at(-1)) {
12
+ args[args.length - 1] += ' ';
13
+ } else {
14
+ args.push(rawValue);
15
+ }
16
+ }
17
+ }
18
+ return args;
19
+ }
20
+
21
+ //# sourceMappingURL=commandToArguments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/commandToArguments.ts"],"sourcesContent":["/**\n * A function that converts a string representing a command into the arguments, i.e. array of strings.\n *\n * @param value The value to convert.\n * @return Arguments.\n */\nexport function commandToArguments(value: string): string[] {\n let rawArgs = value.split(' ');\n let args: string[] = [];\n\n for (let [, rawValue] of rawArgs.entries()) {\n if (typeof rawValue !== 'undefined') {\n if (rawValue === '' && args.at(-1)) {\n args[args.length - 1] += ' ';\n } else {\n args.push(rawValue);\n }\n }\n }\n\n return args;\n}\n"],"names":["commandToArguments","value","rawArgs","split","args","rawValue","entries","at","length","push"],"mappings":"AAAA;;;;;CAKC,GACD,OAAO,SAASA,mBAAmBC,KAAa,EAAY;IAC1D,IAAIC,UAAUD,MAAME,KAAK,CAAC;IAC1B,IAAIC,OAAiB,EAAE;IAEvB,KAAK,IAAI,GAAGC,SAAS,IAAIH,QAAQI,OAAO,GAAI;QAC1C,IAAI,OAAOD,aAAa,aAAa;YACnC,IAAIA,aAAa,MAAMD,KAAKG,EAAE,CAAC,CAAC,IAAI;gBAClCH,IAAI,CAACA,KAAKI,MAAM,GAAG,EAAE,IAAI;YAC3B,OAAO;gBACLJ,KAAKK,IAAI,CAACJ;YACZ,CAAC;QACH,CAAC;IACH;IAEA,OAAOD;AACT,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { type OptionsConfig } from '../types.js';
2
+ export declare function createOptionShortNameMap(optionsConfig: OptionsConfig): Record<string, string>;
@@ -0,0 +1,11 @@
1
+ export function createOptionShortNameMap(optionsConfig) {
2
+ let map = {};
3
+ for (let [optionName, optionConfig] of Object.entries(optionsConfig)){
4
+ if (typeof optionConfig.shortName === 'string') {
5
+ map[optionConfig.shortName] = optionName;
6
+ }
7
+ }
8
+ return map;
9
+ }
10
+
11
+ //# sourceMappingURL=createOptionShortNameMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/internals/createOptionShortNameMap.ts"],"sourcesContent":["import {type OptionsConfig} from '../types.js';\n\nexport function createOptionShortNameMap(optionsConfig: OptionsConfig) {\n let map: Record<string, string> = {};\n\n for (let [optionName, optionConfig] of Object.entries(optionsConfig)) {\n if (typeof optionConfig.shortName === 'string') {\n map[optionConfig.shortName] = optionName;\n }\n }\n\n return map;\n}\n"],"names":["createOptionShortNameMap","optionsConfig","map","optionName","optionConfig","Object","entries","shortName"],"mappings":"AAEA,OAAO,SAASA,yBAAyBC,aAA4B,EAAE;IACrE,IAAIC,MAA8B,CAAC;IAEnC,KAAK,IAAI,CAACC,YAAYC,aAAa,IAAIC,OAAOC,OAAO,CAACL,eAAgB;QACpE,IAAI,OAAOG,aAAaG,SAAS,KAAK,UAAU;YAC9CL,GAAG,CAACE,aAAaG,SAAS,CAAC,GAAGJ;QAChC,CAAC;IACH;IAEA,OAAOD;AACT,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { type Argv } from '../types.js';
2
+ /**
3
+ * A function that converts any argument that is a short options group into separate short options.
4
+ *
5
+ * @param argv Arguments.
6
+ * @return Arguments that contain no short options group
7
+ */
8
+ export declare function expandArguments(argv: Argv): Argv;
@@ -0,0 +1,21 @@
1
+ import { isShortOptionsGroup } from './isShortOptionsGroup.js';
2
+ /**
3
+ * A function that converts any argument that is a short options group into separate short options.
4
+ *
5
+ * @param argv Arguments.
6
+ * @return Arguments that contain no short options group
7
+ */ export function expandArguments(argv) {
8
+ let expandedArguments = [];
9
+ for (let arg of argv){
10
+ if (isShortOptionsGroup(arg)) {
11
+ expandedArguments.push(...[
12
+ ...arg
13
+ ].slice(1).map((value)=>`-${value}`));
14
+ } else {
15
+ expandedArguments.push(arg);
16
+ }
17
+ }
18
+ return expandedArguments;
19
+ }
20
+
21
+ //# sourceMappingURL=expandArguments.js.map