diff --git a/packages/utils/src/shorthand-time.ts b/packages/utils/src/shorthand-time.ts index 94f5c54f..c5e8551d 100644 --- a/packages/utils/src/shorthand-time.ts +++ b/packages/utils/src/shorthand-time.ts @@ -28,8 +28,9 @@ export const shorthandToMilliseconds = ( // Check if the string is purely numeric if (Number.isNaN(Number(shorthand))) { - // Use a case-insensitive regex that supports decimals and 'ms' unit - const match = /^([\d.]+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand); + // Use a case-insensitive regex that supports decimals and 'ms' unit. + // The number must be well-formed (at most one decimal point and at least one digit). + const match = /^(\d+\.?\d*|\.\d+)\s*(ms|s|m|h|hr|d)$/i.exec(shorthand); if (!match) { throw new Error( diff --git a/packages/utils/test/shorthand-time.test.ts b/packages/utils/test/shorthand-time.test.ts index c043096a..8b26beae 100644 --- a/packages/utils/test/shorthand-time.test.ts +++ b/packages/utils/test/shorthand-time.test.ts @@ -34,6 +34,17 @@ describe("time parser", () => { "Unsupported time format: \"1z\". Use 'ms', 's', 'm', 'h', 'hr', or 'd'.", ); }); + test("send in string with malformed number and valid unit throws", () => { + for (const value of ["1.2.3s", "1..5s", "..s", ".s", ".m"]) { + expect(() => shorthandToMilliseconds(value)).toThrowError( + `Unsupported time format: "${value}"`, + ); + } + }); + test("send in string with decimal edge cases", () => { + expect(shorthandToMilliseconds(".5s")).toBe(500); + expect(shorthandToMilliseconds("5.s")).toBe(5000); + }); test("send in string with number", () => { expect(shorthandToMilliseconds("1000")).toBe(1000); });