argot-cli 0.0.0-stage → 0.4.0-beta.1

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.
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Runtime error.
3
+ * Represents errors that occur while parsing input arguments.
4
+ * These errors are triggered by invalid or unexpected user input,
5
+ * such as unknown options, missing values, or values of the wrong type.
6
+ * Runtime errors are produced during the execution of the `.parse()`
7
+ * method and depend on the provided input rather than the parser
8
+ * configuration.
9
+ */
10
+ export declare class RuntimeError extends Error {
11
+ }
12
+ /**
13
+ * Configuration error.
14
+ * Represents errors caused by an invalid parser configuration.
15
+ * These errors occur when defining or initializing the parser,
16
+ * such as using unsupported option types or referencing invalid
17
+ * alias targets.
18
+ * Configuration errors are independent of user input and are
19
+ * typically raised before any parsing takes place.
20
+ */
21
+ export declare class ConfigError extends Error {
22
+ private _errors;
23
+ push(error: Error): void;
24
+ get errors(): Error[];
25
+ }
26
+ /**
27
+ * Invalid integer argument error.
28
+ * Raised when an option of type "int" is provided with an associated
29
+ * value that cannot be parsed as an integer.
30
+ * This error only applies when a value is present. Missing values are
31
+ * reported using NullIntError.
32
+ */
33
+ export declare class InvalidIntError extends RuntimeError {
34
+ value: string;
35
+ constructor(value: string);
36
+ }
37
+ /**
38
+ * Invalid float argument error.
39
+ * Raised when an option of type "float" is provided with an associated
40
+ * value that cannot be parsed as a number.
41
+ * This error only applies when a value is present. Missing values are
42
+ * reported using NullFloatError.
43
+ */
44
+ export declare class InvalidFloatError extends RuntimeError {
45
+ value: string;
46
+ constructor(value: string);
47
+ }
48
+ /**
49
+ * Unsafe integer error.
50
+ * Raised when a parsed integer cannot be safely represented
51
+ * by the underlying runtime.
52
+ * This error only applies to values that are successfully parsed
53
+ * as integers.
54
+ */
55
+ export declare class UnsafeIntegerError extends RuntimeError {
56
+ value: number;
57
+ constructor(value: number);
58
+ }
59
+ /**
60
+ * Missing argument error.
61
+ * Raised when an option that requires an associated value is provided
62
+ * without one.
63
+ * If the option is an alias, the error message includes both the
64
+ * alias name and its target.
65
+ */
66
+ export declare class NullArgError extends RuntimeError {
67
+ option: string;
68
+ target?: string;
69
+ constructor(name: string, target?: string);
70
+ }
71
+ /**
72
+ * Missing integer argument error.
73
+ * Raised when an option of type "int" is provided without an
74
+ * associated value.
75
+ * This error does not cover invalid integer values. Invalid values
76
+ * are reported using InvalidIntError.
77
+ * If the option is an alias, the error message includes both the
78
+ * alias name and its target.
79
+ */
80
+ export declare class NullIntError extends RuntimeError {
81
+ option: string;
82
+ target?: string;
83
+ constructor(name: string, target?: string);
84
+ }
85
+ /**
86
+ * Missing float argument error.
87
+ * Raised when an option of type "float" is provided without an
88
+ * associated value.
89
+ * This error does not cover invalid float values. Invalid values
90
+ * are reported using InvalidFloatError.
91
+ * If the option is an alias, the error message includes both the
92
+ * alias name and its target.
93
+ */
94
+ export declare class NullFloatError extends RuntimeError {
95
+ option: string;
96
+ target?: string;
97
+ constructor(name: string, target?: string);
98
+ }
99
+ /**
100
+ * Unknown option error.
101
+ * Raised when an input contains an option that is not defined in the
102
+ * parser configuration.
103
+ * This applies to both long and short options. The error is triggered
104
+ * as soon as the parser encounters an unrecognized option name.
105
+ */
106
+ export declare class UnknownOptionError extends RuntimeError {
107
+ option: string;
108
+ constructor(name: string);
109
+ }
110
+ /**
111
+ * Invalid option type error.
112
+ * Raised when an option is declared with a type that is not supported
113
+ * by the parser.
114
+ * This is a configuration error and typically occurs during parser
115
+ * initialization rather than at parse time.
116
+ */
117
+ export declare class InvalidOptionTypeError extends ConfigError {
118
+ type: string;
119
+ constructor(tag: string);
120
+ }
121
+ /**
122
+ * Alias target not found error.
123
+ * Raised when an alias references a target option that does not exist
124
+ * in the parser configuration.
125
+ * This is a configuration error and indicates that the alias points
126
+ * to an undefined option.
127
+ */
128
+ export declare class AliasTargetNotFoundError extends ConfigError {
129
+ option: string;
130
+ target: string;
131
+ constructor(name: string, target: string);
132
+ }
133
+ /**
134
+ * Invalid alias target error.
135
+ * Raised when an alias references a target that is not a valid option
136
+ * for aliasing.
137
+ * This may occur if the target is itself an alias (when alias chaining
138
+ * is not supported) or if the target cannot accept the alias due to
139
+ * type or configuration constraints.
140
+ */
141
+ export declare class InvalidAliasTargetError extends ConfigError {
142
+ option: string;
143
+ target: string;
144
+ constructor(name: string, target: string);
145
+ }
146
+ /**
147
+ * Missing option property error.
148
+ * Raised when an option entry in the parser configuration is missing
149
+ * one or more required properties.
150
+ * This is a configuration error and indicates that the option
151
+ * definition is incomplete or malformed.
152
+ * Implementations may include the option name and the missing
153
+ * property name to aid debugging.
154
+ */
155
+ export declare class MissingOptionPropertyError extends ConfigError {
156
+ option: string;
157
+ property: string;
158
+ constructor(option: string, property: string);
159
+ }
160
+ /**
161
+ * Missing option type error.
162
+ * Raised when a configuration entry does not define a "type" property.
163
+ * The "type" property is required for all option entries and determines
164
+ * how the option is parsed and validated. Without it, the entry cannot
165
+ * be interpreted by the parser.
166
+ * This is a configuration error and is typically raised during
167
+ * configuration validation.
168
+ */
169
+ export declare class MissingOptionTypeError extends ConfigError {
170
+ option: string;
171
+ constructor(name: string);
172
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Runtime error.
3
+ * Represents errors that occur while parsing input arguments.
4
+ * These errors are triggered by invalid or unexpected user input,
5
+ * such as unknown options, missing values, or values of the wrong type.
6
+ * Runtime errors are produced during the execution of the `.parse()`
7
+ * method and depend on the provided input rather than the parser
8
+ * configuration.
9
+ */
10
+ export class RuntimeError extends Error {
11
+ }
12
+ /**
13
+ * Configuration error.
14
+ * Represents errors caused by an invalid parser configuration.
15
+ * These errors occur when defining or initializing the parser,
16
+ * such as using unsupported option types or referencing invalid
17
+ * alias targets.
18
+ * Configuration errors are independent of user input and are
19
+ * typically raised before any parsing takes place.
20
+ */
21
+ export class ConfigError extends Error {
22
+ _errors = [];
23
+ push(error) {
24
+ this._errors.push(error);
25
+ }
26
+ get errors() {
27
+ return this._errors;
28
+ }
29
+ }
30
+ /**
31
+ * Invalid integer argument error.
32
+ * Raised when an option of type "int" is provided with an associated
33
+ * value that cannot be parsed as an integer.
34
+ * This error only applies when a value is present. Missing values are
35
+ * reported using NullIntError.
36
+ */
37
+ export class InvalidIntError extends RuntimeError {
38
+ value;
39
+ constructor(value) {
40
+ super(`'${value}' is not a valid integer`);
41
+ this.value = value;
42
+ Object.freeze(this);
43
+ }
44
+ }
45
+ /**
46
+ * Invalid float argument error.
47
+ * Raised when an option of type "float" is provided with an associated
48
+ * value that cannot be parsed as a number.
49
+ * This error only applies when a value is present. Missing values are
50
+ * reported using NullFloatError.
51
+ */
52
+ export class InvalidFloatError extends RuntimeError {
53
+ value;
54
+ constructor(value) {
55
+ super(`'${value}' is not a valid integer`);
56
+ this.value = value;
57
+ Object.freeze(this);
58
+ }
59
+ }
60
+ /**
61
+ * Unsafe integer error.
62
+ * Raised when a parsed integer cannot be safely represented
63
+ * by the underlying runtime.
64
+ * This error only applies to values that are successfully parsed
65
+ * as integers.
66
+ */
67
+ export class UnsafeIntegerError extends RuntimeError {
68
+ value;
69
+ constructor(value) {
70
+ super(`${value} is not a safe integer`);
71
+ this.value = value;
72
+ Object.freeze(this);
73
+ }
74
+ }
75
+ /**
76
+ * Missing argument error.
77
+ * Raised when an option that requires an associated value is provided
78
+ * without one.
79
+ * If the option is an alias, the error message includes both the
80
+ * alias name and its target.
81
+ */
82
+ export class NullArgError extends RuntimeError {
83
+ option;
84
+ target;
85
+ constructor(name, target) {
86
+ const msg = target
87
+ ? `option '${name}' (alias for '${target}') must take an argument`
88
+ : `option '${name}' must take an argument`;
89
+ super(msg);
90
+ this.option = name;
91
+ if (target) {
92
+ this.target = target;
93
+ }
94
+ Object.freeze(this);
95
+ }
96
+ }
97
+ /**
98
+ * Missing integer argument error.
99
+ * Raised when an option of type "int" is provided without an
100
+ * associated value.
101
+ * This error does not cover invalid integer values. Invalid values
102
+ * are reported using InvalidIntError.
103
+ * If the option is an alias, the error message includes both the
104
+ * alias name and its target.
105
+ */
106
+ export class NullIntError extends RuntimeError {
107
+ option;
108
+ target;
109
+ constructor(name, target) {
110
+ const msg = target
111
+ ? `option '${name}' (alias for '${target}') requires an integer number argument`
112
+ : `option '${name}' requires an integer number argument`;
113
+ super(msg);
114
+ this.option = name;
115
+ if (target) {
116
+ this.target = target;
117
+ }
118
+ Object.freeze(this);
119
+ }
120
+ }
121
+ /**
122
+ * Missing float argument error.
123
+ * Raised when an option of type "float" is provided without an
124
+ * associated value.
125
+ * This error does not cover invalid float values. Invalid values
126
+ * are reported using InvalidFloatError.
127
+ * If the option is an alias, the error message includes both the
128
+ * alias name and its target.
129
+ */
130
+ export class NullFloatError extends RuntimeError {
131
+ option;
132
+ target;
133
+ constructor(name, target) {
134
+ const msg = target
135
+ ? `option '${name}' (alias for '${target}') requires a numeric argument`
136
+ : `option '${name}' requires a numeric argument`;
137
+ super(msg);
138
+ this.option = name;
139
+ if (target) {
140
+ this.target = target;
141
+ }
142
+ Object.freeze(this);
143
+ }
144
+ }
145
+ /**
146
+ * Unknown option error.
147
+ * Raised when an input contains an option that is not defined in the
148
+ * parser configuration.
149
+ * This applies to both long and short options. The error is triggered
150
+ * as soon as the parser encounters an unrecognized option name.
151
+ */
152
+ export class UnknownOptionError extends RuntimeError {
153
+ option;
154
+ constructor(name) {
155
+ super(`option '${name}' is not supported`);
156
+ this.option = name;
157
+ Object.freeze(this);
158
+ }
159
+ }
160
+ /**
161
+ * Invalid option type error.
162
+ * Raised when an option is declared with a type that is not supported
163
+ * by the parser.
164
+ * This is a configuration error and typically occurs during parser
165
+ * initialization rather than at parse time.
166
+ */
167
+ export class InvalidOptionTypeError extends ConfigError {
168
+ type;
169
+ constructor(tag) {
170
+ super(`option type '${tag}' is not supported`);
171
+ this.type = tag;
172
+ Object.freeze(this);
173
+ }
174
+ }
175
+ /**
176
+ * Alias target not found error.
177
+ * Raised when an alias references a target option that does not exist
178
+ * in the parser configuration.
179
+ * This is a configuration error and indicates that the alias points
180
+ * to an undefined option.
181
+ */
182
+ export class AliasTargetNotFoundError extends ConfigError {
183
+ option;
184
+ target;
185
+ constructor(name, target) {
186
+ super(`target value '${target}' for option '${name}' was not found`);
187
+ this.option = name;
188
+ this.target = target;
189
+ Object.freeze(this);
190
+ }
191
+ }
192
+ /**
193
+ * Invalid alias target error.
194
+ * Raised when an alias references a target that is not a valid option
195
+ * for aliasing.
196
+ * This may occur if the target is itself an alias (when alias chaining
197
+ * is not supported) or if the target cannot accept the alias due to
198
+ * type or configuration constraints.
199
+ */
200
+ export class InvalidAliasTargetError extends ConfigError {
201
+ option;
202
+ target;
203
+ constructor(name, target) {
204
+ super(`cannot create an alias to another alias (${name} => ${target})`);
205
+ this.option = name;
206
+ this.target = target;
207
+ Object.freeze(this);
208
+ }
209
+ }
210
+ /**
211
+ * Missing option property error.
212
+ * Raised when an option entry in the parser configuration is missing
213
+ * one or more required properties.
214
+ * This is a configuration error and indicates that the option
215
+ * definition is incomplete or malformed.
216
+ * Implementations may include the option name and the missing
217
+ * property name to aid debugging.
218
+ */
219
+ export class MissingOptionPropertyError extends ConfigError {
220
+ option;
221
+ property;
222
+ constructor(option, property) {
223
+ super(`option '${option}' is missing required property '${property}'`);
224
+ this.option = option;
225
+ this.property = property;
226
+ Object.freeze(this);
227
+ }
228
+ }
229
+ /**
230
+ * Missing option type error.
231
+ * Raised when a configuration entry does not define a "type" property.
232
+ * The "type" property is required for all option entries and determines
233
+ * how the option is parsed and validated. Without it, the entry cannot
234
+ * be interpreted by the parser.
235
+ * This is a configuration error and is typically raised during
236
+ * configuration validation.
237
+ */
238
+ export class MissingOptionTypeError extends ConfigError {
239
+ option;
240
+ constructor(name) {
241
+ const msg = `option '${name}' is missing required property 'type'`;
242
+ super(msg);
243
+ this.option = name;
244
+ Object.freeze(this);
245
+ }
246
+ }
package/dist/mod.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Argot CLI argument parser.
3
+ *
4
+ * This module provides a schema-based command-line argument parser.
5
+ * The parser processes an array of strings and produces a structured
6
+ * result containing options, parameters, and operands.
7
+ *
8
+ * Parsing behavior is fully determined by a configuration object.
9
+ *
10
+ * Example:
11
+ *
12
+ * ```ts
13
+ * import {
14
+ * ArgParser,
15
+ * ParserConfig,
16
+ * type ConfigEntries,
17
+ * } from '@argot-cli/argot';
18
+ *
19
+ * const entries: ConfigEntries = {
20
+ * verbose: { type: 'flag' },
21
+ * count: { type: 'int' },
22
+ * name: { type: 'text', default: 'world' },
23
+ * };
24
+ *
25
+ * const config = new ParserConfig(entries);
26
+ *
27
+ * const parser = new ArgParser(config);
28
+ *
29
+ * const result = parser.parse([
30
+ * '--verbose',
31
+ * '--count=3',
32
+ * 'mode=fast',
33
+ * 'file.txt',
34
+ * ]);
35
+ *
36
+ * console.log(result.options.get('verbose')); // true
37
+ * console.log(result.options.get('count')); // 3
38
+ * console.log(result.options.get('name')); // "world"
39
+ *
40
+ * console.log(result.parameters.get('mode')); // "fast"
41
+ *
42
+ * console.log(result.operands); // ["file.txt"]
43
+ * ```
44
+ * @module
45
+ */
46
+ export { ArgParser } from './arg_parser.ts';
47
+ export { ParserConfig } from './parser_config.ts';
48
+ export { readJSONConfig } from './read_config.ts';
49
+ export type { ConfigEntry, ConfigEntries } from './types.ts';
package/dist/mod.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Argot CLI argument parser.
3
+ *
4
+ * This module provides a schema-based command-line argument parser.
5
+ * The parser processes an array of strings and produces a structured
6
+ * result containing options, parameters, and operands.
7
+ *
8
+ * Parsing behavior is fully determined by a configuration object.
9
+ *
10
+ * Example:
11
+ *
12
+ * ```ts
13
+ * import {
14
+ * ArgParser,
15
+ * ParserConfig,
16
+ * type ConfigEntries,
17
+ * } from '@argot-cli/argot';
18
+ *
19
+ * const entries: ConfigEntries = {
20
+ * verbose: { type: 'flag' },
21
+ * count: { type: 'int' },
22
+ * name: { type: 'text', default: 'world' },
23
+ * };
24
+ *
25
+ * const config = new ParserConfig(entries);
26
+ *
27
+ * const parser = new ArgParser(config);
28
+ *
29
+ * const result = parser.parse([
30
+ * '--verbose',
31
+ * '--count=3',
32
+ * 'mode=fast',
33
+ * 'file.txt',
34
+ * ]);
35
+ *
36
+ * console.log(result.options.get('verbose')); // true
37
+ * console.log(result.options.get('count')); // 3
38
+ * console.log(result.options.get('name')); // "world"
39
+ *
40
+ * console.log(result.parameters.get('mode')); // "fast"
41
+ *
42
+ * console.log(result.operands); // ["file.txt"]
43
+ * ```
44
+ * @module
45
+ */
46
+ export { ArgParser } from './arg_parser.js';
47
+ export { ParserConfig } from './parser_config.js';
48
+ export { readJSONConfig } from './read_config.js';
@@ -0,0 +1,23 @@
1
+ import type { ConfigEntry, ParserConfigInput } from './types.ts';
2
+ /**
3
+ * Immutable configuration for the argument parser.
4
+ * The configuration defines the set of supported options and their types.
5
+ * Entries are provided as an object mapping option names to configuration
6
+ * entries.
7
+ * The configuration is normalized and validated during construction.
8
+ * The resulting object is immutable.
9
+ */
10
+ export declare class ParserConfig {
11
+ #private;
12
+ constructor(input: ParserConfigInput);
13
+ entries(): Iterable<[string, ConfigEntry]>;
14
+ get(key: string): ConfigEntry | undefined;
15
+ has(key: string): boolean;
16
+ keys(): Iterable<string>;
17
+ values(): Iterable<ConfigEntry>;
18
+ toJSON(): ParserConfigInput;
19
+ get size(): number;
20
+ get allowUnknown(): boolean;
21
+ get parseParameters(): boolean;
22
+ get aggregateErrors(): boolean;
23
+ }
@@ -0,0 +1,83 @@
1
+ import { validateEntries, validateEntriesAggregate } from './utils.js';
2
+ function isObject(obj) {
3
+ if (Array.isArray(obj) || obj == null || typeof obj !== 'object')
4
+ return false;
5
+ return true;
6
+ }
7
+ /**
8
+ * Immutable configuration for the argument parser.
9
+ * The configuration defines the set of supported options and their types.
10
+ * Entries are provided as an object mapping option names to configuration
11
+ * entries.
12
+ * The configuration is normalized and validated during construction.
13
+ * The resulting object is immutable.
14
+ */
15
+ export class ParserConfig {
16
+ #entries;
17
+ #parser;
18
+ #size;
19
+ constructor(input) {
20
+ if (!isObject(input)) {
21
+ throw new TypeError('input value must be a plain object');
22
+ }
23
+ else if (!isObject(input.options)) {
24
+ throw new TypeError('"options" value must be a plain object');
25
+ }
26
+ else if (input.parser != null && !isObject(input.parser)) {
27
+ throw new TypeError('"parser" value must be a plain object');
28
+ }
29
+ const { options, parser } = input;
30
+ this.#parser = {
31
+ allowUnknown: parser?.allowUnknown ?? false,
32
+ parseParameters: parser?.parseParameters ?? true,
33
+ aggregateErrors: parser?.aggregateErrors ?? false,
34
+ };
35
+ this.#size = 0;
36
+ const entryMap = Object.create(null);
37
+ for (const [key, value] of Object.entries(options)) {
38
+ entryMap[key] = Object.freeze({ ...value });
39
+ this.#size += 1;
40
+ }
41
+ this.#entries = entryMap;
42
+ if (this.#parser.aggregateErrors)
43
+ validateEntriesAggregate(this.#entries);
44
+ else
45
+ validateEntries(this.#entries);
46
+ Object.freeze(this.#entries);
47
+ Object.freeze(this.#parser);
48
+ Object.freeze(this);
49
+ }
50
+ entries() {
51
+ return Object.entries(this.#entries);
52
+ }
53
+ get(key) {
54
+ return this.#entries[key];
55
+ }
56
+ has(key) {
57
+ return Object.hasOwn(this.#entries, key);
58
+ }
59
+ keys() {
60
+ return Object.keys(this.#entries);
61
+ }
62
+ values() {
63
+ return Object.values(this.#entries);
64
+ }
65
+ toJSON() {
66
+ return {
67
+ options: this.#entries,
68
+ parser: this.#parser,
69
+ };
70
+ }
71
+ get size() {
72
+ return this.#size;
73
+ }
74
+ get allowUnknown() {
75
+ return this.#parser.allowUnknown;
76
+ }
77
+ get parseParameters() {
78
+ return this.#parser.parseParameters;
79
+ }
80
+ get aggregateErrors() {
81
+ return this.#parser.aggregateErrors;
82
+ }
83
+ }
@@ -0,0 +1,7 @@
1
+ import { ParserConfig } from './parser_config.ts';
2
+ /**
3
+ * Reads a parser configuration from a JSON file.
4
+ * The file must contain a valid configuration object that can be
5
+ * passed to the ParserConfig constructor.
6
+ */
7
+ export declare function readJSONConfig(configFile: string): ParserConfig;
@@ -0,0 +1,12 @@
1
+ import fs from 'node:fs';
2
+ import { ParserConfig } from './parser_config.js';
3
+ /**
4
+ * Reads a parser configuration from a JSON file.
5
+ * The file must contain a valid configuration object that can be
6
+ * passed to the ParserConfig constructor.
7
+ */
8
+ export function readJSONConfig(configFile) {
9
+ const content = fs.readFileSync(configFile, { encoding: 'utf8' });
10
+ const configObj = JSON.parse(content);
11
+ return new ParserConfig(configObj);
12
+ }