@guanghechen/commander 4.7.9 → 4.8.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/CHANGELOG.md +13 -0
- package/lib/cjs/browser.cjs +48 -10
- package/lib/cjs/node.cjs +48 -10
- package/lib/esm/browser.mjs +48 -10
- package/lib/esm/node.mjs +48 -10
- package/lib/types/browser.d.ts +8 -2
- package/lib/types/node.d.ts +8 -2
- package/package.json +1 -1
- package/lib/schema/preset.config.schema.json +0 -152
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 4.8.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix negative-number preset option serialization, reject empty coerce input, and avoid long-name
|
|
8
|
+
conflicts with no- negation options.
|
|
9
|
+
|
|
10
|
+
## 4.8.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- Expose preset directives in command help output under a dedicated `Preset Directives:` section.
|
|
15
|
+
|
|
3
16
|
## 4.7.9
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/lib/cjs/browser.cjs
CHANGED
|
@@ -489,7 +489,7 @@ function validateOptionConfig(params) {
|
|
|
489
489
|
if (opt.type === 'number' && opt.args === 'optional') {
|
|
490
490
|
throw new CommanderError('ConfigurationError', `number option "--${opt.long}" does not support args: 'optional'`, commandPath);
|
|
491
491
|
}
|
|
492
|
-
if (opt.long
|
|
492
|
+
if (/^no[A-Z]/.test(opt.long)) {
|
|
493
493
|
throw new CommanderError('ConfigurationError', `option long name cannot start with "no": "${opt.long}"`, commandPath);
|
|
494
494
|
}
|
|
495
495
|
if (!/^[a-z][a-zA-Z0-9]*$/.test(opt.long)) {
|
|
@@ -1333,6 +1333,7 @@ class CommandHelpRenderer {
|
|
|
1333
1333
|
usage,
|
|
1334
1334
|
arguments: argumentsLines,
|
|
1335
1335
|
options,
|
|
1336
|
+
presetDirectives: params.presetDirectives ?? [],
|
|
1336
1337
|
commands,
|
|
1337
1338
|
examples,
|
|
1338
1339
|
};
|
|
@@ -1403,6 +1404,14 @@ class CommandHelpRenderer {
|
|
|
1403
1404
|
}
|
|
1404
1405
|
lines.push('');
|
|
1405
1406
|
}
|
|
1407
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1408
|
+
if (presetDirectives.length > 0) {
|
|
1409
|
+
lines.push('Preset Directives:');
|
|
1410
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1411
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth));
|
|
1412
|
+
}
|
|
1413
|
+
lines.push('');
|
|
1414
|
+
}
|
|
1406
1415
|
if (helpData.commands.length > 0) {
|
|
1407
1416
|
lines.push('Commands:');
|
|
1408
1417
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1442,6 +1451,14 @@ class CommandHelpRenderer {
|
|
|
1442
1451
|
}
|
|
1443
1452
|
lines.push('');
|
|
1444
1453
|
}
|
|
1454
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1455
|
+
if (presetDirectives.length > 0) {
|
|
1456
|
+
lines.push(styleText('Preset Directives:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1457
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1458
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth, value => styleText(value, TERMINAL_STYLE.cyan)));
|
|
1459
|
+
}
|
|
1460
|
+
lines.push('');
|
|
1461
|
+
}
|
|
1445
1462
|
if (helpData.commands.length > 0) {
|
|
1446
1463
|
lines.push(styleText('Commands:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1447
1464
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1464,6 +1481,7 @@ class CommandHelpRenderer {
|
|
|
1464
1481
|
const labels = [
|
|
1465
1482
|
...helpData.arguments.map(line => line.sig),
|
|
1466
1483
|
...helpData.options.map(line => line.sig),
|
|
1484
|
+
...(helpData.presetDirectives ?? []).map(line => line.sig),
|
|
1467
1485
|
...helpData.commands.map(line => line.name),
|
|
1468
1486
|
];
|
|
1469
1487
|
if (labels.length === 0) {
|
|
@@ -2130,13 +2148,23 @@ class CommandPresetProfileParser {
|
|
|
2130
2148
|
continue;
|
|
2131
2149
|
}
|
|
2132
2150
|
if (typeof rawValue === 'number') {
|
|
2133
|
-
|
|
2151
|
+
const value = String(rawValue);
|
|
2152
|
+
if (value.startsWith('-'))
|
|
2153
|
+
argv.push(`${positiveFlag}=${value}`);
|
|
2154
|
+
else
|
|
2155
|
+
argv.push(positiveFlag, value);
|
|
2134
2156
|
continue;
|
|
2135
2157
|
}
|
|
2136
2158
|
if (rawValue.length === 0) {
|
|
2137
2159
|
continue;
|
|
2138
2160
|
}
|
|
2139
|
-
|
|
2161
|
+
if (rawValue.some(value => typeof value === 'number' && String(value).startsWith('-'))) {
|
|
2162
|
+
for (const value of rawValue)
|
|
2163
|
+
argv.push(`${positiveFlag}=${String(value)}`);
|
|
2164
|
+
}
|
|
2165
|
+
else {
|
|
2166
|
+
argv.push(positiveFlag, ...rawValue.map(value => String(value)));
|
|
2167
|
+
}
|
|
2140
2168
|
}
|
|
2141
2169
|
return argv;
|
|
2142
2170
|
}
|
|
@@ -3386,6 +3414,16 @@ class Command {
|
|
|
3386
3414
|
commandPath: this.#getCommandPath(),
|
|
3387
3415
|
arguments: this.#arguments,
|
|
3388
3416
|
options: this.#resolveOptionPolicy().mergedOptions,
|
|
3417
|
+
presetDirectives: [
|
|
3418
|
+
{
|
|
3419
|
+
sig: `${PRESET_FILE_FLAG} <value>`,
|
|
3420
|
+
desc: 'Load preset manifest file',
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
sig: `${PRESET_PROFILE_FLAG} <value>`,
|
|
3424
|
+
desc: 'Select preset profile: <profile> or <profile>:<variant>; requires --preset-file or command preset.file',
|
|
3425
|
+
},
|
|
3426
|
+
],
|
|
3389
3427
|
supportsBuiltinVersion: this.#supportsBuiltinVersion(),
|
|
3390
3428
|
subcommands,
|
|
3391
3429
|
examples: this.#examples,
|
|
@@ -3657,10 +3695,10 @@ function isDomain(rawValue) {
|
|
|
3657
3695
|
|
|
3658
3696
|
class Coerce {
|
|
3659
3697
|
constructor() { }
|
|
3660
|
-
static
|
|
3698
|
+
static createNumberCoerce(name, expectedType, validator, errorMessage) {
|
|
3661
3699
|
return (rawValue) => {
|
|
3662
3700
|
const value = Number(rawValue);
|
|
3663
|
-
if (!validator(value)) {
|
|
3701
|
+
if (rawValue.trim() === '' || !validator(value)) {
|
|
3664
3702
|
throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
|
|
3665
3703
|
}
|
|
3666
3704
|
return value;
|
|
@@ -3691,7 +3729,7 @@ class Coerce {
|
|
|
3691
3729
|
};
|
|
3692
3730
|
}
|
|
3693
3731
|
static integer(name, errorMessage) {
|
|
3694
|
-
return this.
|
|
3732
|
+
return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
|
|
3695
3733
|
}
|
|
3696
3734
|
static ip(name, errorMessage) {
|
|
3697
3735
|
return (rawValue) => {
|
|
@@ -3702,16 +3740,16 @@ class Coerce {
|
|
|
3702
3740
|
};
|
|
3703
3741
|
}
|
|
3704
3742
|
static number(name, errorMessage) {
|
|
3705
|
-
return this.
|
|
3743
|
+
return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
|
|
3706
3744
|
}
|
|
3707
3745
|
static port(name, errorMessage) {
|
|
3708
|
-
return this.
|
|
3746
|
+
return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
|
|
3709
3747
|
}
|
|
3710
3748
|
static positiveInteger(name, errorMessage) {
|
|
3711
|
-
return this.
|
|
3749
|
+
return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
|
|
3712
3750
|
}
|
|
3713
3751
|
static positiveNumber(name, errorMessage) {
|
|
3714
|
-
return this.
|
|
3752
|
+
return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
|
|
3715
3753
|
}
|
|
3716
3754
|
}
|
|
3717
3755
|
|
package/lib/cjs/node.cjs
CHANGED
|
@@ -502,7 +502,7 @@ function validateOptionConfig(params) {
|
|
|
502
502
|
if (opt.type === 'number' && opt.args === 'optional') {
|
|
503
503
|
throw new CommanderError('ConfigurationError', `number option "--${opt.long}" does not support args: 'optional'`, commandPath);
|
|
504
504
|
}
|
|
505
|
-
if (opt.long
|
|
505
|
+
if (/^no[A-Z]/.test(opt.long)) {
|
|
506
506
|
throw new CommanderError('ConfigurationError', `option long name cannot start with "no": "${opt.long}"`, commandPath);
|
|
507
507
|
}
|
|
508
508
|
if (!/^[a-z][a-zA-Z0-9]*$/.test(opt.long)) {
|
|
@@ -1346,6 +1346,7 @@ class CommandHelpRenderer {
|
|
|
1346
1346
|
usage,
|
|
1347
1347
|
arguments: argumentsLines,
|
|
1348
1348
|
options,
|
|
1349
|
+
presetDirectives: params.presetDirectives ?? [],
|
|
1349
1350
|
commands,
|
|
1350
1351
|
examples,
|
|
1351
1352
|
};
|
|
@@ -1416,6 +1417,14 @@ class CommandHelpRenderer {
|
|
|
1416
1417
|
}
|
|
1417
1418
|
lines.push('');
|
|
1418
1419
|
}
|
|
1420
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1421
|
+
if (presetDirectives.length > 0) {
|
|
1422
|
+
lines.push('Preset Directives:');
|
|
1423
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1424
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth));
|
|
1425
|
+
}
|
|
1426
|
+
lines.push('');
|
|
1427
|
+
}
|
|
1419
1428
|
if (helpData.commands.length > 0) {
|
|
1420
1429
|
lines.push('Commands:');
|
|
1421
1430
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1455,6 +1464,14 @@ class CommandHelpRenderer {
|
|
|
1455
1464
|
}
|
|
1456
1465
|
lines.push('');
|
|
1457
1466
|
}
|
|
1467
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1468
|
+
if (presetDirectives.length > 0) {
|
|
1469
|
+
lines.push(styleText('Preset Directives:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1470
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1471
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth, value => styleText(value, TERMINAL_STYLE.cyan)));
|
|
1472
|
+
}
|
|
1473
|
+
lines.push('');
|
|
1474
|
+
}
|
|
1458
1475
|
if (helpData.commands.length > 0) {
|
|
1459
1476
|
lines.push(styleText('Commands:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1460
1477
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1477,6 +1494,7 @@ class CommandHelpRenderer {
|
|
|
1477
1494
|
const labels = [
|
|
1478
1495
|
...helpData.arguments.map(line => line.sig),
|
|
1479
1496
|
...helpData.options.map(line => line.sig),
|
|
1497
|
+
...(helpData.presetDirectives ?? []).map(line => line.sig),
|
|
1480
1498
|
...helpData.commands.map(line => line.name),
|
|
1481
1499
|
];
|
|
1482
1500
|
if (labels.length === 0) {
|
|
@@ -2143,13 +2161,23 @@ class CommandPresetProfileParser {
|
|
|
2143
2161
|
continue;
|
|
2144
2162
|
}
|
|
2145
2163
|
if (typeof rawValue === 'number') {
|
|
2146
|
-
|
|
2164
|
+
const value = String(rawValue);
|
|
2165
|
+
if (value.startsWith('-'))
|
|
2166
|
+
argv.push(`${positiveFlag}=${value}`);
|
|
2167
|
+
else
|
|
2168
|
+
argv.push(positiveFlag, value);
|
|
2147
2169
|
continue;
|
|
2148
2170
|
}
|
|
2149
2171
|
if (rawValue.length === 0) {
|
|
2150
2172
|
continue;
|
|
2151
2173
|
}
|
|
2152
|
-
|
|
2174
|
+
if (rawValue.some(value => typeof value === 'number' && String(value).startsWith('-'))) {
|
|
2175
|
+
for (const value of rawValue)
|
|
2176
|
+
argv.push(`${positiveFlag}=${String(value)}`);
|
|
2177
|
+
}
|
|
2178
|
+
else {
|
|
2179
|
+
argv.push(positiveFlag, ...rawValue.map(value => String(value)));
|
|
2180
|
+
}
|
|
2153
2181
|
}
|
|
2154
2182
|
return argv;
|
|
2155
2183
|
}
|
|
@@ -3399,6 +3427,16 @@ class Command {
|
|
|
3399
3427
|
commandPath: this.#getCommandPath(),
|
|
3400
3428
|
arguments: this.#arguments,
|
|
3401
3429
|
options: this.#resolveOptionPolicy().mergedOptions,
|
|
3430
|
+
presetDirectives: [
|
|
3431
|
+
{
|
|
3432
|
+
sig: `${PRESET_FILE_FLAG} <value>`,
|
|
3433
|
+
desc: 'Load preset manifest file',
|
|
3434
|
+
},
|
|
3435
|
+
{
|
|
3436
|
+
sig: `${PRESET_PROFILE_FLAG} <value>`,
|
|
3437
|
+
desc: 'Select preset profile: <profile> or <profile>:<variant>; requires --preset-file or command preset.file',
|
|
3438
|
+
},
|
|
3439
|
+
],
|
|
3402
3440
|
supportsBuiltinVersion: this.#supportsBuiltinVersion(),
|
|
3403
3441
|
subcommands,
|
|
3404
3442
|
examples: this.#examples,
|
|
@@ -3670,10 +3708,10 @@ function isDomain(rawValue) {
|
|
|
3670
3708
|
|
|
3671
3709
|
class Coerce {
|
|
3672
3710
|
constructor() { }
|
|
3673
|
-
static
|
|
3711
|
+
static createNumberCoerce(name, expectedType, validator, errorMessage) {
|
|
3674
3712
|
return (rawValue) => {
|
|
3675
3713
|
const value = Number(rawValue);
|
|
3676
|
-
if (!validator(value)) {
|
|
3714
|
+
if (rawValue.trim() === '' || !validator(value)) {
|
|
3677
3715
|
throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
|
|
3678
3716
|
}
|
|
3679
3717
|
return value;
|
|
@@ -3704,7 +3742,7 @@ class Coerce {
|
|
|
3704
3742
|
};
|
|
3705
3743
|
}
|
|
3706
3744
|
static integer(name, errorMessage) {
|
|
3707
|
-
return this.
|
|
3745
|
+
return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
|
|
3708
3746
|
}
|
|
3709
3747
|
static ip(name, errorMessage) {
|
|
3710
3748
|
return (rawValue) => {
|
|
@@ -3715,16 +3753,16 @@ class Coerce {
|
|
|
3715
3753
|
};
|
|
3716
3754
|
}
|
|
3717
3755
|
static number(name, errorMessage) {
|
|
3718
|
-
return this.
|
|
3756
|
+
return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
|
|
3719
3757
|
}
|
|
3720
3758
|
static port(name, errorMessage) {
|
|
3721
|
-
return this.
|
|
3759
|
+
return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
|
|
3722
3760
|
}
|
|
3723
3761
|
static positiveInteger(name, errorMessage) {
|
|
3724
|
-
return this.
|
|
3762
|
+
return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
|
|
3725
3763
|
}
|
|
3726
3764
|
static positiveNumber(name, errorMessage) {
|
|
3727
|
-
return this.
|
|
3765
|
+
return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
|
|
3728
3766
|
}
|
|
3729
3767
|
}
|
|
3730
3768
|
|
package/lib/esm/browser.mjs
CHANGED
|
@@ -487,7 +487,7 @@ function validateOptionConfig(params) {
|
|
|
487
487
|
if (opt.type === 'number' && opt.args === 'optional') {
|
|
488
488
|
throw new CommanderError('ConfigurationError', `number option "--${opt.long}" does not support args: 'optional'`, commandPath);
|
|
489
489
|
}
|
|
490
|
-
if (opt.long
|
|
490
|
+
if (/^no[A-Z]/.test(opt.long)) {
|
|
491
491
|
throw new CommanderError('ConfigurationError', `option long name cannot start with "no": "${opt.long}"`, commandPath);
|
|
492
492
|
}
|
|
493
493
|
if (!/^[a-z][a-zA-Z0-9]*$/.test(opt.long)) {
|
|
@@ -1331,6 +1331,7 @@ class CommandHelpRenderer {
|
|
|
1331
1331
|
usage,
|
|
1332
1332
|
arguments: argumentsLines,
|
|
1333
1333
|
options,
|
|
1334
|
+
presetDirectives: params.presetDirectives ?? [],
|
|
1334
1335
|
commands,
|
|
1335
1336
|
examples,
|
|
1336
1337
|
};
|
|
@@ -1401,6 +1402,14 @@ class CommandHelpRenderer {
|
|
|
1401
1402
|
}
|
|
1402
1403
|
lines.push('');
|
|
1403
1404
|
}
|
|
1405
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1406
|
+
if (presetDirectives.length > 0) {
|
|
1407
|
+
lines.push('Preset Directives:');
|
|
1408
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1409
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth));
|
|
1410
|
+
}
|
|
1411
|
+
lines.push('');
|
|
1412
|
+
}
|
|
1404
1413
|
if (helpData.commands.length > 0) {
|
|
1405
1414
|
lines.push('Commands:');
|
|
1406
1415
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1440,6 +1449,14 @@ class CommandHelpRenderer {
|
|
|
1440
1449
|
}
|
|
1441
1450
|
lines.push('');
|
|
1442
1451
|
}
|
|
1452
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1453
|
+
if (presetDirectives.length > 0) {
|
|
1454
|
+
lines.push(styleText('Preset Directives:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1455
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1456
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth, value => styleText(value, TERMINAL_STYLE.cyan)));
|
|
1457
|
+
}
|
|
1458
|
+
lines.push('');
|
|
1459
|
+
}
|
|
1443
1460
|
if (helpData.commands.length > 0) {
|
|
1444
1461
|
lines.push(styleText('Commands:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1445
1462
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1462,6 +1479,7 @@ class CommandHelpRenderer {
|
|
|
1462
1479
|
const labels = [
|
|
1463
1480
|
...helpData.arguments.map(line => line.sig),
|
|
1464
1481
|
...helpData.options.map(line => line.sig),
|
|
1482
|
+
...(helpData.presetDirectives ?? []).map(line => line.sig),
|
|
1465
1483
|
...helpData.commands.map(line => line.name),
|
|
1466
1484
|
];
|
|
1467
1485
|
if (labels.length === 0) {
|
|
@@ -2128,13 +2146,23 @@ class CommandPresetProfileParser {
|
|
|
2128
2146
|
continue;
|
|
2129
2147
|
}
|
|
2130
2148
|
if (typeof rawValue === 'number') {
|
|
2131
|
-
|
|
2149
|
+
const value = String(rawValue);
|
|
2150
|
+
if (value.startsWith('-'))
|
|
2151
|
+
argv.push(`${positiveFlag}=${value}`);
|
|
2152
|
+
else
|
|
2153
|
+
argv.push(positiveFlag, value);
|
|
2132
2154
|
continue;
|
|
2133
2155
|
}
|
|
2134
2156
|
if (rawValue.length === 0) {
|
|
2135
2157
|
continue;
|
|
2136
2158
|
}
|
|
2137
|
-
|
|
2159
|
+
if (rawValue.some(value => typeof value === 'number' && String(value).startsWith('-'))) {
|
|
2160
|
+
for (const value of rawValue)
|
|
2161
|
+
argv.push(`${positiveFlag}=${String(value)}`);
|
|
2162
|
+
}
|
|
2163
|
+
else {
|
|
2164
|
+
argv.push(positiveFlag, ...rawValue.map(value => String(value)));
|
|
2165
|
+
}
|
|
2138
2166
|
}
|
|
2139
2167
|
return argv;
|
|
2140
2168
|
}
|
|
@@ -3384,6 +3412,16 @@ class Command {
|
|
|
3384
3412
|
commandPath: this.#getCommandPath(),
|
|
3385
3413
|
arguments: this.#arguments,
|
|
3386
3414
|
options: this.#resolveOptionPolicy().mergedOptions,
|
|
3415
|
+
presetDirectives: [
|
|
3416
|
+
{
|
|
3417
|
+
sig: `${PRESET_FILE_FLAG} <value>`,
|
|
3418
|
+
desc: 'Load preset manifest file',
|
|
3419
|
+
},
|
|
3420
|
+
{
|
|
3421
|
+
sig: `${PRESET_PROFILE_FLAG} <value>`,
|
|
3422
|
+
desc: 'Select preset profile: <profile> or <profile>:<variant>; requires --preset-file or command preset.file',
|
|
3423
|
+
},
|
|
3424
|
+
],
|
|
3387
3425
|
supportsBuiltinVersion: this.#supportsBuiltinVersion(),
|
|
3388
3426
|
subcommands,
|
|
3389
3427
|
examples: this.#examples,
|
|
@@ -3655,10 +3693,10 @@ function isDomain(rawValue) {
|
|
|
3655
3693
|
|
|
3656
3694
|
class Coerce {
|
|
3657
3695
|
constructor() { }
|
|
3658
|
-
static
|
|
3696
|
+
static createNumberCoerce(name, expectedType, validator, errorMessage) {
|
|
3659
3697
|
return (rawValue) => {
|
|
3660
3698
|
const value = Number(rawValue);
|
|
3661
|
-
if (!validator(value)) {
|
|
3699
|
+
if (rawValue.trim() === '' || !validator(value)) {
|
|
3662
3700
|
throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
|
|
3663
3701
|
}
|
|
3664
3702
|
return value;
|
|
@@ -3689,7 +3727,7 @@ class Coerce {
|
|
|
3689
3727
|
};
|
|
3690
3728
|
}
|
|
3691
3729
|
static integer(name, errorMessage) {
|
|
3692
|
-
return this.
|
|
3730
|
+
return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
|
|
3693
3731
|
}
|
|
3694
3732
|
static ip(name, errorMessage) {
|
|
3695
3733
|
return (rawValue) => {
|
|
@@ -3700,16 +3738,16 @@ class Coerce {
|
|
|
3700
3738
|
};
|
|
3701
3739
|
}
|
|
3702
3740
|
static number(name, errorMessage) {
|
|
3703
|
-
return this.
|
|
3741
|
+
return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
|
|
3704
3742
|
}
|
|
3705
3743
|
static port(name, errorMessage) {
|
|
3706
|
-
return this.
|
|
3744
|
+
return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
|
|
3707
3745
|
}
|
|
3708
3746
|
static positiveInteger(name, errorMessage) {
|
|
3709
|
-
return this.
|
|
3747
|
+
return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
|
|
3710
3748
|
}
|
|
3711
3749
|
static positiveNumber(name, errorMessage) {
|
|
3712
|
-
return this.
|
|
3750
|
+
return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
|
|
3713
3751
|
}
|
|
3714
3752
|
}
|
|
3715
3753
|
|
package/lib/esm/node.mjs
CHANGED
|
@@ -500,7 +500,7 @@ function validateOptionConfig(params) {
|
|
|
500
500
|
if (opt.type === 'number' && opt.args === 'optional') {
|
|
501
501
|
throw new CommanderError('ConfigurationError', `number option "--${opt.long}" does not support args: 'optional'`, commandPath);
|
|
502
502
|
}
|
|
503
|
-
if (opt.long
|
|
503
|
+
if (/^no[A-Z]/.test(opt.long)) {
|
|
504
504
|
throw new CommanderError('ConfigurationError', `option long name cannot start with "no": "${opt.long}"`, commandPath);
|
|
505
505
|
}
|
|
506
506
|
if (!/^[a-z][a-zA-Z0-9]*$/.test(opt.long)) {
|
|
@@ -1344,6 +1344,7 @@ class CommandHelpRenderer {
|
|
|
1344
1344
|
usage,
|
|
1345
1345
|
arguments: argumentsLines,
|
|
1346
1346
|
options,
|
|
1347
|
+
presetDirectives: params.presetDirectives ?? [],
|
|
1347
1348
|
commands,
|
|
1348
1349
|
examples,
|
|
1349
1350
|
};
|
|
@@ -1414,6 +1415,14 @@ class CommandHelpRenderer {
|
|
|
1414
1415
|
}
|
|
1415
1416
|
lines.push('');
|
|
1416
1417
|
}
|
|
1418
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1419
|
+
if (presetDirectives.length > 0) {
|
|
1420
|
+
lines.push('Preset Directives:');
|
|
1421
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1422
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth));
|
|
1423
|
+
}
|
|
1424
|
+
lines.push('');
|
|
1425
|
+
}
|
|
1417
1426
|
if (helpData.commands.length > 0) {
|
|
1418
1427
|
lines.push('Commands:');
|
|
1419
1428
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1453,6 +1462,14 @@ class CommandHelpRenderer {
|
|
|
1453
1462
|
}
|
|
1454
1463
|
lines.push('');
|
|
1455
1464
|
}
|
|
1465
|
+
const presetDirectives = helpData.presetDirectives ?? [];
|
|
1466
|
+
if (presetDirectives.length > 0) {
|
|
1467
|
+
lines.push(styleText('Preset Directives:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1468
|
+
for (const { sig, desc } of presetDirectives) {
|
|
1469
|
+
lines.push(this.#renderAlignedHelpLine(sig, desc, labelWidth, value => styleText(value, TERMINAL_STYLE.cyan)));
|
|
1470
|
+
}
|
|
1471
|
+
lines.push('');
|
|
1472
|
+
}
|
|
1456
1473
|
if (helpData.commands.length > 0) {
|
|
1457
1474
|
lines.push(styleText('Commands:', TERMINAL_STYLE.bold, TERMINAL_STYLE.underline));
|
|
1458
1475
|
for (const { name, desc } of helpData.commands) {
|
|
@@ -1475,6 +1492,7 @@ class CommandHelpRenderer {
|
|
|
1475
1492
|
const labels = [
|
|
1476
1493
|
...helpData.arguments.map(line => line.sig),
|
|
1477
1494
|
...helpData.options.map(line => line.sig),
|
|
1495
|
+
...(helpData.presetDirectives ?? []).map(line => line.sig),
|
|
1478
1496
|
...helpData.commands.map(line => line.name),
|
|
1479
1497
|
];
|
|
1480
1498
|
if (labels.length === 0) {
|
|
@@ -2141,13 +2159,23 @@ class CommandPresetProfileParser {
|
|
|
2141
2159
|
continue;
|
|
2142
2160
|
}
|
|
2143
2161
|
if (typeof rawValue === 'number') {
|
|
2144
|
-
|
|
2162
|
+
const value = String(rawValue);
|
|
2163
|
+
if (value.startsWith('-'))
|
|
2164
|
+
argv.push(`${positiveFlag}=${value}`);
|
|
2165
|
+
else
|
|
2166
|
+
argv.push(positiveFlag, value);
|
|
2145
2167
|
continue;
|
|
2146
2168
|
}
|
|
2147
2169
|
if (rawValue.length === 0) {
|
|
2148
2170
|
continue;
|
|
2149
2171
|
}
|
|
2150
|
-
|
|
2172
|
+
if (rawValue.some(value => typeof value === 'number' && String(value).startsWith('-'))) {
|
|
2173
|
+
for (const value of rawValue)
|
|
2174
|
+
argv.push(`${positiveFlag}=${String(value)}`);
|
|
2175
|
+
}
|
|
2176
|
+
else {
|
|
2177
|
+
argv.push(positiveFlag, ...rawValue.map(value => String(value)));
|
|
2178
|
+
}
|
|
2151
2179
|
}
|
|
2152
2180
|
return argv;
|
|
2153
2181
|
}
|
|
@@ -3397,6 +3425,16 @@ class Command {
|
|
|
3397
3425
|
commandPath: this.#getCommandPath(),
|
|
3398
3426
|
arguments: this.#arguments,
|
|
3399
3427
|
options: this.#resolveOptionPolicy().mergedOptions,
|
|
3428
|
+
presetDirectives: [
|
|
3429
|
+
{
|
|
3430
|
+
sig: `${PRESET_FILE_FLAG} <value>`,
|
|
3431
|
+
desc: 'Load preset manifest file',
|
|
3432
|
+
},
|
|
3433
|
+
{
|
|
3434
|
+
sig: `${PRESET_PROFILE_FLAG} <value>`,
|
|
3435
|
+
desc: 'Select preset profile: <profile> or <profile>:<variant>; requires --preset-file or command preset.file',
|
|
3436
|
+
},
|
|
3437
|
+
],
|
|
3400
3438
|
supportsBuiltinVersion: this.#supportsBuiltinVersion(),
|
|
3401
3439
|
subcommands,
|
|
3402
3440
|
examples: this.#examples,
|
|
@@ -3668,10 +3706,10 @@ function isDomain(rawValue) {
|
|
|
3668
3706
|
|
|
3669
3707
|
class Coerce {
|
|
3670
3708
|
constructor() { }
|
|
3671
|
-
static
|
|
3709
|
+
static createNumberCoerce(name, expectedType, validator, errorMessage) {
|
|
3672
3710
|
return (rawValue) => {
|
|
3673
3711
|
const value = Number(rawValue);
|
|
3674
|
-
if (!validator(value)) {
|
|
3712
|
+
if (rawValue.trim() === '' || !validator(value)) {
|
|
3675
3713
|
throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
|
|
3676
3714
|
}
|
|
3677
3715
|
return value;
|
|
@@ -3702,7 +3740,7 @@ class Coerce {
|
|
|
3702
3740
|
};
|
|
3703
3741
|
}
|
|
3704
3742
|
static integer(name, errorMessage) {
|
|
3705
|
-
return this.
|
|
3743
|
+
return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
|
|
3706
3744
|
}
|
|
3707
3745
|
static ip(name, errorMessage) {
|
|
3708
3746
|
return (rawValue) => {
|
|
@@ -3713,16 +3751,16 @@ class Coerce {
|
|
|
3713
3751
|
};
|
|
3714
3752
|
}
|
|
3715
3753
|
static number(name, errorMessage) {
|
|
3716
|
-
return this.
|
|
3754
|
+
return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
|
|
3717
3755
|
}
|
|
3718
3756
|
static port(name, errorMessage) {
|
|
3719
|
-
return this.
|
|
3757
|
+
return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
|
|
3720
3758
|
}
|
|
3721
3759
|
static positiveInteger(name, errorMessage) {
|
|
3722
|
-
return this.
|
|
3760
|
+
return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
|
|
3723
3761
|
}
|
|
3724
3762
|
static positiveNumber(name, errorMessage) {
|
|
3725
|
-
return this.
|
|
3763
|
+
return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
|
|
3726
3764
|
}
|
|
3727
3765
|
}
|
|
3728
3766
|
|
package/lib/types/browser.d.ts
CHANGED
|
@@ -391,6 +391,11 @@ interface IHelpOptionLine {
|
|
|
391
391
|
sig: string;
|
|
392
392
|
desc: string;
|
|
393
393
|
}
|
|
394
|
+
/** Help preset directive line (internal) */
|
|
395
|
+
interface IHelpPresetDirectiveLine {
|
|
396
|
+
sig: string;
|
|
397
|
+
desc: string;
|
|
398
|
+
}
|
|
394
399
|
/** Help argument line (internal) */
|
|
395
400
|
interface IHelpArgumentLine {
|
|
396
401
|
sig: string;
|
|
@@ -413,6 +418,7 @@ interface IHelpData {
|
|
|
413
418
|
usage: string;
|
|
414
419
|
arguments: IHelpArgumentLine[];
|
|
415
420
|
options: IHelpOptionLine[];
|
|
421
|
+
presetDirectives?: IHelpPresetDirectiveLine[];
|
|
416
422
|
commands: IHelpCommandLine[];
|
|
417
423
|
examples: IHelpExampleLine[];
|
|
418
424
|
}
|
|
@@ -586,7 +592,7 @@ declare class Command implements ICommand {
|
|
|
586
592
|
*/
|
|
587
593
|
declare class Coerce {
|
|
588
594
|
private constructor();
|
|
589
|
-
private static
|
|
595
|
+
private static createNumberCoerce;
|
|
590
596
|
static choice<TValue extends string>(name: string, values: ReadonlyArray<TValue>, errorMessage?: string): (rawValue: string) => TValue;
|
|
591
597
|
static domain(name: string, errorMessage?: string): (rawValue: string) => string;
|
|
592
598
|
static host(name: string, errorMessage?: string): (rawValue: string) => string;
|
|
@@ -674,4 +680,4 @@ declare function getDefaultCommandRuntime(): ICommandRuntime;
|
|
|
674
680
|
declare function setDefaultCommandRuntime(runtime: ICommandRuntime): void;
|
|
675
681
|
|
|
676
682
|
export { Coerce, Command, CommanderError, createBrowserCommandRuntime, getDefaultCommandRuntime, isDomain, isIp, isIpv4, isIpv6, logColorfulOption, logDateOption, setDefaultCommandRuntime, silentOption };
|
|
677
|
-
export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandArgvSegment, ICommandBuiltinConfig, ICommandBuiltinOptionConfig, ICommandBuiltinOptionResolved, ICommandBuiltinParsedOptions, ICommandBuiltinResolved, ICommandConfig, ICommandContext, ICommandControlScanResult, ICommandControls, ICommandErrorIssue, ICommandErrorIssueCode, ICommandErrorMeta, ICommandExample, ICommandHintIssue, ICommandHintIssueCode, ICommandInputSources, ICommandIssue, ICommandIssueBase, ICommandIssueCode, ICommandIssueKind, ICommandIssueReason, ICommandIssueScope, ICommandIssueSourceAttribution, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandPresetConfig, ICommandPresetIssueMeta, ICommandPresetProfileDefaults, ICommandPresetProfileItem, ICommandPresetProfileManifest, ICommandPresetProfileOptionValue, ICommandPresetProfileVariantItem, ICommandPresetResult, ICommandPresetSourceMeta, ICommandPresetSourceState, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandRuntime, ICommandRuntimeStats, ICommandShiftResult, ICommandStage, ICommandToken, ICommandTokenSource, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionArgumentMeta, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType, IHelpArgumentLine, IHelpCommandLine, IHelpData, IHelpExampleLine, IHelpOptionLine, ISubcommandEntry };
|
|
683
|
+
export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandArgvSegment, ICommandBuiltinConfig, ICommandBuiltinOptionConfig, ICommandBuiltinOptionResolved, ICommandBuiltinParsedOptions, ICommandBuiltinResolved, ICommandConfig, ICommandContext, ICommandControlScanResult, ICommandControls, ICommandErrorIssue, ICommandErrorIssueCode, ICommandErrorMeta, ICommandExample, ICommandHintIssue, ICommandHintIssueCode, ICommandInputSources, ICommandIssue, ICommandIssueBase, ICommandIssueCode, ICommandIssueKind, ICommandIssueReason, ICommandIssueScope, ICommandIssueSourceAttribution, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandPresetConfig, ICommandPresetIssueMeta, ICommandPresetProfileDefaults, ICommandPresetProfileItem, ICommandPresetProfileManifest, ICommandPresetProfileOptionValue, ICommandPresetProfileVariantItem, ICommandPresetResult, ICommandPresetSourceMeta, ICommandPresetSourceState, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandRuntime, ICommandRuntimeStats, ICommandShiftResult, ICommandStage, ICommandToken, ICommandTokenSource, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionArgumentMeta, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType, IHelpArgumentLine, IHelpCommandLine, IHelpData, IHelpExampleLine, IHelpOptionLine, IHelpPresetDirectiveLine, ISubcommandEntry };
|
package/lib/types/node.d.ts
CHANGED
|
@@ -391,6 +391,11 @@ interface IHelpOptionLine {
|
|
|
391
391
|
sig: string;
|
|
392
392
|
desc: string;
|
|
393
393
|
}
|
|
394
|
+
/** Help preset directive line (internal) */
|
|
395
|
+
interface IHelpPresetDirectiveLine {
|
|
396
|
+
sig: string;
|
|
397
|
+
desc: string;
|
|
398
|
+
}
|
|
394
399
|
/** Help argument line (internal) */
|
|
395
400
|
interface IHelpArgumentLine {
|
|
396
401
|
sig: string;
|
|
@@ -413,6 +418,7 @@ interface IHelpData {
|
|
|
413
418
|
usage: string;
|
|
414
419
|
arguments: IHelpArgumentLine[];
|
|
415
420
|
options: IHelpOptionLine[];
|
|
421
|
+
presetDirectives?: IHelpPresetDirectiveLine[];
|
|
416
422
|
commands: IHelpCommandLine[];
|
|
417
423
|
examples: IHelpExampleLine[];
|
|
418
424
|
}
|
|
@@ -594,7 +600,7 @@ declare class Command implements ICommand {
|
|
|
594
600
|
*/
|
|
595
601
|
declare class Coerce {
|
|
596
602
|
private constructor();
|
|
597
|
-
private static
|
|
603
|
+
private static createNumberCoerce;
|
|
598
604
|
static choice<TValue extends string>(name: string, values: ReadonlyArray<TValue>, errorMessage?: string): (rawValue: string) => TValue;
|
|
599
605
|
static domain(name: string, errorMessage?: string): (rawValue: string) => string;
|
|
600
606
|
static host(name: string, errorMessage?: string): (rawValue: string) => string;
|
|
@@ -727,4 +733,4 @@ declare class PwshCompletion {
|
|
|
727
733
|
}
|
|
728
734
|
|
|
729
735
|
export { BashCompletion, Coerce, Command, CommanderError, CompletionCommand, FishCompletion, PwshCompletion, createBrowserCommandRuntime, createNodeCommandRuntime, getDefaultCommandRuntime, isDomain, isIp, isIpv4, isIpv6, logColorfulOption, logDateOption, setDefaultCommandRuntime, silentOption };
|
|
730
|
-
export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandArgvSegment, ICommandBuiltinConfig, ICommandBuiltinOptionConfig, ICommandBuiltinOptionResolved, ICommandBuiltinParsedOptions, ICommandBuiltinResolved, ICommandConfig, ICommandContext, ICommandControlScanResult, ICommandControls, ICommandErrorIssue, ICommandErrorIssueCode, ICommandErrorMeta, ICommandExample, ICommandHintIssue, ICommandHintIssueCode, ICommandInputSources, ICommandIssue, ICommandIssueBase, ICommandIssueCode, ICommandIssueKind, ICommandIssueReason, ICommandIssueScope, ICommandIssueSourceAttribution, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandPresetConfig, ICommandPresetIssueMeta, ICommandPresetProfileDefaults, ICommandPresetProfileItem, ICommandPresetProfileManifest, ICommandPresetProfileOptionValue, ICommandPresetProfileVariantItem, ICommandPresetResult, ICommandPresetSourceMeta, ICommandPresetSourceState, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandRuntime, ICommandRuntimeStats, ICommandShiftResult, ICommandStage, ICommandToken, ICommandTokenSource, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionArgumentMeta, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType, IHelpArgumentLine, IHelpCommandLine, IHelpData, IHelpExampleLine, IHelpOptionLine, ISubcommandEntry };
|
|
736
|
+
export type { ICommand, ICommandAction, ICommandActionParams, ICommandArgumentConfig, ICommandArgumentKind, ICommandArgumentType, ICommandArgvSegment, ICommandBuiltinConfig, ICommandBuiltinOptionConfig, ICommandBuiltinOptionResolved, ICommandBuiltinParsedOptions, ICommandBuiltinResolved, ICommandConfig, ICommandContext, ICommandControlScanResult, ICommandControls, ICommandErrorIssue, ICommandErrorIssueCode, ICommandErrorMeta, ICommandExample, ICommandHintIssue, ICommandHintIssueCode, ICommandInputSources, ICommandIssue, ICommandIssueBase, ICommandIssueCode, ICommandIssueKind, ICommandIssueReason, ICommandIssueScope, ICommandIssueSourceAttribution, ICommandOptionArgs, ICommandOptionConfig, ICommandOptionType, ICommandParseResult, ICommandParsedArgs, ICommandParsedOpts, ICommandPresetConfig, ICommandPresetIssueMeta, ICommandPresetProfileDefaults, ICommandPresetProfileItem, ICommandPresetProfileManifest, ICommandPresetProfileOptionValue, ICommandPresetProfileVariantItem, ICommandPresetResult, ICommandPresetSourceMeta, ICommandPresetSourceState, ICommandResolveResult, ICommandRouteResult, ICommandRunParams, ICommandRuntime, ICommandRuntimeStats, ICommandShiftResult, ICommandStage, ICommandToken, ICommandTokenSource, ICommandTokenType, ICommandTokenizeResult, ICommanderErrorKind, ICompletionArgumentMeta, ICompletionCommandConfig, ICompletionMeta, ICompletionOptionMeta, ICompletionPaths, ICompletionShellType, IHelpArgumentLine, IHelpCommandLine, IHelpData, IHelpExampleLine, IHelpOptionLine, IHelpPresetDirectiveLine, ISubcommandEntry };
|
package/package.json
CHANGED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://guanghechen.github.io/sora/schemas/commander/preset.config.schema.json",
|
|
4
|
-
"title": "Commander Preset Config",
|
|
5
|
-
"description": "Preset profile manifest for @guanghechen/commander --preset-file.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"required": ["version", "profiles"],
|
|
9
|
-
"examples": [
|
|
10
|
-
{
|
|
11
|
-
"version": 1,
|
|
12
|
-
"defaults": { "profile": "dev:local" },
|
|
13
|
-
"profiles": {
|
|
14
|
-
"dev": {
|
|
15
|
-
"envFile": "dev.env",
|
|
16
|
-
"envs": { "NODE_ENV": "development" },
|
|
17
|
-
"opts": { "logLevel": "debug", "retry": 2 },
|
|
18
|
-
"defaultVariant": "local",
|
|
19
|
-
"variants": {
|
|
20
|
-
"local": { "opts": { "retry": 1 } },
|
|
21
|
-
"ci": { "envFile": "ci.env", "envs": { "CI": "1" } }
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
],
|
|
27
|
-
"properties": {
|
|
28
|
-
"$schema": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"description": "Optional schema reference for editors (e.g. VSCode)."
|
|
31
|
-
},
|
|
32
|
-
"version": {
|
|
33
|
-
"type": "integer",
|
|
34
|
-
"const": 1,
|
|
35
|
-
"description": "Schema version."
|
|
36
|
-
},
|
|
37
|
-
"defaults": {
|
|
38
|
-
"type": "object",
|
|
39
|
-
"additionalProperties": false,
|
|
40
|
-
"properties": {
|
|
41
|
-
"profile": {
|
|
42
|
-
"$ref": "#/$defs/profileSelector"
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
"description": "Default selector when --preset-profile is not provided."
|
|
46
|
-
},
|
|
47
|
-
"profiles": {
|
|
48
|
-
"type": "object",
|
|
49
|
-
"minProperties": 1,
|
|
50
|
-
"propertyNames": {
|
|
51
|
-
"$ref": "#/$defs/profileName"
|
|
52
|
-
},
|
|
53
|
-
"additionalProperties": {
|
|
54
|
-
"$ref": "#/$defs/profileItem"
|
|
55
|
-
},
|
|
56
|
-
"description": "Profiles keyed by profile name."
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"$defs": {
|
|
60
|
-
"profileName": {
|
|
61
|
-
"type": "string",
|
|
62
|
-
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
|
|
63
|
-
"description": "Profile/variant name."
|
|
64
|
-
},
|
|
65
|
-
"profileSelector": {
|
|
66
|
-
"type": "string",
|
|
67
|
-
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*(?::[A-Za-z0-9][A-Za-z0-9._-]*)?$",
|
|
68
|
-
"description": "Selector format: <profile> or <profile>:<variant>."
|
|
69
|
-
},
|
|
70
|
-
"optionName": {
|
|
71
|
-
"type": "string",
|
|
72
|
-
"pattern": "^(?:--)?(?:[a-z][a-zA-Z0-9]*|[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)+)$",
|
|
73
|
-
"description": "Option key in opts map; aligned with runtime normalization."
|
|
74
|
-
},
|
|
75
|
-
"optionValue": {
|
|
76
|
-
"oneOf": [
|
|
77
|
-
{ "type": "boolean" },
|
|
78
|
-
{ "type": "string" },
|
|
79
|
-
{ "type": "number" },
|
|
80
|
-
{
|
|
81
|
-
"type": "array",
|
|
82
|
-
"items": {
|
|
83
|
-
"oneOf": [{ "type": "string" }, { "type": "number" }]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
]
|
|
87
|
-
},
|
|
88
|
-
"envMap": {
|
|
89
|
-
"type": "object",
|
|
90
|
-
"additionalProperties": {
|
|
91
|
-
"type": "string"
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
"optsMap": {
|
|
95
|
-
"type": "object",
|
|
96
|
-
"propertyNames": {
|
|
97
|
-
"$ref": "#/$defs/optionName"
|
|
98
|
-
},
|
|
99
|
-
"additionalProperties": {
|
|
100
|
-
"$ref": "#/$defs/optionValue"
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
"variantItem": {
|
|
104
|
-
"type": "object",
|
|
105
|
-
"additionalProperties": false,
|
|
106
|
-
"properties": {
|
|
107
|
-
"envFile": {
|
|
108
|
-
"type": "string",
|
|
109
|
-
"minLength": 1
|
|
110
|
-
},
|
|
111
|
-
"envs": {
|
|
112
|
-
"$ref": "#/$defs/envMap"
|
|
113
|
-
},
|
|
114
|
-
"opts": {
|
|
115
|
-
"$ref": "#/$defs/optsMap"
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
"variantsMap": {
|
|
120
|
-
"type": "object",
|
|
121
|
-
"propertyNames": {
|
|
122
|
-
"$ref": "#/$defs/profileName"
|
|
123
|
-
},
|
|
124
|
-
"additionalProperties": {
|
|
125
|
-
"$ref": "#/$defs/variantItem"
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
"profileItem": {
|
|
129
|
-
"type": "object",
|
|
130
|
-
"additionalProperties": false,
|
|
131
|
-
"properties": {
|
|
132
|
-
"envFile": {
|
|
133
|
-
"type": "string",
|
|
134
|
-
"minLength": 1
|
|
135
|
-
},
|
|
136
|
-
"envs": {
|
|
137
|
-
"$ref": "#/$defs/envMap"
|
|
138
|
-
},
|
|
139
|
-
"opts": {
|
|
140
|
-
"$ref": "#/$defs/optsMap"
|
|
141
|
-
},
|
|
142
|
-
"defaultVariant": {
|
|
143
|
-
"$ref": "#/$defs/profileName"
|
|
144
|
-
},
|
|
145
|
-
"variants": {
|
|
146
|
-
"$ref": "#/$defs/variantsMap"
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
"description": "defaultVariant existence in variants must still be validated by runtime."
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|