@guanghechen/commander 4.8.0 → 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 CHANGED
@@ -1,5 +1,12 @@
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
+
3
10
  ## 4.8.0
4
11
 
5
12
  ### Minor Changes
@@ -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.startsWith('no')) {
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)) {
@@ -2148,13 +2148,23 @@ class CommandPresetProfileParser {
2148
2148
  continue;
2149
2149
  }
2150
2150
  if (typeof rawValue === 'number') {
2151
- argv.push(positiveFlag, String(rawValue));
2151
+ const value = String(rawValue);
2152
+ if (value.startsWith('-'))
2153
+ argv.push(`${positiveFlag}=${value}`);
2154
+ else
2155
+ argv.push(positiveFlag, value);
2152
2156
  continue;
2153
2157
  }
2154
2158
  if (rawValue.length === 0) {
2155
2159
  continue;
2156
2160
  }
2157
- argv.push(positiveFlag, ...rawValue.map(value => String(value)));
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
+ }
2158
2168
  }
2159
2169
  return argv;
2160
2170
  }
@@ -3685,10 +3695,10 @@ function isDomain(rawValue) {
3685
3695
 
3686
3696
  class Coerce {
3687
3697
  constructor() { }
3688
- static create(name, expectedType, validator, errorMessage) {
3698
+ static createNumberCoerce(name, expectedType, validator, errorMessage) {
3689
3699
  return (rawValue) => {
3690
3700
  const value = Number(rawValue);
3691
- if (!validator(value)) {
3701
+ if (rawValue.trim() === '' || !validator(value)) {
3692
3702
  throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
3693
3703
  }
3694
3704
  return value;
@@ -3719,7 +3729,7 @@ class Coerce {
3719
3729
  };
3720
3730
  }
3721
3731
  static integer(name, errorMessage) {
3722
- return this.create(name, 'an integer', value => Number.isInteger(value), errorMessage);
3732
+ return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
3723
3733
  }
3724
3734
  static ip(name, errorMessage) {
3725
3735
  return (rawValue) => {
@@ -3730,16 +3740,16 @@ class Coerce {
3730
3740
  };
3731
3741
  }
3732
3742
  static number(name, errorMessage) {
3733
- return this.create(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3743
+ return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3734
3744
  }
3735
3745
  static port(name, errorMessage) {
3736
- return this.create(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3746
+ return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3737
3747
  }
3738
3748
  static positiveInteger(name, errorMessage) {
3739
- return this.create(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3749
+ return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3740
3750
  }
3741
3751
  static positiveNumber(name, errorMessage) {
3742
- return this.create(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3752
+ return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3743
3753
  }
3744
3754
  }
3745
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.startsWith('no')) {
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)) {
@@ -2161,13 +2161,23 @@ class CommandPresetProfileParser {
2161
2161
  continue;
2162
2162
  }
2163
2163
  if (typeof rawValue === 'number') {
2164
- argv.push(positiveFlag, String(rawValue));
2164
+ const value = String(rawValue);
2165
+ if (value.startsWith('-'))
2166
+ argv.push(`${positiveFlag}=${value}`);
2167
+ else
2168
+ argv.push(positiveFlag, value);
2165
2169
  continue;
2166
2170
  }
2167
2171
  if (rawValue.length === 0) {
2168
2172
  continue;
2169
2173
  }
2170
- argv.push(positiveFlag, ...rawValue.map(value => String(value)));
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
+ }
2171
2181
  }
2172
2182
  return argv;
2173
2183
  }
@@ -3698,10 +3708,10 @@ function isDomain(rawValue) {
3698
3708
 
3699
3709
  class Coerce {
3700
3710
  constructor() { }
3701
- static create(name, expectedType, validator, errorMessage) {
3711
+ static createNumberCoerce(name, expectedType, validator, errorMessage) {
3702
3712
  return (rawValue) => {
3703
3713
  const value = Number(rawValue);
3704
- if (!validator(value)) {
3714
+ if (rawValue.trim() === '' || !validator(value)) {
3705
3715
  throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
3706
3716
  }
3707
3717
  return value;
@@ -3732,7 +3742,7 @@ class Coerce {
3732
3742
  };
3733
3743
  }
3734
3744
  static integer(name, errorMessage) {
3735
- return this.create(name, 'an integer', value => Number.isInteger(value), errorMessage);
3745
+ return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
3736
3746
  }
3737
3747
  static ip(name, errorMessage) {
3738
3748
  return (rawValue) => {
@@ -3743,16 +3753,16 @@ class Coerce {
3743
3753
  };
3744
3754
  }
3745
3755
  static number(name, errorMessage) {
3746
- return this.create(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3756
+ return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3747
3757
  }
3748
3758
  static port(name, errorMessage) {
3749
- return this.create(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3759
+ return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3750
3760
  }
3751
3761
  static positiveInteger(name, errorMessage) {
3752
- return this.create(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3762
+ return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3753
3763
  }
3754
3764
  static positiveNumber(name, errorMessage) {
3755
- return this.create(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3765
+ return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3756
3766
  }
3757
3767
  }
3758
3768
 
@@ -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.startsWith('no')) {
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)) {
@@ -2146,13 +2146,23 @@ class CommandPresetProfileParser {
2146
2146
  continue;
2147
2147
  }
2148
2148
  if (typeof rawValue === 'number') {
2149
- argv.push(positiveFlag, String(rawValue));
2149
+ const value = String(rawValue);
2150
+ if (value.startsWith('-'))
2151
+ argv.push(`${positiveFlag}=${value}`);
2152
+ else
2153
+ argv.push(positiveFlag, value);
2150
2154
  continue;
2151
2155
  }
2152
2156
  if (rawValue.length === 0) {
2153
2157
  continue;
2154
2158
  }
2155
- argv.push(positiveFlag, ...rawValue.map(value => String(value)));
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
+ }
2156
2166
  }
2157
2167
  return argv;
2158
2168
  }
@@ -3683,10 +3693,10 @@ function isDomain(rawValue) {
3683
3693
 
3684
3694
  class Coerce {
3685
3695
  constructor() { }
3686
- static create(name, expectedType, validator, errorMessage) {
3696
+ static createNumberCoerce(name, expectedType, validator, errorMessage) {
3687
3697
  return (rawValue) => {
3688
3698
  const value = Number(rawValue);
3689
- if (!validator(value)) {
3699
+ if (rawValue.trim() === '' || !validator(value)) {
3690
3700
  throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
3691
3701
  }
3692
3702
  return value;
@@ -3717,7 +3727,7 @@ class Coerce {
3717
3727
  };
3718
3728
  }
3719
3729
  static integer(name, errorMessage) {
3720
- return this.create(name, 'an integer', value => Number.isInteger(value), errorMessage);
3730
+ return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
3721
3731
  }
3722
3732
  static ip(name, errorMessage) {
3723
3733
  return (rawValue) => {
@@ -3728,16 +3738,16 @@ class Coerce {
3728
3738
  };
3729
3739
  }
3730
3740
  static number(name, errorMessage) {
3731
- return this.create(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3741
+ return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3732
3742
  }
3733
3743
  static port(name, errorMessage) {
3734
- return this.create(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3744
+ return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3735
3745
  }
3736
3746
  static positiveInteger(name, errorMessage) {
3737
- return this.create(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3747
+ return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3738
3748
  }
3739
3749
  static positiveNumber(name, errorMessage) {
3740
- return this.create(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3750
+ return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3741
3751
  }
3742
3752
  }
3743
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.startsWith('no')) {
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)) {
@@ -2159,13 +2159,23 @@ class CommandPresetProfileParser {
2159
2159
  continue;
2160
2160
  }
2161
2161
  if (typeof rawValue === 'number') {
2162
- argv.push(positiveFlag, String(rawValue));
2162
+ const value = String(rawValue);
2163
+ if (value.startsWith('-'))
2164
+ argv.push(`${positiveFlag}=${value}`);
2165
+ else
2166
+ argv.push(positiveFlag, value);
2163
2167
  continue;
2164
2168
  }
2165
2169
  if (rawValue.length === 0) {
2166
2170
  continue;
2167
2171
  }
2168
- argv.push(positiveFlag, ...rawValue.map(value => String(value)));
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
+ }
2169
2179
  }
2170
2180
  return argv;
2171
2181
  }
@@ -3696,10 +3706,10 @@ function isDomain(rawValue) {
3696
3706
 
3697
3707
  class Coerce {
3698
3708
  constructor() { }
3699
- static create(name, expectedType, validator, errorMessage) {
3709
+ static createNumberCoerce(name, expectedType, validator, errorMessage) {
3700
3710
  return (rawValue) => {
3701
3711
  const value = Number(rawValue);
3702
- if (!validator(value)) {
3712
+ if (rawValue.trim() === '' || !validator(value)) {
3703
3713
  throw new Error(errorMessage ?? `${name} is expected as ${expectedType}, but got ${rawValue}`);
3704
3714
  }
3705
3715
  return value;
@@ -3730,7 +3740,7 @@ class Coerce {
3730
3740
  };
3731
3741
  }
3732
3742
  static integer(name, errorMessage) {
3733
- return this.create(name, 'an integer', value => Number.isInteger(value), errorMessage);
3743
+ return this.createNumberCoerce(name, 'an integer', value => Number.isInteger(value), errorMessage);
3734
3744
  }
3735
3745
  static ip(name, errorMessage) {
3736
3746
  return (rawValue) => {
@@ -3741,16 +3751,16 @@ class Coerce {
3741
3751
  };
3742
3752
  }
3743
3753
  static number(name, errorMessage) {
3744
- return this.create(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3754
+ return this.createNumberCoerce(name, 'a finite number', value => Number.isFinite(value), errorMessage);
3745
3755
  }
3746
3756
  static port(name, errorMessage) {
3747
- return this.create(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3757
+ return this.createNumberCoerce(name, 'a valid port number (0-65535)', value => Number.isInteger(value) && value >= 0 && value <= 65535, errorMessage);
3748
3758
  }
3749
3759
  static positiveInteger(name, errorMessage) {
3750
- return this.create(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3760
+ return this.createNumberCoerce(name, 'a positive integer', value => Number.isInteger(value) && value > 0, errorMessage);
3751
3761
  }
3752
3762
  static positiveNumber(name, errorMessage) {
3753
- return this.create(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3763
+ return this.createNumberCoerce(name, 'a positive number', value => Number.isFinite(value) && value > 0, errorMessage);
3754
3764
  }
3755
3765
  }
3756
3766
 
@@ -592,7 +592,7 @@ declare class Command implements ICommand {
592
592
  */
593
593
  declare class Coerce {
594
594
  private constructor();
595
- private static create;
595
+ private static createNumberCoerce;
596
596
  static choice<TValue extends string>(name: string, values: ReadonlyArray<TValue>, errorMessage?: string): (rawValue: string) => TValue;
597
597
  static domain(name: string, errorMessage?: string): (rawValue: string) => string;
598
598
  static host(name: string, errorMessage?: string): (rawValue: string) => string;
@@ -600,7 +600,7 @@ declare class Command implements ICommand {
600
600
  */
601
601
  declare class Coerce {
602
602
  private constructor();
603
- private static create;
603
+ private static createNumberCoerce;
604
604
  static choice<TValue extends string>(name: string, values: ReadonlyArray<TValue>, errorMessage?: string): (rawValue: string) => TValue;
605
605
  static domain(name: string, errorMessage?: string): (rawValue: string) => string;
606
606
  static host(name: string, errorMessage?: string): (rawValue: string) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanghechen/commander",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "A minimal, type-safe command-line interface builder with fluent API",
5
5
  "author": {
6
6
  "name": "guanghechen",