Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export * from './reduceItems/index.ts';
export * from './regex/index.ts';
export * from './returns/index.ts';
export * from './rfcEmail/index.ts';
export * from './rfc3339Time/index.ts';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new public action is exported without runtime or type tests, leaving valid offsets/fractions, invalid values, and overload typing unverified before publication. Adding the matching test files would keep this action aligned with the existing validator coverage convention.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At library/src/actions/index.ts, line 94:

<comment>The new public action is exported without runtime or type tests, leaving valid offsets/fractions, invalid values, and overload typing unverified before publication. Adding the matching test files would keep this action aligned with the existing validator coverage convention.</comment>

<file context>
@@ -91,6 +91,7 @@ export * from './reduceItems/index.ts';
 export * from './regex/index.ts';
 export * from './returns/index.ts';
 export * from './rfcEmail/index.ts';
+export * from './rfc3339Time/index.ts';
 export * from './safeInteger/index.ts';
 export * from './size/index.ts';
</file context>

export * from './safeInteger/index.ts';
export * from './size/index.ts';
export * from './slug/index.ts';
Expand Down
1 change: 1 addition & 0 deletions library/src/actions/rfc3339Time/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './rfc3339Time.ts';
90 changes: 90 additions & 0 deletions library/src/actions/rfc3339Time/rfc3339Time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type {
BaseIssue,
BaseValidation,
ErrorMessage,
} from '../../types/index.ts';
import { _addIssue } from '../../utils/index.ts';

/**
* The [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) time regex. Matches
* `HH:MM:SS` with optional fractional seconds and an optional UTC or numeric
* offset (`Z` or `+/-HH:MM`). See issue #1496.
*/
const RFC_3339_TIME_REGEX: RegExp =

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The RFC_3339_TIME_REGEX is defined locally in this file instead of in the shared src/regex.ts module. Every other validation regex in this codebase (ISO_TIME_REGEX, ISO_TIME_SECOND_REGEX, UUID_REGEX, ULID_REGEX, SLUG_REGEX, etc.) is defined in src/regex.ts and imported by the action file. Defining it here instead of in regex.ts breaks the project convention, makes the regex harder to reuse (e.g. in a future rfc3339DateTime action), and is inconsistent with how isoTime and isoTimeSecond handle their regex patterns.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At library/src/actions/rfc3339Time/rfc3339Time.ts, line 13:

<comment>The RFC_3339_TIME_REGEX is defined locally in this file instead of in the shared `src/regex.ts` module. Every other validation regex in this codebase (ISO_TIME_REGEX, ISO_TIME_SECOND_REGEX, UUID_REGEX, ULID_REGEX, SLUG_REGEX, etc.) is defined in `src/regex.ts` and imported by the action file. Defining it here instead of in `regex.ts` breaks the project convention, makes the regex harder to reuse (e.g. in a future `rfc3339DateTime` action), and is inconsistent with how `isoTime` and `isoTimeSecond` handle their regex patterns.</comment>

<file context>
@@ -0,0 +1,90 @@
+ * `HH:MM:SS` with optional fractional seconds and an optional UTC or numeric
+ * offset (`Z` or `+/-HH:MM`). See issue #1496.
+ */
+const RFC_3339_TIME_REGEX: RegExp =
+  /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/u;
+
</file context>

/^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/u;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Valid RFC 3339 leap-second times such as 23:59:60Z are rejected because the seconds group only permits 0059. Accept the 60 form (or explicitly document and test an intentional non-RFC restriction).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At library/src/actions/rfc3339Time/rfc3339Time.ts, line 14:

<comment>Valid RFC 3339 leap-second times such as `23:59:60Z` are rejected because the seconds group only permits `00`–`59`. Accept the `60` form (or explicitly document and test an intentional non-RFC restriction).</comment>

<file context>
@@ -0,0 +1,90 @@
+ * offset (`Z` or `+/-HH:MM`). See issue #1496.
+ */
+const RFC_3339_TIME_REGEX: RegExp =
+  /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/u;
+
+/**
</file context>
Suggested change
/^([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/u;
/^([01]\d|2[0-3]):[0-5]\d:(?:[0-5]\d|60)(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/u;


/**
* RFC 3339 time issue interface.
*/
export interface Rfc3339TimeIssue<TInput extends string>
extends BaseIssue<TInput> {
readonly kind: 'validation';
readonly type: 'rfc3339_time';
readonly expected: null;
readonly received: `"${string}"`;
readonly requirement: RegExp;
}

/**
* RFC 3339 time action interface.
*/
export interface Rfc3339TimeAction<
TInput extends string,
TMessage extends ErrorMessage<Rfc3339TimeIssue<TInput>> | undefined,
> extends BaseValidation<TInput, TInput, Rfc3339TimeIssue<TInput>> {
readonly type: 'rfc3339_time';
readonly reference: typeof rfc3339Time;
readonly expects: null;
readonly requirement: RegExp;
readonly message: TMessage;
}

/**
* Creates an [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) time validation
* action.
*
* Format: `HH:MM:SS` with optional fractional seconds and an optional UTC or
* numeric offset (`Z` or `+/-HH:MM`), e.g. `14:30:00`, `14:30:00Z`,
* `14:30:00.123-05:00`. Unlike {@link isoTime} (`HH:MM`) and
* {@link isoTimeSecond} (`HH:MM:SS`), this accepts the RFC 3339 offset and
* fractional-seconds forms needed for OpenAPI `format: time`. See issue #1496.
*
* @returns An RFC 3339 time action.
*/
export function rfc3339Time<TInput extends string>(): Rfc3339TimeAction<
TInput,
undefined
>;

/**
* Creates an RFC 3339 time validation action.
*
* @param message The error message.
*
* @returns An RFC 3339 time action.
*/
Comment on lines +59 to +65

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the JSDoc comment for this overload.

As per coding guidelines, JSDoc should only be provided on the first overload for overload sets.

♻️ Proposed fix
-/**
- * Creates an RFC 3339 time validation action.
- *
- * `@param` message The error message.
- *
- * `@returns` An RFC 3339 time action.
- */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Creates an RFC 3339 time validation action.
*
* @param message The error message.
*
* @returns An RFC 3339 time action.
*/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@library/src/actions/rfc3339Time/rfc3339Time.ts` around lines 59 - 65, Remove
the JSDoc comment immediately preceding the overload in the RFC 3339 time action
declarations, while preserving the documentation on the first overload and
leaving the overload signatures unchanged.

Source: Coding guidelines

export function rfc3339Time<
TInput extends string,
const TMessage extends ErrorMessage<Rfc3339TimeIssue<TInput>> | undefined,
>(message: TMessage): Rfc3339TimeAction<TInput, TMessage>;

// @__NO_SIDE_EFFECTS__
export function rfc3339Time(
message?: ErrorMessage<Rfc3339TimeIssue<string>>,
): Rfc3339TimeAction<string, ErrorMessage<Rfc3339TimeIssue<string>> | undefined> {
return {
kind: 'validation',
type: 'rfc3339_time',
reference: rfc3339Time,
async: false,
expects: null,
requirement: RFC_3339_TIME_REGEX,
message,
'~run'(dataset, config) {
if (dataset.typed && !this.requirement.test(dataset.value)) {
_addIssue(this, 'time', dataset, config);
}
return dataset;
},
};
}