Skip to content

[typescript-fetch] Add Temporal support - #24924

Open
ondrakucera wants to merge 2 commits into
OpenAPITools:masterfrom
ondrakucera:typescript-fetch-temporal
Open

[typescript-fetch] Add Temporal support#24924
ondrakucera wants to merge 2 commits into
OpenAPITools:masterfrom
ondrakucera:typescript-fetch-temporal

Conversation

@ondrakucera

@ondrakucera ondrakucera commented Sep 10, 2026

Copy link
Copy Markdown

This adds a new date library option to the typescript-fetch generator: "temporal". With it, the generator uses Temporal.Instant for "type: string, format: date-time" and Temporal.PlainDate for "type: string, format: date".

It does what the commit comment says: it adds the option to use Temporal types instead of Date (or String) for typescript-fetch. I've manually tried it on an OpenAPI YAML file having date and date-time parameters/attributes in a URL path, in URL query parameters, and in request/response (JSON) bodies. Everything seems to work well.

Rationale for the changes:

  • JavaScript's Date is suitable to be used as the data type for OpenAPI's "date-time". However, it is notoriously unpleasant to work with in applications needing to work with time-related values across different timezones (among other things). It's also the reason why projects like https://momentjs.com/ gained so much popularity in the past. The new JavaScript Temporal API tries to solve all those Date's pains.
  • Currently, typescript-fetch uses JavaScript's Date even for OpenAPI's "date" (i.e. for a date without time or timezone). The workaround used is to create a Date instance at zero hours (at the local timezone). Again, it's very easy to make a mistake when working with it. Temporal API has PlainDate, which corresponds to OpenAPI's "date" exactly.

The goal is to stay as close as possible to the current implementation built around Date and only use Instant/PlainDate in a manner that's as similar to the existing implementation as possible.

Tagging: @TiFu @taxpon @sebastianhaas @kenisteward @Vrolijkx @macjohnny @topce @akehir @petejohansonxo @amakhrov @davidgamero @mkusaka @joscha @KannaKim.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
    • Please note that on my machine, two (unrelated) tests unfortunately fail (Tests run: 4977, Failures: 2, Errors: 0, Skipped: 7). However, the same two tests fail for me also on master (as of 888f17b) when running mvn clean package -Ddevelocity.cache.local.enabled=false -Ddevelocity.cache.remote.enabled=false. The tests in question: org.openapitools.codegen.cppboostbeast.Oas31ExactRuntimeTest.generatedClientHonorsCompositionAndParameterWireSemantics and org.openapitools.codegen.cppboostbeast.Oas31ExactRuntimeTest.generatedClientPreservesAdditionalPropertiesWhenEnabled.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Adds a temporal option to the dateLibrary setting for the typescript-fetch generator, mapping OpenAPI date to Temporal.PlainDate and date-time to Temporal.Instant instead of Date.

Changes

  • New dateLibrary=temporal option with runtime serialization/deserialization helpers.
  • Templates for path parameters, query strings, and oneOf models handle Temporal types.
  • withoutRuntimeChecks falls back to string for temporal, same as for date.
  • Temporal.Instant and Temporal.PlainDate are now recognized as language-specific primitives.

Written for commit 168198a. Summary will update on new commits.

Review in cubic

This adds a new date library option to the typescript-fetch generator:
"temporal". With it, the generator uses Temporal.Instant for "type:
string, format: date-time" and Temporal.PlainDate for "type: string,
format: date".

{{#isDateLibraryTemporal}}
export function serializeDateTime(value: Temporal.Instant): string {
return value.toString();

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It's worth noting that Temporal.Instant's toString() method gives something like this (based on my experiments):

  • Node: "2026-08-15T14:25:49.161593018Z"
  • Firefox: "2026-08-15T14:25:46.876Z"
  • Chromium: "2026-08-15T14:26:24.1674Z"

So in Node, the precision is up to nanoseconds. Also, the Temporal specification says that the number of places after the decimal point may differ because trailing zeroes are removed.

Date's toISOString() method uses precision only down to milliseconds in all three runtimes I've tried.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache:311">
P2: When `dateLibrary=temporal` is used for a path parameter, the generated API references `Temporal` without providing its TypeScript declaration. Add an explicit Temporal type dependency/reference, or otherwise generate the required ambient typing so the generated package builds without manual consumer setup.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

{{#pathParams}}
{{#isDateTimeType}}
{{#isDateLibraryTemporal}}
if (requestParameters['{{paramName}}'] instanceof Temporal.Instant) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: When dateLibrary=temporal is used for a path parameter, the generated API references Temporal without providing its TypeScript declaration. Add an explicit Temporal type dependency/reference, or otherwise generate the required ambient typing so the generated package builds without manual consumer setup.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache, line 311:

<comment>When `dateLibrary=temporal` is used for a path parameter, the generated API references `Temporal` without providing its TypeScript declaration. Add an explicit Temporal type dependency/reference, or otherwise generate the required ambient typing so the generated package builds without manual consumer setup.</comment>

<file context>
@@ -307,16 +307,28 @@ export class {{classname}} extends runtime.BaseAPI {
         {{#pathParams}}
         {{#isDateTimeType}}
+        {{#isDateLibraryTemporal}}
+        if (requestParameters['{{paramName}}'] instanceof Temporal.Instant) {
+            urlPath = urlPath.replace({{=<< >>=}}'{<<baseName>>}'<<={{ }}=>>, encodeURIComponent(runtime.serializeDateTime(requestParameters['{{paramName}}'])));
+        {{/isDateLibraryTemporal}}
</file context>

Based on comments from cubic-dev-ai.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant