args-tokens 0.18.0 → 0.19.0
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/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArgToken, ParserOptions, parseArgs$1 as parseArgs } from "./parser-Bx112mWZ.js";
|
|
2
|
-
import { ArgResolveError$1 as ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ResolveArgs, resolveArgs$1 as resolveArgs } from "./resolver-
|
|
2
|
+
import { ArgResolveError$1 as ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ResolveArgs, resolveArgs$1 as resolveArgs } from "./resolver-COGeGqd3.js";
|
|
3
3
|
|
|
4
4
|
//#region src/parse.d.ts
|
|
5
5
|
/**
|
package/lib/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ArgToken } from "./parser-Bx112mWZ.js";
|
|
|
6
6
|
* This schema is similar to the schema of the `node:utils`.
|
|
7
7
|
* difference is that:
|
|
8
8
|
* - `required` property and `description` property are added
|
|
9
|
-
* - `type` is not only 'string' and 'boolean', but also 'number', 'enum'
|
|
9
|
+
* - `type` is not only 'string' and 'boolean', but also 'number', 'enum', 'positional', 'custom' too.
|
|
10
10
|
* - `default` property type, not support multiple types
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
@@ -14,16 +14,16 @@ import { ArgToken } from "./parser-Bx112mWZ.js";
|
|
|
14
14
|
* This schema is similar to the schema of the `node:utils`.
|
|
15
15
|
* difference is that:
|
|
16
16
|
* - `required` property and `description` property are added
|
|
17
|
-
* - `type` is not only 'string' and 'boolean', but also 'number', 'enum'
|
|
17
|
+
* - `type` is not only 'string' and 'boolean', but also 'number', 'enum', 'positional', 'custom' too.
|
|
18
18
|
* - `default` property type, not support multiple types
|
|
19
19
|
*/
|
|
20
20
|
interface ArgSchema {
|
|
21
21
|
/**
|
|
22
22
|
* Type of argument.
|
|
23
23
|
*/
|
|
24
|
-
type: "string" | "boolean" | "number" | "enum" | "positional";
|
|
24
|
+
type: "string" | "boolean" | "number" | "enum" | "positional" | "custom";
|
|
25
25
|
/**
|
|
26
|
-
* A single character alias for the
|
|
26
|
+
* A single character alias for the argument.
|
|
27
27
|
*/
|
|
28
28
|
short?: string;
|
|
29
29
|
/**
|
|
@@ -51,6 +51,19 @@ interface ArgSchema {
|
|
|
51
51
|
* if the type is 'enum', the default value must be one of the allowed values.
|
|
52
52
|
*/
|
|
53
53
|
default?: string | boolean | number;
|
|
54
|
+
/**
|
|
55
|
+
* Whether to convert the argument name to kebab-case.
|
|
56
|
+
*/
|
|
57
|
+
toKebab?: true;
|
|
58
|
+
/**
|
|
59
|
+
* A function to parse the value of the argument. if the type is 'custom', this function is required.
|
|
60
|
+
* If argument value will be invalid, this function have to throw an error.
|
|
61
|
+
* @param value
|
|
62
|
+
* @returns Parsed value
|
|
63
|
+
* @throws An Error, If the value is invalid. Error type should be `Error` or extends it
|
|
64
|
+
*/
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
parse?: (value: string) => any;
|
|
54
67
|
}
|
|
55
68
|
/**
|
|
56
69
|
* An object that contains {@link ArgSchema | argument schema}.
|
|
@@ -64,10 +77,12 @@ interface Args {
|
|
|
64
77
|
type ArgValues<T> = T extends Args ? ResolveArgValues<T, { [Arg in keyof T]: ExtractOptionValue<T[Arg]> }> : {
|
|
65
78
|
[option: string]: string | boolean | number | (string | boolean | number)[] | undefined;
|
|
66
79
|
};
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
|
+
type IsFunction<T> = T extends ((...args: any[]) => any) ? true : false;
|
|
67
82
|
/**
|
|
68
83
|
* @internal
|
|
69
84
|
*/
|
|
70
|
-
type ExtractOptionValue<A extends ArgSchema> = A["type"] extends "string" ? ResolveOptionValue<A, string> : A["type"] extends "boolean" ? ResolveOptionValue<A, boolean> : A["type"] extends "number" ? ResolveOptionValue<A, number> : A["type"] extends "positional" ? ResolveOptionValue<A, string> : A["type"] extends "enum" ? A["choices"] extends string[] | readonly string[] ? ResolveOptionValue<A, A["choices"][number]> : never : ResolveOptionValue<A, string | boolean | number>;
|
|
85
|
+
type ExtractOptionValue<A extends ArgSchema> = A["type"] extends "string" ? ResolveOptionValue<A, string> : A["type"] extends "boolean" ? ResolveOptionValue<A, boolean> : A["type"] extends "number" ? ResolveOptionValue<A, number> : A["type"] extends "positional" ? ResolveOptionValue<A, string> : A["type"] extends "enum" ? A["choices"] extends string[] | readonly string[] ? ResolveOptionValue<A, A["choices"][number]> : never : A["type"] extends "custom" ? IsFunction<A["parse"]> extends true ? ResolveOptionValue<A, ReturnType<NonNullable<A["parse"]>>> : never : ResolveOptionValue<A, string | boolean | number>;
|
|
71
86
|
type ResolveOptionValue<A extends ArgSchema, T> = A["multiple"] extends true ? T[] : T;
|
|
72
87
|
/**
|
|
73
88
|
* @internal
|
|
@@ -82,16 +97,21 @@ type FilterArgs<A extends Args, V extends Record<keyof A, unknown>, K extends ke
|
|
|
82
97
|
*/
|
|
83
98
|
interface ResolveArgs {
|
|
84
99
|
/**
|
|
85
|
-
* Whether to group short
|
|
100
|
+
* Whether to group short arguments.
|
|
86
101
|
* @default false
|
|
87
102
|
* @see guideline 5 in https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html
|
|
88
103
|
*/
|
|
89
|
-
|
|
104
|
+
shortGrouping?: boolean;
|
|
90
105
|
/**
|
|
91
106
|
* Skip positional arguments index.
|
|
92
107
|
* @default -1
|
|
93
108
|
*/
|
|
94
109
|
skipPositional?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Whether to convert the argument name to kebab-case. This option is applied to all arguments as `toKebab: true`, if set to `true`.
|
|
112
|
+
* @default false
|
|
113
|
+
*/
|
|
114
|
+
toKebab?: boolean;
|
|
95
115
|
}
|
|
96
116
|
/**
|
|
97
117
|
* Resolve command line arguments.
|
|
@@ -101,8 +121,9 @@ interface ResolveArgs {
|
|
|
101
121
|
* @returns An object that contains the values of the arguments, positional arguments, rest arguments, and {@link AggregateError | validation errors}.
|
|
102
122
|
*/
|
|
103
123
|
declare function resolveArgs<A extends Args>(args: A, tokens: ArgToken[], {
|
|
104
|
-
|
|
105
|
-
skipPositional
|
|
124
|
+
shortGrouping,
|
|
125
|
+
skipPositional,
|
|
126
|
+
toKebab
|
|
106
127
|
}?: ResolveArgs): {
|
|
107
128
|
values: ArgValues<A>;
|
|
108
129
|
positionals: string[];
|
|
@@ -2,6 +2,9 @@ import { hasLongOptionPrefix, isShortOption } from "./parser-Dr4iAGaX.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/resolver.ts
|
|
4
4
|
const SKIP_POSITIONAL_DEFAULT = -1;
|
|
5
|
+
function kebabnize(str) {
|
|
6
|
+
return str.replace(/[A-Z]/g, (match, offset) => (offset > 0 ? "-" : "") + match.toLowerCase());
|
|
7
|
+
}
|
|
5
8
|
/**
|
|
6
9
|
* Resolve command line arguments.
|
|
7
10
|
* @param args - An arguments that contains {@link ArgSchema | arguments schema}.
|
|
@@ -9,7 +12,7 @@ const SKIP_POSITIONAL_DEFAULT = -1;
|
|
|
9
12
|
* @param resolveArgs - An arguments that contains {@link ResolveArgs | resolve arguments}.
|
|
10
13
|
* @returns An object that contains the values of the arguments, positional arguments, rest arguments, and {@link AggregateError | validation errors}.
|
|
11
14
|
*/
|
|
12
|
-
function resolveArgs(args, tokens, {
|
|
15
|
+
function resolveArgs(args, tokens, { shortGrouping = false, skipPositional = SKIP_POSITIONAL_DEFAULT, toKebab = false } = {}) {
|
|
13
16
|
const skipPositionalIndex = typeof skipPositional === "number" ? Math.max(skipPositional, SKIP_POSITIONAL_DEFAULT) : SKIP_POSITIONAL_DEFAULT;
|
|
14
17
|
const rest = [];
|
|
15
18
|
const optionTokens = [];
|
|
@@ -68,7 +71,7 @@ function resolveArgs(args, tokens, { optionGrouping = false, skipPositional = SK
|
|
|
68
71
|
else currentLongOption = { ...token };
|
|
69
72
|
applyShortOptionValue();
|
|
70
73
|
} else if (isShortOption(token.rawName)) if (currentShortOption) {
|
|
71
|
-
if (currentShortOption.index === token.index) if (
|
|
74
|
+
if (currentShortOption.index === token.index) if (shortGrouping) {
|
|
72
75
|
currentShortOption.value = token.value;
|
|
73
76
|
optionTokens.push({ ...currentShortOption });
|
|
74
77
|
currentShortOption = { ...token };
|
|
@@ -115,48 +118,43 @@ function resolveArgs(args, tokens, { optionGrouping = false, skipPositional = SK
|
|
|
115
118
|
return Math.min(skipPositionalIndex, positionalItemCount);
|
|
116
119
|
}
|
|
117
120
|
let positionalsCount = 0;
|
|
118
|
-
for (const [
|
|
121
|
+
for (const [rawArg, schema] of Object.entries(args)) {
|
|
122
|
+
const arg = toKebab || schema.toKebab ? kebabnize(rawArg) : rawArg;
|
|
119
123
|
if (schema.required) {
|
|
120
124
|
const found = optionTokens.find((token) => {
|
|
121
|
-
return schema.short && token.name === schema.short || token.rawName && hasLongOptionPrefix(token.rawName) && token.name ===
|
|
125
|
+
return schema.short && token.name === schema.short || token.rawName && hasLongOptionPrefix(token.rawName) && token.name === arg;
|
|
122
126
|
});
|
|
123
127
|
if (!found) {
|
|
124
|
-
errors.push(createRequireError(
|
|
128
|
+
errors.push(createRequireError(arg, schema));
|
|
125
129
|
continue;
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
132
|
if (schema.type === "positional") {
|
|
129
133
|
if (skipPositionalIndex > SKIP_POSITIONAL_DEFAULT) while (positionalsCount <= getPositionalSkipIndex()) positionalsCount++;
|
|
130
134
|
const positional = positionalTokens[positionalsCount];
|
|
131
|
-
if (positional != null) values[
|
|
132
|
-
else errors.push(createRequireError(
|
|
135
|
+
if (positional != null) values[rawArg] = positional.value;
|
|
136
|
+
else errors.push(createRequireError(arg, schema));
|
|
133
137
|
positionalsCount++;
|
|
134
138
|
continue;
|
|
135
139
|
}
|
|
136
140
|
for (let i = 0; i < optionTokens.length; i++) {
|
|
137
141
|
const token = optionTokens[i];
|
|
138
|
-
if (checkTokenName(
|
|
139
|
-
const invalid = validateRequire(token,
|
|
142
|
+
if (checkTokenName(arg, schema, token) && token.rawName != void 0 && hasLongOptionPrefix(token.rawName) || schema.short === token.name && token.rawName != void 0 && isShortOption(token.rawName)) {
|
|
143
|
+
const invalid = validateRequire(token, arg, schema);
|
|
140
144
|
if (invalid) {
|
|
141
145
|
errors.push(invalid);
|
|
142
146
|
continue;
|
|
143
147
|
}
|
|
144
148
|
if (schema.type === "boolean") token.value = void 0;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
if (schema.multiple) {
|
|
153
|
-
values[option] ||= [];
|
|
154
|
-
values[option].push(resolveArgumentValue(token, schema));
|
|
155
|
-
} else values[option] = resolveArgumentValue(token, schema);
|
|
156
|
-
continue;
|
|
149
|
+
const [parsedValue, error] = parse(token, arg, schema);
|
|
150
|
+
if (error) errors.push(error);
|
|
151
|
+
else if (schema.multiple) {
|
|
152
|
+
values[rawArg] ||= [];
|
|
153
|
+
values[rawArg].push(parsedValue);
|
|
154
|
+
} else values[rawArg] = parsedValue;
|
|
157
155
|
}
|
|
158
156
|
}
|
|
159
|
-
if (values[
|
|
157
|
+
if (values[rawArg] == null && schema.default != null) values[rawArg] = schema.default;
|
|
160
158
|
}
|
|
161
159
|
return {
|
|
162
160
|
values,
|
|
@@ -165,6 +163,29 @@ function resolveArgs(args, tokens, { optionGrouping = false, skipPositional = SK
|
|
|
165
163
|
error: errors.length > 0 ? new AggregateError(errors) : void 0
|
|
166
164
|
};
|
|
167
165
|
}
|
|
166
|
+
function parse(token, option, schema) {
|
|
167
|
+
switch (schema.type) {
|
|
168
|
+
case "string": return typeof token.value === "string" ? [token.value || schema.default, void 0] : [void 0, createTypeError(option, schema)];
|
|
169
|
+
case "boolean": return token.value ? [token.value || schema.default, void 0] : [!(schema.negatable && token.name.startsWith("no-")), void 0];
|
|
170
|
+
case "number": {
|
|
171
|
+
if (!isNumeric(token.value)) return [void 0, createTypeError(option, schema)];
|
|
172
|
+
return token.value ? [+token.value, void 0] : [+(schema.default || ""), void 0];
|
|
173
|
+
}
|
|
174
|
+
case "enum": {
|
|
175
|
+
if (schema.choices && !schema.choices.includes(token.value)) return [void 0, new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be chosen from '${schema.type}' [${schema.choices.map((c) => JSON.stringify(c)).join(", ")}] values`, option, "type", schema)];
|
|
176
|
+
return [token.value || schema.default, void 0];
|
|
177
|
+
}
|
|
178
|
+
case "custom": {
|
|
179
|
+
if (typeof schema.parse !== "function") throw new TypeError(`argument '${option}' should have a 'parse' function`);
|
|
180
|
+
try {
|
|
181
|
+
return [schema.parse(token.value || String(schema.default || "")), void 0];
|
|
182
|
+
} catch (error) {
|
|
183
|
+
return [void 0, error];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
default: throw new Error(`Unsupported argument type '${schema.type}' for option '${option}'`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
168
189
|
function createRequireError(option, schema) {
|
|
169
190
|
const message = schema.type === "positional" ? `Positional argument '${option}' is required` : `Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}is required`;
|
|
170
191
|
return new ArgResolveError(message, option, "required", schema);
|
|
@@ -187,33 +208,12 @@ var ArgResolveError = class extends Error {
|
|
|
187
208
|
function validateRequire(token, option, schema) {
|
|
188
209
|
if (schema.required && schema.type !== "boolean" && !token.value) return createRequireError(option, schema);
|
|
189
210
|
}
|
|
190
|
-
function validateValue(token, option, schema) {
|
|
191
|
-
switch (schema.type) {
|
|
192
|
-
case "number": {
|
|
193
|
-
if (!isNumeric(token.value)) return createTypeError(option, schema);
|
|
194
|
-
break;
|
|
195
|
-
}
|
|
196
|
-
case "string": {
|
|
197
|
-
if (typeof token.value !== "string") return createTypeError(option, schema);
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
case "enum": {
|
|
201
|
-
if (schema.choices && !schema.choices.includes(token.value)) return new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be chosen from '${schema.type}' [${schema.choices.map((c) => JSON.stringify(c)).join(", ")}] values`, option, "type", schema);
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
211
|
function isNumeric(str) {
|
|
207
212
|
return str.trim() !== "" && !isNaN(str);
|
|
208
213
|
}
|
|
209
214
|
function createTypeError(option, schema) {
|
|
210
215
|
return new ArgResolveError(`Optional argument '--${option}' ${schema.short ? `or '-${schema.short}' ` : ""}should be '${schema.type}'`, option, "type", schema);
|
|
211
216
|
}
|
|
212
|
-
function resolveArgumentValue(token, schema) {
|
|
213
|
-
if (token.value) return schema.type === "number" ? +token.value : token.value;
|
|
214
|
-
if (schema.type === "boolean") return schema.negatable && token.name.startsWith("no-") ? false : true;
|
|
215
|
-
return schema.type === "number" ? +(schema.default || "") : schema.default;
|
|
216
|
-
}
|
|
217
217
|
|
|
218
218
|
//#endregion
|
|
219
219
|
export { ArgResolveError, resolveArgs };
|
package/lib/resolver.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import "./parser-Bx112mWZ.js";
|
|
2
|
-
import { ArgResolveError$1 as ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ExtractOptionValue, FilterArgs, ResolveArgValues, ResolveArgs, resolveArgs$1 as resolveArgs } from "./resolver-
|
|
2
|
+
import { ArgResolveError$1 as ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ExtractOptionValue, FilterArgs, ResolveArgValues, ResolveArgs, resolveArgs$1 as resolveArgs } from "./resolver-COGeGqd3.js";
|
|
3
3
|
export { ArgResolveError, ArgResolveErrorType, ArgSchema, ArgValues, Args, ExtractOptionValue, FilterArgs, ResolveArgValues, ResolveArgs, resolveArgs };
|
package/lib/resolver.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "args-tokens",
|
|
3
3
|
"description": "parseArgs tokens compatibility and more high-performance parser",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.19.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "kazuya kawaguchi",
|
|
7
7
|
"email": "kawakazu80@gmail.com"
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@kazupon/eslint-config": "^0.29.0",
|
|
70
70
|
"@kazupon/prettier-config": "^0.1.1",
|
|
71
71
|
"@types/node": "^22.15.21",
|
|
72
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
72
|
+
"@typescript/native-preview": "7.0.0-dev.20250525.1",
|
|
73
73
|
"@vitest/eslint-plugin": "^1.2.0",
|
|
74
74
|
"bumpp": "^10.1.1",
|
|
75
75
|
"deno": "^2.3.3",
|
|
@@ -91,7 +91,8 @@
|
|
|
91
91
|
"tsdown": "^0.12.1",
|
|
92
92
|
"typescript": "^5.8.3",
|
|
93
93
|
"typescript-eslint": "^8.32.1",
|
|
94
|
-
"vitest": "^3.1.4"
|
|
94
|
+
"vitest": "^3.1.4",
|
|
95
|
+
"zod": "^3.25.28"
|
|
95
96
|
},
|
|
96
97
|
"prettier": "@kazupon/prettier-config",
|
|
97
98
|
"lint-staged": {
|
|
@@ -124,7 +125,7 @@
|
|
|
124
125
|
"lint:knip": "knip",
|
|
125
126
|
"lint:prettier": "prettier . --check",
|
|
126
127
|
"release": "bumpp --commit \"release: v%s\" --all --push --tag",
|
|
127
|
-
"test": "vitest run",
|
|
128
|
+
"test": "vitest run --typecheck",
|
|
128
129
|
"typecheck": "pnpm run --parallel --color \"/^typecheck:/\"",
|
|
129
130
|
"typecheck:deno": "deno check src",
|
|
130
131
|
"typecheck:tsc": "tsgo --noEmit"
|