From 2eb92583271f9f33967ed5822565264d279ccea5 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 1 Apr 2025 12:02:05 +0200 Subject: [PATCH 1/4] Move luxon and utils to `snaps-utils` --- packages/snaps-rpc-methods/package.json | 4 +- .../src/permitted/scheduleBackgroundEvent.ts | 58 ++++---------- packages/snaps-utils/package.json | 2 + packages/snaps-utils/src/index.ts | 1 + packages/snaps-utils/src/time.test.ts | 75 +++++++++++++++++++ packages/snaps-utils/src/time.ts | 56 ++++++++++++++ yarn.lock | 4 +- 7 files changed, 150 insertions(+), 50 deletions(-) create mode 100644 packages/snaps-utils/src/time.test.ts create mode 100644 packages/snaps-utils/src/time.ts diff --git a/packages/snaps-rpc-methods/package.json b/packages/snaps-rpc-methods/package.json index 485952b6d1..1820bc10ae 100644 --- a/packages/snaps-rpc-methods/package.json +++ b/packages/snaps-rpc-methods/package.json @@ -62,8 +62,7 @@ "@metamask/snaps-utils": "workspace:^", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.2.0", - "@noble/hashes": "^1.7.1", - "luxon": "^3.5.0" + "@noble/hashes": "^1.7.1" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", @@ -72,7 +71,6 @@ "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", "@ts-bridge/cli": "^0.6.1", - "@types/luxon": "^3", "@types/node": "18.14.2", "deepmerge": "^4.2.2", "depcheck": "^1.4.7", diff --git a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts index 6f96e8ac1b..862b00901d 100644 --- a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts +++ b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts @@ -8,20 +8,18 @@ import { type ScheduleBackgroundEventResult, } from '@metamask/snaps-sdk'; import type { CronjobRpcRequest, InferMatching } from '@metamask/snaps-utils'; -import { CronjobRpcRequestStruct } from '@metamask/snaps-utils'; import { - StructError, - create, - object, - refine, - string, -} from '@metamask/superstruct'; + CronjobRpcRequestStruct, + getStartDate, + Iso8601DateStruct, + Iso8601DurationStruct, +} from '@metamask/snaps-utils'; +import { StructError, create, object } from '@metamask/superstruct'; import { assert, hasProperty, type PendingJsonRpcResponse, } from '@metamask/utils'; -import { DateTime, Duration } from 'luxon'; import { SnapEndowments } from '../endowments'; import type { MethodHooksObject } from '../utils'; @@ -56,31 +54,13 @@ export const scheduleBackgroundEventHandler: PermittedHandlerExport< hookNames, }; -const offsetRegex = /Z|([+-]\d{2}:?\d{2})$/u; - const ScheduleBackgroundEventParametersWithDateStruct = object({ - date: refine(string(), 'date', (val) => { - const date = DateTime.fromISO(val); - if (date.isValid) { - // Luxon doesn't have a reliable way to check if timezone info was not provided - if (!offsetRegex.test(val)) { - return 'ISO 8601 date must have timezone information'; - } - return true; - } - return 'Not a valid ISO 8601 date'; - }), + date: Iso8601DateStruct, request: CronjobRpcRequestStruct, }); const ScheduleBackgroundEventParametersWithDurationStruct = object({ - duration: refine(string(), 'duration', (val) => { - const duration = Duration.fromISO(val); - if (!duration.isValid) { - return 'Not a valid ISO 8601 duration'; - } - return true; - }), + duration: Iso8601DurationStruct, request: CronjobRpcRequestStruct, }); @@ -96,22 +76,6 @@ export type ScheduleBackgroundEventParameters = InferMatching< ScheduleBackgroundEventParams >; -/** - * Generates a `DateTime` object based on if a duration or date is provided. - * - * @param params - The validated params from the `snap_scheduleBackgroundEvent` call. - * @returns A `DateTime` object. - */ -function getStartDate(params: ScheduleBackgroundEventParams) { - if ('duration' in params) { - return DateTime.fromJSDate(new Date()) - .toUTC() - .plus(Duration.fromISO(params.duration)); - } - - return DateTime.fromISO(params.date, { setZone: true }); -} - /** * The `snap_scheduleBackgroundEvent` method implementation. * @@ -146,7 +110,11 @@ async function getScheduleBackgroundEventImplementation( const { request } = validatedParams; - const date = getStartDate(validatedParams); + const time = hasProperty(validatedParams, 'date') + ? (validatedParams.date as string) + : validatedParams.duration; + + const date = getStartDate(time); // Make sure any millisecond precision is removed. const truncatedDate = date.startOf('second').toISO({ diff --git a/packages/snaps-utils/package.json b/packages/snaps-utils/package.json index 5668ca9450..5c4f33b9a9 100644 --- a/packages/snaps-utils/package.json +++ b/packages/snaps-utils/package.json @@ -95,6 +95,7 @@ "fast-deep-equal": "^3.1.3", "fast-json-stable-stringify": "^2.1.0", "fast-xml-parser": "^4.4.1", + "luxon": "^3.5.0", "marked": "^12.0.1", "rfdc": "^1.3.0", "semver": "^7.5.4", @@ -111,6 +112,7 @@ "@swc/jest": "^0.2.26", "@ts-bridge/cli": "^0.6.1", "@types/jest": "^27.5.1", + "@types/luxon": "^3", "@types/mocha": "^10.0.1", "@types/node": "18.14.2", "@types/semver": "^7.5.0", diff --git a/packages/snaps-utils/src/index.ts b/packages/snaps-utils/src/index.ts index 92ae8f3843..bc35f64f4d 100644 --- a/packages/snaps-utils/src/index.ts +++ b/packages/snaps-utils/src/index.ts @@ -26,6 +26,7 @@ export * from './platform-version'; export * from './snaps'; export * from './strings'; export * from './structs'; +export * from './time'; export * from './types'; export * from './ui'; export * from './url'; diff --git a/packages/snaps-utils/src/time.test.ts b/packages/snaps-utils/src/time.test.ts new file mode 100644 index 0000000000..b7840dec54 --- /dev/null +++ b/packages/snaps-utils/src/time.test.ts @@ -0,0 +1,75 @@ +import { create, is } from '@metamask/superstruct'; +import { DateTime } from 'luxon'; + +import { getStartDate, Iso8601DateStruct, Iso8601DurationStruct } from './time'; + +describe('Iso8601dateStruct', () => { + it('should return true for a valid ISO 8601 date', () => { + const value = DateTime.now().toISO(); + expect(is(value, Iso8601DateStruct)).toBe(true); + }); + + it('should return false for an invalid ISO 8601 date', () => { + const value = 'Mon Mar 31 2025'; + expect(is(value, Iso8601DateStruct)).toBe(false); + }); + + it('should return false for an ISO 8601 date without timezone information', () => { + const value = '2025-03-31T12:00:00'; + expect(is(value, Iso8601DateStruct)).toBe(false); + }); + + it('should return an error message for invalid ISO 8601 date', () => { + const value = 'Mon Mar 31 2025'; + expect(() => create(value, Iso8601DateStruct)).toThrow( + 'Not a valid ISO 8601 date', + ); + }); + + it('should return an error message for ISO 8601 date without timezone information', () => { + const value = '2025-03-31T12:00:00'; + expect(() => create(value, Iso8601DateStruct)).toThrow( + 'ISO 8601 date must have timezone information', + ); + }); +}); + +describe('Iso8601DurationStruct', () => { + it('should return true for a valid ISO 8601 duration', () => { + const value = 'P3Y6M4DT12H30M5S'; + expect(is(value, Iso8601DurationStruct)).toBe(true); + }); + + it('should return false for an invalid ISO 8601 duration', () => { + const value = 'Millisecond'; + expect(is(value, Iso8601DurationStruct)).toBe(false); + }); + + it('should return an error message for invalid ISO 8601 duration', () => { + const value = '1Millisecond'; + expect(() => create(value, Iso8601DurationStruct)).toThrow( + 'Not a valid ISO 8601 duration', + ); + }); +}); + +describe('getStartDate', () => { + it('should return a DateTime object for a valid ISO 8601 date', () => { + const value = '2025-03-31T12:00:00Z'; + const final = DateTime.fromISO(value, { setZone: true }); + + expect(getStartDate(value)).toStrictEqual(final); + }); + + it('should return a DateTime object with the valid ISO 8601 duration added', () => { + jest + .useFakeTimers('modern') + .setSystemTime(new Date('2025-03-31T12:00:00Z')); + + const value = 'P3Y6M'; + + expect(getStartDate(value)).toStrictEqual( + DateTime.fromISO('2028-09-30T12:00:00.000Z', { setZone: true }), + ); + }); +}); diff --git a/packages/snaps-utils/src/time.ts b/packages/snaps-utils/src/time.ts new file mode 100644 index 0000000000..49b6511a53 --- /dev/null +++ b/packages/snaps-utils/src/time.ts @@ -0,0 +1,56 @@ +import { is, refine, string } from '@metamask/superstruct'; +import { DateTime, Duration } from 'luxon'; + +/** + * Refines a string as an ISO 8601 duration. + */ +export const Iso8601DurationStruct = refine( + string(), + 'ISO 8601 duration', + (value) => { + const parsedDuration = Duration.fromISO(value); + if (!parsedDuration.isValid) { + return 'Not a valid ISO 8601 duration'; + } + return true; + }, +); + +/** + * Regex to match the offset part of an ISO 8601 date. + */ +const offsetRegex = /Z|([+-]\d{2}:?\d{2})$/u; + +/** + * Refines a string as an ISO 8601 date. + */ +export const Iso8601DateStruct = refine(string(), 'ISO 8601 date', (value) => { + const parsedDate = DateTime.fromISO(value); + + if (!parsedDate.isValid) { + return 'Not a valid ISO 8601 date'; + } + + if (!offsetRegex.test(value)) { + // Luxon doesn't have a reliable way to check if timezone info was not provided + return 'ISO 8601 date must have timezone information'; + } + + return true; +}); + +/** + * Generates a `DateTime` object based on if a duration or date is provided. + * + * @param iso8601Time - The ISO 8601 time string. + * @returns A `DateTime` object. + */ +export function getStartDate(iso8601Time: string) { + if (is(iso8601Time, Iso8601DurationStruct)) { + return DateTime.fromJSDate(new Date()) + .toUTC() + .plus(Duration.fromISO(iso8601Time)); + } + + return DateTime.fromISO(iso8601Time, { setZone: true }); +} diff --git a/yarn.lock b/yarn.lock index 381f8a7bc8..2d88c71bd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5845,7 +5845,6 @@ __metadata: "@swc/core": "npm:1.3.78" "@swc/jest": "npm:^0.2.26" "@ts-bridge/cli": "npm:^0.6.1" - "@types/luxon": "npm:^3" "@types/node": "npm:18.14.2" deepmerge: "npm:^4.2.2" depcheck: "npm:^1.4.7" @@ -5853,7 +5852,6 @@ __metadata: jest: "npm:^29.0.2" jest-it-up: "npm:^2.0.0" jest-silent-reporter: "npm:^0.6.0" - luxon: "npm:^3.5.0" prettier: "npm:^3.3.3" typescript: "npm:~5.3.3" languageName: unknown @@ -6049,6 +6047,7 @@ __metadata: "@swc/jest": "npm:^0.2.26" "@ts-bridge/cli": "npm:^0.6.1" "@types/jest": "npm:^27.5.1" + "@types/luxon": "npm:^3" "@types/mocha": "npm:^10.0.1" "@types/node": "npm:18.14.2" "@types/semver": "npm:^7.5.0" @@ -6075,6 +6074,7 @@ __metadata: istanbul-reports: "npm:^3.1.5" jest: "npm:^29.0.2" jest-silent-reporter: "npm:^0.6.0" + luxon: "npm:^3.5.0" marked: "npm:^12.0.1" memfs: "npm:^3.4.13" prettier: "npm:^3.3.3" From 9b558ae2b664d9669df8d318f5a408bde38c4a72 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 1 Apr 2025 12:04:32 +0200 Subject: [PATCH 2/4] update coverage --- packages/snaps-rpc-methods/jest.config.js | 8 ++++---- packages/snaps-utils/coverage.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/snaps-rpc-methods/jest.config.js b/packages/snaps-rpc-methods/jest.config.js index 906d4228db..1a5f7f18db 100644 --- a/packages/snaps-rpc-methods/jest.config.js +++ b/packages/snaps-rpc-methods/jest.config.js @@ -10,10 +10,10 @@ module.exports = deepmerge(baseConfig, { ], coverageThreshold: { global: { - branches: 94.98, - functions: 98.64, - lines: 98.76, - statements: 98.45, + branches: 94.95, + functions: 98.62, + lines: 98.75, + statements: 98.43, }, }, }); diff --git a/packages/snaps-utils/coverage.json b/packages/snaps-utils/coverage.json index 7a20a59bf4..7fd5745cab 100644 --- a/packages/snaps-utils/coverage.json +++ b/packages/snaps-utils/coverage.json @@ -1,6 +1,6 @@ { - "branches": 99.74, - "functions": 98.93, - "lines": 99.61, - "statements": 96.95 + "branches": 99.75, + "functions": 98.95, + "lines": 99.62, + "statements": 97 } From 07ec0ed27523451c552800efc4e9dab7bca99930 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 1 Apr 2025 12:22:50 +0200 Subject: [PATCH 3/4] move `getStartDate` back to `snaps-rpc-methods` --- packages/snaps-rpc-methods/jest.config.js | 6 ++--- packages/snaps-rpc-methods/package.json | 4 +++- .../src/permitted/scheduleBackgroundEvent.ts | 24 ++++++++++++++----- packages/snaps-utils/coverage.json | 4 ++-- packages/snaps-utils/src/time.test.ts | 23 +----------------- packages/snaps-utils/src/time.ts | 18 +------------- yarn.lock | 2 ++ 7 files changed, 30 insertions(+), 51 deletions(-) diff --git a/packages/snaps-rpc-methods/jest.config.js b/packages/snaps-rpc-methods/jest.config.js index 1a5f7f18db..944600fe0d 100644 --- a/packages/snaps-rpc-methods/jest.config.js +++ b/packages/snaps-rpc-methods/jest.config.js @@ -10,10 +10,10 @@ module.exports = deepmerge(baseConfig, { ], coverageThreshold: { global: { - branches: 94.95, - functions: 98.62, + branches: 94.93, + functions: 98.63, lines: 98.75, - statements: 98.43, + statements: 98.44, }, }, }); diff --git a/packages/snaps-rpc-methods/package.json b/packages/snaps-rpc-methods/package.json index 1820bc10ae..485952b6d1 100644 --- a/packages/snaps-rpc-methods/package.json +++ b/packages/snaps-rpc-methods/package.json @@ -62,7 +62,8 @@ "@metamask/snaps-utils": "workspace:^", "@metamask/superstruct": "^3.1.0", "@metamask/utils": "^11.2.0", - "@noble/hashes": "^1.7.1" + "@noble/hashes": "^1.7.1", + "luxon": "^3.5.0" }, "devDependencies": { "@lavamoat/allow-scripts": "^3.0.4", @@ -71,6 +72,7 @@ "@swc/core": "1.3.78", "@swc/jest": "^0.2.26", "@ts-bridge/cli": "^0.6.1", + "@types/luxon": "^3", "@types/node": "18.14.2", "deepmerge": "^4.2.2", "depcheck": "^1.4.7", diff --git a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts index 862b00901d..de54850aec 100644 --- a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts +++ b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts @@ -10,7 +10,6 @@ import { import type { CronjobRpcRequest, InferMatching } from '@metamask/snaps-utils'; import { CronjobRpcRequestStruct, - getStartDate, Iso8601DateStruct, Iso8601DurationStruct, } from '@metamask/snaps-utils'; @@ -20,6 +19,7 @@ import { hasProperty, type PendingJsonRpcResponse, } from '@metamask/utils'; +import { DateTime, Duration } from 'luxon'; import { SnapEndowments } from '../endowments'; import type { MethodHooksObject } from '../utils'; @@ -76,6 +76,22 @@ export type ScheduleBackgroundEventParameters = InferMatching< ScheduleBackgroundEventParams >; +/** + * Generates a `DateTime` object based on if a duration or date is provided. + * + * @param params - The validated params from the `snap_scheduleBackgroundEvent` call. + * @returns A `DateTime` object. + */ +function getStartDate(params: ScheduleBackgroundEventParams) { + if ('duration' in params) { + return DateTime.fromJSDate(new Date()) + .toUTC() + .plus(Duration.fromISO(params.duration)); + } + + return DateTime.fromISO(params.date, { setZone: true }); +} + /** * The `snap_scheduleBackgroundEvent` method implementation. * @@ -110,11 +126,7 @@ async function getScheduleBackgroundEventImplementation( const { request } = validatedParams; - const time = hasProperty(validatedParams, 'date') - ? (validatedParams.date as string) - : validatedParams.duration; - - const date = getStartDate(time); + const date = getStartDate(validatedParams); // Make sure any millisecond precision is removed. const truncatedDate = date.startOf('second').toISO({ diff --git a/packages/snaps-utils/coverage.json b/packages/snaps-utils/coverage.json index 7fd5745cab..dcf2e2b964 100644 --- a/packages/snaps-utils/coverage.json +++ b/packages/snaps-utils/coverage.json @@ -1,6 +1,6 @@ { "branches": 99.75, - "functions": 98.95, + "functions": 98.94, "lines": 99.62, - "statements": 97 + "statements": 96.99 } diff --git a/packages/snaps-utils/src/time.test.ts b/packages/snaps-utils/src/time.test.ts index b7840dec54..3d8cfdc3af 100644 --- a/packages/snaps-utils/src/time.test.ts +++ b/packages/snaps-utils/src/time.test.ts @@ -1,7 +1,7 @@ import { create, is } from '@metamask/superstruct'; import { DateTime } from 'luxon'; -import { getStartDate, Iso8601DateStruct, Iso8601DurationStruct } from './time'; +import { Iso8601DateStruct, Iso8601DurationStruct } from './time'; describe('Iso8601dateStruct', () => { it('should return true for a valid ISO 8601 date', () => { @@ -52,24 +52,3 @@ describe('Iso8601DurationStruct', () => { ); }); }); - -describe('getStartDate', () => { - it('should return a DateTime object for a valid ISO 8601 date', () => { - const value = '2025-03-31T12:00:00Z'; - const final = DateTime.fromISO(value, { setZone: true }); - - expect(getStartDate(value)).toStrictEqual(final); - }); - - it('should return a DateTime object with the valid ISO 8601 duration added', () => { - jest - .useFakeTimers('modern') - .setSystemTime(new Date('2025-03-31T12:00:00Z')); - - const value = 'P3Y6M'; - - expect(getStartDate(value)).toStrictEqual( - DateTime.fromISO('2028-09-30T12:00:00.000Z', { setZone: true }), - ); - }); -}); diff --git a/packages/snaps-utils/src/time.ts b/packages/snaps-utils/src/time.ts index 49b6511a53..fa25a99f12 100644 --- a/packages/snaps-utils/src/time.ts +++ b/packages/snaps-utils/src/time.ts @@ -1,4 +1,4 @@ -import { is, refine, string } from '@metamask/superstruct'; +import { refine, string } from '@metamask/superstruct'; import { DateTime, Duration } from 'luxon'; /** @@ -38,19 +38,3 @@ export const Iso8601DateStruct = refine(string(), 'ISO 8601 date', (value) => { return true; }); - -/** - * Generates a `DateTime` object based on if a duration or date is provided. - * - * @param iso8601Time - The ISO 8601 time string. - * @returns A `DateTime` object. - */ -export function getStartDate(iso8601Time: string) { - if (is(iso8601Time, Iso8601DurationStruct)) { - return DateTime.fromJSDate(new Date()) - .toUTC() - .plus(Duration.fromISO(iso8601Time)); - } - - return DateTime.fromISO(iso8601Time, { setZone: true }); -} diff --git a/yarn.lock b/yarn.lock index 2d88c71bd6..0957e665d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5845,6 +5845,7 @@ __metadata: "@swc/core": "npm:1.3.78" "@swc/jest": "npm:^0.2.26" "@ts-bridge/cli": "npm:^0.6.1" + "@types/luxon": "npm:^3" "@types/node": "npm:18.14.2" deepmerge: "npm:^4.2.2" depcheck: "npm:^1.4.7" @@ -5852,6 +5853,7 @@ __metadata: jest: "npm:^29.0.2" jest-it-up: "npm:^2.0.0" jest-silent-reporter: "npm:^0.6.0" + luxon: "npm:^3.5.0" prettier: "npm:^3.3.3" typescript: "npm:~5.3.3" languageName: unknown From f91cf68e5dd3e7ec733bdafd89433f6f1c443746 Mon Sep 17 00:00:00 2001 From: Guillaume Roux Date: Tue, 1 Apr 2025 12:32:06 +0200 Subject: [PATCH 4/4] `Iso` -> `ISO` --- .../src/permitted/scheduleBackgroundEvent.ts | 8 +++---- packages/snaps-utils/src/time.test.ts | 22 +++++++++---------- packages/snaps-utils/src/time.ts | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts index de54850aec..7073708c46 100644 --- a/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts +++ b/packages/snaps-rpc-methods/src/permitted/scheduleBackgroundEvent.ts @@ -10,8 +10,8 @@ import { import type { CronjobRpcRequest, InferMatching } from '@metamask/snaps-utils'; import { CronjobRpcRequestStruct, - Iso8601DateStruct, - Iso8601DurationStruct, + ISO8601DateStruct, + ISO8601DurationStruct, } from '@metamask/snaps-utils'; import { StructError, create, object } from '@metamask/superstruct'; import { @@ -55,12 +55,12 @@ export const scheduleBackgroundEventHandler: PermittedHandlerExport< }; const ScheduleBackgroundEventParametersWithDateStruct = object({ - date: Iso8601DateStruct, + date: ISO8601DateStruct, request: CronjobRpcRequestStruct, }); const ScheduleBackgroundEventParametersWithDurationStruct = object({ - duration: Iso8601DurationStruct, + duration: ISO8601DurationStruct, request: CronjobRpcRequestStruct, }); diff --git a/packages/snaps-utils/src/time.test.ts b/packages/snaps-utils/src/time.test.ts index 3d8cfdc3af..a0d65bf4fb 100644 --- a/packages/snaps-utils/src/time.test.ts +++ b/packages/snaps-utils/src/time.test.ts @@ -1,53 +1,53 @@ import { create, is } from '@metamask/superstruct'; import { DateTime } from 'luxon'; -import { Iso8601DateStruct, Iso8601DurationStruct } from './time'; +import { ISO8601DateStruct, ISO8601DurationStruct } from './time'; -describe('Iso8601dateStruct', () => { +describe('ISO8601DateStruct', () => { it('should return true for a valid ISO 8601 date', () => { const value = DateTime.now().toISO(); - expect(is(value, Iso8601DateStruct)).toBe(true); + expect(is(value, ISO8601DateStruct)).toBe(true); }); it('should return false for an invalid ISO 8601 date', () => { const value = 'Mon Mar 31 2025'; - expect(is(value, Iso8601DateStruct)).toBe(false); + expect(is(value, ISO8601DateStruct)).toBe(false); }); it('should return false for an ISO 8601 date without timezone information', () => { const value = '2025-03-31T12:00:00'; - expect(is(value, Iso8601DateStruct)).toBe(false); + expect(is(value, ISO8601DateStruct)).toBe(false); }); it('should return an error message for invalid ISO 8601 date', () => { const value = 'Mon Mar 31 2025'; - expect(() => create(value, Iso8601DateStruct)).toThrow( + expect(() => create(value, ISO8601DateStruct)).toThrow( 'Not a valid ISO 8601 date', ); }); it('should return an error message for ISO 8601 date without timezone information', () => { const value = '2025-03-31T12:00:00'; - expect(() => create(value, Iso8601DateStruct)).toThrow( + expect(() => create(value, ISO8601DateStruct)).toThrow( 'ISO 8601 date must have timezone information', ); }); }); -describe('Iso8601DurationStruct', () => { +describe('ISO8601DurationStruct', () => { it('should return true for a valid ISO 8601 duration', () => { const value = 'P3Y6M4DT12H30M5S'; - expect(is(value, Iso8601DurationStruct)).toBe(true); + expect(is(value, ISO8601DurationStruct)).toBe(true); }); it('should return false for an invalid ISO 8601 duration', () => { const value = 'Millisecond'; - expect(is(value, Iso8601DurationStruct)).toBe(false); + expect(is(value, ISO8601DurationStruct)).toBe(false); }); it('should return an error message for invalid ISO 8601 duration', () => { const value = '1Millisecond'; - expect(() => create(value, Iso8601DurationStruct)).toThrow( + expect(() => create(value, ISO8601DurationStruct)).toThrow( 'Not a valid ISO 8601 duration', ); }); diff --git a/packages/snaps-utils/src/time.ts b/packages/snaps-utils/src/time.ts index fa25a99f12..71a0130ead 100644 --- a/packages/snaps-utils/src/time.ts +++ b/packages/snaps-utils/src/time.ts @@ -4,7 +4,7 @@ import { DateTime, Duration } from 'luxon'; /** * Refines a string as an ISO 8601 duration. */ -export const Iso8601DurationStruct = refine( +export const ISO8601DurationStruct = refine( string(), 'ISO 8601 duration', (value) => { @@ -24,7 +24,7 @@ const offsetRegex = /Z|([+-]\d{2}:?\d{2})$/u; /** * Refines a string as an ISO 8601 date. */ -export const Iso8601DateStruct = refine(string(), 'ISO 8601 date', (value) => { +export const ISO8601DateStruct = refine(string(), 'ISO 8601 date', (value) => { const parsedDate = DateTime.fromISO(value); if (!parsedDate.isValid) {