diff --git a/src/parse.ts b/src/parse.ts index b67cfa3..e811875 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -29,16 +29,19 @@ export function readJsonBodyOption( } export function parseIntOption(value: string, name: string): number { - const parsed = Number.parseInt(value, 10) - if (Number.isNaN(parsed)) { + const parsed = Number(value) + if (!/^[+-]?\d+$/.test(value) || !Number.isFinite(parsed)) { throw new Error(`Invalid value for ${name}: "${value}" is not an integer`) } return parsed } export function parseFloatOption(value: string, name: string): number { - const parsed = Number.parseFloat(value) - if (Number.isNaN(parsed)) { + const parsed = Number(value) + if ( + !/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(value) || + !Number.isFinite(parsed) + ) { throw new Error(`Invalid value for ${name}: "${value}" is not a number`) } return parsed diff --git a/test/parse.test.ts b/test/parse.test.ts index 7236df5..ed1073d 100644 --- a/test/parse.test.ts +++ b/test/parse.test.ts @@ -27,6 +27,17 @@ describe("parseIntOption", () => { 'Invalid value for --limit: "" is not an integer', ) }) + + it.each([ + "10foo", + "1.9", + "1e2", + "0x10", + ])('throws when "%s" is not entirely an integer', value => { + expect(() => parseIntOption(value, "--limit")).toThrow( + `Invalid value for --limit: "${value}" is not an integer`, + ) + }) }) describe("parseFloatOption", () => { @@ -34,6 +45,9 @@ describe("parseFloatOption", () => { expect(parseFloatOption("0.5", "--slippage")).toBe(0.5) expect(parseFloatOption("1", "--slippage")).toBe(1) expect(parseFloatOption("0.01", "--slippage")).toBe(0.01) + expect(parseFloatOption(".5", "--slippage")).toBe(0.5) + expect(parseFloatOption("1.", "--slippage")).toBe(1) + expect(parseFloatOption("1e-2", "--slippage")).toBe(0.01) }) it("throws on non-numeric strings", () => { @@ -47,6 +61,17 @@ describe("parseFloatOption", () => { 'Invalid value for --slippage: "" is not a number', ) }) + + it.each([ + "0.5oops", + "0.01%", + "Infinity", + "1e309", + ])('throws when "%s" is not an entirely finite number', value => { + expect(() => parseFloatOption(value, "--slippage")).toThrow( + `Invalid value for --slippage: "${value}" is not a number`, + ) + }) }) describe("readJsonBodyOption", () => {