argot-cli 0.4.0-beta → 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.
- package/argot-cli-0.4.0-beta.1.tgz +0 -0
- package/dist/arg_parser.d.ts +60 -0
- package/dist/arg_parser.js +557 -0
- package/dist/errors.d.ts +172 -0
- package/dist/errors.js +246 -0
- package/dist/mod.d.ts +49 -0
- package/dist/mod.js +48 -0
- package/dist/parser_config.d.ts +23 -0
- package/dist/parser_config.js +83 -0
- package/dist/read_config.d.ts +7 -0
- package/dist/read_config.js +12 -0
- package/dist/types.d.ts +185 -0
- package/dist/types.js +112 -0
- package/dist/utils.d.ts +48 -0
- package/dist/utils.js +175 -0
- package/package.json +1 -1
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Option type.
|
|
3
|
+
* Defines the kind of value an option accepts and how it is parsed.
|
|
4
|
+
*/
|
|
5
|
+
export type OptionType = 'flag' | 'text' | 'int' | 'float' | 'count' | 'list' | 'alias';
|
|
6
|
+
/**
|
|
7
|
+
* Alias target type.
|
|
8
|
+
* Represents the set of option types that an alias may reference.
|
|
9
|
+
* Aliases cannot target other aliases.
|
|
10
|
+
*/
|
|
11
|
+
export type AliasType = 'flag' | 'text' | 'int' | 'float' | 'count' | 'list';
|
|
12
|
+
/**
|
|
13
|
+
* Flag option entry.
|
|
14
|
+
* A flag is a boolean option that is set to true when present.
|
|
15
|
+
*/
|
|
16
|
+
export type FlagEntry = {
|
|
17
|
+
type: 'flag';
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Text option entry.
|
|
21
|
+
* A text option accepts a string value. A default value may be
|
|
22
|
+
* defined for command-line options provided without an associated
|
|
23
|
+
* value.
|
|
24
|
+
*/
|
|
25
|
+
export type TextEntry = {
|
|
26
|
+
type: 'text';
|
|
27
|
+
default?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Integer option entry.
|
|
31
|
+
* An integer option accepts a numeric value. The value must be a
|
|
32
|
+
* valid integer and must be a safe integer. A default value may
|
|
33
|
+
* be defined for command-line options provided without an
|
|
34
|
+
* associated value.
|
|
35
|
+
*/
|
|
36
|
+
export type IntEntry = {
|
|
37
|
+
type: 'int';
|
|
38
|
+
default?: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Float option entry.
|
|
42
|
+
* A float option takes any value that can be represented as a
|
|
43
|
+
* floating point number. Integer values are converted to floats.
|
|
44
|
+
*/
|
|
45
|
+
export type FloatEntry = {
|
|
46
|
+
type: 'float';
|
|
47
|
+
default?: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Count option entry.
|
|
51
|
+
* A count option increments a numeric counter each time the option
|
|
52
|
+
* is provided.
|
|
53
|
+
*/
|
|
54
|
+
export type CountEntry = {
|
|
55
|
+
type: 'count';
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* List option entry.
|
|
59
|
+
* A list option accepts a string value and splits it into multiple
|
|
60
|
+
* entries using a separator.
|
|
61
|
+
* The separator defaults to a comma if not specified.
|
|
62
|
+
*/
|
|
63
|
+
export type ListEntry = {
|
|
64
|
+
type: 'list';
|
|
65
|
+
sep?: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Alias option entry.
|
|
69
|
+
* An alias forwards its value to another option.
|
|
70
|
+
* The target must reference a valid, non-alias option.
|
|
71
|
+
*/
|
|
72
|
+
export type AliasEntry = {
|
|
73
|
+
type: 'alias';
|
|
74
|
+
target: string;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* A configuration entry representing a single command-line option.
|
|
78
|
+
*/
|
|
79
|
+
export type ConfigEntry = (FlagEntry | TextEntry | IntEntry | FloatEntry | CountEntry | ListEntry | AliasEntry);
|
|
80
|
+
/**
|
|
81
|
+
* An object holding option configuration entries.
|
|
82
|
+
*/
|
|
83
|
+
export type ConfigEntries = Record<string, ConfigEntry>;
|
|
84
|
+
/**
|
|
85
|
+
* ParserConfig configuration flags that don't refer to a single
|
|
86
|
+
* command-line option.
|
|
87
|
+
*/
|
|
88
|
+
export type ParserOptions = {
|
|
89
|
+
allowUnknown?: boolean;
|
|
90
|
+
parseParameters?: boolean;
|
|
91
|
+
aggregateErrors?: boolean;
|
|
92
|
+
};
|
|
93
|
+
export type StrictParserOptions = {
|
|
94
|
+
allowUnknown: boolean;
|
|
95
|
+
parseParameters: boolean;
|
|
96
|
+
aggregateErrors: boolean;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* The input object for the ParserConfig constructor.
|
|
100
|
+
* Contains configuration for specific command-line options
|
|
101
|
+
* and general configuration options.
|
|
102
|
+
*/
|
|
103
|
+
export type ParserConfigInput = {
|
|
104
|
+
options: ConfigEntries;
|
|
105
|
+
parser?: ParserOptions;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Option value.
|
|
109
|
+
* Represents the possible values returned for parsed options.
|
|
110
|
+
*/
|
|
111
|
+
export type OptionValue = boolean | string | number | string[];
|
|
112
|
+
/**
|
|
113
|
+
* Result mapping.
|
|
114
|
+
* A map-like structure used to store parsed key-value pairs.
|
|
115
|
+
* Instances can be frozen to prevent further modifications.
|
|
116
|
+
*/
|
|
117
|
+
declare abstract class ResultMapping<K, V> extends Map<K, V> {
|
|
118
|
+
protected isFrozen: boolean;
|
|
119
|
+
constructor(entries?: [K, V][]);
|
|
120
|
+
/**
|
|
121
|
+
* Sets a value for the given key.
|
|
122
|
+
* Throws if the mapping is frozen.
|
|
123
|
+
*/
|
|
124
|
+
set(key: K, value: V): this;
|
|
125
|
+
/**
|
|
126
|
+
* Deletes a key from the mapping.
|
|
127
|
+
* Throws if the mapping is frozen.
|
|
128
|
+
*/
|
|
129
|
+
delete(key: K): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Clears all entries from the mapping.
|
|
132
|
+
* Throws if the mapping is frozen.
|
|
133
|
+
*/
|
|
134
|
+
clear(): void;
|
|
135
|
+
/**
|
|
136
|
+
* Freezes the mapping, preventing further modifications.
|
|
137
|
+
*/
|
|
138
|
+
freeze(): void;
|
|
139
|
+
/**
|
|
140
|
+
* Serializes the mapping to a plain object.
|
|
141
|
+
*/
|
|
142
|
+
toJSON(): Record<string, V>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Result list.
|
|
146
|
+
* An array-like structure used to store ordered values.
|
|
147
|
+
* Only numeric indices and the length property may be modified.
|
|
148
|
+
* Assigning any other property will throw an error.
|
|
149
|
+
*/
|
|
150
|
+
declare abstract class ResultList<T> extends Array<T> {
|
|
151
|
+
constructor(args?: T[]);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parsed option values.
|
|
155
|
+
* Values are determined by the parser configuration. Repeated options
|
|
156
|
+
* either overwrite previous values or accumulate them, depending on
|
|
157
|
+
* their type.
|
|
158
|
+
*/
|
|
159
|
+
export declare class Options extends ResultMapping<string, OptionValue> {
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parsed key/value assignments.
|
|
163
|
+
* Parameters are parsed from arguments of the form "key=value" and do
|
|
164
|
+
* not depend on the parser configuration.
|
|
165
|
+
*/
|
|
166
|
+
export declare class Parameters extends ResultMapping<string, string> {
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Positional arguments.
|
|
170
|
+
* Operands are arguments that are not parsed as options or parameters.
|
|
171
|
+
*/
|
|
172
|
+
export declare class Operands extends ResultList<string> {
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The result of parsing operations.
|
|
176
|
+
* - options: parsed option values
|
|
177
|
+
* - parameters: parsed named parameters
|
|
178
|
+
* - operands: positional arguments
|
|
179
|
+
*/
|
|
180
|
+
export interface ParseResult {
|
|
181
|
+
options: Options;
|
|
182
|
+
parameters?: Parameters;
|
|
183
|
+
operands: Operands;
|
|
184
|
+
}
|
|
185
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result mapping.
|
|
3
|
+
* A map-like structure used to store parsed key-value pairs.
|
|
4
|
+
* Instances can be frozen to prevent further modifications.
|
|
5
|
+
*/
|
|
6
|
+
class ResultMapping extends Map {
|
|
7
|
+
isFrozen = false;
|
|
8
|
+
constructor(entries) {
|
|
9
|
+
super(entries);
|
|
10
|
+
// Prevent property from showing up in console.log.
|
|
11
|
+
Object.defineProperty(this, 'isFrozen', {
|
|
12
|
+
enumerable: false,
|
|
13
|
+
});
|
|
14
|
+
// Prevent regular object property assignments.
|
|
15
|
+
Object.preventExtensions(this);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sets a value for the given key.
|
|
19
|
+
* Throws if the mapping is frozen.
|
|
20
|
+
*/
|
|
21
|
+
set(key, value) {
|
|
22
|
+
if (this.isFrozen) {
|
|
23
|
+
const name = this.constructor.name.toLowerCase();
|
|
24
|
+
throw new TypeError(`you cannot modify parsed ${name}`);
|
|
25
|
+
}
|
|
26
|
+
return super.set(key, value);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Deletes a key from the mapping.
|
|
30
|
+
* Throws if the mapping is frozen.
|
|
31
|
+
*/
|
|
32
|
+
delete(key) {
|
|
33
|
+
if (this.isFrozen) {
|
|
34
|
+
const name = this.constructor.name.toLowerCase();
|
|
35
|
+
throw new TypeError(`you cannot delete parsed ${name}`);
|
|
36
|
+
}
|
|
37
|
+
return super.delete(key);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Clears all entries from the mapping.
|
|
41
|
+
* Throws if the mapping is frozen.
|
|
42
|
+
*/
|
|
43
|
+
clear() {
|
|
44
|
+
if (this.isFrozen) {
|
|
45
|
+
const name = this.constructor.name.toLowerCase();
|
|
46
|
+
throw new TypeError(`you cannot delete parsed ${name}`);
|
|
47
|
+
}
|
|
48
|
+
super.clear();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Freezes the mapping, preventing further modifications.
|
|
52
|
+
*/
|
|
53
|
+
freeze() {
|
|
54
|
+
this.isFrozen = true;
|
|
55
|
+
Object.freeze(this);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Serializes the mapping to a plain object.
|
|
59
|
+
*/
|
|
60
|
+
toJSON() {
|
|
61
|
+
return Object.fromEntries(this.entries());
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Result list.
|
|
66
|
+
* An array-like structure used to store ordered values.
|
|
67
|
+
* Only numeric indices and the length property may be modified.
|
|
68
|
+
* Assigning any other property will throw an error.
|
|
69
|
+
*/
|
|
70
|
+
class ResultList extends Array {
|
|
71
|
+
constructor(args) {
|
|
72
|
+
const length = args?.length ?? 0;
|
|
73
|
+
super(length);
|
|
74
|
+
for (let i = 0; i < length; i++) {
|
|
75
|
+
this[i] = args[i];
|
|
76
|
+
}
|
|
77
|
+
return new Proxy(this, {
|
|
78
|
+
set(target, prop, value) {
|
|
79
|
+
if (prop === 'length') {
|
|
80
|
+
target[prop] = value;
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
else if (String(Number(prop)) === prop) {
|
|
84
|
+
target[Number(prop)] = value;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
throw new TypeError(`Cannot add non-index property: ${String(prop)}`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Parsed option values.
|
|
94
|
+
* Values are determined by the parser configuration. Repeated options
|
|
95
|
+
* either overwrite previous values or accumulate them, depending on
|
|
96
|
+
* their type.
|
|
97
|
+
*/
|
|
98
|
+
export class Options extends ResultMapping {
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parsed key/value assignments.
|
|
102
|
+
* Parameters are parsed from arguments of the form "key=value" and do
|
|
103
|
+
* not depend on the parser configuration.
|
|
104
|
+
*/
|
|
105
|
+
export class Parameters extends ResultMapping {
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Positional arguments.
|
|
109
|
+
* Operands are arguments that are not parsed as options or parameters.
|
|
110
|
+
*/
|
|
111
|
+
export class Operands extends ResultList {
|
|
112
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ConfigEntry, ConfigEntries } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Parses a string as an integer.
|
|
4
|
+
* The value must consist only of an optional sign followed by digits.
|
|
5
|
+
* The resulting number must be safely representable by the runtime.
|
|
6
|
+
* Throws:
|
|
7
|
+
* - InvalidIntError if the value is not a valid integer string
|
|
8
|
+
* - UnsafeIntegerError if the parsed value cannot be safely represented
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseIntStrict(value: string): number;
|
|
11
|
+
/**
|
|
12
|
+
* Parses a string as a floating-point number.
|
|
13
|
+
* The value must consist only of:
|
|
14
|
+
* - an optional sign
|
|
15
|
+
* - digits
|
|
16
|
+
* - an optional fractional part
|
|
17
|
+
* - an optional exponent
|
|
18
|
+
*
|
|
19
|
+
* Whitespace, Infinity and NaN are not allowed.
|
|
20
|
+
*
|
|
21
|
+
* Throws:
|
|
22
|
+
* - InvalidFloatError if the value is not a valid float string
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseFloatStrict(value: string): number;
|
|
25
|
+
/**
|
|
26
|
+
* Validates a single configuration entry.
|
|
27
|
+
* The entry must be a labeled object containing at least the "option"
|
|
28
|
+
* and "type" properties. Additional properties are validated according
|
|
29
|
+
* to the entry type.
|
|
30
|
+
* Throws:
|
|
31
|
+
* - TypeError if the entry is not an object or contains invalid values
|
|
32
|
+
* - MissingOptionPropertyError if a required property is missing
|
|
33
|
+
* - InvalidOptionTypeError if the option type is not supported
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateEntry(name: string, entry: ConfigEntry): void;
|
|
36
|
+
/**
|
|
37
|
+
* Validates a set of configuration entries.
|
|
38
|
+
* Each entry is validated individually. Alias entries are validated
|
|
39
|
+
* after all entries have been processed to ensure that:
|
|
40
|
+
* - the target exists
|
|
41
|
+
* - the target is not itself an alias
|
|
42
|
+
* Throws:
|
|
43
|
+
* - Any error raised by validateEntry
|
|
44
|
+
* - AliasTargetNotFoundError if an alias target does not exist
|
|
45
|
+
* - InvalidAliasTargetError if an alias targets another alias
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateEntries(entries: ConfigEntries): void;
|
|
48
|
+
export declare function validateEntriesAggregate(entries: ConfigEntries): void;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { AliasTargetNotFoundError, ConfigError, InvalidAliasTargetError, InvalidFloatError, InvalidIntError, InvalidOptionTypeError, MissingOptionPropertyError, MissingOptionTypeError, UnsafeIntegerError, } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses a string as an integer.
|
|
4
|
+
* The value must consist only of an optional sign followed by digits.
|
|
5
|
+
* The resulting number must be safely representable by the runtime.
|
|
6
|
+
* Throws:
|
|
7
|
+
* - InvalidIntError if the value is not a valid integer string
|
|
8
|
+
* - UnsafeIntegerError if the parsed value cannot be safely represented
|
|
9
|
+
*/
|
|
10
|
+
export function parseIntStrict(value) {
|
|
11
|
+
if (!/^(-|\+)?\d+$/.test(value)) {
|
|
12
|
+
throw new InvalidIntError(value);
|
|
13
|
+
}
|
|
14
|
+
const num = Number(value);
|
|
15
|
+
if (!Number.isSafeInteger(num)) {
|
|
16
|
+
throw new UnsafeIntegerError(num);
|
|
17
|
+
}
|
|
18
|
+
return num;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses a string as a floating-point number.
|
|
22
|
+
* The value must consist only of:
|
|
23
|
+
* - an optional sign
|
|
24
|
+
* - digits
|
|
25
|
+
* - an optional fractional part
|
|
26
|
+
* - an optional exponent
|
|
27
|
+
*
|
|
28
|
+
* Whitespace, Infinity and NaN are not allowed.
|
|
29
|
+
*
|
|
30
|
+
* Throws:
|
|
31
|
+
* - InvalidFloatError if the value is not a valid float string
|
|
32
|
+
*/
|
|
33
|
+
export function parseFloatStrict(value) {
|
|
34
|
+
if (!/^(-|\+)?(\d+(\.\d+)?|\.\d+)([eE](-|\+)?\d+)?$/.test(value)) {
|
|
35
|
+
throw new InvalidFloatError(value);
|
|
36
|
+
}
|
|
37
|
+
const num = Number(value);
|
|
38
|
+
if (!Number.isFinite(num)) {
|
|
39
|
+
throw new InvalidFloatError(value);
|
|
40
|
+
}
|
|
41
|
+
return num;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validates a single configuration entry.
|
|
45
|
+
* The entry must be a labeled object containing at least the "option"
|
|
46
|
+
* and "type" properties. Additional properties are validated according
|
|
47
|
+
* to the entry type.
|
|
48
|
+
* Throws:
|
|
49
|
+
* - TypeError if the entry is not an object or contains invalid values
|
|
50
|
+
* - MissingOptionPropertyError if a required property is missing
|
|
51
|
+
* - InvalidOptionTypeError if the option type is not supported
|
|
52
|
+
*/
|
|
53
|
+
export function validateEntry(name, entry) {
|
|
54
|
+
if (entry == null || typeof entry !== 'object') {
|
|
55
|
+
throw new TypeError('option config entry must be an object');
|
|
56
|
+
}
|
|
57
|
+
else if (!Object.hasOwn(entry, 'type')) {
|
|
58
|
+
throw new MissingOptionTypeError(name);
|
|
59
|
+
}
|
|
60
|
+
const tag = entry.type;
|
|
61
|
+
switch (tag) {
|
|
62
|
+
case 'flag':
|
|
63
|
+
case 'count': {
|
|
64
|
+
/* these types have no extra mandatory values */
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case 'text': {
|
|
68
|
+
if (!Object.hasOwn(entry, 'default'))
|
|
69
|
+
break;
|
|
70
|
+
const { default: def } = entry;
|
|
71
|
+
if (typeof def !== 'string')
|
|
72
|
+
throw new TypeError('default value must be a string');
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'int': {
|
|
76
|
+
if (!Object.hasOwn(entry, 'default'))
|
|
77
|
+
break;
|
|
78
|
+
const { default: def } = entry;
|
|
79
|
+
if (typeof def !== 'number' || !Number.isInteger(def))
|
|
80
|
+
throw new TypeError('default value must be an integer');
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case 'float': {
|
|
84
|
+
if (!Object.hasOwn(entry, 'default'))
|
|
85
|
+
break;
|
|
86
|
+
const { default: def } = entry;
|
|
87
|
+
if (typeof def !== 'number' || !Number.isFinite(def))
|
|
88
|
+
throw new TypeError('default value must be a number');
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case 'list': {
|
|
92
|
+
if (!Object.hasOwn(entry, 'sep'))
|
|
93
|
+
break;
|
|
94
|
+
const { sep } = entry;
|
|
95
|
+
if (typeof sep !== 'string')
|
|
96
|
+
throw new TypeError('sep value must be a string');
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'alias': {
|
|
100
|
+
if (!Object.hasOwn(entry, 'target')) {
|
|
101
|
+
throw new MissingOptionPropertyError(name, 'target');
|
|
102
|
+
}
|
|
103
|
+
const { target } = entry;
|
|
104
|
+
if (typeof target !== 'string')
|
|
105
|
+
throw new TypeError('target value must be a string');
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
default: {
|
|
109
|
+
throw new InvalidOptionTypeError(tag);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Validates a set of configuration entries.
|
|
115
|
+
* Each entry is validated individually. Alias entries are validated
|
|
116
|
+
* after all entries have been processed to ensure that:
|
|
117
|
+
* - the target exists
|
|
118
|
+
* - the target is not itself an alias
|
|
119
|
+
* Throws:
|
|
120
|
+
* - Any error raised by validateEntry
|
|
121
|
+
* - AliasTargetNotFoundError if an alias target does not exist
|
|
122
|
+
* - InvalidAliasTargetError if an alias targets another alias
|
|
123
|
+
*/
|
|
124
|
+
export function validateEntries(entries) {
|
|
125
|
+
const aliases = [];
|
|
126
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
127
|
+
validateEntry(name, entry);
|
|
128
|
+
const tag = entry.type;
|
|
129
|
+
if (tag === 'alias') {
|
|
130
|
+
const { target } = entry;
|
|
131
|
+
aliases.push([name, target]);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const [name, target] of aliases) {
|
|
135
|
+
if (!Object.hasOwn(entries, target)) {
|
|
136
|
+
throw new AliasTargetNotFoundError(name, target);
|
|
137
|
+
}
|
|
138
|
+
const targetEntry = entries[target];
|
|
139
|
+
if (targetEntry.type === 'alias') {
|
|
140
|
+
throw new InvalidAliasTargetError(name, target);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export function validateEntriesAggregate(entries) {
|
|
145
|
+
const aliases = [];
|
|
146
|
+
const error = new ConfigError('parser configuration is not valid');
|
|
147
|
+
for (const [name, entry] of Object.entries(entries)) {
|
|
148
|
+
try {
|
|
149
|
+
validateEntry(name, entry);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
error.push(err);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const tag = entry.type;
|
|
156
|
+
if (tag === 'alias') {
|
|
157
|
+
const { target } = entry;
|
|
158
|
+
aliases.push([name, target]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const [name, target] of aliases) {
|
|
162
|
+
if (!Object.hasOwn(entries, target)) {
|
|
163
|
+
error.push(new AliasTargetNotFoundError(name, target));
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const targetEntry = entries[target];
|
|
167
|
+
if (targetEntry.type === 'alias') {
|
|
168
|
+
error.push(new InvalidAliasTargetError(name, target));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (error.errors.length === 1)
|
|
172
|
+
throw error.errors[0];
|
|
173
|
+
else if (error.errors.length > 1)
|
|
174
|
+
throw error;
|
|
175
|
+
}
|